From 8774cb7ca08d7a66c8ecad3c4f1596f067d08e75 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 11 Jul 2013 15:48:17 -0700 Subject: [PATCH 01/10] fix hungergames circle bug, and improve performance of isLeafOrLOD logic --- libraries/voxels/src/VoxelTree.cpp | 33 ++++++++---------------------- 1 file changed, 8 insertions(+), 25 deletions(-) diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 8dccb8fcb1..e1f4f27c08 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -1346,33 +1346,16 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp // There are two types of nodes for which we want to send colors: // 1) Leaves - obviously - // 2) Non-leaves who's children would be visible and beyond our LOD. - // NOTE: This code works, but it's pretty expensive, because we're calculating distances for all the grand - // children, which we'll end up doing again later in the next level of recursion. We need to optimize this - // in the future. + // 2) Non-leaves who's children would be visible but are beyond our LOD. bool isLeafOrLOD = childNode->isLeaf(); if (params.viewFrustum && childNode->isColored() && !childNode->isLeaf()) { - int grandChildrenInView = 0; - int grandChildrenInLOD = 0; - float grandChildBoundaryDistance = boundaryDistanceForRenderLevel(childNode->getLevel() + - 1 + params.boundaryLevelAdjust); - for (int grandChildIndex = 0; grandChildIndex < NUMBER_OF_CHILDREN; grandChildIndex++) { - VoxelNode* grandChild = childNode->getChildAtIndex(grandChildIndex); - - if (grandChild && grandChild->isColored() && grandChild->isInView(*params.viewFrustum)) { - grandChildrenInView++; - - float grandChildDistance = grandChild->distanceToCamera(*params.viewFrustum); - if (grandChildDistance < grandChildBoundaryDistance) { - grandChildrenInLOD++; - } - } - } - // if any of our grandchildren ARE in view, then we don't want to include our color. If none are, then - // we do want to include our color - if (grandChildrenInView > 0 && grandChildrenInLOD == 0) { - isLeafOrLOD = true; - } + float distanceToNode = distance; + int childLevel = childNode->getLevel(); + float childBoundary = boundaryDistanceForRenderLevel(childLevel + params.boundaryLevelAdjust); + float grandChildBoundary = boundaryDistanceForRenderLevel(childLevel + 1 + params.boundaryLevelAdjust); + bool inChildBoundary = (distanceToNode <= childBoundary); + bool inGrandChildBoundary = (distanceToNode <= grandChildBoundary); + isLeafOrLOD = (inChildBoundary && !inGrandChildBoundary); } // track children with actual color, only if the child wasn't previously in view! From 79b2703e1ca21aa6dbe8d1dd62da6b5b5b5c76c1 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 11 Jul 2013 15:53:07 -0700 Subject: [PATCH 02/10] Improve avatar movement, added Physics.cpp for routines to help with physics calculations --- interface/src/Avatar.cpp | 24 +++++++++-------------- interface/src/Physics.cpp | 40 +++++++++++++++++++++++++++++++++++++++ interface/src/Physics.h | 15 +++++++++++++++ 3 files changed, 64 insertions(+), 15 deletions(-) create mode 100644 interface/src/Physics.cpp create mode 100644 interface/src/Physics.h diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 426aad57b3..a3ebc4db8e 100755 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -16,12 +16,14 @@ #include "Hand.h" #include "Head.h" #include "Log.h" +#include "Physics.h" #include "ui/TextRenderer.h" #include #include #include #include + using namespace std; const bool BALLS_ON = false; @@ -553,21 +555,13 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { _bodyYawDelta *= bodySpinMomentum; _bodyRollDelta *= bodySpinMomentum; - // Decay velocity. If velocity is really low, increase decay to simulate static friction - const float VELOCITY_DECAY_UNDER_THRUST = 0.2; - const float VELOCITY_FAST_DECAY = 0.6; - const float VELOCITY_SLOW_DECAY = 3.0; - const float VELOCITY_FAST_THRESHOLD = 2.0f; - float decayConstant, decay; - if (glm::length(_thrust) > 0.f) { - decayConstant = VELOCITY_DECAY_UNDER_THRUST; - } else if (glm::length(_velocity) > VELOCITY_FAST_THRESHOLD) { - decayConstant = VELOCITY_FAST_DECAY; - } else { - decayConstant = VELOCITY_SLOW_DECAY; - } - decay = glm::clamp(1.0f - decayConstant * deltaTime, 0.0f, 1.0f); - _velocity *= decay; + const float MAX_STATIC_FRICTION_VELOCITY = 0.25f; + const float STATIC_FRICTION_STRENGTH = 20.f; + applyStaticFriction(deltaTime, _velocity, MAX_STATIC_FRICTION_VELOCITY, STATIC_FRICTION_STRENGTH); + + const float LINEAR_DAMPING_STRENGTH = 0.2f; + const float SQUARED_DAMPING_STRENGTH = 0.1f; + applyDamping(deltaTime, _velocity, LINEAR_DAMPING_STRENGTH, SQUARED_DAMPING_STRENGTH); //pitch and roll the body as a function of forward speed and turning delta const float BODY_PITCH_WHILE_WALKING = -20.0; diff --git a/interface/src/Physics.cpp b/interface/src/Physics.cpp new file mode 100644 index 0000000000..31e64ccad3 --- /dev/null +++ b/interface/src/Physics.cpp @@ -0,0 +1,40 @@ +// +// Physics.cpp +// hifi +// +// Created by Philip on July 11, 2013 +// +// Routines to help with doing virtual world physics +// + +#include +#include + +#include "Util.h" +#include "world.h" +#include "Physics.h" + +// +// Applies static friction: maxVelocity is the largest velocity for which there +// there is friction, and strength is the amount of friction force applied to reduce +// velocity. +// +void applyStaticFriction(float deltaTime, glm::vec3& velocity, float maxVelocity, float strength) { + float v = glm::length(velocity); + if (v < maxVelocity) { + velocity *= glm::clamp((1.0f - deltaTime * strength * (1.f - v / maxVelocity)), 0.0f, 1.0f); + } +} + +// +// Applies velocity damping, with a strength value for linear and squared velocity damping +// + +void applyDamping(float deltaTime, glm::vec3& velocity, float linearStrength, float squaredStrength) { + if (squaredStrength == 0.f) { + velocity *= glm::clamp(1.f - deltaTime * linearStrength, 0.f, 1.f); + } else { + velocity *= glm::clamp(1.f - deltaTime * (linearStrength + glm::length(velocity) * squaredStrength), 0.f, 1.f); + } +} + diff --git a/interface/src/Physics.h b/interface/src/Physics.h new file mode 100644 index 0000000000..699497c187 --- /dev/null +++ b/interface/src/Physics.h @@ -0,0 +1,15 @@ +// +// Balls.h +// hifi +// +// Created by Philip on 4/25/13. +// +// + +#ifndef hifi_Physics_h +#define hifi_Physics_h + +void applyStaticFriction(float deltaTime, glm::vec3& velocity, float maxVelocity, float strength); +void applyDamping(float deltaTime, glm::vec3& velocity, float linearStrength, float squaredStrength); + +#endif From 58b50067ade0849fc1d306460e5c26d96023f0f4 Mon Sep 17 00:00:00 2001 From: Eric Johnston Date: Thu, 11 Jul 2013 16:06:31 -0700 Subject: [PATCH 03/10] Some Leap finger fixes, but also temporarily disable Leap data sending, due to a crash. Will resolve the crash before re-enabling. --- interface/src/Hand.cpp | 2 +- libraries/avatars/src/AvatarData.cpp | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/interface/src/Hand.cpp b/interface/src/Hand.cpp index 950a5fe556..29a2c32bf1 100755 --- a/interface/src/Hand.cpp +++ b/interface/src/Hand.cpp @@ -54,7 +54,7 @@ void Hand::calculateGeometry() { _position = head.getPosition() + head.getOrientation() * offset; _orientation = head.getOrientation(); - int numLeapBalls = _fingerTips.size() + _fingerRoots.size(); + int numLeapBalls = _fingerTips.size(); _leapBalls.resize(numLeapBalls); for (int i = 0; i < _fingerTips.size(); ++i) { diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 2c941be9be..27a755e03f 100755 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -137,6 +137,11 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) { if (numFingerVectors > 255) numFingerVectors = 0; // safety. We shouldn't ever get over 255, so consider that invalid. + ///////////////////////////////// + // Temporarily disable Leap finger sending, as it's causing a crash whenever someone's got a Leap connected + numFingerVectors = 0; + ///////////////////////////////// + *destinationBuffer++ = (unsigned char)numFingerVectors; if (numFingerVectors > 0) { @@ -255,8 +260,8 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { // leap hand data if (sourceBuffer - startPosition < numBytes) // safety check { - std::vector fingerTips = _handData->getFingerTips(); - std::vector fingerRoots = _handData->getFingerRoots(); + std::vector fingerTips; + std::vector fingerRoots; unsigned int numFingerVectors = *sourceBuffer++; unsigned int numFingerTips = numFingerVectors / 2; unsigned int numFingerRoots = numFingerVectors - numFingerTips; @@ -267,6 +272,11 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(fingerTips[i].y), 4); sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(fingerTips[i].z), 4); } + for (size_t i = 0; i < numFingerRoots; ++i) { + sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(fingerRoots[i].x), 4); + sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(fingerRoots[i].y), 4); + sourceBuffer += unpackFloatScalarFromSignedTwoByteFixed((int16_t*) sourceBuffer, &(fingerRoots[i].z), 4); + } _handData->setFingerTips(fingerTips); _handData->setFingerRoots(fingerRoots); } From 323644d8771ad99c5562af116d533fa15b7aa654 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 11 Jul 2013 16:09:08 -0700 Subject: [PATCH 04/10] CR feedback --- libraries/voxels/src/VoxelTree.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index e1f4f27c08..d2ea383b8e 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -1349,13 +1349,10 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp // 2) Non-leaves who's children would be visible but are beyond our LOD. bool isLeafOrLOD = childNode->isLeaf(); if (params.viewFrustum && childNode->isColored() && !childNode->isLeaf()) { - float distanceToNode = distance; int childLevel = childNode->getLevel(); float childBoundary = boundaryDistanceForRenderLevel(childLevel + params.boundaryLevelAdjust); float grandChildBoundary = boundaryDistanceForRenderLevel(childLevel + 1 + params.boundaryLevelAdjust); - bool inChildBoundary = (distanceToNode <= childBoundary); - bool inGrandChildBoundary = (distanceToNode <= grandChildBoundary); - isLeafOrLOD = (inChildBoundary && !inGrandChildBoundary); + isLeafOrLOD = ((distance <= childBoundary) && !(distance <= grandChildBoundary)); } // track children with actual color, only if the child wasn't previously in view! From 76dc01e84e6edbe1dd6c40dc1dae262b3d41f3ce Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 11 Jul 2013 17:55:59 -0700 Subject: [PATCH 05/10] fix audio silence on receive bail --- interface/src/Audio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 7a480cff57..7af42478d5 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -448,7 +448,7 @@ void Audio::addReceivedAudioToBuffer(unsigned char* receivedData, int receivedBy //printf("Got audio packet %d\n", _packetsReceivedThisPlayback); - _ringBuffer.parseData((unsigned char*) receivedData, PACKET_LENGTH_BYTES + sizeof(PACKET_TYPE)); + _ringBuffer.parseData((unsigned char*) receivedData, receivedBytes); Application::getInstance()->getBandwidthMeter()->inputStream(BandwidthMeter::AUDIO) .updateValue(PACKET_LENGTH_BYTES + sizeof(PACKET_TYPE)); From 4b95f2bae518fe3be981b407731e8da91634edb1 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 11 Jul 2013 19:10:34 -0700 Subject: [PATCH 06/10] Better thrust values and no jittering when standing --- interface/src/Avatar.cpp | 58 +++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index a3ebc4db8e..7953194ad8 100755 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -364,10 +364,10 @@ void Avatar::updateThrust(float deltaTime, Transmitter * transmitter) { glm::vec3 up = orientation * IDENTITY_UP; const float THRUST_MAG_UP = 800.0f; - const float THRUST_MAG_DOWN = 200.f; - const float THRUST_MAG_FWD = 300.f; - const float THRUST_MAG_BACK = 150.f; - const float THRUST_MAG_LATERAL = 200.f; + const float THRUST_MAG_DOWN = 300.f; + const float THRUST_MAG_FWD = 500.f; + const float THRUST_MAG_BACK = 300.f; + const float THRUST_MAG_LATERAL = 250.f; const float THRUST_JUMP = 120.f; // Add Thrusts from keyboard @@ -422,7 +422,7 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { glm::quat orientation = getOrientation(); glm::vec3 front = orientation * IDENTITY_FRONT; glm::vec3 right = orientation * IDENTITY_RIGHT; - + // Update movement timers if (isMyAvatar()) { _elapsedTimeSinceCollision += deltaTime; @@ -445,9 +445,6 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { glm::vec3 oldVelocity = getVelocity(); if (isMyAvatar()) { - // update position by velocity - _position += _velocity * deltaTime; - // calculate speed _speed = glm::length(_velocity); } @@ -482,7 +479,7 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { enableHandMovement &= (it->jointID != AVATAR_JOINT_RIGHT_WRIST); } - // update avatar skeleton + // update avatar skeleton _skeleton.update(deltaTime, getOrientation(), _position); //determine the lengths of the body springs now that we have updated the skeleton at least once @@ -503,42 +500,41 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { _ballSpringsInitialized = true; } - // if this is not my avatar, then hand position comes from transmitted data if (!isMyAvatar()) { _skeleton.joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position = _handPosition; } - - //detect and respond to collisions with other avatars... - if (isMyAvatar()) { - updateAvatarCollisions(deltaTime); - } - + //update the movement of the hand and process handshaking with other avatars... updateHandMovementAndTouching(deltaTime, enableHandMovement); _avatarTouch.simulate(deltaTime); - // apply gravity and collision with the ground/floor - if (isMyAvatar() && USING_AVATAR_GRAVITY) { - _velocity += _gravity * (GRAVITY_EARTH * deltaTime); - } if (isMyAvatar()) { + + // apply gravity + if (USING_AVATAR_GRAVITY) { + // For gravity, always move the avatar by the amount driven by gravity, so that the collision + // routines will detect it and collide every frame when pulled by gravity to a surface + // + _velocity += _gravity * (GRAVITY_EARTH * deltaTime); + _position += _gravity * (GRAVITY_EARTH * deltaTime) * deltaTime; + } + updateCollisionWithEnvironment(); + updateCollisionWithVoxels(); + updateAvatarCollisions(deltaTime); } // update body balls updateBodyBalls(deltaTime); + // test for avatar collision response with the big sphere if (usingBigSphereCollisionTest) { updateCollisionWithSphere(_TEST_bigSpherePosition, _TEST_bigSphereRadius, deltaTime); } - // collision response with voxels - if (isMyAvatar()) { - updateCollisionWithVoxels(); - } - + if (isMyAvatar()) { // add thrust to velocity @@ -547,7 +543,6 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { // update body yaw by body yaw delta orientation = orientation * glm::quat(glm::radians( glm::vec3(_bodyPitchDelta, _bodyYawDelta, _bodyRollDelta) * deltaTime)); - // decay body rotation momentum float bodySpinMomentum = 1.0 - BODY_SPIN_FRICTION * deltaTime; if (bodySpinMomentum < 0.0f) { bodySpinMomentum = 0.0f; } @@ -555,14 +550,14 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { _bodyYawDelta *= bodySpinMomentum; _bodyRollDelta *= bodySpinMomentum; - const float MAX_STATIC_FRICTION_VELOCITY = 0.25f; + const float MAX_STATIC_FRICTION_VELOCITY = 0.5f; const float STATIC_FRICTION_STRENGTH = 20.f; applyStaticFriction(deltaTime, _velocity, MAX_STATIC_FRICTION_VELOCITY, STATIC_FRICTION_STRENGTH); - const float LINEAR_DAMPING_STRENGTH = 0.2f; - const float SQUARED_DAMPING_STRENGTH = 0.1f; + const float LINEAR_DAMPING_STRENGTH = 3.0f; + const float SQUARED_DAMPING_STRENGTH = 0.2f; applyDamping(deltaTime, _velocity, LINEAR_DAMPING_STRENGTH, SQUARED_DAMPING_STRENGTH); - + //pitch and roll the body as a function of forward speed and turning delta const float BODY_PITCH_WHILE_WALKING = -20.0; const float BODY_ROLL_WHILE_TURNING = 0.2; @@ -653,6 +648,9 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { _mode = AVATAR_MODE_INTERACTING; } + // update position by velocity, and subtract the change added earlier for gravity + _position += _velocity * deltaTime; + // Zero thrust out now that we've added it to velocity in this frame _thrust = glm::vec3(0, 0, 0); From 6609a850eb485bcb487508bcd8b70a032b8b7859 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 11 Jul 2013 21:34:42 -0700 Subject: [PATCH 07/10] Gyros and touch look now work at same time --- interface/src/Application.cpp | 21 +++++++++++---------- interface/src/Application.h | 2 ++ interface/src/Avatar.cpp | 11 ++++++++--- interface/src/Avatar.h | 5 ++++- 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 044f58f3fd..c77cfec918 100755 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -183,6 +183,8 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _touchAvgX(0.0f), _touchAvgY(0.0f), _isTouchPressed(false), + _yawFromTouch(0.0f), + _pitchFromTouch(0.0f), _mousePressed(false), _mouseVoxelScale(1.0f / 1024.0f), _justEditedVoxel(false), @@ -969,6 +971,9 @@ void Application::idle() { gettimeofday(&check, NULL); // Only run simulation code if more than IDLE_SIMULATE_MSECS have passed since last time we ran + sendPostedEvents(NULL, QEvent::TouchBegin); + sendPostedEvents(NULL, QEvent::TouchUpdate); + sendPostedEvents(NULL, QEvent::TouchEnd); double timeSinceLastUpdate = diffclock(&_lastTimeUpdated, &check); if (timeSinceLastUpdate > IDLE_SIMULATE_MSECS) { @@ -978,9 +983,6 @@ void Application::idle() { // This is necessary because id the idle() call takes longer than the // interval between idle() calls, the event loop never gets to run, // and touch events get delayed. - sendPostedEvents(NULL, QEvent::TouchBegin); - sendPostedEvents(NULL, QEvent::TouchUpdate); - sendPostedEvents(NULL, QEvent::TouchEnd); const float BIGGEST_DELTA_TIME_SECS = 0.25f; update(glm::clamp((float)timeSinceLastUpdate / 1000.f, 0.f, BIGGEST_DELTA_TIME_SECS)); @@ -1902,12 +1904,9 @@ void Application::update(float deltaTime) { if (_isTouchPressed) { float TOUCH_YAW_SCALE = -50.0f; float TOUCH_PITCH_SCALE = -50.0f; - _myAvatar.getHead().addYaw((_touchAvgX - _lastTouchAvgX) - * TOUCH_YAW_SCALE - * deltaTime); - _myAvatar.getHead().addPitch((_touchAvgY - _lastTouchAvgY) - * TOUCH_PITCH_SCALE - * deltaTime); + _yawFromTouch += ((_touchAvgX - _lastTouchAvgX) * TOUCH_YAW_SCALE * deltaTime); + _pitchFromTouch += ((_touchAvgY - _lastTouchAvgY) * TOUCH_PITCH_SCALE * deltaTime); + _lastTouchAvgX = _touchAvgX; _lastTouchAvgY = _touchAvgY; } @@ -2015,7 +2014,9 @@ void Application::updateAvatar(float deltaTime) { _myAvatar.updateFromGyrosAndOrWebcam(_gyroLook->isChecked(), glm::vec3(_headCameraPitchYawScale, _headCameraPitchYawScale, - _headCameraPitchYawScale)); + _headCameraPitchYawScale), + _yawFromTouch, + _pitchFromTouch); if (_serialHeadSensor.isActive()) { diff --git a/interface/src/Application.h b/interface/src/Application.h index cea4d7d46d..acb2263cbf 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -332,6 +332,8 @@ private: float _touchDragStartedAvgX; float _touchDragStartedAvgY; bool _isTouchPressed; // true if multitouch has been pressed (clear when finished) + float _yawFromTouch; + float _pitchFromTouch; VoxelDetail _mouseVoxelDragging; glm::vec3 _voxelThrust; diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 7953194ad8..d032262ed8 100755 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -287,7 +287,10 @@ void Avatar::reset() { } // Update avatar head rotation with sensor data -void Avatar::updateFromGyrosAndOrWebcam(bool gyroLook, const glm::vec3& amplifyAngle) { +void Avatar::updateFromGyrosAndOrWebcam(bool gyroLook, + const glm::vec3& amplifyAngle, + float yawFromTouch, + float pitchFromTouch) { SerialInterface* gyros = Application::getInstance()->getSerialHeadSensor(); Webcam* webcam = Application::getInstance()->getWebcam(); glm::vec3 estimatedPosition, estimatedRotation; @@ -298,6 +301,8 @@ void Avatar::updateFromGyrosAndOrWebcam(bool gyroLook, const glm::vec3& amplifyA estimatedRotation = webcam->getEstimatedRotation(); } else { + _head.setPitch(pitchFromTouch); + _head.setYaw(yawFromTouch); return; } if (webcam->isActive()) { @@ -318,8 +323,8 @@ void Avatar::updateFromGyrosAndOrWebcam(bool gyroLook, const glm::vec3& amplifyA } } } - _head.setPitch(estimatedRotation.x * amplifyAngle.x); - _head.setYaw(estimatedRotation.y * amplifyAngle.y); + _head.setPitch(estimatedRotation.x * amplifyAngle.x + pitchFromTouch); + _head.setYaw(estimatedRotation.y * amplifyAngle.y + yawFromTouch); _head.setRoll(estimatedRotation.z * amplifyAngle.z); _head.setCameraFollowsHead(gyroLook); diff --git a/interface/src/Avatar.h b/interface/src/Avatar.h index 5e46eebb19..777b4dca59 100755 --- a/interface/src/Avatar.h +++ b/interface/src/Avatar.h @@ -87,7 +87,10 @@ public: void reset(); void simulate(float deltaTime, Transmitter* transmitter); void updateThrust(float deltaTime, Transmitter * transmitter); - void updateFromGyrosAndOrWebcam(bool gyroLook, const glm::vec3& amplifyAngles); + void updateFromGyrosAndOrWebcam(bool gyroLook, + const glm::vec3& amplifyAngle, + float yawFromTouch, + float pitchFromTouch); void addBodyYaw(float y) {_bodyYaw += y;}; void render(bool lookingInMirror, bool renderAvatarBalls); From d2dd41ba0f3d67789fac967fd9956323c65c8f2a Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 11 Jul 2013 21:46:13 -0700 Subject: [PATCH 08/10] make thrust be in direction of head/view --- interface/src/Avatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index d032262ed8..6e028e3674 100755 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -363,7 +363,7 @@ void Avatar::updateThrust(float deltaTime, Transmitter * transmitter) { // // Gather thrust information from keyboard and sensors to apply to avatar motion // - glm::quat orientation = getOrientation(); + glm::quat orientation = getHead().getOrientation(); glm::vec3 front = orientation * IDENTITY_FRONT; glm::vec3 right = orientation * IDENTITY_RIGHT; glm::vec3 up = orientation * IDENTITY_UP; From 4e89c679b91edcff05b8dcd88b9b618878a257e0 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 11 Jul 2013 21:51:13 -0700 Subject: [PATCH 09/10] Oculus will work with touch look (hopefully) --- interface/src/Application.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c77cfec918..bb3bc55307 100755 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2056,8 +2056,8 @@ void Application::updateAvatar(float deltaTime) { float yaw, pitch, roll; OculusManager::getEulerAngles(yaw, pitch, roll); - _myAvatar.getHead().setYaw(yaw); - _myAvatar.getHead().setPitch(pitch); + _myAvatar.getHead().setYaw(yaw + _yawFromTouch); + _myAvatar.getHead().setPitch(pitch + _pitchFromTouch); _myAvatar.getHead().setRoll(roll); } From 4e9530f946e04022be5edd541d4e72cc5dafc7cc Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 11 Jul 2013 22:31:31 -0700 Subject: [PATCH 10/10] Body slowly turns to follow touch look --- interface/src/Application.cpp | 7 +++++++ interface/src/Avatar.cpp | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index bb3bc55307..86b420f7f4 100755 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2010,6 +2010,13 @@ void Application::update(float deltaTime) { void Application::updateAvatar(float deltaTime) { + // When head is rotated via touch/mouse look, slowly turn body to follow + const float BODY_FOLLOW_HEAD_RATE = 0.5f; + // update body yaw by body yaw delta + _myAvatar.setOrientation(_myAvatar.getOrientation() + * glm::quat(glm::vec3(0, _yawFromTouch * deltaTime * BODY_FOLLOW_HEAD_RATE, 0) * deltaTime)); + _yawFromTouch -= _yawFromTouch * deltaTime * BODY_FOLLOW_HEAD_RATE; + // Update my avatar's state from gyros and/or webcam _myAvatar.updateFromGyrosAndOrWebcam(_gyroLook->isChecked(), glm::vec3(_headCameraPitchYawScale, diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 6e028e3674..ab57d6d0df 100755 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -544,7 +544,7 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { // add thrust to velocity _velocity += _thrust * deltaTime; - + // update body yaw by body yaw delta orientation = orientation * glm::quat(glm::radians( glm::vec3(_bodyPitchDelta, _bodyYawDelta, _bodyRollDelta) * deltaTime));