Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Stephen Birarda 2013-04-16 12:00:55 -07:00
commit 1dd21a450e
15 changed files with 513 additions and 355 deletions

View file

@ -14,18 +14,20 @@
//------------------------ //------------------------
Camera::Camera() Camera::Camera()
{ {
mode = CAMERA_MODE_THIRD_PERSON; _mode = CAMERA_MODE_THIRD_PERSON;
tightness = DEFAULT_CAMERA_TIGHTNESS; _tightness = DEFAULT_CAMERA_TIGHTNESS;
fieldOfView = 60.0; // default _fieldOfView = 60.0; // default
yaw = 0.0; _nearClip = 0.1; // default
pitch = 0.0; _farClip = 50.0; // default
roll = 0.0; _yaw = 0.0;
up = 0.0; _pitch = 0.0;
distance = 0.0; _roll = 0.0;
targetPosition = glm::vec3( 0.0, 0.0, 0.0 ); _up = 0.0;
position = glm::vec3( 0.0, 0.0, 0.0 ); _distance = 0.0;
idealPosition = glm::vec3( 0.0, 0.0, 0.0 ); _targetPosition = glm::vec3( 0.0, 0.0, 0.0 );
orientation.setToIdentity(); _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 ) 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. //these need to be checked to make sure they correspond to the cordinate system.
double x = distance * -sin( radian ); float x = _distance * -sin( radian );
double z = distance * cos( radian ); float z = _distance * cos( radian );
double y = up; float y = _up;
idealPosition = targetPosition + glm::vec3( x, y, z ); _idealPosition = _targetPosition + glm::vec3( x, y, z );
float t = _tightness * deltaTime;
float t = tightness * deltaTime;
if ( t > 1.0 ){ if ( t > 1.0 ){
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 //geterate the ortho-normals for the orientation based on the Euler angles
//------------------------------------------------------------------------- //------------------------------------------------------------------------
orientation.setToIdentity(); _orientation.setToIdentity();
orientation.yaw ( yaw ); _orientation.yaw ( _yaw );
orientation.pitch ( pitch ); _orientation.pitch ( _pitch );
orientation.roll ( roll ); _orientation.roll ( _roll );
} }

View file

@ -13,11 +13,11 @@
enum CameraMode enum CameraMode
{ {
CAMERA_MODE_NULL = -1, CAMERA_MODE_NULL = -1,
CAMERA_MODE_FIRST_PERSON, CAMERA_MODE_FIRST_PERSON,
CAMERA_MODE_THIRD_PERSON, CAMERA_MODE_THIRD_PERSON,
CAMERA_MODE_MY_OWN_FACE, CAMERA_MODE_MY_OWN_FACE,
NUM_CAMERA_MODES NUM_CAMERA_MODES
}; };
static const float DEFAULT_CAMERA_TIGHTNESS = 10.0f; static const float DEFAULT_CAMERA_TIGHTNESS = 10.0f;
@ -25,42 +25,55 @@ static const float DEFAULT_CAMERA_TIGHTNESS = 10.0f;
class Camera class Camera
{ {
public: public:
Camera(); 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); }
float getYaw () { return yaw; } void update( float deltaTime );
float getPitch () { return pitch; }
float getRoll () { return roll; } void setMode ( CameraMode m ) { _mode = m; }
glm::vec3 getPosition () { return position; } void setYaw ( float y ) { _yaw = y; }
Orientation getOrientation () { return orientation; } void setPitch ( float p ) { _pitch = p; }
CameraMode getMode () { return mode; } 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: private:
CameraMode mode; CameraMode _mode;
glm::vec3 position; glm::vec3 _position;
glm::vec3 idealPosition; glm::vec3 _idealPosition;
glm::vec3 targetPosition; glm::vec3 _targetPosition;
float fieldOfView; float _yaw;
float yaw; float _pitch;
float pitch; float _roll;
float roll; float _up;
float up; float _distance;
float distance; float _tightness;
float tightness; Orientation _orientation;
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 #endif

View file

@ -214,6 +214,7 @@ void Head::UpdatePos(float frametime, SerialInterface * serialInterface, int hea
if ((Pitch < MAX_PITCH) && (Pitch > MIN_PITCH)) if ((Pitch < MAX_PITCH) && (Pitch > MIN_PITCH))
addPitch(measured_pitch_rate * -HEAD_ROTATION_SCALE * frametime); addPitch(measured_pitch_rate * -HEAD_ROTATION_SCALE * frametime);
addRoll(-measured_roll_rate * HEAD_ROLL_SCALE * frametime); addRoll(-measured_roll_rate * HEAD_ROLL_SCALE * frametime);
if (head_mirror) { if (head_mirror) {

View file

@ -60,8 +60,10 @@ public:
*/ */
void activate() const { void activate() const {
if (_hndProg != 0u) if (_hndProg != 0u) {
oGlLog( glUseProgram(_hndProg) ); oGlLog( glUseProgram(_hndProg) );
}
} }
/** /**
@ -77,16 +79,20 @@ public:
*/ */
bool addShader(GLenum type, GLsizei nStrings, GLchar const** strings) { 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); GLuint s = glCreateShader(type);
glShaderSource(s, nStrings, strings, 0l); glShaderSource(s, nStrings, strings, 0l);
glCompileShader(s); glCompileShader(s);
GLint status; GLint status;
glGetShaderiv(s, GL_COMPILE_STATUS, & status); glGetShaderiv(s, GL_COMPILE_STATUS, & status);
if (!! status) if (status != 0)
glAttachShader(_hndProg, s); glAttachShader(_hndProg, s);
#ifdef NDEBUG #ifdef NDEBUG // always fetch log in debug mode
else else
#endif #endif
fetchLog(s, glGetShaderiv, glGetShaderInfoLog); fetchLog(s, glGetShaderiv, glGetShaderInfoLog);
@ -104,12 +110,21 @@ public:
glLinkProgram(_hndProg); glLinkProgram(_hndProg);
GLint status; GLint status;
glGetProgramiv(_hndProg, GL_LINK_STATUS, & status); glGetProgramiv(_hndProg, GL_LINK_STATUS, & status);
#ifdef NDEBUG #ifndef NDEBUG // always fetch log in debug mode
if (status == 0) fetchLog(_hndProg, glGetProgramiv, glGetProgramInfoLog);
#endif #endif
if (status == 0) {
#ifdef NDEBUG // only on error in release mode
fetchLog(_hndProg, glGetProgramiv, glGetProgramInfoLog); fetchLog(_hndProg, glGetProgramiv, glGetProgramInfoLog);
#endif
glDeleteProgram(_hndProg);
_hndProg = 0u;
return false;
return status != 0; } else {
return true;
}
} }
private: private:

View file

@ -6,12 +6,12 @@
// //
// Channels are received in the following order (integer 0-4096 based on voltage 0-3.3v) // Channels are received in the following order (integer 0-4096 based on voltage 0-3.3v)
// //
// AIN 15: Pitch Gyro (nodding your head 'yes') // 0 - AIN 15: Pitch Gyro (nodding your head 'yes')
// AIN 16: Yaw Gyro (shaking your head 'no') // 1 - AIN 16: Yaw Gyro (shaking your head 'no')
// AIN 17: Roll Gyro (looking quizzical, tilting your head) // 2 - AIN 17: Roll Gyro (looking quizzical, tilting your head)
// AIN 18: Lateral acceleration (moving from side-to-side in front of your monitor) // 3 - 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) // 4 - AIN 19: Up/Down acceleration (sitting up/ducking in front of your monitor)
// AIN 20: Forward/Back acceleration (Toward or away from your monitor) // 5 - AIN 20: Forward/Back acceleration (Toward or away from your monitor)
// //
#include "SerialInterface.h" #include "SerialInterface.h"
@ -21,14 +21,15 @@
#include <sys/time.h> #include <sys/time.h>
#endif #endif
int serial_fd; int serialFd;
const int MAX_BUFFER = 255; const int MAX_BUFFER = 255;
char serial_buffer[MAX_BUFFER]; char serialBuffer[MAX_BUFFER];
int serial_buffer_pos = 0; int serialBufferPos = 0;
const int ZERO_OFFSET = 2048; const int ZERO_OFFSET = 2048;
const short NO_READ_MAXIMUM_MSECS = 3000; 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() { void SerialInterface::pair() {
@ -48,7 +49,7 @@ void SerialInterface::pair() {
char *serialPortname = new char[100]; char *serialPortname = new char[100];
sprintf(serialPortname, "/dev/%s", entry->d_name); sprintf(serialPortname, "/dev/%s", entry->d_name);
init(serialPortname, 115200); initializePort(serialPortname, 115200);
delete [] serialPortname; delete [] serialPortname;
} }
@ -60,18 +61,20 @@ void SerialInterface::pair() {
} }
// Init the serial port to the specified values // Connect to the serial port
int SerialInterface::init(char* portname, int baud) int SerialInterface::initializePort(char* portname, int baud)
{ {
#ifdef __APPLE__ #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); printf("Opening SerialUSB %s: ", portname);
if (serial_fd == -1) return -1; // Failed to open port
if (serialFd == -1) {
printf("Failed.\n");
return -1; // Failed to open port
}
struct termios options; struct termios options;
tcgetattr(serial_fd,&options); tcgetattr(serialFd,&options);
switch(baud) switch(baud)
{ {
case 9600: cfsetispeed(&options,B9600); case 9600: cfsetispeed(&options,B9600);
@ -95,10 +98,10 @@ int SerialInterface::init(char* portname, int baud)
options.c_cflag &= ~CSTOPB; options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE; options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8; options.c_cflag |= CS8;
tcsetattr(serial_fd,TCSANOW,&options); tcsetattr(serialFd,TCSANOW,&options);
printf("Serial interface opened!\n"); printf("Connected.\n");
resetSerial(); resetSerial();
active = true; active = true;
#endif #endif
@ -126,22 +129,17 @@ void SerialInterface::renderLevels(int width, int height) {
glBegin(GL_LINES); glBegin(GL_LINES);
glVertex2f(disp_x, height*0.95); glVertex2f(disp_x, height*0.95);
glVertex2f(disp_x, height*(0.25 + 0.75f*getValue(i)/4096)); 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(); glEnd();
// Trailing Average value // Trailing Average value
glColor4f(1, 1, 0, 1);
glBegin(GL_LINES); glBegin(GL_LINES);
glVertex2f(disp_x + 2, height*0.95); glColor4f(1, 1, 1, 1);
glVertex2f(disp_x + 2, height*(0.25 + 0.75f*getTrailingValue(i)/4096)); glVertex2f(disp_x, height*(0.25 + 0.75f*getTrailingValue(i)/4096));
glVertex2f(disp_x + 4, height*(0.25 + 0.75f*getTrailingValue(i)/4096));
glEnd(); 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)); sprintf(val, "%d", getValue(i));
drawtext(disp_x-GAP/2, (height*0.95)+2, 0.08, 90, 1.0, 0, val, 0, 1, 0); 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() { void SerialInterface::readData() {
#ifdef __APPLE__ #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 // 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]; char bufchar[1];
int initialSamples = totalSamples; int initialSamples = totalSamples;
while (read(serial_fd, &bufchar, 1) > 0) { while (read(serialFd, &bufchar, 1) > 0) {
//std::cout << bufchar[0]; //std::cout << bufchar[0];
serial_buffer[serial_buffer_pos] = bufchar[0]; serialBuffer[serialBufferPos] = bufchar[0];
serial_buffer_pos++; serialBufferPos++;
// Have we reached end of a line of input? // Have we reached end of a line of input?
if ((bufchar[0] == '\n') || (serial_buffer_pos >= MAX_BUFFER)) { if ((bufchar[0] == '\n') || (serialBufferPos >= MAX_BUFFER)) {
std::string serialLine(serial_buffer, serial_buffer_pos-1); std::string serialLine(serialBuffer, serialBufferPos-1);
//std::cout << serialLine << "\n"; //std::cout << serialLine << "\n";
int spot; int spot;
//int channel = 0; //int channel = 0;
@ -191,6 +189,7 @@ void SerialInterface::readData() {
serialLine = serialLine.substr(spot+1, serialLine.length() - spot - 1); serialLine = serialLine.substr(spot+1, serialLine.length() - spot - 1);
} }
// Update Trailing Averages
for (int i = 0; i < NUM_CHANNELS; i++) { for (int i = 0; i < NUM_CHANNELS; i++) {
if (totalSamples > SAMPLES_TO_DISCARD) { if (totalSamples > SAMPLES_TO_DISCARD) {
trailingAverage[i] = (1.f - AVG_RATE[i])*trailingAverage[i] + 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++; totalSamples++;
serial_buffer_pos = 0; serialBufferPos = 0;
} }
} }
@ -210,7 +222,7 @@ void SerialInterface::readData() {
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
if (diffclock(&lastGoodRead, &now) > NO_READ_MAXIMUM_MSECS) { 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(); resetSerial();
} }
} else { } else {
@ -223,6 +235,7 @@ void SerialInterface::resetSerial() {
#ifdef __APPLE__ #ifdef __APPLE__
active = false; active = false;
totalSamples = 0; totalSamples = 0;
gravity = glm::vec3(0,-1,0);
gettimeofday(&lastGoodRead, NULL); gettimeofday(&lastGoodRead, NULL);
@ -233,7 +246,7 @@ void SerialInterface::resetSerial() {
} }
// Clear serial input buffer // Clear serial input buffer
for (int i = 1; i < MAX_BUFFER; i++) { for (int i = 1; i < MAX_BUFFER; i++) {
serial_buffer[i] = ' '; serialBuffer[i] = ' ';
} }
#endif #endif
} }

View file

@ -45,8 +45,10 @@ public:
void resetTrailingAverages(); void resetTrailingAverages();
void renderLevels(int width, int height); void renderLevels(int width, int height);
bool active; bool active;
glm::vec3 getGravity() {return gravity;};
private: private:
int init(char * portname, int baud); int initializePort(char * portname, int baud);
void resetSerial(); void resetSerial();
int lastMeasured[NUM_CHANNELS]; int lastMeasured[NUM_CHANNELS];
float trailingAverage[NUM_CHANNELS]; float trailingAverage[NUM_CHANNELS];
@ -54,6 +56,7 @@ private:
int LED; int LED;
int totalSamples; int totalSamples;
timeval lastGoodRead; timeval lastGoodRead;
glm::vec3 gravity;
}; };
#endif #endif

View file

@ -79,6 +79,9 @@
using namespace std; using namespace std;
void reshape(int width, int height); // will be defined below
pthread_t networkReceiveThread; pthread_t networkReceiveThread;
bool stopNetworkReceiveThread = false; bool stopNetworkReceiveThread = false;
@ -97,10 +100,13 @@ bool wantColorRandomizer = true; // for addSphere and load file
Oscilloscope audioScope(256,200,true); Oscilloscope audioScope(256,200,true);
Head myAvatar; // The rendered avatar of oneself ViewFrustum viewFrustum; // current state of view frustum, perspective, orientation, etc.
Camera myCamera; // My view onto the world (sometimes on myself :)
// 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"; char starFile[] = "https://s3-us-west-1.amazonaws.com/highfidelity/stars.txt";
FieldOfView fov; FieldOfView fov;
Stars stars; Stars stars;
@ -136,10 +142,7 @@ Audio audio(&audioScope, &myAvatar);
#define IDLE_SIMULATE_MSECS 8 // How often should call simulate and other stuff #define IDLE_SIMULATE_MSECS 8 // How often should call simulate and other stuff
// in the idle loop? // in the idle loop?
float yaw = 0.f; // The yaw, pitch for the avatar head
float pitch = 0.f;
float startYaw = 122.f; float startYaw = 122.f;
float renderPitch = 0.f;
float renderYawRate = 0.f; float renderYawRate = 0.f;
float renderPitchRate = 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 mouse is being dragged, send current force to the hand controller
if (mousePressed == 1) 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 gyroPitchRate = serialPort.getRelativeValue(PITCH_RATE);
// float measured_yaw_rate = serialPort.getRelativeValue(YAW_RATE); float gyroYawRate = 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);
myAvatar.UpdatePos(frametime, &serialPort, headMirror, &gravity); 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 MIN_MOUSE_RATE = 30.0;
const float MOUSE_SENSITIVITY = 0.1f; const float MOUSE_SENSITIVITY = 0.1f;
if (powf(measured_yaw_rate*measured_yaw_rate + if (powf(gyroYawRate*gyroYawRate +
measured_pitch_rate*measured_pitch_rate, 0.5) > MIN_MOUSE_RATE) gyroPitchRate*gyroPitchRate, 0.5) > MIN_MOUSE_RATE)
{ {
headMouseX += measured_yaw_rate*MOUSE_SENSITIVITY; headMouseX += gyroYawRate*MOUSE_SENSITIVITY;
headMouseY += measured_pitch_rate*MOUSE_SENSITIVITY*(float)HEIGHT/(float)WIDTH; headMouseY += gyroPitchRate*MOUSE_SENSITIVITY*(float)HEIGHT/(float)WIDTH;
} }
headMouseX = max(headMouseX, 0); headMouseX = max(headMouseX, 0);
headMouseX = min(headMouseX, WIDTH); headMouseX = min(headMouseX, WIDTH);
@ -409,7 +410,6 @@ void simulateHead(float frametime)
// Update render direction (pitch/yaw) based on measured gyro rates // Update render direction (pitch/yaw) based on measured gyro rates
const int MIN_YAW_RATE = 100; const int MIN_YAW_RATE = 100;
const int MIN_PITCH_RATE = 100; const int MIN_PITCH_RATE = 100;
const float YAW_SENSITIVITY = 0.02; const float YAW_SENSITIVITY = 0.02;
const float PITCH_SENSITIVITY = 0.05; 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_LEFT)) renderYawRate -= KEY_YAW_SENSITIVITY*frametime;
if (myAvatar.getDriveKeys(ROT_RIGHT)) 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) if (gyroYawRate > 0)
renderYawRate += (measured_yaw_rate - MIN_YAW_RATE) * YAW_SENSITIVITY * frametime; renderYawRate += (gyroYawRate - MIN_YAW_RATE) * YAW_SENSITIVITY * frametime;
else 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) if (gyroPitchRate > 0)
renderPitchRate += (measured_pitch_rate - MIN_PITCH_RATE) * PITCH_SENSITIVITY * frametime; renderPitchRate += (gyroPitchRate - MIN_PITCH_RATE) * PITCH_SENSITIVITY * frametime;
else 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 // Decay renderPitch toward zero because we never look constantly up/down
renderPitch *= (1.f - 2.0*frametime); renderPitch *= (1.f - 2.0*frametime);
@ -442,9 +441,9 @@ void simulateHead(float frametime)
renderPitchRate *= (1.f - 5.0*frametime); renderPitchRate *= (1.f - 5.0*frametime);
renderYawRate *= (1.f - 7.0*frametime); renderYawRate *= (1.f - 7.0*frametime);
// Update own head data // Update own avatar data
myAvatar.setRenderYaw(myAvatar.getRenderYaw() + renderYawRate); myAvatar.setRenderYaw(myAvatar.getRenderYaw() + renderYawRate);
myAvatar.setRenderPitch(renderPitch); myAvatar.setRenderPitch(renderPitch + renderPitchRate);
// Get audio loudness data from audio input device // Get audio loudness data from audio input device
float loudness, averageLoudness; float loudness, averageLoudness;
@ -528,39 +527,57 @@ float viewFrustumOffsetUp = 0.0;
void render_view_frustum() { 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 // We will use these below, from either the camera or head vectors calculated above
glm::vec3 position; glm::vec3 position;
glm::vec3 direction; glm::vec3 direction;
glm::vec3 up; glm::vec3 up;
glm::vec3 right; glm::vec3 right;
float fov, nearClip, farClip;
// Camera or Head? // Camera or Head?
if (::cameraFrustum) { if (::cameraFrustum) {
position = cameraPosition; position = ::myCamera.getPosition();
direction = cameraDirection; direction = ::myCamera.getOrientation().getFront() * glm::vec3(1,1,-1);
up = cameraUp; up = ::myCamera.getOrientation().getUp() * glm::vec3(1,1,1);
right = cameraRight; right = ::myCamera.getOrientation().getRight() * glm::vec3(1,1,-1);
fov = ::myCamera.getFieldOfView();
nearClip = ::myCamera.getNearClip();
farClip = ::myCamera.getFarClip();
} else { } else {
position = headPosition; position = ::myAvatar.getHeadPosition();
direction = headDirection; direction = ::myAvatar.getHeadLookatDirection();
up = headUp; up = ::myAvatar.getHeadLookatDirectionUp();
right = headRight; 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 // 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 // Get ready to draw some lines
glDisable(GL_LIGHTING); glDisable(GL_LIGHTING);
@ -593,64 +610,64 @@ void render_view_frustum() {
if (::frustumDrawingMode == FRUSTUM_DRAW_MODE_ALL || ::frustumDrawingMode == FRUSTUM_DRAW_MODE_PLANES if (::frustumDrawingMode == FRUSTUM_DRAW_MODE_ALL || ::frustumDrawingMode == FRUSTUM_DRAW_MODE_PLANES
|| ::frustumDrawingMode == FRUSTUM_DRAW_MODE_NEAR_PLANE) { || ::frustumDrawingMode == FRUSTUM_DRAW_MODE_NEAR_PLANE) {
// Drawing the bounds of the frustum // Drawing the bounds of the frustum
// vf.getNear plane - bottom edge // viewFrustum.getNear plane - bottom edge
glColor3f(1,0,0); glColor3f(1,0,0);
glVertex3f(vf.getNearBottomLeft().x, vf.getNearBottomLeft().y, vf.getNearBottomLeft().z); glVertex3f(viewFrustum.getNearBottomLeft().x, viewFrustum.getNearBottomLeft().y, viewFrustum.getNearBottomLeft().z);
glVertex3f(vf.getNearBottomRight().x, vf.getNearBottomRight().y, vf.getNearBottomRight().z); glVertex3f(viewFrustum.getNearBottomRight().x, viewFrustum.getNearBottomRight().y, viewFrustum.getNearBottomRight().z);
// vf.getNear plane - top edge // viewFrustum.getNear plane - top edge
glVertex3f(vf.getNearTopLeft().x, vf.getNearTopLeft().y, vf.getNearTopLeft().z); glVertex3f(viewFrustum.getNearTopLeft().x, viewFrustum.getNearTopLeft().y, viewFrustum.getNearTopLeft().z);
glVertex3f(vf.getNearTopRight().x, vf.getNearTopRight().y, vf.getNearTopRight().z); glVertex3f(viewFrustum.getNearTopRight().x, viewFrustum.getNearTopRight().y, viewFrustum.getNearTopRight().z);
// vf.getNear plane - right edge // viewFrustum.getNear plane - right edge
glVertex3f(vf.getNearBottomRight().x, vf.getNearBottomRight().y, vf.getNearBottomRight().z); glVertex3f(viewFrustum.getNearBottomRight().x, viewFrustum.getNearBottomRight().y, viewFrustum.getNearBottomRight().z);
glVertex3f(vf.getNearTopRight().x, vf.getNearTopRight().y, vf.getNearTopRight().z); glVertex3f(viewFrustum.getNearTopRight().x, viewFrustum.getNearTopRight().y, viewFrustum.getNearTopRight().z);
// vf.getNear plane - left edge // viewFrustum.getNear plane - left edge
glVertex3f(vf.getNearBottomLeft().x, vf.getNearBottomLeft().y, vf.getNearBottomLeft().z); glVertex3f(viewFrustum.getNearBottomLeft().x, viewFrustum.getNearBottomLeft().y, viewFrustum.getNearBottomLeft().z);
glVertex3f(vf.getNearTopLeft().x, vf.getNearTopLeft().y, vf.getNearTopLeft().z); glVertex3f(viewFrustum.getNearTopLeft().x, viewFrustum.getNearTopLeft().y, viewFrustum.getNearTopLeft().z);
} }
if (::frustumDrawingMode == FRUSTUM_DRAW_MODE_ALL || ::frustumDrawingMode == FRUSTUM_DRAW_MODE_PLANES if (::frustumDrawingMode == FRUSTUM_DRAW_MODE_ALL || ::frustumDrawingMode == FRUSTUM_DRAW_MODE_PLANES
|| ::frustumDrawingMode == FRUSTUM_DRAW_MODE_FAR_PLANE) { || ::frustumDrawingMode == FRUSTUM_DRAW_MODE_FAR_PLANE) {
// vf.getFar plane - bottom edge // viewFrustum.getFar plane - bottom edge
glColor3f(0,1,0); // GREEN!!! glColor3f(0,1,0); // GREEN!!!
glVertex3f(vf.getFarBottomLeft().x, vf.getFarBottomLeft().y, vf.getFarBottomLeft().z); glVertex3f(viewFrustum.getFarBottomLeft().x, viewFrustum.getFarBottomLeft().y, viewFrustum.getFarBottomLeft().z);
glVertex3f(vf.getFarBottomRight().x, vf.getFarBottomRight().y, vf.getFarBottomRight().z); glVertex3f(viewFrustum.getFarBottomRight().x, viewFrustum.getFarBottomRight().y, viewFrustum.getFarBottomRight().z);
// vf.getFar plane - top edge // viewFrustum.getFar plane - top edge
glVertex3f(vf.getFarTopLeft().x, vf.getFarTopLeft().y, vf.getFarTopLeft().z); glVertex3f(viewFrustum.getFarTopLeft().x, viewFrustum.getFarTopLeft().y, viewFrustum.getFarTopLeft().z);
glVertex3f(vf.getFarTopRight().x, vf.getFarTopRight().y, vf.getFarTopRight().z); glVertex3f(viewFrustum.getFarTopRight().x, viewFrustum.getFarTopRight().y, viewFrustum.getFarTopRight().z);
// vf.getFar plane - right edge // viewFrustum.getFar plane - right edge
glVertex3f(vf.getFarBottomRight().x, vf.getFarBottomRight().y, vf.getFarBottomRight().z); glVertex3f(viewFrustum.getFarBottomRight().x, viewFrustum.getFarBottomRight().y, viewFrustum.getFarBottomRight().z);
glVertex3f(vf.getFarTopRight().x, vf.getFarTopRight().y, vf.getFarTopRight().z); glVertex3f(viewFrustum.getFarTopRight().x, viewFrustum.getFarTopRight().y, viewFrustum.getFarTopRight().z);
// vf.getFar plane - left edge // viewFrustum.getFar plane - left edge
glVertex3f(vf.getFarBottomLeft().x, vf.getFarBottomLeft().y, vf.getFarBottomLeft().z); glVertex3f(viewFrustum.getFarBottomLeft().x, viewFrustum.getFarBottomLeft().y, viewFrustum.getFarBottomLeft().z);
glVertex3f(vf.getFarTopLeft().x, vf.getFarTopLeft().y, vf.getFarTopLeft().z); glVertex3f(viewFrustum.getFarTopLeft().x, viewFrustum.getFarTopLeft().y, viewFrustum.getFarTopLeft().z);
} }
if (::frustumDrawingMode == FRUSTUM_DRAW_MODE_ALL || ::frustumDrawingMode == FRUSTUM_DRAW_MODE_PLANES) { if (::frustumDrawingMode == FRUSTUM_DRAW_MODE_ALL || ::frustumDrawingMode == FRUSTUM_DRAW_MODE_PLANES) {
// RIGHT PLANE IS CYAN // RIGHT PLANE IS CYAN
// right plane - bottom edge - vf.getNear to distant // right plane - bottom edge - viewFrustum.getNear to distant
glColor3f(0,1,1); glColor3f(0,1,1);
glVertex3f(vf.getNearBottomRight().x, vf.getNearBottomRight().y, vf.getNearBottomRight().z); glVertex3f(viewFrustum.getNearBottomRight().x, viewFrustum.getNearBottomRight().y, viewFrustum.getNearBottomRight().z);
glVertex3f(vf.getFarBottomRight().x, vf.getFarBottomRight().y, vf.getFarBottomRight().z); glVertex3f(viewFrustum.getFarBottomRight().x, viewFrustum.getFarBottomRight().y, viewFrustum.getFarBottomRight().z);
// right plane - top edge - vf.getNear to distant // right plane - top edge - viewFrustum.getNear to distant
glVertex3f(vf.getNearTopRight().x, vf.getNearTopRight().y, vf.getNearTopRight().z); glVertex3f(viewFrustum.getNearTopRight().x, viewFrustum.getNearTopRight().y, viewFrustum.getNearTopRight().z);
glVertex3f(vf.getFarTopRight().x, vf.getFarTopRight().y, vf.getFarTopRight().z); glVertex3f(viewFrustum.getFarTopRight().x, viewFrustum.getFarTopRight().y, viewFrustum.getFarTopRight().z);
// LEFT PLANE IS BLUE // LEFT PLANE IS BLUE
// left plane - bottom edge - vf.getNear to distant // left plane - bottom edge - viewFrustum.getNear to distant
glColor3f(0,0,1); glColor3f(0,0,1);
glVertex3f(vf.getNearBottomLeft().x, vf.getNearBottomLeft().y, vf.getNearBottomLeft().z); glVertex3f(viewFrustum.getNearBottomLeft().x, viewFrustum.getNearBottomLeft().y, viewFrustum.getNearBottomLeft().z);
glVertex3f(vf.getFarBottomLeft().x, vf.getFarBottomLeft().y, vf.getFarBottomLeft().z); glVertex3f(viewFrustum.getFarBottomLeft().x, viewFrustum.getFarBottomLeft().y, viewFrustum.getFarBottomLeft().z);
// left plane - top edge - vf.getNear to distant // left plane - top edge - viewFrustum.getNear to distant
glVertex3f(vf.getNearTopLeft().x, vf.getNearTopLeft().y, vf.getNearTopLeft().z); glVertex3f(viewFrustum.getNearTopLeft().x, viewFrustum.getNearTopLeft().y, viewFrustum.getNearTopLeft().z);
glVertex3f(vf.getFarTopLeft().x, vf.getFarTopLeft().y, vf.getFarTopLeft().z); glVertex3f(viewFrustum.getFarTopLeft().x, viewFrustum.getFarTopLeft().y, viewFrustum.getFarTopLeft().z);
} }
glEnd(); glEnd();
@ -660,8 +677,6 @@ void render_view_frustum() {
void display(void) void display(void)
{ {
//printf( "avatar head lookat = %f, %f, %f\n", myAvatar.getAvatarHeadLookatDirection().x, myAvatar.getAvatarHeadLookatDirection().y, myAvatar.getAvatarHeadLookatDirection().z );
PerfStat("display"); PerfStat("display");
glEnable(GL_LINE_SMOOTH); glEnable(GL_LINE_SMOOTH);
@ -710,13 +725,14 @@ void display(void)
//---------------------------------------------------- //----------------------------------------------------
myCamera.setTargetPosition ( myAvatar.getBodyPosition() ); myCamera.setTargetPosition ( myAvatar.getBodyPosition() );
myCamera.setYaw ( 180.0 - myAvatar.getBodyYaw() ); 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.setRoll ( 0.0 );
myCamera.setUp ( 0.45 ); myCamera.setUp ( 0.45 );
myCamera.setDistance ( 0.5 ); myCamera.setDistance ( 0.5 );
myCamera.setTightness ( 10.0f ); myCamera.setTightness ( 10.0f );
myCamera.update ( 1.f/FPS ); myCamera.update ( 1.f/FPS );
} }
// Note: whichCamera is used to pick between the normal camera myCamera for our // 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 // main camera, vs, an alternate camera. The alternate camera we support right now
// is the viewFrustumOffsetCamera. But theoretically, we could use this same mechanism // 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 // myCamera is. But we also want to do meaningful camera transforms on OpenGL for the offset camera
Camera whichCamera = myCamera; Camera whichCamera = myCamera;
Camera viewFrustumOffsetCamera = myCamera; Camera viewFrustumOffsetCamera = myCamera;
if (::viewFrustumFromOffset && ::frustumOn) { if (::viewFrustumFromOffset && ::frustumOn) {
//---------------------------------------------------- //----------------------------------------------------
// set the camera to third-person view but offset so we can see the frustum // set the camera to third-person view but offset so we can see the frustum
//---------------------------------------------------- //----------------------------------------------------
viewFrustumOffsetCamera.setYaw ( 180.0 - myAvatar.getBodyYaw() + ::viewFrustumOffsetYaw ); viewFrustumOffsetCamera.setYaw ( 180.0 - myAvatar.getBodyYaw() + ::viewFrustumOffsetYaw );
viewFrustumOffsetCamera.setPitch ( 0.0 + ::viewFrustumOffsetPitch ); viewFrustumOffsetCamera.setPitch ( 0.0 + ::viewFrustumOffsetPitch );
viewFrustumOffsetCamera.setRoll ( 0.0 + ::viewFrustumOffsetRoll ); viewFrustumOffsetCamera.setRoll ( 0.0 + ::viewFrustumOffsetRoll );
viewFrustumOffsetCamera.setUp ( 0.2 + 0.2 ); viewFrustumOffsetCamera.setUp ( 0.2 + ::viewFrustumOffsetUp );
viewFrustumOffsetCamera.setDistance( 0.5 + 0.2 ); viewFrustumOffsetCamera.setDistance ( 0.5 + ::viewFrustumOffsetDistance );
viewFrustumOffsetCamera.update( 1.f/FPS ); viewFrustumOffsetCamera.update(1.f/FPS);
whichCamera = viewFrustumOffsetCamera; whichCamera = viewFrustumOffsetCamera;
} }
//--------------------------------------------- //---------------------------------------------
// transform view according to whichCamera // transform view according to whichCamera
// could be myCamera (if in normal mode) // could be myCamera (if in normal mode)
@ -752,6 +767,8 @@ void display(void)
glRotatef ( whichCamera.getRoll(), 0, 0, 1 ); glRotatef ( whichCamera.getRoll(), 0, 0, 1 );
glTranslatef( -whichCamera.getPosition().x, -whichCamera.getPosition().y, -whichCamera.getPosition().z ); glTranslatef( -whichCamera.getPosition().x, -whichCamera.getPosition().y, -whichCamera.getPosition().z );
if (::starsOn) { if (::starsOn) {
// should be the first rendering pass - w/o depth buffer / lighting // should be the first rendering pass - w/o depth buffer / lighting
stars.render(fov); 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 application has just started, report time from startup to now (first frame display)
if (justStarted) { if (justStarted) {
printf("Startup Time: %4.2f\n", float startupTime = (usecTimestampNow() - usecTimestamp(&applicationStartupTime))/1000000.0;
(usecTimestampNow() - usecTimestamp(&applicationStartupTime))/1000000.0);
justStarted = false; 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) { 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) { int setFrustumOrigin(int state) {
@ -1028,12 +1054,13 @@ void initMenu() {
menuColumnOptions->addRow("(V)oxels", setVoxels); menuColumnOptions->addRow("(V)oxels", setVoxels);
menuColumnOptions->addRow("Stars (*)", setStars); menuColumnOptions->addRow("Stars (*)", setStars);
menuColumnOptions->addRow("(Q)uit", quitApp); menuColumnOptions->addRow("(Q)uit", quitApp);
// Tools // Tools
menuColumnTools = menu.addColumn("Tools"); menuColumnTools = menu.addColumn("Tools");
menuColumnTools->addRow("Stats (/)", setStats); menuColumnTools->addRow("Stats (/)", setStats);
menuColumnTools->addRow("(M)enu", setMenu); menuColumnTools->addRow("(M)enu", setMenu);
// Debug // Frustum Options
menuColumnFrustum = menu.addColumn("Frustum"); menuColumnFrustum = menu.addColumn("Frustum");
menuColumnFrustum->addRow("Display (F)rustum", setDisplayFrustum); menuColumnFrustum->addRow("Display (F)rustum", setDisplayFrustum);
menuColumnFrustum->addRow("Use (O)ffset Camera", setFrustumOffset); 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 == 'V' || k == 'v') ::showingVoxels = !::showingVoxels; // toggle voxels
if (k == 'F') ::frustumOn = !::frustumOn; // toggle view frustum debugging if (k == 'F') ::frustumOn = !::frustumOn; // toggle view frustum debugging
if (k == 'C') ::cameraFrustum = !::cameraFrustum; // toggle which frustum to look at 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;
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 == '>') ::viewFrustumOffsetDistance += 0.5;
if (k == ',') ::viewFrustumOffsetUp -= 0.05; if (k == ',') ::viewFrustumOffsetUp -= 0.05;
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 == 'R') setFrustumRenderMode(MENU_ROW_PICKED);
if (k == '&') { if (k == '&') {
@ -1326,8 +1355,10 @@ void idle(void) {
myAvatar.setTriggeringAction( false ); 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 //test
@ -1342,8 +1373,8 @@ void idle(void) {
} }
*/ */
simulateHand(1.f/FPS); updateAvatarHand(1.f/FPS);
field.simulate(1.f/FPS); field.simulate(1.f/FPS);
myAvatar.simulate(1.f/FPS); myAvatar.simulate(1.f/FPS);
balls.simulate(1.f/FPS); balls.simulate(1.f/FPS);
@ -1361,27 +1392,66 @@ void idle(void) {
} }
void reshape(int width, int height) void reshape(int width, int height)
{ {
WIDTH = width; WIDTH = width;
HEIGHT = height; 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 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); glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); glLoadIdentity();
glViewport(0, 0, width, height);
} }
void mouseFunc( int button, int state, int x, int y ) void mouseFunc( int button, int state, int x, int y )
{ {
if( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN ) if( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN )
@ -1464,6 +1534,9 @@ int main(int argc, const char * argv[])
AgentList::getInstance()->startPingUnknownAgentsThread(); AgentList::getInstance()->startPingUnknownAgentsThread();
glutInit(&argc, (char**)argv); glutInit(&argc, (char**)argv);
WIDTH = glutGet(GLUT_SCREEN_WIDTH);
HEIGHT = glutGet(GLUT_SCREEN_HEIGHT);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(WIDTH, HEIGHT); glutInitWindowSize(WIDTH, HEIGHT);
glutCreateWindow("Interface"); glutCreateWindow("Interface");
@ -1471,6 +1544,12 @@ int main(int argc, const char * argv[])
#ifdef _WIN32 #ifdef _WIN32
glewInit(); glewInit();
#endif #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" ); printf( "Created Display Window.\n" );

View file

@ -67,7 +67,7 @@
#include <glm/gtc/swizzle.hpp> #include <glm/gtc/swizzle.hpp>
#include "UrlReader.h" #include "UrlReader.h"
#include "AngleUtils.h" #include "AngleUtil.h"
#include "Radix2InplaceSort.h" #include "Radix2InplaceSort.h"
#include "Radix2IntegerScanner.h" #include "Radix2IntegerScanner.h"
#include "FloodFill.h" #include "FloodFill.h"

View file

@ -72,16 +72,17 @@ namespace starfield {
size_t _valLodNalloc; size_t _valLodNalloc;
size_t _valLodNrender; size_t _valLodNrender;
BrightnessLevels _seqLodBrightness; BrightnessLevels _seqLodBrightness;
BrightnessLevel _valLodAllocBrightness;
#if STARFIELD_MULTITHREADING #if STARFIELD_MULTITHREADING
atomic<BrightnessLevel> _valLodBrightness; atomic<BrightnessLevel> _valLodBrightness;
BrightnessLevel _valLodAllocBrightness;
atomic<Renderer*> _ptrRenderer; atomic<Renderer*> _ptrRenderer;
typedef lock_guard<mutex> lock; typedef lock_guard<mutex> lock;
#else #else
BrightnessLevel _valLodBrightness; BrightnessLevel _valLodBrightness;
BrightnessLevel _valLodAllocBrightness;
Renderer* _ptrRenderer; Renderer* _ptrRenderer;
@ -89,6 +90,10 @@ namespace starfield {
#define _(x) #define _(x)
#endif #endif
static inline size_t toBufSize(double f) {
return size_t(floor(f + 0.5f));
}
public: public:
Controller() : Controller() :
@ -99,8 +104,8 @@ namespace starfield {
_valLodOveralloc(1.2), _valLodOveralloc(1.2),
_valLodNalloc(0), _valLodNalloc(0),
_valLodNrender(0), _valLodNrender(0),
_valLodAllocBrightness(0),
_valLodBrightness(0), _valLodBrightness(0),
_valLodAllocBrightness(0),
_ptrRenderer(0l) { _ptrRenderer(0l) {
} }
@ -144,8 +149,8 @@ namespace starfield {
rcpChange = 1.0; rcpChange = 1.0;
nRender = lrint(_valLodFraction * newLast); nRender = toBufSize(_valLodFraction * newLast);
n = min(newLast, size_t(lrint(_valLodOveralloc * nRender))); n = min(newLast, toBufSize(_valLodOveralloc * nRender));
} else { } else {
@ -282,7 +287,7 @@ namespace starfield {
// calculate allocation size and corresponding brightness // calculate allocation size and corresponding brightness
// threshold // threshold
double oaFract = std::min(fraction * (1.0 + overalloc), 1.0); double oaFract = std::min(fraction * (1.0 + overalloc), 1.0);
n = lrint(oaFract * last); n = toBufSize(oaFract * last);
bMin = _seqLodBrightness[n]; bMin = _seqLodBrightness[n];
n = std::upper_bound( n = std::upper_bound(
_seqLodBrightness.begin() + n - 1, _seqLodBrightness.begin() + n - 1,
@ -290,7 +295,7 @@ namespace starfield {
bMin, GreaterBrightness() ) - _seqLodBrightness.begin(); bMin, GreaterBrightness() ) - _seqLodBrightness.begin();
// also determine number of vertices to render and brightness // 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 // Note: nRender does not have to be accurate
b = _seqLodBrightness[nRender]; b = _seqLodBrightness[nRender];
// this setting controls the renderer, also keep b as the // this setting controls the renderer, also keep b as the
@ -304,7 +309,7 @@ namespace starfield {
// fprintf(stderr, "Stars.cpp: " // fprintf(stderr, "Stars.cpp: "
// "fraction = %lf, oaFract = %lf, n = %d, n' = %d, bMin = %d, b = %d\n", // "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 // will not have to reallocate? set new fraction right away
// (it is consistent with the rest of the state in this case) // (it is consistent with the rest of the state in this case)

View file

@ -50,8 +50,8 @@ namespace starfield {
return false; return false;
} }
fprintf(stderr, "Stars.cpp: read %d stars, rendering %ld\n", fprintf(stderr, "Stars.cpp: read %u vertices, using %lu\n",
_valRecordsRead, _ptrVertices->size()); _valRecordsRead, _ptrVertices->size());
return true; return true;
} }

View file

@ -26,8 +26,8 @@ namespace starfield {
InputVertex(float azimuth, float altitude, unsigned color) { InputVertex(float azimuth, float altitude, unsigned color) {
_valColor = (color >> 16 & 0xffu) | (color & 0xff00u) | _valColor = ((color >> 16) & 0xffu) | (color & 0xff00u) |
(color << 16 & 0xff0000u) | 0xff000000u; ((color << 16) & 0xff0000u) | 0xff000000u;
azimuth = angleConvert<Degrees,Radians>(azimuth); azimuth = angleConvert<Degrees,Radians>(azimuth);
altitude = angleConvert<Degrees,Radians>(altitude); altitude = angleConvert<Degrees,Radians>(altitude);

View file

@ -13,15 +13,8 @@
#error "This is an implementation file - not intended for direct inclusion." #error "This is an implementation file - not intended for direct inclusion."
#endif #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" #include "starfield/Config.h"
#endif
namespace starfield { namespace starfield {
class Tiling { class Tiling {
@ -35,7 +28,7 @@ namespace starfield {
Tiling(unsigned k) : Tiling(unsigned k) :
_valK(k), _valK(k),
_valRcpSlice(k / Radians::twicePi()) { _valRcpSlice(k / Radians::twicePi()) {
_valBits = ceil(log2(getTileCount())); _valBits = ceil(log(getTileCount()) * 1.4426950408889634); // log2
} }
unsigned getAzimuthalTiles() const { return _valK; } unsigned getAzimuthalTiles() const { return _valK; }
@ -58,7 +51,7 @@ namespace starfield {
private: private:
unsigned discreteAngle(float unsigned_angle) const { 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 { unsigned discreteAzimuth(float a) const {

View file

@ -32,9 +32,9 @@ struct Rotations {
static float halfPi() { return 0.25f; } 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 > template< class UnitFrom, class UnitTo >
float angleConvert(float a) { 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 > template< class Unit >
float angleSignedNormal(float a) { float angleSignedNormal(float a) {
float result = remainder(a, Unit::twicePi()); // result is remainder(a, Unit::twicePi());
if (result == Unit::pi()) float result = fmod(a, Unit::twicePi());
result = -Unit::pi(); if (result >= Unit::pi()) {
result -= Unit::twicePi();
} else if (result < -Unit::pi()) {
result += Unit::twicePi();
}
return result; 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 > template< class Unit >
float angleUnsignedNormal(float a) { 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) // 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. // degrees and altitude is in the range of [-90; 90] degrees.
* //
* The so normalized angle still contains ambiguity due to gimbal lock: // The so normalized angle still contains ambiguity due to gimbal lock:
* Both poles can be reached from any azimuthal direction. // Both poles can be reached from any azimuthal direction.
*/ //
template< class Unit > template< class Unit >
void angleHorizontalPolar(float& azimuth, float& altitude) { void angleHorizontalPolar(float& azimuth, float& altitude) {

View file

@ -8,14 +8,32 @@
// //
// //
#include "Util.h"
#include "ViewFrustum.h" #include "ViewFrustum.h"
float ViewFrustum::fovAngleAdust=1.65; ViewFrustum::ViewFrustum() :
_position(glm::vec3(0,0,0)),
ViewFrustum::ViewFrustum(glm::vec3 position, glm::vec3 direction, _direction(glm::vec3(0,0,0)),
glm::vec3 up, glm::vec3 right, float screenWidth, float screenHeight) { _up(glm::vec3(0,0,0)),
this->calculateViewFrustum(position, direction, up, right, screenWidth, screenHeight); _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() // ViewFrustum::calculateViewFrustum()
@ -26,47 +44,41 @@ ViewFrustum::ViewFrustum(glm::vec3 position, glm::vec3 direction,
// Notes on how/why this works: // Notes on how/why this works:
// http://www.lighthouse3d.com/tutorials/view-frustum-culling/view-frustums-shape/ // http://www.lighthouse3d.com/tutorials/view-frustum-culling/view-frustums-shape/
// //
void ViewFrustum::calculateViewFrustum(glm::vec3 position, glm::vec3 direction, void ViewFrustum::calculate() {
glm::vec3 up, glm::vec3 right, float screenWidth, float screenHeight) {
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... glm::vec3 front = _direction;
this->_position = position;
this->_direction = direction;
this->_up = up;
this->_right = right;
this->_screenWidth = screenWidth;
this->_screenHeight = screenHeight;
glm::vec3 front = direction;
// Calculating field of view. // Calculating field of view.
// 0.7854f is 45 deg float fovInRadians = this->_fieldOfView * PI_OVER_180;
// 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;
this->_nearDist = 0.1; float twoTimesTanHalfFOV = 2.0f * tan(fovInRadians/2.0f);
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 farHalfHeight = this->_farHeight * 0.5f; float slightlySmaller = 0.0f;
float farHalfWidth = this->_farWidth * 0.5f; float slightlyInsideWidth= 0.0f - slightlySmaller;
this->_farCenter = this->_position+front * this->_farDist; 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->_farTopLeft = this->_farCenter + (this->_up * farHalfHeight) - (this->_right * farHalfWidth);
this->_farTopRight = 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->_farBottomLeft = this->_farCenter - (this->_up * farHalfHeight) - (this->_right * farHalfWidth);
this->_farBottomRight = 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 nearHalfHeight = (this->_nearHeight * 0.5f) + slightlyInsideWidth;
float nearHalfWidth = this->_nearWidth * 0.5f; float nearHalfWidth = (this->_nearWidth * 0.5f) + slightlyInsideWidth;
this->_nearCenter = this->_position+front * this->_nearDist; this->_nearCenter = this->_position+front * nearClip;
this->_nearTopLeft = this->_nearCenter + (this->_up * nearHalfHeight) - (this->_right * nearHalfWidth); this->_nearTopLeft = this->_nearCenter + (this->_up * nearHalfHeight) - (this->_right * nearHalfWidth);
this->_nearTopRight = 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); 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("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("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("farHeight=%f\n", this->_farHeight);
printf("farWidth=%f\n", this->_farWidth); 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("nearHeight=%f\n", this->_nearHeight);
printf("nearWidth=%f\n", this->_nearWidth); printf("nearWidth=%f\n", this->_nearWidth);

View file

@ -15,54 +15,70 @@
class ViewFrustum { class ViewFrustum {
private: private:
glm::vec3 _position;
glm::vec3 _direction;
glm::vec3 _up;
glm::vec3 _right;
float _screenWidth;
float _screenHeight;
float _nearDist; // camera location/orientation attributes
float _farDist; glm::vec3 _position;
glm::vec3 _direction;
float _nearHeight; glm::vec3 _up;
float _nearWidth; glm::vec3 _right;
float _farHeight;
float _farWidth;
glm::vec3 _farCenter; // Lens attributes
glm::vec3 _farTopLeft; float _fieldOfView;
glm::vec3 _farTopRight; float _aspectRatio;
glm::vec3 _farBottomLeft; float _nearClip;
glm::vec3 _farBottomRight; float _farClip;
glm::vec3 _nearCenter; // Calculated values
glm::vec3 _nearTopLeft; float _nearHeight;
glm::vec3 _nearTopRight; float _nearWidth;
glm::vec3 _nearBottomLeft; float _farHeight;
glm::vec3 _nearBottomRight; 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: public:
const glm::vec3& getFarCenter() const { return _farCenter; }; // setters for camera attributes
const glm::vec3& getFarTopLeft() const { return _farTopLeft; }; void setPosition (const glm::vec3& p) { _position = p; }
const glm::vec3& getFarTopRight() const { return _farTopRight; }; void setOrientation (const glm::vec3& d, const glm::vec3& u, const glm::vec3& r )
const glm::vec3& getFarBottomLeft() const { return _farBottomLeft; }; { _direction = d; _up = u; _right = r; }
const glm::vec3& getFarBottomRight() const { return _farBottomRight; };
const glm::vec3& getNearCenter() const { return _nearCenter; }; // setters for lens attributes
const glm::vec3& getNearTopLeft() const { return _nearTopLeft; }; void setFieldOfView ( float f ) { _fieldOfView = f; }
const glm::vec3& getNearTopRight() const { return _nearTopRight; }; void setAspectRatio ( float a ) { _aspectRatio = a; }
const glm::vec3& getNearBottomLeft() const { return _nearBottomLeft; }; void setNearClip ( float n ) { _nearClip = n; }
const glm::vec3& getNearBottomRight() const { return _nearBottomRight; }; void setFarClip ( float f ) { _farClip = f; }
void calculateViewFrustum(glm::vec3 position, glm::vec3 direction, // getters for lens attributes
glm::vec3 up, glm::vec3 right, float screenWidth, float screenHeight); 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, const glm::vec3& getFarCenter() const { return _farCenter; };
glm::vec3 up, glm::vec3 right, float screenWidth, float screenHeight); const glm::vec3& getFarTopLeft() const { return _farTopLeft; };
const glm::vec3& getFarTopRight() const { return _farTopRight; };
void dump(); const glm::vec3& getFarBottomLeft() const { return _farBottomLeft; };
const glm::vec3& getFarBottomRight() const { return _farBottomRight; };
static float fovAngleAdust;
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();
}; };