mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 08:04:01 +02:00
Fix for starfield rendering on Oculus: put inter-pupil translation in
modelview matrix where it belongs, don't reset perspective projection for starfield.
This commit is contained in:
parent
111936e13a
commit
9b433c974c
2 changed files with 129 additions and 152 deletions
|
@ -285,130 +285,90 @@ void Application::paintGL() {
|
|||
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
glPushMatrix(); {
|
||||
glLoadIdentity();
|
||||
|
||||
if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
|
||||
_myCamera.setTightness (100.0f);
|
||||
_myCamera.setTargetPosition(_myAvatar.getSpringyHeadPosition());
|
||||
_myCamera.setTargetRotation(_myAvatar.getBodyYaw() - 180.0f,
|
||||
0.0f,
|
||||
0.0f);
|
||||
} else if (OculusManager::isConnected()) {
|
||||
if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
|
||||
_myCamera.setTightness (100.0f);
|
||||
_myCamera.setTargetPosition(_myAvatar.getSpringyHeadPosition());
|
||||
_myCamera.setTargetRotation(_myAvatar.getBodyYaw() - 180.0f,
|
||||
0.0f,
|
||||
0.0f);
|
||||
} else if (OculusManager::isConnected()) {
|
||||
_myAvatar.setDisplayingHead(false);
|
||||
_myCamera.setUpShift (0.0f);
|
||||
_myCamera.setDistance (0.0f);
|
||||
_myCamera.setTightness (100.0f);
|
||||
_myCamera.setTargetPosition(_myAvatar.getHeadPosition());
|
||||
_myCamera.setTargetRotation(_myAvatar.getAbsoluteHeadYaw(),
|
||||
_myAvatar.getHead().getPitch(),
|
||||
-_myAvatar.getHead().getRoll());
|
||||
} else if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
|
||||
_myCamera.setTargetPosition(_myAvatar.getSpringyHeadPosition());
|
||||
_myCamera.setTargetRotation(_myAvatar.getAbsoluteHeadYaw(),
|
||||
_myAvatar.getAbsoluteHeadPitch(),
|
||||
0.0f);
|
||||
// Take a look at whether we are inside head, don't render it if so.
|
||||
const float HEAD_RENDER_DISTANCE = 0.5;
|
||||
glm::vec3 distanceToHead(_myCamera.getPosition() - _myAvatar.getSpringyHeadPosition());
|
||||
|
||||
if (glm::length(distanceToHead) < HEAD_RENDER_DISTANCE) {
|
||||
_myAvatar.setDisplayingHead(false);
|
||||
_myCamera.setUpShift (0.0f);
|
||||
_myCamera.setDistance (0.0f);
|
||||
_myCamera.setTightness (100.0f);
|
||||
_myCamera.setTargetPosition(_myAvatar.getHeadPosition());
|
||||
_myCamera.setTargetRotation(_myAvatar.getAbsoluteHeadYaw(),
|
||||
_myAvatar.getHead().getPitch(),
|
||||
-_myAvatar.getHead().getRoll());
|
||||
} else if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
|
||||
_myCamera.setTargetPosition(_myAvatar.getSpringyHeadPosition());
|
||||
_myCamera.setTargetRotation(_myAvatar.getAbsoluteHeadYaw(),
|
||||
_myAvatar.getAbsoluteHeadPitch(),
|
||||
0.0f);
|
||||
// Take a look at whether we are inside head, don't render it if so.
|
||||
const float HEAD_RENDER_DISTANCE = 0.5;
|
||||
glm::vec3 distanceToHead(_myCamera.getPosition() - _myAvatar.getSpringyHeadPosition());
|
||||
|
||||
if (glm::length(distanceToHead) < HEAD_RENDER_DISTANCE) {
|
||||
_myAvatar.setDisplayingHead(false);
|
||||
}
|
||||
} else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
|
||||
_myCamera.setTargetPosition(_myAvatar.getHeadPosition());
|
||||
_myCamera.setTargetRotation(_myAvatar.getBodyYaw(),
|
||||
0.0f,
|
||||
//-_myAvatar.getAbsoluteHeadPitch(),
|
||||
0.0f);
|
||||
}
|
||||
|
||||
// important...
|
||||
_myCamera.update( 1.f/_fps );
|
||||
|
||||
// Render anything (like HUD items) that we want to be in 3D but not in worldspace
|
||||
/*
|
||||
const float HUD_Z_OFFSET = -5.f;
|
||||
glPushMatrix();
|
||||
glm::vec3 test(0.5, 0.5, 0.5);
|
||||
glTranslatef(1, 1, HUD_Z_OFFSET);
|
||||
drawVector(&test);
|
||||
glPopMatrix();
|
||||
*/
|
||||
|
||||
|
||||
// Note: whichCamera is used to pick between the normal camera myCamera for our
|
||||
// main camera, vs, an alternate camera. The alternate camera we support right now
|
||||
// is the viewFrustumOffsetCamera. But theoretically, we could use this same mechanism
|
||||
// to add other cameras.
|
||||
//
|
||||
// Why have two cameras? Well, one reason is that because in the case of the renderViewFrustum()
|
||||
// code, we want to keep the state of "myCamera" intact, so we can render what the view frustum of
|
||||
// myCamera is. But we also want to do meaningful camera transforms on OpenGL for the offset camera
|
||||
Camera whichCamera = _myCamera;
|
||||
|
||||
if (_viewFrustumFromOffset->isChecked() && _frustumOn->isChecked()) {
|
||||
|
||||
// set the camera to third-person view but offset so we can see the frustum
|
||||
_viewFrustumOffsetCamera.setTargetYaw(_viewFrustumOffsetYaw + _myAvatar.getBodyYaw());
|
||||
_viewFrustumOffsetCamera.setPitch (_viewFrustumOffsetPitch );
|
||||
_viewFrustumOffsetCamera.setRoll (_viewFrustumOffsetRoll );
|
||||
_viewFrustumOffsetCamera.setUpShift (_viewFrustumOffsetUp );
|
||||
_viewFrustumOffsetCamera.setDistance (_viewFrustumOffsetDistance);
|
||||
_viewFrustumOffsetCamera.update(1.f/_fps);
|
||||
whichCamera = _viewFrustumOffsetCamera;
|
||||
}
|
||||
|
||||
// transform by eye offset
|
||||
|
||||
glm::vec3 eyeOffsetPos = whichCamera.getEyeOffsetPosition();
|
||||
glm::quat eyeOffsetOrient = whichCamera.getEyeOffsetOrientation();
|
||||
glm::vec3 eyeOffsetAxis = glm::axis(eyeOffsetOrient);
|
||||
glRotatef(-glm::angle(eyeOffsetOrient), eyeOffsetAxis.x, eyeOffsetAxis.y, eyeOffsetAxis.z);
|
||||
glTranslatef(-eyeOffsetPos.x, -eyeOffsetPos.y, -eyeOffsetPos.z);
|
||||
|
||||
// transform view according to whichCamera
|
||||
// could be myCamera (if in normal mode)
|
||||
// or could be viewFrustumOffsetCamera if in offset mode
|
||||
// I changed the ordering here - roll is FIRST (JJV)
|
||||
|
||||
glRotatef ( whichCamera.getRoll(), IDENTITY_FRONT.x, IDENTITY_FRONT.y, IDENTITY_FRONT.z);
|
||||
glRotatef ( whichCamera.getPitch(), IDENTITY_RIGHT.x, IDENTITY_RIGHT.y, IDENTITY_RIGHT.z);
|
||||
glRotatef (180.0 - whichCamera.getYaw(), IDENTITY_UP.x, IDENTITY_UP.y, IDENTITY_UP.z );
|
||||
|
||||
glTranslatef(-whichCamera.getPosition().x, -whichCamera.getPosition().y, -whichCamera.getPosition().z);
|
||||
|
||||
// Setup 3D lights (after the camera transform, so that they are positioned in world space)
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
|
||||
|
||||
glm::vec3 relativeSunLoc = glm::normalize(_environment.getClosestData(whichCamera.getPosition()).getSunLocation() -
|
||||
whichCamera.getPosition());
|
||||
GLfloat light_position0[] = { relativeSunLoc.x, relativeSunLoc.y, relativeSunLoc.z, 0.0 };
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
|
||||
GLfloat ambient_color[] = { 0.7, 0.7, 0.8 };
|
||||
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_color);
|
||||
GLfloat diffuse_color[] = { 0.8, 0.7, 0.7 };
|
||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_color);
|
||||
GLfloat specular_color[] = { 1.0, 1.0, 1.0, 1.0};
|
||||
glLightfv(GL_LIGHT0, GL_SPECULAR, specular_color);
|
||||
|
||||
glMaterialfv(GL_FRONT, GL_SPECULAR, specular_color);
|
||||
glMateriali(GL_FRONT, GL_SHININESS, 96);
|
||||
|
||||
if (_oculusOn->isChecked()) {
|
||||
displayOculus(whichCamera);
|
||||
|
||||
} else {
|
||||
displaySide(whichCamera);
|
||||
glPopMatrix();
|
||||
|
||||
displayOverlay();
|
||||
}
|
||||
} else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
|
||||
_myCamera.setTargetPosition(_myAvatar.getHeadPosition());
|
||||
_myCamera.setTargetRotation(_myAvatar.getBodyYaw(),
|
||||
0.0f,
|
||||
//-_myAvatar.getAbsoluteHeadPitch(),
|
||||
0.0f);
|
||||
}
|
||||
|
||||
// important...
|
||||
_myCamera.update( 1.f/_fps );
|
||||
|
||||
// Render anything (like HUD items) that we want to be in 3D but not in worldspace
|
||||
/*
|
||||
const float HUD_Z_OFFSET = -5.f;
|
||||
glPushMatrix();
|
||||
glm::vec3 test(0.5, 0.5, 0.5);
|
||||
glTranslatef(1, 1, HUD_Z_OFFSET);
|
||||
drawVector(&test);
|
||||
glPopMatrix();
|
||||
*/
|
||||
|
||||
|
||||
// Note: whichCamera is used to pick between the normal camera myCamera for our
|
||||
// main camera, vs, an alternate camera. The alternate camera we support right now
|
||||
// is the viewFrustumOffsetCamera. But theoretically, we could use this same mechanism
|
||||
// to add other cameras.
|
||||
//
|
||||
// Why have two cameras? Well, one reason is that because in the case of the renderViewFrustum()
|
||||
// code, we want to keep the state of "myCamera" intact, so we can render what the view frustum of
|
||||
// myCamera is. But we also want to do meaningful camera transforms on OpenGL for the offset camera
|
||||
Camera whichCamera = _myCamera;
|
||||
|
||||
if (_viewFrustumFromOffset->isChecked() && _frustumOn->isChecked()) {
|
||||
|
||||
// set the camera to third-person view but offset so we can see the frustum
|
||||
_viewFrustumOffsetCamera.setTargetYaw(_viewFrustumOffsetYaw + _myAvatar.getBodyYaw());
|
||||
_viewFrustumOffsetCamera.setPitch (_viewFrustumOffsetPitch );
|
||||
_viewFrustumOffsetCamera.setRoll (_viewFrustumOffsetRoll );
|
||||
_viewFrustumOffsetCamera.setUpShift (_viewFrustumOffsetUp );
|
||||
_viewFrustumOffsetCamera.setDistance (_viewFrustumOffsetDistance);
|
||||
_viewFrustumOffsetCamera.update(1.f/_fps);
|
||||
whichCamera = _viewFrustumOffsetCamera;
|
||||
}
|
||||
|
||||
if (_oculusOn->isChecked()) {
|
||||
displayOculus(whichCamera);
|
||||
|
||||
} else {
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
displaySide(whichCamera);
|
||||
glPopMatrix();
|
||||
|
||||
displayOverlay();
|
||||
}
|
||||
|
||||
_frameCount++;
|
||||
}
|
||||
|
@ -1537,10 +1497,13 @@ void Application::displayOculus(Camera& whichCamera) {
|
|||
glTranslatef(0.151976, 0, 0); // +h, see Oculus SDK docs p. 26
|
||||
gluPerspective(whichCamera.getFieldOfView(), whichCamera.getAspectRatio(),
|
||||
whichCamera.getNearClip(), whichCamera.getFarClip());
|
||||
|
||||
glViewport(0, 0, _glWidget->width() / 2, _glWidget->height());
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glTranslatef(0.032, 0, 0); // dip/2, see p. 27
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glViewport(0, 0, _glWidget->width() / 2, _glWidget->height());
|
||||
displaySide(whichCamera);
|
||||
|
||||
// and the right eye to the right side
|
||||
|
@ -1549,10 +1512,12 @@ void Application::displayOculus(Camera& whichCamera) {
|
|||
glTranslatef(-0.151976, 0, 0); // -h
|
||||
gluPerspective(whichCamera.getFieldOfView(), whichCamera.getAspectRatio(),
|
||||
whichCamera.getNearClip(), whichCamera.getFarClip());
|
||||
|
||||
glViewport(_glWidget->width() / 2, 0, _glWidget->width() / 2, _glWidget->height());
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(-0.032, 0, 0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glViewport(_glWidget->width() / 2, 0, _glWidget->width() / 2, _glWidget->height());
|
||||
displaySide(whichCamera);
|
||||
|
||||
glPopMatrix();
|
||||
|
@ -1638,7 +1603,42 @@ void Application::displayOculus(Camera& whichCamera) {
|
|||
}
|
||||
|
||||
void Application::displaySide(Camera& whichCamera) {
|
||||
glPushMatrix();
|
||||
// transform by eye offset
|
||||
|
||||
glm::vec3 eyeOffsetPos = whichCamera.getEyeOffsetPosition();
|
||||
glm::quat eyeOffsetOrient = whichCamera.getEyeOffsetOrientation();
|
||||
glm::vec3 eyeOffsetAxis = glm::axis(eyeOffsetOrient);
|
||||
glRotatef(-glm::angle(eyeOffsetOrient), eyeOffsetAxis.x, eyeOffsetAxis.y, eyeOffsetAxis.z);
|
||||
glTranslatef(-eyeOffsetPos.x, -eyeOffsetPos.y, -eyeOffsetPos.z);
|
||||
|
||||
// transform view according to whichCamera
|
||||
// could be myCamera (if in normal mode)
|
||||
// or could be viewFrustumOffsetCamera if in offset mode
|
||||
// I changed the ordering here - roll is FIRST (JJV)
|
||||
|
||||
glRotatef ( whichCamera.getRoll(), IDENTITY_FRONT.x, IDENTITY_FRONT.y, IDENTITY_FRONT.z);
|
||||
glRotatef ( whichCamera.getPitch(), IDENTITY_RIGHT.x, IDENTITY_RIGHT.y, IDENTITY_RIGHT.z);
|
||||
glRotatef (180.0 - whichCamera.getYaw(), IDENTITY_UP.x, IDENTITY_UP.y, IDENTITY_UP.z );
|
||||
|
||||
glTranslatef(-whichCamera.getPosition().x, -whichCamera.getPosition().y, -whichCamera.getPosition().z);
|
||||
|
||||
// Setup 3D lights (after the camera transform, so that they are positioned in world space)
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
|
||||
|
||||
glm::vec3 relativeSunLoc = glm::normalize(_environment.getClosestData(whichCamera.getPosition()).getSunLocation() -
|
||||
whichCamera.getPosition());
|
||||
GLfloat light_position0[] = { relativeSunLoc.x, relativeSunLoc.y, relativeSunLoc.z, 0.0 };
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
|
||||
GLfloat ambient_color[] = { 0.7, 0.7, 0.8 };
|
||||
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_color);
|
||||
GLfloat diffuse_color[] = { 0.8, 0.7, 0.7 };
|
||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_color);
|
||||
GLfloat specular_color[] = { 1.0, 1.0, 1.0, 1.0};
|
||||
glLightfv(GL_LIGHT0, GL_SPECULAR, specular_color);
|
||||
|
||||
glMaterialfv(GL_FRONT, GL_SPECULAR, specular_color);
|
||||
glMateriali(GL_FRONT, GL_SHININESS, 96);
|
||||
|
||||
if (_renderStarsOn->isChecked()) {
|
||||
// should be the first rendering pass - w/o depth buffer / lighting
|
||||
|
@ -1727,8 +1727,6 @@ void Application::displaySide(Camera& whichCamera) {
|
|||
|
||||
// brad's frustum for debugging
|
||||
if (_frustumOn->isChecked()) renderViewFrustum(_viewFrustum);
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
void Application::displayOverlay() {
|
||||
|
|
|
@ -116,19 +116,6 @@ namespace starfield {
|
|||
|
||||
float halfPersp = perspective * 0.5f;
|
||||
|
||||
// define diagonal and near distance
|
||||
float halfDiag = std::sin(halfPersp);
|
||||
float nearClip = std::cos(halfPersp);
|
||||
|
||||
// determine half dimensions based on the screen diagonal
|
||||
//
|
||||
// ww + hh = dd
|
||||
// a = w / h => w = ha
|
||||
// hh + hh aa = dd
|
||||
// hh = dd / (1 + aa)
|
||||
float hh = sqrt(halfDiag * halfDiag / (1.0f + aspect * aspect));
|
||||
float hw = hh * aspect;
|
||||
|
||||
// cancel all translation
|
||||
mat4 matrix = orientation;
|
||||
matrix[3][0] = 0.0f;
|
||||
|
@ -149,15 +136,14 @@ namespace starfield {
|
|||
#endif
|
||||
|
||||
#if STARFIELD_DEBUG_CULLING
|
||||
mat4 matrix_debug = glm::translate(glm::frustum(-hw, hw, -hh, hh, nearClip, 10.0f),
|
||||
vec3(0.0f, 0.0f, -4.0f)) *
|
||||
mat4 matrix_debug = glm::translate(vec3(0.0f, 0.0f, -4.0f)) *
|
||||
glm::affineInverse(matrix);
|
||||
#endif
|
||||
|
||||
matrix = glm::frustum(-hw,hw, -hh,hh, nearClip,10.0f) * glm::affineInverse(matrix);
|
||||
matrix = glm::affineInverse(matrix);
|
||||
|
||||
this->_outIndexPos = (unsigned*) _batchOffs;
|
||||
this->_wRowVec = vec3(row(matrix, 3));
|
||||
this->_wRowVec = -vec3(row(matrix, 2));
|
||||
this->_halfPerspectiveAngle = halfPersp;
|
||||
this->_minBright = minBright;
|
||||
|
||||
|
@ -498,13 +484,7 @@ namespace starfield {
|
|||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
// setup modelview matrix (identity)
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
// set projection matrix
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
// setup modelview matrix
|
||||
glPushMatrix();
|
||||
glLoadMatrixf(matrix);
|
||||
|
||||
|
@ -529,8 +509,7 @@ namespace starfield {
|
|||
_program.release();
|
||||
glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
|
||||
glDisable(GL_POINT_SMOOTH);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue