cam.enableOrtho() -- when to call this fn

The plan: create an initial mesh surface in setup() then apply user-induced modifications in the update()/draw() loop. I want to use orthographic projection and enable user interaction via mouse events. I successfully create and color the initial mesh.

Problem #1: The last line of code in setup() is “cam.enableOrtho()”, which I hoped would allow exact registration of the mouse cursor with a graphic ‘+’ generated when a mouse click is detected. But no! The cross aligns with the cursor only at dead center of the mesh. Elsewhere, the cross/cursor difference is proportional to center offset. So orthographic projection is not in force.

In brief, the code sequence in draw() is this:
cam.begin()
mesh.draw()
cam.end()
check mouse position and draw cross.

Problem #2: As I move the mouse cursor around in the mesh, the mesh rotates. I don’t want this behavior. Rather, once built, I want only to alter camera viewpoint when a mouse button or wheel is active.

I would like to know what command can “lock down” what I take to be ofCam or ofEasyCam response to simple mouse motion.

Any pointers to oF documentation or comments are appreciated.

Hi. Having an orthographic projection doesn’t mean that there will be a direct relationship between screen positions (like mouse) and world positions (the vertices in your mesh). you need to use the cameras functions for transforming from one coordinate system to the other. http://openframeworks.cc/documentation/3d/ofCamera/#!show_worldToScreen

if you use ofEsyCam, the camera should only move when you drag the mouse.
if you disable cam.begin() and cam.end() does the mesh still move when you move the mouse?
if you call cam.enableOrtho() does this behavior still happen?

roymacdonald: Thanks for the reply.

I was totally wrong about #2: I indeed had a mouse button pressed while moving the cursor so it was a “drag” operation and, thus, triggered the mesh rotation. I plead innocent by reason of brain fatigue.
STILL, I would like to be able to lock down the mesh from rotating because I will later want to let the user drag across the mesh image to trigger an effect (e.g. disableMouseInput() from ofEasyCam).

On #1: I will study more on ofEasyCam (viewport, etc.), my mesh creation coordinates and a transform using cam.screenToWorld(). I need the latter’s return to apply user-directed effects on the mesh z-coordinates. (My mesh is a heightfield with z values on a fixed (x,y) grid.

hi, no worries. I guess that brain fatigue mistakes are something common in this place. :wink:

if you want the mesh not rotating you can enable and disable the mouse input on the cam.
cheers

Roy: I just discovered ofxInfiniteCanvas. Look forward to tutoring myself on ortho projection and other features of this addon.

Hi @bob97086 , that addon is quite straight forwards. Just write me if you have doubts.
cheers

Roy, thanks for the invitation to “write me if you have doubts”. You may regret the offer.

I’ve started stepping my way through the example ofxInfiniteCanvas code and the supporting .cpp and .h files. I thought I understood the “cam” instance of an ofxInfiniteCanvas object and the initial code of ofApp.h and .cpp. That is, until draw() placed the grid, the cone and other objects at the bottom right-hand corner of the window.

If I correctly interpreted your initial steps, the following parameters should hold (using informal notation):

  • setLookAt is at FRONT

…continuing after inadvertent Return…

reset() has these effects:
translation = (ofGetWidth()/2, ofGetHeight()/2,0), abbreviated as (W/2,H/2,0)
thus moving (0,0.0) to center of window
offset = (0,0,0)
scale = 1
bFlipY = false
bUseOfCam = true

In ofApp draw() the camera test selects cam.draw() to do this (short form):
vec3 t => vec3 reduced from vec4: {(W/2, H/2, 0) + (0,0,0)}*I4; I4 is FM unit matrix.

thus, since bUseOfCam is true and bFlipY false I think we get this:
cam.position(-W/2, H/2, 0);
set scale to (1, 1, 1)

The cam.begin() call results in easyCam setEvents() then ofCamera bindEvents(). (Note my low-level competence in C++ terminology).

The geometric figures are drawn to coordinates that should, in my view, place them right in the center of the window – the new (0,0,0) – not at the lower right corner. :exploding_head:

Hi @bob97086,
well it is me now the one with brain fatigue. I’m not completely understanding you. If you run the example you should see the grid, cone, and other shapes in the center of the screen.
I can see what you describe and that definitely is a bug. :frowning:

I don’t really remember why I added an ofEasyCam instance to the example.
I havent been using this addon for a while since it will become deprecated with the soon to come 0.10 release of openFrameworks.

If you are using the nightly builds or pulling from OF’s github you can use the following and have the very same behaviour as ofxInfiniteCanvas.

make an instance of ofEasyCam (in ofApp.h for example).

ofEasyCam cam;

in ofApp.cpp inside of ofApp::setup() put the following

cam.removeAllInteractions();
cam.addInteraction(ofEasyCam::TRANSFORM_TRANSLATE_XY, OF_MOUSE_BUTTON_LEFT);
cam.addInteraction(ofEasyCam::TRANSFORM_TRANSLATE_Z, OF_MOUSE_BUTTON_RIGHT);

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

btw, I have to document this feature. @arturo I would like to add a post in OF’s blog with this feature, how can I do that?

Thanks again for reply. I will launch another effort in orthoscopic mode following your suggestion.

I think I’ve picked up enough info from your and other forum postings to customize mouse interactions for my needs. Specifically, I want the user to click on a spot so as to trigger a surface reaction exactly there on a “heightfield” of z(x,y). That’s why I was interested in enableOrtho() to begin with rather than nasty perspective.

I’ll watch for further developments – possibly from arturo.

@roymacdonald
I’ve rewritten my app to follow your easyCam guide in ofApp::setup(). In setup() I execute all the easyCam functions you outlined (e.g. cam.removeAllInteractions()). I also define a height map that is flat except for a small rectangular plateau for test purposes.

In update() I operate on the z-values of the vertices in my height map to find an auxiliary array which is the 2D differential (Laplacian) indicating “flow”. I then add back to the z-values in the mesh the differentials to produce a dynamic picture.

I’m pretty sure my math and programming produce an altered set of mesh vertices (I’m careful to use a mesh “reference”, as a failure there burned me once before). I have done many “cout” checks including the final (per frame) values of z in a couple of vertices. The mesh z-values look good but I see no changes in the displayed image.

Here’s the entire code in draw():

void ofApp::draw(){
	ofBackground(ofColor(128));
	cam.begin();
	//mesh.drawWireframe();
	mesh.draw();
	cam.end();
}

No doubt I am making a simple easyCam blunder, but I would appreciate some help.
Bob

Hi @bob97086, I’m not really getting what you are doing with your mesh, although that shouldn’t be a problem. What is that you expect? you might have your mesh oriented wrong? can you post some screenshots please?

@arturo I sent you a private message some days ago with a “tutorial” about setting the mouse interactions for being posted in the blog.

The short answer is that the initial mesh is drawn correctly but all subsequent modifications to the z-component of vertices in update() (verified by “cout” data) are not shown in frames generated in draw().

Here is setup():

void ofApp::setup(){
	cam.removeAllInteractions();
	// Not using the addInteraction()s since I want mouse clicks to modify surface
	//cam.addInteraction(ofEasyCam::TRANSFORM_TRANSLATE_XY, OF_MOUSE_BUTTON_LEFT);
	//cam.addInteraction(ofEasyCam::TRANSFORM_TRANSLATE_Z, OF_MOUSE_BUTTON_RIGHT);

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

	// Build flat mesh, z(x,y)=constant.
	buildFlatMesh(mesh, nVerticesX, nVerticesY, nSkip, Z, darkSeaGreen);
	setNormals(mesh);

	// Perturb flat mesh for testing. Will be evolved in update() and draw() loop.
	tweakMeshRect(mesh, 5, 5, 10, 10, 400, red);
	
	// Reports:
	glm::vec3 meshCornerUL = mesh.getVertex(mesh.getIndex(0));	// upper left corner
	showMeshParams(mesh, nVerticesX, nVerticesY, nSkip, meshCornerUL);
}

Here is update():

void ofApp::update(){

	++frameNum;
	cout << " Frame " << frameNum ;

	// Transfer mesh vertices' z-component into array with extra boundary rows/columns.
	getMeshVertexZ(mesh, zPlus2, nVerticesY+2, nVerticesX+2, reflect);
	if (oneShot) cout << ": u[8][8] = " << zPlus2[8][8] ;

	// Build differential view (Laplacian) in scratch data structure convolvedZP2[][]
	convolveZ(zPlus2, convolvedZP2, nVerticesY + 2, nVerticesX + 2);
	if (oneShot) cout << ". dZ[8][8] = " << convolvedZP2[8][8] ;

	// update vertices' z value
	setMeshVertexZ(mesh, convolvedZP2, nVerticesY + 2, nVerticesX + 2, scale);
	if (oneShot) cout << ". New vertex.z = " << mesh.getVertex(testVertex).z ;
	if (oneShot) cout << ". z[50][50] = " << mesh.getVertex(randomVertex).z; // << endl;

	setNormals(mesh);
}

setMeshVertexZ() adds the differential modifications to z back into the z-component of the mesh -- the latter is defined in the call as "**ofMesh & mesh**". The draw() code is as above. Simple. Maybe too simple as I feel I've left something out as the image doesn't change.

Here is the unchanging mesh:

![RippleTest|666x500](upload://2kEHzFgRd9k5aZZKentLjLeAERc.png)

Of course the screen shot didn’t work the first time. Here’s another shot at it:

well if you are using an ortho camera any changes to the mesh’s z-cordinates will not be shown. That´s how the ortho camera works. if you dont remove any interaction you should be able to rotate the camera and you will be able to see the changes in the mesh

if you are removing all the camera interactions it is just the same as an ofCamera. on the other hand if you want to use the mouse to make clics, you can call cam.enableMouseInput(); and cam.disableMouseInput(); and you can use cam.getMouseInputEnabled() to easily toggle between these states. When using the camera you need to transform the mouse coordinates so you get the right position using

glm::vec3 mouseInWorld = cam.screenToWorld(ofGetMouseX(), ofGetMouseY());

Check the example “examples/3d/pointPickerExample”.

Thanks once more @roymacdonald. I have outsmarted myself again, although “smart” is maybe not the right term. I chose orthographic projection to easily, I thought, map user mouse click onto image point directly under cursor so as to trigger an event there. I will look at pointPickerExample too.

Another thought: add lighting to cast shadows in orthographic scene.
This worked well in my previous (Java/Processing) version which was, I admit, in perspective view.

1 Like

@bob97086 youre welcome. :slight_smile:
casting shadows in ortho mode shouldnt be a problem.
cheers