Thanks to @kode80 I now have a better idea of and wording for what I’m trying to do:
"
create an off-axis perspective projection, then offset the camera slightly in the opposite direction to lock the near plane
."
(from there I also found that post of the forum - http://forum.openframeworks.cc/t/ofcamera-007-off-center-perspective-projections/6003/2 )
Here some code he shared that I have implemented in an OF app. It’s definitively going in to the good direction and I have now a better understanding of what is going on. But I’m still unable to really get my head around how to set all this properly (ie. to keep the white cube (in front) snapped to the edges of the windows).
Here is a screen capture of the following code running. I use the mouse to simulate the user’s head movement.
http://smallfly.com/of/off-axis/off-axis.mov
The questions/issues I’m having for now:
- not sure why I need to have a negative ‘zOffset’ (used with ofTranslate) in order to place the cubes.
- how to set the ‘fov’
-
Any thoughts on what is going on? Thanks.
#include "testApp.h"
//--------------------------------------------------------------
void testApp::setup(){
headX = 0;
headY = 0;
headZ = 0;
near = .1f;
far = 10000.0f;
fov = 1.5f;
roomSize = 800.0f;
zOffset = -660.0f;
}
//--------------------------------------------------------------
void testApp::update(){
}
//--------------------------------------------------------------
void testApp::draw(){
offAxis();
drawSteps();
drawCube();
}
//--------------------------------------------------------------
void testApp::offAxis() {
float headDisplacementFactor = 1.0f;
headX = (mouseX - ofGetWidth()/2.0f) / ofGetWidth() * headDisplacementFactor;
headY = (mouseY - ofGetHeight()/2.0f) / ofGetHeight() * headDisplacementFactor;
float ratio = ofGetWidth() / ofGetHeight();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// CREATE OFF-AXIS PROJECTION MATRIX
glFrustum(near*(-fov * ratio + headX),
near*(fov * ratio + headX),
near*(-fov + headY),
near*(fov + headY),
near, far);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// CREATE OFFSET MODELVIEW MATRIX
float mag = -80.0f;
float sx = mag/ratio;
float sy = mag/ratio;
gluLookAt( headX * sx, headY * sy, 0, headX * sx, headY * sy, -20, 0, 1, 0);
}
//--------------------------------------------------------------
void testApp::drawCube() {
ofBackground(0);
ofPushMatrix();
{
ofSetColor(255.0f , .0f, .0f);
ofTranslate(0,0,zOffset);
ofNoFill();
ofSetColor(255.0f);
ofBox(roomSize);
}
ofPopMatrix();
ofPushMatrix();
{
ofTranslate(.0f, .0f, (-roomSize + zOffset));
ofNoFill();
ofSetColor(255.0f, .0f, .0f);
ofBox(roomSize);
}
ofPopMatrix();
ofPushMatrix();
{
ofTranslate(.0f, .0f, (-roomSize/4.0f));
ofSetColor(.0f, .0f, 255.0f, 255.0f);
ofFill();
ofBox(50);
ofNoFill();
ofSetColor(.0f);
ofBox(50);
}
ofPopMatrix();
}
//--------------------------------------------------------------
void testApp::drawSteps() {
int nbOfSteps = 10;
float frameW = roomSize;
float frameH = roomSize;
ofPushMatrix();
{
ofTranslate(-ofGetWidth()/2.0f, -ofGetHeight()/2.0f);
ofPushStyle();
ofSetColor(255.0f, .0f, 255.0f);
for (int i=0; i < nbOfSteps; i++) {
ofPushMatrix();
{
ofTranslate(.0f, .0f, i * -100.0f);
ofLine(.0f, .0f, frameW, .0f);
ofLine(frameW, .0f, frameW, frameH);
ofLine(frameW, frameH, .0f, frameH);
ofLine(.0f, frameH, .0f, .0f);
}
ofPopMatrix();
}
ofPopStyle();
}
ofPopMatrix();
}