In setup(), I can modify a mesh with inline code but not via fn. call

I create a simple heightfield type mesh, initially constant z(x,y), then modify a small rectangular area to experiment with perspective parameters. With this code block inside setup(), the little raised area is shown in draw(). But – and this makes me wonder about my sanity – when I package the identical code in a function which is called at the same point in setup() where the inline code was (now commented out) the draw() loop does not show the “bump”.

Further (in)sanity check: near the end of setup() is a function call to setNormals(mesh) which I have copied out of the book “Mastering openFrameworks”. This function call appears to work as you would expect!

int numVertsX = 100;
int numVertsY =  50;
int Z =  10;		// Initial field height. Later subject field to "ripples".
int Skip =  10;		// Spacing between vertices.

//--------------------------------------------------------------
void ofApp::setup(){
	ofSetVerticalSync(true);
	ofEnableDepthTest();	// Z-buffering

	// Create mesh
	for (int y = 0; y < numVertsY; y++) {
		for (int x = 0; x < numVertsX; x++) {
			ofPoint p = ofPoint(x * Skip, y * Skip, Z);
			mesh.addVertex(p);
			mesh.addColor(darkSeaGreen);
		}
	}

	// Set up triangles' indices
	for (int y = 0; y < numVertsY - 1; y++) {
		for (int x = 0; x < numVertsX - 1; x++) {
			int i1 = x + numVertsX * y;
			int i2 = x + 1 + numVertsX * y;
			int i3 = x + numVertsX * (y + 1);
			int i4 = x + 1 + numVertsX * (y + 1);
			mesh.addTriangle(i1, i2, i3);	// e.g. (0,0)-->(1,0)-->(0,1)
			mesh.addTriangle(i2, i4, i3);	// and  (1,0)-->(1,1)-->(0,1)
		}
	}

	// Perturb mesh beginning at vertex (offsetX, offsetY) 
	// with rectangle dX-by-dY and dZ high
	/**/
	int offsetX = 5;
	int offsetY = 5;	
	int dX = 10;
	int dY = 10;
	int dZ = 40;
	
	//tweakMesh(mesh, offsetX, offsetY, dX, dY, dZ);
	// Modify mesh here:
	/**/
	for (int y = offsetX; y <= (offsetX + dY); y++) {
		for (int x = offsetX; x <= (offsetX + dX); x++) {
			int index = x + y * numVertsX;
			ofVec3f v = mesh.getVertex(index);
			v.z += dZ;
			mesh.setVertex(index, v);
			mesh.setColor(index, red);

			cout << "at (" << x << "," << y << ") z becomes " << v.z << endl;
		}
	}
	/**/
	
	setNormals(mesh);

	// Place mesh in middle of window
	meshOffset.x = (ofGetWidth() - numVertsX * Skip) / 2.;
	meshOffset.y = (ofGetHeight() - numVertsY * Skip) / 2.;

	// Reports:
	showMeshParams(numVertsX, numVertsY, Skip);
	showCameraProps(cam);

}

Here’s the function with same tweaking as inline version:

void tweakMesh(ofMesh mesh, int offsetX, int offsetY, int dX, int dY, int dZ) {
	for (int y = offsetX; y <= (offsetX + dY); y++) {
		for (int x = offsetX; x <= (offsetX + dX); x++) {
			int index = x + y * numVertsX;
			ofVec3f v = mesh.getVertex(index);
			v.z += dZ;
			mesh.setVertex(index, v);
			mesh.setColor(index, red);

			cout << "at (" << x << "," << y << ") z becomes " << v.z << endl;
		}
	}
}

I would appreciate any input including psychotherapist referral.

when you pass a parameter to a function like that you are passing a copy of it so it won’t be modified. you can do two things, return it again as in:

ofMesh tweakMesh(ofMesh mesh, ....)

or pass it by reference so you can modify the original as in:

void tweakMesh(ofMesh & mesh,...)

Arturo to the rescue again. Thanks.
I was confused partly by the setNormals(mesh) call with the ofMesh argument like I tried to use. I guess the difference is that setNormals(mesh) doesn’t change the mesh vertices but rather generates the set of normals by explicit calls to mesh.clearNormals() and mesh.addNormals(norm).

If anyone is interested, here’s the setNormals() code:

void setNormals(ofMesh mesh) {
	int nV = mesh.getNumVertices();
	int nT = mesh.getNumIndices() / 3;

vector<glm::vec3> norm(nV);	// Storage for normals

// Scan all triangles to set normals
for (int t = 0; t < nT; t++) {
	// Get indices of triangle t
	int i1 = mesh.getIndex(3 * t);
	int i2 = mesh.getIndex(3 * t + 1);
	int i3 = mesh.getIndex(3 * t + 2);

	// Get vertices of the triangle
	const ofPoint &v1 = mesh.getVertex(i1);
	const ofPoint &v2 = mesh.getVertex(i2);
	const ofPoint &v3 = mesh.getVertex(i3);

	// Compute triangle's normal
	ofPoint dir = ((v2 - v1).getCrossed(v3 - v1)).getNormalized();

	//Accumulate it to norm array for i1, i2, i3
	norm[i1] += dir;
	norm[i2] += dir;
	norm[i3] += dir;
}

//Normalize the normal's length
/*
for (int i = 0; i<nV; i++) {
norm[i].getNormalized();
}
*/

//Set the normals to mesh
mesh.clearNormals();
mesh.addNormals(norm);

}

where is that code from? that wouldn’t work either, you are passing a copy as well so you won’t never get the result back

I copied the setNormals() code from p. 194 of “Mastering openFrameworks: Creative Coding Demystified” by Denis Perevalov. That is I thought I had copied it perfectly into my program but, checking the original text, I now see the input parameter is “ofMesh & mesh”. I overlooked the “&” when reading the book while banging away at the keyboard. Also, my migration from ‘C’ experience towards ‘C++’ is painfully slow.

Thanks again Arturo.

This quote from Wikipedia, Reference (C++), helps clarify the C use of pointers from C++ references:

There is a simple conversion between pointers and references: the address-of operator (&) will yield a pointer referring to the same object when applied to a reference, and a reference which is initialized from the dereference (*) of a pointer value will refer to the same object as that pointer, where this is possible without invoking undefined behavior. This equivalence is a reflection of the typical implementation, which effectively compiles references into pointers which are implicitly dereferenced at each use. Though that is usually the case, the C++ Standard does not force compilers to implement references using pointers.