Relation between mesh.addVertex and .addColor


#1

In setup(), I have created a usable mesh through “normal methods”. That is, by traversing horizontal and vertical space, creating an ofPoint, call mesh.addVertex(point) then .addColor(color).

I want, during update(), to modify the color but have not found an effective method. Further, I don’t understand why addColor(color) doesn’t explicitly reference the associated vertex.

I realize this is pretty vague, but the basic question is what do I loop over to access and change mesh color?

Thanks for any input!


#2

Have you tried setColor() ?


#3

Hi, if you added all the vertices and all the colors at the same time then each vertex should have the index as its color.
You can use mesh.setColor(…) which expects the index and the color.
so, if you want you can just loop over the colors like


for(size_t i = 0; i < mesh.getNumColors(); i++){
    mesh.getColors()[i];// Use this to get the current color
    mesh.setColor(i, ofFloatColor(0));// pass which ever ofFloatColor you want to.
}

#4

Thanks “hrs” and roymacdonald for quick responses. I will get cracking on this approach!


#5

I tried to implement your suggestion at the appropriate place in my update() code but with no change in results. I will outline the situation and if you have any thoughts, please unload them here.

Basic idea: setup() defines a flat mesh in (x,y) that is perturbed in the z-direction at the location of the mouse cursor when pressed. This triggers a ripple that spreads and dies out. A simple lighting setup helps show the ripple effect. So far, so good.

A boolean bChangeColor is initially false but can be flipped to true by pressing the keyboard ‘c’. When made true the following piece of code in update() is run:

if (bChangeColors) {
				// Rebuild mesh with new color
				cout << " * There are " << mesh.getNumColors() << " colors" << endl;
				for (size_t i = 0; i < mesh.getNumColors(); i++) {
					mesh.setColor(i, ofColor(127));
				}
				bChangeColors = false;
			}

As a trial I am only setting all colors to medium gray. Sadly, the “cout” text appears on output but no change in mesh color. This code executes at the beginning of update() followed by action on the vertices to reflect the ripple and ending with setNormals(mesh).

I realize this is only a small peek into a larger body of code, but I think this is the critical section.

Thanks again for all your help with me and other “early learners”!


#6

Hi,
there was a mistake with my code though, sorry, which I have corrected.
you have to use an ofFloatColor instead of an ofColor.

if changing to ofFloatColor did not work for you, please post your complete code. it might be easier to spot the problem that way.


#7

not sure what’s the problem but ofColor should auto convert to ofFloatColor so there’s no need to use ofFloatColor when pushing new colors on a mesh


#8

roymacdonald: Generous offer to look at my “complete code”. I will furnish the main parts of ofApp.cpp but with some features (audio control) deleted. Also no supporting files that do auxiliary stuff like manipulate a copy of vertices to simulate wave action.

This summary might help understanding my very C-like code.
setup():
initialize mouse to “active” state,
set mesh size and “skip” factor,
camera data, lighting data,
initial flat mesh and transfer z-values to working array

