From 02ef1db0d040cfbc648682921fbdac94f20a49b7 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 1 May 2013 12:38:22 -0700 Subject: [PATCH 01/52] Adding devices for Glass, Android --- interface/src/Avatar.cpp | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 3c60f32d04..01c2f0c3fe 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -1267,7 +1267,9 @@ void Avatar::SetNewHeadTarget(float pitch, float yaw) { _head.yawTarget = yaw; } +// // Process UDP interface data from Android transmitter or Google Glass +// void Avatar::processTransmitterData(unsigned char* packetData, int numBytes) { // Read a packet from a transmitter app, process the data float @@ -1278,30 +1280,43 @@ void Avatar::processTransmitterData(unsigned char* packetData, int numBytes) { rot1, rot2, rot3, rot4; // Rotation of device: // rot1 = roll, ranges from -1 to 1, 0 = flat on table // rot2 = pitch, ranges from -1 to 1, 0 = flat on table - // rot3 = yaw, ranges from -1 to 1 + // rot3 = yaw, ranges from -1 to 1 + char device[100]; // Device ID - const bool IS_GLASS = false; // Whether to assume this is a Google glass transmitting + enum deviceTypes { DEVICE_GLASS, DEVICE_ANDROID, DEVICE_IPHONE, DEVICE_UNKNOWN }; - sscanf((char *)packetData, "tacc %f %f %f gra %f %f %f gyr %f %f %f lin %f %f %f rot %f %f %f %f", + sscanf((char *)packetData, + "tacc %f %f %f gra %f %f %f gyr %f %f %f lin %f %f %f rot %f %f %f %f dna \"%s", &accX, &accY, &accZ, &graX, &graY, &graZ, &gyrX, &gyrY, &gyrZ, &linX, &linY, &linZ, - &rot1, &rot2, &rot3, &rot4); + &rot1, &rot2, &rot3, &rot4, (char *)&device); + + // decode transmitter device type + deviceTypes deviceType = DEVICE_UNKNOWN; + if (strcmp(device, "ADR")) { + deviceType = DEVICE_ANDROID; + } else { + deviceType = DEVICE_GLASS; + } if (_transmitterPackets++ == 0) { // If first packet received, note time, turn head spring return OFF, get start rotation gettimeofday(&_transmitterTimer, NULL); - if (IS_GLASS) { + if (deviceType == DEVICE_GLASS) { setHeadReturnToCenter(true); setHeadSpringScale(10.f); printLog("Using Google Glass to drive head, springs ON.\n"); } else { setHeadReturnToCenter(false); - printLog("Using Transmitter to drive head, springs OFF.\n"); + printLog("Using Transmitter %s to drive head, springs OFF.\n", device); } + printLog("Packet: [%s]\n", packetData); + printLog("Version: %s\n", device); + _transmitterInitialReading = glm::vec3( rot3, rot2, rot1 ); @@ -1327,7 +1342,7 @@ void Avatar::processTransmitterData(unsigned char* packetData, int numBytes) { if (eulerAngles.x < -180.f) { eulerAngles.x += 360.f; } glm::vec3 angularVelocity; - if (!IS_GLASS) { + if (!(deviceType == DEVICE_GLASS)) { angularVelocity = glm::vec3(glm::degrees(gyrZ), glm::degrees(-gyrX), glm::degrees(gyrY)); setHeadFromGyros( &eulerAngles, &angularVelocity, (_transmitterHz == 0.f) ? 0.f : 1.f / _transmitterHz, 1.0); @@ -1338,7 +1353,6 @@ void Avatar::processTransmitterData(unsigned char* packetData, int numBytes) { (_transmitterHz == 0.f) ? 0.f : 1.f / _transmitterHz, 1000.0); } - } void Avatar::setHeadFromGyros(glm::vec3* eulerAngles, glm::vec3* angularVelocity, float deltaTime, float smoothingTime) { From 01816ccda3f31c78144ea00095cd2e02f50eb660 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 1 May 2013 14:23:25 -0700 Subject: [PATCH 02/52] add a base config for a pairing server --- CMakeLists.txt | 1 + pairing-server/CMakeLists.txt | 13 +++++++++++++ pairing-server/src/main.cpp | 13 +++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 pairing-server/CMakeLists.txt create mode 100644 pairing-server/src/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3923f543fa..2a4a8d6c01 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,5 +8,6 @@ add_subdirectory(domain-server) add_subdirectory(eve) add_subdirectory(interface) add_subdirectory(injector) +add_subdirectory(pairing-server) add_subdirectory(space-server) add_subdirectory(voxel-server) \ No newline at end of file diff --git a/pairing-server/CMakeLists.txt b/pairing-server/CMakeLists.txt new file mode 100644 index 0000000000..9feb1aa424 --- /dev/null +++ b/pairing-server/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 2.8) + +set(ROOT_DIR ..) +set(MACRO_DIR ${ROOT_DIR}/cmake/macros) + +set(TARGET_NAME pairing-server) + +include(${MACRO_DIR}/SetupHifiProject.cmake) +setup_hifi_project(${TARGET_NAME}) + +# link the shared hifi library +include(${MACRO_DIR}/LinkHifiLibrary.cmake) +link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR}) \ No newline at end of file diff --git a/pairing-server/src/main.cpp b/pairing-server/src/main.cpp new file mode 100644 index 0000000000..bfbed4ed88 --- /dev/null +++ b/pairing-server/src/main.cpp @@ -0,0 +1,13 @@ +// +// main.cpp +// pairing-server +// +// Created by Stephen Birarda on 5/1/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +int main(int argc, const char* argv[]) { + +} + + From 87f48b5bc4d275027c2f8a62b392dd1dc25a4735 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 1 May 2013 15:40:31 -0700 Subject: [PATCH 03/52] add a PariableDevice struct that will hold device info in vector --- pairing-server/src/main.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/pairing-server/src/main.cpp b/pairing-server/src/main.cpp index bfbed4ed88..729946527b 100644 --- a/pairing-server/src/main.cpp +++ b/pairing-server/src/main.cpp @@ -6,8 +6,34 @@ // Copyright (c) 2013 High Fidelity, Inc. All rights reserved. // +#include +#include + +#include + +const int PAIRING_SERVER_LISTEN_PORT = 52934; +const int MAX_PACKET_SIZE_BYTES = 1400; + +struct PairableDevice { + char identifier[64]; + char name[64]; + sockaddr localSocket; +}; + int main(int argc, const char* argv[]) { + UDPSocket serverSocket(PAIRING_SERVER_LISTEN_PORT); + sockaddr deviceAddress; + char deviceData[MAX_PACKET_SIZE_BYTES] = {}; + ssize_t receivedBytes = 0; + + std::vector devices; + + while (true) { + if (serverSocket.receive(&deviceAddress, &deviceData, &receivedBytes)) { + + } + } } From 5b6b28664f2a56c9e2e6ee41e0da67bac94d3d43 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 1 May 2013 18:22:45 -0700 Subject: [PATCH 04/52] Most of the way towards basic Oculus support. --- interface/src/main.cpp | 386 ++++++++++++++++++++++++++++------------- 1 file changed, 263 insertions(+), 123 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index c68c6aee9c..13a7768210 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -174,7 +174,9 @@ 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 +GLuint oculusProgramID = 0; // The GLSL program containing the distortion shader // // Serial USB Variables @@ -688,6 +690,252 @@ 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( 5.0f, 9 ); + + // 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); + } + } + 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); + + glPopMatrix(); +} + +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);" + "}"; + +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) { + // render the left eye view to the left side of the screen + glViewport(0, 0, WIDTH/2, HEIGHT); + displaySide(whichCamera); + + // and the right eye to the right side + glViewport(WIDTH/2, 0, WIDTH/2, HEIGHT); + displaySide(whichCamera); + + // 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); + + GLuint 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); + + glPopMatrix(); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + gluOrtho2D(0, WIDTH, 0, HEIGHT); + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + + glEnable(GL_TEXTURE_2D); + glUseProgramObjectARB(::oculusProgramID); + glUniform1fARB(textureLocation, 0); + glUniform2fARB(lensCenterLocation, 0.25, 0.5); + glUniform2fARB(screenCenterLocation, 0.25, 0.5); + glUniform2fARB(scaleLocation, 0.25, 0.5); + glUniform2fARB(scaleInLocation, 4, 2); + 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.75, 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(); + + glDisable(GL_TEXTURE_2D); + 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) { @@ -846,131 +1094,17 @@ void display(void) glRotatef ( whichCamera.getYaw(), 0, 1, 0 ); 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( 5.0f, 9 ); - - // 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); - } - } - 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); } - 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++; @@ -1040,6 +1174,10 @@ int setStars(int state) { return setValue(state, &::starsOn); } +int setOculus(int state) { + return setValue(state, &::oculusOn); +} + int setStats(int state) { return setValue(state, &::statsOn); } @@ -1162,6 +1300,7 @@ void initMenu() { menuColumnRender = menu.addColumn("Render"); menuColumnRender->addRow("Voxels (V)", setVoxels); menuColumnRender->addRow("Stars (*)", setStars); + menuColumnRender->addRow("Oculus (o)", setOculus); // Tools menuColumnTools = menu.addColumn("Tools"); @@ -1353,6 +1492,7 @@ 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 == 'o') ::oculusOn = !::oculusOn; if (k == '[') ::viewFrustumOffsetYaw -= 0.5; if (k == ']') ::viewFrustumOffsetYaw += 0.5; From 09a6a476d597fa5c054bcf462de666b535a19d33 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 1 May 2013 20:55:40 -0700 Subject: [PATCH 05/52] Slow down when near other avatars - incremental commit --- interface/src/Avatar.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index d59395e01f..e4a63fce51 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -320,6 +320,8 @@ void Avatar::setMousePressed( bool d ) { void Avatar::simulate(float deltaTime) { + float nearestAvatarDistance = 1000000.f; + // update balls if (_balls) { _balls->simulate(deltaTime); } @@ -341,7 +343,7 @@ void Avatar::simulate(float deltaTime) { if ( _isMine ) { float closestDistance = 10000.0f; - + AgentList* agentList = AgentList::getInstance(); for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) { if (agent->getLinkedData() != NULL && agent->getType() == AGENT_TYPE_AVATAR) { @@ -355,6 +357,8 @@ void Avatar::simulate(float deltaTime) { v -= otherAvatar->getBonePosition( AVATAR_BONE_RIGHT_HAND ); float distance = glm::length( v ); + if ( distance < nearestAvatarDistance ) { nearestAvatarDistance = distance; } + if ( distance < _maxArmLength + _maxArmLength ) { closestDistance = distance; @@ -442,6 +446,11 @@ void Avatar::simulate(float deltaTime) { // decay velocity _velocity *= ( 1.0 - LIN_VEL_DECAY * deltaTime ); + + // If other avatars nearby, damp velocity much more! + if (_isMine && (nearestAvatarDistance < 3.f)) { + _velocity *= (1.0 - fmin(10.f * glm::length(_velocity) * deltaTime, 1.0)); + } // update head information updateHead(deltaTime); From ee1e5d16fcef5c2e4596f4ffc2f48cc7f3ebb22c Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 1 May 2013 22:03:57 -0700 Subject: [PATCH 06/52] Avatars are now slowed down when they get near other avatars, for easy fine positioning. --- interface/src/Avatar.cpp | 22 ++++++++++++++++------ interface/src/main.cpp | 20 ++++++-------------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 53ba706604..402af33c55 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -324,7 +324,16 @@ void Avatar::setMousePressed( bool d ) { void Avatar::simulate(float deltaTime) { - float nearestAvatarDistance = 1000000.f; + float nearestAvatarDistance = std::numeric_limits::max(); + +//keep this - I'm still using it to test things.... +/* +//TEST +static float tt = 0.0f; +tt += deltaTime * 2.0f; +//_head.leanSideways = 0.01 * sin( tt ); +_head.leanForward = 0.02 * sin( tt * 0.8 ); +*/ // update balls if (_balls) { _balls->simulate(deltaTime); } @@ -346,8 +355,7 @@ void Avatar::simulate(float deltaTime) { // all the other avatars for potential interactions... if ( _isMine ) { - float closestDistance = 10000.0f; - + AgentList* agentList = AgentList::getInstance(); for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) { if (agent->getLinkedData() != NULL && agent->getType() == AGENT_TYPE_AVATAR) { @@ -467,9 +475,11 @@ void Avatar::simulate(float deltaTime) { // decay velocity _velocity *= ( 1.0 - LIN_VEL_DECAY * deltaTime ); - // If other avatars nearby, damp velocity much more! - if (_isMine && (nearestAvatarDistance < 3.f)) { - _velocity *= (1.0 - fmin(10.f * glm::length(_velocity) * deltaTime, 1.0)); + // If someone is near, damp velocity as a function of closeness + const float AVATAR_BRAKING_RANGE = 1.2f; + const float AVATAR_BRAKING_STRENGTH = 25.f; + if (_isMine && (nearestAvatarDistance < AVATAR_BRAKING_RANGE )) { + _velocity *= (1.f - deltaTime * AVATAR_BRAKING_STRENGTH * (AVATAR_BRAKING_RANGE - nearestAvatarDistance)); } // update head information diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 055bf73c85..ce15eb07c4 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -221,23 +221,15 @@ void displayStats(void) if (::menuOn == 0) { statsVerticalOffset = 8; } - // bitmap chars are about 10 pels high - char legend[] = "/ - toggle this display, Q - exit, H - show head, M - show hand, T - test audio"; - drawtext(10, statsVerticalOffset + 15, 0.10f, 0, 1.0, 0, legend); - char legend2[] = "* - toggle stars, & - toggle paint mode, '-' - send erase all, '%' - send add scene"; - drawtext(10, statsVerticalOffset + 32, 0.10f, 0, 1.0, 0, legend2); - - glm::vec3 avatarPos = myAvatar.getPosition(); - char stats[200]; - sprintf(stats, "FPS = %3.0f Pkts/s = %d Bytes/s = %d Head(x,y,z)= %4.2f, %4.2f, %4.2f ", - FPS, packetsPerSecond, bytesPerSecond, avatarPos.x,avatarPos.y,avatarPos.z); - drawtext(10, statsVerticalOffset + 49, 0.10f, 0, 1.0, 0, stats); + sprintf(stats, "%3.0f FPS, %d Pkts/sec, %3.2f Mbps", + FPS, packetsPerSecond, (float)bytesPerSecond * 8.f / 1000000.f); + drawtext(10, statsVerticalOffset + 15, 0.10f, 0, 1.0, 0, stats); std::stringstream voxelStats; voxelStats << "Voxels Rendered: " << voxels.getVoxelsRendered() << " Updated: " << voxels.getVoxelsUpdated(); - drawtext(10, statsVerticalOffset + 70, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); + drawtext(10, statsVerticalOffset + 230, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); voxelStats.str(""); voxelStats << "Voxels Created: " << voxels.getVoxelsCreated() << " (" << voxels.getVoxelsCreatedPerSecondAverage() @@ -251,7 +243,7 @@ void displayStats(void) voxelStats.str(""); voxelStats << "Voxels Bytes Read: " << voxels.getVoxelsBytesRead() - << " (" << voxels.getVoxelsBytesReadPerSecondAverage() << " Bps)"; + << " (" << voxels.getVoxelsBytesReadPerSecondAverage() * 8.f / 1000000.f << " Mbps)"; drawtext(10, statsVerticalOffset + 290,0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); voxelStats.str(""); @@ -1633,7 +1625,7 @@ int main(int argc, const char * argv[]) } // Handle Local Domain testing with the --local command line - if (true || cmdOptionExists(argc, argv, "--local")) { + if (cmdOptionExists(argc, argv, "--local")) { printLog("Local Domain MODE!\n"); int ip = getLocalAddress(); sprintf(DOMAIN_IP,"%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF)); From 900caa6278de7811c392c25702dbc48aeffdc3e8 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 1 May 2013 22:40:38 -0700 Subject: [PATCH 07/52] Changed idle simulate call to 16msecs (which will set avatar mixer rate at 60FPS), further small stats improvements --- interface/src/main.cpp | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index ce15eb07c4..822bfe81f6 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -15,7 +15,7 @@ // Welcome Aboard! // // -// Keyboard Commands: +// Keyboard Commands: // // / = toggle stats display // spacebar = reset gyros/head position @@ -134,7 +134,7 @@ VoxelSystem voxels; Audio audio(&audioScope, &myAvatar); #endif -#define IDLE_SIMULATE_MSECS 8 // How often should call simulate and other stuff +#define IDLE_SIMULATE_MSECS 16 // How often should call simulate and other stuff // in the idle loop? // Where one's own agent begins in the world (needs to become a dynamic thing passed to the program) @@ -228,22 +228,23 @@ void displayStats(void) drawtext(10, statsVerticalOffset + 15, 0.10f, 0, 1.0, 0, stats); std::stringstream voxelStats; - voxelStats << "Voxels Rendered: " << voxels.getVoxelsRendered() << " Updated: " << voxels.getVoxelsUpdated(); + voxelStats.precision(4); + voxelStats << "Voxels Rendered: " << voxels.getVoxelsRendered()/1000.f << "K Updated: " << voxels.getVoxelsUpdated()/1000.f << "K"; drawtext(10, statsVerticalOffset + 230, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); voxelStats.str(""); - voxelStats << "Voxels Created: " << voxels.getVoxelsCreated() << " (" << voxels.getVoxelsCreatedPerSecondAverage() - << "/sec) "; + voxelStats << "Voxels Created: " << voxels.getVoxelsCreated()/1000.f << "K (" << voxels.getVoxelsCreatedPerSecondAverage()/1000.f + << "Kps) "; drawtext(10, statsVerticalOffset + 250, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); voxelStats.str(""); - voxelStats << "Voxels Colored: " << voxels.getVoxelsColored() << " (" << voxels.getVoxelsColoredPerSecondAverage() - << "/sec) "; + voxelStats << "Voxels Colored: " << voxels.getVoxelsColored()/1000.f << "K (" << voxels.getVoxelsColoredPerSecondAverage()/1000.f + << "Kps) "; drawtext(10, statsVerticalOffset + 270, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); voxelStats.str(""); - voxelStats << "Voxels Bytes Read: " << voxels.getVoxelsBytesRead() - << " (" << voxels.getVoxelsBytesReadPerSecondAverage() * 8.f / 1000000.f << " Mbps)"; + voxelStats << "Voxel Bits Read: " << voxels.getVoxelsBytesRead() * 8.f / 1000000.f + << "M (" << voxels.getVoxelsBytesReadPerSecondAverage() * 8.f / 1000000.f << " Mbps)"; drawtext(10, statsVerticalOffset + 290,0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); voxelStats.str(""); @@ -251,13 +252,13 @@ void displayStats(void) ? ((float) voxels.getVoxelsBytesRead() / voxels.getVoxelsColored()) : 0; - voxelStats << "Voxels Bytes per Colored: " << voxelsBytesPerColored; + voxelStats << "Voxels Bits per Colored: " << voxelsBytesPerColored * 8; drawtext(10, statsVerticalOffset + 310, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); Agent *avatarMixer = AgentList::getInstance()->soloAgentOfType(AGENT_TYPE_AVATAR_MIXER); char avatarMixerStats[200]; if (avatarMixer) { - sprintf(avatarMixerStats, "Avatar Mixer - %.f kbps, %.f pps", + sprintf(avatarMixerStats, "Avatar Mixer: %.f kbps, %.f pps", roundf(avatarMixer->getAverageKilobitsPerSecond()), roundf(avatarMixer->getAveragePacketsPerSecond())); } else { From 6a7ebb3a556b5536c6a4462a0c3975e7a45957bf Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 1 May 2013 22:57:19 -0700 Subject: [PATCH 08/52] fixed LOD issue in client --- interface/src/VoxelSystem.cpp | 2 +- libraries/voxels/src/VoxelNode.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 76fda4f942..9dd948e881 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -164,7 +164,7 @@ int VoxelSystem::newTreeToArrays(VoxelNode* node) { float childBoundary = boundaryDistanceForRenderLevel(*node->octalCode + 2); bool inBoundary = (distanceToNode <= boundary); bool inChildBoundary = (distanceToNode <= childBoundary); - bool shouldRender = node->isColored() && ((node->isLeaf() && inChildBoundary) || (inBoundary && !inChildBoundary)); + bool shouldRender = node->isColored() && ((node->isLeaf() && inChildBoundary) || (inBoundary && !inChildBoundary)); node->setShouldRender(shouldRender); // let children figure out their renderness diff --git a/libraries/voxels/src/VoxelNode.cpp b/libraries/voxels/src/VoxelNode.cpp index 6f8f1d71f8..776aec7a9a 100644 --- a/libraries/voxels/src/VoxelNode.cpp +++ b/libraries/voxels/src/VoxelNode.cpp @@ -234,6 +234,7 @@ bool VoxelNode::isInView(const ViewFrustum& viewFrustum) const { float VoxelNode::distanceToCamera(const ViewFrustum& viewFrustum) const { AABox box; getAABox(box); + box.scale(TREE_SCALE); float distanceToVoxelCenter = sqrtf(powf(viewFrustum.getPosition().x - (box.getCorner().x + box.getSize().x), 2) + powf(viewFrustum.getPosition().y - (box.getCorner().y + box.getSize().y), 2) + powf(viewFrustum.getPosition().z - (box.getCorner().z + box.getSize().z), 2)); From a6d2bb73ada91462e7ba3dfbcedb176c7d85271c Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 1 May 2013 23:24:46 -0700 Subject: [PATCH 09/52] added warnings if bitstream processing takes too long --- interface/src/VoxelSystem.cpp | 57 +++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 9dd948e881..a1f4404e20 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -97,8 +97,21 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { switch(command) { case PACKET_HEADER_VOXEL_DATA: + { + double start = usecTimestampNow(); // ask the VoxelTree to read the bitstream into the tree _tree->readBitstreamToTree(voxelData, numBytes - 1); + double end = usecTimestampNow(); + double elapsedmsec = (end - start)/1000.0; + if (elapsedmsec > 100) { + if (elapsedmsec > 1000) { + double elapsedsec = (end - start)/1000000.0; + printLog("WARNING! readBitstreamToTree() took %lf seconds\n",elapsedsec); + } else { + printLog("WARNING! readBitstreamToTree() took %lf milliseconds\n",elapsedmsec); + } + } + } break; case PACKET_HEADER_ERASE_VOXEL: // ask the tree to read the "remove" bitstream @@ -135,16 +148,28 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { } void VoxelSystem::setupNewVoxelsForDrawing() { + double start = usecTimestampNow(); _voxelsUpdated = newTreeToArrays(_tree->rootNode); if (_voxelsUpdated) { _voxelsDirty=true; } + double end = usecTimestampNow(); + double elapsedmsec = (end - start)/1000.0; + if (elapsedmsec > 100) { + if (elapsedmsec > 1000) { + double elapsedsec = (end - start)/1000000.0; + printLog("WARNING! newTreeToArrays() took %lf seconds\n",elapsedsec); + } else { + printLog("WARNING! newTreeToArrays() took %lf milliseconds\n",elapsedmsec); + } + } // copy the newly written data to the arrays designated for reading copyWrittenDataToReadArrays(); } void VoxelSystem::copyWrittenDataToReadArrays() { + double start = usecTimestampNow(); if (_voxelsDirty) { // lock on the buffer write lock so we can't modify the data when the GPU is reading it pthread_mutex_lock(&_bufferWriteLock); @@ -154,6 +179,16 @@ void VoxelSystem::copyWrittenDataToReadArrays() { memcpy(_readColorsArray, _writeColorsArray, bytesOfColors ); pthread_mutex_unlock(&_bufferWriteLock); } + double end = usecTimestampNow(); + double elapsedmsec = (end - start)/1000.0; + if (elapsedmsec > 100) { + if (elapsedmsec > 1000) { + double elapsedsec = (end - start)/1000000.0; + printLog("WARNING! copyWrittenDataToReadArrays() took %lf seconds\n",elapsedsec); + } else { + printLog("WARNING! copyWrittenDataToReadArrays() took %lf milliseconds\n",elapsedmsec); + } + } } int VoxelSystem::newTreeToArrays(VoxelNode* node) { @@ -296,6 +331,7 @@ void VoxelSystem::init() { } void VoxelSystem::updateVBOs() { + double start = usecTimestampNow(); if (_voxelsDirty) { glBufferIndex segmentStart = 0; glBufferIndex segmentEnd = 0; @@ -327,9 +363,20 @@ void VoxelSystem::updateVBOs() { } _voxelsDirty = false; } + double end = usecTimestampNow(); + double elapsedmsec = (end - start)/1000.0; + if (elapsedmsec > 100) { + if (elapsedmsec > 1000) { + double elapsedsec = (end - start)/1000000.0; + printLog("WARNING! updateVBOs() took %lf seconds\n",elapsedsec); + } else { + printLog("WARNING! updateVBOs() took %lf milliseconds\n",elapsedmsec); + } + } } void VoxelSystem::render() { + double start = usecTimestampNow(); glPushMatrix(); updateVBOs(); // tell OpenGL where to find vertex and color information @@ -362,6 +409,16 @@ void VoxelSystem::render() { // scale back down to 1 so heads aren't massive glPopMatrix(); + double end = usecTimestampNow(); + double elapsedmsec = (end - start)/1000.0; + if (elapsedmsec > 100) { + if (elapsedmsec > 1000) { + double elapsedsec = (end - start)/1000000.0; + printLog("WARNING! render() took %lf seconds\n",elapsedsec); + } else { + printLog("WARNING! render() took %lf milliseconds\n",elapsedmsec); + } + } } int VoxelSystem::_nodeCount = 0; From 174c3ee65b5ca6798745aed92ca1ad383f270842 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 May 2013 11:31:20 -0700 Subject: [PATCH 10/52] search into level appropriately --- libraries/voxels/src/VoxelTree.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 3ff14b5afd..ba13ee1c28 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -498,10 +498,10 @@ int VoxelTree::searchForColoredNodesRecursion(int maxSearchLevel, int& currentSe // Keep track of how deep we've searched. currentSearchLevel++; - // If we've reached our max Search Level, then stop searching. - if (currentSearchLevel >= maxSearchLevel) { - return currentSearchLevel; - } + // If we've passed our max Search Level, then stop searching. return last level searched + if (currentSearchLevel > maxSearchLevel) { + return currentSearchLevel-1; + } // If we're at a node that is out of view, then we can return, because no nodes below us will be in view! if (!node->isInView(viewFrustum)) { From 275772bb3d3cd800d615e78397fc0b6cd70eb084 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 May 2013 12:26:51 -0700 Subject: [PATCH 11/52] debugging voxel sending behavior --- interface/src/VoxelSystem.cpp | 11 +++++++++-- interface/src/VoxelSystem.h | 2 ++ interface/src/main.cpp | 17 +++++++++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index a1f4404e20..72a153ded2 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -423,10 +423,17 @@ void VoxelSystem::render() { int VoxelSystem::_nodeCount = 0; +void VoxelSystem::killLocalVoxels() { + _tree->eraseAllVoxels(); + _voxelsInArrays = 0; // better way to do this?? + //setupNewVoxelsForDrawing(); +} + + bool VoxelSystem::randomColorOperation(VoxelNode* node, void* extraData) { _nodeCount++; if (node->isColored()) { - nodeColor newColor = { randomColorValue(150), randomColorValue(150), randomColorValue(150), 1 }; + nodeColor newColor = { 255, randomColorValue(150), randomColorValue(150), 1 }; node->setColor(newColor); } return true; @@ -442,7 +449,7 @@ void VoxelSystem::randomizeVoxelColors() { bool VoxelSystem::falseColorizeRandomOperation(VoxelNode* node, void* extraData) { _nodeCount++; // always false colorize - node->setFalseColor(randomColorValue(150), randomColorValue(150), randomColorValue(150)); + node->setFalseColor(255, randomColorValue(150), randomColorValue(150)); return true; // keep going! } diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index e6798f9fd1..63f3b8622e 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -58,6 +58,8 @@ public: void falseColorizeInView(ViewFrustum* viewFrustum); void falseColorizeDistanceFromView(ViewFrustum* viewFrustum); + void killLocalVoxels(); + private: // Operation functions for tree recursion methods static int _nodeCount; diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 08b1666d05..d5c28770be 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -130,6 +130,9 @@ glm::vec3 box(WORLD_SIZE,WORLD_SIZE,WORLD_SIZE); VoxelSystem voxels; +bool wantToKillLocalVoxels = false; + + #ifndef _WIN32 Audio audio(&audioScope, &myAvatar); #endif @@ -1071,6 +1074,13 @@ int setFrustumRenderMode(int state) { return ::frustumDrawingMode; } +int doKillLocalVoxels(int state) { + if (state == MENU_ROW_PICKED) { + ::wantToKillLocalVoxels = true; + } + return state; +} + int doRandomizeVoxelColors(int state) { if (state == MENU_ROW_PICKED) { ::voxels.randomizeVoxelColors(); @@ -1168,6 +1178,7 @@ void initMenu() { // Debug menuColumnDebug = menu.addColumn("Debug"); + menuColumnDebug->addRow("Kill Local Voxels", doKillLocalVoxels); menuColumnDebug->addRow("Randomize Voxel TRUE Colors", doRandomizeVoxelColors); menuColumnDebug->addRow("FALSE Color Voxels Randomly", doFalseRandomizeVoxelColors); menuColumnDebug->addRow("FALSE Color Voxels by Distance", doFalseColorizeByDistance); @@ -1412,6 +1423,12 @@ void* networkReceive(void* args) ssize_t bytesReceived; while (!stopNetworkReceiveThread) { + // check to see if the UI thread asked us to kill the voxel tree. since we're the only thread allowed to do that + if (::wantToKillLocalVoxels) { + ::voxels.killLocalVoxels(); + ::wantToKillLocalVoxels = false; + } + if (AgentList::getInstance()->getAgentSocket().receive(&senderAddress, incomingPacket, &bytesReceived)) { packetCount++; bytesCount += bytesReceived; From 0f48ac67b8b3d2cd594d46b5ae095cef02438fe2 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 May 2013 12:27:16 -0700 Subject: [PATCH 12/52] added timing details to voxel sending behavior --- voxel-server/src/main.cpp | 51 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 9ab5675d7e..2c215b03e4 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -167,8 +167,14 @@ void eraseVoxelTreeAndCleanupAgentVisitData() { void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAgentData* agentData, ViewFrustum& viewFrustum) { - // If the bag is empty, fill it... - if (agentData->nodeBag.isEmpty()) { + bool searchReset = false; + int searchLoops = 0; + int searchLevelWas = agentData->getMaxSearchLevel(); + double start = usecTimestampNow(); + while (!searchReset && agentData->nodeBag.isEmpty()) { + searchLoops++; + + searchLevelWas = agentData->getMaxSearchLevel(); int maxLevelReached = randomTree.searchForColoredNodes(agentData->getMaxSearchLevel(), randomTree.rootNode, viewFrustum, agentData->nodeBag); agentData->setMaxLevelReached(maxLevelReached); @@ -177,17 +183,38 @@ void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAge if (agentData->nodeBag.isEmpty()) { if (agentData->getMaxLevelReached() < agentData->getMaxSearchLevel()) { agentData->resetMaxSearchLevel(); + searchReset = true; } else { agentData->incrementMaxSearchLevel(); } } } + double end = usecTimestampNow(); + double elapsedmsec = (end - start)/1000.0; + if (elapsedmsec > 100) { + if (elapsedmsec > 1000) { + double elapsedsec = (end - start)/1000000.0; + printf("WARNING! searchForColoredNodes() took %lf seconds to identify %d nodes at level %d in %d loops\n", + elapsedsec, agentData->nodeBag.count(), searchLevelWas, searchLoops); + } else { + printf("WARNING! searchForColoredNodes() took %lf milliseconds to identify %d nodes at level %d in %d loops\n", + elapsedmsec, agentData->nodeBag.count(), searchLevelWas, searchLoops); + } + } else { + printf("searchForColoredNodes() took %lf milliseconds to identify %d nodes at level %d in %d loops\n", + elapsedmsec, agentData->nodeBag.count(), searchLevelWas, searchLoops); + } + // If we have something in our nodeBag, then turn them into packets and send them out... if (!agentData->nodeBag.isEmpty()) { static unsigned char tempOutputBuffer[MAX_VOXEL_PACKET_SIZE - 1]; // save on allocs by making this static int bytesWritten = 0; int packetsSentThisInterval = 0; + int truePacketsSent = 0; + int trueBytesSent = 0; + double start = usecTimestampNow(); + while (packetsSentThisInterval < PACKETS_PER_CLIENT_PER_INTERVAL) { if (!agentData->nodeBag.isEmpty()) { VoxelNode* subTree = agentData->nodeBag.extract(); @@ -200,6 +227,8 @@ void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAge } else { agentList->getAgentSocket().send(agent->getActiveSocket(), agentData->getPacket(), agentData->getPacketLength()); + trueBytesSent += agentData->getPacketLength(); + truePacketsSent++; packetsSentThisInterval++; agentData->resetVoxelPacket(); agentData->writeToPacket(&tempOutputBuffer[0], bytesWritten); @@ -208,12 +237,30 @@ void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAge if (agentData->isPacketWaiting()) { agentList->getAgentSocket().send(agent->getActiveSocket(), agentData->getPacket(), agentData->getPacketLength()); + trueBytesSent += agentData->getPacketLength(); + truePacketsSent++; agentData->resetVoxelPacket(); } packetsSentThisInterval = PACKETS_PER_CLIENT_PER_INTERVAL; // done for now, no nodes left } } + double end = usecTimestampNow(); + double elapsedmsec = (end - start)/1000.0; + if (elapsedmsec > 100) { + if (elapsedmsec > 1000) { + double elapsedsec = (end - start)/1000000.0; + printf("WARNING! packetLoop() took %lf seconds to generate %d bytes in %d packets at level %d, %d nodes still to send\n", + elapsedsec, trueBytesSent, truePacketsSent, searchLevelWas, agentData->nodeBag.count()); + } else { + printf("WARNING! packetLoop() took %lf milliseconds to generate %d bytes in %d packets at level %d, %d nodes still to send\n", + elapsedmsec, trueBytesSent, truePacketsSent, searchLevelWas, agentData->nodeBag.count()); + } + } else { + printf("packetLoop() took %lf milliseconds to generate %d bytes in %d packets at level %d, %d nodes still to send\n", + elapsedmsec, trueBytesSent, truePacketsSent, searchLevelWas, agentData->nodeBag.count()); + } + // if during this last pass, we emptied our bag, then we want to move to the next level. if (agentData->nodeBag.isEmpty()) { if (agentData->getMaxLevelReached() < agentData->getMaxSearchLevel()) { From e2481f514c75a6ecd13c9561bffeef59df48f799 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 May 2013 12:53:56 -0700 Subject: [PATCH 13/52] lower warning threshold to 1 millisecond for voxel render pipeline steps --- interface/src/VoxelSystem.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 72a153ded2..ba76202822 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -103,7 +103,7 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { _tree->readBitstreamToTree(voxelData, numBytes - 1); double end = usecTimestampNow(); double elapsedmsec = (end - start)/1000.0; - if (elapsedmsec > 100) { + if (elapsedmsec > 1) { if (elapsedmsec > 1000) { double elapsedsec = (end - start)/1000000.0; printLog("WARNING! readBitstreamToTree() took %lf seconds\n",elapsedsec); @@ -155,7 +155,7 @@ void VoxelSystem::setupNewVoxelsForDrawing() { } double end = usecTimestampNow(); double elapsedmsec = (end - start)/1000.0; - if (elapsedmsec > 100) { + if (elapsedmsec > 1) { if (elapsedmsec > 1000) { double elapsedsec = (end - start)/1000000.0; printLog("WARNING! newTreeToArrays() took %lf seconds\n",elapsedsec); @@ -181,7 +181,7 @@ void VoxelSystem::copyWrittenDataToReadArrays() { } double end = usecTimestampNow(); double elapsedmsec = (end - start)/1000.0; - if (elapsedmsec > 100) { + if (elapsedmsec > 1) { if (elapsedmsec > 1000) { double elapsedsec = (end - start)/1000000.0; printLog("WARNING! copyWrittenDataToReadArrays() took %lf seconds\n",elapsedsec); @@ -365,7 +365,7 @@ void VoxelSystem::updateVBOs() { } double end = usecTimestampNow(); double elapsedmsec = (end - start)/1000.0; - if (elapsedmsec > 100) { + if (elapsedmsec > 1) { if (elapsedmsec > 1000) { double elapsedsec = (end - start)/1000000.0; printLog("WARNING! updateVBOs() took %lf seconds\n",elapsedsec); @@ -411,7 +411,7 @@ void VoxelSystem::render() { glPopMatrix(); double end = usecTimestampNow(); double elapsedmsec = (end - start)/1000.0; - if (elapsedmsec > 100) { + if (elapsedmsec > 1) { if (elapsedmsec > 1000) { double elapsedsec = (end - start)/1000000.0; printLog("WARNING! render() took %lf seconds\n",elapsedsec); From 7625c9a62122dff2cb2be08ff3fa0cbfe7d2b28a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 May 2013 12:54:26 -0700 Subject: [PATCH 14/52] add command line option to debug voxel sending time --- voxel-server/src/main.cpp | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 2c215b03e4..4a64da8a0f 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -45,8 +45,7 @@ const int MAX_VOXEL_TREE_DEPTH_LEVELS = 4; VoxelTree randomTree; bool wantColorRandomizer = false; -bool debugViewFrustum = false; -bool viewFrustumCulling = true; // for now +bool debugVoxelSending = false; void addSphere(VoxelTree * tree,bool random, bool wantColorRandomizer) { float r = random ? randFloatInRange(0.05,0.1) : 0.25; @@ -200,7 +199,7 @@ void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAge printf("WARNING! searchForColoredNodes() took %lf milliseconds to identify %d nodes at level %d in %d loops\n", elapsedmsec, agentData->nodeBag.count(), searchLevelWas, searchLoops); } - } else { + } else if (::debugVoxelSending) { printf("searchForColoredNodes() took %lf milliseconds to identify %d nodes at level %d in %d loops\n", elapsedmsec, agentData->nodeBag.count(), searchLevelWas, searchLoops); } @@ -256,7 +255,7 @@ void voxelDistributor(AgentList* agentList, AgentList::iterator& agent, VoxelAge printf("WARNING! packetLoop() took %lf milliseconds to generate %d bytes in %d packets at level %d, %d nodes still to send\n", elapsedmsec, trueBytesSent, truePacketsSent, searchLevelWas, agentData->nodeBag.count()); } - } else { + } else if (::debugVoxelSending) { printf("packetLoop() took %lf milliseconds to generate %d bytes in %d packets at level %d, %d nodes still to send\n", elapsedmsec, trueBytesSent, truePacketsSent, searchLevelWas, agentData->nodeBag.count()); } @@ -343,13 +342,9 @@ int main(int argc, const char * argv[]) srand((unsigned)time(0)); - const char* DEBUG_VIEW_FRUSTUM = "--DebugViewFrustum"; - ::debugViewFrustum = cmdOptionExists(argc, argv, DEBUG_VIEW_FRUSTUM); - printf("debugViewFrustum=%s\n", (::debugViewFrustum ? "yes" : "no")); - - const char* NO_VIEW_FRUSTUM_CULLING = "--NoViewFrustumCulling"; - ::viewFrustumCulling = !cmdOptionExists(argc, argv, NO_VIEW_FRUSTUM_CULLING); - printf("viewFrustumCulling=%s\n", (::viewFrustumCulling ? "yes" : "no")); + const char* DEBUG_VOXEL_SENDING = "--DebugVoxelSending"; + ::debugVoxelSending = cmdOptionExists(argc, argv, DEBUG_VOXEL_SENDING); + printf("debugVoxelSending=%s\n", (::debugVoxelSending ? "yes" : "no")); const char* WANT_COLOR_RANDOMIZER = "--wantColorRandomizer"; ::wantColorRandomizer = cmdOptionExists(argc, argv, WANT_COLOR_RANDOMIZER); @@ -427,8 +422,6 @@ int main(int argc, const char * argv[]) delete []vertices; randomTree.readCodeColorBufferToTree(pVoxelData); - //printf("readCodeColorBufferToTree() of size=%d atByte=%d receivedBytes=%ld\n", - // voxelDataSize,atByte,receivedBytes); // skip to next pVoxelData+=voxelDataSize; atByte+=voxelDataSize; From 94f1e03eb1e09d467bba18dbc5352bc636264b97 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 2 May 2013 13:02:11 -0700 Subject: [PATCH 15/52] More work on Oculus integration; added some notes to explain the source of the magic numbers. --- interface/src/main.cpp | 66 ++++++++++++++++++++++++++++++------------ 1 file changed, 48 insertions(+), 18 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 13a7768210..8a6af32692 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -177,6 +177,7 @@ 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 GLuint oculusProgramID = 0; // The GLSL program containing the distortion shader +float oculusDistortionScale = 1.5f; // Controls the Oculus field of view // // Serial USB Variables @@ -743,6 +744,9 @@ void displaySide(Camera& whichCamera) { 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;" @@ -766,6 +770,7 @@ const char* DISTORTION_FRAGMENT_SHADER = " above.s * above.t * below.s * below.t);" "}"; +// the locations of the uniform variables int textureLocation; int lensCenterLocation; int screenCenterLocation; @@ -775,11 +780,27 @@ 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(); + glTranslatef(-0.151976, 0, 0); // -h, see Oculus SDK docs p. 26 + glMatrixMode(GL_MODELVIEW); glViewport(0, 0, WIDTH/2, HEIGHT); displaySide(whichCamera); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); // and the right eye to the right side + glPushMatrix(); + glTranslatef(0.151976, 0, 0); // +h + glMatrixMode(GL_MODELVIEW); glViewport(WIDTH/2, 0, WIDTH/2, HEIGHT); displaySide(whichCamera); @@ -813,19 +834,23 @@ void displayOculus(Camera& whichCamera) { glPopMatrix(); glMatrixMode(GL_PROJECTION); - glPushMatrix(); 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; + glEnable(GL_TEXTURE_2D); glUseProgramObjectARB(::oculusProgramID); glUniform1fARB(textureLocation, 0); - glUniform2fARB(lensCenterLocation, 0.25, 0.5); + glUniform2fARB(lensCenterLocation, 0.287994, 0.5); // see SDK docs, p. 29 glUniform2fARB(screenCenterLocation, 0.25, 0.5); - glUniform2fARB(scaleLocation, 0.25, 0.5); - glUniform2fARB(scaleInLocation, 4, 2); + 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); @@ -840,7 +865,7 @@ void displayOculus(Camera& whichCamera) { glVertex2f(0, HEIGHT); glEnd(); - glUniform2fARB(lensCenterLocation, 0.75, 0.5); + glUniform2fARB(lensCenterLocation, 0.787994, 0.5); glUniform2fARB(screenCenterLocation, 0.75, 0.5); glBegin(GL_QUADS); @@ -1175,7 +1200,12 @@ int setStars(int state) { } int setOculus(int state) { - return setValue(state, &::oculusOn); + bool wasOn = ::oculusOn; + int value = setValue(state, &::oculusOn); + if (::oculusOn != wasOn) { + reshape(WIDTH, HEIGHT); + } + return value; } int setStats(int state) { @@ -1492,7 +1522,7 @@ 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 == 'o') ::oculusOn = !::oculusOn; + if (k == 'o') setOculus(!::oculusOn); if (k == '[') ::viewFrustumOffsetYaw -= 0.5; if (k == ']') ::viewFrustumOffsetYaw += 0.5; @@ -1663,19 +1693,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 + 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", From cd334c2ade297ca68374b2be1741dde590769b6a Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Thu, 2 May 2013 13:13:56 -0700 Subject: [PATCH 16/52] renamed avatar skeleton from "bones" to "joints" to be more consistent with standard language. Also improved skeleton some --- interface/src/Avatar.cpp | 680 ++++++++++++++++++--------------------- interface/src/Avatar.h | 109 ++++--- 2 files changed, 390 insertions(+), 399 deletions(-) diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index cfb6fb9f6a..5ffae0115e 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -20,29 +20,6 @@ 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 THRUST_MAG = 0.0; - -const float YAW_MAG = 500.0; //JJV - changed from 300.0; -const float TEST_YAW_DECAY = 5.0; -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 COLLISION_RADIUS_SCALAR = 1.8; -const float COLLISION_BALL_FORCE = 0.6; -const float COLLISION_BODY_FORCE = 6.0; -const float COLLISION_BALL_FRICTION = 200.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}; @@ -140,7 +117,6 @@ Avatar::Avatar(bool isMine) { _renderPitch = 0.0; _sphere = NULL; _interactingOther = NULL; - //_canReachToOtherAvatar = false; _handHoldingPosition = glm::vec3( 0.0, 0.0, 0.0 ); initializeSkeleton(); @@ -162,7 +138,6 @@ Avatar::Avatar(const Avatar &otherAvatar) { _velocity = otherAvatar._velocity; _thrust = otherAvatar._thrust; _rotation = otherAvatar._rotation; - //_canReachToOtherAvatar = otherAvatar._canReachToOtherAvatar; _bodyYaw = otherAvatar._bodyYaw; _bodyPitch = otherAvatar._bodyPitch; _bodyRoll = otherAvatar._bodyRoll; @@ -328,115 +303,21 @@ bool Avatar::getIsNearInteractingOther() { void Avatar::simulate(float deltaTime) { -//keep this - I'm still using it to test things.... -/* -//TEST -static float tt = 0.0f; -tt += deltaTime * 2.0f; -//_head.leanSideways = 0.01 * sin( tt ); -_head.leanForward = 0.02 * sin( tt * 0.8 ); -*/ - // update balls if (_balls) { _balls->simulate(deltaTime); } // update avatar skeleton updateSkeleton(); - // reset hand and arm positions according to hand movement - updateHandMovement( deltaTime ); - - if ( !_avatarTouch.getAbleToReachOtherAvatar() ) { - //initialize _handHolding - _handHoldingPosition = _bone[ AVATAR_BONE_RIGHT_HAND ].position; - } - - //reset these for the next go-round - _avatarTouch.setAbleToReachOtherAvatar (false); - _avatarTouch.setHandsCloseEnoughToGrasp(false); - - // if the avatar being simulated is mine, then loop through - // all the other avatars for potential interactions... - if ( _isMine ) - { - AgentList* agentList = AgentList::getInstance(); - for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) { - if (agent->getLinkedData() != NULL && agent->getType() == AGENT_TYPE_AVATAR) { - Avatar *otherAvatar = (Avatar *)agent->getLinkedData(); - - // check for collisions with other avatars and respond - updateCollisionWithOtherAvatar(otherAvatar, deltaTime ); - - // test other avatar hand position for proximity - glm::vec3 v( _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position ); - v -= otherAvatar->getBonePosition( AVATAR_BONE_RIGHT_SHOULDER ); - - float distance = glm::length( v ); - if ( distance < _maxArmLength + _maxArmLength ) { - - _interactingOther = otherAvatar; - _avatarTouch.setAbleToReachOtherAvatar(true); - - glm::vec3 vectorBetweenHands( _bone[ AVATAR_BONE_RIGHT_HAND ].position ); - vectorBetweenHands -= otherAvatar->getBonePosition( AVATAR_BONE_RIGHT_HAND ); - float distanceBetweenHands = glm::length(vectorBetweenHands); - - if (distanceBetweenHands < _avatarTouch.HANDS_CLOSE_ENOUGH_TO_GRASP) { - _avatarTouch.setHandsCloseEnoughToGrasp(true); - } - - // if I am holding hands with another avatar, a force is applied - if (( _handState == 1 ) || ( _interactingOther->_handState == 1 )) { - - // if the hands are close enough to grasp... - if (distanceBetweenHands < _avatarTouch.HANDS_CLOSE_ENOUGH_TO_GRASP) - { - // apply the forces... - glm::vec3 vectorToOtherHand = _interactingOther->_handPosition - _handHoldingPosition; - glm::vec3 vectorToMyHand = _bone[ AVATAR_BONE_RIGHT_HAND ].position - _handHoldingPosition; - - _handHoldingPosition += vectorToOtherHand * YOUR_HAND_HOLDING_PULL; - _handHoldingPosition += vectorToMyHand * MY_HAND_HOLDING_PULL; - _bone[ AVATAR_BONE_RIGHT_HAND ].position = _handHoldingPosition; - - // apply a force to the avatar body - if ( glm::length(vectorToOtherHand) > _maxArmLength * 0.9 ) { - _velocity += vectorToOtherHand; - } - } - } - } - } - } + //update the movement of the hand and process handshaking with other avatars... + updateHandMovementAndTouching(deltaTime); - // Set the vector we send for hand position to other people to be our right hand - setHandPosition(_bone[ AVATAR_BONE_RIGHT_HAND ].position); - - }//if ( _isMine ) - - //constrain right arm length and re-adjust elbow position as it bends - updateArmIKAndConstraints( deltaTime ); - - // set hand positions for _avatarTouch.setMyHandPosition AFTER calling updateArmIKAndConstraints - if ( _interactingOther ) { - if (_isMine) { - _avatarTouch.setMyHandPosition ( _bone[ AVATAR_BONE_RIGHT_HAND ].position ); - _avatarTouch.setYourHandPosition( _interactingOther->_bone[ AVATAR_BONE_RIGHT_HAND ].position ); - _avatarTouch.setMyHandState ( _handState ); - _avatarTouch.setYourHandState ( _interactingOther->_handState ); - _avatarTouch.simulate(deltaTime); - } - } - - if (!_avatarTouch.getAbleToReachOtherAvatar() ) { - _interactingOther = NULL; - } - + // test for avatar collision response with the big sphere if (usingBigSphereCollisionTest) { - // test for avatar collision response with the big sphere updateCollisionWithSphere( _TEST_bigSpherePosition, _TEST_bigSphereRadius, deltaTime ); } + // apply gravity and collision wiht the ground/floor if ( AVATAR_GRAVITY ) { if ( _position.y > _pelvisStandingHeight + 0.01 ) { _velocity += glm::dvec3(getGravity(getPosition())) * ( 6.0 * deltaTime ); @@ -497,6 +378,112 @@ _head.leanForward = 0.02 * sin( tt * 0.8 ); } } + + +//update the movement of the hand and process handshaking with other avatars... +void Avatar::updateHandMovementAndTouching(float deltaTime) { + + // reset hand and arm positions according to hand movement + glm::vec3 transformedHandMovement + = _orientation.getRight() * _movedHandOffset.x * 2.0f + + _orientation.getUp() * -_movedHandOffset.y * 1.0f + + _orientation.getFront() * -_movedHandOffset.y * 1.0f; + + _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position += transformedHandMovement; + + if (_isMine) { + _handState = _mousePressed; + } + + //reset these for the next go-round + _avatarTouch.setAbleToReachOtherAvatar (false); + _avatarTouch.setHandsCloseEnoughToGrasp(false); + + // if the avatar being simulated is mine, then loop through + // all the other avatars for potential interactions... + if ( _isMine ) + { + AgentList* agentList = AgentList::getInstance(); + for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) { + if (agent->getLinkedData() != NULL && agent->getType() == AGENT_TYPE_AVATAR) { + Avatar *otherAvatar = (Avatar *)agent->getLinkedData(); + + // check for collisions with other avatars and respond + updateCollisionWithOtherAvatar(otherAvatar, deltaTime ); + + // test other avatar hand position for proximity + glm::vec3 v( _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].position ); + v -= otherAvatar->getJointPosition( AVATAR_JOINT_RIGHT_SHOULDER ); + + float distance = glm::length( v ); + if ( distance < _maxArmLength + _maxArmLength ) { + + _interactingOther = otherAvatar; + + if ( ! _avatarTouch.getAbleToReachOtherAvatar() ) { + //initialize _handHolding + _handHoldingPosition = _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position; + _avatarTouch.setAbleToReachOtherAvatar(true); + } + + glm::vec3 vectorBetweenHands( _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position ); + vectorBetweenHands -= otherAvatar->getJointPosition( AVATAR_JOINT_RIGHT_FINGERTIPS ); + float distanceBetweenHands = glm::length(vectorBetweenHands); + + if (distanceBetweenHands < _avatarTouch.HANDS_CLOSE_ENOUGH_TO_GRASP) { + _avatarTouch.setHandsCloseEnoughToGrasp(true); + } + + // if I am holding hands with another avatar, a force is applied + if (( _handState == 1 ) || ( _interactingOther->_handState == 1 )) { + + // if the hands are close enough to grasp... + if (distanceBetweenHands < _avatarTouch.HANDS_CLOSE_ENOUGH_TO_GRASP) + { + // apply the forces... + glm::vec3 vectorToOtherHand = _interactingOther->_handPosition - _handHoldingPosition; + glm::vec3 vectorToMyHand = _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position - _handHoldingPosition; + + _handHoldingPosition += vectorToOtherHand * YOUR_HAND_HOLDING_PULL; + _handHoldingPosition += vectorToMyHand * MY_HAND_HOLDING_PULL; + _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position = _handHoldingPosition; + + // apply a force to the avatar body + if ( glm::length(vectorToOtherHand) > _maxArmLength * 0.9 ) { + _velocity += vectorToOtherHand; + } + } + } + } + } + } + + // Set the vector we send for hand position to other people to be our right hand + setHandPosition(_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position); + + }//if ( _isMine ) + + //constrain right arm length and re-adjust elbow position as it bends + updateArmIKAndConstraints( deltaTime ); + + // set hand positions for _avatarTouch.setMyHandPosition AFTER calling updateArmIKAndConstraints + if ( _interactingOther ) { + if (_isMine) { + _avatarTouch.setMyHandPosition ( _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position ); + _avatarTouch.setYourHandPosition( _interactingOther->_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position ); + _avatarTouch.setMyHandState ( _handState ); + _avatarTouch.setYourHandState ( _interactingOther->_handState ); + _avatarTouch.simulate(deltaTime); + } + } + + if (!_avatarTouch.getAbleToReachOtherAvatar() ) { + _interactingOther = NULL; + } +} + + + void Avatar::updateHead(float deltaTime) { //apply the head lean values to the springy position... @@ -504,7 +491,7 @@ void Avatar::updateHead(float deltaTime) { glm::vec3 headLean = _orientation.getRight() * _head.leanSideways + _orientation.getFront() * _head.leanForward; - _bone[ AVATAR_BONE_HEAD ].springyPosition += headLean; + _joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition += headLean; } // Decay head back to center if turned on @@ -618,10 +605,10 @@ void Avatar::updateCollisionWithSphere( glm::vec3 position, float radius, float float distanceToBigSphere = glm::length(vectorFromMyBodyToBigSphere); if ( distanceToBigSphere < myBodyApproximateBoundingRadius + radius ) { - for (int b = 0; b < NUM_AVATAR_BONES; b++) { - glm::vec3 vectorFromJointToBigSphereCenter(_bone[b].springyPosition - position); + for (int b = 0; b < NUM_AVATAR_JOINTS; b++) { + glm::vec3 vectorFromJointToBigSphereCenter(_joint[b].springyPosition - position); float distanceToBigSphereCenter = glm::length(vectorFromJointToBigSphereCenter); - float combinedRadius = _bone[b].radius + radius; + float combinedRadius = _joint[b].radius + radius; if ( distanceToBigSphereCenter < combinedRadius ) { jointCollision = true; @@ -631,9 +618,9 @@ void Avatar::updateCollisionWithSphere( glm::vec3 position, float radius, float float penetration = 1.0 - (distanceToBigSphereCenter / combinedRadius); glm::vec3 collisionForce = vectorFromJointToBigSphereCenter * penetration; - _bone[b].springyVelocity += collisionForce * 30.0f * deltaTime; + _joint[b].springyVelocity += collisionForce * 30.0f * deltaTime; _velocity += collisionForce * 100.0f * deltaTime; - _bone[b].springyPosition = position + directionVector * combinedRadius; + _joint[b].springyPosition = position + directionVector * combinedRadius; } } } @@ -658,18 +645,18 @@ void Avatar::updateCollisionWithOtherAvatar( Avatar * otherAvatar, float deltaTi float bodyMomentum = 1.0f; glm::vec3 bodyPushForce = glm::vec3( 0.0, 0.0, 0.0 ); - // loop through the bones of each avatar to check for every possible collision - for (int b=1; b_bone[o].isCollidable ) { + for (int o=b+1; o_joint[o].isCollidable ) { - glm::vec3 vectorBetweenJoints(_bone[b].springyPosition - otherAvatar->_bone[o].springyPosition); + glm::vec3 vectorBetweenJoints(_joint[b].springyPosition - otherAvatar->_joint[o].springyPosition); float distanceBetweenJoints = glm::length(vectorBetweenJoints); if ( distanceBetweenJoints > 0.0 ) { // to avoid divide by zero - float combinedRadius = _bone[b].radius + otherAvatar->_bone[o].radius; + float combinedRadius = _joint[b].radius + otherAvatar->_joint[o].radius; // check for collision if ( distanceBetweenJoints < combinedRadius * COLLISION_RADIUS_SCALAR) { @@ -681,11 +668,11 @@ void Avatar::updateCollisionWithOtherAvatar( Avatar * otherAvatar, float deltaTi float ballMomentum = 1.0 - COLLISION_BALL_FRICTION * deltaTime; if ( ballMomentum < 0.0 ) { ballMomentum = 0.0;} - _bone[b].springyVelocity += ballPushForce; - otherAvatar->_bone[o].springyVelocity -= ballPushForce; + _joint[b].springyVelocity += ballPushForce; + otherAvatar->_joint[o].springyVelocity -= ballPushForce; - _bone[b].springyVelocity *= ballMomentum; - otherAvatar->_bone[o].springyVelocity *= ballMomentum; + _joint[b].springyVelocity *= ballMomentum; + otherAvatar->_joint[o].springyVelocity *= ballMomentum; // accumulate forces and frictions to apply to the velocities of avatar bodies bodyPushForce += directionVector * COLLISION_BODY_FORCE * deltaTime; @@ -812,19 +799,19 @@ void Avatar::renderHead(bool lookingInMirror) { glEnable(GL_RESCALE_NORMAL); // show head orientation - //renderOrientationDirections( _bone[ AVATAR_BONE_HEAD ].springyPosition, _bone[ AVATAR_BONE_HEAD ].orientation, 0.2f ); + //renderOrientationDirections( _joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition, _joint[ AVATAR_JOINT_HEAD_BASE ].orientation, 0.2f ); glPushMatrix(); if (_usingBodySprings) { - glTranslatef(_bone[ AVATAR_BONE_HEAD ].springyPosition.x, - _bone[ AVATAR_BONE_HEAD ].springyPosition.y, - _bone[ AVATAR_BONE_HEAD ].springyPosition.z); + glTranslatef(_joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition.x, + _joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition.y, + _joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition.z); } else { - glTranslatef(_bone[ AVATAR_BONE_HEAD ].position.x, - _bone[ AVATAR_BONE_HEAD ].position.y, - _bone[ AVATAR_BONE_HEAD ].position.z); + glTranslatef(_joint[ AVATAR_JOINT_HEAD_BASE ].position.x, + _joint[ AVATAR_JOINT_HEAD_BASE ].position.y, + _joint[ AVATAR_JOINT_HEAD_BASE ].position.z); } glScalef( 0.03, 0.03, 0.03 ); @@ -975,149 +962,149 @@ AvatarMode Avatar::getMode() { void Avatar::initializeSkeleton() { - for (int b=0; b 0.0f ) { glm::vec3 springDirection = springVector / length; - float force = (length - _bone[b].length) * BODY_SPRING_FORCE * deltaTime; + float force = (length - _joint[b].length) * BODY_SPRING_FORCE * deltaTime; - _bone[b].springyVelocity -= springDirection * force; + _joint[b].springyVelocity -= springDirection * force; - if ( _bone[b].parent != AVATAR_BONE_NULL ) { - _bone[_bone[b].parent].springyVelocity += springDirection * force; + if ( _joint[b].parent != AVATAR_JOINT_NULL ) { + _joint[_joint[b].parent].springyVelocity += springDirection * force; } } - _bone[b].springyVelocity += (_bone[b].position - _bone[b].springyPosition) * _bone[b].springBodyTightness * deltaTime; + _joint[b].springyVelocity += (_joint[b].position - _joint[b].springyPosition) * _joint[b].springBodyTightness * deltaTime; float decay = 1.0 - BODY_SPRING_DECAY * deltaTime; if (decay > 0.0) { - _bone[b].springyVelocity *= decay; + _joint[b].springyVelocity *= decay; } else { - _bone[b].springyVelocity = glm::vec3( 0.0f, 0.0f, 0.0f ); + _joint[b].springyVelocity = glm::vec3( 0.0f, 0.0f, 0.0f ); } - _bone[b].springyPosition += _bone[b].springyVelocity; + _joint[b].springyPosition += _joint[b].springyVelocity; } } @@ -1222,34 +1209,19 @@ const glm::vec3& Avatar::getHeadPosition() const { //if (_usingBodySprings) { - // return _bone[ AVATAR_BONE_HEAD ].springyPosition; + // return _joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition; //} - return _bone[ AVATAR_BONE_HEAD ].position; + return _joint[ AVATAR_JOINT_HEAD_BASE ].position; } -void Avatar::updateHandMovement( float deltaTime ) { - glm::vec3 transformedHandMovement; - - transformedHandMovement - = _orientation.getRight() * _movedHandOffset.x * 2.0f - + _orientation.getUp() * -_movedHandOffset.y * 1.0f - + _orientation.getFront() * -_movedHandOffset.y * 1.0f; - - _bone[ AVATAR_BONE_RIGHT_HAND ].position += transformedHandMovement; - - if (_isMine) { - _handState = _mousePressed; - } -} - void Avatar::updateArmIKAndConstraints( float deltaTime ) { // determine the arm vector - glm::vec3 armVector = _bone[ AVATAR_BONE_RIGHT_HAND ].position; - armVector -= _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position; + glm::vec3 armVector = _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position; + armVector -= _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].position; // test to see if right hand is being dragged beyond maximum arm length float distance = glm::length( armVector ); @@ -1257,30 +1229,29 @@ void Avatar::updateArmIKAndConstraints( float deltaTime ) { // don't let right hand get dragged beyond maximum arm length... if ( distance > _maxArmLength ) { // reset right hand to be constrained to maximum arm length - _bone[ AVATAR_BONE_RIGHT_HAND ].position = _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position; + _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position = _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].position; glm::vec3 armNormal = armVector / distance; armVector = armNormal * _maxArmLength; distance = _maxArmLength; - glm::vec3 constrainedPosition = _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position; + glm::vec3 constrainedPosition = _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].position; constrainedPosition += armVector; - _bone[ AVATAR_BONE_RIGHT_HAND ].position = constrainedPosition; + _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position = constrainedPosition; } // set elbow position - glm::vec3 newElbowPosition = _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position; + glm::vec3 newElbowPosition = _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].position; newElbowPosition += armVector * ONE_HALF; - glm::vec3 perpendicular = glm::cross( _orientation.getFront(), armVector ); - + glm::vec3 perpendicular = glm::cross( _orientation.getFront(), armVector ); + newElbowPosition += perpendicular * ( 1.0f - ( _maxArmLength / distance ) ) * ONE_HALF; - _bone[ AVATAR_BONE_RIGHT_UPPER_ARM ].position = newElbowPosition; + _joint[ AVATAR_JOINT_RIGHT_ELBOW ].position = newElbowPosition; // set wrist position - glm::vec3 vv( _bone[ AVATAR_BONE_RIGHT_HAND ].position ); - vv -= _bone[ AVATAR_BONE_RIGHT_UPPER_ARM ].position; - glm::vec3 newWristPosition = _bone[ AVATAR_BONE_RIGHT_UPPER_ARM ].position; - newWristPosition += vv * 0.7f; - _bone[ AVATAR_BONE_RIGHT_FOREARM ].position = newWristPosition; + glm::vec3 vv( _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position ); + vv -= _joint[ AVATAR_JOINT_RIGHT_ELBOW ].position; + glm::vec3 newWristPosition = _joint[ AVATAR_JOINT_RIGHT_ELBOW ].position + vv * 0.7f; + _joint[ AVATAR_JOINT_RIGHT_WRIST ].position = newWristPosition; } @@ -1288,41 +1259,41 @@ void Avatar::updateArmIKAndConstraints( float deltaTime ) { void Avatar::renderBody() { - // Render bone positions as spheres - for (int b = 0; b < NUM_AVATAR_BONES; b++) { + // Render joint positions as spheres + for (int b = 0; b < NUM_AVATAR_JOINTS; b++) { - if ( b != AVATAR_BONE_HEAD ) { // the head is rendered as a special case in "renderHead" + if ( b != AVATAR_JOINT_HEAD_BASE ) { // the head is rendered as a special case in "renderHead" //render bone orientation - //renderOrientationDirections( _bone[b].springyPosition, _bone[b].orientation, _bone[b].radius * 2.0 ); + //renderOrientationDirections( _joint[b].springyPosition, _joint[b].orientation, _joint[b].radius * 2.0 ); if ( _usingBodySprings ) { glColor3fv( skinColor ); glPushMatrix(); - glTranslatef( _bone[b].springyPosition.x, _bone[b].springyPosition.y, _bone[b].springyPosition.z ); - glutSolidSphere( _bone[b].radius, 20.0f, 20.0f ); + glTranslatef( _joint[b].springyPosition.x, _joint[b].springyPosition.y, _joint[b].springyPosition.z ); + glutSolidSphere( _joint[b].radius, 20.0f, 20.0f ); glPopMatrix(); } else { glColor3fv( skinColor ); glPushMatrix(); - glTranslatef( _bone[b].position.x, _bone[b].position.y, _bone[b].position.z ); - glutSolidSphere( _bone[b].radius, 20.0f, 20.0f ); + glTranslatef( _joint[b].position.x, _joint[b].position.y, _joint[b].position.z ); + glutSolidSphere( _joint[b].radius, 20.0f, 20.0f ); glPopMatrix(); } } } - // Render lines connecting the bone positions + // Render lines connecting the joint positions if ( _usingBodySprings ) { glColor3f( 0.4f, 0.5f, 0.6f ); glLineWidth(3.0); - for (int b = 1; b < NUM_AVATAR_BONES; b++) { - if ( _bone[b].parent != AVATAR_BONE_NULL ) { + for (int b = 1; b < NUM_AVATAR_JOINTS; b++) { + if ( _joint[b].parent != AVATAR_JOINT_NULL ) { glBegin( GL_LINE_STRIP ); - glVertex3fv( &_bone[ _bone[ b ].parent ].springyPosition.x ); - glVertex3fv( &_bone[ b ].springyPosition.x ); + glVertex3fv( &_joint[ _joint[ b ].parent ].springyPosition.x ); + glVertex3fv( &_joint[ b ].springyPosition.x ); glEnd(); } } @@ -1331,30 +1302,15 @@ void Avatar::renderBody() { glColor3fv( skinColor ); glLineWidth(3.0); - for (int b = 1; b < NUM_AVATAR_BONES; b++) { - if ( _bone[b].parent != AVATAR_BONE_NULL ) { + for (int b = 1; b < NUM_AVATAR_JOINTS; b++) { + if ( _joint[b].parent != AVATAR_JOINT_NULL ) { glBegin( GL_LINE_STRIP ); - glVertex3fv( &_bone[ _bone[ b ].parent ].position.x ); - glVertex3fv( &_bone[ b ].position.x); + glVertex3fv( &_joint[ _joint[ b ].parent ].position.x ); + glVertex3fv( &_joint[ b ].position.x); glEnd(); } } } - - /* - // if the hand is grasping, show it... - if (( _usingBodySprings ) && ( _handState == 1 )) { - glPushMatrix(); - glTranslatef(_bone[ AVATAR_BONE_RIGHT_HAND ].springyPosition.x, - _bone[ AVATAR_BONE_RIGHT_HAND ].springyPosition.y, - _bone[ AVATAR_BONE_RIGHT_HAND ].springyPosition.z); - glColor4f( 1.0, 1.0, 0.8, 0.3 ); glutSolidSphere( 0.020f, 10.0f, 10.0f ); - glColor4f( 1.0, 1.0, 0.4, 0.2 ); glutSolidSphere( 0.025f, 10.0f, 10.0f ); - glColor4f( 1.0, 1.0, 0.2, 0.1 ); glutSolidSphere( 0.030f, 10.0f, 10.0f ); - - glPopMatrix(); - } - */ } void Avatar::SetNewHeadTarget(float pitch, float yaw) { diff --git a/interface/src/Avatar.h b/interface/src/Avatar.h index fec8b6e4d0..c14680df4f 100644 --- a/interface/src/Avatar.h +++ b/interface/src/Avatar.h @@ -42,36 +42,71 @@ enum AvatarMode NUM_AVATAR_MODES }; -enum AvatarBoneID + +enum AvatarJointID { - AVATAR_BONE_NULL = -1, - AVATAR_BONE_PELVIS_SPINE, // connects pelvis joint with torso joint (not supposed to be rotated) - AVATAR_BONE_MID_SPINE, // connects torso joint with chest joint - AVATAR_BONE_CHEST_SPINE, // connects chest joint with neckBase joint (not supposed to be rotated) - AVATAR_BONE_NECK, // connects neckBase joint with headBase joint - AVATAR_BONE_HEAD, // connects headBase joint with headTop joint - AVATAR_BONE_LEFT_CHEST, // connects chest joint with left clavicle joint (not supposed to be rotated) - AVATAR_BONE_LEFT_SHOULDER, // connects left clavicle joint with left shoulder joint - AVATAR_BONE_LEFT_UPPER_ARM, // connects left shoulder joint with left elbow joint - AVATAR_BONE_LEFT_FOREARM, // connects left elbow joint with left wrist joint - AVATAR_BONE_LEFT_HAND, // connects left wrist joint with left fingertips joint - AVATAR_BONE_RIGHT_CHEST, // connects chest joint with right clavicle joint (not supposed to be rotated) - AVATAR_BONE_RIGHT_SHOULDER, // connects right clavicle joint with right shoulder joint - AVATAR_BONE_RIGHT_UPPER_ARM, // connects right shoulder joint with right elbow joint - AVATAR_BONE_RIGHT_FOREARM, // connects right elbow joint with right wrist joint - AVATAR_BONE_RIGHT_HAND, // connects right wrist joint with right fingertips joint - AVATAR_BONE_LEFT_PELVIS, // connects pelvis joint with left hip joint (not supposed to be rotated) - AVATAR_BONE_LEFT_THIGH, // connects left hip joint with left knee joint - AVATAR_BONE_LEFT_SHIN, // connects left knee joint with left heel joint - AVATAR_BONE_LEFT_FOOT, // connects left heel joint with left toes joint - AVATAR_BONE_RIGHT_PELVIS, // connects pelvis joint with right hip joint (not supposed to be rotated) - AVATAR_BONE_RIGHT_THIGH, // connects right hip joint with right knee joint - AVATAR_BONE_RIGHT_SHIN, // connects right knee joint with right heel joint - AVATAR_BONE_RIGHT_FOOT, // connects right heel joint with right toes joint + AVATAR_JOINT_NULL = -1, + AVATAR_JOINT_PELVIS, + AVATAR_JOINT_TORSO, + AVATAR_JOINT_CHEST, + AVATAR_JOINT_NECK_BASE, + AVATAR_JOINT_HEAD_BASE, + AVATAR_JOINT_HEAD_TOP, + + AVATAR_JOINT_LEFT_COLLAR, + AVATAR_JOINT_LEFT_SHOULDER, + AVATAR_JOINT_LEFT_ELBOW, + AVATAR_JOINT_LEFT_WRIST, + AVATAR_JOINT_LEFT_FINGERTIPS, + + AVATAR_JOINT_RIGHT_COLLAR, + AVATAR_JOINT_RIGHT_SHOULDER, + AVATAR_JOINT_RIGHT_ELBOW, + AVATAR_JOINT_RIGHT_WRIST, + AVATAR_JOINT_RIGHT_FINGERTIPS, + + AVATAR_JOINT_LEFT_HIP, + AVATAR_JOINT_LEFT_KNEE, + AVATAR_JOINT_LEFT_HEEL, + AVATAR_JOINT_LEFT_TOES, + AVATAR_JOINT_RIGHT_HIP, + AVATAR_JOINT_RIGHT_KNEE, + AVATAR_JOINT_RIGHT_HEEL, + AVATAR_JOINT_RIGHT_TOES, + + /* + AVATAR_JOINT_NULL = -1, + AVATAR_JOINT_PELVIS, + AVATAR_JOINT_TORSO, + AVATAR_JOINT_CHEST, + AVATAR_JOINT_NECK_BASE, + AVATAR_JOINT_HEAD_BASE, + AVATAR_JOINT_HEAD_TOP, + AVATAR_JOINT_LEFT_COLLAR, + AVATAR_JOINT_LEFT_SHOULDER, + AVATAR_JOINT_LEFT_ELBOW, + AVATAR_JOINT_LEFT_WRIST, + AVATAR_JOINT_LEFT_FINGERTIPS, + AVATAR_JOINT_RIGHT_COLLAR, + AVATAR_JOINT_RIGHT_SHOULDER, + AVATAR_JOINT_RIGHT_ELBOW, + AVATAR_JOINT_RIGHT_WRIST, + AVATAR_JOINT_RIGHT_FINGERTIPS, + AVATAR_JOINT_LEFT_HIP, + AVATAR_JOINT_LEFT_KNEE, + AVATAR_JOINT_LEFT_HEEL, + AVATAR_JOINT_LEFT_TOES, + AVATAR_JOINT_RIGHT_HIP, + AVATAR_JOINT_RIGHT_KNEE, + AVATAR_JOINT_RIGHT_HEEL, + AVATAR_JOINT_RIGHT_TOES, + */ + + NUM_AVATAR_JOINTS - NUM_AVATAR_BONES }; + class Avatar : public AvatarData { public: Avatar(bool isMine); @@ -103,7 +138,7 @@ public: const glm::vec3& getHeadLookatDirectionUp() const { return _orientation.getUp(); }; const glm::vec3& getHeadLookatDirectionRight() const { return _orientation.getRight(); }; const glm::vec3& getHeadPosition() const ; - const glm::vec3& getBonePosition(AvatarBoneID b) const { return _bone[b].position; }; + const glm::vec3& getJointPosition(AvatarJointID j) const { return _joint[j].position; }; const glm::vec3& getBodyUpDirection() const { return _orientation.getUp(); }; float getSpeed() const { return _speed; }; float getGirth(); @@ -117,7 +152,6 @@ public: void renderHead(bool lookingInMirror); void simulate(float); void setHandMovementValues( glm::vec3 movement ); - void updateHandMovement( float deltaTime ); void updateArmIKAndConstraints( float deltaTime ); void setDisplayingHead( bool displayingHead ); @@ -168,22 +202,22 @@ private: void setHeadReturnToCenter(bool r) { _returnHeadToCenter = r; }; const bool getHeadReturnToCenter() const { return _returnHeadToCenter; }; - struct AvatarBone + struct AvatarJoint { - AvatarBoneID parent; // which bone is this bone connected to? - glm::vec3 position; // the position at the "end" of the bone - in global space + AvatarJointID parent; // which joint is this joint connected to? + glm::vec3 position; // the position at the "end" of the joint - in global space glm::vec3 defaultPosePosition; // the parent relative position when the avatar is in the "T-pose" glm::vec3 springyPosition; // used for special effects (a 'flexible' variant of position) glm::vec3 springyVelocity; // used for special effects ( the velocity of the springy position) float springBodyTightness; // how tightly the springy position tries to stay on the position glm::quat rotation; // this will eventually replace yaw, pitch and roll (and maybe orientation) - float yaw; // the yaw Euler angle of the bone rotation off the parent - float pitch; // the pitch Euler angle of the bone rotation off the parent - float roll; // the roll Euler angle of the bone rotation off the parent + float yaw; // the yaw Euler angle of the joint rotation off the parent + float pitch; // the pitch Euler angle of the joint rotation off the parent + float roll; // the roll Euler angle of the joint rotation off the parent Orientation orientation; // three orthogonal normals determined by yaw, pitch, roll - float length; // the length of the bone + float length; // the length of the joint float radius; // used for detecting collisions for certain physical effects - bool isCollidable; // when false, the bone position will not register a collision + bool isCollidable; // when false, the joint position will not register a collision }; struct AvatarHead @@ -238,7 +272,7 @@ private: bool _usingBodySprings; glm::vec3 _movedHandOffset; glm::quat _rotation; // the rotation of the avatar body as a whole expressed as a quaternion - AvatarBone _bone[ NUM_AVATAR_BONES ]; + AvatarJoint _joint[ NUM_AVATAR_JOINTS ]; AvatarMode _mode; glm::vec3 _handHoldingPosition; glm::vec3 _velocity; @@ -272,6 +306,7 @@ private: void calculateBoneLengths(); void readSensors(); void updateHead( float deltaTime ); + void updateHandMovementAndTouching(float deltaTime); void updateCollisionWithSphere( glm::vec3 position, float radius, float deltaTime ); void updateCollisionWithOtherAvatar( Avatar * other, float deltaTime ); void setHeadFromGyros(glm::vec3 * eulerAngles, glm::vec3 * angularVelocity, float deltaTime, float smoothingTime); From 8f0dd1ffa16752bf19eab7c199e0615d9c84fbf1 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 May 2013 13:17:06 -0700 Subject: [PATCH 17/52] added render pipeline warnings menu item --- interface/src/VoxelSystem.cpp | 12 +++++++----- interface/src/VoxelSystem.h | 3 +++ interface/src/main.cpp | 11 +++++++++++ 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index ba76202822..1005da8850 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -103,7 +103,7 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { _tree->readBitstreamToTree(voxelData, numBytes - 1); double end = usecTimestampNow(); double elapsedmsec = (end - start)/1000.0; - if (elapsedmsec > 1) { + if (_renderWarningsOn && elapsedmsec > 1) { if (elapsedmsec > 1000) { double elapsedsec = (end - start)/1000000.0; printLog("WARNING! readBitstreamToTree() took %lf seconds\n",elapsedsec); @@ -155,7 +155,7 @@ void VoxelSystem::setupNewVoxelsForDrawing() { } double end = usecTimestampNow(); double elapsedmsec = (end - start)/1000.0; - if (elapsedmsec > 1) { + if (_renderWarningsOn && elapsedmsec > 1) { if (elapsedmsec > 1000) { double elapsedsec = (end - start)/1000000.0; printLog("WARNING! newTreeToArrays() took %lf seconds\n",elapsedsec); @@ -181,7 +181,7 @@ void VoxelSystem::copyWrittenDataToReadArrays() { } double end = usecTimestampNow(); double elapsedmsec = (end - start)/1000.0; - if (elapsedmsec > 1) { + if (_renderWarningsOn && elapsedmsec > 1) { if (elapsedmsec > 1000) { double elapsedsec = (end - start)/1000000.0; printLog("WARNING! copyWrittenDataToReadArrays() took %lf seconds\n",elapsedsec); @@ -260,6 +260,8 @@ VoxelSystem* VoxelSystem::clone() const { void VoxelSystem::init() { + _renderWarningsOn = false; + // When we change voxels representations in the arrays, we'll update this _voxelsDirty = false; _voxelsInArrays = 0; @@ -365,7 +367,7 @@ void VoxelSystem::updateVBOs() { } double end = usecTimestampNow(); double elapsedmsec = (end - start)/1000.0; - if (elapsedmsec > 1) { + if (_renderWarningsOn && elapsedmsec > 1) { if (elapsedmsec > 1000) { double elapsedsec = (end - start)/1000000.0; printLog("WARNING! updateVBOs() took %lf seconds\n",elapsedsec); @@ -411,7 +413,7 @@ void VoxelSystem::render() { glPopMatrix(); double end = usecTimestampNow(); double elapsedmsec = (end - start)/1000.0; - if (elapsedmsec > 1) { + if (_renderWarningsOn && elapsedmsec > 1) { if (elapsedmsec > 1000) { double elapsedsec = (end - start)/1000000.0; printLog("WARNING! render() took %lf seconds\n",elapsedsec); diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 63f3b8622e..d2c3fed499 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -59,8 +59,11 @@ public: void falseColorizeDistanceFromView(ViewFrustum* viewFrustum); void killLocalVoxels(); + void setRenderPipelineWarnings(bool on) { _renderWarningsOn = on; }; + bool getRenderPipelineWarnings() const { return _renderWarningsOn; }; private: + bool _renderWarningsOn; // Operation functions for tree recursion methods static int _nodeCount; static bool randomColorOperation(VoxelNode* node, void* extraData); diff --git a/interface/src/main.cpp b/interface/src/main.cpp index d5c28770be..2b8760abdf 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -143,6 +143,8 @@ Audio audio(&audioScope, &myAvatar); // Where one's own agent begins in the world (needs to become a dynamic thing passed to the program) glm::vec3 start_location(6.1f, 0, 1.4f); +bool renderWarningsOn = false; // Whether to show render pipeline warnings + bool statsOn = false; // Whether to show onscreen text overlay with stats bool starsOn = false; // Whether to display the stars bool paintOn = false; // Whether to paint voxels as you fly around @@ -1041,6 +1043,14 @@ int setMenu(int state) { return setValue(state, &::menuOn); } +int setRenderWarnings(int state) { + int value = setValue(state, &::renderWarningsOn); + if (state == MENU_ROW_PICKED) { + ::voxels.setRenderPipelineWarnings(::renderWarningsOn); + } + return value; +} + int setDisplayFrustum(int state) { return setValue(state, &::frustumOn); } @@ -1178,6 +1188,7 @@ void initMenu() { // Debug menuColumnDebug = menu.addColumn("Debug"); + menuColumnDebug->addRow("Show Render Pipeline Warnings", setRenderWarnings); menuColumnDebug->addRow("Kill Local Voxels", doKillLocalVoxels); menuColumnDebug->addRow("Randomize Voxel TRUE Colors", doRandomizeVoxelColors); menuColumnDebug->addRow("FALSE Color Voxels Randomly", doFalseRandomizeVoxelColors); From c353c1d2bf3517e5803a87e0d490caa5f66de8e7 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 May 2013 13:18:12 -0700 Subject: [PATCH 18/52] added command line options for packets per second and debug packet sending --- voxel-server/src/main.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 4a64da8a0f..ecccbf0291 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -38,7 +38,7 @@ const float DEATH_STAR_RADIUS = 4.0; const float MAX_CUBE = 0.05f; const int VOXEL_SEND_INTERVAL_USECS = 100 * 1000; -const int PACKETS_PER_CLIENT_PER_INTERVAL = 20; +int PACKETS_PER_CLIENT_PER_INTERVAL = 20; const int MAX_VOXEL_TREE_DEPTH_LEVELS = 4; @@ -342,7 +342,7 @@ int main(int argc, const char * argv[]) srand((unsigned)time(0)); - const char* DEBUG_VOXEL_SENDING = "--DebugVoxelSending"; + const char* DEBUG_VOXEL_SENDING = "--debugVoxelSending"; ::debugVoxelSending = cmdOptionExists(argc, argv, DEBUG_VOXEL_SENDING); printf("debugVoxelSending=%s\n", (::debugVoxelSending ? "yes" : "no")); @@ -357,6 +357,17 @@ int main(int argc, const char * argv[]) if (voxelsFilename) { randomTree.loadVoxelsFile(voxelsFilename,wantColorRandomizer); } + + // Check to see if the user passed in a command line option for setting packet send rate + const char* PACKETS_PER_SECOND = "--packetsPerSecond"; + const char* packetsPerSecond = getCmdOption(argc, argv, PACKETS_PER_SECOND); + if (packetsPerSecond) { + PACKETS_PER_CLIENT_PER_INTERVAL = atoi(packetsPerSecond)/10; + if (PACKETS_PER_CLIENT_PER_INTERVAL < 1) { + PACKETS_PER_CLIENT_PER_INTERVAL = 1; + } + printf("packetsPerSecond=%s PACKETS_PER_CLIENT_PER_INTERVAL=%d\n", packetsPerSecond, PACKETS_PER_CLIENT_PER_INTERVAL); + } const char* ADD_RANDOM_VOXELS = "--AddRandomVoxels"; if (cmdOptionExists(argc, argv, ADD_RANDOM_VOXELS)) { From 673936e14179a7a08229e7b9de17e2b9ff9c1562 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Thu, 2 May 2013 14:05:51 -0700 Subject: [PATCH 19/52] adjusted proportions of avatar skeleton to make it closer to average human --- eve/src/main.cpp | 4 +- interface/src/Avatar.cpp | 100 ++++++++++++++++++++++++--------------- interface/src/main.cpp | 2 +- 3 files changed, 64 insertions(+), 42 deletions(-) diff --git a/eve/src/main.cpp b/eve/src/main.cpp index 9ebffec7e9..30de50c284 100644 --- a/eve/src/main.cpp +++ b/eve/src/main.cpp @@ -114,7 +114,7 @@ int main(int argc, const char* argv[]) { // pick a random point inside a 10x10 grid eve.setPosition(glm::vec3(randFloatInRange(-RANDOM_POSITION_MAX_DIMENSION, RANDOM_POSITION_MAX_DIMENSION), - 0.32, // this is the same as the pelvis standing height (as of 4/26/13) + 1.33, // this should be the same as the avatar's pelvis standing height randFloatInRange(-RANDOM_POSITION_MAX_DIMENSION, RANDOM_POSITION_MAX_DIMENSION))); // face any instance of eve down the z-axis @@ -122,7 +122,7 @@ int main(int argc, const char* argv[]) { // put her hand out so somebody can shake it eve.setHandPosition(glm::vec3(eve.getPosition()[0] - 0.2, - 0.25, + 0.5, eve.getPosition()[2] + 0.1)); // read eve's audio data AudioInjector eveAudioInjector("/etc/highfidelity/eve/resources/eve.raw"); diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 5ffae0115e..8cca1a7a9a 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -69,7 +69,7 @@ Avatar::Avatar(bool isMine) { _speed = 0.0; _pelvisStandingHeight = 0.0f; _displayingHead = true; - _TEST_bigSphereRadius = 0.3f; + _TEST_bigSphereRadius = 0.4f; _TEST_bigSpherePosition = glm::vec3( 0.0f, _TEST_bigSphereRadius, 2.0f ); for (int i = 0; i < MAX_DRIVE_KEYS; i++) _driveKeys[i] = false; @@ -814,7 +814,13 @@ void Avatar::renderHead(bool lookingInMirror) { _joint[ AVATAR_JOINT_HEAD_BASE ].position.z); } - glScalef( 0.03, 0.03, 0.03 ); + glScalef + ( + _joint[ AVATAR_JOINT_HEAD_BASE ].radius, + _joint[ AVATAR_JOINT_HEAD_BASE ].radius, + _joint[ AVATAR_JOINT_HEAD_BASE ].radius + ); + if (lookingInMirror) { glRotatef(_bodyYaw - _headYaw, 0, 1, 0); @@ -826,7 +832,7 @@ void Avatar::renderHead(bool lookingInMirror) { glRotatef(_bodyRoll + _headRoll, 0, 0, 1); } - glScalef(2.0, 2.0, 2.0); + //glScalef(2.0, 2.0, 2.0); glColor3fv(skinColor); glutSolidSphere(1, 30, 30); @@ -1006,50 +1012,58 @@ void Avatar::initializeSkeleton() { // specify the default pose position _joint[ AVATAR_JOINT_PELVIS ].defaultPosePosition = glm::vec3( 0.0, 0.0, 0.0 ); - _joint[ AVATAR_JOINT_TORSO ].defaultPosePosition = glm::vec3( 0.0, 0.05, 0.0 ); - _joint[ AVATAR_JOINT_CHEST ].defaultPosePosition = glm::vec3( 0.0, 0.06, 0.0 ); - _joint[ AVATAR_JOINT_NECK_BASE ].defaultPosePosition = glm::vec3( 0.0, 0.06, 0.0 ); - _joint[ AVATAR_JOINT_HEAD_BASE ].defaultPosePosition = glm::vec3( 0.0, 0.1, 0.0 ); - _joint[ AVATAR_JOINT_LEFT_COLLAR ].defaultPosePosition = glm::vec3( -0.05, 0.02, 0.0 ); - _joint[ AVATAR_JOINT_LEFT_SHOULDER ].defaultPosePosition = glm::vec3( -0.03, 0.0, 0.0 ); - _joint[ AVATAR_JOINT_LEFT_ELBOW ].defaultPosePosition = glm::vec3( 0.0, -0.1, 0.0 ); - _joint[ AVATAR_JOINT_LEFT_WRIST ].defaultPosePosition = glm::vec3( 0.0, -0.1, 0.0 ); - _joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].defaultPosePosition = glm::vec3( 0.0, -0.05, 0.0 ); - _joint[ AVATAR_JOINT_RIGHT_COLLAR ].defaultPosePosition = glm::vec3( 0.05, 0.02, 0.0 ); - _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].defaultPosePosition = glm::vec3( 0.03, 0.0, 0.0 ); - _joint[ AVATAR_JOINT_RIGHT_ELBOW ].defaultPosePosition = glm::vec3( 0.0, -0.1, 0.0 ); - _joint[ AVATAR_JOINT_RIGHT_WRIST ].defaultPosePosition = glm::vec3( 0.0, -0.1, 0.0 ); - _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].defaultPosePosition = glm::vec3( 0.0, -0.05, 0.0 ); - _joint[ AVATAR_JOINT_LEFT_HIP ].defaultPosePosition = glm::vec3( -0.03, 0.0, 0.0 ); - _joint[ AVATAR_JOINT_LEFT_KNEE ].defaultPosePosition = glm::vec3( 0.0, -0.15, 0.0 ); - _joint[ AVATAR_JOINT_LEFT_HEEL ].defaultPosePosition = glm::vec3( 0.0, -0.15, 0.0 ); + _joint[ AVATAR_JOINT_TORSO ].defaultPosePosition = glm::vec3( 0.0, 0.08, 0.0 ); + _joint[ AVATAR_JOINT_CHEST ].defaultPosePosition = glm::vec3( 0.0, 0.09, 0.0 ); + _joint[ AVATAR_JOINT_NECK_BASE ].defaultPosePosition = glm::vec3( 0.0, 0.1, 0.0 ); + _joint[ AVATAR_JOINT_HEAD_BASE ].defaultPosePosition = glm::vec3( 0.0, 0.08, 0.0 ); + + _joint[ AVATAR_JOINT_LEFT_COLLAR ].defaultPosePosition = glm::vec3( -0.06, 0.04, 0.0 ); + _joint[ AVATAR_JOINT_LEFT_SHOULDER ].defaultPosePosition = glm::vec3( -0.04, 0.0, 0.0 ); + _joint[ AVATAR_JOINT_LEFT_ELBOW ].defaultPosePosition = glm::vec3( 0.0, -0.13, 0.0 ); + _joint[ AVATAR_JOINT_LEFT_WRIST ].defaultPosePosition = glm::vec3( 0.0, -0.11, 0.0 ); + _joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].defaultPosePosition = glm::vec3( 0.0, -0.07, 0.0 ); + + _joint[ AVATAR_JOINT_RIGHT_COLLAR ].defaultPosePosition = glm::vec3( 0.06, 0.04, 0.0 ); + _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].defaultPosePosition = glm::vec3( 0.04, 0.0, 0.0 ); + _joint[ AVATAR_JOINT_RIGHT_ELBOW ].defaultPosePosition = glm::vec3( 0.0, -0.13, 0.0 ); + _joint[ AVATAR_JOINT_RIGHT_WRIST ].defaultPosePosition = glm::vec3( 0.0, -0.11, 0.0 ); + _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].defaultPosePosition = glm::vec3( 0.0, -0.07, 0.0 ); + + _joint[ AVATAR_JOINT_LEFT_HIP ].defaultPosePosition = glm::vec3( -0.05, 0.0, 0.0 ); + _joint[ AVATAR_JOINT_LEFT_KNEE ].defaultPosePosition = glm::vec3( 0.0, -0.22, 0.0 ); + _joint[ AVATAR_JOINT_LEFT_HEEL ].defaultPosePosition = glm::vec3( 0.0, -0.22, 0.0 ); _joint[ AVATAR_JOINT_LEFT_TOES ].defaultPosePosition = glm::vec3( 0.0, 0.0, 0.04 ); - _joint[ AVATAR_JOINT_RIGHT_HIP ].defaultPosePosition = glm::vec3( 0.03, 0.0, 0.0 ); - _joint[ AVATAR_JOINT_RIGHT_KNEE ].defaultPosePosition = glm::vec3( 0.0, -0.15, 0.0 ); - _joint[ AVATAR_JOINT_RIGHT_HEEL ].defaultPosePosition = glm::vec3( 0.0, -0.15, 0.0 ); + + _joint[ AVATAR_JOINT_RIGHT_HIP ].defaultPosePosition = glm::vec3( 0.05, 0.0, 0.0 ); + _joint[ AVATAR_JOINT_RIGHT_KNEE ].defaultPosePosition = glm::vec3( 0.0, -0.22, 0.0 ); + _joint[ AVATAR_JOINT_RIGHT_HEEL ].defaultPosePosition = glm::vec3( 0.0, -0.22, 0.0 ); _joint[ AVATAR_JOINT_RIGHT_TOES ].defaultPosePosition = glm::vec3( 0.0, 0.0, 0.04 ); // specify the radii of the bone positions - _joint[ AVATAR_JOINT_PELVIS ].radius = 0.05; - _joint[ AVATAR_JOINT_TORSO ].radius = 0.04; - _joint[ AVATAR_JOINT_CHEST ].radius = 0.06; - _joint[ AVATAR_JOINT_NECK_BASE ].radius = 0.02; - _joint[ AVATAR_JOINT_HEAD_BASE ].radius = 0.02; - _joint[ AVATAR_JOINT_LEFT_COLLAR ].radius = 0.025; - _joint[ AVATAR_JOINT_LEFT_SHOULDER ].radius = 0.02; - _joint[ AVATAR_JOINT_LEFT_ELBOW ].radius = 0.015; - _joint[ AVATAR_JOINT_LEFT_WRIST ].radius = 0.015; + _joint[ AVATAR_JOINT_PELVIS ].radius = 0.06; + _joint[ AVATAR_JOINT_TORSO ].radius = 0.055; + _joint[ AVATAR_JOINT_CHEST ].radius = 0.075; + _joint[ AVATAR_JOINT_NECK_BASE ].radius = 0.03; + _joint[ AVATAR_JOINT_HEAD_BASE ].radius = 0.07; + + _joint[ AVATAR_JOINT_LEFT_COLLAR ].radius = 0.027; + _joint[ AVATAR_JOINT_LEFT_SHOULDER ].radius = 0.023; + _joint[ AVATAR_JOINT_LEFT_ELBOW ].radius = 0.017; + _joint[ AVATAR_JOINT_LEFT_WRIST ].radius = 0.017; _joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].radius = 0.01; - _joint[ AVATAR_JOINT_RIGHT_COLLAR ].radius = 0.025; - _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].radius = 0.02; + + _joint[ AVATAR_JOINT_RIGHT_COLLAR ].radius = 0.027; + _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].radius = 0.023; _joint[ AVATAR_JOINT_RIGHT_ELBOW ].radius = 0.015; _joint[ AVATAR_JOINT_RIGHT_WRIST ].radius = 0.015; _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].radius = 0.01; - _joint[ AVATAR_JOINT_LEFT_HIP ].radius = 0.02; + + _joint[ AVATAR_JOINT_LEFT_HIP ].radius = 0.03; _joint[ AVATAR_JOINT_LEFT_KNEE ].radius = 0.02; _joint[ AVATAR_JOINT_LEFT_HEEL ].radius = 0.015; _joint[ AVATAR_JOINT_LEFT_TOES ].radius = 0.02; - _joint[ AVATAR_JOINT_RIGHT_HIP ].radius = 0.02; + + _joint[ AVATAR_JOINT_RIGHT_HIP ].radius = 0.03; _joint[ AVATAR_JOINT_RIGHT_KNEE ].radius = 0.02; _joint[ AVATAR_JOINT_RIGHT_HEEL ].radius = 0.015; _joint[ AVATAR_JOINT_RIGHT_TOES ].radius = 0.02; @@ -1091,14 +1105,16 @@ void Avatar::initializeSkeleton() { calculateBoneLengths(); _pelvisStandingHeight = - _joint[ AVATAR_JOINT_LEFT_TOES ].radius + + _joint[ AVATAR_JOINT_LEFT_HEEL ].radius + _joint[ AVATAR_JOINT_LEFT_HEEL ].length + - _joint[ AVATAR_JOINT_LEFT_KNEE ].length + - _joint[ AVATAR_JOINT_PELVIS ].length; + _joint[ AVATAR_JOINT_LEFT_KNEE ].length; _height = ( _pelvisStandingHeight + + _joint[ AVATAR_JOINT_LEFT_HEEL ].radius + + _joint[ AVATAR_JOINT_LEFT_HEEL ].length + + _joint[ AVATAR_JOINT_LEFT_KNEE ].length + _joint[ AVATAR_JOINT_PELVIS ].length + _joint[ AVATAR_JOINT_TORSO ].length + _joint[ AVATAR_JOINT_CHEST ].length + @@ -1107,6 +1123,12 @@ void Avatar::initializeSkeleton() { _joint[ AVATAR_JOINT_HEAD_BASE ].radius ); + printf( "_height = %f\n", _height ); + + + + + // generate world positions updateSkeleton(); } diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 08b1666d05..e3788ec236 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -728,7 +728,7 @@ void display(void) float thirdPersonPitch = 0.0f; float thirdPersonUpShift = -0.1f; - float thirdPersonDistance = 1.f; + float thirdPersonDistance = 1.2f; float thirdPersonTightness = 8.0f; if ( USING_FIRST_PERSON_EFFECT ) { From 5de15dd5a4c535a531095b0ef66e2aa4bad19808 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 2 May 2013 14:39:00 -0700 Subject: [PATCH 20/52] Final bits for Oculus support. Works! --- interface/src/main.cpp | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 6fe0bab8ff..628b4ae952 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -102,7 +102,7 @@ int packetsPerSecond = 0; int bytesPerSecond = 0; int bytesCount = 0; -int WIDTH = 1200; // Window size +int WIDTH = 1280; // Window size int HEIGHT = 800; int fullscreen = 0; float aspectRatio = 1.0f; @@ -177,7 +177,7 @@ 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 GLuint oculusProgramID = 0; // The GLSL program containing the distortion shader -float oculusDistortionScale = 1.5f; // Controls the Oculus field of view +float oculusDistortionScale = 1.25; // Controls the Oculus field of view // // Serial USB Variables @@ -778,20 +778,30 @@ void displayOculus(Camera& whichCamera) { // render the left eye view to the left side of the screen glMatrixMode(GL_PROJECTION); glPushMatrix(); - glTranslatef(-0.151976, 0, 0); // -h, see Oculus SDK docs p. 26 + 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); + glMatrixMode(GL_MODELVIEW); glViewport(0, 0, WIDTH/2, HEIGHT); displaySide(whichCamera); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - + // and the right eye to the right side - glPushMatrix(); - glTranslatef(0.151976, 0, 0); // +h + 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); @@ -819,8 +829,6 @@ void displayOculus(Camera& whichCamera) { } glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, WIDTH, HEIGHT); - glPopMatrix(); - glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, WIDTH, 0, HEIGHT); @@ -868,6 +876,7 @@ void displayOculus(Camera& whichCamera) { glEnd(); glDisable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, 0); glUseProgramObjectARB(0); glPopMatrix(); @@ -1691,7 +1700,7 @@ void reshape(int width, int height) if (::oculusOn) { // more magic numbers; see Oculus SDK docs, p. 32 - aspectRatio *= 0.5; + camera.setAspectRatio(aspectRatio *= 0.5); camera.setFieldOfView(fov = 2 * atan((0.0468 * ::oculusDistortionScale) / 0.041) * (180 / PI)); } else { @@ -1808,6 +1817,8 @@ 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)); } + + fullscreen = cmdOptionExists(argc, argv, "--fullscreen"); // the callback for our instance of AgentList is attachNewHeadToAgent AgentList::getInstance()->linkedDataCreateCallback = &attachNewHeadToAgent; From 762c635744e4a4ab7245afbe47def2bede01ebe2 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 2 May 2013 14:44:03 -0700 Subject: [PATCH 21/52] Restored constant value added another reference to the SDK docs. --- interface/src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 628b4ae952..27e6a39354 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -102,7 +102,7 @@ int packetsPerSecond = 0; int bytesPerSecond = 0; int bytesCount = 0; -int WIDTH = 1280; // Window size +int WIDTH = 1200; // Window size int HEIGHT = 800; int fullscreen = 0; float aspectRatio = 1.0f; @@ -782,7 +782,7 @@ void displayOculus(Camera& whichCamera) { 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); + glTranslatef(0.032, 0, 0); // dip/2, see p. 27 glMatrixMode(GL_MODELVIEW); glViewport(0, 0, WIDTH/2, HEIGHT); From ccded56ecf8a1b34c2dcca70450c32b56063ce30 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 2 May 2013 15:20:29 -0700 Subject: [PATCH 22/52] Use the right type here; Xcode complains about it. --- interface/src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 27e6a39354..d039866b8c 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -176,7 +176,7 @@ 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 -GLuint oculusProgramID = 0; // The GLSL program containing the distortion shader +GLhandleARB oculusProgramID = 0; // The GLSL program containing the distortion shader float oculusDistortionScale = 1.25; // Controls the Oculus field of view // @@ -811,7 +811,7 @@ void displayOculus(Camera& whichCamera) { 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); - GLuint shaderID = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); + GLhandleARB shaderID = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); glShaderSourceARB(shaderID, 1, &DISTORTION_FRAGMENT_SHADER, 0); glCompileShaderARB(shaderID); ::oculusProgramID = glCreateProgramObjectARB(); From 8e2c43e983030b1497b930d135345183416f559b Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 2 May 2013 15:54:58 -0700 Subject: [PATCH 23/52] Need to disable blending when we render the distorted screen quad. --- interface/src/main.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index d039866b8c..957b93e453 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -840,6 +840,7 @@ void displayOculus(Camera& whichCamera) { float scaleFactor = 1.0 / ::oculusDistortionScale; float aspectRatio = (WIDTH * 0.5) / HEIGHT; + glDisable(GL_BLEND); glEnable(GL_TEXTURE_2D); glUseProgramObjectARB(::oculusProgramID); glUniform1fARB(textureLocation, 0); @@ -874,7 +875,8 @@ void displayOculus(Camera& whichCamera) { glTexCoord2f(0.5, 1); glVertex2f(WIDTH/2, HEIGHT); glEnd(); - + + glEnable(GL_BLEND); glDisable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); glUseProgramObjectARB(0); From 5a14c71225c8a506773ced4073f1d9e4101a4c34 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 May 2013 15:57:31 -0700 Subject: [PATCH 24/52] added dirty bit support to VoxelTree, use it to determine when to call treeToArrays --- interface/src/VoxelSystem.cpp | 9 +++++++-- libraries/voxels/src/VoxelNode.cpp | 2 ++ libraries/voxels/src/VoxelTree.cpp | 26 +++++++++++++++++++++----- libraries/voxels/src/VoxelTree.h | 5 +++++ 4 files changed, 35 insertions(+), 7 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 1005da8850..5ee098a775 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -149,7 +149,12 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { void VoxelSystem::setupNewVoxelsForDrawing() { double start = usecTimestampNow(); - _voxelsUpdated = newTreeToArrays(_tree->rootNode); + if (_tree->isDirty()) { + _voxelsUpdated = newTreeToArrays(_tree->rootNode); + _tree->clearDirtyBit(); // after we pull the trees into the array, we can consider the tree clean + } else { + _voxelsUpdated = 0; + } if (_voxelsUpdated) { _voxelsDirty=true; } @@ -248,8 +253,8 @@ int VoxelSystem::newTreeToArrays(VoxelNode* node) { _voxelsInArrays++; // our know vertices in the arrays } voxelsUpdated++; - node->clearDirtyBit(); } + node->clearDirtyBit(); // always clear the dirty bit, even if it doesn't need to be rendered return voxelsUpdated; } diff --git a/libraries/voxels/src/VoxelNode.cpp b/libraries/voxels/src/VoxelNode.cpp index 776aec7a9a..80da795fe1 100644 --- a/libraries/voxels/src/VoxelNode.cpp +++ b/libraries/voxels/src/VoxelNode.cpp @@ -143,6 +143,8 @@ void VoxelNode::setFalseColored(bool isFalseColored) { void VoxelNode::setColor(const nodeColor& color) { if (_trueColor[0] != color[0] || _trueColor[1] != color[1] || _trueColor[2] != color[2]) { + //printLog("VoxelNode::setColor() was: (%d,%d,%d) is: (%d,%d,%d)\n", + // _trueColor[0],_trueColor[1],_trueColor[2],color[0],color[1],color[2]); memcpy(&_trueColor,&color,sizeof(nodeColor)); if (!_falseColored) { memcpy(&_currentColor,&color,sizeof(nodeColor)); diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index ba13ee1c28..f781c16b0d 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -35,7 +35,8 @@ VoxelTree::VoxelTree() : voxelsBytesRead(0), voxelsCreatedStats(100), voxelsColoredStats(100), - voxelsBytesReadStats(100) { + voxelsBytesReadStats(100), + _isDirty(true) { rootNode = new VoxelNode(); rootNode->octalCode = new unsigned char[1]; @@ -127,10 +128,13 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, // check the colors mask to see if we have a child to color in if (oneAtBit(*nodeData, i)) { // create the child if it doesn't exist - if (destinationNode->children[i] == NULL) { + if (!destinationNode->children[i]) { destinationNode->addChildAtIndex(i); - this->voxelsCreated++; - this->voxelsCreatedStats.updateAverage(1); + if (destinationNode->isDirty()) { + _isDirty = true; + } + voxelsCreated++; + voxelsCreatedStats.updateAverage(1); } // pull the color for this child @@ -138,6 +142,9 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, memcpy(newColor, nodeData + bytesRead, 3); newColor[3] = 1; destinationNode->children[i]->setColor(newColor); + if (destinationNode->children[i]->isDirty()) { + _isDirty = true; + } this->voxelsColored++; this->voxelsColoredStats.updateAverage(1); @@ -146,6 +153,9 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, } // average node's color based on color of children destinationNode->setColorFromAverageOfChildren(); + if (destinationNode->isDirty()) { + _isDirty = true; + } // give this destination node the child mask from the packet unsigned char childMask = *(nodeData + bytesRead); @@ -157,9 +167,12 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, // check the exists mask to see if we have a child to traverse into if (oneAtBit(childMask, childIndex)) { - if (destinationNode->children[childIndex] == NULL) { + if (!destinationNode->children[childIndex]) { // add a child at that index, if it doesn't exist destinationNode->addChildAtIndex(childIndex); + if (destinationNode->isDirty()) { + _isDirty = true; + } this->voxelsCreated++; this->voxelsCreatedStats.updateAverage(this->voxelsCreated); } @@ -193,6 +206,9 @@ void VoxelTree::readBitstreamToTree(unsigned char * bitstream, int bufferSizeByt // Note: we need to create this node relative to root, because we're assuming that the bitstream for the initial // octal code is always relative to root! bitstreamRootNode = createMissingNode(rootNode, (unsigned char*) bitstreamAt); + if (bitstreamRootNode->isDirty()) { + _isDirty = true; + } } int octalCodeBytes = bytesRequiredForCodeLength(*bitstreamAt); diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index 7f5a6b866b..1209868c62 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -54,6 +54,9 @@ public: VoxelNodeBag& bag); int searchForColoredNodes(int maxSearchLevel, VoxelNode* node, const ViewFrustum& viewFrustum, VoxelNodeBag& bag); + + bool isDirty() const { return _isDirty; }; + void clearDirtyBit() { _isDirty = false; }; private: int encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel, @@ -68,6 +71,8 @@ private: VoxelNode* nodeForOctalCode(VoxelNode* ancestorNode, unsigned char* needleCode, VoxelNode** parentOfFoundNode); VoxelNode* createMissingNode(VoxelNode* lastParentNode, unsigned char* deepestCodeToCreate); int readNodeData(VoxelNode *destinationNode, unsigned char* nodeData, int bufferSizeBytes); + + bool _isDirty; }; int boundaryDistanceForRenderLevel(unsigned int renderLevel); From 905064239012bad8b1f312bf8569d48d846f4737 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 2 May 2013 16:11:34 -0700 Subject: [PATCH 25/52] add pairing device to vector after creation --- pairing-server/src/main.cpp | 43 +++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/pairing-server/src/main.cpp b/pairing-server/src/main.cpp index 729946527b..0586bb9411 100644 --- a/pairing-server/src/main.cpp +++ b/pairing-server/src/main.cpp @@ -10,6 +10,7 @@ #include #include +#include const int PAIRING_SERVER_LISTEN_PORT = 52934; const int MAX_PACKET_SIZE_BYTES = 1400; @@ -17,9 +18,19 @@ const int MAX_PACKET_SIZE_BYTES = 1400; struct PairableDevice { char identifier[64]; char name[64]; - sockaddr localSocket; + sockaddr_in localSocket; }; +int indexOfFirstOccurenceOfCharacter(char* haystack, char needle) { + int currentIndex = 0; + + while (haystack[currentIndex] != '\0' && haystack[currentIndex] != needle) { + currentIndex++; + } + + return currentIndex; +} + int main(int argc, const char* argv[]) { UDPSocket serverSocket(PAIRING_SERVER_LISTEN_PORT); @@ -31,9 +42,33 @@ int main(int argc, const char* argv[]) { while (true) { if (serverSocket.receive(&deviceAddress, &deviceData, &receivedBytes)) { + // create a new PairableDevice + PairableDevice newDevice = {}; + int addressBytes[4]; + int socketPort = 0; + + sscanf(deviceData, "A %s %d.%d.%d.%d:%d %s", + newDevice.identifier, + &addressBytes[3], + &addressBytes[2], + &addressBytes[1], + &addressBytes[0], + &socketPort, + newDevice.name); + + // setup the localSocket for the pairing device + newDevice.localSocket.sin_family = AF_INET; + newDevice.localSocket.sin_addr.s_addr = (addressBytes[3] | + addressBytes[2] << 8 | + addressBytes[1] << 16 | + addressBytes[0] << 24); + newDevice.localSocket.sin_port = socketPort; + + // push this new device into the vector + printf("Adding device %s (%s) to list\n", newDevice.identifier, newDevice.name); + devices.push_back(newDevice); } } -} - - + +} \ No newline at end of file From e5cd66313a68634d20e9ac670f4c0a5400295ce9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 2 May 2013 16:28:19 -0700 Subject: [PATCH 26/52] check the number of sscanf matches, store sending socket for device to reply --- pairing-server/src/main.cpp | 50 +++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/pairing-server/src/main.cpp b/pairing-server/src/main.cpp index 0586bb9411..4383efe1ad 100644 --- a/pairing-server/src/main.cpp +++ b/pairing-server/src/main.cpp @@ -18,6 +18,7 @@ const int MAX_PACKET_SIZE_BYTES = 1400; struct PairableDevice { char identifier[64]; char name[64]; + sockaddr_in sendingSocket; sockaddr_in localSocket; }; @@ -34,40 +35,47 @@ int indexOfFirstOccurenceOfCharacter(char* haystack, char needle) { int main(int argc, const char* argv[]) { UDPSocket serverSocket(PAIRING_SERVER_LISTEN_PORT); - sockaddr deviceAddress; + sockaddr_in deviceAddress; char deviceData[MAX_PACKET_SIZE_BYTES] = {}; ssize_t receivedBytes = 0; std::vector devices; while (true) { - if (serverSocket.receive(&deviceAddress, &deviceData, &receivedBytes)) { + if (serverSocket.receive((sockaddr *)&deviceAddress, &deviceData, &receivedBytes)) { // create a new PairableDevice PairableDevice newDevice = {}; int addressBytes[4]; int socketPort = 0; - sscanf(deviceData, "A %s %d.%d.%d.%d:%d %s", - newDevice.identifier, - &addressBytes[3], - &addressBytes[2], - &addressBytes[1], - &addressBytes[0], - &socketPort, - newDevice.name); + int numMatches = sscanf(deviceData, "A %s %d.%d.%d.%d:%d %s", + newDevice.identifier, + &addressBytes[3], + &addressBytes[2], + &addressBytes[1], + &addressBytes[0], + &socketPort, + newDevice.name); - // setup the localSocket for the pairing device - newDevice.localSocket.sin_family = AF_INET; - newDevice.localSocket.sin_addr.s_addr = (addressBytes[3] | - addressBytes[2] << 8 | - addressBytes[1] << 16 | - addressBytes[0] << 24); - newDevice.localSocket.sin_port = socketPort; - - // push this new device into the vector - printf("Adding device %s (%s) to list\n", newDevice.identifier, newDevice.name); - devices.push_back(newDevice); + if (numMatches >= 6) { + // if we have fewer than 6 matches the packet wasn't properly formatted + + // setup the localSocket for the pairing device + newDevice.localSocket.sin_family = AF_INET; + newDevice.localSocket.sin_addr.s_addr = (addressBytes[3] | + addressBytes[2] << 8 | + addressBytes[1] << 16 | + addressBytes[0] << 24); + newDevice.localSocket.sin_port = socketPort; + + // store this device's sending socket so we can talk back to it + newDevice.sendingSocket = deviceAddress; + + // push this new device into the vector + printf("Adding device %s (%s) to list\n", newDevice.identifier, newDevice.name); + devices.push_back(newDevice); + } } } From fcce4753c9f85d2a7e82a868d52bd7b16c704a6f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 May 2013 16:37:31 -0700 Subject: [PATCH 27/52] more optimizations on render pipeline --- interface/src/VoxelSystem.cpp | 33 +++++++++++++++++++++--------- interface/src/VoxelSystem.h | 2 ++ libraries/voxels/src/VoxelNode.cpp | 12 ++++++++--- 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 5ee098a775..2195c7fe1a 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -150,6 +150,7 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { void VoxelSystem::setupNewVoxelsForDrawing() { double start = usecTimestampNow(); if (_tree->isDirty()) { + _callsToTreesToArrays++; _voxelsUpdated = newTreeToArrays(_tree->rootNode); _tree->clearDirtyBit(); // after we pull the trees into the array, we can consider the tree clean } else { @@ -163,14 +164,16 @@ void VoxelSystem::setupNewVoxelsForDrawing() { if (_renderWarningsOn && elapsedmsec > 1) { if (elapsedmsec > 1000) { double elapsedsec = (end - start)/1000000.0; - printLog("WARNING! newTreeToArrays() took %lf seconds\n",elapsedsec); + printLog("WARNING! newTreeToArrays() took %lf seconds %ld voxels updated\n", elapsedsec, _voxelsUpdated); } else { - printLog("WARNING! newTreeToArrays() took %lf milliseconds\n",elapsedmsec); + printLog("WARNING! newTreeToArrays() took %lf milliseconds %ld voxels updated\n", elapsedmsec, _voxelsUpdated); } } - // copy the newly written data to the arrays designated for reading - copyWrittenDataToReadArrays(); + if (_voxelsDirty) { + // copy the newly written data to the arrays designated for reading + copyWrittenDataToReadArrays(); + } } void VoxelSystem::copyWrittenDataToReadArrays() { @@ -189,9 +192,11 @@ void VoxelSystem::copyWrittenDataToReadArrays() { if (_renderWarningsOn && elapsedmsec > 1) { if (elapsedmsec > 1000) { double elapsedsec = (end - start)/1000000.0; - printLog("WARNING! copyWrittenDataToReadArrays() took %lf seconds\n",elapsedsec); + printLog("WARNING! copyWrittenDataToReadArrays() took %lf seconds for %ld voxels %ld updated\n", + elapsedsec, _voxelsInArrays, _voxelsUpdated); } else { - printLog("WARNING! copyWrittenDataToReadArrays() took %lf milliseconds\n",elapsedmsec); + printLog("WARNING! copyWrittenDataToReadArrays() took %lf milliseconds for %ld voxels %ld updated\n", + elapsedmsec, _voxelsInArrays, _voxelsUpdated); } } } @@ -266,6 +271,7 @@ VoxelSystem* VoxelSystem::clone() const { void VoxelSystem::init() { _renderWarningsOn = false; + _callsToTreesToArrays = 0; // When we change voxels representations in the arrays, we'll update this _voxelsDirty = false; @@ -373,13 +379,20 @@ void VoxelSystem::updateVBOs() { double end = usecTimestampNow(); double elapsedmsec = (end - start)/1000.0; if (_renderWarningsOn && elapsedmsec > 1) { - if (elapsedmsec > 1000) { - double elapsedsec = (end - start)/1000000.0; - printLog("WARNING! updateVBOs() took %lf seconds\n",elapsedsec); + if (elapsedmsec > 1) { + if (elapsedmsec > 1000) { + double elapsedsec = (end - start)/1000000.0; + printLog("WARNING! updateVBOs() took %lf seconds after %d calls to newTreeToArrays()\n", + elapsedsec, _callsToTreesToArrays); + } else { + printLog("WARNING! updateVBOs() took %lf milliseconds after %d calls to newTreeToArrays()\n", + elapsedmsec, _callsToTreesToArrays); + } } else { - printLog("WARNING! updateVBOs() took %lf milliseconds\n",elapsedmsec); + printLog("WARNING! updateVBOs() called after %d calls to newTreeToArrays()\n",_callsToTreesToArrays); } } + _callsToTreesToArrays = 0; // clear it } void VoxelSystem::render() { diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index d2c3fed499..949417cf3b 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -63,6 +63,8 @@ public: bool getRenderPipelineWarnings() const { return _renderWarningsOn; }; private: + int _callsToTreesToArrays; + bool _renderWarningsOn; // Operation functions for tree recursion methods static int _nodeCount; diff --git a/libraries/voxels/src/VoxelNode.cpp b/libraries/voxels/src/VoxelNode.cpp index 80da795fe1..7e411d9c4b 100644 --- a/libraries/voxels/src/VoxelNode.cpp +++ b/libraries/voxels/src/VoxelNode.cpp @@ -125,7 +125,9 @@ void VoxelNode::setFalseColor(colorPart red, colorPart green, colorPart blue) { _currentColor[1] = green; _currentColor[2] = blue; _currentColor[3] = 1; // XXXBHG - False colors are always considered set - _isDirty = true; + if (_shouldRender) { + _isDirty = true; + } } } @@ -136,7 +138,9 @@ void VoxelNode::setFalseColored(bool isFalseColored) { memcpy(&_currentColor,&_trueColor,sizeof(nodeColor)); } _falseColored = isFalseColored; - _isDirty = true; + if (_shouldRender) { + _isDirty = true; + } } }; @@ -149,7 +153,9 @@ void VoxelNode::setColor(const nodeColor& color) { if (!_falseColored) { memcpy(&_currentColor,&color,sizeof(nodeColor)); } - _isDirty = true; + if (_shouldRender) { + _isDirty = true; + } } } #endif From dea203820070bcde6e7a3b7439a364011a4cfe88 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 2 May 2013 17:00:39 -0700 Subject: [PATCH 28/52] send the address and socket of device requesting pair to last available --- pairing-server/src/main.cpp | 77 ++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 30 deletions(-) diff --git a/pairing-server/src/main.cpp b/pairing-server/src/main.cpp index 4383efe1ad..d869170344 100644 --- a/pairing-server/src/main.cpp +++ b/pairing-server/src/main.cpp @@ -35,46 +35,63 @@ int indexOfFirstOccurenceOfCharacter(char* haystack, char needle) { int main(int argc, const char* argv[]) { UDPSocket serverSocket(PAIRING_SERVER_LISTEN_PORT); - sockaddr_in deviceAddress; + sockaddr_in senderSocket; char deviceData[MAX_PACKET_SIZE_BYTES] = {}; ssize_t receivedBytes = 0; std::vector devices; while (true) { - if (serverSocket.receive((sockaddr *)&deviceAddress, &deviceData, &receivedBytes)) { - // create a new PairableDevice - PairableDevice newDevice = {}; + if (serverSocket.receive((sockaddr *)&senderSocket, &deviceData, &receivedBytes)) { - int addressBytes[4]; - int socketPort = 0; - - int numMatches = sscanf(deviceData, "A %s %d.%d.%d.%d:%d %s", - newDevice.identifier, - &addressBytes[3], - &addressBytes[2], - &addressBytes[1], - &addressBytes[0], - &socketPort, - newDevice.name); - - if (numMatches >= 6) { - // if we have fewer than 6 matches the packet wasn't properly formatted + if (deviceData[0] == 'A') { + // this is a device reporting itself as available - // setup the localSocket for the pairing device - newDevice.localSocket.sin_family = AF_INET; - newDevice.localSocket.sin_addr.s_addr = (addressBytes[3] | - addressBytes[2] << 8 | - addressBytes[1] << 16 | - addressBytes[0] << 24); - newDevice.localSocket.sin_port = socketPort; + // create a new PairableDevice + PairableDevice newDevice = {}; - // store this device's sending socket so we can talk back to it - newDevice.sendingSocket = deviceAddress; + int addressBytes[4]; + int socketPort = 0; - // push this new device into the vector - printf("Adding device %s (%s) to list\n", newDevice.identifier, newDevice.name); - devices.push_back(newDevice); + int numMatches = sscanf(deviceData, "A %s %d.%d.%d.%d:%d %s", + newDevice.identifier, + &addressBytes[3], + &addressBytes[2], + &addressBytes[1], + &addressBytes[0], + &socketPort, + newDevice.name); + + if (numMatches >= 6) { + // if we have fewer than 6 matches the packet wasn't properly formatted + + // setup the localSocket for the pairing device + newDevice.localSocket.sin_family = AF_INET; + newDevice.localSocket.sin_addr.s_addr = (addressBytes[3] | + addressBytes[2] << 8 | + addressBytes[1] << 16 | + addressBytes[0] << 24); + newDevice.localSocket.sin_port = socketPort; + + // store this device's sending socket so we can talk back to it + newDevice.sendingSocket = senderSocket; + + // push this new device into the vector + printf("Adding device %s (%s) to list\n", newDevice.identifier, newDevice.name); + devices.push_back(newDevice); + } + } else if (deviceData[0] == 'P') { + // this is a client looking to pair with a device + // send the most recent device this address so it can attempt to pair + + char requestorSocketString[INET_ADDRSTRLEN + 6] = {}; + char requestorAddress[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &(senderSocket.sin_addr), requestorAddress, INET_ADDRSTRLEN); + + sprintf(requestorSocketString, "%s:%d", requestorAddress, ntohs(senderSocket.sin_port)); + + PairableDevice lastDevice = devices[devices.size() - 1]; + serverSocket.send((sockaddr*) &lastDevice.sendingSocket, requestorSocketString, strlen(requestorSocketString)); } } } From c46fc5a861f0df65db652db387a70a44c35afab1 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Thu, 2 May 2013 17:46:10 -0700 Subject: [PATCH 29/52] (1) added avatar tilting while walking; (2) added avatar renderer; (3) tweaked body proportions; (4) --- interface/src/Avatar.cpp | 141 +++++++++++++++++++++------------------ interface/src/Avatar.h | 77 +++++++-------------- interface/src/main.cpp | 6 ++ 3 files changed, 106 insertions(+), 118 deletions(-) diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 8cca1a7a9a..4655c0e9ec 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -135,31 +135,31 @@ Avatar::Avatar(bool isMine) { Avatar::Avatar(const Avatar &otherAvatar) { - _velocity = otherAvatar._velocity; - _thrust = otherAvatar._thrust; - _rotation = otherAvatar._rotation; - _bodyYaw = otherAvatar._bodyYaw; - _bodyPitch = otherAvatar._bodyPitch; - _bodyRoll = otherAvatar._bodyRoll; - _bodyPitchDelta = otherAvatar._bodyPitchDelta; - _bodyYawDelta = otherAvatar._bodyYawDelta; - _bodyRollDelta = otherAvatar._bodyRollDelta; - _mousePressed = otherAvatar._mousePressed; - _mode = otherAvatar._mode; - _isMine = otherAvatar._isMine; - _renderYaw = otherAvatar._renderYaw; - _renderPitch = otherAvatar._renderPitch; - _maxArmLength = otherAvatar._maxArmLength; - _transmitterTimer = otherAvatar._transmitterTimer; - _transmitterIsFirstData = otherAvatar._transmitterIsFirstData; - _transmitterTimeLastReceived = otherAvatar._transmitterTimeLastReceived; - _transmitterHz = otherAvatar._transmitterHz; - _transmitterInitialReading = otherAvatar._transmitterInitialReading; - _transmitterPackets = otherAvatar._transmitterPackets; - _TEST_bigSphereRadius = otherAvatar._TEST_bigSphereRadius; - _TEST_bigSpherePosition = otherAvatar._TEST_bigSpherePosition; - _movedHandOffset = otherAvatar._movedHandOffset; - _usingBodySprings = otherAvatar._usingBodySprings; + _velocity = otherAvatar._velocity; + _thrust = otherAvatar._thrust; + _rotation = otherAvatar._rotation; + _bodyYaw = otherAvatar._bodyYaw; + _bodyPitch = otherAvatar._bodyPitch; + _bodyRoll = otherAvatar._bodyRoll; + _bodyPitchDelta = otherAvatar._bodyPitchDelta; + _bodyYawDelta = otherAvatar._bodyYawDelta; + _bodyRollDelta = otherAvatar._bodyRollDelta; + _mousePressed = otherAvatar._mousePressed; + _mode = otherAvatar._mode; + _isMine = otherAvatar._isMine; + _renderYaw = otherAvatar._renderYaw; + _renderPitch = otherAvatar._renderPitch; + _maxArmLength = otherAvatar._maxArmLength; + _transmitterTimer = otherAvatar._transmitterTimer; + _transmitterIsFirstData = otherAvatar._transmitterIsFirstData; + _transmitterTimeLastReceived = otherAvatar._transmitterTimeLastReceived; + _transmitterHz = otherAvatar._transmitterHz; + _transmitterInitialReading = otherAvatar._transmitterInitialReading; + _transmitterPackets = otherAvatar._transmitterPackets; + _TEST_bigSphereRadius = otherAvatar._TEST_bigSphereRadius; + _TEST_bigSpherePosition = otherAvatar._TEST_bigSpherePosition; + _movedHandOffset = otherAvatar._movedHandOffset; + _usingBodySprings = otherAvatar._usingBodySprings; _orientation.set( otherAvatar._orientation ); @@ -347,16 +347,34 @@ void Avatar::simulate(float deltaTime) { // update body yaw by body yaw delta if (_isMine) { - _bodyYaw += _bodyYawDelta * deltaTime; + _bodyPitch += _bodyPitchDelta * deltaTime; + _bodyYaw += _bodyYawDelta * deltaTime; + _bodyRoll += _bodyRollDelta * deltaTime; } - // decay body rotation deltas - _bodyPitchDelta *= (1.0 - BODY_PITCH_DECAY * deltaTime); - _bodyYawDelta *= (1.0 - BODY_YAW_DECAY * deltaTime); - _bodyRollDelta *= (1.0 - BODY_ROLL_DECAY * deltaTime); - + // decay body rotation momentum + float bodySpinMomentum = 1.0 - BODY_SPIN_FRICTION * deltaTime; + if ( bodySpinMomentum < 0.0f ) { bodySpinMomentum = 0.0f; } + _bodyPitchDelta *= bodySpinMomentum; + _bodyYawDelta *= bodySpinMomentum; + _bodyRollDelta *= bodySpinMomentum; + // add thrust to velocity _velocity += _thrust * deltaTime; + + // calculate speed + _speed = glm::length( _velocity ); + + //pitch and roll the body as a function of forward speed and turning delta + float forwardComponentOfVelocity = glm::dot( _orientation.getFront(), _velocity ); + _bodyPitch += BODY_PITCH_WHILE_WALKING * deltaTime * forwardComponentOfVelocity; + _bodyRoll += BODY_ROLL_WHILE_TURNING * deltaTime * _speed * _bodyYawDelta; + + // these forces keep the body upright... + float tiltDecay = 1.0 - BODY_UPRIGHT_FORCE * deltaTime; + if ( tiltDecay < 0.0f ) { tiltDecay = 0.0f; } + _bodyPitch *= tiltDecay; + _bodyRoll *= tiltDecay; // update position by velocity _position += _velocity * deltaTime; @@ -367,11 +385,8 @@ void Avatar::simulate(float deltaTime) { // update head information updateHead(deltaTime); - // calculate speed, and use that to determine walking vs. standing - _speed = glm::length( _velocity ); - float rotationalSpeed = fabs( _bodyYawDelta ); - - if ( _speed + rotationalSpeed > 0.2 ) { + // use speed and angular velocity to determine walking vs. standing + if ( _speed + fabs( _bodyYawDelta ) > 0.2 ) { _mode = AVATAR_MODE_WALKING; } else { _mode = AVATAR_MODE_INTERACTING; @@ -708,6 +723,7 @@ static TextRenderer* textRenderer() { } void Avatar::render(bool lookingInMirror) { + /* // show avatar position @@ -991,6 +1007,7 @@ void Avatar::initializeSkeleton() { _joint[ AVATAR_JOINT_CHEST ].parent = AVATAR_JOINT_TORSO; _joint[ AVATAR_JOINT_NECK_BASE ].parent = AVATAR_JOINT_CHEST; _joint[ AVATAR_JOINT_HEAD_BASE ].parent = AVATAR_JOINT_NECK_BASE; + _joint[ AVATAR_JOINT_HEAD_TOP ].parent = AVATAR_JOINT_HEAD_BASE; _joint[ AVATAR_JOINT_LEFT_COLLAR ].parent = AVATAR_JOINT_CHEST; _joint[ AVATAR_JOINT_LEFT_SHOULDER ].parent = AVATAR_JOINT_LEFT_COLLAR; _joint[ AVATAR_JOINT_LEFT_ELBOW ].parent = AVATAR_JOINT_LEFT_SHOULDER; @@ -1012,32 +1029,28 @@ void Avatar::initializeSkeleton() { // specify the default pose position _joint[ AVATAR_JOINT_PELVIS ].defaultPosePosition = glm::vec3( 0.0, 0.0, 0.0 ); - _joint[ AVATAR_JOINT_TORSO ].defaultPosePosition = glm::vec3( 0.0, 0.08, 0.0 ); + _joint[ AVATAR_JOINT_TORSO ].defaultPosePosition = glm::vec3( 0.0, 0.08, 0.01 ); _joint[ AVATAR_JOINT_CHEST ].defaultPosePosition = glm::vec3( 0.0, 0.09, 0.0 ); - _joint[ AVATAR_JOINT_NECK_BASE ].defaultPosePosition = glm::vec3( 0.0, 0.1, 0.0 ); - _joint[ AVATAR_JOINT_HEAD_BASE ].defaultPosePosition = glm::vec3( 0.0, 0.08, 0.0 ); - - _joint[ AVATAR_JOINT_LEFT_COLLAR ].defaultPosePosition = glm::vec3( -0.06, 0.04, 0.0 ); - _joint[ AVATAR_JOINT_LEFT_SHOULDER ].defaultPosePosition = glm::vec3( -0.04, 0.0, 0.0 ); + _joint[ AVATAR_JOINT_NECK_BASE ].defaultPosePosition = glm::vec3( 0.0, 0.1, -0.01 ); + _joint[ AVATAR_JOINT_HEAD_BASE ].defaultPosePosition = glm::vec3( 0.0, 0.08, 0.01 ); + _joint[ AVATAR_JOINT_LEFT_COLLAR ].defaultPosePosition = glm::vec3( -0.06, 0.04, -0.01 ); + _joint[ AVATAR_JOINT_LEFT_SHOULDER ].defaultPosePosition = glm::vec3( -0.03, 0.0, -0.01 ); _joint[ AVATAR_JOINT_LEFT_ELBOW ].defaultPosePosition = glm::vec3( 0.0, -0.13, 0.0 ); _joint[ AVATAR_JOINT_LEFT_WRIST ].defaultPosePosition = glm::vec3( 0.0, -0.11, 0.0 ); _joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].defaultPosePosition = glm::vec3( 0.0, -0.07, 0.0 ); - - _joint[ AVATAR_JOINT_RIGHT_COLLAR ].defaultPosePosition = glm::vec3( 0.06, 0.04, 0.0 ); - _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].defaultPosePosition = glm::vec3( 0.04, 0.0, 0.0 ); + _joint[ AVATAR_JOINT_RIGHT_COLLAR ].defaultPosePosition = glm::vec3( 0.06, 0.04, -0.01 ); + _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].defaultPosePosition = glm::vec3( 0.03, 0.0, -0.01 ); _joint[ AVATAR_JOINT_RIGHT_ELBOW ].defaultPosePosition = glm::vec3( 0.0, -0.13, 0.0 ); _joint[ AVATAR_JOINT_RIGHT_WRIST ].defaultPosePosition = glm::vec3( 0.0, -0.11, 0.0 ); _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].defaultPosePosition = glm::vec3( 0.0, -0.07, 0.0 ); - - _joint[ AVATAR_JOINT_LEFT_HIP ].defaultPosePosition = glm::vec3( -0.05, 0.0, 0.0 ); - _joint[ AVATAR_JOINT_LEFT_KNEE ].defaultPosePosition = glm::vec3( 0.0, -0.22, 0.0 ); - _joint[ AVATAR_JOINT_LEFT_HEEL ].defaultPosePosition = glm::vec3( 0.0, -0.22, 0.0 ); - _joint[ AVATAR_JOINT_LEFT_TOES ].defaultPosePosition = glm::vec3( 0.0, 0.0, 0.04 ); - - _joint[ AVATAR_JOINT_RIGHT_HIP ].defaultPosePosition = glm::vec3( 0.05, 0.0, 0.0 ); - _joint[ AVATAR_JOINT_RIGHT_KNEE ].defaultPosePosition = glm::vec3( 0.0, -0.22, 0.0 ); - _joint[ AVATAR_JOINT_RIGHT_HEEL ].defaultPosePosition = glm::vec3( 0.0, -0.22, 0.0 ); - _joint[ AVATAR_JOINT_RIGHT_TOES ].defaultPosePosition = glm::vec3( 0.0, 0.0, 0.04 ); + _joint[ AVATAR_JOINT_LEFT_HIP ].defaultPosePosition = glm::vec3( -0.04, 0.0, -0.02 ); + _joint[ AVATAR_JOINT_LEFT_KNEE ].defaultPosePosition = glm::vec3( 0.0, -0.22, 0.02 ); + _joint[ AVATAR_JOINT_LEFT_HEEL ].defaultPosePosition = glm::vec3( 0.0, -0.22, -0.01 ); + _joint[ AVATAR_JOINT_LEFT_TOES ].defaultPosePosition = glm::vec3( 0.0, 0.0, 0.05 ); + _joint[ AVATAR_JOINT_RIGHT_HIP ].defaultPosePosition = glm::vec3( 0.04, 0.0, -0.02 ); + _joint[ AVATAR_JOINT_RIGHT_KNEE ].defaultPosePosition = glm::vec3( 0.0, -0.22, 0.02 ); + _joint[ AVATAR_JOINT_RIGHT_HEEL ].defaultPosePosition = glm::vec3( 0.0, -0.22, -0.01 ); + _joint[ AVATAR_JOINT_RIGHT_TOES ].defaultPosePosition = glm::vec3( 0.0, 0.0, 0.05 ); // specify the radii of the bone positions _joint[ AVATAR_JOINT_PELVIS ].radius = 0.06; @@ -1046,13 +1059,13 @@ void Avatar::initializeSkeleton() { _joint[ AVATAR_JOINT_NECK_BASE ].radius = 0.03; _joint[ AVATAR_JOINT_HEAD_BASE ].radius = 0.07; - _joint[ AVATAR_JOINT_LEFT_COLLAR ].radius = 0.027; + _joint[ AVATAR_JOINT_LEFT_COLLAR ].radius = 0.029; _joint[ AVATAR_JOINT_LEFT_SHOULDER ].radius = 0.023; _joint[ AVATAR_JOINT_LEFT_ELBOW ].radius = 0.017; _joint[ AVATAR_JOINT_LEFT_WRIST ].radius = 0.017; _joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].radius = 0.01; - _joint[ AVATAR_JOINT_RIGHT_COLLAR ].radius = 0.027; + _joint[ AVATAR_JOINT_RIGHT_COLLAR ].radius = 0.029; _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].radius = 0.023; _joint[ AVATAR_JOINT_RIGHT_ELBOW ].radius = 0.015; _joint[ AVATAR_JOINT_RIGHT_WRIST ].radius = 0.015; @@ -1122,12 +1135,7 @@ void Avatar::initializeSkeleton() { _joint[ AVATAR_JOINT_HEAD_BASE ].length + _joint[ AVATAR_JOINT_HEAD_BASE ].radius ); - - printf( "_height = %f\n", _height ); - - - - + //printf( "_height = %f\n", _height ); // generate world positions updateSkeleton(); @@ -1145,9 +1153,12 @@ void Avatar::calculateBoneLengths() { } void Avatar::updateSkeleton() { - // rotate body... + + // rotate body... _orientation.setToIdentity(); - _orientation.yaw( _bodyYaw ); + _orientation.yaw ( _bodyYaw ); + _orientation.pitch( _bodyPitch ); + _orientation.roll ( _bodyRoll ); // calculate positions of all bones by traversing the skeleton tree: for (int b = 0; b < NUM_AVATAR_JOINTS; b++) { diff --git a/interface/src/Avatar.h b/interface/src/Avatar.h index c14680df4f..45b43e50bb 100644 --- a/interface/src/Avatar.h +++ b/interface/src/Avatar.h @@ -42,7 +42,6 @@ enum AvatarMode NUM_AVATAR_MODES }; - enum AvatarJointID { AVATAR_JOINT_NULL = -1, @@ -52,19 +51,16 @@ enum AvatarJointID AVATAR_JOINT_NECK_BASE, AVATAR_JOINT_HEAD_BASE, AVATAR_JOINT_HEAD_TOP, - AVATAR_JOINT_LEFT_COLLAR, AVATAR_JOINT_LEFT_SHOULDER, AVATAR_JOINT_LEFT_ELBOW, AVATAR_JOINT_LEFT_WRIST, AVATAR_JOINT_LEFT_FINGERTIPS, - AVATAR_JOINT_RIGHT_COLLAR, AVATAR_JOINT_RIGHT_SHOULDER, AVATAR_JOINT_RIGHT_ELBOW, AVATAR_JOINT_RIGHT_WRIST, AVATAR_JOINT_RIGHT_FINGERTIPS, - AVATAR_JOINT_LEFT_HIP, AVATAR_JOINT_LEFT_KNEE, AVATAR_JOINT_LEFT_HEEL, @@ -73,37 +69,8 @@ enum AvatarJointID AVATAR_JOINT_RIGHT_KNEE, AVATAR_JOINT_RIGHT_HEEL, AVATAR_JOINT_RIGHT_TOES, - - /* - AVATAR_JOINT_NULL = -1, - AVATAR_JOINT_PELVIS, - AVATAR_JOINT_TORSO, - AVATAR_JOINT_CHEST, - AVATAR_JOINT_NECK_BASE, - AVATAR_JOINT_HEAD_BASE, - AVATAR_JOINT_HEAD_TOP, - AVATAR_JOINT_LEFT_COLLAR, - AVATAR_JOINT_LEFT_SHOULDER, - AVATAR_JOINT_LEFT_ELBOW, - AVATAR_JOINT_LEFT_WRIST, - AVATAR_JOINT_LEFT_FINGERTIPS, - AVATAR_JOINT_RIGHT_COLLAR, - AVATAR_JOINT_RIGHT_SHOULDER, - AVATAR_JOINT_RIGHT_ELBOW, - AVATAR_JOINT_RIGHT_WRIST, - AVATAR_JOINT_RIGHT_FINGERTIPS, - AVATAR_JOINT_LEFT_HIP, - AVATAR_JOINT_LEFT_KNEE, - AVATAR_JOINT_LEFT_HEEL, - AVATAR_JOINT_LEFT_TOES, - AVATAR_JOINT_RIGHT_HIP, - AVATAR_JOINT_RIGHT_KNEE, - AVATAR_JOINT_RIGHT_HEEL, - AVATAR_JOINT_RIGHT_TOES, - */ NUM_AVATAR_JOINTS - }; @@ -134,9 +101,12 @@ public: void setLeanSideways(float dist); void addLean(float x, float z); - const glm::vec3& getHeadLookatDirection() const { return _orientation.getFront(); }; - const glm::vec3& getHeadLookatDirectionUp() const { return _orientation.getUp(); }; - const glm::vec3& getHeadLookatDirectionRight() const { return _orientation.getRight(); }; + /* + const glm::vec3& getHeadRightDirection() const { return _orientation.getRight(); }; + const glm::vec3& getHeadUpDirection () const { return _orientation.getUp (); }; + const glm::vec3& getHeadFrontDirection() const { return _orientation.getFront(); }; + */ + const glm::vec3& getHeadPosition() const ; const glm::vec3& getJointPosition(AvatarJointID j) const { return _joint[j].position; }; const glm::vec3& getBodyUpDirection() const { return _orientation.getUp(); }; @@ -183,9 +153,10 @@ private: const float DECAY = 0.1; const float THRUST_MAG = 1200.0; const float YAW_MAG = 500.0; - const float BODY_PITCH_DECAY = 5.0; - const float BODY_YAW_DECAY = 5.0; - const float BODY_ROLL_DECAY = 5.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; @@ -204,20 +175,20 @@ private: struct AvatarJoint { - AvatarJointID parent; // which joint is this joint connected to? - glm::vec3 position; // the position at the "end" of the joint - in global space - glm::vec3 defaultPosePosition; // the parent relative position when the avatar is in the "T-pose" - glm::vec3 springyPosition; // used for special effects (a 'flexible' variant of position) - glm::vec3 springyVelocity; // used for special effects ( the velocity of the springy position) - float springBodyTightness; // how tightly the springy position tries to stay on the position - glm::quat rotation; // this will eventually replace yaw, pitch and roll (and maybe orientation) - float yaw; // the yaw Euler angle of the joint rotation off the parent - float pitch; // the pitch Euler angle of the joint rotation off the parent - float roll; // the roll Euler angle of the joint rotation off the parent - Orientation orientation; // three orthogonal normals determined by yaw, pitch, roll - float length; // the length of the joint - float radius; // used for detecting collisions for certain physical effects - bool isCollidable; // when false, the joint position will not register a collision + AvatarJointID parent; // which joint is this joint connected to? + glm::vec3 position; // the position at the "end" of the joint - in global space + glm::vec3 defaultPosePosition; // the parent relative position when the avatar is in the "T-pose" + glm::vec3 springyPosition; // used for special effects (a 'flexible' variant of position) + glm::vec3 springyVelocity; // used for special effects ( the velocity of the springy position) + float springBodyTightness; // how tightly the springy position tries to stay on the position + glm::quat rotation; // this will eventually replace yaw, pitch and roll (and maybe orientation) + float yaw; // the yaw Euler angle of the joint rotation off the parent + float pitch; // the pitch Euler angle of the joint rotation off the parent + float roll; // the roll Euler angle of the joint rotation off the parent + Orientation orientation; // three orthogonal normals determined by yaw, pitch, roll + float length; // the length of vector connecting the joint and its parent + float radius; // used for detecting collisions for certain physical effects + bool isCollidable; // when false, the joint position will not register a collision }; struct AvatarHead diff --git a/interface/src/main.cpp b/interface/src/main.cpp index e3788ec236..a8f6a6fec4 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -69,6 +69,7 @@ #include "Camera.h" #include "Avatar.h" +#include "AvatarRenderer.h" #include "Texture.h" #include #include @@ -119,6 +120,9 @@ Avatar myAvatar(true); // 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 + +AvatarRenderer avatarRenderer; + // Starfield information char starFile[] = "https://s3-us-west-1.amazonaws.com/highfidelity/stars.txt"; char starCacheFile[] = "cachedStars.txt"; @@ -869,6 +873,7 @@ void display(void) 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(); @@ -881,6 +886,7 @@ void display(void) //Render my own avatar myAvatar.render(::lookingInMirror); + //avatarRenderer.render(&myAvatar, lookingInMirror); // this will replace the above call } glPopMatrix(); From 7a52d51251e1b5e2cd8a10551e5cf9a49a9062c8 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Thu, 2 May 2013 17:47:28 -0700 Subject: [PATCH 30/52] adding avatar renderer --- interface/src/AvatarRenderer.cpp | 32 ++++++++++++++++++++++++++++++++ interface/src/AvatarRenderer.h | 25 +++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 interface/src/AvatarRenderer.cpp create mode 100644 interface/src/AvatarRenderer.h diff --git a/interface/src/AvatarRenderer.cpp b/interface/src/AvatarRenderer.cpp new file mode 100644 index 0000000000..b533b69e22 --- /dev/null +++ b/interface/src/AvatarRenderer.cpp @@ -0,0 +1,32 @@ +// +// AvatarRenderer.cpp +// interface +// +// Created by Jeffrey Ventrella +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// +#include +#include +#include +#include "AvatarRenderer.h" +#include "InterfaceConfig.h" + + +AvatarRenderer::AvatarRenderer() { +} + +// this method renders the avatar +void AvatarRenderer::render(Avatar *avatar, bool lookingInMirror) { + +/* + // show avatar position + glColor4f( 0.5f, 0.5f, 0.5f, 0.6 ); + glPushMatrix(); + glTranslatef(avatar->_position.x, avatar->_position.y, avatar->_position.z); + glScalef( 0.03, 0.03, 0.03 ); + glutSolidSphere( 1, 10, 10 ); + glPopMatrix(); + */ +} + + \ No newline at end of file diff --git a/interface/src/AvatarRenderer.h b/interface/src/AvatarRenderer.h new file mode 100644 index 0000000000..80728ba560 --- /dev/null +++ b/interface/src/AvatarRenderer.h @@ -0,0 +1,25 @@ +// +// AvatarRenderer.h +// interface +// +// Created by Jeffrey Ventrella +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#ifndef __interface__AvatarRenderer__ +#define __interface__AvatarRenderer__ + +#include "Avatar.h" +#include + +class AvatarRenderer { +public: + + AvatarRenderer(); + void render(Avatar *avatar, bool lookingInMirror); + +private: + +}; + +#endif From 771c6041212110d833214bcb8d01c12d3088a840 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 May 2013 18:12:55 -0700 Subject: [PATCH 31/52] more render pipeline optimizations --- interface/src/VoxelSystem.cpp | 7 ++++++- libraries/voxels/src/VoxelNode.cpp | 12 ++++++------ libraries/voxels/src/VoxelTree.cpp | 25 ++++++++++++++++++++++--- libraries/voxels/src/VoxelTree.h | 2 ++ 4 files changed, 36 insertions(+), 10 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 2195c7fe1a..ebcc12a707 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -101,6 +101,11 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { double start = usecTimestampNow(); // ask the VoxelTree to read the bitstream into the tree _tree->readBitstreamToTree(voxelData, numBytes - 1); + if (_renderWarningsOn && _tree->getNodesChangedFromBitstream()) { + printLog("readBitstreamToTree()... getNodesChangedFromBitstream=%ld _tree->isDirty()=%s \n", + _tree->getNodesChangedFromBitstream(), (_tree->isDirty() ? "yes" : "no") ); + } + double end = usecTimestampNow(); double elapsedmsec = (end - start)/1000.0; if (_renderWarningsOn && elapsedmsec > 1) { @@ -178,7 +183,7 @@ void VoxelSystem::setupNewVoxelsForDrawing() { void VoxelSystem::copyWrittenDataToReadArrays() { double start = usecTimestampNow(); - if (_voxelsDirty) { + if (_voxelsDirty && _voxelsUpdated) { // lock on the buffer write lock so we can't modify the data when the GPU is reading it pthread_mutex_lock(&_bufferWriteLock); int bytesOfVertices = (_voxelsInArrays * VERTEX_POINTS_PER_VOXEL) * sizeof(GLfloat); diff --git a/libraries/voxels/src/VoxelNode.cpp b/libraries/voxels/src/VoxelNode.cpp index 7e411d9c4b..3d0e400782 100644 --- a/libraries/voxels/src/VoxelNode.cpp +++ b/libraries/voxels/src/VoxelNode.cpp @@ -125,9 +125,9 @@ void VoxelNode::setFalseColor(colorPart red, colorPart green, colorPart blue) { _currentColor[1] = green; _currentColor[2] = blue; _currentColor[3] = 1; // XXXBHG - False colors are always considered set - if (_shouldRender) { + //if (_shouldRender) { _isDirty = true; - } + //} } } @@ -138,9 +138,9 @@ void VoxelNode::setFalseColored(bool isFalseColored) { memcpy(&_currentColor,&_trueColor,sizeof(nodeColor)); } _falseColored = isFalseColored; - if (_shouldRender) { + //if (_shouldRender) { _isDirty = true; - } + //} } }; @@ -153,9 +153,9 @@ void VoxelNode::setColor(const nodeColor& color) { if (!_falseColored) { memcpy(&_currentColor,&color,sizeof(nodeColor)); } - if (_shouldRender) { + //if (_shouldRender) { _isDirty = true; - } + //} } } #endif diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index f781c16b0d..87e87ff1a7 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -132,6 +132,7 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, destinationNode->addChildAtIndex(i); if (destinationNode->isDirty()) { _isDirty = true; + _nodesChangedFromBitstream++; } voxelsCreated++; voxelsCreatedStats.updateAverage(1); @@ -141,9 +142,14 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, nodeColor newColor; memcpy(newColor, nodeData + bytesRead, 3); newColor[3] = 1; + bool nodeWasDirty = destinationNode->children[i]->isDirty(); destinationNode->children[i]->setColor(newColor); - if (destinationNode->children[i]->isDirty()) { + bool nodeIsDirty = destinationNode->children[i]->isDirty(); + if (nodeIsDirty) { _isDirty = true; + } + if (!nodeWasDirty && nodeIsDirty) { + _nodesChangedFromBitstream++; } this->voxelsColored++; this->voxelsColoredStats.updateAverage(1); @@ -152,10 +158,15 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, } } // average node's color based on color of children + bool nodeWasDirty = destinationNode->isDirty(); destinationNode->setColorFromAverageOfChildren(); - if (destinationNode->isDirty()) { + bool nodeIsDirty = destinationNode->isDirty(); + if (nodeIsDirty) { _isDirty = true; } + if (!nodeWasDirty && nodeIsDirty) { + _nodesChangedFromBitstream++; + } // give this destination node the child mask from the packet unsigned char childMask = *(nodeData + bytesRead); @@ -169,10 +180,15 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, if (oneAtBit(childMask, childIndex)) { if (!destinationNode->children[childIndex]) { // add a child at that index, if it doesn't exist + bool nodeWasDirty = destinationNode->isDirty(); destinationNode->addChildAtIndex(childIndex); - if (destinationNode->isDirty()) { + bool nodeIsDirty = destinationNode->isDirty(); + if (nodeIsDirty) { _isDirty = true; } + if (!nodeWasDirty && nodeIsDirty) { + _nodesChangedFromBitstream++; + } this->voxelsCreated++; this->voxelsCreatedStats.updateAverage(this->voxelsCreated); } @@ -192,6 +208,8 @@ int VoxelTree::readNodeData(VoxelNode* destinationNode, void VoxelTree::readBitstreamToTree(unsigned char * bitstream, int bufferSizeBytes) { int bytesRead = 0; unsigned char* bitstreamAt = bitstream; + + _nodesChangedFromBitstream = 0; // Keep looping through the buffer calling readNodeData() this allows us to pack multiple root-relative Octal codes // into a single network packet. readNodeData() basically goes down a tree from the root, and fills things in from there @@ -208,6 +226,7 @@ void VoxelTree::readBitstreamToTree(unsigned char * bitstream, int bufferSizeByt bitstreamRootNode = createMissingNode(rootNode, (unsigned char*) bitstreamAt); if (bitstreamRootNode->isDirty()) { _isDirty = true; + _nodesChangedFromBitstream++; } } diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index 1209868c62..e5b18b86c0 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -57,6 +57,7 @@ public: bool isDirty() const { return _isDirty; }; void clearDirtyBit() { _isDirty = false; }; + unsigned long int getNodesChangedFromBitstream() const { return _nodesChangedFromBitstream; }; private: int encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEncodeLevel, @@ -73,6 +74,7 @@ private: int readNodeData(VoxelNode *destinationNode, unsigned char* nodeData, int bufferSizeBytes); bool _isDirty; + unsigned long int _nodesChangedFromBitstream; }; int boundaryDistanceForRenderLevel(unsigned int renderLevel); From 581365f1f18108fa26ef272565989017fb094099 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 2 May 2013 20:51:17 -0700 Subject: [PATCH 32/52] Fixes per code review. --- interface/src/Avatar.cpp | 16 +++++++++------- interface/src/main.cpp | 6 +++--- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 05450f64f2..b75e151a5b 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -375,9 +375,9 @@ _head.leanForward = 0.02 * sin( tt * 0.8 ); v -= otherAvatar->getBonePosition( AVATAR_BONE_RIGHT_SHOULDER ); float distance = glm::length( v ); - if ( distance < nearestAvatarDistance ) { nearestAvatarDistance = distance; } + if (distance < nearestAvatarDistance) { nearestAvatarDistance = distance; } - if ( distance < _maxArmLength + _maxArmLength ) { + if (distance < _maxArmLength + _maxArmLength) { _interactingOther = otherAvatar; _avatarTouch.setAbleToReachOtherAvatar(true); @@ -491,8 +491,10 @@ _head.leanForward = 0.02 * sin( tt * 0.8 ); // If someone is near, damp velocity as a function of closeness const float AVATAR_BRAKING_RANGE = 1.2f; const float AVATAR_BRAKING_STRENGTH = 25.f; - if (_isMine && (nearestAvatarDistance < AVATAR_BRAKING_RANGE )) { - _velocity *= (1.f - deltaTime * AVATAR_BRAKING_STRENGTH * (AVATAR_BRAKING_RANGE - nearestAvatarDistance)); + if (_isMine && (nearestAvatarDistance < AVATAR_BRAKING_RANGE)) { + _velocity *= + (1.f - deltaTime * AVATAR_BRAKING_STRENGTH * + (AVATAR_BRAKING_RANGE - nearestAvatarDistance)); } // update head information @@ -1421,8 +1423,8 @@ void Avatar::processTransmitterData(unsigned char* packetData, int numBytes) { printLog("Using Transmitter %s to drive head, springs OFF.\n", device); } - printLog("Packet: [%s]\n", packetData); - printLog("Version: %s\n", device); + //printLog("Packet: [%s]\n", packetData); + //printLog("Version: %s\n", device); _transmitterInitialReading = glm::vec3( rot3, rot2, @@ -1449,7 +1451,7 @@ void Avatar::processTransmitterData(unsigned char* packetData, int numBytes) { if (eulerAngles.x < -180.f) { eulerAngles.x += 360.f; } glm::vec3 angularVelocity; - if (!(deviceType == DEVICE_GLASS)) { + if (deviceType != DEVICE_GLASS) { angularVelocity = glm::vec3(glm::degrees(gyrZ), glm::degrees(-gyrX), glm::degrees(gyrY)); setHeadFromGyros( &eulerAngles, &angularVelocity, (_transmitterHz == 0.f) ? 0.f : 1.f / _transmitterHz, 1.0); diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 822bfe81f6..3edab8bfe9 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -229,16 +229,16 @@ void displayStats(void) std::stringstream voxelStats; voxelStats.precision(4); - voxelStats << "Voxels Rendered: " << voxels.getVoxelsRendered()/1000.f << "K Updated: " << voxels.getVoxelsUpdated()/1000.f << "K"; + voxelStats << "Voxels Rendered: " << voxels.getVoxelsRendered() / 1000.f << "K Updated: " << voxels.getVoxelsUpdated()/1000.f << "K"; drawtext(10, statsVerticalOffset + 230, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); voxelStats.str(""); - voxelStats << "Voxels Created: " << voxels.getVoxelsCreated()/1000.f << "K (" << voxels.getVoxelsCreatedPerSecondAverage()/1000.f + voxelStats << "Voxels Created: " << voxels.getVoxelsCreated() / 1000.f << "K (" << voxels.getVoxelsCreatedPerSecondAverage() / 1000.f << "Kps) "; drawtext(10, statsVerticalOffset + 250, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); voxelStats.str(""); - voxelStats << "Voxels Colored: " << voxels.getVoxelsColored()/1000.f << "K (" << voxels.getVoxelsColoredPerSecondAverage()/1000.f + voxelStats << "Voxels Colored: " << voxels.getVoxelsColored() / 1000.f << "K (" << voxels.getVoxelsColoredPerSecondAverage() / 1000.f << "Kps) "; drawtext(10, statsVerticalOffset + 270, 0.10f, 0, 1.0, 0, (char *)voxelStats.str().c_str()); From 34a059db9a0bf442e5350e11e98ecfe4bb734f12 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 May 2013 22:26:56 -0700 Subject: [PATCH 33/52] more optimizations of render pipeline --- interface/src/VoxelSystem.cpp | 23 ++++++++++++++++++----- interface/src/VoxelSystem.h | 4 ++++ libraries/voxels/src/VoxelConstants.h | 1 + libraries/voxels/src/VoxelTree.cpp | 6 ++++++ libraries/voxels/src/VoxelTree.h | 1 + 5 files changed, 30 insertions(+), 5 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index ebcc12a707..b8f8485a67 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -154,6 +154,13 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { void VoxelSystem::setupNewVoxelsForDrawing() { double start = usecTimestampNow(); + + double sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished); + + if (sinceLastTime <= std::max(_setupNewVoxelsForDrawingLastElapsed,SIXTY_FPS_IN_MILLISECONDS)) { + return; // bail early, it hasn't been long enough since the last time we ran + } + if (_tree->isDirty()) { _callsToTreesToArrays++; _voxelsUpdated = newTreeToArrays(_tree->rootNode); @@ -164,6 +171,12 @@ void VoxelSystem::setupNewVoxelsForDrawing() { if (_voxelsUpdated) { _voxelsDirty=true; } + + if (_voxelsDirty) { + // copy the newly written data to the arrays designated for reading + copyWrittenDataToReadArrays(); + } + double end = usecTimestampNow(); double elapsedmsec = (end - start)/1000.0; if (_renderWarningsOn && elapsedmsec > 1) { @@ -174,11 +187,9 @@ void VoxelSystem::setupNewVoxelsForDrawing() { printLog("WARNING! newTreeToArrays() took %lf milliseconds %ld voxels updated\n", elapsedmsec, _voxelsUpdated); } } - - if (_voxelsDirty) { - // copy the newly written data to the arrays designated for reading - copyWrittenDataToReadArrays(); - } + + _setupNewVoxelsForDrawingLastFinished = end; + _setupNewVoxelsForDrawingLastElapsed = elapsedmsec; } void VoxelSystem::copyWrittenDataToReadArrays() { @@ -277,6 +288,8 @@ void VoxelSystem::init() { _renderWarningsOn = false; _callsToTreesToArrays = 0; + _setupNewVoxelsForDrawingLastFinished = 0; + _setupNewVoxelsForDrawingLastElapsed = 0; // When we change voxels representations in the arrays, we'll update this _voxelsDirty = false; diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 949417cf3b..d217e8aa55 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -90,6 +90,10 @@ private: unsigned long _voxelsUpdated; unsigned long _voxelsInArrays; + + double _setupNewVoxelsForDrawingLastElapsed; + double _setupNewVoxelsForDrawingLastFinished; + GLuint _vboVerticesID; GLuint _vboNormalsID; GLuint _vboColorsID; diff --git a/libraries/voxels/src/VoxelConstants.h b/libraries/voxels/src/VoxelConstants.h index 2ba4d05e31..8669ec7130 100644 --- a/libraries/voxels/src/VoxelConstants.h +++ b/libraries/voxels/src/VoxelConstants.h @@ -24,4 +24,5 @@ const int COLOR_VALUES_PER_VOXEL = 3 * VERTICES_PER_VOXEL; typedef unsigned long int glBufferIndex; const glBufferIndex GLBUFFER_INDEX_UNKNOWN = ULONG_MAX; +const double SIXTY_FPS_IN_MILLISECONDS = 1000.0/60; #endif diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 87e87ff1a7..72327c2346 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -438,6 +438,12 @@ void VoxelTree::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) { } } +void VoxelTree::createVoxel(float x, float y, float z, float s, unsigned char red, unsigned char green, unsigned char blue) { + unsigned char* voxelData = pointToVoxel(x,y,z,s,red,green,blue); + this->readCodeColorBufferToTree(voxelData); + delete voxelData; +} + void VoxelTree::createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer) { // About the color of the sphere... we're going to make this sphere be a gradient // between two RGB colors. We will do the gradient along the phi spectrum diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index e5b18b86c0..2ccb704964 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -46,6 +46,7 @@ public: void reaverageVoxelColors(VoxelNode *startNode); void loadVoxelsFile(const char* fileName, bool wantColorRandomizer); void createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer); + void createVoxel(float x, float y, float z, float s, unsigned char red, unsigned char green, unsigned char blue); void recurseTreeWithOperation(RecurseVoxelTreeOperation operation, void* extraData=NULL); From ac879f5809adbf1b287d36b283617310a5207c15 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 2 May 2013 22:27:33 -0700 Subject: [PATCH 34/52] added corner voxels to scene --- voxel-server/src/main.cpp | 68 +++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 27 deletions(-) diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index ecccbf0291..315a2bb09a 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -75,43 +75,57 @@ bool countVoxelsOperation(VoxelNode* node, void* extraData) { } void addSphereScene(VoxelTree * tree, bool wantColorRandomizer) { - printf("adding scene of spheres...\n"); - - int sphereBaseSize = 512; - - tree->createSphere(0.25, 0.5, 0.5, 0.5, (1.0 / sphereBaseSize), true, wantColorRandomizer); - printf("one sphere added...\n"); - tree->createSphere(0.030625, 0.5, 0.5, (0.25-0.06125), (1.0 / (sphereBaseSize * 2)), true, true); + printf("adding scene of spheres...\n"); + + int sphereBaseSize = 512; + + tree->createSphere(0.25, 0.5, 0.5, 0.5, (1.0 / sphereBaseSize), true, wantColorRandomizer); + printf("one sphere added...\n"); + tree->createSphere(0.030625, 0.5, 0.5, (0.25-0.06125), (1.0 / (sphereBaseSize * 2)), true, true); - printf("two spheres added...\n"); - tree->createSphere(0.030625, (1.0 - 0.030625), (1.0 - 0.030625), (1.0 - 0.06125), (1.0 / (sphereBaseSize * 2)), true, true); - printf("three spheres added...\n"); - tree->createSphere(0.030625, (1.0 - 0.030625), (1.0 - 0.030625), 0.06125, (1.0 / (sphereBaseSize * 2)), true, true); - printf("four spheres added...\n"); - tree->createSphere(0.030625, (1.0 - 0.030625), 0.06125, (1.0 - 0.06125), (1.0 / (sphereBaseSize * 2)), true, true); - printf("five spheres added...\n"); - tree->createSphere(0.06125, 0.125, 0.125, (1.0 - 0.125), (1.0 / (sphereBaseSize * 2)), true, true); + printf("two spheres added...\n"); + tree->createSphere(0.030625, (0.75 - 0.030625), (0.75 - 0.030625), (0.75 - 0.06125), (1.0 / (sphereBaseSize * 2)), true, true); + printf("three spheres added...\n"); + tree->createSphere(0.030625, (0.75 - 0.030625), (0.75 - 0.030625), 0.06125, (1.0 / (sphereBaseSize * 2)), true, true); + printf("four spheres added...\n"); + tree->createSphere(0.030625, (0.75 - 0.030625), 0.06125, (0.75 - 0.06125), (1.0 / (sphereBaseSize * 2)), true, true); + printf("five spheres added...\n"); + tree->createSphere(0.06125, 0.125, 0.125, (0.75 - 0.125), (1.0 / (sphereBaseSize * 2)), true, true); float radius = 0.0125f; - printf("6 spheres added...\n"); - tree->createSphere(radius, 0.25, radius * 5.0f, 0.25, (1.0 / 4096), true, true); - printf("7 spheres added...\n"); - tree->createSphere(radius, 0.125, radius * 5.0f, 0.25, (1.0 / 4096), true, true); - printf("8 spheres added...\n"); - tree->createSphere(radius, 0.075, radius * 5.0f, 0.25, (1.0 / 4096), true, true); - printf("9 spheres added...\n"); - tree->createSphere(radius, 0.05, radius * 5.0f, 0.25, (1.0 / 4096), true, true); - printf("10 spheres added...\n"); - tree->createSphere(radius, 0.025, radius * 5.0f, 0.25, (1.0 / 4096), true, true); - printf("11 spheres added...\n"); + printf("6 spheres added...\n"); + tree->createSphere(radius, 0.25, radius * 5.0f, 0.25, (1.0 / 4096), true, true); + printf("7 spheres added...\n"); + tree->createSphere(radius, 0.125, radius * 5.0f, 0.25, (1.0 / 4096), true, true); + printf("8 spheres added...\n"); + tree->createSphere(radius, 0.075, radius * 5.0f, 0.25, (1.0 / 4096), true, true); + printf("9 spheres added...\n"); + tree->createSphere(radius, 0.05, radius * 5.0f, 0.25, (1.0 / 4096), true, true); + printf("10 spheres added...\n"); + tree->createSphere(radius, 0.025, radius * 5.0f, 0.25, (1.0 / 4096), true, true); + printf("11 spheres added...\n"); + + float voxelSize = 1.0f/8; + printf("creating corner points...\n"); + tree->createVoxel(0 , 0 , 0 , voxelSize, 255, 255 ,255); + tree->createVoxel(1.0 - voxelSize, 0 , 0 , voxelSize, 255, 0 ,0 ); + tree->createVoxel(0 , 1.0 - voxelSize, 0 , voxelSize, 0 , 255 ,0 ); + tree->createVoxel(0 , 0 , 1.0 - voxelSize, voxelSize, 0 , 0 ,255); + + + tree->createVoxel(1.0 - voxelSize, 0 , 1.0 - voxelSize, voxelSize, 255, 0 ,255); + tree->createVoxel(0 , 1.0 - voxelSize, 1.0 - voxelSize, voxelSize, 0 , 255 ,255); + tree->createVoxel(1.0 - voxelSize, 1.0 - voxelSize, 1.0 - voxelSize, voxelSize, 255, 255 ,255); + tree->createVoxel(1.0 - voxelSize, 1.0 - voxelSize, 0 , voxelSize, 255, 255 ,0 ); + printf("DONE creating corner points...\n"); _nodeCount=0; tree->recurseTreeWithOperation(countVoxelsOperation); printf("Nodes after adding scene %d nodes\n", _nodeCount); - printf("DONE adding scene of spheres...\n"); + printf("DONE adding scene of spheres...\n"); } From 9716ea9550e80ecb6e5030b6a45b603524ebaf22 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 2 May 2013 22:28:41 -0700 Subject: [PATCH 35/52] Ground plane moved to 0->10 and lines are exactly 1 meter --- interface/src/Avatar.cpp | 9 ++++++-- interface/src/Util.cpp | 44 ++++++++++++++-------------------------- interface/src/Util.h | 2 +- interface/src/main.cpp | 2 +- 4 files changed, 24 insertions(+), 33 deletions(-) diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index b75e151a5b..a1f9103d37 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -1508,8 +1508,13 @@ glm::vec3 Avatar::getGravity(glm::vec3 pos) { // For now, we'll test this with a simple global lookup, but soon we will add getting this // from the domain/voxelserver (or something similar) // - if (glm::length(pos) < 5.f) { - // If near the origin sphere, turn gravity ON + if ((pos.x > 0.f) && + (pos.x < 10.f) && + (pos.z > 0.f) && + (pos.z < 10.f) && + (pos.y > 0.f) && + (pos.y < 3.f)) { + // If above ground plane, turn gravity on return glm::vec3(0.f, -1.f, 0.f); } else { // If flying in space, turn gravity OFF diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index ef51f9b72a..138ae7aef4 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -213,42 +213,28 @@ void drawvec3(int x, int y, float scale, float rotate, float thick, int mono, gl } -void drawGroundPlaneGrid( float size, int resolution ) +void drawGroundPlaneGrid(float size) { - glColor3f( 0.4f, 0.5f, 0.3f ); + glColor3f( 0.4f, 0.5f, 0.3f ); glLineWidth(2.0); - float gridSize = 10.0; - int gridResolution = 20; - - for (int g=0; g Date: Thu, 2 May 2013 22:38:58 -0700 Subject: [PATCH 36/52] small tweak to corner boxes --- voxel-server/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 315a2bb09a..9f5fc75ccb 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -106,7 +106,7 @@ void addSphereScene(VoxelTree * tree, bool wantColorRandomizer) { tree->createSphere(radius, 0.025, radius * 5.0f, 0.25, (1.0 / 4096), true, true); printf("11 spheres added...\n"); - float voxelSize = 1.0f/8; + float voxelSize = 0.99f/8; printf("creating corner points...\n"); tree->createVoxel(0 , 0 , 0 , voxelSize, 255, 255 ,255); tree->createVoxel(1.0 - voxelSize, 0 , 0 , voxelSize, 255, 0 ,0 ); From b703d0982e35bec61186be11d79593d350c81aa4 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Fri, 3 May 2013 09:55:25 -0700 Subject: [PATCH 37/52] Changed avatar.h to store _distanceToNearestAvatar --- interface/src/Avatar.cpp | 15 +++++++++------ interface/src/Avatar.h | 1 + 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index a1f9103d37..b1b1eb159a 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -142,6 +142,7 @@ Avatar::Avatar(bool isMine) { _interactingOther = NULL; //_canReachToOtherAvatar = false; _handHoldingPosition = glm::vec3( 0.0, 0.0, 0.0 ); + _distanceToNearestAvatar = std::numeric_limits::max(); initializeSkeleton(); @@ -230,6 +231,7 @@ Avatar::Avatar(const Avatar &otherAvatar) { _head.lastLoudness = otherAvatar._head.lastLoudness; _head.browAudioLift = otherAvatar._head.browAudioLift; _head.noise = otherAvatar._head.noise; + _distanceToNearestAvatar = otherAvatar._distanceToNearestAvatar; initializeSkeleton(); @@ -328,7 +330,6 @@ bool Avatar::getIsNearInteractingOther() { void Avatar::simulate(float deltaTime) { - float nearestAvatarDistance = std::numeric_limits::max(); //keep this - I'm still using it to test things.... /* @@ -360,8 +361,10 @@ _head.leanForward = 0.02 * sin( tt * 0.8 ); // if the avatar being simulated is mine, then loop through // all the other avatars for potential interactions... if ( _isMine ) - { - + { + // Reset detector for nearest avatar + _distanceToNearestAvatar = std::numeric_limits::max(); + AgentList* agentList = AgentList::getInstance(); for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) { if (agent->getLinkedData() != NULL && agent->getType() == AGENT_TYPE_AVATAR) { @@ -375,7 +378,7 @@ _head.leanForward = 0.02 * sin( tt * 0.8 ); v -= otherAvatar->getBonePosition( AVATAR_BONE_RIGHT_SHOULDER ); float distance = glm::length( v ); - if (distance < nearestAvatarDistance) { nearestAvatarDistance = distance; } + if (distance < _distanceToNearestAvatar) { _distanceToNearestAvatar = distance; } if (distance < _maxArmLength + _maxArmLength) { @@ -491,10 +494,10 @@ _head.leanForward = 0.02 * sin( tt * 0.8 ); // If someone is near, damp velocity as a function of closeness const float AVATAR_BRAKING_RANGE = 1.2f; const float AVATAR_BRAKING_STRENGTH = 25.f; - if (_isMine && (nearestAvatarDistance < AVATAR_BRAKING_RANGE)) { + if (_isMine && (_distanceToNearestAvatar < AVATAR_BRAKING_RANGE)) { _velocity *= (1.f - deltaTime * AVATAR_BRAKING_STRENGTH * - (AVATAR_BRAKING_RANGE - nearestAvatarDistance)); + (AVATAR_BRAKING_RANGE - _distanceToNearestAvatar)); } // update head information diff --git a/interface/src/Avatar.h b/interface/src/Avatar.h index fec8b6e4d0..f88e5fe848 100644 --- a/interface/src/Avatar.h +++ b/interface/src/Avatar.h @@ -263,6 +263,7 @@ private: AvatarTouch _avatarTouch; bool _displayingHead; // should be false if in first-person view bool _returnHeadToCenter; + float _distanceToNearestAvatar; // How close is the nearest avatar? // private methods... void initializeSkeleton(); From a4f2dc283dac65b857d708f7d2df984029fc8581 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 3 May 2013 09:58:52 -0700 Subject: [PATCH 38/52] various changes to help debug render pipeline - fixing some cases where TREE_SCALE was not using constant in prep for making TREE_SCALE larger - added createLine() to VoxelTree - added axis lines made of voxels to scene - added corner points made of voxels to scene --- interface/src/VoxelSystem.cpp | 2 +- interface/src/main.cpp | 2 +- libraries/voxels/src/VoxelNode.h | 1 + libraries/voxels/src/VoxelTree.cpp | 17 +++++++++++- libraries/voxels/src/VoxelTree.h | 2 ++ voxel-server/src/main.cpp | 44 ++++++++++++++++++++---------- 6 files changed, 50 insertions(+), 18 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index b8f8485a67..989ab8ff3d 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -433,7 +433,7 @@ void VoxelSystem::render() { // draw the number of voxels we have glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID); - glScalef(10, 10, 10); + glScalef(TREE_SCALE, TREE_SCALE, TREE_SCALE); glDrawElements(GL_TRIANGLES, 36 * _voxelsInArrays, GL_UNSIGNED_INT, 0); // deactivate vertex and color arrays after drawing diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 6d3adcdbba..f3b82cc663 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -1696,7 +1696,7 @@ int main(int argc, const char * argv[]) // field of view and near and far clip to make it interesting. //viewFrustumOffsetCamera.setFieldOfView(90.0); viewFrustumOffsetCamera.setNearClip(0.1); - viewFrustumOffsetCamera.setFarClip(500.0); + viewFrustumOffsetCamera.setFarClip(500.0*TREE_SCALE); printLog( "Created Display Window.\n" ); diff --git a/libraries/voxels/src/VoxelNode.h b/libraries/voxels/src/VoxelNode.h index 26edb87e79..90ee3bf730 100644 --- a/libraries/voxels/src/VoxelNode.h +++ b/libraries/voxels/src/VoxelNode.h @@ -15,6 +15,7 @@ typedef unsigned char colorPart; typedef unsigned char nodeColor[4]; +typedef unsigned char rgbColor[3]; class VoxelNode { private: diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 72327c2346..21118c929e 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -25,7 +25,7 @@ using voxels_lib::printLog; int boundaryDistanceForRenderLevel(unsigned int renderLevel) { - float voxelSizeScale = 5000.0; + float voxelSizeScale = 500.0*TREE_SCALE; return voxelSizeScale / powf(2, renderLevel); } @@ -444,6 +444,21 @@ void VoxelTree::createVoxel(float x, float y, float z, float s, unsigned char re delete voxelData; } + +void VoxelTree::createLine(glm::vec3 point1, glm::vec3 point2, float unitSize, rgbColor color) { + glm::vec3 distance = point2 - point1; + glm::vec3 items = distance / unitSize; + int maxItems = std::max(items.x, std::max(items.y, items.z)); + glm::vec3 increment = distance * (1.0f/ maxItems); + glm::vec3 pointAt = point1; + for (int i = 0; i <= maxItems; i++ ) { + pointAt += increment; + unsigned char* voxelData = pointToVoxel(pointAt.x,pointAt.y,pointAt.z,unitSize,color[0],color[1],color[2]); + readCodeColorBufferToTree(voxelData); + delete voxelData; + } +} + void VoxelTree::createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer) { // About the color of the sphere... we're going to make this sphere be a gradient // between two RGB colors. We will do the gradient along the phi spectrum diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index 2ccb704964..309766bcd2 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -47,6 +47,8 @@ public: void loadVoxelsFile(const char* fileName, bool wantColorRandomizer); void createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer); void createVoxel(float x, float y, float z, float s, unsigned char red, unsigned char green, unsigned char blue); + + void createLine(glm::vec3 point1, glm::vec3 point2, float unitSize, rgbColor color); void recurseTreeWithOperation(RecurseVoxelTreeOperation operation, void* extraData=NULL); diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 9f5fc75ccb..17c4915988 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -75,10 +75,36 @@ bool countVoxelsOperation(VoxelNode* node, void* extraData) { } void addSphereScene(VoxelTree * tree, bool wantColorRandomizer) { - printf("adding scene of spheres...\n"); + printf("adding scene...\n"); + + float voxelSize = 1.f/32; + printf("creating corner points...\n"); + tree->createVoxel(0 , 0 , 0 , voxelSize, 255, 255 ,255); + tree->createVoxel(1.0 - voxelSize, 0 , 0 , voxelSize, 255, 0 ,0 ); + tree->createVoxel(0 , 1.0 - voxelSize, 0 , voxelSize, 0 , 255 ,0 ); + tree->createVoxel(0 , 0 , 1.0 - voxelSize, voxelSize, 0 , 0 ,255); + + + tree->createVoxel(1.0 - voxelSize, 0 , 1.0 - voxelSize, voxelSize, 255, 0 ,255); + tree->createVoxel(0 , 1.0 - voxelSize, 1.0 - voxelSize, voxelSize, 0 , 255 ,255); + tree->createVoxel(1.0 - voxelSize, 1.0 - voxelSize, 0 , voxelSize, 255, 255 ,0 ); + tree->createVoxel(1.0 - voxelSize, 1.0 - voxelSize, 1.0 - voxelSize, voxelSize, 255, 255 ,255); + printf("DONE creating corner points...\n"); + + printf("creating voxel lines...\n"); + float lineVoxelSize = 0.99f/256; + rgbColor red = {255,0,0}; + rgbColor green = {0,255,0}; + rgbColor blue = {0,0,255}; + + tree->createLine(glm::vec3(0, 0, 0), glm::vec3(0, 0, 1), lineVoxelSize, blue); + tree->createLine(glm::vec3(0, 0, 0), glm::vec3(1, 0, 0), lineVoxelSize, red); + tree->createLine(glm::vec3(0, 0, 0), glm::vec3(0, 1, 0), lineVoxelSize, green); + + printf("DONE creating lines...\n"); int sphereBaseSize = 512; - + printf("creating spheres...\n"); tree->createSphere(0.25, 0.5, 0.5, 0.5, (1.0 / sphereBaseSize), true, wantColorRandomizer); printf("one sphere added...\n"); tree->createSphere(0.030625, 0.5, 0.5, (0.25-0.06125), (1.0 / (sphereBaseSize * 2)), true, true); @@ -106,19 +132,7 @@ void addSphereScene(VoxelTree * tree, bool wantColorRandomizer) { tree->createSphere(radius, 0.025, radius * 5.0f, 0.25, (1.0 / 4096), true, true); printf("11 spheres added...\n"); - float voxelSize = 0.99f/8; - printf("creating corner points...\n"); - tree->createVoxel(0 , 0 , 0 , voxelSize, 255, 255 ,255); - tree->createVoxel(1.0 - voxelSize, 0 , 0 , voxelSize, 255, 0 ,0 ); - tree->createVoxel(0 , 1.0 - voxelSize, 0 , voxelSize, 0 , 255 ,0 ); - tree->createVoxel(0 , 0 , 1.0 - voxelSize, voxelSize, 0 , 0 ,255); - - - tree->createVoxel(1.0 - voxelSize, 0 , 1.0 - voxelSize, voxelSize, 255, 0 ,255); - tree->createVoxel(0 , 1.0 - voxelSize, 1.0 - voxelSize, voxelSize, 0 , 255 ,255); - tree->createVoxel(1.0 - voxelSize, 1.0 - voxelSize, 1.0 - voxelSize, voxelSize, 255, 255 ,255); - tree->createVoxel(1.0 - voxelSize, 1.0 - voxelSize, 0 , voxelSize, 255, 255 ,0 ); - printf("DONE creating corner points...\n"); + printf("DONE creating spheres...\n"); _nodeCount=0; tree->recurseTreeWithOperation(countVoxelsOperation); From 08350a5d3aa5173905183081a9f3e79fbe916cbe Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 3 May 2013 10:22:10 -0700 Subject: [PATCH 39/52] Rather than a command line parameter, provide a menu option for switching to/from fullscreen mode. --- interface/src/main.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index c602d37823..b0d929ff7e 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -1190,6 +1190,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); } @@ -1338,6 +1352,7 @@ 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 @@ -1538,6 +1553,7 @@ 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; @@ -1841,8 +1857,6 @@ int main(int argc, const char * argv[]) sprintf(DOMAIN_IP,"%d.%d.%d.%d", (ip & 0xFF), ((ip >> 8) & 0xFF),((ip >> 16) & 0xFF), ((ip >> 24) & 0xFF)); } - fullscreen = cmdOptionExists(argc, argv, "--fullscreen"); - // the callback for our instance of AgentList is attachNewHeadToAgent AgentList::getInstance()->linkedDataCreateCallback = &attachNewHeadToAgent; From e0b33e56daf5019344beb04c84e7692fd48fc768 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Fri, 3 May 2013 10:52:44 -0700 Subject: [PATCH 40/52] couple of small code cleanups --- interface/src/Avatar.cpp | 52 ++++++++++++++++++++-------------------- interface/src/Avatar.h | 2 +- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 4655c0e9ec..5dbbba3272 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -49,17 +49,17 @@ Avatar::Avatar(bool isMine) { _orientation.setToIdentity(); - _velocity = glm::vec3( 0.0, 0.0, 0.0 ); - _thrust = glm::vec3( 0.0, 0.0, 0.0 ); + _velocity = glm::vec3( 0.0, 0.0, 0.0 ); + _thrust = glm::vec3( 0.0, 0.0, 0.0 ); _rotation = glm::quat( 0.0f, 0.0f, 0.0f, 0.0f ); - _bodyYaw = -90.0; - _bodyPitch = 0.0; - _bodyRoll = 0.0; - _bodyPitchDelta = 0.0; - _bodyYawDelta = 0.0; - _bodyRollDelta = 0.0; - _mousePressed = false; - _mode = AVATAR_MODE_STANDING; + _bodyYaw = -90.0; + _bodyPitch = 0.0; + _bodyRoll = 0.0; + _bodyPitchDelta = 0.0; + _bodyYawDelta = 0.0; + _bodyRollDelta = 0.0; + _mousePressed = false; + _mode = AVATAR_MODE_STANDING; _isMine = isMine; _maxArmLength = 0.0; _transmitterHz = 0.0; @@ -111,11 +111,11 @@ Avatar::Avatar(bool isMine) { _head.browAudioLift = 0.0; _head.noise = 0; _head.returnSpringScale = 1.0; - _movedHandOffset = glm::vec3( 0.0, 0.0, 0.0 ); + _movedHandOffset = glm::vec3( 0.0, 0.0, 0.0 ); _usingBodySprings = true; _renderYaw = 0.0; _renderPitch = 0.0; - _sphere = NULL; + _sphere = NULL; _interactingOther = NULL; _handHoldingPosition = glm::vec3( 0.0, 0.0, 0.0 ); @@ -136,16 +136,16 @@ Avatar::Avatar(bool isMine) { Avatar::Avatar(const Avatar &otherAvatar) { _velocity = otherAvatar._velocity; - _thrust = otherAvatar._thrust; + _thrust = otherAvatar._thrust; _rotation = otherAvatar._rotation; - _bodyYaw = otherAvatar._bodyYaw; - _bodyPitch = otherAvatar._bodyPitch; - _bodyRoll = otherAvatar._bodyRoll; - _bodyPitchDelta = otherAvatar._bodyPitchDelta; - _bodyYawDelta = otherAvatar._bodyYawDelta; - _bodyRollDelta = otherAvatar._bodyRollDelta; - _mousePressed = otherAvatar._mousePressed; - _mode = otherAvatar._mode; + _bodyYaw = otherAvatar._bodyYaw; + _bodyPitch = otherAvatar._bodyPitch; + _bodyRoll = otherAvatar._bodyRoll; + _bodyPitchDelta = otherAvatar._bodyPitchDelta; + _bodyYawDelta = otherAvatar._bodyYawDelta; + _bodyRollDelta = otherAvatar._bodyRollDelta; + _mousePressed = otherAvatar._mousePressed; + _mode = otherAvatar._mode; _isMine = otherAvatar._isMine; _renderYaw = otherAvatar._renderYaw; _renderPitch = otherAvatar._renderPitch; @@ -158,12 +158,12 @@ Avatar::Avatar(const Avatar &otherAvatar) { _transmitterPackets = otherAvatar._transmitterPackets; _TEST_bigSphereRadius = otherAvatar._TEST_bigSphereRadius; _TEST_bigSpherePosition = otherAvatar._TEST_bigSpherePosition; - _movedHandOffset = otherAvatar._movedHandOffset; - _usingBodySprings = otherAvatar._usingBodySprings; - - _orientation.set( otherAvatar._orientation ); + _movedHandOffset = otherAvatar._movedHandOffset; + _usingBodySprings = otherAvatar._usingBodySprings; - _sphere = NULL; + _orientation.set( otherAvatar._orientation ); + + _sphere = NULL; initializeSkeleton(); diff --git a/interface/src/Avatar.h b/interface/src/Avatar.h index 45b43e50bb..db238e8c2d 100644 --- a/interface/src/Avatar.h +++ b/interface/src/Avatar.h @@ -145,7 +145,7 @@ public: // Find out what the local gravity vector is at this location glm::vec3 getGravity(glm::vec3 pos); - + private: const bool BALLS_ON = false; From 9dfc6c6590c63bbfe698d452f02263f734143035 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 3 May 2013 10:57:51 -0700 Subject: [PATCH 41/52] Fix for fullscreen mode switching: when we reshape, we need to resize the render texture (if it exists). --- interface/src/main.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index cb1249638c..777c625e56 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -1748,6 +1748,12 @@ void reshape(int width, int height) camera.setAspectRatio(aspectRatio *= 0.5); camera.setFieldOfView(fov = 2 * atan((0.0468 * ::oculusDistortionScale) / 0.041) * (180 / PI)); + // resize the render texture + if (::oculusTextureID != 0) { + glBindTexture(GL_TEXTURE_2D, ::oculusTextureID); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, WIDTH, HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + glBindTexture(GL_TEXTURE_2D, 0); + } } else { camera.setFieldOfView(fov = 60); } From bd6f0d9885054862c62b1a9497853a1ee495fa5b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 3 May 2013 10:58:57 -0700 Subject: [PATCH 42/52] couple of line deletions --- interface/src/main.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 08b1666d05..2473c43380 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -1593,8 +1593,6 @@ void mouseoverFunc( int x, int y) {} } - - void attachNewHeadToAgent(Agent *newAgent) { if (newAgent->getLinkedData() == NULL) { newAgent->setLinkedData(new Avatar(false)); From 8457b91fe0f1e8dce659a7a119b1737dcdfd3c32 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Fri, 3 May 2013 11:15:49 -0700 Subject: [PATCH 43/52] cleaned up a bunch of leftover tabs and converted each to 4 spaces --- interface/src/Avatar.cpp | 456 ++++++++++++++++++++------------------- 1 file changed, 231 insertions(+), 225 deletions(-) diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index ac4f2a54c5..7a4468d608 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -431,13 +431,13 @@ void Avatar::simulate(float deltaTime) { //update the movement of the hand and process handshaking with other avatars... void Avatar::updateHandMovementAndTouching(float deltaTime) { - // reset hand and arm positions according to hand movement - glm::vec3 transformedHandMovement - = _orientation.getRight() * _movedHandOffset.x * 2.0f - + _orientation.getUp() * -_movedHandOffset.y * 1.0f - + _orientation.getFront() * -_movedHandOffset.y * 1.0f; + // reset hand and arm positions according to hand movement + glm::vec3 transformedHandMovement + = _orientation.getRight() * _movedHandOffset.x * 2.0f + + _orientation.getUp() * -_movedHandOffset.y * 1.0f + + _orientation.getFront() * -_movedHandOffset.y * 1.0f; - _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position += transformedHandMovement; + _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position += transformedHandMovement; if (_isMine) { _handState = _mousePressed; @@ -446,8 +446,8 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) { //reset these for the next go-round _avatarTouch.setAbleToReachOtherAvatar (false); _avatarTouch.setHandsCloseEnoughToGrasp(false); - - // if the avatar being simulated is mine, then loop through + + // if the avatar being simulated is mine, then loop through // all the other avatars for potential interactions... if ( _isMine ) { @@ -763,13 +763,13 @@ void Avatar::render(bool lookingInMirror) { /* - // show avatar position + // show avatar position glColor4f( 0.5f, 0.5f, 0.5f, 0.6 ); - glPushMatrix(); + glPushMatrix(); glTranslatef(_position.x, _position.y, _position.z); glScalef( 0.03, 0.03, 0.03 ); glutSolidSphere( 1, 10, 10 ); - glPopMatrix(); + glPopMatrix(); */ if ( usingBigSphereCollisionTest ) { @@ -782,15 +782,15 @@ void Avatar::render(bool lookingInMirror) { glPopMatrix(); } - //render body - renderBody(); + //render body + renderBody(); - // render head + // render head if (_displayingHead) { renderHead(lookingInMirror); - } + } - // if this is my avatar, then render my interactions with the other avatar + // if this is my avatar, then render my interactions with the other avatar if ( _isMine ) { _avatarTouch.render(); } @@ -856,16 +856,16 @@ void Avatar::renderHead(bool lookingInMirror) { glPushMatrix(); - if (_usingBodySprings) { - glTranslatef(_joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition.x, + if (_usingBodySprings) { + glTranslatef(_joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition.x, _joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition.y, _joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition.z); - } - else { - glTranslatef(_joint[ AVATAR_JOINT_HEAD_BASE ].position.x, + } + else { + glTranslatef(_joint[ AVATAR_JOINT_HEAD_BASE ].position.x, _joint[ AVATAR_JOINT_HEAD_BASE ].position.y, _joint[ AVATAR_JOINT_HEAD_BASE ].position.z); - } + } glScalef ( @@ -877,12 +877,18 @@ void Avatar::renderHead(bool lookingInMirror) { if (lookingInMirror) { glRotatef(_bodyYaw - _headYaw, 0, 1, 0); - glRotatef(_bodyPitch + _headPitch, 1, 0, 0); - glRotatef(_bodyRoll - _headRoll, 0, 0, 1); + //glRotatef(_bodyPitch + _headPitch, 1, 0, 0); + //glRotatef(_bodyRoll - _headRoll, 0, 0, 1); + // don't let body pitch and roll affect the head.. + glRotatef( _headPitch, 1, 0, 0); + glRotatef( -_headRoll, 0, 0, 1); } else { glRotatef(_bodyYaw + _headYaw, 0, 1, 0); - glRotatef(_bodyPitch + _headPitch, 1, 0, 0); - glRotatef(_bodyRoll + _headRoll, 0, 0, 1); + //glRotatef(_bodyPitch + _headPitch, 1, 0, 0); + //glRotatef(_bodyRoll + _headRoll, 0, 0, 1); + // don't let body pitch and roll affect the head.. + glRotatef( _headPitch, 1, 0, 0); + glRotatef( _headRoll, 0, 0, 1); } //glScalef(2.0, 2.0, 2.0); @@ -1036,128 +1042,128 @@ void Avatar::initializeSkeleton() { _joint[b].radius = 0.0; _joint[b].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS; _joint[b].orientation.setToIdentity(); - } + } - // specify the parental hierarchy - _joint[ AVATAR_JOINT_PELVIS ].parent = AVATAR_JOINT_NULL; - _joint[ AVATAR_JOINT_TORSO ].parent = AVATAR_JOINT_PELVIS; - _joint[ AVATAR_JOINT_CHEST ].parent = AVATAR_JOINT_TORSO; - _joint[ AVATAR_JOINT_NECK_BASE ].parent = AVATAR_JOINT_CHEST; - _joint[ AVATAR_JOINT_HEAD_BASE ].parent = AVATAR_JOINT_NECK_BASE; - _joint[ AVATAR_JOINT_HEAD_TOP ].parent = AVATAR_JOINT_HEAD_BASE; - _joint[ AVATAR_JOINT_LEFT_COLLAR ].parent = AVATAR_JOINT_CHEST; - _joint[ AVATAR_JOINT_LEFT_SHOULDER ].parent = AVATAR_JOINT_LEFT_COLLAR; - _joint[ AVATAR_JOINT_LEFT_ELBOW ].parent = AVATAR_JOINT_LEFT_SHOULDER; - _joint[ AVATAR_JOINT_LEFT_WRIST ].parent = AVATAR_JOINT_LEFT_ELBOW; - _joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].parent = AVATAR_JOINT_LEFT_WRIST; - _joint[ AVATAR_JOINT_RIGHT_COLLAR ].parent = AVATAR_JOINT_CHEST; - _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].parent = AVATAR_JOINT_RIGHT_COLLAR; - _joint[ AVATAR_JOINT_RIGHT_ELBOW ].parent = AVATAR_JOINT_RIGHT_SHOULDER; - _joint[ AVATAR_JOINT_RIGHT_WRIST ].parent = AVATAR_JOINT_RIGHT_ELBOW; - _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].parent = AVATAR_JOINT_RIGHT_WRIST; - _joint[ AVATAR_JOINT_LEFT_HIP ].parent = AVATAR_JOINT_PELVIS; - _joint[ AVATAR_JOINT_LEFT_KNEE ].parent = AVATAR_JOINT_LEFT_HIP; - _joint[ AVATAR_JOINT_LEFT_HEEL ].parent = AVATAR_JOINT_LEFT_KNEE; - _joint[ AVATAR_JOINT_LEFT_TOES ].parent = AVATAR_JOINT_LEFT_HEEL; - _joint[ AVATAR_JOINT_RIGHT_HIP ].parent = AVATAR_JOINT_PELVIS; - _joint[ AVATAR_JOINT_RIGHT_KNEE ].parent = AVATAR_JOINT_RIGHT_HIP; - _joint[ AVATAR_JOINT_RIGHT_HEEL ].parent = AVATAR_JOINT_RIGHT_KNEE; - _joint[ AVATAR_JOINT_RIGHT_TOES ].parent = AVATAR_JOINT_RIGHT_HEEL; + // specify the parental hierarchy + _joint[ AVATAR_JOINT_PELVIS ].parent = AVATAR_JOINT_NULL; + _joint[ AVATAR_JOINT_TORSO ].parent = AVATAR_JOINT_PELVIS; + _joint[ AVATAR_JOINT_CHEST ].parent = AVATAR_JOINT_TORSO; + _joint[ AVATAR_JOINT_NECK_BASE ].parent = AVATAR_JOINT_CHEST; + _joint[ AVATAR_JOINT_HEAD_BASE ].parent = AVATAR_JOINT_NECK_BASE; + _joint[ AVATAR_JOINT_HEAD_TOP ].parent = AVATAR_JOINT_HEAD_BASE; + _joint[ AVATAR_JOINT_LEFT_COLLAR ].parent = AVATAR_JOINT_CHEST; + _joint[ AVATAR_JOINT_LEFT_SHOULDER ].parent = AVATAR_JOINT_LEFT_COLLAR; + _joint[ AVATAR_JOINT_LEFT_ELBOW ].parent = AVATAR_JOINT_LEFT_SHOULDER; + _joint[ AVATAR_JOINT_LEFT_WRIST ].parent = AVATAR_JOINT_LEFT_ELBOW; + _joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].parent = AVATAR_JOINT_LEFT_WRIST; + _joint[ AVATAR_JOINT_RIGHT_COLLAR ].parent = AVATAR_JOINT_CHEST; + _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].parent = AVATAR_JOINT_RIGHT_COLLAR; + _joint[ AVATAR_JOINT_RIGHT_ELBOW ].parent = AVATAR_JOINT_RIGHT_SHOULDER; + _joint[ AVATAR_JOINT_RIGHT_WRIST ].parent = AVATAR_JOINT_RIGHT_ELBOW; + _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].parent = AVATAR_JOINT_RIGHT_WRIST; + _joint[ AVATAR_JOINT_LEFT_HIP ].parent = AVATAR_JOINT_PELVIS; + _joint[ AVATAR_JOINT_LEFT_KNEE ].parent = AVATAR_JOINT_LEFT_HIP; + _joint[ AVATAR_JOINT_LEFT_HEEL ].parent = AVATAR_JOINT_LEFT_KNEE; + _joint[ AVATAR_JOINT_LEFT_TOES ].parent = AVATAR_JOINT_LEFT_HEEL; + _joint[ AVATAR_JOINT_RIGHT_HIP ].parent = AVATAR_JOINT_PELVIS; + _joint[ AVATAR_JOINT_RIGHT_KNEE ].parent = AVATAR_JOINT_RIGHT_HIP; + _joint[ AVATAR_JOINT_RIGHT_HEEL ].parent = AVATAR_JOINT_RIGHT_KNEE; + _joint[ AVATAR_JOINT_RIGHT_TOES ].parent = AVATAR_JOINT_RIGHT_HEEL; - // specify the default pose position - _joint[ AVATAR_JOINT_PELVIS ].defaultPosePosition = glm::vec3( 0.0, 0.0, 0.0 ); - _joint[ AVATAR_JOINT_TORSO ].defaultPosePosition = glm::vec3( 0.0, 0.08, 0.01 ); - _joint[ AVATAR_JOINT_CHEST ].defaultPosePosition = glm::vec3( 0.0, 0.09, 0.0 ); - _joint[ AVATAR_JOINT_NECK_BASE ].defaultPosePosition = glm::vec3( 0.0, 0.1, -0.01 ); - _joint[ AVATAR_JOINT_HEAD_BASE ].defaultPosePosition = glm::vec3( 0.0, 0.08, 0.01 ); + // specify the default pose position + _joint[ AVATAR_JOINT_PELVIS ].defaultPosePosition = glm::vec3( 0.0, 0.0, 0.0 ); + _joint[ AVATAR_JOINT_TORSO ].defaultPosePosition = glm::vec3( 0.0, 0.08, 0.01 ); + _joint[ AVATAR_JOINT_CHEST ].defaultPosePosition = glm::vec3( 0.0, 0.09, 0.0 ); + _joint[ AVATAR_JOINT_NECK_BASE ].defaultPosePosition = glm::vec3( 0.0, 0.1, -0.01 ); + _joint[ AVATAR_JOINT_HEAD_BASE ].defaultPosePosition = glm::vec3( 0.0, 0.08, 0.01 ); _joint[ AVATAR_JOINT_LEFT_COLLAR ].defaultPosePosition = glm::vec3( -0.06, 0.04, -0.01 ); - _joint[ AVATAR_JOINT_LEFT_SHOULDER ].defaultPosePosition = glm::vec3( -0.03, 0.0, -0.01 ); - _joint[ AVATAR_JOINT_LEFT_ELBOW ].defaultPosePosition = glm::vec3( 0.0, -0.13, 0.0 ); - _joint[ AVATAR_JOINT_LEFT_WRIST ].defaultPosePosition = glm::vec3( 0.0, -0.11, 0.0 ); - _joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].defaultPosePosition = glm::vec3( 0.0, -0.07, 0.0 ); + _joint[ AVATAR_JOINT_LEFT_SHOULDER ].defaultPosePosition = glm::vec3( -0.03, 0.0, -0.01 ); + _joint[ AVATAR_JOINT_LEFT_ELBOW ].defaultPosePosition = glm::vec3( 0.0, -0.13, 0.0 ); + _joint[ AVATAR_JOINT_LEFT_WRIST ].defaultPosePosition = glm::vec3( 0.0, -0.11, 0.0 ); + _joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].defaultPosePosition = glm::vec3( 0.0, -0.07, 0.0 ); _joint[ AVATAR_JOINT_RIGHT_COLLAR ].defaultPosePosition = glm::vec3( 0.06, 0.04, -0.01 ); - _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].defaultPosePosition = glm::vec3( 0.03, 0.0, -0.01 ); + _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].defaultPosePosition = glm::vec3( 0.03, 0.0, -0.01 ); _joint[ AVATAR_JOINT_RIGHT_ELBOW ].defaultPosePosition = glm::vec3( 0.0, -0.13, 0.0 ); _joint[ AVATAR_JOINT_RIGHT_WRIST ].defaultPosePosition = glm::vec3( 0.0, -0.11, 0.0 ); - _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].defaultPosePosition = glm::vec3( 0.0, -0.07, 0.0 ); + _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].defaultPosePosition = glm::vec3( 0.0, -0.07, 0.0 ); _joint[ AVATAR_JOINT_LEFT_HIP ].defaultPosePosition = glm::vec3( -0.04, 0.0, -0.02 ); - _joint[ AVATAR_JOINT_LEFT_KNEE ].defaultPosePosition = glm::vec3( 0.0, -0.22, 0.02 ); - _joint[ AVATAR_JOINT_LEFT_HEEL ].defaultPosePosition = glm::vec3( 0.0, -0.22, -0.01 ); - _joint[ AVATAR_JOINT_LEFT_TOES ].defaultPosePosition = glm::vec3( 0.0, 0.0, 0.05 ); + _joint[ AVATAR_JOINT_LEFT_KNEE ].defaultPosePosition = glm::vec3( 0.0, -0.22, 0.02 ); + _joint[ AVATAR_JOINT_LEFT_HEEL ].defaultPosePosition = glm::vec3( 0.0, -0.22, -0.01 ); + _joint[ AVATAR_JOINT_LEFT_TOES ].defaultPosePosition = glm::vec3( 0.0, 0.0, 0.05 ); _joint[ AVATAR_JOINT_RIGHT_HIP ].defaultPosePosition = glm::vec3( 0.04, 0.0, -0.02 ); - _joint[ AVATAR_JOINT_RIGHT_KNEE ].defaultPosePosition = glm::vec3( 0.0, -0.22, 0.02 ); - _joint[ AVATAR_JOINT_RIGHT_HEEL ].defaultPosePosition = glm::vec3( 0.0, -0.22, -0.01 ); - _joint[ AVATAR_JOINT_RIGHT_TOES ].defaultPosePosition = glm::vec3( 0.0, 0.0, 0.05 ); + _joint[ AVATAR_JOINT_RIGHT_KNEE ].defaultPosePosition = glm::vec3( 0.0, -0.22, 0.02 ); + _joint[ AVATAR_JOINT_RIGHT_HEEL ].defaultPosePosition = glm::vec3( 0.0, -0.22, -0.01 ); + _joint[ AVATAR_JOINT_RIGHT_TOES ].defaultPosePosition = glm::vec3( 0.0, 0.0, 0.05 ); - // specify the radii of the bone positions - _joint[ AVATAR_JOINT_PELVIS ].radius = 0.06; - _joint[ AVATAR_JOINT_TORSO ].radius = 0.055; - _joint[ AVATAR_JOINT_CHEST ].radius = 0.075; - _joint[ AVATAR_JOINT_NECK_BASE ].radius = 0.03; - _joint[ AVATAR_JOINT_HEAD_BASE ].radius = 0.07; + // specify the radii of the bone positions + _joint[ AVATAR_JOINT_PELVIS ].radius = 0.06; + _joint[ AVATAR_JOINT_TORSO ].radius = 0.055; + _joint[ AVATAR_JOINT_CHEST ].radius = 0.075; + _joint[ AVATAR_JOINT_NECK_BASE ].radius = 0.03; + _joint[ AVATAR_JOINT_HEAD_BASE ].radius = 0.07; - _joint[ AVATAR_JOINT_LEFT_COLLAR ].radius = 0.029; - _joint[ AVATAR_JOINT_LEFT_SHOULDER ].radius = 0.023; - _joint[ AVATAR_JOINT_LEFT_ELBOW ].radius = 0.017; - _joint[ AVATAR_JOINT_LEFT_WRIST ].radius = 0.017; - _joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].radius = 0.01; + _joint[ AVATAR_JOINT_LEFT_COLLAR ].radius = 0.029; + _joint[ AVATAR_JOINT_LEFT_SHOULDER ].radius = 0.023; + _joint[ AVATAR_JOINT_LEFT_ELBOW ].radius = 0.017; + _joint[ AVATAR_JOINT_LEFT_WRIST ].radius = 0.017; + _joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].radius = 0.01; - _joint[ AVATAR_JOINT_RIGHT_COLLAR ].radius = 0.029; - _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].radius = 0.023; - _joint[ AVATAR_JOINT_RIGHT_ELBOW ].radius = 0.015; - _joint[ AVATAR_JOINT_RIGHT_WRIST ].radius = 0.015; - _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].radius = 0.01; + _joint[ AVATAR_JOINT_RIGHT_COLLAR ].radius = 0.029; + _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].radius = 0.023; + _joint[ AVATAR_JOINT_RIGHT_ELBOW ].radius = 0.015; + _joint[ AVATAR_JOINT_RIGHT_WRIST ].radius = 0.015; + _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].radius = 0.01; - _joint[ AVATAR_JOINT_LEFT_HIP ].radius = 0.03; - _joint[ AVATAR_JOINT_LEFT_KNEE ].radius = 0.02; - _joint[ AVATAR_JOINT_LEFT_HEEL ].radius = 0.015; - _joint[ AVATAR_JOINT_LEFT_TOES ].radius = 0.02; + _joint[ AVATAR_JOINT_LEFT_HIP ].radius = 0.03; + _joint[ AVATAR_JOINT_LEFT_KNEE ].radius = 0.02; + _joint[ AVATAR_JOINT_LEFT_HEEL ].radius = 0.015; + _joint[ AVATAR_JOINT_LEFT_TOES ].radius = 0.02; - _joint[ AVATAR_JOINT_RIGHT_HIP ].radius = 0.03; - _joint[ AVATAR_JOINT_RIGHT_KNEE ].radius = 0.02; - _joint[ AVATAR_JOINT_RIGHT_HEEL ].radius = 0.015; - _joint[ AVATAR_JOINT_RIGHT_TOES ].radius = 0.02; + _joint[ AVATAR_JOINT_RIGHT_HIP ].radius = 0.03; + _joint[ AVATAR_JOINT_RIGHT_KNEE ].radius = 0.02; + _joint[ AVATAR_JOINT_RIGHT_HEEL ].radius = 0.015; + _joint[ AVATAR_JOINT_RIGHT_TOES ].radius = 0.02; - // specify the tightness of the springy positions as far as attraction to rigid body - _joint[ AVATAR_JOINT_PELVIS ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 1.0; - _joint[ AVATAR_JOINT_TORSO ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.8; - _joint[ AVATAR_JOINT_CHEST ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.5; - _joint[ AVATAR_JOINT_NECK_BASE ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.4; - _joint[ AVATAR_JOINT_HEAD_BASE ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.3; + // specify the tightness of the springy positions as far as attraction to rigid body + _joint[ AVATAR_JOINT_PELVIS ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 1.0; + _joint[ AVATAR_JOINT_TORSO ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.8; + _joint[ AVATAR_JOINT_CHEST ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.5; + _joint[ AVATAR_JOINT_NECK_BASE ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.4; + _joint[ AVATAR_JOINT_HEAD_BASE ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.3; _joint[ AVATAR_JOINT_LEFT_COLLAR ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.5; - _joint[ AVATAR_JOINT_LEFT_SHOULDER ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.5; - _joint[ AVATAR_JOINT_LEFT_ELBOW ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.5; - _joint[ AVATAR_JOINT_LEFT_WRIST ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.3; - _joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.3; + _joint[ AVATAR_JOINT_LEFT_SHOULDER ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.5; + _joint[ AVATAR_JOINT_LEFT_ELBOW ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.5; + _joint[ AVATAR_JOINT_LEFT_WRIST ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.3; + _joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.3; _joint[ AVATAR_JOINT_RIGHT_COLLAR ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.5; - _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.5; - _joint[ AVATAR_JOINT_RIGHT_ELBOW ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.5; - _joint[ AVATAR_JOINT_RIGHT_WRIST ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.3; + _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.5; + _joint[ AVATAR_JOINT_RIGHT_ELBOW ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.5; + _joint[ AVATAR_JOINT_RIGHT_WRIST ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.3; _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.3; - _joint[ AVATAR_JOINT_LEFT_HIP ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS; - _joint[ AVATAR_JOINT_LEFT_KNEE ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS; - _joint[ AVATAR_JOINT_LEFT_HEEL ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS; - _joint[ AVATAR_JOINT_LEFT_TOES ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS; - _joint[ AVATAR_JOINT_RIGHT_HIP ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS; - _joint[ AVATAR_JOINT_RIGHT_KNEE ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS; - _joint[ AVATAR_JOINT_RIGHT_HEEL ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS; - _joint[ AVATAR_JOINT_RIGHT_TOES ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS; + _joint[ AVATAR_JOINT_LEFT_HIP ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS; + _joint[ AVATAR_JOINT_LEFT_KNEE ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS; + _joint[ AVATAR_JOINT_LEFT_HEEL ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS; + _joint[ AVATAR_JOINT_LEFT_TOES ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS; + _joint[ AVATAR_JOINT_RIGHT_HIP ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS; + _joint[ AVATAR_JOINT_RIGHT_KNEE ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS; + _joint[ AVATAR_JOINT_RIGHT_HEEL ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS; + _joint[ AVATAR_JOINT_RIGHT_TOES ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS; - // to aid in hand-shaking and hand-holding, the right hand is not collidable - _joint[ AVATAR_JOINT_RIGHT_ELBOW ].isCollidable = false; - _joint[ AVATAR_JOINT_RIGHT_WRIST ].isCollidable = false; - _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].isCollidable = false; + // to aid in hand-shaking and hand-holding, the right hand is not collidable + _joint[ AVATAR_JOINT_RIGHT_ELBOW ].isCollidable = false; + _joint[ AVATAR_JOINT_RIGHT_WRIST ].isCollidable = false; + _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].isCollidable = false; - // calculate bone length - calculateBoneLengths(); + // calculate bone length + calculateBoneLengths(); _pelvisStandingHeight = - _joint[ AVATAR_JOINT_LEFT_HEEL ].radius + - _joint[ AVATAR_JOINT_LEFT_HEEL ].length + - _joint[ AVATAR_JOINT_LEFT_KNEE ].length; + _joint[ AVATAR_JOINT_LEFT_HEEL ].radius + + _joint[ AVATAR_JOINT_LEFT_HEEL ].length + + _joint[ AVATAR_JOINT_LEFT_KNEE ].length; _height = ( @@ -1174,39 +1180,39 @@ void Avatar::initializeSkeleton() { ); //printf( "_height = %f\n", _height ); - // generate world positions - updateSkeleton(); + // generate world positions + updateSkeleton(); } void Avatar::calculateBoneLengths() { - for (int b = 0; b < NUM_AVATAR_JOINTS; b++) { - _joint[b].length = glm::length( _joint[b].defaultPosePosition ); - } + for (int b = 0; b < NUM_AVATAR_JOINTS; b++) { + _joint[b].length = glm::length( _joint[b].defaultPosePosition ); + } - _maxArmLength - = _joint[ AVATAR_JOINT_RIGHT_ELBOW ].length - + _joint[ AVATAR_JOINT_RIGHT_WRIST ].length - + _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].length; + _maxArmLength + = _joint[ AVATAR_JOINT_RIGHT_ELBOW ].length + + _joint[ AVATAR_JOINT_RIGHT_WRIST ].length + + _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].length; } void Avatar::updateSkeleton() { // rotate body... - _orientation.setToIdentity(); - _orientation.yaw ( _bodyYaw ); - _orientation.pitch( _bodyPitch ); - _orientation.roll ( _bodyRoll ); + _orientation.setToIdentity(); + _orientation.yaw ( _bodyYaw ); + _orientation.pitch( _bodyPitch ); + _orientation.roll ( _bodyRoll ); - // calculate positions of all bones by traversing the skeleton tree: - for (int b = 0; b < NUM_AVATAR_JOINTS; b++) { - if ( _joint[b].parent == AVATAR_JOINT_NULL ) { + // calculate positions of all bones by traversing the skeleton tree: + for (int b = 0; b < NUM_AVATAR_JOINTS; b++) { + if ( _joint[b].parent == AVATAR_JOINT_NULL ) { _joint[b].orientation.set( _orientation ); - _joint[b].position = _position; - } - else { - _joint[b].orientation.set( _joint[ _joint[b].parent ].orientation ); - _joint[b].position = _joint[ _joint[b].parent ].position; - } + _joint[b].position = _position; + } + else { + _joint[b].orientation.set( _joint[ _joint[b].parent ].orientation ); + _joint[b].position = _joint[ _joint[b].parent ].position; + } // if this is not my avatar, then hand position comes from transmitted data if ( ! _isMine ) { @@ -1214,65 +1220,64 @@ void Avatar::updateSkeleton() { } // the following will be replaced by a proper rotation...close - float xx = glm::dot( _joint[b].defaultPosePosition, _joint[b].orientation.getRight() ); - float yy = glm::dot( _joint[b].defaultPosePosition, _joint[b].orientation.getUp () ); - float zz = glm::dot( _joint[b].defaultPosePosition, _joint[b].orientation.getFront() ); + float xx = glm::dot( _joint[b].defaultPosePosition, _joint[b].orientation.getRight() ); + float yy = glm::dot( _joint[b].defaultPosePosition, _joint[b].orientation.getUp () ); + float zz = glm::dot( _joint[b].defaultPosePosition, _joint[b].orientation.getFront() ); - glm::vec3 rotatedJointVector( xx, yy, zz ); + glm::vec3 rotatedJointVector( xx, yy, zz ); //glm::vec3 myEuler ( 0.0f, 0.0f, 0.0f ); //glm::quat myQuat ( myEuler ); - _joint[b].position += rotatedJointVector; - } + _joint[b].position += rotatedJointVector; + } } void Avatar::initializeBodySprings() { - for (int b = 0; b < NUM_AVATAR_JOINTS; b++) { - _joint[b].springyPosition = _joint[b].position; - _joint[b].springyVelocity = glm::vec3( 0.0f, 0.0f, 0.0f ); - } + for (int b = 0; b < NUM_AVATAR_JOINTS; b++) { + _joint[b].springyPosition = _joint[b].position; + _joint[b].springyVelocity = glm::vec3( 0.0f, 0.0f, 0.0f ); + } } - void Avatar::updateBodySprings( float deltaTime ) { - for (int b = 0; b < NUM_AVATAR_JOINTS; b++) { - glm::vec3 springVector( _joint[b].springyPosition ); + for (int b = 0; b < NUM_AVATAR_JOINTS; b++) { + glm::vec3 springVector( _joint[b].springyPosition ); - if ( _joint[b].parent == AVATAR_JOINT_NULL ) { - springVector -= _position; - } - else { - springVector -= _joint[ _joint[b].parent ].springyPosition; - } + if ( _joint[b].parent == AVATAR_JOINT_NULL ) { + springVector -= _position; + } + else { + springVector -= _joint[ _joint[b].parent ].springyPosition; + } - float length = glm::length( springVector ); + float length = glm::length( springVector ); - if ( length > 0.0f ) { - glm::vec3 springDirection = springVector / length; + if ( length > 0.0f ) { + glm::vec3 springDirection = springVector / length; - float force = (length - _joint[b].length) * BODY_SPRING_FORCE * deltaTime; + float force = (length - _joint[b].length) * BODY_SPRING_FORCE * deltaTime; - _joint[b].springyVelocity -= springDirection * force; + _joint[b].springyVelocity -= springDirection * force; if ( _joint[b].parent != AVATAR_JOINT_NULL ) { _joint[_joint[b].parent].springyVelocity += springDirection * force; } - } + } _joint[b].springyVelocity += (_joint[b].position - _joint[b].springyPosition) * _joint[b].springBodyTightness * deltaTime; - float decay = 1.0 - BODY_SPRING_DECAY * deltaTime; + float decay = 1.0 - BODY_SPRING_DECAY * deltaTime; - if (decay > 0.0) { - _joint[b].springyVelocity *= decay; - } - else { - _joint[b].springyVelocity = glm::vec3( 0.0f, 0.0f, 0.0f ); - } + if (decay > 0.0) { + _joint[b].springyVelocity *= decay; + } + else { + _joint[b].springyVelocity = glm::vec3( 0.0f, 0.0f, 0.0f ); + } - _joint[b].springyPosition += _joint[b].springyVelocity; - } + _joint[b].springyPosition += _joint[b].springyVelocity; + } } const glm::vec3& Avatar::getHeadPosition() const { @@ -1282,55 +1287,53 @@ const glm::vec3& Avatar::getHeadPosition() const { // return _joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition; //} - return _joint[ AVATAR_JOINT_HEAD_BASE ].position; + return _joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition; } void Avatar::updateArmIKAndConstraints( float deltaTime ) { - // determine the arm vector - glm::vec3 armVector = _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position; - armVector -= _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].position; + // determine the arm vector + glm::vec3 armVector = _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position; + armVector -= _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].position; - // test to see if right hand is being dragged beyond maximum arm length - float distance = glm::length( armVector ); + // test to see if right hand is being dragged beyond maximum arm length + float distance = glm::length( armVector ); - // don't let right hand get dragged beyond maximum arm length... - if ( distance > _maxArmLength ) { - // reset right hand to be constrained to maximum arm length - _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position = _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].position; - glm::vec3 armNormal = armVector / distance; - armVector = armNormal * _maxArmLength; - distance = _maxArmLength; - glm::vec3 constrainedPosition = _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].position; - constrainedPosition += armVector; - _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position = constrainedPosition; - } + // don't let right hand get dragged beyond maximum arm length... + if ( distance > _maxArmLength ) { + // reset right hand to be constrained to maximum arm length + _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position = _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].position; + glm::vec3 armNormal = armVector / distance; + armVector = armNormal * _maxArmLength; + distance = _maxArmLength; + glm::vec3 constrainedPosition = _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].position; + constrainedPosition += armVector; + _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position = constrainedPosition; + } - // set elbow position - glm::vec3 newElbowPosition = _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].position; - newElbowPosition += armVector * ONE_HALF; + // set elbow position + glm::vec3 newElbowPosition = _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].position; + newElbowPosition += armVector * ONE_HALF; - glm::vec3 perpendicular = glm::cross( _orientation.getFront(), armVector ); + glm::vec3 perpendicular = glm::cross( _orientation.getFront(), armVector ); - newElbowPosition += perpendicular * ( 1.0f - ( _maxArmLength / distance ) ) * ONE_HALF; - _joint[ AVATAR_JOINT_RIGHT_ELBOW ].position = newElbowPosition; + newElbowPosition += perpendicular * ( 1.0f - ( _maxArmLength / distance ) ) * ONE_HALF; + _joint[ AVATAR_JOINT_RIGHT_ELBOW ].position = newElbowPosition; - // set wrist position - glm::vec3 vv( _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position ); - vv -= _joint[ AVATAR_JOINT_RIGHT_ELBOW ].position; - glm::vec3 newWristPosition = _joint[ AVATAR_JOINT_RIGHT_ELBOW ].position + vv * 0.7f; - _joint[ AVATAR_JOINT_RIGHT_WRIST ].position = newWristPosition; + // set wrist position + glm::vec3 vv( _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position ); + vv -= _joint[ AVATAR_JOINT_RIGHT_ELBOW ].position; + glm::vec3 newWristPosition = _joint[ AVATAR_JOINT_RIGHT_ELBOW ].position + vv * 0.7f; + _joint[ AVATAR_JOINT_RIGHT_WRIST ].position = newWristPosition; } - - void Avatar::renderBody() { // Render joint positions as spheres - for (int b = 0; b < NUM_AVATAR_JOINTS; b++) { + for (int b = 0; b < NUM_AVATAR_JOINTS; b++) { if ( b != AVATAR_JOINT_HEAD_BASE ) { // the head is rendered as a special case in "renderHead" @@ -1352,35 +1355,38 @@ void Avatar::renderBody() { glPopMatrix(); } } - } + } // Render lines connecting the joint positions - if ( _usingBodySprings ) { - glColor3f( 0.4f, 0.5f, 0.6f ); - glLineWidth(3.0); + if ( _usingBodySprings ) { + glColor3f( 0.4f, 0.5f, 0.6f ); + glLineWidth(3.0); - for (int b = 1; b < NUM_AVATAR_JOINTS; b++) { - if ( _joint[b].parent != AVATAR_JOINT_NULL ) { + for (int b = 1; b < NUM_AVATAR_JOINTS; b++) { + if ( _joint[b].parent != AVATAR_JOINT_NULL ) + if ( b != AVATAR_JOINT_HEAD_TOP ) { glBegin( GL_LINE_STRIP ); glVertex3fv( &_joint[ _joint[ b ].parent ].springyPosition.x ); glVertex3fv( &_joint[ b ].springyPosition.x ); glEnd(); } - } - } - else { - glColor3fv( skinColor ); - glLineWidth(3.0); + } + } + /* + else { + glColor3fv( skinColor ); + glLineWidth(3.0); - for (int b = 1; b < NUM_AVATAR_JOINTS; b++) { + for (int b = 1; b < NUM_AVATAR_JOINTS; b++) { if ( _joint[b].parent != AVATAR_JOINT_NULL ) { glBegin( GL_LINE_STRIP ); glVertex3fv( &_joint[ _joint[ b ].parent ].position.x ); glVertex3fv( &_joint[ b ].position.x); glEnd(); } - } - } + } + } + */ } void Avatar::SetNewHeadTarget(float pitch, float yaw) { From d0444ee5b7dbf8628716109f9f8249dca51f65c2 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 3 May 2013 12:22:20 -0700 Subject: [PATCH 44/52] accept a local address and port from requestor --- pairing-server/src/main.cpp | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/pairing-server/src/main.cpp b/pairing-server/src/main.cpp index d869170344..2b2e416e66 100644 --- a/pairing-server/src/main.cpp +++ b/pairing-server/src/main.cpp @@ -36,15 +36,15 @@ int main(int argc, const char* argv[]) { UDPSocket serverSocket(PAIRING_SERVER_LISTEN_PORT); sockaddr_in senderSocket; - char deviceData[MAX_PACKET_SIZE_BYTES] = {}; + char senderData[MAX_PACKET_SIZE_BYTES] = {}; ssize_t receivedBytes = 0; std::vector devices; while (true) { - if (serverSocket.receive((sockaddr *)&senderSocket, &deviceData, &receivedBytes)) { + if (serverSocket.receive((sockaddr *)&senderSocket, &senderData, &receivedBytes)) { - if (deviceData[0] == 'A') { + if (senderData[0] == 'A') { // this is a device reporting itself as available // create a new PairableDevice @@ -53,7 +53,7 @@ int main(int argc, const char* argv[]) { int addressBytes[4]; int socketPort = 0; - int numMatches = sscanf(deviceData, "A %s %d.%d.%d.%d:%d %s", + int numMatches = sscanf(senderData, "Available %s %d.%d.%d.%d:%d %s", newDevice.identifier, &addressBytes[3], &addressBytes[2], @@ -80,18 +80,23 @@ int main(int argc, const char* argv[]) { printf("Adding device %s (%s) to list\n", newDevice.identifier, newDevice.name); devices.push_back(newDevice); } - } else if (deviceData[0] == 'P') { + } else if (senderData[0] == 'F') { // this is a client looking to pair with a device // send the most recent device this address so it can attempt to pair - char requestorSocketString[INET_ADDRSTRLEN + 6] = {}; - char requestorAddress[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, &(senderSocket.sin_addr), requestorAddress, INET_ADDRSTRLEN); + char requestorAddress[INET_ADDRSTRLEN] = {}; + int requestorPort = 0; - sprintf(requestorSocketString, "%s:%d", requestorAddress, ntohs(senderSocket.sin_port)); + int requestorMatches = sscanf(senderData, "Find %[^:]:%d", requestorAddress, &requestorPort); - PairableDevice lastDevice = devices[devices.size() - 1]; - serverSocket.send((sockaddr*) &lastDevice.sendingSocket, requestorSocketString, strlen(requestorSocketString)); + if (requestorMatches == 2) { + PairableDevice lastDevice = devices[devices.size() - 1]; + + char pairData[INET_ADDRSTRLEN + 6] = {}; + sprintf(pairData, "%s:%d", requestorAddress, requestorPort); + + serverSocket.send((sockaddr*) &lastDevice.sendingSocket, pairData, strlen(pairData)); + } } } } From 597c8336bdfa1824857b8b6c5d0085b05e4d94b0 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 3 May 2013 12:34:29 -0700 Subject: [PATCH 45/52] change the pairing server listen port to 7247 --- pairing-server/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pairing-server/src/main.cpp b/pairing-server/src/main.cpp index 2b2e416e66..a17f425443 100644 --- a/pairing-server/src/main.cpp +++ b/pairing-server/src/main.cpp @@ -12,7 +12,7 @@ #include #include -const int PAIRING_SERVER_LISTEN_PORT = 52934; +const int PAIRING_SERVER_LISTEN_PORT = 7247; const int MAX_PACKET_SIZE_BYTES = 1400; struct PairableDevice { From 2ab7bc0d8a72fb3f57e0fe6444fcc812d22b2c3c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 3 May 2013 13:01:02 -0700 Subject: [PATCH 46/52] add cstdio for sscanf and printf --- pairing-server/src/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/pairing-server/src/main.cpp b/pairing-server/src/main.cpp index a17f425443..3c6aaeae57 100644 --- a/pairing-server/src/main.cpp +++ b/pairing-server/src/main.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include From 82db78cc674b31f1c4c66b70f359a3619ef57030 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 3 May 2013 14:41:56 -0700 Subject: [PATCH 47/52] include cstring for use of strlen --- pairing-server/src/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/pairing-server/src/main.cpp b/pairing-server/src/main.cpp index 3c6aaeae57..07b769d8bc 100644 --- a/pairing-server/src/main.cpp +++ b/pairing-server/src/main.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include From 90a08b4dd86fa8c89ee725117cb71427c628018d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 3 May 2013 14:45:47 -0700 Subject: [PATCH 48/52] cleanup in Audio and Util --- interface/src/Audio.cpp | 7 ++----- interface/src/Util.cpp | 2 -- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index a83bf5e4d5..69e0b148f3 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -317,8 +317,8 @@ void *receiveAudioViaUDP(void *args) { if (LOG_SAMPLE_DELAY) { - char *directory = new char[50]; - char *filename = new char[50]; + char directory[50]; + char filename[50]; sprintf(directory, "%s/Desktop/echo_tests", getenv("HOME")); @@ -326,9 +326,6 @@ void *receiveAudioViaUDP(void *args) { sprintf(filename, "%s/%ld.csv", directory, previousReceiveTime.tv_sec); logFile.open(filename, std::ios::out); - - delete[] directory; - delete[] filename; } while (!stopAudioReceiveThread) { diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index 138ae7aef4..aeba937e0a 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -24,7 +24,6 @@ using namespace std; // no clue which versions are affected... #define WORKAROUND_BROKEN_GLUT_STROKES // see http://www.opengl.org/resources/libraries/glut/spec3/node78.html -static float MONO_STROKE_WIDTH_GLUT = 104.76; void eulerToOrthonormals(glm::vec3 * angles, glm::vec3 * front, glm::vec3 * right, glm::vec3 * up) { // @@ -172,7 +171,6 @@ void drawtext(int x, int y, float scale, float rotate, float thick, int mono, // // Draws text on screen as stroked so it can be resized // - int len, i; glPushMatrix(); glTranslatef( static_cast(x), static_cast(y), 0.0f); glColor3f(r,g,b); From 1a8564f9d9b48acbd5645b3f96a57ecf9548517f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 3 May 2013 15:05:28 -0700 Subject: [PATCH 49/52] store avatar position and yaw in file to restore on relaunch --- interface/src/Avatar.cpp | 20 ++++++++++++++++++++ interface/src/Avatar.h | 3 +++ interface/src/main.cpp | 6 +++++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 7a4468d608..675d4ce1c0 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -1539,3 +1539,23 @@ glm::vec3 Avatar::getGravity(glm::vec3 pos) { return glm::vec3(0.f, 0.f, 0.f); } } + +const char AVATAR_DATA_FILENAME[] = "avatar.ifd"; + +void Avatar::writeAvatarDataToFile() { + // write the avatar position and yaw to a local file + FILE* avatarFile = fopen(AVATAR_DATA_FILENAME, "w"); + + if (avatarFile) { + fprintf(avatarFile, "%f,%f,%f %f", _position.x, _position.y, _position.z, _bodyYaw); + fclose(avatarFile); + } +} + +void Avatar::readAvatarDataFromFile() { + FILE* avatarFile = fopen(AVATAR_DATA_FILENAME, "r"); + + if (avatarFile) { + fscanf(avatarFile, "%f,%f,%f %f", &_position.x, &_position.y, &_position.z, &_bodyYaw); + } +} diff --git a/interface/src/Avatar.h b/interface/src/Avatar.h index e327df25c2..d2570d1976 100644 --- a/interface/src/Avatar.h +++ b/interface/src/Avatar.h @@ -145,6 +145,9 @@ public: // Find out what the local gravity vector is at this location glm::vec3 getGravity(glm::vec3 pos); + + void writeAvatarDataToFile(); + void readAvatarDataFromFile(); private: diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 7bf7a181ff..125cc07597 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -344,7 +344,9 @@ void init(void) void terminate () { // Close serial port - //close(serial_fd); + // close(serial_fd); + + myAvatar.writeAvatarDataToFile(); #ifndef _WIN32 audio.terminate(); @@ -1944,6 +1946,8 @@ int main(int argc, const char * argv[]) printLog("Network receive thread created.\n"); } + myAvatar.readAvatarDataFromFile(); + glutTimerFunc(1000, Timer, 0); glutMainLoop(); From da93b596de05c6b9eb9e355002998335280fcd37 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 3 May 2013 15:08:48 -0700 Subject: [PATCH 50/52] some deletion cleanup in main.cpp --- interface/src/main.cpp | 50 ++++++++++++------------------------------ 1 file changed, 14 insertions(+), 36 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 125cc07597..990f4e8197 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -1491,8 +1491,7 @@ void specialkeyUp(int k, int x, int y) { } -void specialkey(int k, int x, int y) -{ +void specialkey(int k, int x, int y) { if (::chatEntryOn) { chatEntry.specialKey(k); return; @@ -1534,7 +1533,6 @@ void keyUp(unsigned char k, int x, int y) { if (k == 's') myAvatar.setDriveKeys(BACK, 0); if (k == 'a') myAvatar.setDriveKeys(ROT_LEFT, 0); if (k == 'd') myAvatar.setDriveKeys(ROT_RIGHT, 0); - } void key(unsigned char k, int x, int y) @@ -1626,8 +1624,7 @@ void key(unsigned char k, int x, int y) } // Receive packets from other agents/servers and decide what to do with them! -void* networkReceive(void* args) -{ +void* networkReceive(void* args) { sockaddr senderAddress; ssize_t bytesReceived; @@ -1699,9 +1696,7 @@ void idle(void) { handControl.stop(); } - // // Sample hardware, update view frustum if needed, Lsend avatar data to mixer/agents - // updateAvatar(deltaTime); // read incoming packets from network @@ -1732,9 +1727,7 @@ void idle(void) { } } - -void reshape(int width, int height) -{ +void reshape(int width, int height) { WIDTH = width; HEIGHT = height; aspectRatio = ((float)width/(float)height); // based on screen resize @@ -1760,17 +1753,12 @@ void reshape(int width, int height) camera.setFieldOfView(fov = 60); } - //printLog("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); glLoadIdentity(); // XXXBHG - If we're in view frustum mode, then we need to do this little bit of hackery so that @@ -1787,42 +1775,32 @@ void reshape(int width, int height) glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - - } -void mouseFunc( int button, int state, int x, int y ) -{ - if( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN ) - { - if (!menu.mouseClick(x, y)) { +void mouseFunc(int button, int state, int x, int y) { + if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN ) { + if (state == GLUT_DOWN && !menu.mouseClick(x, y)) { mouseX = x; mouseY = y; mousePressed = 1; + } else if (state == GLUT_UP) { + mouseX = x; + mouseY = y; + mousePressed = 0; } - } - if( button == GLUT_LEFT_BUTTON && state == GLUT_UP ) { - mouseX = x; - mouseY = y; - mousePressed = 0; - } - + } } -void motionFunc( int x, int y) -{ +void motionFunc(int x, int y) { mouseX = x; mouseY = y; } -void mouseoverFunc( int x, int y) -{ +void mouseoverFunc(int x, int y){ menu.mouseOver(x, y); mouseX = x; mouseY = y; - if (mousePressed == 0) - {} } void attachNewHeadToAgent(Agent *newAgent) { From 31e9c1834619fd8b9af55ae83073e0e035d8f898 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 3 May 2013 15:09:44 -0700 Subject: [PATCH 51/52] couple of extra line deletions in main.cpp --- interface/src/main.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 990f4e8197..8f5a70cbe6 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -1292,7 +1292,6 @@ int doRandomizeVoxelColors(int state) { return state; } - int doFalseRandomizeVoxelColors(int state) { if (state == MENU_ROW_PICKED) { ::voxels.falseColorizeRandom(); @@ -1324,7 +1323,6 @@ int doFalseColorizeInView(int state) { return state; } - const char* modeAll = " - All "; const char* modeVectors = " - Vectors "; const char* modePlanes = " - Planes "; @@ -1398,8 +1396,7 @@ void testPointToVoxel() float y=0; float z=0; float s=0.1; - for (float x=0; x<=1; x+= 0.05) - { + for (float x=0; x<=1; x+= 0.05) { printLog(" x=%f"); unsigned char red = 200; //randomColorValue(65); @@ -1488,7 +1485,6 @@ void specialkeyUp(int k, int x, int y) { myAvatar.setDriveKeys(RIGHT, 0); myAvatar.setDriveKeys(ROT_RIGHT, 0); } - } void specialkey(int k, int x, int y) { From bd3c902b683520985d1d30993a70cfc0a589a589 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 3 May 2013 15:13:38 -0700 Subject: [PATCH 52/52] remove logging of audio stats --- interface/src/Audio.cpp | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 69e0b148f3..7474f434b7 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -80,10 +80,6 @@ timeval firstPlaybackTimer; int packetsReceivedThisPlayback = 0; float usecsAtStartup = 0; -#define LOG_SAMPLE_DELAY 0 - -std::ofstream logFile; - /** * Audio callback used by portaudio. * Communicates with Audio via a shared pointer to Audio::data. @@ -315,31 +311,12 @@ void *receiveAudioViaUDP(void *args) { stdev.reset(); - if (LOG_SAMPLE_DELAY) { - - char directory[50]; - char filename[50]; - - sprintf(directory, "%s/Desktop/echo_tests", getenv("HOME")); - - mkdir(directory, S_IRWXU | S_IRWXG | S_IRWXO); - sprintf(filename, "%s/%ld.csv", directory, previousReceiveTime.tv_sec); - - logFile.open(filename, std::ios::out); - } - while (!stopAudioReceiveThread) { if (sharedAudioData->audioSocket->receive((void *)receivedData, &receivedBytes)) { gettimeofday(¤tReceiveTime, NULL); totalPacketsReceived++; - - if (LOG_SAMPLE_DELAY) { - // write time difference (in microseconds) between packet receipts to file - double timeDiff = diffclock(&previousReceiveTime, ¤tReceiveTime); - logFile << timeDiff << std::endl; - } double tDiff = diffclock(&previousReceiveTime, ¤tReceiveTime); //printLog("tDiff %4.1f\n", tDiff); @@ -559,8 +536,7 @@ void Audio::render(int screenWidth, int screenHeight) * @return Returns true if the initialization was successful, or false if an error occured. The error code may be retrieved by Audio::getError(). */ -bool Audio::terminate () -{ +bool Audio::terminate() { stopAudioReceiveThread = true; pthread_join(audioReceiveThread, NULL); @@ -574,7 +550,6 @@ bool Audio::terminate () if (paError != paNoError) goto error; } - logFile.close(); delete audioData; return true;