ofCamera rotating around a point [solved]

Hey folks,

I’m trying to spin a virtual camera around a point in 3D space. It’s actually a torus-like shape and the camera is circling the minor axis, going through the ring.

I’m using ofCamera’s setPosition() and lookAt() functionality to do so. When the camera’s up vector position is set to default ofVec3f(0, 1, 0), the torus is oriented in the wrong direction. But when I change the up vector to ofVec3f(0, 0, 1), I encounter some moments where the camera gets all funky, flips, unexpectedly starts moving backwards.

Here’s some code that demonstrates this behavior …

ofBackground(100);
ofSetCircleResolution(50);
ofEnableLighting();
ofEnableSmoothing();
ofEnableDepthTest();

float rot = 0.5 * DEG_TO_RAD * ofGetFrameNum();

float x = cos( rot ) * 50;
float z = sin( rot ) * 50;

ofVec3f camPos;
ofVec3f lookAtPos;

camPos = ofVec3f( 100+x, 0, z);
lookAtPos = ofVec3f( 100, 0, 0);

cam.setPosition( camPos );

cam.lookAt( lookAtPos, ofVec3f(0, 0, 1) ); // funky
//cam.lookAt( lookAtPos, ofVec3f(0, 1, 0) ); // not-funky

cam.setFov(60);
cam.setNearClip(1);
cam.setFarClip(2000);
cam.begin();

ofSetColor(255, 0, 0);
ofDrawSphere( lookAtPos, 1);

ofMesh m;
m.setMode(OF_PRIMITIVE_LINE_LOOP);

for(int i=0; i<360; i++){
    
    float x = sin( i * DEG_TO_RAD ) * 100;
    float z = cos( i * DEG_TO_RAD ) * 100;
    
    m.addVertex( ofVec3f(x, z, 0));
}
m.draw();

cam.end();

ofDisableLighting();

Looking at the quaternion for cam.getGlobalOrientation(), I’m seeing a lot of NANs.

Any thoughts on what’s causing these undesirable moments? I know I can avoid them by switching the orientation that my torus is being drawn, but I have other items in the scene.

Thanks++ for any advice!

Jeremy

1 Like

Here’s a sketch illustrating the camera behavior –

Red is the lookAt position
Blue is the camera position
White is the camera path (rotating around the lookAt position)

Take it easy. Basically you don’t need to change lookAt and position, and you need model view matrix transformation (operations like ofTranslate and ofRotate). So I’ll rewrite it to

ofBackground(100);
ofSetCircleResolution(50);
ofEnableLighting();
ofEnableSmoothing();
ofEnableDepthTest();

float rot = 0.5 * ofGetFrameNum(); // ofRotate takes degrees

cam.setFov(60);
cam.setNearClip(1);
cam.setFarClip(2000);
cam.begin();

ofTranslate(0, 0, -100); // draw sphere and ring at (0, 0, -100)
ofRotateX(rot); // draw them with rotation

ofSetColor(255, 0, 0);
ofDrawSphere(ofVec3f(0, 0, 0), 1);

ofMesh m;
m.setMode(OF_PRIMITIVE_LINE_LOOP);

for(int i=0; i<360; i++){
	
	float x = sin( i * DEG_TO_RAD ) * 100;
	float z = cos( i * DEG_TO_RAD ) * 100 + 100; // shift the ring
	
	m.addVertex( ofVec3f(x, z, 0));
}
m.draw();

cam.end();

ofDisableLighting();

And you may notice that mesh generation and camera parameter setting can be done in void setup().

Hi @micuat,

Don’t worry, I’m cool : )

Because it’s part of a larger scene, it’s going to be useful to use a virtual camera instead of moving all the objects around accordingly. There’s always multiple ways to go about things in GL.

I definitely appreciate your advice!

Jeremy

Now I understand what you mean by the image. Here is an updated code:

ofBackground(100);
ofSetCircleResolution(50);
ofEnableLighting();
ofEnableSmoothing();
ofEnableDepthTest();

float rot = 0.5 * ofGetFrameNum(); // ofRotate takes degrees

glMatrixMode(GL_PROJECTION);
cam.setFov(60);
cam.setNearClip(1);
cam.setFarClip(2000);
cam.begin();

ofTranslate(0, 0, -100); // draw sphere and ring at (0, 0, -100)
ofRotateX(rot); // draw them with rotation

ofSetColor(255, 0, 0);
ofDrawSphere(ofVec3f(0, 0, 0), 1);

ofMesh m;
m.setMode(OF_PRIMITIVE_LINES);

ofTranslate(0, 100, 0);
ofRotateZ(rot);
for(int i=0; i<360; i++){
	
	float x = sin( i * DEG_TO_RAD ) * 100;
	float z = cos( i * DEG_TO_RAD ) * 100;
	
	m.addVertex( ofVec3f(x, z, 0));
}
m.draw();

cam.end();

ofDisableLighting();

I know this is not the way you want to achieve it, but at least can you tell me if this is the desired animation or not?

Yup, that’s what I had in mind. Just like jumping through a hula hoop : )

glMatrixMode(GL_PROJECTION) isn’t necessary tho.

Ooops, when rotating a camera upside down, its up vector should be rotated to preserve the expected orientation.

// rotate the camera orientation too
ofVec3f upVector;
upVector.set(0, 1, 0);
upVector.rotate( rot-90, ofVec3f(1, 0, 0));

cam.setPosition( camPos );
cam.lookAt( lookAtPos, upVector );