update():
With an active mouse (user-set rain drop location),
a mouse click and bChangeColors=true,
then change color everywhere to, in this case, 127.
Find mouse cursor, set drop height and size, calculate rain drop impulse.
Find new z-values (convolution, scale, add into current mesh vertices.
Set normals.

Here, brave volunteer, is my abbreviated ofApp.cpp:


//--------------------------------------------------------------
/* setup():
*	Define initial flat mesh: vertices, normals, colors. No texture. 
*/
void ofApp::setup(){
	ofSetFrameRate(64);
	scale = 0.99;
	bReflect = false;			// ripples reflect off sides
	bShowHelp = true;			// toggle text display at startup
	bChangeColors = false;		// allow/disallow automatic color change w/rain drop
	bMouseActive = true;		// Control mode: mouse driven or random (disabled)
	
	// Define mesh size to nearly fill window
	nSkip = 6;		// 12 if "full screen"; 6, if not
	nVertsX = ofGetWidth() / nSkip;
	nVertsY = ofGetHeight() / nSkip;
	initZ = 10;

	// Derivative quantities:
	nZPlusX = nVertsX + 2;
	nZPlusY = nVertsY + 2;
	nZPlus = nZPlusX * nZPlusY;
	zPlus = new float[nZPlus] { initZ };	
	zDel2 = new float[nZPlus]{ 0 };

	// Mouse and mesh relations
	myMouseX = myMouseY = 0;
	meshX0 = (ofGetWidth() - nSkip * nVertsX) / 2.;
	meshY0 = (ofGetHeight() - nSkip * nVertsY) / 2.;
	
	// Random rain drop controls (DELETED)
	
	ofBackground(ofColor(127));

	cam.removeAllInteractions();
	cam.enableOrtho();
	cam.setNearClip(-1000000);
	cam.setFarClip(1000000);
	cam.setVFlip(true);

	// Build mesh as heightfield ("terrain map") with constant z over base (x,y)
	buildFlatMesh(mesh, nVertsX, nVertsY, nSkip, initZ, lightSeaGreen);

	// Load z-values into working array
	getVertexZValues(mesh, nVertsX, nVertsY, zPlus);
	addInitZtoBoundary(zPlus, nZPlusX, nZPlusY, initZ);

	// Lighting and material
	light.setPosition(1000, 1000, 1000);
	light.setOrientation(ofVec3f(45.0, -45.0, 0.0));
	light.setDiffuseColor(lightSeaGreen);
	light.setSpecularColor(ofColor(255.f, 255.f, 255.f));
	material.setShininess(120);

	// Audio (DELETED)
}

//--------------------------------------------------------------
void ofApp::update(){

	unique_lock<mutex> lock(audioMutex);

	float dropHt;
	float dropSigma;
	float midSigma;
	float freqFraction = 0.05;
	float dropX0, dropY0;

	if (bMouseActive) {
		if (bNewMouseClick) {
			// Process mouse-triggered rain drop
			if (bChangeColors) {
				// Rebuild mesh once with new color
				for (size_t i = 0; i < mesh.getNumColors(); i++) {
					mesh.setColor(i, ofColor(127));
				}
				bChangeColors = false;
			}

			// Location
			meshMouseX = (myMouseX - meshX0) / nSkip;
			meshMouseY = (myMouseY - meshY0) / nSkip;

			// Drop size and audio volume 
			dropHt = ofRandom(dropHtMin, dropHtMax);
			dropSigma = ofRandom(dropSigmaMin, dropSigmaMax);
			volume = (dropHt - dropHtMin) / (dropHtMax - dropHtMin);

			// Initialize "pulse" on surface mesh
			defineImpulseGauss(gPulse, meshMouseX, meshMouseY, dropSigma, dropHt);
			applyImpulseGauss(zPlus, nZPlusX, nZPlusY, gPulse);
			
			// Wait for next mouse click
			bNewMouseClick = false;
		}
	} 
	// DELETE ALTERNATIVE (RANDOM) RAIN DROP CODE -- for clarity
	// DELETE SOUND VOLUME INITIALIZATION
	
	// Make wave in scratch array
	convolveZ(zPlus, zDel2, nZPlusX, nZPlusY, bReflect);		// Laplacian
	scaleConvolution(zDel2, nZPlusX, nZPlusY, scale);
	addConvolution(zPlus, zDel2, nZPlusX, nZPlusY);				// Apply and scale

	// Load new amplitudes back into mesh
	setVertexZValues(mesh, nVertsX, nVertsY, zPlus, nZPlusX);
	setNormals(mesh);
}

//--------------------------------------------------------------
void ofApp::draw(){
	ofEnableLighting();
	light.enable();
	material.begin();
	cam.begin();
	//mesh.drawWireframe();
	mesh.draw();
	cam.end();
	material.end();
	ofDisableLighting();
}


//--------------------------------------------------------------
// Draw text that explains user choices
void ofApp::drawHelpText() {
	string helpText = "Press h to turn help text on or off.";
	string switchText = " m to switch between mouse-selected or random drops.";
	string colorText  = " c to enable/disable color changing mode.";
	ofDrawBitmapString(helpText, 20, 20);
	ofDrawBitmapString(switchText, 20, 40); 
	ofDrawBitmapString(colorText, 20, 60);
}


//--------------------------------------------------------------
// Make 'h' help response and other keys to modify random rain properties
// and toggle action, etc.
void ofApp::keyPressed(int key){
	if (key == 'h' || key == 'H') {
		// Toggle "Help" text
		//cout << "Show/hide help text" << endl;
		bShowHelp = !bShowHelp;
	}

	if (key == 'm' || key == 'M') {
		bMouseActive = !bMouseActive;
		if (!bMouseActive) {
			t0 = ofGetElapsedTimeMillis();	// start the clock for random time
		}
	}

	if (key == 'c' || key == 'C') {
		// Enable/disable color changes with each rain drop
		bChangeColors = !bChangeColors;
		if (bChangeColors) {
			cout << "Enable color changes" << endl;
		}
		else {
			cout << "Disable color changes" << endl;
		}
	}
}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){
	//cout << " Got mPressed at (" << x << "," << y << ")" << endl;
	myMouseX = x;
	myMouseY = y;
	bNewMouseClick = true;
}

