Merge branch 'master' of github.com:worklist/hifi into assignee

This commit is contained in:
Stephen Birarda 2013-07-12 10:19:15 -07:00
commit fd64ec44a1
9 changed files with 143 additions and 88 deletions

View file

@ -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;
}
@ -2011,11 +2010,20 @@ 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,
_headCameraPitchYawScale,
_headCameraPitchYawScale));
_headCameraPitchYawScale),
_yawFromTouch,
_pitchFromTouch);
if (_serialHeadSensor.isActive()) {
@ -2055,8 +2063,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);
}

View file

@ -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;

View file

@ -16,12 +16,14 @@
#include "Hand.h"
#include "Head.h"
#include "Log.h"
#include "Physics.h"
#include "ui/TextRenderer.h"
#include <NodeList.h>
#include <NodeTypes.h>
#include <PacketHeaders.h>
#include <OculusManager.h>
using namespace std;
const bool BALLS_ON = false;
@ -285,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;
@ -296,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()) {
@ -316,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);
@ -356,16 +363,16 @@ 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;
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
@ -420,7 +427,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;
@ -443,9 +450,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);
}
@ -480,7 +484,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
@ -501,51 +505,49 @@ 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
_velocity += _thrust * deltaTime;
// 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; }
@ -553,22 +555,14 @@ 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.5f;
const float STATIC_FRICTION_STRENGTH = 20.f;
applyStaticFriction(deltaTime, _velocity, MAX_STATIC_FRICTION_VELOCITY, STATIC_FRICTION_STRENGTH);
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;
@ -659,6 +653,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);

View file

@ -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);

View file

@ -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) {

40
interface/src/Physics.cpp Normal file
View file

@ -0,0 +1,40 @@
//
// Physics.cpp
// hifi
//
// Created by Philip on July 11, 2013
//
// Routines to help with doing virtual world physics
//
#include <glm/glm.hpp>
#include <SharedUtil.h>
#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);
}
}

15
interface/src/Physics.h Normal file
View file

@ -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

View file

@ -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<glm::vec3> fingerTips = _handData->getFingerTips();
std::vector<glm::vec3> fingerRoots = _handData->getFingerRoots();
std::vector<glm::vec3> fingerTips;
std::vector<glm::vec3> 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);
}

View file

@ -1346,33 +1346,13 @@ 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;
}
int childLevel = childNode->getLevel();
float childBoundary = boundaryDistanceForRenderLevel(childLevel + params.boundaryLevelAdjust);
float grandChildBoundary = boundaryDistanceForRenderLevel(childLevel + 1 + params.boundaryLevelAdjust);
isLeafOrLOD = ((distance <= childBoundary) && !(distance <= grandChildBoundary));
}
// track children with actual color, only if the child wasn't previously in view!