mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 06:44:06 +02:00
Merge pull request #182 from ey6es/master
Support for rendering to Oculus rift.
This commit is contained in:
commit
cff1d73496
4 changed files with 359 additions and 162 deletions
|
@ -20,6 +20,27 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
const bool BALLS_ON = false;
|
||||
const bool AVATAR_GRAVITY = true;
|
||||
const float DECAY = 0.1;
|
||||
const float THRUST_MAG = 1200.0;
|
||||
const float YAW_MAG = 500.0;
|
||||
const float BODY_SPIN_FRICTION = 5.0;
|
||||
const float BODY_UPRIGHT_FORCE = 10.0;
|
||||
const float BODY_PITCH_WHILE_WALKING = 30.0;
|
||||
const float BODY_ROLL_WHILE_TURNING = 0.1;
|
||||
const float LIN_VEL_DECAY = 5.0;
|
||||
const float MY_HAND_HOLDING_PULL = 0.2;
|
||||
const float YOUR_HAND_HOLDING_PULL = 1.0;
|
||||
const float BODY_SPRING_FORCE = 6.0f;
|
||||
const float BODY_SPRING_DECAY = 16.0f;
|
||||
const float BODY_SPRING_DEFAULT_TIGHTNESS = 10.0f;
|
||||
const float COLLISION_RADIUS_SCALAR = 1.8;
|
||||
const float COLLISION_BALL_FORCE = 1.0;
|
||||
const float COLLISION_BODY_FORCE = 6.0;
|
||||
const float COLLISION_BALL_FRICTION = 60.0;
|
||||
const float COLLISION_BODY_FRICTION = 0.5;
|
||||
|
||||
float skinColor[] = {1.0, 0.84, 0.66};
|
||||
float lightBlue[] = { 0.7, 0.8, 1.0 };
|
||||
float browColor[] = {210.0/255.0, 105.0/255.0, 30.0/255.0};
|
||||
|
@ -462,7 +483,7 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) {
|
|||
vectorBetweenHands -= otherAvatar->getJointPosition( AVATAR_JOINT_RIGHT_FINGERTIPS );
|
||||
float distanceBetweenHands = glm::length(vectorBetweenHands);
|
||||
|
||||
if (distanceBetweenHands < _avatarTouch.HANDS_CLOSE_ENOUGH_TO_GRASP) {
|
||||
if (distanceBetweenHands < HANDS_CLOSE_ENOUGH_TO_GRASP) {
|
||||
_avatarTouch.setHandsCloseEnoughToGrasp(true);
|
||||
}
|
||||
|
||||
|
@ -470,7 +491,7 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) {
|
|||
if (( _handState == 1 ) || ( _interactingOther->_handState == 1 )) {
|
||||
|
||||
// if the hands are close enough to grasp...
|
||||
if (distanceBetweenHands < _avatarTouch.HANDS_CLOSE_ENOUGH_TO_GRASP)
|
||||
if (distanceBetweenHands < HANDS_CLOSE_ENOUGH_TO_GRASP)
|
||||
{
|
||||
// apply the forces...
|
||||
glm::vec3 vectorToOtherHand = _interactingOther->_handPosition - _handHoldingPosition;
|
||||
|
|
|
@ -148,27 +148,6 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
const bool BALLS_ON = false;
|
||||
const bool AVATAR_GRAVITY = true;
|
||||
const float DECAY = 0.1;
|
||||
const float THRUST_MAG = 1200.0;
|
||||
const float YAW_MAG = 500.0;
|
||||
const float BODY_SPIN_FRICTION = 5.0;
|
||||
const float BODY_UPRIGHT_FORCE = 10.0;
|
||||
const float BODY_PITCH_WHILE_WALKING = 30.0;
|
||||
const float BODY_ROLL_WHILE_TURNING = 0.1;
|
||||
const float LIN_VEL_DECAY = 5.0;
|
||||
const float MY_HAND_HOLDING_PULL = 0.2;
|
||||
const float YOUR_HAND_HOLDING_PULL = 1.0;
|
||||
const float BODY_SPRING_FORCE = 6.0f;
|
||||
const float BODY_SPRING_DECAY = 16.0f;
|
||||
const float BODY_SPRING_DEFAULT_TIGHTNESS = 10.0f;
|
||||
const float COLLISION_RADIUS_SCALAR = 1.8;
|
||||
const float COLLISION_BALL_FORCE = 1.0;
|
||||
const float COLLISION_BODY_FORCE = 6.0;
|
||||
const float COLLISION_BALL_FRICTION = 60.0;
|
||||
const float COLLISION_BODY_FRICTION = 0.5;
|
||||
|
||||
// Do you want head to try to return to center (depends on interface detected)
|
||||
void setHeadReturnToCenter(bool r) { _returnHeadToCenter = r; };
|
||||
const bool getHeadReturnToCenter() const { return _returnHeadToCenter; };
|
||||
|
|
|
@ -11,11 +11,11 @@
|
|||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
const float HANDS_CLOSE_ENOUGH_TO_GRASP = 0.1;
|
||||
|
||||
class AvatarTouch {
|
||||
public:
|
||||
|
||||
const float HANDS_CLOSE_ENOUGH_TO_GRASP = 0.1;
|
||||
|
||||
AvatarTouch();
|
||||
|
||||
void simulate(float deltaTime);
|
||||
|
|
|
@ -183,7 +183,10 @@ int menuOn = 1; // Whether to show onscreen menu
|
|||
ChatEntry chatEntry; // chat entry field
|
||||
bool chatEntryOn = false; // Whether to show the chat entry
|
||||
|
||||
|
||||
bool oculusOn = false; // Whether to configure the display for the Oculus Rift
|
||||
GLuint oculusTextureID = 0; // The texture to which we render for Oculus distortion
|
||||
GLhandleARB oculusProgramID = 0; // The GLSL program containing the distortion shader
|
||||
float oculusDistortionScale = 1.25; // Controls the Oculus field of view
|
||||
|
||||
//
|
||||
// Serial USB Variables
|
||||
|
@ -678,6 +681,289 @@ void renderViewFrustum(ViewFrustum& viewFrustum) {
|
|||
glEnable(GL_LIGHTING);
|
||||
}
|
||||
|
||||
// displays a single side (left, right, or combined for non-Oculus)
|
||||
void displaySide(Camera& whichCamera) {
|
||||
glPushMatrix();
|
||||
|
||||
if (::starsOn) {
|
||||
// should be the first rendering pass - w/o depth buffer / lighting
|
||||
|
||||
// finally render the starfield
|
||||
stars.render(whichCamera.getFieldOfView(), aspectRatio, whichCamera.getNearClip());
|
||||
}
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
// draw a red sphere
|
||||
float sphereRadius = 0.25f;
|
||||
glColor3f(1,0,0);
|
||||
glPushMatrix();
|
||||
glutSolidSphere( sphereRadius, 15, 15 );
|
||||
glPopMatrix();
|
||||
|
||||
//draw a grid ground plane....
|
||||
drawGroundPlaneGrid(10.f);
|
||||
|
||||
// Draw voxels
|
||||
if ( showingVoxels )
|
||||
{
|
||||
voxels.render();
|
||||
}
|
||||
|
||||
// Render avatars of other agents
|
||||
AgentList* agentList = AgentList::getInstance();
|
||||
agentList->lock();
|
||||
for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
|
||||
if (agent->getLinkedData() != NULL && agent->getType() == AGENT_TYPE_AVATAR) {
|
||||
Avatar *avatar = (Avatar *)agent->getLinkedData();
|
||||
avatar->render(0);
|
||||
//avatarRenderer.render(avatar, 0); // this will replace the above call
|
||||
}
|
||||
}
|
||||
agentList->unlock();
|
||||
|
||||
// Render the world box
|
||||
if (!::lookingInMirror && ::statsOn) { render_world_box(); }
|
||||
|
||||
// brad's frustum for debugging
|
||||
if (::frustumOn) renderViewFrustum(::viewFrustum);
|
||||
|
||||
//Render my own avatar
|
||||
myAvatar.render(::lookingInMirror);
|
||||
//avatarRenderer.render(&myAvatar, lookingInMirror); // this will replace the above call
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
// this shader is an adaptation (HLSL -> GLSL, removed conditional) of the one in the Oculus sample
|
||||
// code (Samples/OculusRoomTiny/RenderTiny_D3D1X_Device.cpp), which is under the Apache license
|
||||
// (http://www.apache.org/licenses/LICENSE-2.0)
|
||||
const char* DISTORTION_FRAGMENT_SHADER =
|
||||
"#version 120\n"
|
||||
"uniform sampler2D texture;"
|
||||
"uniform vec2 lensCenter;"
|
||||
"uniform vec2 screenCenter;"
|
||||
"uniform vec2 scale;"
|
||||
"uniform vec2 scaleIn;"
|
||||
"uniform vec4 hmdWarpParam;"
|
||||
"vec2 hmdWarp(vec2 in01) {"
|
||||
" vec2 theta = (in01 - lensCenter) * scaleIn;"
|
||||
" float rSq = theta.x * theta.x + theta.y * theta.y;"
|
||||
" vec2 theta1 = theta * (hmdWarpParam.x + hmdWarpParam.y * rSq + "
|
||||
" hmdWarpParam.z * rSq * rSq + hmdWarpParam.w * rSq * rSq * rSq);"
|
||||
" return lensCenter + scale * theta1;"
|
||||
"}"
|
||||
"void main(void) {"
|
||||
" vec2 tc = hmdWarp(gl_TexCoord[0].st);"
|
||||
" vec2 below = step(screenCenter.st + vec2(-0.25, -0.5), tc.st);"
|
||||
" vec2 above = vec2(1.0, 1.0) - step(screenCenter.st + vec2(0.25, 0.5), tc.st);"
|
||||
" gl_FragColor = mix(vec4(0.0, 0.0, 0.0, 1.0), texture2D(texture, tc), "
|
||||
" above.s * above.t * below.s * below.t);"
|
||||
"}";
|
||||
|
||||
// the locations of the uniform variables
|
||||
int textureLocation;
|
||||
int lensCenterLocation;
|
||||
int screenCenterLocation;
|
||||
int scaleLocation;
|
||||
int scaleInLocation;
|
||||
int hmdWarpParamLocation;
|
||||
|
||||
// renders both sides into a texture, then renders the texture to the display with distortion
|
||||
void displayOculus(Camera& whichCamera) {
|
||||
// magic numbers ahoy! in order to avoid pulling in the Oculus utility library that calculates
|
||||
// the rendering parameters from the hardware stats, i just folded their calculations into
|
||||
// constants using the stats for the current-model hardware as contained in the SDK file
|
||||
// LibOVR/Src/Util/Util_Render_Stereo.cpp
|
||||
|
||||
// eye
|
||||
|
||||
// render the left eye view to the left side of the screen
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glTranslatef(0.151976, 0, 0); // +h, see Oculus SDK docs p. 26
|
||||
gluPerspective(whichCamera.getFieldOfView(), whichCamera.getAspectRatio(),
|
||||
whichCamera.getNearClip(), whichCamera.getFarClip());
|
||||
glTranslatef(0.032, 0, 0); // dip/2, see p. 27
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glViewport(0, 0, WIDTH/2, HEIGHT);
|
||||
displaySide(whichCamera);
|
||||
|
||||
// and the right eye to the right side
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glTranslatef(-0.151976, 0, 0); // -h
|
||||
gluPerspective(whichCamera.getFieldOfView(), whichCamera.getAspectRatio(),
|
||||
whichCamera.getNearClip(), whichCamera.getFarClip());
|
||||
glTranslatef(-0.032, 0, 0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glViewport(WIDTH/2, 0, WIDTH/2, HEIGHT);
|
||||
displaySide(whichCamera);
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
// restore our normal viewport
|
||||
glViewport(0, 0, WIDTH, HEIGHT);
|
||||
|
||||
if (::oculusTextureID == 0) {
|
||||
glGenTextures(1, &::oculusTextureID);
|
||||
glBindTexture(GL_TEXTURE_2D, ::oculusTextureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, WIDTH, HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
GLhandleARB shaderID = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
|
||||
glShaderSourceARB(shaderID, 1, &DISTORTION_FRAGMENT_SHADER, 0);
|
||||
glCompileShaderARB(shaderID);
|
||||
::oculusProgramID = glCreateProgramObjectARB();
|
||||
glAttachObjectARB(::oculusProgramID, shaderID);
|
||||
glLinkProgramARB(::oculusProgramID);
|
||||
textureLocation = glGetUniformLocationARB(::oculusProgramID, "texture");
|
||||
lensCenterLocation = glGetUniformLocationARB(::oculusProgramID, "lensCenter");
|
||||
screenCenterLocation = glGetUniformLocationARB(::oculusProgramID, "screenCenter");
|
||||
scaleLocation = glGetUniformLocationARB(::oculusProgramID, "scale");
|
||||
scaleInLocation = glGetUniformLocationARB(::oculusProgramID, "scaleIn");
|
||||
hmdWarpParamLocation = glGetUniformLocationARB(::oculusProgramID, "hmdWarpParam");
|
||||
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, ::oculusTextureID);
|
||||
}
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
gluOrtho2D(0, WIDTH, 0, HEIGHT);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
// for reference on setting these values, see SDK file Samples/OculusRoomTiny/RenderTiny_Device.cpp
|
||||
|
||||
float scaleFactor = 1.0 / ::oculusDistortionScale;
|
||||
float aspectRatio = (WIDTH * 0.5) / HEIGHT;
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glUseProgramObjectARB(::oculusProgramID);
|
||||
glUniform1fARB(textureLocation, 0);
|
||||
glUniform2fARB(lensCenterLocation, 0.287994, 0.5); // see SDK docs, p. 29
|
||||
glUniform2fARB(screenCenterLocation, 0.25, 0.5);
|
||||
glUniform2fARB(scaleLocation, 0.25 * scaleFactor, 0.5 * scaleFactor * aspectRatio);
|
||||
glUniform2fARB(scaleInLocation, 4, 2 / aspectRatio);
|
||||
glUniform4fARB(hmdWarpParamLocation, 1.0, 0.22, 0.24, 0);
|
||||
|
||||
glColor3f(1, 0, 1);
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0, 0);
|
||||
glVertex2f(0, 0);
|
||||
glTexCoord2f(0.5, 0);
|
||||
glVertex2f(WIDTH/2, 0);
|
||||
glTexCoord2f(0.5, 1);
|
||||
glVertex2f(WIDTH/2, HEIGHT);
|
||||
glTexCoord2f(0, 1);
|
||||
glVertex2f(0, HEIGHT);
|
||||
glEnd();
|
||||
|
||||
glUniform2fARB(lensCenterLocation, 0.787994, 0.5);
|
||||
glUniform2fARB(screenCenterLocation, 0.75, 0.5);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0.5, 0);
|
||||
glVertex2f(WIDTH/2, 0);
|
||||
glTexCoord2f(1, 0);
|
||||
glVertex2f(WIDTH, 0);
|
||||
glTexCoord2f(1, 1);
|
||||
glVertex2f(WIDTH, HEIGHT);
|
||||
glTexCoord2f(0.5, 1);
|
||||
glVertex2f(WIDTH/2, HEIGHT);
|
||||
glEnd();
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glUseProgramObjectARB(0);
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
void displayOverlay() {
|
||||
// Render 2D overlay: I/O level bar graphs and text
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
gluOrtho2D(0, WIDTH, HEIGHT, 0);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
#ifndef _WIN32
|
||||
audio.render(WIDTH, HEIGHT);
|
||||
audioScope.render();
|
||||
#endif
|
||||
|
||||
if (displayHeadMouse && !::lookingInMirror && statsOn) {
|
||||
// Display small target box at center or head mouse target that can also be used to measure LOD
|
||||
glColor3f(1.0, 1.0, 1.0);
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
const int PIXEL_BOX = 20;
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex2f(headMouseX - PIXEL_BOX/2, headMouseY - PIXEL_BOX/2);
|
||||
glVertex2f(headMouseX + PIXEL_BOX/2, headMouseY - PIXEL_BOX/2);
|
||||
glVertex2f(headMouseX + PIXEL_BOX/2, headMouseY + PIXEL_BOX/2);
|
||||
glVertex2f(headMouseX - PIXEL_BOX/2, headMouseY + PIXEL_BOX/2);
|
||||
glVertex2f(headMouseX - PIXEL_BOX/2, headMouseY - PIXEL_BOX/2);
|
||||
glEnd();
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
}
|
||||
|
||||
// Show detected levels from the serial I/O ADC channel sensors
|
||||
if (displayLevels) serialPort.renderLevels(WIDTH,HEIGHT);
|
||||
|
||||
// Display stats and log text onscreen
|
||||
glLineWidth(1.0f);
|
||||
glPointSize(1.0f);
|
||||
|
||||
if (::statsOn) { displayStats(); }
|
||||
if (::logOn) { logger.render(WIDTH, HEIGHT); }
|
||||
|
||||
// Show menu
|
||||
if (::menuOn) {
|
||||
glLineWidth(1.0f);
|
||||
glPointSize(1.0f);
|
||||
menu.render(WIDTH,HEIGHT);
|
||||
}
|
||||
|
||||
// Show chat entry field
|
||||
if (::chatEntryOn) {
|
||||
chatEntry.render(WIDTH, HEIGHT);
|
||||
}
|
||||
|
||||
// Stats at upper right of screen about who domain server is telling us about
|
||||
glPointSize(1.0f);
|
||||
char agents[100];
|
||||
|
||||
AgentList* agentList = AgentList::getInstance();
|
||||
int totalAvatars = 0, totalServers = 0;
|
||||
|
||||
for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
|
||||
agent->getType() == AGENT_TYPE_AVATAR ? totalAvatars++ : totalServers++;
|
||||
}
|
||||
|
||||
sprintf(agents, "Servers: %d, Avatars: %d\n", totalServers, totalAvatars);
|
||||
drawtext(WIDTH-150,20, 0.10, 0, 1.0, 0, agents, 1, 0, 0);
|
||||
|
||||
if (::paintOn) {
|
||||
|
||||
char paintMessage[100];
|
||||
sprintf(paintMessage,"Painting (%.3f,%.3f,%.3f/%.3f/%d,%d,%d)",
|
||||
::paintingVoxel.x,::paintingVoxel.y,::paintingVoxel.z,::paintingVoxel.s,
|
||||
(unsigned int)::paintingVoxel.red,(unsigned int)::paintingVoxel.green,(unsigned int)::paintingVoxel.blue);
|
||||
drawtext(WIDTH-350,50, 0.10, 0, 1.0, 0, paintMessage, 1, 1, 0);
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
void display(void)
|
||||
{
|
||||
|
@ -838,133 +1124,17 @@ void display(void)
|
|||
|
||||
glTranslatef( -whichCamera.getPosition().x, -whichCamera.getPosition().y, -whichCamera.getPosition().z );
|
||||
|
||||
if (::starsOn) {
|
||||
// should be the first rendering pass - w/o depth buffer / lighting
|
||||
|
||||
// finally render the starfield
|
||||
stars.render(whichCamera.getFieldOfView(), aspectRatio, whichCamera.getNearClip());
|
||||
if (::oculusOn) {
|
||||
displayOculus(whichCamera);
|
||||
|
||||
} else {
|
||||
displaySide(whichCamera);
|
||||
glPopMatrix();
|
||||
|
||||
displayOverlay();
|
||||
}
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
// draw a red sphere
|
||||
float sphereRadius = 0.25f;
|
||||
glColor3f(1,0,0);
|
||||
glPushMatrix();
|
||||
glutSolidSphere( sphereRadius, 15, 15 );
|
||||
glPopMatrix();
|
||||
|
||||
//draw a grid ground plane....
|
||||
drawGroundPlaneGrid(10.f);
|
||||
|
||||
// Draw voxels
|
||||
if ( showingVoxels )
|
||||
{
|
||||
voxels.render();
|
||||
}
|
||||
|
||||
// Render avatars of other agents
|
||||
AgentList* agentList = AgentList::getInstance();
|
||||
agentList->lock();
|
||||
for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
|
||||
if (agent->getLinkedData() != NULL && agent->getType() == AGENT_TYPE_AVATAR) {
|
||||
Avatar *avatar = (Avatar *)agent->getLinkedData();
|
||||
avatar->render(0);
|
||||
//avatarRenderer.render(avatar, 0); // this will replace the above call
|
||||
}
|
||||
}
|
||||
agentList->unlock();
|
||||
|
||||
// Render the world box
|
||||
if (!::lookingInMirror && ::statsOn) { render_world_box(); }
|
||||
|
||||
// brad's frustum for debugging
|
||||
if (::frustumOn) renderViewFrustum(::viewFrustum);
|
||||
|
||||
//Render my own avatar
|
||||
myAvatar.render(::lookingInMirror);
|
||||
//avatarRenderer.render(&myAvatar, lookingInMirror); // this will replace the above call
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
// Render 2D overlay: I/O level bar graphs and text
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
gluOrtho2D(0, WIDTH, HEIGHT, 0);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
#ifndef _WIN32
|
||||
audio.render(WIDTH, HEIGHT);
|
||||
audioScope.render();
|
||||
#endif
|
||||
|
||||
if (displayHeadMouse && !::lookingInMirror && statsOn) {
|
||||
// Display small target box at center or head mouse target that can also be used to measure LOD
|
||||
glColor3f(1.0, 1.0, 1.0);
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
const int PIXEL_BOX = 20;
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glVertex2f(headMouseX - PIXEL_BOX/2, headMouseY - PIXEL_BOX/2);
|
||||
glVertex2f(headMouseX + PIXEL_BOX/2, headMouseY - PIXEL_BOX/2);
|
||||
glVertex2f(headMouseX + PIXEL_BOX/2, headMouseY + PIXEL_BOX/2);
|
||||
glVertex2f(headMouseX - PIXEL_BOX/2, headMouseY + PIXEL_BOX/2);
|
||||
glVertex2f(headMouseX - PIXEL_BOX/2, headMouseY - PIXEL_BOX/2);
|
||||
glEnd();
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
}
|
||||
|
||||
// Show detected levels from the serial I/O ADC channel sensors
|
||||
if (displayLevels) serialPort.renderLevels(WIDTH,HEIGHT);
|
||||
|
||||
// Display stats and log text onscreen
|
||||
glLineWidth(1.0f);
|
||||
glPointSize(1.0f);
|
||||
|
||||
if (::statsOn) { displayStats(); }
|
||||
if (::logOn) { logger.render(WIDTH, HEIGHT); }
|
||||
|
||||
// Show menu
|
||||
if (::menuOn) {
|
||||
glLineWidth(1.0f);
|
||||
glPointSize(1.0f);
|
||||
menu.render(WIDTH,HEIGHT);
|
||||
}
|
||||
|
||||
// Show chat entry field
|
||||
if (::chatEntryOn) {
|
||||
chatEntry.render(WIDTH, HEIGHT);
|
||||
}
|
||||
|
||||
// Stats at upper right of screen about who domain server is telling us about
|
||||
glPointSize(1.0f);
|
||||
char agents[100];
|
||||
|
||||
AgentList* agentList = AgentList::getInstance();
|
||||
int totalAvatars = 0, totalServers = 0;
|
||||
|
||||
for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
|
||||
agent->getType() == AGENT_TYPE_AVATAR ? totalAvatars++ : totalServers++;
|
||||
}
|
||||
|
||||
sprintf(agents, "Servers: %d, Avatars: %d\n", totalServers, totalAvatars);
|
||||
drawtext(WIDTH-150,20, 0.10, 0, 1.0, 0, agents, 1, 0, 0);
|
||||
|
||||
if (::paintOn) {
|
||||
|
||||
char paintMessage[100];
|
||||
sprintf(paintMessage,"Painting (%.3f,%.3f,%.3f/%.3f/%d,%d,%d)",
|
||||
::paintingVoxel.x,::paintingVoxel.y,::paintingVoxel.z,::paintingVoxel.s,
|
||||
(unsigned int)::paintingVoxel.red,(unsigned int)::paintingVoxel.green,(unsigned int)::paintingVoxel.blue);
|
||||
drawtext(WIDTH-350,50, 0.10, 0, 1.0, 0, paintMessage, 1, 1, 0);
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
|
||||
glutSwapBuffers();
|
||||
frameCount++;
|
||||
|
||||
|
@ -1026,6 +1196,20 @@ int setGyroLook(int state) {
|
|||
return iRet;
|
||||
}
|
||||
|
||||
int setFullscreen(int state) {
|
||||
bool wasFullscreen = ::fullscreen;
|
||||
int value = setValue(state, &::fullscreen);
|
||||
if (::fullscreen != wasFullscreen) {
|
||||
if (::fullscreen) {
|
||||
glutFullScreen();
|
||||
|
||||
} else {
|
||||
glutReshapeWindow(WIDTH, HEIGHT);
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
int setVoxels(int state) {
|
||||
return setValue(state, &::showingVoxels);
|
||||
}
|
||||
|
@ -1034,6 +1218,15 @@ int setStars(int state) {
|
|||
return setValue(state, &::starsOn);
|
||||
}
|
||||
|
||||
int setOculus(int state) {
|
||||
bool wasOn = ::oculusOn;
|
||||
int value = setValue(state, &::oculusOn);
|
||||
if (::oculusOn != wasOn) {
|
||||
reshape(WIDTH, HEIGHT);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
int setStats(int state) {
|
||||
return setValue(state, &::statsOn);
|
||||
}
|
||||
|
@ -1165,12 +1358,14 @@ void initMenu() {
|
|||
menuColumnOptions->addRow("Mirror (h)", setHead);
|
||||
menuColumnOptions->addRow("Noise (n)", setNoise);
|
||||
menuColumnOptions->addRow("Gyro Look", setGyroLook);
|
||||
menuColumnOptions->addRow("Fullscreen (f)", setFullscreen);
|
||||
menuColumnOptions->addRow("Quit (q)", quitApp);
|
||||
|
||||
// Render
|
||||
menuColumnRender = menu.addColumn("Render");
|
||||
menuColumnRender->addRow("Voxels (V)", setVoxels);
|
||||
menuColumnRender->addRow("Stars (*)", setStars);
|
||||
menuColumnRender->addRow("Oculus (o)", setOculus);
|
||||
|
||||
// Tools
|
||||
menuColumnTools = menu.addColumn("Tools");
|
||||
|
@ -1364,6 +1559,8 @@ void key(unsigned char k, int x, int y)
|
|||
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') setFrustumOffset(MENU_ROW_PICKED); // toggle view frustum offset debugging
|
||||
if (k == 'f') setFullscreen(!::fullscreen);
|
||||
if (k == 'o') setOculus(!::oculusOn);
|
||||
|
||||
if (k == '[') ::viewFrustumOffsetYaw -= 0.5;
|
||||
if (k == ']') ::viewFrustumOffsetYaw += 0.5;
|
||||
|
@ -1540,19 +1737,19 @@ void reshape(int width, int height)
|
|||
HEIGHT = height;
|
||||
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();
|
||||
Camera& camera = ::viewFrustumFromOffset ? (::viewFrustumOffsetCamera) : (::myCamera);
|
||||
float nearClip = camera.getNearClip();
|
||||
float farClip = camera.getFarClip();
|
||||
float fov;
|
||||
|
||||
if (::oculusOn) {
|
||||
// more magic numbers; see Oculus SDK docs, p. 32
|
||||
camera.setAspectRatio(aspectRatio *= 0.5);
|
||||
camera.setFieldOfView(fov = 2 * atan((0.0468 * ::oculusDistortionScale) / 0.041) * (180 / PI));
|
||||
|
||||
} else {
|
||||
fov = ::myCamera.getFieldOfView();
|
||||
nearClip = ::myCamera.getNearClip();
|
||||
farClip = ::myCamera.getFarClip();
|
||||
camera.setFieldOfView(fov = 60);
|
||||
}
|
||||
|
||||
//printLog("reshape() width=%d, height=%d, aspectRatio=%f fov=%f near=%f far=%f \n",
|
||||
|
@ -1665,7 +1862,7 @@ int main(int argc, const char * argv[])
|
|||
int ip = getLocalAddress();
|
||||
sprintf(DOMAIN_IP,"%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF));
|
||||
}
|
||||
|
||||
|
||||
// the callback for our instance of AgentList is attachNewHeadToAgent
|
||||
AgentList::getInstance()->linkedDataCreateCallback = &attachNewHeadToAgent;
|
||||
|
||||
|
|
Loading…
Reference in a new issue