diff --git a/interface/src/Camera.cpp b/interface/src/Camera.cpp index 5539413b2b..a718c8a137 100644 --- a/interface/src/Camera.cpp +++ b/interface/src/Camera.cpp @@ -14,18 +14,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(); } @@ -34,29 +36,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 100644 --- 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/Head.cpp b/interface/src/Head.cpp index 06ebdad0f3..97b50bfc3e 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -214,6 +214,7 @@ void Head::UpdatePos(float frametime, SerialInterface * serialInterface, int hea if ((Pitch < MAX_PITCH) && (Pitch > MIN_PITCH)) addPitch(measured_pitch_rate * -HEAD_ROTATION_SCALE * frametime); + addRoll(-measured_roll_rate * HEAD_ROLL_SCALE * frametime); if (head_mirror) { diff --git a/interface/src/OGlProgram.h b/interface/src/OGlProgram.h index 06e684d2b3..23d42b0f35 100644 --- a/interface/src/OGlProgram.h +++ b/interface/src/OGlProgram.h @@ -60,8 +60,10 @@ public: */ void activate() const { - if (_hndProg != 0u) + if (_hndProg != 0u) { + oGlLog( glUseProgram(_hndProg) ); + } } /** @@ -77,16 +79,20 @@ public: */ bool addShader(GLenum type, GLsizei nStrings, GLchar const** strings) { - if (! _hndProg) { _hndProg = glCreateProgram(); } + if (! _hndProg && !! glCreateProgram) { + + _hndProg = glCreateProgram(); + } + if (! _hndProg) { return false; } GLuint s = glCreateShader(type); glShaderSource(s, nStrings, strings, 0l); glCompileShader(s); GLint status; glGetShaderiv(s, GL_COMPILE_STATUS, & status); - if (!! status) + if (status != 0) glAttachShader(_hndProg, s); -#ifdef NDEBUG +#ifdef NDEBUG // always fetch log in debug mode else #endif fetchLog(s, glGetShaderiv, glGetShaderInfoLog); @@ -104,12 +110,21 @@ public: glLinkProgram(_hndProg); GLint status; glGetProgramiv(_hndProg, GL_LINK_STATUS, & status); -#ifdef NDEBUG - if (status == 0) +#ifndef NDEBUG // always fetch log in debug mode + fetchLog(_hndProg, glGetProgramiv, glGetProgramInfoLog); #endif + if (status == 0) { +#ifdef NDEBUG // only on error in release mode fetchLog(_hndProg, glGetProgramiv, glGetProgramInfoLog); +#endif + glDeleteProgram(_hndProg); + _hndProg = 0u; + return false; - return status != 0; + } else { + + return true; + } } private: diff --git a/interface/src/SerialInterface.cpp b/interface/src/SerialInterface.cpp index 9ab1ce6373..7a124f02f3 100644 --- a/interface/src/SerialInterface.cpp +++ b/interface/src/SerialInterface.cpp @@ -6,12 +6,12 @@ // // Channels are received in the following order (integer 0-4096 based on voltage 0-3.3v) // -// AIN 15: Pitch Gyro (nodding your head 'yes') -// AIN 16: Yaw Gyro (shaking your head 'no') -// AIN 17: Roll Gyro (looking quizzical, tilting your head) -// AIN 18: Lateral acceleration (moving from side-to-side in front of your monitor) -// AIN 19: Up/Down acceleration (sitting up/ducking in front of your monitor) -// AIN 20: Forward/Back acceleration (Toward or away from your monitor) +// 0 - AIN 15: Pitch Gyro (nodding your head 'yes') +// 1 - AIN 16: Yaw Gyro (shaking your head 'no') +// 2 - AIN 17: Roll Gyro (looking quizzical, tilting your head) +// 3 - AIN 18: Lateral acceleration (moving from side-to-side in front of your monitor) +// 4 - AIN 19: Up/Down acceleration (sitting up/ducking in front of your monitor) +// 5 - AIN 20: Forward/Back acceleration (Toward or away from your monitor) // #include "SerialInterface.h" @@ -21,14 +21,15 @@ #include #endif -int serial_fd; +int serialFd; const int MAX_BUFFER = 255; -char serial_buffer[MAX_BUFFER]; -int serial_buffer_pos = 0; +char serialBuffer[MAX_BUFFER]; +int serialBufferPos = 0; const int ZERO_OFFSET = 2048; const short NO_READ_MAXIMUM_MSECS = 3000; -const short SAMPLES_TO_DISCARD = 100; +const short SAMPLES_TO_DISCARD = 100; // Throw out the first few samples +const int GRAVITY_SAMPLES = 200; // Use the first samples to compute gravity vector void SerialInterface::pair() { @@ -48,7 +49,7 @@ void SerialInterface::pair() { char *serialPortname = new char[100]; sprintf(serialPortname, "/dev/%s", entry->d_name); - init(serialPortname, 115200); + initializePort(serialPortname, 115200); delete [] serialPortname; } @@ -60,18 +61,20 @@ void SerialInterface::pair() { } -// Init the serial port to the specified values -int SerialInterface::init(char* portname, int baud) +// Connect to the serial port +int SerialInterface::initializePort(char* portname, int baud) { #ifdef __APPLE__ - serial_fd = open(portname, O_RDWR | O_NOCTTY | O_NDELAY); + serialFd = open(portname, O_RDWR | O_NOCTTY | O_NDELAY); - printf("Attemping to open serial interface: %s\n", portname); - - if (serial_fd == -1) return -1; // Failed to open port + printf("Opening SerialUSB %s: ", portname); + if (serialFd == -1) { + printf("Failed.\n"); + return -1; // Failed to open port + } struct termios options; - tcgetattr(serial_fd,&options); + tcgetattr(serialFd,&options); switch(baud) { case 9600: cfsetispeed(&options,B9600); @@ -95,10 +98,10 @@ int SerialInterface::init(char* portname, int baud) options.c_cflag &= ~CSTOPB; options.c_cflag &= ~CSIZE; options.c_cflag |= CS8; - tcsetattr(serial_fd,TCSANOW,&options); + tcsetattr(serialFd,TCSANOW,&options); - printf("Serial interface opened!\n"); + printf("Connected.\n"); resetSerial(); active = true; #endif @@ -126,22 +129,17 @@ void SerialInterface::renderLevels(int width, int height) { glBegin(GL_LINES); glVertex2f(disp_x, height*0.95); glVertex2f(disp_x, height*(0.25 + 0.75f*getValue(i)/4096)); + glColor4f(1, 0, 0, 1); + glVertex2f(disp_x - 3, height*(0.25 + 0.75f*getValue(i)/4096)); + glVertex2f(disp_x, height*(0.25 + 0.75f*getValue(i)/4096)); glEnd(); // Trailing Average value - glColor4f(1, 1, 0, 1); glBegin(GL_LINES); - glVertex2f(disp_x + 2, height*0.95); - glVertex2f(disp_x + 2, height*(0.25 + 0.75f*getTrailingValue(i)/4096)); + glColor4f(1, 1, 1, 1); + glVertex2f(disp_x, height*(0.25 + 0.75f*getTrailingValue(i)/4096)); + glVertex2f(disp_x + 4, height*(0.25 + 0.75f*getTrailingValue(i)/4096)); glEnd(); - /* - glColor3f(1,0,0); - glBegin(GL_LINES); - glLineWidth(4.0); - glVertex2f(disp_x - 10, height*0.5 - getValue(i)/4096); - glVertex2f(disp_x + 10, height*0.5 - getValue(i)/4096); - glEnd(); - */ sprintf(val, "%d", getValue(i)); drawtext(disp_x-GAP/2, (height*0.95)+2, 0.08, 90, 1.0, 0, val, 0, 1, 0); @@ -162,20 +160,20 @@ void SerialInterface::renderLevels(int width, int height) { } void SerialInterface::readData() { #ifdef __APPLE__ - // This array sets the rate of trailing averaging for each channel. + // This array sets the rate of trailing averaging for each channel: // If the sensor rate is 100Hz, 0.001 will make the long term average a 10-second average - const float AVG_RATE[] = {0.01, 0.01, 0.01, 0.01, 0.01, 0.01}; + const float AVG_RATE[] = {0.002, 0.002, 0.002, 0.002, 0.002, 0.002}; char bufchar[1]; int initialSamples = totalSamples; - while (read(serial_fd, &bufchar, 1) > 0) { + while (read(serialFd, &bufchar, 1) > 0) { //std::cout << bufchar[0]; - serial_buffer[serial_buffer_pos] = bufchar[0]; - serial_buffer_pos++; + serialBuffer[serialBufferPos] = bufchar[0]; + serialBufferPos++; // Have we reached end of a line of input? - if ((bufchar[0] == '\n') || (serial_buffer_pos >= MAX_BUFFER)) { - std::string serialLine(serial_buffer, serial_buffer_pos-1); + if ((bufchar[0] == '\n') || (serialBufferPos >= MAX_BUFFER)) { + std::string serialLine(serialBuffer, serialBufferPos-1); //std::cout << serialLine << "\n"; int spot; //int channel = 0; @@ -191,6 +189,7 @@ void SerialInterface::readData() { serialLine = serialLine.substr(spot+1, serialLine.length() - spot - 1); } + // Update Trailing Averages for (int i = 0; i < NUM_CHANNELS; i++) { if (totalSamples > SAMPLES_TO_DISCARD) { trailingAverage[i] = (1.f - AVG_RATE[i])*trailingAverage[i] + @@ -200,8 +199,21 @@ void SerialInterface::readData() { } } + + // Use a set of initial samples to compute gravity + if (totalSamples < GRAVITY_SAMPLES) { + gravity.x += lastMeasured[ACCEL_X]; + gravity.y += lastMeasured[ACCEL_Y]; + gravity.z += lastMeasured[ACCEL_Z]; + } + if (totalSamples == GRAVITY_SAMPLES) { + gravity = glm::normalize(gravity); + std::cout << "gravity: " << gravity.x << "," << + gravity.y << "," << gravity.z << "\n"; + } + totalSamples++; - serial_buffer_pos = 0; + serialBufferPos = 0; } } @@ -210,7 +222,7 @@ void SerialInterface::readData() { gettimeofday(&now, NULL); if (diffclock(&lastGoodRead, &now) > NO_READ_MAXIMUM_MSECS) { - std::cout << "No data coming over serial. Shutting down SerialInterface.\n"; + std::cout << "No data - Shutting down SerialInterface.\n"; resetSerial(); } } else { @@ -223,6 +235,7 @@ void SerialInterface::resetSerial() { #ifdef __APPLE__ active = false; totalSamples = 0; + gravity = glm::vec3(0,-1,0); gettimeofday(&lastGoodRead, NULL); @@ -233,7 +246,7 @@ void SerialInterface::resetSerial() { } // Clear serial input buffer for (int i = 1; i < MAX_BUFFER; i++) { - serial_buffer[i] = ' '; + serialBuffer[i] = ' '; } #endif } diff --git a/interface/src/SerialInterface.h b/interface/src/SerialInterface.h index 8849d7f5d9..50fde4a13d 100644 --- a/interface/src/SerialInterface.h +++ b/interface/src/SerialInterface.h @@ -45,8 +45,10 @@ public: void resetTrailingAverages(); void renderLevels(int width, int height); bool active; + glm::vec3 getGravity() {return gravity;}; + private: - int init(char * portname, int baud); + int initializePort(char * portname, int baud); void resetSerial(); int lastMeasured[NUM_CHANNELS]; float trailingAverage[NUM_CHANNELS]; @@ -54,6 +56,7 @@ private: int LED; int totalSamples; timeval lastGoodRead; + glm::vec3 gravity; }; #endif diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 75bf28cc26..efb9a70e28 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; @@ -136,10 +142,7 @@ Audio audio(&audioScope, &myAvatar); #define IDLE_SIMULATE_MSECS 8 // How often should call simulate and other stuff // in the idle loop? -float yaw = 0.f; // The yaw, pitch for the avatar head -float pitch = 0.f; float startYaw = 122.f; -float renderPitch = 0.f; float renderYawRate = 0.f; float renderPitchRate = 0.f; @@ -364,7 +367,7 @@ void reset_sensors() } } -void simulateHand(float deltaTime) { +void updateAvatarHand(float deltaTime) { // If mouse is being dragged, send current force to the hand controller if (mousePressed == 1) { @@ -378,28 +381,26 @@ void simulateHand(float deltaTime) { } } -void simulateHead(float frametime) -// Using serial data, update avatar/render position and angles +// +// Using gyro data, update both view frustum and avatar head position +// +void updateAvatar(float frametime) { -// float measured_pitch_rate = serialPort.getRelativeValue(PITCH_RATE); -// float measured_yaw_rate = serialPort.getRelativeValue(YAW_RATE); - - float measured_pitch_rate = 0; - float measured_yaw_rate = 0; - - //float measured_lateral_accel = serialPort.getRelativeValue(ACCEL_X); - //float measured_fwd_accel = serialPort.getRelativeValue(ACCEL_Z); + float gyroPitchRate = serialPort.getRelativeValue(PITCH_RATE); + float gyroYawRate = serialPort.getRelativeValue(YAW_RATE); myAvatar.UpdatePos(frametime, &serialPort, headMirror, &gravity); - // Update head_mouse model + // + // Update gyro-based mouse (X,Y on screen) + // const float MIN_MOUSE_RATE = 30.0; const float MOUSE_SENSITIVITY = 0.1f; - if (powf(measured_yaw_rate*measured_yaw_rate + - measured_pitch_rate*measured_pitch_rate, 0.5) > MIN_MOUSE_RATE) + if (powf(gyroYawRate*gyroYawRate + + gyroPitchRate*gyroPitchRate, 0.5) > MIN_MOUSE_RATE) { - headMouseX += measured_yaw_rate*MOUSE_SENSITIVITY; - headMouseY += measured_pitch_rate*MOUSE_SENSITIVITY*(float)HEIGHT/(float)WIDTH; + headMouseX += gyroYawRate*MOUSE_SENSITIVITY; + headMouseY += gyroPitchRate*MOUSE_SENSITIVITY*(float)HEIGHT/(float)WIDTH; } headMouseX = max(headMouseX, 0); headMouseX = min(headMouseX, WIDTH); @@ -409,7 +410,6 @@ void simulateHead(float frametime) // Update render direction (pitch/yaw) based on measured gyro rates const int MIN_YAW_RATE = 100; const int MIN_PITCH_RATE = 100; - const float YAW_SENSITIVITY = 0.02; const float PITCH_SENSITIVITY = 0.05; @@ -418,23 +418,22 @@ void simulateHead(float frametime) if (myAvatar.getDriveKeys(ROT_LEFT)) renderYawRate -= KEY_YAW_SENSITIVITY*frametime; if (myAvatar.getDriveKeys(ROT_RIGHT)) renderYawRate += KEY_YAW_SENSITIVITY*frametime; - if (fabs(measured_yaw_rate) > MIN_YAW_RATE) + if (fabs(gyroYawRate) > MIN_YAW_RATE) { - if (measured_yaw_rate > 0) - renderYawRate += (measured_yaw_rate - MIN_YAW_RATE) * YAW_SENSITIVITY * frametime; + if (gyroYawRate > 0) + renderYawRate += (gyroYawRate - MIN_YAW_RATE) * YAW_SENSITIVITY * frametime; else - renderYawRate += (measured_yaw_rate + MIN_YAW_RATE) * YAW_SENSITIVITY * frametime; + renderYawRate += (gyroYawRate + MIN_YAW_RATE) * YAW_SENSITIVITY * frametime; } - if (fabs(measured_pitch_rate) > MIN_PITCH_RATE) + if (fabs(gyroPitchRate) > MIN_PITCH_RATE) { - if (measured_pitch_rate > 0) - renderPitchRate += (measured_pitch_rate - MIN_PITCH_RATE) * PITCH_SENSITIVITY * frametime; + if (gyroPitchRate > 0) + renderPitchRate += (gyroPitchRate - MIN_PITCH_RATE) * PITCH_SENSITIVITY * frametime; else - renderPitchRate += (measured_pitch_rate + MIN_PITCH_RATE) * PITCH_SENSITIVITY * frametime; + renderPitchRate += (gyroPitchRate + MIN_PITCH_RATE) * PITCH_SENSITIVITY * frametime; } - renderPitch += renderPitchRate; - + float renderPitch = myAvatar.getRenderPitch(); // Decay renderPitch toward zero because we never look constantly up/down renderPitch *= (1.f - 2.0*frametime); @@ -442,9 +441,9 @@ void simulateHead(float frametime) renderPitchRate *= (1.f - 5.0*frametime); renderYawRate *= (1.f - 7.0*frametime); - // Update own head data + // Update own avatar data myAvatar.setRenderYaw(myAvatar.getRenderYaw() + renderYawRate); - myAvatar.setRenderPitch(renderPitch); + myAvatar.setRenderPitch(renderPitch + renderPitchRate); // Get audio loudness data from audio input device float loudness, averageLoudness; @@ -528,39 +527,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); @@ -593,64 +610,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(); @@ -660,8 +677,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); @@ -710,13 +725,14 @@ void display(void) //---------------------------------------------------- myCamera.setTargetPosition ( myAvatar.getBodyPosition() ); 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 @@ -727,21 +743,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) @@ -752,6 +767,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); @@ -895,9 +912,11 @@ void display(void) // If application has just started, report time from startup to now (first frame display) if (justStarted) { - printf("Startup Time: %4.2f\n", - (usecTimestampNow() - usecTimestamp(&applicationStartupTime))/1000000.0); + float startupTime = (usecTimestampNow() - usecTimestamp(&applicationStartupTime))/1000000.0; justStarted = false; + char title[30]; + snprintf(title, 30, "Interface: %4.2f seconds", startupTime); + glutSetWindowTitle(title); } } @@ -968,7 +987,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) { @@ -1028,12 +1054,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); @@ -1189,7 +1216,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; @@ -1201,8 +1228,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 == '&') { @@ -1326,8 +1355,10 @@ void idle(void) { myAvatar.setTriggeringAction( false ); } - // Simulation - simulateHead( 1.f/FPS ); + // + // Sample hardware, update view frustum if needed, send avatar data to mixer/agents + // + updateAvatar( 1.f/FPS ); //test @@ -1342,8 +1373,8 @@ void idle(void) { } */ - simulateHand(1.f/FPS); - + updateAvatarHand(1.f/FPS); + field.simulate(1.f/FPS); myAvatar.simulate(1.f/FPS); balls.simulate(1.f/FPS); @@ -1361,27 +1392,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 ) @@ -1464,6 +1534,9 @@ int main(int argc, const char * argv[]) AgentList::getInstance()->startPingUnknownAgentsThread(); glutInit(&argc, (char**)argv); + WIDTH = glutGet(GLUT_SCREEN_WIDTH); + HEIGHT = glutGet(GLUT_SCREEN_HEIGHT); + glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); glutInitWindowSize(WIDTH, HEIGHT); glutCreateWindow("Interface"); @@ -1471,6 +1544,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/interface/src/starfield/Config.h b/interface/src/starfield/Config.h index 7e9b816838..001af23a5f 100644 --- a/interface/src/starfield/Config.h +++ b/interface/src/starfield/Config.h @@ -67,7 +67,7 @@ #include #include "UrlReader.h" -#include "AngleUtils.h" +#include "AngleUtil.h" #include "Radix2InplaceSort.h" #include "Radix2IntegerScanner.h" #include "FloodFill.h" diff --git a/interface/src/starfield/Controller.h b/interface/src/starfield/Controller.h index edf9fd7ec7..329119bbc4 100644 --- a/interface/src/starfield/Controller.h +++ b/interface/src/starfield/Controller.h @@ -72,16 +72,17 @@ namespace starfield { size_t _valLodNalloc; size_t _valLodNrender; BrightnessLevels _seqLodBrightness; - BrightnessLevel _valLodAllocBrightness; #if STARFIELD_MULTITHREADING atomic _valLodBrightness; + BrightnessLevel _valLodAllocBrightness; atomic _ptrRenderer; typedef lock_guard lock; #else BrightnessLevel _valLodBrightness; + BrightnessLevel _valLodAllocBrightness; Renderer* _ptrRenderer; @@ -89,6 +90,10 @@ namespace starfield { #define _(x) #endif + static inline size_t toBufSize(double f) { + return size_t(floor(f + 0.5f)); + } + public: Controller() : @@ -99,8 +104,8 @@ namespace starfield { _valLodOveralloc(1.2), _valLodNalloc(0), _valLodNrender(0), - _valLodAllocBrightness(0), _valLodBrightness(0), + _valLodAllocBrightness(0), _ptrRenderer(0l) { } @@ -144,8 +149,8 @@ namespace starfield { rcpChange = 1.0; - nRender = lrint(_valLodFraction * newLast); - n = min(newLast, size_t(lrint(_valLodOveralloc * nRender))); + nRender = toBufSize(_valLodFraction * newLast); + n = min(newLast, toBufSize(_valLodOveralloc * nRender)); } else { @@ -282,7 +287,7 @@ namespace starfield { // calculate allocation size and corresponding brightness // threshold double oaFract = std::min(fraction * (1.0 + overalloc), 1.0); - n = lrint(oaFract * last); + n = toBufSize(oaFract * last); bMin = _seqLodBrightness[n]; n = std::upper_bound( _seqLodBrightness.begin() + n - 1, @@ -290,7 +295,7 @@ namespace starfield { bMin, GreaterBrightness() ) - _seqLodBrightness.begin(); // also determine number of vertices to render and brightness - nRender = lrint(fraction * last); + nRender = toBufSize(fraction * last); // Note: nRender does not have to be accurate b = _seqLodBrightness[nRender]; // this setting controls the renderer, also keep b as the @@ -304,7 +309,7 @@ namespace starfield { // fprintf(stderr, "Stars.cpp: " // "fraction = %lf, oaFract = %lf, n = %d, n' = %d, bMin = %d, b = %d\n", -// fraction, oaFract, lrint(oaFract * last)), n, bMin, b); +// fraction, oaFract, toBufSize(oaFract * last)), n, bMin, b); // will not have to reallocate? set new fraction right away // (it is consistent with the rest of the state in this case) diff --git a/interface/src/starfield/Loader.h b/interface/src/starfield/Loader.h index bff41409a2..03dfd18a53 100644 --- a/interface/src/starfield/Loader.h +++ b/interface/src/starfield/Loader.h @@ -50,8 +50,8 @@ namespace starfield { return false; } - fprintf(stderr, "Stars.cpp: read %d stars, rendering %ld\n", - _valRecordsRead, _ptrVertices->size()); + fprintf(stderr, "Stars.cpp: read %u vertices, using %lu\n", + _valRecordsRead, _ptrVertices->size()); return true; } diff --git a/interface/src/starfield/data/InputVertex.h b/interface/src/starfield/data/InputVertex.h index 9f30755325..670056bd74 100644 --- a/interface/src/starfield/data/InputVertex.h +++ b/interface/src/starfield/data/InputVertex.h @@ -26,8 +26,8 @@ namespace starfield { InputVertex(float azimuth, float altitude, unsigned color) { - _valColor = (color >> 16 & 0xffu) | (color & 0xff00u) | - (color << 16 & 0xff0000u) | 0xff000000u; + _valColor = ((color >> 16) & 0xffu) | (color & 0xff00u) | + ((color << 16) & 0xff0000u) | 0xff000000u; azimuth = angleConvert(azimuth); altitude = angleConvert(altitude); diff --git a/interface/src/starfield/renderer/Tiling.h b/interface/src/starfield/renderer/Tiling.h index 802640b139..1df4dd1956 100644 --- a/interface/src/starfield/renderer/Tiling.h +++ b/interface/src/starfield/renderer/Tiling.h @@ -13,15 +13,8 @@ #error "This is an implementation file - not intended for direct inclusion." #endif -#ifdef _WIN32 -#include "../Config.h" -#define lrint(x) (floor(x + (x > 0) ? 0.5 : -0.5)) - inline float remainder(float x, float y) { return std::fmod(x, y); } - inline int round(float x) { return (floor(x + 0.5)); } - double log2( double n ) { return log( n ) / log( 2 ); } -#else #include "starfield/Config.h" -#endif + namespace starfield { class Tiling { @@ -35,7 +28,7 @@ namespace starfield { Tiling(unsigned k) : _valK(k), _valRcpSlice(k / Radians::twicePi()) { - _valBits = ceil(log2(getTileCount())); + _valBits = ceil(log(getTileCount()) * 1.4426950408889634); // log2 } unsigned getAzimuthalTiles() const { return _valK; } @@ -58,7 +51,7 @@ namespace starfield { private: unsigned discreteAngle(float unsigned_angle) const { - return unsigned(round(unsigned_angle * _valRcpSlice)); + return unsigned(floor(unsigned_angle * _valRcpSlice + 0.5f)); } unsigned discreteAzimuth(float a) const { diff --git a/libraries/shared/src/AngleUtils.h b/libraries/shared/src/AngleUtil.h similarity index 68% rename from libraries/shared/src/AngleUtils.h rename to libraries/shared/src/AngleUtil.h index dfe4f09124..8308eadf43 100644 --- a/libraries/shared/src/AngleUtils.h +++ b/libraries/shared/src/AngleUtil.h @@ -32,9 +32,9 @@ struct Rotations { static float halfPi() { return 0.25f; } }; -/** - * Converts an angle from one unit to another. - */ +// +// Converts an angle from one unit to another. +// template< class UnitFrom, class UnitTo > float angleConvert(float a) { @@ -42,21 +42,28 @@ float angleConvert(float a) { } -/** - * Clamps an angle to the range of [-180; 180) degrees. - */ +// +// Clamps an angle to the range of [-180; 180) degrees. +// template< class Unit > float angleSignedNormal(float a) { - float result = remainder(a, Unit::twicePi()); - if (result == Unit::pi()) - result = -Unit::pi(); + // result is remainder(a, Unit::twicePi()); + float result = fmod(a, Unit::twicePi()); + if (result >= Unit::pi()) { + + result -= Unit::twicePi(); + + } else if (result < -Unit::pi()) { + + result += Unit::twicePi(); + } return result; } -/** - * Clamps an angle to the range of [0; 360) degrees. - */ +// +// Clamps an angle to the range of [0; 360) degrees. +// template< class Unit > float angleUnsignedNormal(float a) { @@ -64,13 +71,13 @@ float angleUnsignedNormal(float a) { } -/** - * Clamps a polar direction so that azimuth is in the range of [0; 360) - * degrees and altitude is in the range of [-90; 90] degrees. - * - * The so normalized angle still contains ambiguity due to gimbal lock: - * Both poles can be reached from any azimuthal direction. - */ +// +// Clamps a polar direction so that azimuth is in the range of [0; 360) +// degrees and altitude is in the range of [-90; 90] degrees. +// +// The so normalized angle still contains ambiguity due to gimbal lock: +// Both poles can be reached from any azimuthal direction. +// template< class Unit > void angleHorizontalPolar(float& azimuth, float& altitude) { 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(); };