From b74ceae61ae25bb7220ceb4954ee1acf9cafdc89 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Thu, 23 May 2013 22:52:43 -0700 Subject: [PATCH 01/17] added avatar hair --- interface/src/Application.cpp | 4 +- interface/src/Avatar.cpp | 11 ++- interface/src/Avatar.h | 3 +- interface/src/Head.cpp | 167 +++++++++++++++++++++++++++++++++- interface/src/Head.h | 18 +++- 5 files changed, 192 insertions(+), 11 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b9b0948490..c4db1bd71d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1707,13 +1707,13 @@ void Application::displaySide(Camera& whichCamera) { 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(false); + avatar->render(false, _myCamera.getPosition()); } } agentList->unlock(); // Render my own Avatar - _myAvatar.render(_lookingInMirror->isChecked()); + _myAvatar.render(_lookingInMirror->isChecked(), _myCamera.getPosition()); _myAvatar.setDisplayingLookatVectors(_renderLookatOn->isChecked()); } diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index bdfd7c8691..a48e4e9b48 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -79,6 +79,7 @@ Avatar::Avatar(bool isMine) : _bodyRollDelta(0.0f), _movedHandOffset(0.0f, 0.0f, 0.0f), _rotation(0.0f, 0.0f, 0.0f, 0.0f), + _cameraPosition(0.0f, 0.0f, 0.0f), _mode(AVATAR_MODE_STANDING), _handHoldingPosition(0.0f, 0.0f, 0.0f), _velocity(0.0f, 0.0f, 0.0f), @@ -725,7 +726,9 @@ void Avatar::setGravity(glm::vec3 gravity) { _head.setGravity(_gravity); } -void Avatar::render(bool lookingInMirror) { +void Avatar::render(bool lookingInMirror, glm::vec3 cameraPosition) { + + _cameraPosition = cameraPosition; if (_isMine && usingBigSphereCollisionTest) { // show TEST big sphere @@ -745,7 +748,7 @@ void Avatar::render(bool lookingInMirror) { // if this is my avatar, then render my interactions with the other avatar if (_isMine) { - _avatarTouch.render(getCameraPosition()); + _avatarTouch.render(_cameraPosition); } // Render the balls @@ -1132,11 +1135,11 @@ void Avatar::renderBody(bool lookingInMirror) { // Render the body as balls and cones for (int b = 0; b < NUM_AVATAR_JOINTS; b++) { - float distanceToCamera = glm::length(getCameraPosition() - _joint[b].position); + float distanceToCamera = glm::length(_cameraPosition - _joint[b].position); // Always render other people, and render myself when beyond threshold distance if (b == AVATAR_JOINT_HEAD_BASE) { // the head is rendered as a special case if (lookingInMirror || !_isMine || distanceToCamera > RENDER_OPAQUE_BEYOND) { - _head.render(lookingInMirror); + _head.render(lookingInMirror, _cameraPosition); } } else if (!_isMine || distanceToCamera > RENDER_TRANSLUCENT_BEYOND) { // Render the sphere at the joint diff --git a/interface/src/Avatar.h b/interface/src/Avatar.h index 59f9018af3..964a0a04f6 100644 --- a/interface/src/Avatar.h +++ b/interface/src/Avatar.h @@ -107,7 +107,7 @@ public: Head& getHead() { return _head; } void setMousePressed(bool pressed); - void render(bool lookingInMirror); + void render(bool lookingInMirror, glm::vec3 cameraPosition); void renderBody(bool lookingInMirror); void simulate(float deltaTime, Transmitter* transmitter); void setMovedHandOffset(glm::vec3 movedHandOffset) { _movedHandOffset = movedHandOffset; } @@ -162,6 +162,7 @@ private: glm::quat _rotation; // the rotation of the avatar body as a whole expressed as a quaternion AvatarJoint _joint[ NUM_AVATAR_JOINTS ]; AvatarMode _mode; + glm::vec3 _cameraPosition; glm::vec3 _handHoldingPosition; glm::vec3 _velocity; glm::vec3 _thrust; diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index cb42c6cc54..c29145774d 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -21,6 +21,13 @@ const float HEAD_MOTION_DECAY = 0.1; const float MINIMUM_EYE_ROTATION_DOT = 0.5f; // based on a dot product: 1.0 is straight ahead, 0.0 is 90 degrees off const float EYEBALL_RADIUS = 0.017; const float EYEBALL_COLOR[3] = { 0.9f, 0.9f, 0.8f }; +const float HAIR_COLOR[3] = { 0.8f, 0.6f, 0.5f }; +const float HAIR_SPRING_FORCE = 10.0f; +const float HAIR_TORQUE_FORCE = 0.1f; +const float HAIR_GRAVITY_FORCE = 0.05f; +const float HAIR_DRAG = 10.0f; +const float HAIR_LENGTH = 0.06f; +const float HAIR_THICKNESS = 0.02f; const float IRIS_RADIUS = 0.007; const float IRIS_PROTRUSION = 0.0145f; const char IRIS_TEXTURE_FILENAME[] = "resources/images/iris.png"; @@ -55,14 +62,31 @@ Head::Head() : _bodyRotation(0.0f, 0.0f, 0.0f), _headRotation(0.0f, 0.0f, 0.0f), _renderLookatVectors(false) { + + for (int t = 0; t < NUM_HAIR_TUFTS; t ++) { + _hairTuft[t].length = HAIR_LENGTH; + _hairTuft[t].thickness = HAIR_THICKNESS; + _hairTuft[t].basePosition = glm::vec3(0.0f, 0.0f, 0.0f); + _hairTuft[t].midPosition = glm::vec3(0.0f, 0.0f, 0.0f); + _hairTuft[t].endPosition = glm::vec3(0.0f, 0.0f, 0.0f); + _hairTuft[t].midVelocity = glm::vec3(0.0f, 0.0f, 0.0f); + _hairTuft[t].endVelocity = glm::vec3(0.0f, 0.0f, 0.0f); + } } void Head::reset() { _yaw = _pitch = _roll = 0.0f; _leanForward = _leanSideways = 0.0f; + + for (int t = 0; t < NUM_HAIR_TUFTS; t ++) { + _hairTuft[t].basePosition = _position + _orientation.getUp() * _scale * 0.9f; + _hairTuft[t].midPosition = _hairTuft[t].basePosition + _orientation.getUp() * _hairTuft[t].length * ONE_HALF; + _hairTuft[t].endPosition = _hairTuft[t].midPosition + _orientation.getUp() * _hairTuft[t].length * ONE_HALF; + _hairTuft[t].midVelocity = glm::vec3(0.0f, 0.0f, 0.0f); + _hairTuft[t].endVelocity = glm::vec3(0.0f, 0.0f, 0.0f); + } } - void Head::simulate(float deltaTime, bool isMine) { const float HEAD_MOTION_DECAY = 0.00; @@ -109,7 +133,9 @@ void Head::simulate(float deltaTime, bool isMine) { _browAudioLift *= 0.7f; // based on the nature of the lookat position, determine if the eyes can look / are looking at it. - determineIfLookingAtSomething(); + determineIfLookingAtSomething(); + + updateHair(deltaTime); } void Head::determineIfLookingAtSomething() { @@ -168,7 +194,7 @@ void Head::calculateGeometry(bool lookingInMirror) { } -void Head::render(bool lookingInMirror) { +void Head::render(bool lookingInMirror, glm::vec3 cameraPosition) { calculateGeometry(lookingInMirror); @@ -180,6 +206,7 @@ void Head::render(bool lookingInMirror) { renderEars(); renderMouth(); renderEyeBrows(); + renderHair(cameraPosition); if (_renderLookatVectors && _lookingAtSomething) { renderLookatVectors(_leftEyePosition, _rightEyePosition, _lookAtPosition); @@ -430,4 +457,138 @@ void Head::renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosi } +void Head::updateHair(float deltaTime) { + + for (int t = 0; t < NUM_HAIR_TUFTS; t ++) { + + float fraction = (float)t / (float)(NUM_HAIR_TUFTS-1); + + float angle = -20.0f + 40.0f * fraction; + + float radian = angle * PI_OVER_180; + glm::vec3 baseDirection + = _orientation.getFront() * sinf(radian) + + _orientation.getUp() * cosf(radian); + + _hairTuft[t].basePosition = _position + _scale * 0.9f * baseDirection; + + glm::vec3 midAxis = _hairTuft[t].midPosition - _hairTuft[t].basePosition; + glm::vec3 endAxis = _hairTuft[t].endPosition - _hairTuft[t].midPosition; + + float midLength = glm::length(midAxis); + float endLength = glm::length(endAxis); + + glm::vec3 midDirection; + glm::vec3 endDirection; + + if (midLength > 0.0f) { + midDirection = midAxis / midLength; + } else { + midDirection = _orientation.getUp(); + } + + if (endLength > 0.0f) { + endDirection = endAxis / endLength; + } else { + endDirection = _orientation.getUp(); + } + + // add spring force + float midForce = midLength - _hairTuft[t].length * ONE_HALF; + float endForce = endLength - _hairTuft[t].length * ONE_HALF; + _hairTuft[t].midVelocity -= midDirection * midForce * HAIR_SPRING_FORCE * deltaTime; + _hairTuft[t].endVelocity -= endDirection * endForce * HAIR_SPRING_FORCE * deltaTime; + + // add gravity force + glm::vec3 gravityForce = _gravity * HAIR_GRAVITY_FORCE * deltaTime; + _hairTuft[t].midVelocity += gravityForce; + _hairTuft[t].endVelocity += gravityForce; + + // add torque force + _hairTuft[t].midVelocity += baseDirection * HAIR_TORQUE_FORCE * deltaTime; + _hairTuft[t].endVelocity += midDirection * HAIR_TORQUE_FORCE * deltaTime; + + // add drag force + float momentum = 1.0f - (HAIR_DRAG * deltaTime); + if (momentum < 0.0f) { + _hairTuft[t].midVelocity = glm::vec3(0.0f, 0.0f, 0.0f); + _hairTuft[t].endVelocity = glm::vec3(0.0f, 0.0f, 0.0f); + } else { + _hairTuft[t].midVelocity *= momentum; + _hairTuft[t].endVelocity *= momentum; + } + + // update position by velocity + _hairTuft[t].midPosition += _hairTuft[t].midVelocity; + _hairTuft[t].endPosition += _hairTuft[t].endVelocity; + + // clamp lengths + glm::vec3 newMidVector = _hairTuft[t].midPosition - _hairTuft[t].basePosition; + glm::vec3 newEndVector = _hairTuft[t].endPosition - _hairTuft[t].midPosition; + + float newMidLength = glm::length(newMidVector); + float newEndLength = glm::length(newEndVector); + + glm::vec3 newMidDirection; + glm::vec3 newEndDirection; + + if (newMidLength > 0.0f) { + newMidDirection = newMidVector/newMidLength; + } else { + newMidDirection = _orientation.getUp(); + } + + if (newEndLength > 0.0f) { + newEndDirection = newEndVector/newEndLength; + } else { + newEndDirection = _orientation.getUp(); + } + + _hairTuft[t].endPosition = _hairTuft[t].midPosition + newEndDirection * _hairTuft[t].length * ONE_HALF; + _hairTuft[t].midPosition = _hairTuft[t].basePosition + newMidDirection * _hairTuft[t].length * ONE_HALF; + } +} + + + +void Head::renderHair(glm::vec3 cameraPosition) { + + for (int t = 0; t < NUM_HAIR_TUFTS; t ++) { + + glm::vec3 baseAxis = _hairTuft[t].midPosition - _hairTuft[t].basePosition; + glm::vec3 midAxis = _hairTuft[t].endPosition - _hairTuft[t].midPosition; + glm::vec3 viewVector = _hairTuft[t].basePosition - cameraPosition; + + glm::vec3 basePerpendicular = glm::normalize(glm::cross(baseAxis, viewVector)); + glm::vec3 midPerpendicular = glm::normalize(glm::cross(midAxis, viewVector)); + + glm::vec3 base1 = _hairTuft[t].basePosition - basePerpendicular * _hairTuft[t].thickness * ONE_HALF; + glm::vec3 base2 = _hairTuft[t].basePosition + basePerpendicular * _hairTuft[t].thickness * ONE_HALF; + + glm::vec3 mid1 = _hairTuft[t].midPosition - midPerpendicular * _hairTuft[t].thickness * ONE_HALF * ONE_HALF; + glm::vec3 mid2 = _hairTuft[t].midPosition + midPerpendicular * _hairTuft[t].thickness * ONE_HALF * ONE_HALF; + + glColor3fv(HAIR_COLOR); + + glBegin(GL_TRIANGLES); + + glVertex3f(base1.x, base1.y, base1.z ); + glVertex3f(base2.x, base2.y, base2.z ); + glVertex3f(mid1.x, mid1.y, mid1.z ); + + glVertex3f(base2.x, base2.y, base2.z ); + glVertex3f(mid1.x, mid1.y, mid1.z ); + glVertex3f(mid2.x, mid2.y, mid2.z ); + + glVertex3f(mid1.x, mid1.y, mid1.z ); + glVertex3f(mid2.x, mid2.y, mid2.z ); + glVertex3f(_hairTuft[t].endPosition.x, _hairTuft[t].endPosition.y, _hairTuft[t].endPosition.z ); + + glEnd(); + } +} + + + + diff --git a/interface/src/Head.h b/interface/src/Head.h index 6ea9218bbf..32f7ddab7e 100644 --- a/interface/src/Head.h +++ b/interface/src/Head.h @@ -24,13 +24,15 @@ enum eyeContactTargets MOUTH }; +const int NUM_HAIR_TUFTS = 4; + class Head : public HeadData { public: Head(); void reset(); void simulate(float deltaTime, bool isMine); - void render(bool lookingInMirror); + void render(bool lookingInMirror, glm::vec3 cameraPosition); void setScale (float scale ) { _scale = scale; } void setPosition (glm::vec3 position ) { _position = position; } @@ -56,6 +58,17 @@ private: Head(const Head&); Head& operator= (const Head&); + struct HairTuft + { + float length; + float thickness; + glm::vec3 basePosition; + glm::vec3 midPosition; + glm::vec3 endPosition; + glm::vec3 midVelocity; + glm::vec3 endVelocity; + }; + bool _returnHeadToCenter; float _audioLoudness; glm::vec3 _skinColor; @@ -80,6 +93,7 @@ private: glm::vec3 _bodyRotation; glm::vec3 _headRotation; bool _renderLookatVectors; + HairTuft _hairTuft[NUM_HAIR_TUFTS]; // private methods void renderHeadSphere(); @@ -90,6 +104,8 @@ private: void renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition); void calculateGeometry( bool lookingInMirror); void determineIfLookingAtSomething(); + void updateHair(float deltaTime); + void renderHair(glm::vec3 cameraPosition); }; #endif From 51ddf40ffeda137605fa66d578a36215b1d9f039 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Fri, 24 May 2013 11:54:55 -0700 Subject: [PATCH 02/17] cleaned up hair code --- interface/src/Head.cpp | 15 +++++++-------- interface/src/Head.h | 6 ++++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index c29145774d..44e540db45 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -64,13 +64,16 @@ Head::Head() : _renderLookatVectors(false) { for (int t = 0; t < NUM_HAIR_TUFTS; t ++) { - _hairTuft[t].length = HAIR_LENGTH; - _hairTuft[t].thickness = HAIR_THICKNESS; + _hairTuft[t].length = HAIR_LENGTH; + _hairTuft[t].thickness = HAIR_THICKNESS; + _hairTuft[t].basePosition = glm::vec3(0.0f, 0.0f, 0.0f); + //_hairTuft[t].baseDirection = glm::vec3(0.0f, 1.0f, 0.0f); + _hairTuft[t].basePosition = glm::vec3(0.0f, 0.0f, 0.0f); _hairTuft[t].midPosition = glm::vec3(0.0f, 0.0f, 0.0f); _hairTuft[t].endPosition = glm::vec3(0.0f, 0.0f, 0.0f); _hairTuft[t].midVelocity = glm::vec3(0.0f, 0.0f, 0.0f); - _hairTuft[t].endVelocity = glm::vec3(0.0f, 0.0f, 0.0f); + _hairTuft[t].endVelocity = glm::vec3(0.0f, 0.0f, 0.0f); } } @@ -79,6 +82,7 @@ void Head::reset() { _leanForward = _leanSideways = 0.0f; for (int t = 0; t < NUM_HAIR_TUFTS; t ++) { + _hairTuft[t].basePosition = _position + _orientation.getUp() * _scale * 0.9f; _hairTuft[t].midPosition = _hairTuft[t].basePosition + _orientation.getUp() * _hairTuft[t].length * ONE_HALF; _hairTuft[t].endPosition = _hairTuft[t].midPosition + _orientation.getUp() * _hairTuft[t].length * ONE_HALF; @@ -564,7 +568,6 @@ void Head::renderHair(glm::vec3 cameraPosition) { glm::vec3 base1 = _hairTuft[t].basePosition - basePerpendicular * _hairTuft[t].thickness * ONE_HALF; glm::vec3 base2 = _hairTuft[t].basePosition + basePerpendicular * _hairTuft[t].thickness * ONE_HALF; - glm::vec3 mid1 = _hairTuft[t].midPosition - midPerpendicular * _hairTuft[t].thickness * ONE_HALF * ONE_HALF; glm::vec3 mid2 = _hairTuft[t].midPosition + midPerpendicular * _hairTuft[t].thickness * ONE_HALF * ONE_HALF; @@ -588,7 +591,3 @@ void Head::renderHair(glm::vec3 cameraPosition) { } } - - - - diff --git a/interface/src/Head.h b/interface/src/Head.h index 32f7ddab7e..cdb0ea7cb4 100644 --- a/interface/src/Head.h +++ b/interface/src/Head.h @@ -24,7 +24,8 @@ enum eyeContactTargets MOUTH }; -const int NUM_HAIR_TUFTS = 4; +const int NUM_HAIR_TUFTS = 4; +const int NUM_HAIR_SEGMENTS = 4; class Head : public HeadData { public: @@ -62,11 +63,12 @@ private: { float length; float thickness; + glm::vec3 basePosition; glm::vec3 midPosition; glm::vec3 endPosition; glm::vec3 midVelocity; - glm::vec3 endVelocity; + glm::vec3 endVelocity; }; bool _returnHeadToCenter; From 995fbcf4f952f53fe55c62da474c1da12e39b74f Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Fri, 24 May 2013 14:46:26 -0700 Subject: [PATCH 03/17] mohawk also follows body pitch when accelerating --- interface/src/Head.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index 6fec0837c6..99237ba6b4 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -229,7 +229,7 @@ void Head::renderMohawk(bool lookingInMirror) { glTranslatef(_position.x, _position.y, _position.z); glRotatef((lookingInMirror ? (_bodyRotation.y - _yaw) : (_bodyRotation.y + _yaw)), 0, 1, 0); glRotatef(lookingInMirror ? _roll: -_roll, 0, 0, 1); - glRotatef(-_pitch, 1, 0, 0); + glRotatef(-_pitch - _bodyRotation.x, 1, 0, 0); glBegin(GL_TRIANGLE_FAN); for (int i = 0; i < MOHAWK_TRIANGLES; i++) { From 608a4f71bfe423cb784bd85f55d647cbaa1d87ce Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Fri, 24 May 2013 14:51:06 -0700 Subject: [PATCH 04/17] ground surface is 20 meters across. play on! --- interface/src/Application.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d97e5f83a2..c478554903 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1667,7 +1667,8 @@ void Application::displaySide(Camera& whichCamera) { glPopMatrix(); //draw a grid ground plane.... - drawGroundPlaneGrid(10.f); + const float EDGE_SIZE_GROUND_PLANE = 20.f; + drawGroundPlaneGrid(EDGE_SIZE_GROUND_PLANE); // Draw voxels if (_renderVoxels->isChecked()) { From 65168e6aec597ceb932761de765c1da088e7161a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 24 May 2013 15:23:25 -0700 Subject: [PATCH 05/17] add a yaw offset to the oculus so it can pull body --- interface/src/Avatar.cpp | 18 +++++++++++++++++- interface/src/OculusManager.cpp | 10 +++++++++- interface/src/OculusManager.h | 3 +++ libraries/avatars/src/HeadData.h | 4 ++-- 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 21dea8886f..09900d1404 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -300,7 +300,6 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { deltaTime * _orientation.getUp(); } - } } @@ -381,11 +380,28 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { const float ACCELERATION_PITCH_DECAY = 0.4f; const float ACCELERATION_YAW_DECAY = 0.4f; + const float OCULUS_ACCELERATION_PULL_THRESHOLD = 1.0f; + const int OCULUS_YAW_OFFSET_THRESHOLD = 10; + // Decay HeadPitch as a function of acceleration, so that you look straight ahead when // you start moving, but don't do this with an HMD like the Oculus. if (!OculusManager::isConnected()) { _head.setPitch(_head.getPitch() * (1.f - acceleration * ACCELERATION_PITCH_DECAY * deltaTime)); _head.setYaw(_head.getYaw() * (1.f - acceleration * ACCELERATION_YAW_DECAY * deltaTime)); + } else if (fabsf(acceleration) > OCULUS_ACCELERATION_PULL_THRESHOLD + && fabs(_head.getYaw()) > OCULUS_YAW_OFFSET_THRESHOLD) { + // if we're wearing the oculus + // and this acceleration is above the pull threshold + // and the head yaw if off the body by more than OCULUS_YAW_OFFSET_THRESHOLD + + // match the body yaw to the oculus yaw + _bodyYaw = getAbsoluteHeadYaw(); + + // set the head yaw to zero for this draw + _head.setYaw(0); + + // correct the oculus yaw offset + OculusManager::updateYawOffset(); } //apply the head lean values to the springy position... diff --git a/interface/src/OculusManager.cpp b/interface/src/OculusManager.cpp index e0272ac8ef..168616ec83 100644 --- a/interface/src/OculusManager.cpp +++ b/interface/src/OculusManager.cpp @@ -16,6 +16,7 @@ Ptr OculusManager::_deviceManager; Ptr OculusManager::_hmdDevice; Ptr OculusManager::_sensorDevice; SensorFusion OculusManager::_sensorFusion; +float OculusManager::_yawOffset = 0; #endif void OculusManager::connect() { @@ -36,12 +37,19 @@ void OculusManager::connect() { #endif } +void OculusManager::updateYawOffset() { + float yaw, pitch, roll; + _sensorFusion.GetOrientation().GetEulerAngles(&yaw, &pitch, &roll); + _yawOffset = yaw; +} + void OculusManager::getEulerAngles(float& yaw, float& pitch, float& roll) { #ifdef __APPLE__ _sensorFusion.GetOrientation().GetEulerAngles(&yaw, &pitch, &roll); // convert each angle to degrees - yaw = glm::degrees(yaw); + // remove the yaw offset from the returned yaw + yaw = glm::degrees(yaw - _yawOffset); pitch = glm::degrees(pitch); roll = glm::degrees(roll); #endif diff --git a/interface/src/OculusManager.h b/interface/src/OculusManager.h index 6570a2a4cc..7bfea8b419 100644 --- a/interface/src/OculusManager.h +++ b/interface/src/OculusManager.h @@ -21,12 +21,15 @@ public: static bool isConnected() { return _isConnected; } static void getEulerAngles(float& yaw, float& pitch, float& roll); + + static void updateYawOffset(); private: static bool _isConnected; static Ptr _deviceManager; static Ptr _hmdDevice; static Ptr _sensorDevice; static SensorFusion _sensorFusion; + static float _yawOffset; }; #endif /* defined(__hifi__OculusManager__) */ diff --git a/libraries/avatars/src/HeadData.h b/libraries/avatars/src/HeadData.h index 1f0a8181b5..0eb135b899 100644 --- a/libraries/avatars/src/HeadData.h +++ b/libraries/avatars/src/HeadData.h @@ -13,8 +13,8 @@ #include -const float MIN_HEAD_YAW = -85; -const float MAX_HEAD_YAW = 85; +const float MIN_HEAD_YAW = -110; +const float MAX_HEAD_YAW = 110; const float MIN_HEAD_PITCH = -60; const float MAX_HEAD_PITCH = 60; const float MIN_HEAD_ROLL = -50; From c661796b81923e3147f673b8685f706c427f391a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 24 May 2013 15:37:48 -0700 Subject: [PATCH 06/17] don't copy audio data if the agent sent the wrong amount --- libraries/audio/src/AudioRingBuffer.cpp | 36 ++++++++++++++----------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/libraries/audio/src/AudioRingBuffer.cpp b/libraries/audio/src/AudioRingBuffer.cpp index ee693ebde3..299ffcc2cb 100644 --- a/libraries/audio/src/AudioRingBuffer.cpp +++ b/libraries/audio/src/AudioRingBuffer.cpp @@ -68,23 +68,27 @@ int AudioRingBuffer::parseData(unsigned char* sourceBuffer, int numBytes) { _shouldLoopbackForAgent = false; } } - - if (!_endOfLastWrite) { - _endOfLastWrite = _buffer; - } else if (diffLastWriteNextOutput() > _ringBufferLengthSamples - _bufferLengthSamples) { - _endOfLastWrite = _buffer; - _nextOutput = _buffer; - _started = false; + + // make sure we have enough bytes left for this to be the right amount of audio + // otherwise we should not copy that data, and leave the buffer pointers where they are + if (numBytes - (dataBuffer - sourceBuffer) == _bufferLengthSamples * sizeof(int16_t)) { + if (!_endOfLastWrite) { + _endOfLastWrite = _buffer; + } else if (diffLastWriteNextOutput() > _ringBufferLengthSamples - _bufferLengthSamples) { + _endOfLastWrite = _buffer; + _nextOutput = _buffer; + _started = false; + } + + memcpy(_endOfLastWrite, dataBuffer, _bufferLengthSamples * sizeof(int16_t)); + + _endOfLastWrite += _bufferLengthSamples; + + if (_endOfLastWrite >= _buffer + _ringBufferLengthSamples) { + _endOfLastWrite = _buffer; + } } - - memcpy(_endOfLastWrite, dataBuffer, _bufferLengthSamples * sizeof(int16_t)); - - _endOfLastWrite += _bufferLengthSamples; - - if (_endOfLastWrite >= _buffer + _ringBufferLengthSamples) { - _endOfLastWrite = _buffer; - } - + return numBytes; } From a8b08647d04eb93225fcaecf4b1de6d470e97610 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 24 May 2013 16:18:36 -0700 Subject: [PATCH 07/17] require that crotch grabbing be explicit, not implicit --- interface/src/Avatar.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 7568e45116..006b19908e 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -838,6 +838,8 @@ void Avatar::initializeSkeleton() { _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; From 12d0ccb7124dc8835ecd4fa1ac9092dae4105112 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 24 May 2013 16:32:52 -0700 Subject: [PATCH 08/17] tune the distance attenuation to use log of base 2.5 --- audio-mixer/src/main.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/audio-mixer/src/main.cpp b/audio-mixer/src/main.cpp index 73263ae05e..e4a4f83b07 100644 --- a/audio-mixer/src/main.cpp +++ b/audio-mixer/src/main.cpp @@ -167,7 +167,8 @@ int main(int argc, const char* argv[]) { float minCoefficient = std::min(1.0f, powf(0.5, - (logf(DISTANCE_RATIO * distanceToAgent) / logf(2)) - 1)); + (logf(DISTANCE_RATIO * distanceToAgent) / logf(2.5)) + - 1)); distanceCoefficients[lowAgentIndex][highAgentIndex] = minCoefficient; } From 56438435c165b7f618f800c4a5e068892aff45da Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Fri, 24 May 2013 17:12:14 -0700 Subject: [PATCH 09/17] made mouth conform to the head sphere --- interface/src/Head.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index b2818b857c..9306ae8769 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -78,7 +78,6 @@ Head::Head(Avatar* owningAvatar) : _hairTuft[t].midVelocity = glm::vec3(0.0f, 0.0f, 0.0f); _hairTuft[t].endVelocity = glm::vec3(0.0f, 0.0f, 0.0f); } - } void Head::reset() { @@ -312,6 +311,15 @@ void Head::renderMouth() { glm::vec3 rightTop = _mouthPosition + r * 0.4f + u * 0.7f + f; glm::vec3 leftBottom = _mouthPosition - r * 0.4f - u * 1.0f + f * 0.7f; glm::vec3 rightBottom = _mouthPosition + r * 0.4f - u * 1.0f + f * 0.7f; + + // constrain all mouth vertices to a sphere slightly larger than the head... + float constrainedRadius = _scale + 0.001f; + leftCorner = _position + glm::normalize(leftCorner - _position) * constrainedRadius; + rightCorner = _position + glm::normalize(rightCorner - _position) * constrainedRadius; + leftTop = _position + glm::normalize(leftTop - _position) * constrainedRadius; + rightTop = _position + glm::normalize(rightTop - _position) * constrainedRadius; + leftBottom = _position + glm::normalize(leftBottom - _position) * constrainedRadius; + rightBottom = _position + glm::normalize(rightBottom - _position) * constrainedRadius; glColor3f(0.2f, 0.0f, 0.0f); From 30e951578ed34dbed5aebeecd29a2e72956eb56e Mon Sep 17 00:00:00 2001 From: Freddy Date: Fri, 24 May 2013 17:27:56 -0700 Subject: [PATCH 10/17] procedural voxel create/delete noises --- interface/src/Application.cpp | 83 ++++++++++++++++++++++++++++++++--- 1 file changed, 76 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c478554903..a101d0b03d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include "Application.h" #include "InterfaceConfig.h" @@ -2013,22 +2015,78 @@ void Application::shiftPaintingColor() { _paintingVoxel.blue = (_dominantColor == 2) ? randIntInRange(200, 255) : randIntInRange(40, 100); } + void Application::maybeEditVoxelUnderCursor() { if (_addVoxelMode->isChecked() || _colorVoxelMode->isChecked()) { - if (_mouseVoxel.s != 0) { + if (_mouseVoxel.s != 0) { PACKET_HEADER message = (_destructiveAddVoxel->isChecked() ? - PACKET_HEADER_SET_VOXEL_DESTRUCTIVE : PACKET_HEADER_SET_VOXEL); + PACKET_HEADER_SET_VOXEL_DESTRUCTIVE : PACKET_HEADER_SET_VOXEL); sendVoxelEditMessage(message, _mouseVoxel); - // create the voxel locally so it appears immediately + // create the voxel locally so it appears immediately _voxels.createVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s, _mouseVoxel.red, _mouseVoxel.green, _mouseVoxel.blue, _destructiveAddVoxel->isChecked()); - + // remember the position for drag detection _justEditedVoxel = true; + + AudioInjector* voxelInjector = AudioInjectionManager::injectorWithCapacity(22050); + voxelInjector->setPosition(glm::vec3(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z)); + //_myAvatar.getPosition() + voxelInjector->setBearing(-1 * _myAvatar.getAbsoluteHeadYaw()); + voxelInjector->setVolume (16 * pow (_mouseVoxel.s, 2) / .0000001); //255 is max, and also default value + printf("mousevoxelscale is %f\n", _mouseVoxel.s); + + /* for (int i = 0; i + < 22050; i++) { + if (i % 4 == 0) { + voxelInjector->addSample(4000); + } else if (i % 4 == 1) { + voxelInjector->addSample(0); + } else if (i % 4 == 2) { + voxelInjector->addSample(-4000); + } else { + voxelInjector->addSample(0); + } + */ + + + for (int i=0; i < 11025; i++) { + + /* + A440 square wave + if (sin(i * 2 * PIE / 50)>=0) { + voxelInjector->addSample(4000); + } else { + voxelInjector->addSample(-4000); + } + */ + + if (_mouseVoxel.s > .01) { + voxelInjector->addSample(20000 * sin((i * 2 * PIE) /(500*sin((i+1)/200)))); + } else { + voxelInjector->addSample(16000 * sin(i/(1.5 * log (_mouseVoxel.s/.0001) * ((i+11025)/5512.5)))); //808 + } + } + + //voxelInjector->addSample(32500 * sin(i/(2 * 1 * ((i+5000)/5512.5)))); //80 + //voxelInjector->addSample(20000 * sin(i/(6 * (_mouseVoxel.s/.001) *((i+5512.5)/5512.5)))); //808 + //voxelInjector->addSample(20000 * sin(i/(6 * ((i+5512.5)/5512.5)))); //808 + //voxelInjector->addSample(4000 * sin(i * 2 * PIE /50)); //A440 sine wave + //voxelInjector->addSample(4000 * sin(i * 2 * PIE /50) * sin (i/500)); //A440 sine wave with amplitude modulation + + //FM library + //voxelInjector->addSample(20000 * sin((i * 2 * PIE) /(500*sin((i+1)/200)))); //FM 1 dubstep + //voxelInjector->addSample(20000 * sin((i * 2 * PIE) /(300*sin((i+1)/5.0)))); //FM 2 flange sweep + //voxelInjector->addSample(10000 * sin((i * 2 * PIE) /(500*sin((i+1)/500.0)))); //FM 3 resonant pulse + + + + + AudioInjectionManager::threadInjector(voxelInjector); } } else if (_deleteVoxelMode->isChecked()) { - deleteVoxelUnderCursor(); + deleteVoxelUnderCursor(); } } @@ -2036,10 +2094,21 @@ void Application::deleteVoxelUnderCursor() { if (_mouseVoxel.s != 0) { // sending delete to the server is sufficient, server will send new version so we see updates soon enough sendVoxelEditMessage(PACKET_HEADER_ERASE_VOXEL, _mouseVoxel); + AudioInjector* voxelInjector = AudioInjectionManager::injectorWithCapacity(5000); + voxelInjector->setPosition(glm::vec3(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z)); + voxelInjector->setBearing(0); //straight down the z axis + voxelInjector->setVolume (255); //255 is max, and also default value - // remember the position for drag detection - _justEditedVoxel = true; + + for (int i=0; i < 5000; i++) { + voxelInjector->addSample(10000 * sin((i * 2 * PIE) /(500*sin((i+1)/500.0)))); //FM 3 resonant pulse + // voxelInjector->addSample(20000 * sin((i) /((4 / _mouseVoxel.s) * sin((i)/(20 * _mouseVoxel.s / .001))))); //FM 2 comb filter + } + + AudioInjectionManager::threadInjector(voxelInjector); } + // remember the position for drag detection + _justEditedVoxel = true; } void Application::goHome() { From 6a4bcf32fa6b492aa7f3404b3dbd39e15c378139 Mon Sep 17 00:00:00 2001 From: Freddy Date: Fri, 24 May 2013 17:58:31 -0700 Subject: [PATCH 11/17] Code review fixes --- interface/src/Application.cpp | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a101d0b03d..9bb2afa056 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2020,7 +2020,7 @@ void Application::maybeEditVoxelUnderCursor() { if (_addVoxelMode->isChecked() || _colorVoxelMode->isChecked()) { if (_mouseVoxel.s != 0) { PACKET_HEADER message = (_destructiveAddVoxel->isChecked() ? - PACKET_HEADER_SET_VOXEL_DESTRUCTIVE : PACKET_HEADER_SET_VOXEL); + PACKET_HEADER_SET_VOXEL_DESTRUCTIVE : PACKET_HEADER_SET_VOXEL); sendVoxelEditMessage(message, _mouseVoxel); // create the voxel locally so it appears immediately @@ -2030,12 +2030,12 @@ void Application::maybeEditVoxelUnderCursor() { // remember the position for drag detection _justEditedVoxel = true; - AudioInjector* voxelInjector = AudioInjectionManager::injectorWithCapacity(22050); + AudioInjector* voxelInjector = AudioInjectionManager::injectorWithCapacity(11025); voxelInjector->setPosition(glm::vec3(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z)); //_myAvatar.getPosition() voxelInjector->setBearing(-1 * _myAvatar.getAbsoluteHeadYaw()); voxelInjector->setVolume (16 * pow (_mouseVoxel.s, 2) / .0000001); //255 is max, and also default value - printf("mousevoxelscale is %f\n", _mouseVoxel.s); + // printf("mousevoxelscale is %f\n", _mouseVoxel.s); /* for (int i = 0; i < 22050; i++) { @@ -2051,7 +2051,9 @@ void Application::maybeEditVoxelUnderCursor() { */ - for (int i=0; i < 11025; i++) { + const float BIG_VOXEL_MIN_SIZE = .01f; + + for (int i = 0; i < 11025; i++) { /* A440 square wave @@ -2062,10 +2064,10 @@ void Application::maybeEditVoxelUnderCursor() { } */ - if (_mouseVoxel.s > .01) { - voxelInjector->addSample(20000 * sin((i * 2 * PIE) /(500*sin((i+1)/200)))); + if (_mouseVoxel.s > BIG_VOXEL_MIN_SIZE) { + voxelInjector->addSample(20000 * sin((i * 2 * PIE) / (500 * sin((i + 1) / 200)))); } else { - voxelInjector->addSample(16000 * sin(i/(1.5 * log (_mouseVoxel.s/.0001) * ((i+11025)/5512.5)))); //808 + voxelInjector->addSample(16000 * sin(i / (1.5 * log (_mouseVoxel.s / .0001) * ((i + 11025) / 5512.5)))); //808 } } @@ -2079,10 +2081,7 @@ void Application::maybeEditVoxelUnderCursor() { //voxelInjector->addSample(20000 * sin((i * 2 * PIE) /(500*sin((i+1)/200)))); //FM 1 dubstep //voxelInjector->addSample(20000 * sin((i * 2 * PIE) /(300*sin((i+1)/5.0)))); //FM 2 flange sweep //voxelInjector->addSample(10000 * sin((i * 2 * PIE) /(500*sin((i+1)/500.0)))); //FM 3 resonant pulse - - - - + AudioInjectionManager::threadInjector(voxelInjector); } } else if (_deleteVoxelMode->isChecked()) { @@ -2100,8 +2099,8 @@ void Application::deleteVoxelUnderCursor() { voxelInjector->setVolume (255); //255 is max, and also default value - for (int i=0; i < 5000; i++) { - voxelInjector->addSample(10000 * sin((i * 2 * PIE) /(500*sin((i+1)/500.0)))); //FM 3 resonant pulse + for (int i = 0; i < 5000; i++) { + voxelInjector->addSample(10000 * sin((i * 2 * PIE) / (500 * sin((i + 1) / 500.0)))); //FM 3 resonant pulse // voxelInjector->addSample(20000 * sin((i) /((4 / _mouseVoxel.s) * sin((i)/(20 * _mouseVoxel.s / .001))))); //FM 2 comb filter } From 0c2c90b84da919e1ef53ceae8d7663be14483e0e Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Fri, 24 May 2013 18:01:25 -0700 Subject: [PATCH 12/17] cleanup --- interface/src/Head.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index 0e6bf28a9e..28b526894b 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -28,8 +28,8 @@ const float HAIR_SPRING_FORCE = 10.0f; const float HAIR_TORQUE_FORCE = 0.1f; const float HAIR_GRAVITY_FORCE = 0.05f; const float HAIR_DRAG = 10.0f; -const float HAIR_LENGTH = 0.06f; -const float HAIR_THICKNESS = 0.02f; +const float HAIR_LENGTH = 0.09f; +const float HAIR_THICKNESS = 0.03f; const float IRIS_RADIUS = 0.007; const float IRIS_PROTRUSION = 0.0145f; const char IRIS_TEXTURE_FILENAME[] = "resources/images/iris.png"; @@ -65,12 +65,11 @@ Head::Head(Avatar* owningAvatar) : _mohawkTriangleFan(NULL), _mohawkColors(NULL), _renderLookatVectors(false) { - + for (int t = 0; t < NUM_HAIR_TUFTS; t ++) { _hairTuft[t].length = HAIR_LENGTH; _hairTuft[t].thickness = HAIR_THICKNESS; _hairTuft[t].basePosition = glm::vec3(0.0f, 0.0f, 0.0f); - //_hairTuft[t].baseDirection = glm::vec3(0.0f, 1.0f, 0.0f); _hairTuft[t].basePosition = glm::vec3(0.0f, 0.0f, 0.0f); _hairTuft[t].midPosition = glm::vec3(0.0f, 0.0f, 0.0f); @@ -240,6 +239,7 @@ void Head::createMohawk() { _mohawkTriangleFan[0] = glm::vec3(0, 0, 0); glm::vec3 basicColor(randFloat(), randFloat(), randFloat()); _mohawkColors[0] = basicColor; + for (int i = 1; i < MOHAWK_TRIANGLES; i++) { _mohawkTriangleFan[i] = glm::vec3((randFloat() - 0.5f) * variance, height * cosf(i * RAD_PER_TRIANGLE - PI / 2.f) From 1e4771fe27c5a9d8c0d8e0afbef8608f14d4e637 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Fri, 24 May 2013 18:05:14 -0700 Subject: [PATCH 13/17] fix --- interface/src/Head.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index 28b526894b..1486013c9c 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -530,7 +530,7 @@ void Head::updateHair(float deltaTime) { for (int t = 0; t < NUM_HAIR_TUFTS; t ++) { - float fraction = (float)t / (float)(NUM_HAIR_TUFTS-1); + float fraction = (float)t / (float)(NUM_HAIR_TUFTS - 1); float angle = -20.0f + 40.0f * fraction; From 1f8842c6af1b70b737b7fefebb16c4a43e9ca730 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 25 May 2013 15:28:09 -0700 Subject: [PATCH 14/17] tweak recording of lastKnownViewFrustum as part of delta sending fix --- voxel-server/src/VoxelAgentData.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/voxel-server/src/VoxelAgentData.cpp b/voxel-server/src/VoxelAgentData.cpp index e25defef7a..3d2baa54a8 100644 --- a/voxel-server/src/VoxelAgentData.cpp +++ b/voxel-server/src/VoxelAgentData.cpp @@ -65,7 +65,11 @@ bool VoxelAgentData::updateCurrentViewFrustum() { } void VoxelAgentData::updateLastKnownViewFrustum() { - // save our currentViewFrustum into our lastKnownViewFrustum - _lastKnownViewFrustum = _currentViewFrustum; + bool frustumChanges = !_lastKnownViewFrustum.matches(_currentViewFrustum); + + if (frustumChanges) { + // save our currentViewFrustum into our lastKnownViewFrustum + _lastKnownViewFrustum = _currentViewFrustum; + } } From 48ca562b10d6ddf16c40eadcee37ffa3099a2bc8 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 25 May 2013 15:28:56 -0700 Subject: [PATCH 15/17] tweak ViewFrustum::matches() to use EPSILON compare --- libraries/voxels/src/ViewFrustum.cpp | 61 +++++++++++++++++----------- libraries/voxels/src/ViewFrustum.h | 4 +- 2 files changed, 39 insertions(+), 26 deletions(-) diff --git a/libraries/voxels/src/ViewFrustum.cpp b/libraries/voxels/src/ViewFrustum.cpp index e58085e606..061727b003 100644 --- a/libraries/voxels/src/ViewFrustum.cpp +++ b/libraries/voxels/src/ViewFrustum.cpp @@ -220,57 +220,70 @@ ViewFrustum::location ViewFrustum::boxInFrustum(const AABox& box) const { } } return(result); - } - -bool ViewFrustum::matches(const ViewFrustum& compareTo) const { - bool debug = false; - bool result = compareTo._position == _position && - compareTo._direction == _direction && - compareTo._up == _up && - compareTo._right == _right && - compareTo._fieldOfView == _fieldOfView && - compareTo._aspectRatio == _aspectRatio && - compareTo._nearClip == _nearClip && - compareTo._farClip == _farClip && - compareTo._eyeOffsetPosition == _eyeOffsetPosition && - compareTo._eyeOffsetOrientation == _eyeOffsetOrientation; +} + +bool testMatches(glm::quat lhs, glm::quat rhs) { + return (fabs(lhs.x - rhs.x) <= EPSILON && fabs(lhs.y - rhs.y) <= EPSILON && fabs(lhs.z - rhs.z) <= EPSILON + && fabs(lhs.w - rhs.w) <= EPSILON); +} + +bool testMatches(glm::vec3 lhs, glm::vec3 rhs) { + return (fabs(lhs.x - rhs.x) <= EPSILON && fabs(lhs.y - rhs.y) <= EPSILON && fabs(lhs.z - rhs.z) <= EPSILON); +} + +bool testMatches(float lhs, float rhs) { + return (fabs(lhs - rhs) <= EPSILON); +} + +bool ViewFrustum::matches(const ViewFrustum& compareTo, bool debug) const { + bool result = + testMatches(compareTo._position, _position ) && + testMatches(compareTo._direction, _direction ) && + testMatches(compareTo._up, _up ) && + testMatches(compareTo._right, _right ) && + testMatches(compareTo._fieldOfView, _fieldOfView ) && + testMatches(compareTo._aspectRatio, _aspectRatio ) && + testMatches(compareTo._nearClip, _nearClip ) && + testMatches(compareTo._farClip, _farClip ) && + testMatches(compareTo._eyeOffsetPosition, _eyeOffsetPosition ) && + testMatches(compareTo._eyeOffsetOrientation, _eyeOffsetOrientation); if (!result && debug) { printLog("ViewFrustum::matches()... result=%s\n", debug::valueOf(result)); printLog("%s -- compareTo._position=%f,%f,%f _position=%f,%f,%f\n", - (compareTo._position == _position ? "MATCHES " : "NO MATCH"), + (testMatches(compareTo._position,_position) ? "MATCHES " : "NO MATCH"), compareTo._position.x, compareTo._position.y, compareTo._position.z, _position.x, _position.y, _position.z ); printLog("%s -- compareTo._direction=%f,%f,%f _direction=%f,%f,%f\n", - (compareTo._direction == _direction ? "MATCHES " : "NO MATCH"), + (testMatches(compareTo._direction, _direction) ? "MATCHES " : "NO MATCH"), compareTo._direction.x, compareTo._direction.y, compareTo._direction.z, _direction.x, _direction.y, _direction.z ); printLog("%s -- compareTo._up=%f,%f,%f _up=%f,%f,%f\n", - (compareTo._up == _up ? "MATCHES " : "NO MATCH"), + (testMatches(compareTo._up, _up) ? "MATCHES " : "NO MATCH"), compareTo._up.x, compareTo._up.y, compareTo._up.z, _up.x, _up.y, _up.z ); printLog("%s -- compareTo._right=%f,%f,%f _right=%f,%f,%f\n", - (compareTo._right == _right ? "MATCHES " : "NO MATCH"), + (testMatches(compareTo._right, _right) ? "MATCHES " : "NO MATCH"), compareTo._right.x, compareTo._right.y, compareTo._right.z, _right.x, _right.y, _right.z ); printLog("%s -- compareTo._fieldOfView=%f _fieldOfView=%f\n", - (compareTo._fieldOfView == _fieldOfView ? "MATCHES " : "NO MATCH"), + (testMatches(compareTo._fieldOfView, _fieldOfView) ? "MATCHES " : "NO MATCH"), compareTo._fieldOfView, _fieldOfView); printLog("%s -- compareTo._aspectRatio=%f _aspectRatio=%f\n", - (compareTo._aspectRatio == _aspectRatio ? "MATCHES " : "NO MATCH"), + (testMatches(compareTo._aspectRatio, _aspectRatio) ? "MATCHES " : "NO MATCH"), compareTo._aspectRatio, _aspectRatio); printLog("%s -- compareTo._nearClip=%f _nearClip=%f\n", - (compareTo._nearClip == _nearClip ? "MATCHES " : "NO MATCH"), + (testMatches(compareTo._nearClip, _nearClip) ? "MATCHES " : "NO MATCH"), compareTo._nearClip, _nearClip); printLog("%s -- compareTo._farClip=%f _farClip=%f\n", - (compareTo._farClip == _farClip ? "MATCHES " : "NO MATCH"), + (testMatches(compareTo._farClip, _farClip) ? "MATCHES " : "NO MATCH"), compareTo._farClip, _farClip); printLog("%s -- compareTo._eyeOffsetPosition=%f,%f,%f _eyeOffsetPosition=%f,%f,%f\n", - (compareTo._eyeOffsetPosition == _eyeOffsetPosition ? "MATCHES " : "NO MATCH"), + (testMatches(compareTo._eyeOffsetPosition, _eyeOffsetPosition) ? "MATCHES " : "NO MATCH"), compareTo._eyeOffsetPosition.x, compareTo._eyeOffsetPosition.y, compareTo._eyeOffsetPosition.z, _eyeOffsetPosition.x, _eyeOffsetPosition.y, _eyeOffsetPosition.z); printLog("%s -- compareTo._eyeOffsetOrientation=%f,%f,%f,%f _eyeOffsetOrientation=%f,%f,%f,%f\n", - (compareTo._eyeOffsetOrientation == _eyeOffsetOrientation ? "MATCHES " : "NO MATCH"), + (testMatches(compareTo._eyeOffsetOrientation, _eyeOffsetOrientation) ? "MATCHES " : "NO MATCH"), compareTo._eyeOffsetOrientation.x, compareTo._eyeOffsetOrientation.y, compareTo._eyeOffsetOrientation.z, compareTo._eyeOffsetOrientation.w, _eyeOffsetOrientation.x, _eyeOffsetOrientation.y, _eyeOffsetOrientation.z, _eyeOffsetOrientation.w); diff --git a/libraries/voxels/src/ViewFrustum.h b/libraries/voxels/src/ViewFrustum.h index 0170030b6c..1ae33d55ad 100644 --- a/libraries/voxels/src/ViewFrustum.h +++ b/libraries/voxels/src/ViewFrustum.h @@ -108,8 +108,8 @@ public: ViewFrustum::location boxInFrustum(const AABox& box) const; // some frustum comparisons - bool matches(const ViewFrustum& compareTo) const; - bool matches(const ViewFrustum* compareTo) const { return matches(*compareTo); }; + bool matches(const ViewFrustum& compareTo, bool debug = false) const; + bool matches(const ViewFrustum* compareTo, bool debug = false) const { return matches(*compareTo, debug); }; void computePickRay(float x, float y, glm::vec3& origin, glm::vec3& direction) const; From f6863081f9be1d46baa1fbf2f10ad1ab5def2424 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 25 May 2013 15:29:23 -0700 Subject: [PATCH 16/17] Fix Delta Sending mode by not culling out of view voxels until we STOP moving - added isViewChanging() which determines if the view is currently changing - made hasViewChanged() report false UNTIL we've stopped moving - changed setupNewVoxelsForDrawing() to only call removeOutOfView() if we're not moving --- interface/src/VoxelSystem.cpp | 26 +++++++++++++++++++++++--- interface/src/VoxelSystem.h | 2 ++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 026f1dd4ee..7ff8649e43 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -160,13 +160,15 @@ void VoxelSystem::setupNewVoxelsForDrawing() { } double sinceLastViewCulling = (start - _lastViewCulling) / 1000.0; - // If the view frustum has changed, since last time, then remove nodes that are out of view - if ((sinceLastViewCulling >= std::max(_lastViewCullingElapsed, VIEW_CULLING_RATE_IN_MILLISECONDS)) && hasViewChanged()) { + // If the view frustum is no longer changing, but has changed, since last time, then remove nodes that are out of view + if ((sinceLastViewCulling >= std::max(_lastViewCullingElapsed, VIEW_CULLING_RATE_IN_MILLISECONDS)) + && !isViewChanging() && hasViewChanged()) { _lastViewCulling = start; // When we call removeOutOfView() voxels, we don't actually remove the voxels from the VBOs, but we do remove // them from tree, this makes our tree caclulations faster, but doesn't require us to fully rebuild the VBOs (which // can be expensive). +printLog("CALLING---removeOutOfView(); sinceLastViewCulling=%lf \n",sinceLastViewCulling); removeOutOfView(); // Once we call cleanupRemovedVoxels() we do need to rebuild our VBOs (if anything was actually removed). So, @@ -883,8 +885,10 @@ bool VoxelSystem::removeOutOfViewOperation(VoxelNode* node, void* extraData) { return true; // keep going! } -bool VoxelSystem::hasViewChanged() { + +bool VoxelSystem::isViewChanging() { bool result = false; // assume the best + // If our viewFrustum has changed since our _lastKnowViewFrustum if (_viewFrustum && !_lastKnowViewFrustum.matches(_viewFrustum)) { result = true; _lastKnowViewFrustum = *_viewFrustum; // save last known @@ -892,6 +896,22 @@ bool VoxelSystem::hasViewChanged() { return result; } +bool VoxelSystem::hasViewChanged() { + bool result = false; // assume the best + + // If we're still changing, report no change yet. + if (isViewChanging()) { + return false; + } + + // If our viewFrustum has changed since our _lastKnowViewFrustum + if (_viewFrustum && !_lastStableViewFrustum.matches(_viewFrustum)) { + result = true; + _lastStableViewFrustum = *_viewFrustum; // save last stable + } + return result; +} + void VoxelSystem::removeOutOfView() { PerformanceWarning warn(_renderWarningsOn, "removeOutOfView()"); removeOutOfViewArgs args(this); diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 21c1ec38ee..7bffb1d33c 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -66,6 +66,7 @@ public: void removeOutOfView(); bool hasViewChanged(); + bool isViewChanging(); bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, VoxelDetail& detail, float& distance, BoxFace& face); @@ -147,6 +148,7 @@ private: ViewFrustum* _viewFrustum; ViewFrustum _lastKnowViewFrustum; + ViewFrustum _lastStableViewFrustum; int newTreeToArrays(VoxelNode *currentNode); void cleanupRemovedVoxels(); From 60f2b9a438e574961055e4efd048d1b426007753 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 25 May 2013 15:31:28 -0700 Subject: [PATCH 17/17] removed debug --- interface/src/VoxelSystem.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 7ff8649e43..f8625663e9 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -168,7 +168,6 @@ void VoxelSystem::setupNewVoxelsForDrawing() { // When we call removeOutOfView() voxels, we don't actually remove the voxels from the VBOs, but we do remove // them from tree, this makes our tree caclulations faster, but doesn't require us to fully rebuild the VBOs (which // can be expensive). -printLog("CALLING---removeOutOfView(); sinceLastViewCulling=%lf \n",sinceLastViewCulling); removeOutOfView(); // Once we call cleanupRemovedVoxels() we do need to rebuild our VBOs (if anything was actually removed). So,