diff --git a/interface/src/Camera.cpp b/interface/src/Camera.cpp index e9d8a26675..3d43391f96 100755 --- a/interface/src/Camera.cpp +++ b/interface/src/Camera.cpp @@ -13,18 +13,20 @@ //------------------------ Camera::Camera() { - mode = CAMERA_MODE_THIRD_PERSON; - tightness = DEFAULT_CAMERA_TIGHTNESS; - fieldOfView = 60.0; // default - yaw = 0.0; - pitch = 0.0; - roll = 0.0; - up = 0.0; - distance = 0.0; - targetPosition = glm::vec3( 0.0, 0.0, 0.0 ); - position = glm::vec3( 0.0, 0.0, 0.0 ); - idealPosition = glm::vec3( 0.0, 0.0, 0.0 ); - orientation.setToIdentity(); + _mode = CAMERA_MODE_THIRD_PERSON; + _tightness = DEFAULT_CAMERA_TIGHTNESS; + _fieldOfView = 60.0; // default + _nearClip = 0.1; // default + _farClip = 50.0; // default + _yaw = 0.0; + _pitch = 0.0; + _roll = 0.0; + _up = 0.0; + _distance = 0.0; + _targetPosition = glm::vec3( 0.0, 0.0, 0.0 ); + _position = glm::vec3( 0.0, 0.0, 0.0 ); + _idealPosition = glm::vec3( 0.0, 0.0, 0.0 ); + _orientation.setToIdentity(); } @@ -33,29 +35,28 @@ Camera::Camera() //------------------------------------ void Camera::update( float deltaTime ) { - double radian = ( yaw / 180.0 ) * PIE; + float radian = ( _yaw / 180.0 ) * PIE; //these need to be checked to make sure they correspond to the cordinate system. - double x = distance * -sin( radian ); - double z = distance * cos( radian ); - double y = up; + float x = _distance * -sin( radian ); + float z = _distance * cos( radian ); + float y = _up; - idealPosition = targetPosition + glm::vec3( x, y, z ); - - float t = tightness * deltaTime; + _idealPosition = _targetPosition + glm::vec3( x, y, z ); + float t = _tightness * deltaTime; if ( t > 1.0 ){ t = 1.0; } - position += ( idealPosition - position ) * t; + _position += ( _idealPosition - _position ) * t; //------------------------------------------------------------------------- //geterate the ortho-normals for the orientation based on the Euler angles - //------------------------------------------------------------------------- - orientation.setToIdentity(); - orientation.yaw ( yaw ); - orientation.pitch ( pitch ); - orientation.roll ( roll ); + //------------------------------------------------------------------------ + _orientation.setToIdentity(); + _orientation.yaw ( _yaw ); + _orientation.pitch ( _pitch ); + _orientation.roll ( _roll ); } diff --git a/interface/src/Camera.h b/interface/src/Camera.h index fd347d00f7..89d60aad42 100755 --- a/interface/src/Camera.h +++ b/interface/src/Camera.h @@ -13,11 +13,11 @@ enum CameraMode { - CAMERA_MODE_NULL = -1, - CAMERA_MODE_FIRST_PERSON, - CAMERA_MODE_THIRD_PERSON, - CAMERA_MODE_MY_OWN_FACE, - NUM_CAMERA_MODES + CAMERA_MODE_NULL = -1, + CAMERA_MODE_FIRST_PERSON, + CAMERA_MODE_THIRD_PERSON, + CAMERA_MODE_MY_OWN_FACE, + NUM_CAMERA_MODES }; static const float DEFAULT_CAMERA_TIGHTNESS = 10.0f; @@ -25,42 +25,55 @@ static const float DEFAULT_CAMERA_TIGHTNESS = 10.0f; class Camera { public: - Camera(); - - void update( float deltaTime ); - - void setMode ( CameraMode m ) { mode = m; } - void setYaw ( float y ) { yaw = y; } - void setPitch ( float p ) { pitch = p; } - void setRoll ( float r ) { roll = r; } - void setUp ( float u ) { up = u; } - void setDistance ( float d ) { distance = d; } - void setTargetPosition ( glm::vec3 t ) { targetPosition = t; } - void setPosition ( glm::vec3 p ) { position = p; } - void setTightness ( float t ) { tightness = t; } - void setOrientation ( Orientation o ) { orientation.set(o); } + Camera(); - float getYaw () { return yaw; } - float getPitch () { return pitch; } - float getRoll () { return roll; } - glm::vec3 getPosition () { return position; } - Orientation getOrientation () { return orientation; } - CameraMode getMode () { return mode; } + void update( float deltaTime ); + + void setMode ( CameraMode m ) { _mode = m; } + void setYaw ( float y ) { _yaw = y; } + void setPitch ( float p ) { _pitch = p; } + void setRoll ( float r ) { _roll = r; } + void setUp ( float u ) { _up = u; } + void setDistance ( float d ) { _distance = d; } + void setTargetPosition ( glm::vec3 t ) { _targetPosition = t; }; + void setPosition ( glm::vec3 p ) { _position = p; }; + void setOrientation ( Orientation o ) { _orientation.set(o); } + void setTightness ( float t ) { _tightness = t; } + void setFieldOfView ( float f ) { _fieldOfView = f; } + void setAspectRatio ( float a ) { _aspectRatio = a; } + void setNearClip ( float n ) { _nearClip = n; } + void setFarClip ( float f ) { _farClip = f; } + + float getYaw () { return _yaw; } + float getPitch () { return _pitch; } + float getRoll () { return _roll; } + glm::vec3 getPosition () { return _position; } + Orientation getOrientation () { return _orientation; } + CameraMode getMode () { return _mode; } + float getFieldOfView () { return _fieldOfView; } + float getAspectRatio () { return _aspectRatio; } + float getNearClip () { return _nearClip; } + float getFarClip () { return _farClip; } private: - CameraMode mode; - glm::vec3 position; - glm::vec3 idealPosition; - glm::vec3 targetPosition; - float fieldOfView; - float yaw; - float pitch; - float roll; - float up; - float distance; - float tightness; - Orientation orientation; + CameraMode _mode; + glm::vec3 _position; + glm::vec3 _idealPosition; + glm::vec3 _targetPosition; + float _yaw; + float _pitch; + float _roll; + float _up; + float _distance; + float _tightness; + Orientation _orientation; + + // Lens attributes + float _fieldOfView; // in degrees + float _aspectRatio; // width/height + float _nearClip; // in world units? - XXXBHG - we need to think about this! + float _farClip; // in world units? }; #endif diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 932d96199e..e146d84a1e 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -79,6 +79,9 @@ using namespace std; +void reshape(int width, int height); // will be defined below + + pthread_t networkReceiveThread; bool stopNetworkReceiveThread = false; @@ -97,10 +100,13 @@ bool wantColorRandomizer = true; // for addSphere and load file Oscilloscope audioScope(256,200,true); -Head myAvatar; // The rendered avatar of oneself -Camera myCamera; // My view onto the world (sometimes on myself :) +ViewFrustum viewFrustum; // current state of view frustum, perspective, orientation, etc. - // Starfield information +Head myAvatar; // The rendered avatar of oneself +Camera myCamera; // My view onto the world (sometimes on myself :) +Camera viewFrustumOffsetCamera; // The camera we use to sometimes show the view frustum from an offset mode + +// Starfield information char starFile[] = "https://s3-us-west-1.amazonaws.com/highfidelity/stars.txt"; FieldOfView fov; Stars stars; @@ -516,39 +522,57 @@ float viewFrustumOffsetUp = 0.0; void render_view_frustum() { - glm::vec3 cameraPosition = ::myCamera.getPosition(); - glm::vec3 headPosition = ::myAvatar.getHeadPosition(); - - glm::vec3 cameraDirection = ::myCamera.getOrientation().getFront() * glm::vec3(1,1,-1); - glm::vec3 headDirection = myAvatar.getHeadLookatDirection(); // direction still backwards - - glm::vec3 cameraUp = myCamera.getOrientation().getUp() * glm::vec3(1,1,1); - glm::vec3 headUp = myAvatar.getHeadLookatDirectionUp(); - - glm::vec3 cameraRight = myCamera.getOrientation().getRight() * glm::vec3(1,1,-1); - glm::vec3 headRight = myAvatar.getHeadLookatDirectionRight() * glm::vec3(-1,1,-1); // z is flipped! - // We will use these below, from either the camera or head vectors calculated above glm::vec3 position; glm::vec3 direction; glm::vec3 up; glm::vec3 right; + float fov, nearClip, farClip; // Camera or Head? if (::cameraFrustum) { - position = cameraPosition; - direction = cameraDirection; - up = cameraUp; - right = cameraRight; + position = ::myCamera.getPosition(); + direction = ::myCamera.getOrientation().getFront() * glm::vec3(1,1,-1); + up = ::myCamera.getOrientation().getUp() * glm::vec3(1,1,1); + right = ::myCamera.getOrientation().getRight() * glm::vec3(1,1,-1); + fov = ::myCamera.getFieldOfView(); + nearClip = ::myCamera.getNearClip(); + farClip = ::myCamera.getFarClip(); } else { - position = headPosition; - direction = headDirection; - up = headUp; - right = headRight; + position = ::myAvatar.getHeadPosition(); + direction = ::myAvatar.getHeadLookatDirection(); + up = ::myAvatar.getHeadLookatDirectionUp(); + right = ::myAvatar.getHeadLookatDirectionRight() * glm::vec3(-1,1,-1); + + // NOTE: we use the same lens details if we draw from the head + fov = ::myCamera.getFieldOfView(); + nearClip = ::myCamera.getNearClip(); + farClip = ::myCamera.getFarClip(); } - + + /* + printf("position.x=%f, position.y=%f, position.z=%f\n", position.x, position.y, position.z); + printf("direction.x=%f, direction.y=%f, direction.z=%f\n", direction.x, direction.y, direction.z); + printf("up.x=%f, up.y=%f, up.z=%f\n", up.x, up.y, up.z); + printf("right.x=%f, right.y=%f, right.z=%f\n", right.x, right.y, right.z); + printf("fov=%f\n", fov); + printf("nearClip=%f\n", nearClip); + printf("farClip=%f\n", farClip); + */ + + // Set the viewFrustum up with the correct position and orientation of the camera + viewFrustum.setPosition(position); + viewFrustum.setOrientation(direction,up,right); + + // Also make sure it's got the correct lens details from the camera + viewFrustum.setFieldOfView(fov); + viewFrustum.setNearClip(nearClip); + viewFrustum.setFarClip(farClip); + // Ask the ViewFrustum class to calculate our corners - ViewFrustum vf(position,direction,up,right,::WIDTH,::HEIGHT); + viewFrustum.calculate(); + + //viewFrustum.dump(); // Get ready to draw some lines glDisable(GL_LIGHTING); @@ -581,64 +605,64 @@ void render_view_frustum() { if (::frustumDrawingMode == FRUSTUM_DRAW_MODE_ALL || ::frustumDrawingMode == FRUSTUM_DRAW_MODE_PLANES || ::frustumDrawingMode == FRUSTUM_DRAW_MODE_NEAR_PLANE) { // Drawing the bounds of the frustum - // vf.getNear plane - bottom edge + // viewFrustum.getNear plane - bottom edge glColor3f(1,0,0); - glVertex3f(vf.getNearBottomLeft().x, vf.getNearBottomLeft().y, vf.getNearBottomLeft().z); - glVertex3f(vf.getNearBottomRight().x, vf.getNearBottomRight().y, vf.getNearBottomRight().z); + glVertex3f(viewFrustum.getNearBottomLeft().x, viewFrustum.getNearBottomLeft().y, viewFrustum.getNearBottomLeft().z); + glVertex3f(viewFrustum.getNearBottomRight().x, viewFrustum.getNearBottomRight().y, viewFrustum.getNearBottomRight().z); - // vf.getNear plane - top edge - glVertex3f(vf.getNearTopLeft().x, vf.getNearTopLeft().y, vf.getNearTopLeft().z); - glVertex3f(vf.getNearTopRight().x, vf.getNearTopRight().y, vf.getNearTopRight().z); + // viewFrustum.getNear plane - top edge + glVertex3f(viewFrustum.getNearTopLeft().x, viewFrustum.getNearTopLeft().y, viewFrustum.getNearTopLeft().z); + glVertex3f(viewFrustum.getNearTopRight().x, viewFrustum.getNearTopRight().y, viewFrustum.getNearTopRight().z); - // vf.getNear plane - right edge - glVertex3f(vf.getNearBottomRight().x, vf.getNearBottomRight().y, vf.getNearBottomRight().z); - glVertex3f(vf.getNearTopRight().x, vf.getNearTopRight().y, vf.getNearTopRight().z); + // viewFrustum.getNear plane - right edge + glVertex3f(viewFrustum.getNearBottomRight().x, viewFrustum.getNearBottomRight().y, viewFrustum.getNearBottomRight().z); + glVertex3f(viewFrustum.getNearTopRight().x, viewFrustum.getNearTopRight().y, viewFrustum.getNearTopRight().z); - // vf.getNear plane - left edge - glVertex3f(vf.getNearBottomLeft().x, vf.getNearBottomLeft().y, vf.getNearBottomLeft().z); - glVertex3f(vf.getNearTopLeft().x, vf.getNearTopLeft().y, vf.getNearTopLeft().z); + // viewFrustum.getNear plane - left edge + glVertex3f(viewFrustum.getNearBottomLeft().x, viewFrustum.getNearBottomLeft().y, viewFrustum.getNearBottomLeft().z); + glVertex3f(viewFrustum.getNearTopLeft().x, viewFrustum.getNearTopLeft().y, viewFrustum.getNearTopLeft().z); } if (::frustumDrawingMode == FRUSTUM_DRAW_MODE_ALL || ::frustumDrawingMode == FRUSTUM_DRAW_MODE_PLANES || ::frustumDrawingMode == FRUSTUM_DRAW_MODE_FAR_PLANE) { - // vf.getFar plane - bottom edge + // viewFrustum.getFar plane - bottom edge glColor3f(0,1,0); // GREEN!!! - glVertex3f(vf.getFarBottomLeft().x, vf.getFarBottomLeft().y, vf.getFarBottomLeft().z); - glVertex3f(vf.getFarBottomRight().x, vf.getFarBottomRight().y, vf.getFarBottomRight().z); + glVertex3f(viewFrustum.getFarBottomLeft().x, viewFrustum.getFarBottomLeft().y, viewFrustum.getFarBottomLeft().z); + glVertex3f(viewFrustum.getFarBottomRight().x, viewFrustum.getFarBottomRight().y, viewFrustum.getFarBottomRight().z); - // vf.getFar plane - top edge - glVertex3f(vf.getFarTopLeft().x, vf.getFarTopLeft().y, vf.getFarTopLeft().z); - glVertex3f(vf.getFarTopRight().x, vf.getFarTopRight().y, vf.getFarTopRight().z); + // viewFrustum.getFar plane - top edge + glVertex3f(viewFrustum.getFarTopLeft().x, viewFrustum.getFarTopLeft().y, viewFrustum.getFarTopLeft().z); + glVertex3f(viewFrustum.getFarTopRight().x, viewFrustum.getFarTopRight().y, viewFrustum.getFarTopRight().z); - // vf.getFar plane - right edge - glVertex3f(vf.getFarBottomRight().x, vf.getFarBottomRight().y, vf.getFarBottomRight().z); - glVertex3f(vf.getFarTopRight().x, vf.getFarTopRight().y, vf.getFarTopRight().z); + // viewFrustum.getFar plane - right edge + glVertex3f(viewFrustum.getFarBottomRight().x, viewFrustum.getFarBottomRight().y, viewFrustum.getFarBottomRight().z); + glVertex3f(viewFrustum.getFarTopRight().x, viewFrustum.getFarTopRight().y, viewFrustum.getFarTopRight().z); - // vf.getFar plane - left edge - glVertex3f(vf.getFarBottomLeft().x, vf.getFarBottomLeft().y, vf.getFarBottomLeft().z); - glVertex3f(vf.getFarTopLeft().x, vf.getFarTopLeft().y, vf.getFarTopLeft().z); + // viewFrustum.getFar plane - left edge + glVertex3f(viewFrustum.getFarBottomLeft().x, viewFrustum.getFarBottomLeft().y, viewFrustum.getFarBottomLeft().z); + glVertex3f(viewFrustum.getFarTopLeft().x, viewFrustum.getFarTopLeft().y, viewFrustum.getFarTopLeft().z); } if (::frustumDrawingMode == FRUSTUM_DRAW_MODE_ALL || ::frustumDrawingMode == FRUSTUM_DRAW_MODE_PLANES) { // RIGHT PLANE IS CYAN - // right plane - bottom edge - vf.getNear to distant + // right plane - bottom edge - viewFrustum.getNear to distant glColor3f(0,1,1); - glVertex3f(vf.getNearBottomRight().x, vf.getNearBottomRight().y, vf.getNearBottomRight().z); - glVertex3f(vf.getFarBottomRight().x, vf.getFarBottomRight().y, vf.getFarBottomRight().z); + glVertex3f(viewFrustum.getNearBottomRight().x, viewFrustum.getNearBottomRight().y, viewFrustum.getNearBottomRight().z); + glVertex3f(viewFrustum.getFarBottomRight().x, viewFrustum.getFarBottomRight().y, viewFrustum.getFarBottomRight().z); - // right plane - top edge - vf.getNear to distant - glVertex3f(vf.getNearTopRight().x, vf.getNearTopRight().y, vf.getNearTopRight().z); - glVertex3f(vf.getFarTopRight().x, vf.getFarTopRight().y, vf.getFarTopRight().z); + // right plane - top edge - viewFrustum.getNear to distant + glVertex3f(viewFrustum.getNearTopRight().x, viewFrustum.getNearTopRight().y, viewFrustum.getNearTopRight().z); + glVertex3f(viewFrustum.getFarTopRight().x, viewFrustum.getFarTopRight().y, viewFrustum.getFarTopRight().z); // LEFT PLANE IS BLUE - // left plane - bottom edge - vf.getNear to distant + // left plane - bottom edge - viewFrustum.getNear to distant glColor3f(0,0,1); - glVertex3f(vf.getNearBottomLeft().x, vf.getNearBottomLeft().y, vf.getNearBottomLeft().z); - glVertex3f(vf.getFarBottomLeft().x, vf.getFarBottomLeft().y, vf.getFarBottomLeft().z); + glVertex3f(viewFrustum.getNearBottomLeft().x, viewFrustum.getNearBottomLeft().y, viewFrustum.getNearBottomLeft().z); + glVertex3f(viewFrustum.getFarBottomLeft().x, viewFrustum.getFarBottomLeft().y, viewFrustum.getFarBottomLeft().z); - // left plane - top edge - vf.getNear to distant - glVertex3f(vf.getNearTopLeft().x, vf.getNearTopLeft().y, vf.getNearTopLeft().z); - glVertex3f(vf.getFarTopLeft().x, vf.getFarTopLeft().y, vf.getFarTopLeft().z); + // left plane - top edge - viewFrustum.getNear to distant + glVertex3f(viewFrustum.getNearTopLeft().x, viewFrustum.getNearTopLeft().y, viewFrustum.getNearTopLeft().z); + glVertex3f(viewFrustum.getFarTopLeft().x, viewFrustum.getFarTopLeft().y, viewFrustum.getFarTopLeft().z); } glEnd(); @@ -648,8 +672,6 @@ void render_view_frustum() { void display(void) { - //printf( "avatar head lookat = %f, %f, %f\n", myAvatar.getAvatarHeadLookatDirection().x, myAvatar.getAvatarHeadLookatDirection().y, myAvatar.getAvatarHeadLookatDirection().z ); - PerfStat("display"); glEnable(GL_LINE_SMOOTH); @@ -696,13 +718,14 @@ void display(void) //---------------------------------------------------- myCamera.setTargetPosition ( myAvatar.getPos() ); myCamera.setYaw ( 180.0 - myAvatar.getBodyYaw() ); - myCamera.setPitch ( 10.0 ); + myCamera.setPitch ( 0.0 ); // temporarily, this must be 0.0 or else bad juju myCamera.setRoll ( 0.0 ); myCamera.setUp ( 0.45 ); myCamera.setDistance ( 0.5 ); myCamera.setTightness ( 10.0f ); myCamera.update ( 1.f/FPS ); } + // 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 @@ -713,21 +736,20 @@ void display(void) // myCamera is. But we also want to do meaningful camera transforms on OpenGL for the offset camera Camera whichCamera = myCamera; Camera viewFrustumOffsetCamera = myCamera; - + if (::viewFrustumFromOffset && ::frustumOn) { //---------------------------------------------------- // set the camera to third-person view but offset so we can see the frustum //---------------------------------------------------- viewFrustumOffsetCamera.setYaw ( 180.0 - myAvatar.getBodyYaw() + ::viewFrustumOffsetYaw ); - viewFrustumOffsetCamera.setPitch ( 0.0 + ::viewFrustumOffsetPitch ); - viewFrustumOffsetCamera.setRoll ( 0.0 + ::viewFrustumOffsetRoll ); - viewFrustumOffsetCamera.setUp ( 0.2 + 0.2 ); - viewFrustumOffsetCamera.setDistance( 0.5 + 0.2 ); - viewFrustumOffsetCamera.update( 1.f/FPS ); - + viewFrustumOffsetCamera.setPitch ( 0.0 + ::viewFrustumOffsetPitch ); + viewFrustumOffsetCamera.setRoll ( 0.0 + ::viewFrustumOffsetRoll ); + viewFrustumOffsetCamera.setUp ( 0.2 + ::viewFrustumOffsetUp ); + viewFrustumOffsetCamera.setDistance ( 0.5 + ::viewFrustumOffsetDistance ); + viewFrustumOffsetCamera.update(1.f/FPS); whichCamera = viewFrustumOffsetCamera; } - + //--------------------------------------------- // transform view according to whichCamera // could be myCamera (if in normal mode) @@ -738,6 +760,8 @@ void display(void) glRotatef ( whichCamera.getRoll(), 0, 0, 1 ); glTranslatef( -whichCamera.getPosition().x, -whichCamera.getPosition().y, -whichCamera.getPosition().z ); + + if (::starsOn) { // should be the first rendering pass - w/o depth buffer / lighting stars.render(fov); @@ -954,7 +978,14 @@ int setDisplayFrustum(int state) { } int setFrustumOffset(int state) { - return setValue(state, &::viewFrustumFromOffset); + int value = setValue(state, &::viewFrustumFromOffset); + + // reshape so that OpenGL will get the right lens details for the camera of choice + if (state == MENU_ROW_PICKED) { + reshape(::WIDTH,::HEIGHT); + } + + return value; } int setFrustumOrigin(int state) { @@ -1014,12 +1045,13 @@ void initMenu() { menuColumnOptions->addRow("(V)oxels", setVoxels); menuColumnOptions->addRow("Stars (*)", setStars); menuColumnOptions->addRow("(Q)uit", quitApp); + // Tools menuColumnTools = menu.addColumn("Tools"); menuColumnTools->addRow("Stats (/)", setStats); menuColumnTools->addRow("(M)enu", setMenu); - // Debug + // Frustum Options menuColumnFrustum = menu.addColumn("Frustum"); menuColumnFrustum->addRow("Display (F)rustum", setDisplayFrustum); menuColumnFrustum->addRow("Use (O)ffset Camera", setFrustumOffset); @@ -1175,7 +1207,7 @@ void key(unsigned char k, int x, int y) if (k == 'V' || k == 'v') ::showingVoxels = !::showingVoxels; // toggle voxels if (k == 'F') ::frustumOn = !::frustumOn; // toggle view frustum debugging if (k == 'C') ::cameraFrustum = !::cameraFrustum; // toggle which frustum to look at - if (k == 'O' || k == 'G') ::viewFrustumFromOffset = !::viewFrustumFromOffset; // toggle view frustum offset debugging + if (k == 'O' || k == 'G') setFrustumOffset(MENU_ROW_PICKED); // toggle view frustum offset debugging if (k == '[') ::viewFrustumOffsetYaw -= 0.5; if (k == ']') ::viewFrustumOffsetYaw += 0.5; @@ -1187,8 +1219,10 @@ void key(unsigned char k, int x, int y) if (k == '>') ::viewFrustumOffsetDistance += 0.5; if (k == ',') ::viewFrustumOffsetUp -= 0.05; if (k == '.') ::viewFrustumOffsetUp += 0.05; - if (k == '|') ViewFrustum::fovAngleAdust -= 0.05; - if (k == '\\') ViewFrustum::fovAngleAdust += 0.05; + +// if (k == '|') ViewFrustum::fovAngleAdust -= 0.05; +// if (k == '\\') ViewFrustum::fovAngleAdust += 0.05; + if (k == 'R') setFrustumRenderMode(MENU_ROW_PICKED); if (k == '&') { @@ -1349,27 +1383,66 @@ void idle(void) { } - void reshape(int width, int height) { WIDTH = width; HEIGHT = height; + float aspectRatio = ((float)width/(float)height); // based on screen resize + float fov; + float nearClip; + float farClip; + + // get the lens details from the current camera + if (::viewFrustumFromOffset) { + fov = ::viewFrustumOffsetCamera.getFieldOfView(); + nearClip = ::viewFrustumOffsetCamera.getNearClip(); + farClip = ::viewFrustumOffsetCamera.getFarClip(); + } else { + fov = ::myCamera.getFieldOfView(); + nearClip = ::myCamera.getNearClip(); + farClip = ::myCamera.getFarClip(); + } + + //printf("reshape() width=%d, height=%d, aspectRatio=%f fov=%f near=%f far=%f \n", + // width,height,aspectRatio,fov,nearClip,farClip); + + // Tell our viewFrustum about this change + ::viewFrustum.setAspectRatio(aspectRatio); + + + glViewport(0, 0, width, height); // shouldn't this account for the menu??? glMatrixMode(GL_PROJECTION); //hello - fov.setResolution(width, height) - .setBounds(glm::vec3(-0.5f,-0.5f,-500.0f), glm::vec3(0.5f, 0.5f, 0.1f) ) - .setPerspective(0.7854f); - glLoadMatrixf(glm::value_ptr(fov.getViewerScreenXform())); + // XXXBHG - Note: this is Tobias's code for loading the perspective matrix. At Philip's suggestion, I'm removing + // it and putting back our old code that simply loaded the fov, ratio, and near/far clips. But I'm keeping this here + // for reference for now. + //fov.setResolution(width, height) + // .setBounds(glm::vec3(-0.5f,-0.5f,-500.0f), glm::vec3(0.5f, 0.5f, 0.1f) ) + // .setPerspective(0.7854f); + //glLoadMatrixf(glm::value_ptr(fov.getViewerScreenXform())); + + glLoadIdentity(); + + // XXXBHG - If we're in view frustum mode, then we need to do this little bit of hackery so that + // OpenGL won't clip our frustum rendering lines. This is a debug hack for sure! Basically, this makes + // the near clip a little bit closer (therefor you see more) and the far clip a little bit farther (also, + // to see more.) + if (::frustumOn) { + nearClip -= 0.01f; + farClip += 0.01f; + } + + // On window reshape, we need to tell OpenGL about our new setting + gluPerspective(fov,aspectRatio,nearClip,farClip); + glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - glViewport(0, 0, width, height); + } - - void mouseFunc( int button, int state, int x, int y ) { if( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN ) @@ -1459,6 +1532,12 @@ int main(int argc, const char * argv[]) #ifdef _WIN32 glewInit(); #endif + + // Before we render anything, let's set up our viewFrustumOffsetCamera with a sufficiently large + // field of view and near and far clip to make it interesting. + //viewFrustumOffsetCamera.setFieldOfView(90.0); + viewFrustumOffsetCamera.setNearClip(0.1); + viewFrustumOffsetCamera.setFarClip(500.0); printf( "Created Display Window.\n" ); diff --git a/libraries/voxels/src/ViewFrustum.cpp b/libraries/voxels/src/ViewFrustum.cpp index 73cce9baad..1de5c11d6a 100644 --- a/libraries/voxels/src/ViewFrustum.cpp +++ b/libraries/voxels/src/ViewFrustum.cpp @@ -8,14 +8,32 @@ // // +#include "Util.h" #include "ViewFrustum.h" -float ViewFrustum::fovAngleAdust=1.65; - -ViewFrustum::ViewFrustum(glm::vec3 position, glm::vec3 direction, - glm::vec3 up, glm::vec3 right, float screenWidth, float screenHeight) { - this->calculateViewFrustum(position, direction, up, right, screenWidth, screenHeight); -} +ViewFrustum::ViewFrustum() : + _position(glm::vec3(0,0,0)), + _direction(glm::vec3(0,0,0)), + _up(glm::vec3(0,0,0)), + _right(glm::vec3(0,0,0)), + _fieldOfView(0.0), + _aspectRatio(1.0), + _nearClip(0.1), + _farClip(500.0), + _nearHeight(0.0), + _nearWidth(0.0), + _farHeight(0.0), + _farWidth(0.0), + _farCenter(glm::vec3(0,0,0)), + _farTopLeft(glm::vec3(0,0,0)), + _farTopRight(glm::vec3(0,0,0)), + _farBottomLeft(glm::vec3(0,0,0)), + _farBottomRight(glm::vec3(0,0,0)), + _nearCenter(glm::vec3(0,0,0)), + _nearTopLeft(glm::vec3(0,0,0)), + _nearTopRight(glm::vec3(0,0,0)), + _nearBottomLeft(glm::vec3(0,0,0)), + _nearBottomRight(glm::vec3(0,0,0)) { } ///////////////////////////////////////////////////////////////////////////////////// // ViewFrustum::calculateViewFrustum() @@ -26,47 +44,41 @@ ViewFrustum::ViewFrustum(glm::vec3 position, glm::vec3 direction, // Notes on how/why this works: // http://www.lighthouse3d.com/tutorials/view-frustum-culling/view-frustums-shape/ // -void ViewFrustum::calculateViewFrustum(glm::vec3 position, glm::vec3 direction, - glm::vec3 up, glm::vec3 right, float screenWidth, float screenHeight) { +void ViewFrustum::calculate() { + + static const double PI_OVER_180 = 3.14159265359 / 180.0; // would be better if this was in a shared location - // Save the values we were passed... - this->_position = position; - this->_direction = direction; - this->_up = up; - this->_right = right; - this->_screenWidth = screenWidth; - this->_screenHeight = screenHeight; - - glm::vec3 front = direction; + glm::vec3 front = _direction; // Calculating field of view. - // 0.7854f is 45 deg - // ViewFrustum::fovAngleAdust defaults to 1.65 - // Apparently our fov is around 1.75 times this value or 74.25 degrees - // you can adjust this in interface by using the "|" and "\" keys to tweak - // the adjustment and see effects of different FOVs - float fovHalfAngle = 0.7854f * ViewFrustum::fovAngleAdust; - float ratio = screenWidth / screenHeight; + float fovInRadians = this->_fieldOfView * PI_OVER_180; - this->_nearDist = 0.1; - this->_farDist = 10.0; - - this->_nearHeight = 2 * tan(fovHalfAngle) * this->_nearDist; - this->_nearWidth = this->_nearHeight * ratio; - this->_farHeight = 2 * tan(fovHalfAngle) * this->_farDist; - this->_farWidth = this->_farHeight * ratio; + float twoTimesTanHalfFOV = 2.0f * tan(fovInRadians/2.0f); - float farHalfHeight = this->_farHeight * 0.5f; - float farHalfWidth = this->_farWidth * 0.5f; - this->_farCenter = this->_position+front * this->_farDist; + float slightlySmaller = 0.0f; + float slightlyInsideWidth= 0.0f - slightlySmaller; + float slightlyInsideNear = 0.0f + slightlySmaller; + float slightlyInsideFar = 0.0f - slightlySmaller; + + float nearClip = this->_nearClip + slightlyInsideNear; + float farClip = this->_farClip + slightlyInsideFar; + + this->_nearHeight = (twoTimesTanHalfFOV * nearClip); + this->_nearWidth = this->_nearHeight * this->_aspectRatio; + this->_farHeight = (twoTimesTanHalfFOV * farClip); + this->_farWidth = this->_farHeight * this->_aspectRatio; + + float farHalfHeight = (this->_farHeight * 0.5f) + slightlyInsideWidth; + float farHalfWidth = (this->_farWidth * 0.5f) + slightlyInsideWidth; + this->_farCenter = this->_position+front * farClip; this->_farTopLeft = this->_farCenter + (this->_up * farHalfHeight) - (this->_right * farHalfWidth); this->_farTopRight = this->_farCenter + (this->_up * farHalfHeight) + (this->_right * farHalfWidth); this->_farBottomLeft = this->_farCenter - (this->_up * farHalfHeight) - (this->_right * farHalfWidth); this->_farBottomRight = this->_farCenter - (this->_up * farHalfHeight) + (this->_right * farHalfWidth); - float nearHalfHeight = this->_nearHeight * 0.5f; - float nearHalfWidth = this->_nearWidth * 0.5f; - this->_nearCenter = this->_position+front * this->_nearDist; + float nearHalfHeight = (this->_nearHeight * 0.5f) + slightlyInsideWidth; + float nearHalfWidth = (this->_nearWidth * 0.5f) + slightlyInsideWidth; + this->_nearCenter = this->_position+front * nearClip; this->_nearTopLeft = this->_nearCenter + (this->_up * nearHalfHeight) - (this->_right * nearHalfWidth); this->_nearTopRight = this->_nearCenter + (this->_up * nearHalfHeight) + (this->_right * nearHalfWidth); this->_nearBottomLeft = this->_nearCenter - (this->_up * nearHalfHeight) - (this->_right * nearHalfWidth); @@ -80,11 +92,11 @@ void ViewFrustum::dump() { printf("up.x=%f, up.y=%f, up.z=%f\n", this->_up.x, this->_up.y, this->_up.z); printf("right.x=%f, right.y=%f, right.z=%f\n", this->_right.x, this->_right.y, this->_right.z); - printf("farDist=%f\n", this->_farDist); + printf("farDist=%f\n", this->_farClip); printf("farHeight=%f\n", this->_farHeight); printf("farWidth=%f\n", this->_farWidth); - printf("nearDist=%f\n", this->_nearDist); + printf("nearDist=%f\n", this->_nearClip); printf("nearHeight=%f\n", this->_nearHeight); printf("nearWidth=%f\n", this->_nearWidth); diff --git a/libraries/voxels/src/ViewFrustum.h b/libraries/voxels/src/ViewFrustum.h index 9fb17ae339..ed704e5755 100644 --- a/libraries/voxels/src/ViewFrustum.h +++ b/libraries/voxels/src/ViewFrustum.h @@ -15,54 +15,70 @@ class ViewFrustum { private: - glm::vec3 _position; - glm::vec3 _direction; - glm::vec3 _up; - glm::vec3 _right; - float _screenWidth; - float _screenHeight; - float _nearDist; - float _farDist; - - float _nearHeight; - float _nearWidth; - float _farHeight; - float _farWidth; + // camera location/orientation attributes + glm::vec3 _position; + glm::vec3 _direction; + glm::vec3 _up; + glm::vec3 _right; - glm::vec3 _farCenter; - glm::vec3 _farTopLeft; - glm::vec3 _farTopRight; - glm::vec3 _farBottomLeft; - glm::vec3 _farBottomRight; + // Lens attributes + float _fieldOfView; + float _aspectRatio; + float _nearClip; + float _farClip; - glm::vec3 _nearCenter; - glm::vec3 _nearTopLeft; - glm::vec3 _nearTopRight; - glm::vec3 _nearBottomLeft; - glm::vec3 _nearBottomRight; + // Calculated values + float _nearHeight; + float _nearWidth; + float _farHeight; + float _farWidth; + glm::vec3 _farCenter; + glm::vec3 _farTopLeft; + glm::vec3 _farTopRight; + glm::vec3 _farBottomLeft; + glm::vec3 _farBottomRight; + glm::vec3 _nearCenter; + glm::vec3 _nearTopLeft; + glm::vec3 _nearTopRight; + glm::vec3 _nearBottomLeft; + glm::vec3 _nearBottomRight; + public: - const glm::vec3& getFarCenter() const { return _farCenter; }; - const glm::vec3& getFarTopLeft() const { return _farTopLeft; }; - const glm::vec3& getFarTopRight() const { return _farTopRight; }; - const glm::vec3& getFarBottomLeft() const { return _farBottomLeft; }; - const glm::vec3& getFarBottomRight() const { return _farBottomRight; }; + // setters for camera attributes + void setPosition (const glm::vec3& p) { _position = p; } + void setOrientation (const glm::vec3& d, const glm::vec3& u, const glm::vec3& r ) + { _direction = d; _up = u; _right = r; } - const glm::vec3& getNearCenter() const { return _nearCenter; }; - const glm::vec3& getNearTopLeft() const { return _nearTopLeft; }; - const glm::vec3& getNearTopRight() const { return _nearTopRight; }; - const glm::vec3& getNearBottomLeft() const { return _nearBottomLeft; }; - const glm::vec3& getNearBottomRight() const { return _nearBottomRight; }; + // setters for lens attributes + void setFieldOfView ( float f ) { _fieldOfView = f; } + void setAspectRatio ( float a ) { _aspectRatio = a; } + void setNearClip ( float n ) { _nearClip = n; } + void setFarClip ( float f ) { _farClip = f; } - void calculateViewFrustum(glm::vec3 position, glm::vec3 direction, - glm::vec3 up, glm::vec3 right, float screenWidth, float screenHeight); + // getters for lens attributes + float getFieldOfView() const { return _fieldOfView; }; + float getAspectRatio() const { return _aspectRatio; }; + float getNearClip() const { return _nearClip; }; + float getFarClip() const { return _farClip; }; - ViewFrustum(glm::vec3 position, glm::vec3 direction, - glm::vec3 up, glm::vec3 right, float screenWidth, float screenHeight); - - void dump(); - - static float fovAngleAdust; + const glm::vec3& getFarCenter() const { return _farCenter; }; + const glm::vec3& getFarTopLeft() const { return _farTopLeft; }; + const glm::vec3& getFarTopRight() const { return _farTopRight; }; + const glm::vec3& getFarBottomLeft() const { return _farBottomLeft; }; + const glm::vec3& getFarBottomRight() const { return _farBottomRight; }; + + const glm::vec3& getNearCenter() const { return _nearCenter; }; + const glm::vec3& getNearTopLeft() const { return _nearTopLeft; }; + const glm::vec3& getNearTopRight() const { return _nearTopRight; }; + const glm::vec3& getNearBottomLeft() const { return _nearBottomLeft; }; + const glm::vec3& getNearBottomRight() const { return _nearBottomRight;}; + + void calculate(); + + ViewFrustum(); + + void dump(); };