3d bearings (& ofCam)

Hi, ofCamera easyCam was broken in my tests (up vector 0 0 1, 0 -1 0) so I ended up coding a simple bearings example. Here is the behavior i was seeking.

#pragma once

#include "ofMain.h"

#include "Panel.h"

class ofApp : public ofBaseApp{
	public:

		Panel panel;


		void setup(){

			panel.clear();
			panel.setup( "bearings", ofPoint(20,20), ofPoint(255,15),0);

			panel.addSlider("fov", 45, 0,100);
			panel.addSlider("near", 0.1, 0,1000);
			panel.addSlider("far", 10000, 0,12500000);
			panel.addSlider("camx", 0, -1000,1000);
			panel.addSlider("camy", 0, -1000,1000);
			panel.addSlider("camz", 400, -1000,1000);
			panel.addSlider("eyex", 0, -1000,1000);
			panel.addSlider("eyey", 0, -1000,1000);
			panel.addSlider("eyez", 0, -1000,1000);
			panel.addSlider("upx", 0, -1,1);
			panel.addSlider("upy", -1, -1,1);
			panel.addSlider("upz", 0, -1,1);

		}
		void update(){
			panel.update();
		}
		void draw(){

			// ofBackground(0,255,0);
			ofBackground(200);

			glMatrixMode( GL_PROJECTION );
			glLoadIdentity();
			gluPerspective( panel.get("fov"), ofGetWidth()/ofGetHeight(),
						   panel.get("near"), panel.get("far") );

		   glMatrixMode( GL_MODELVIEW );
		   glLoadIdentity();

			ofPushMatrix();
				gluLookAt(
						panel.get("camx"),
						panel.get("camy"),
						panel.get("camz"),
						panel.get("eyex"),
						panel.get("eyey"),
						panel.get("eyez"),
						panel.get("upx"),
						panel.get("upy"),
						panel.get("upz")
				);


			ofSetColor(0);
			ofBox(100);

			ofPopMatrix();


			ofSetupScreen();
			ofSetColor(255);
			panel.draw();

		}

		// void keyPressed(int key);
		// void keyReleased(int key);
		// void mouseMoved(int x, int y);
		// void mouseDragged(int x, int y, int button);
		// void mousePressed(int x, int y, int button);
		// void mouseReleased(int x, int y, int button);
		// void mouseEntered(int x, int y);
		// void mouseExited(int x, int y);
		// void windowResized(int w, int h);
		// void dragEvent(ofDragInfo dragInfo);
		// void gotMessage(ofMessage msg);
};

These are portable to OpenGL Es but you have to implement gluLookAt, gluPerspective

Hi, what’s the problem with ofCamera? How are you testing it and what do you get?

Hi. Tests are shapes built on XY, plane with Z up, shapes on XZ plane with Y up (this sort of works). Implementing a follow cam with ofCamera fails to change the perspective to up vector (0, 0, 1), view continues with up vector (0, 1, 0). Another issue, eye position is wrong under this setup, followed shapes are on top left screen corner, instead of center screen. With the above setup (gluLookAt, gluPerspective) things work smooth, up vector correctly changes screen orientation and shapes are followed center screen. Thought i’d share.

Perhaps you can see the issue here

#pragma once

#include "ofMain.h"

class ofApp : public ofBaseApp{
	public:
		bool glcam = true;
		void keyPressed(int k){ if(k==' ') glcam ^= true; }
		ofEasyCam cam;

		float fov = 91.0f;
		float near = 1.0f;
		float far = 1e7;
		ofPoint campos, camlook, camup;

		void setup(){
			campos.set(0,0,1000);
			camlook.set(0,0,0);
			camup.set(0,0,1);
		}
		void update(){
			float a = (int)(250 * ofGetElapsedTimef()) % 2500;
			campos.set( a ,  0,  1000    );
		}
		void draw(){

			ofBackground(200);

			if(glcam){
				glMatrixMode( GL_PROJECTION );
				glLoadIdentity();
				gluPerspective(fov, ofGetWidth()/ofGetHeight(), near, far);

			    glMatrixMode( GL_MODELVIEW );
			    glLoadIdentity();

				ofPushMatrix();
				gluLookAt( campos.x, campos.y, campos.z, look.x, look.y, look.z, camup.x, camup.y, camup.z);
			} else {
				cam.setFov(fov);
				cam.setNearClip(near);
				cam.setFarClip(far);
				cam.setPosition(campos);
				cam.setUpAxis(camup);
				cam.setTarget(camlook);
				cam.begin();
			}


			ofSetColor(0);
			for(size_t a=0; a<100; a++){
				glPushMatrix();
				// glTranslatef( (a % 10) * 250, (a / 10) * 250, 0 );
				glTranslatef( (a % 10) * 250, 0 , (a / 10) * 250 );
				ofBox(100);
				glPopMatrix();
			}


			if(glcam){
				ofPopMatrix();
				ofSetupScreen();
			} else {
				cam.end();
			}

			ofDrawBitmapString("glcam "+ofToString(glcam), 10, 10);

		}

};

Hi,
I don’t get what you see as wrong with ofEasyCam
What version of OpenFrameworks are you using?
When using it, shapes are drawn in the middle of the screen, as expected.
Note that ofEasyCam is intended to be used with the mouse, not via code, although it will work you´ll get some “unexpected behaviors” as trying to set the up axis, which is not for setting the cameras orientation instead the up axis for the mouse manipulation.

Hello,

As @roymacdonald mentioned, ofEasyCam is meant for mouse input, so you could just try an ofCamera if you do not want mouse input. Or you could disable the auto distance and mouse input features in the setup function:

cam.setAutoDistance(false);
cam.disableMouseInput();

and then update the camera with the lookAt function to maintain the correct up vector though this function might suffer from gimbal lock if the cam orientation is closely aligned to the camup vector //

cam.setFov(fov);
cam.setNearClip(near);
cam.setFarClip(far);
cam.setPosition(campos);
cam.lookAt( camlook, camup);

Hi Roy and Nick.

Thank you for your valuable input! Using cam.lookat instead of cam.setUpAxis solves my bearings issues. However, i’ll stick to glcam cause there’s no need for mouse expensive code overheads. Somehow it feels weird that cameras in of dont provide cheap low level access to projection + model matrix creation. Cheers and HNY.

Hi, ofCamera does not have any of the mouse interactions of ofEasyCam, thus no overheads, yet still has the lookAt function. You can setup the cameras internal matrices manually, with the [setupPerspective](https://github.com/openframeworks/openFrameworks/blob/patch-release/libs/openFrameworks/3d/ofCamera.cpp#L61-L81) function, although it uses fixed values for the lookat up axis, yet, I think it is a better way and more compatible with the rest of the ecosystem, if you modify this function and add an additional argument for the upAxis. and then use that.