ofxEasyCam

This is meant to act similarly to Processing’s “PeasyCam”:

http://mrfeinberg.com/peasycam/

In Processing, all you have to do is say:

  
  
import peasy.*;  
  
void setup() {  
  PeasyCam cam = new PeasyCam(this, 500);  
}  
  

And it automatically registers methods to Processing’s mouse event and draw method so that you can control the camera with the mouse.

ofxEasyCam can be used similarly.

1 Download ofx3dUtils http://code.google.com/p/ofx3dutils/
2 Add #include “ofxEasyCam.h” to your testApp.h
3 Add ofxEasyCam camera; as a member of your testApp
4 In testApp:setup(), specify the z-distance of the camera:

  
  
camera.setup(this, 500);  
  

5 In testApp::draw(), add:

  
  
camera.draw();  
  

To the beginning of the method. (I can’t register for ofEvents.draw, because that’s called at the end of draw() rather than the beginning).

ofxEasyCam extends ofx3dUtils’ ofxCamera, so all of its methods are available.

  
  
#pragma once  
  
#include "ofx3DUtils.h"  
  
class ofxEasyCam : public ofxCamera {  
private:  
	bool mouseHasMoved, mouseClicked;  
	float dmouseX, dmouseY, pmouseX, pmouseY;  
	int mouseButton;  
public:  
	float zoomSpeed, orbitSpeed, panSpeed;  
  
	ofxEasyCam() {  
		zoomSpeed = 1;  
		orbitSpeed = .2;  
		panSpeed = 1;  
		ofAddListener(ofEvents.mousePressed, this, &ofxEasyCam::mousePressed);  
		ofAddListener(ofEvents.mouseReleased, this, &ofxEasyCam::mouseReleased);  
		ofAddListener(ofEvents.mouseDragged, this, &ofxEasyCam::mouseDragged);  
	}  
	void setup(ofBaseApp* app, float dist) {  
		position(ofGetWidth() / 2, ofGetHeight() / 2, dist);  
		dmouseX = dmouseY = pmouseX = pmouseY = 0;  
		mouseHasMoved = false;  
		mouseClicked = false;  
	}  
	void draw() {  
		ofxVec3f relx = getDir().getCrossed(getUp()).normalize();  
		ofxVec3f rely = getDir().getCrossed(relx).normalize();  
		if(mouseButton == 0) {  
			orbitAround(  
				getEye(),  
				relx,  
				orbitSpeed * dmouseY);  
			orbitAround(  
				getEye(),  
				rely,  
				orbitSpeed * -dmouseX);  
		} else if(mouseButton == 2) {  
			ofxVec3f offset = getDir().normalize() * (zoomSpeed * dmouseY);  
			eye(getEye() - offset);  
			moveGlobal(offset);  
		} else if(mouseButton == 3) {  
			ofxVec3f offset =  
				(relx * dmouseX * panSpeed) +  
				(rely * dmouseY * panSpeed);  
			moveGlobal(offset);  
		}  
		dmouseX *= .9;  
		dmouseY *= .9;  
		place();  
	}  
	void mousePressed(ofMouseEventArgs& event) {  
		if(mouseClicked == true)  
			mouseButton = 3; // left + right  
		else  
			mouseButton = event.button;  
		mouseClicked = true;  
	}  
  
	void mouseDragged(ofMouseEventArgs& event) {  
		int x = event.x;  
		int y = event.y;  
		if(mouseHasMoved) {  
			dmouseX = pmouseX - x;  
			dmouseY = pmouseY - y;  
		} else  
			mouseHasMoved = true;  
		pmouseX = x;  
		pmouseY = y;  
	}  
  
	void mouseReleased(ofMouseEventArgs& event) {  
		mouseHasMoved = false;  
		mouseClicked = false;  
	}  
};  
  

There is one known bug: gimbal lock. If you look from the north or south pole positions, you can get some weirdly fast rotation.

update: ofxEasyCam is now in the ofx3DUtils svn, I’ll maintain it there.

How hard would it be to implement quaternions for rotations in ofx3DUtils? I have zero experience using them unfortunately…

not too hard i think.
some time ago i started working on an ofxQuaternion addon that would be used for that (amongst other things) but i never got to finish it.
but i remember seeing an ofxQuaternion addon somewhere here in the forum already, so that could be integrated.

i think its time for an ofx3dutils update :stuck_out_tongue:

Judging from the wishlist on the wiki, I wouldn’t be surprised if a few things from ofx3dutils are put in the core – which I suppose leaves even more space for ofx3dutils to be developed :slight_smile:

More on quaternions/mat4x4: http://forum.openframeworks.cc/t/ofxmatrix4x4/1865/1