Thanks again.
Bob


#9

Hi, there are a lot of functions that should be relevant that you have omitted.
Yet, I just noticed that there might be a bug with the glRenderer.
So switch to the programable renderer.
in the main.cpp file replace

ofSetupOpenGL(1024,768,OF_WINDOW);

with

ofGLWindowSettings settings;
settings.setGLVersion(3,2);
ofCreateWindow(settings);

@arturo, I just noticed that the vertices colorss have no effect when using the ofGLRenderer as the main renderer.
In ofGLRenderer.cpp I changed

void ofGLRenderer::bind(const ofBaseMaterial & material){
	ofFloatColor diffuse = material.getDiffuseColor();
	ofFloatColor specular = material.getSpecularColor();
	ofFloatColor ambient = material.getAmbientColor();
	ofFloatColor emissive = material.getEmissiveColor();
	float shininess = material.getShininess();
	glDisable(GL_COLOR_MATERIAL);
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, &diffuse.r);
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &specular.r);
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, &ambient.r);
	glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, &emissive.r);
	glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &shininess);
	materialBound = true;
}

for

void ofGLRenderer::bind(const ofBaseMaterial & material){
	ofFloatColor diffuse = material.getDiffuseColor();
	ofFloatColor specular = material.getSpecularColor();
	ofFloatColor ambient = material.getAmbientColor();
	ofFloatColor emissive = material.getEmissiveColor();
	float shininess = material.getShininess();
#ifndef TARGET_OPENGLES
	glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
#endif
	glEnable(GL_COLOR_MATERIAL);
//	glDisable(GL_COLOR_MATERIAL);
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, &diffuse.r);
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &specular.r);
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, &ambient.r);
	glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, &emissive.r);
	glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &shininess);
	materialBound = true;
}

and it seems to work in the same way as when using ofGLProgrammableRenderer although I am not sure if it is the correct thing to do.

hope this helps.


#10

Finally got some free time to try your suggestions.

  1. Insert “settings.setGLVersion(3,2);”. At first no effect but I re-examined my color swapping code (:face_with_raised_eyebrow:) and saw a problem.

  2. Made color swapping test code actually do swapping and PRESTO! Color changes occur.

  3. Comment out the main.cpp line setting GL version to (3,2) and, as you might have predicted, color swapping dies. Good test.

I’m sure you’re right about lots of settings (lights, etc.) missing but at least I have a kind-of working version.

Thanks again, Bob