Merge pull request #523 from PhilipRosedale/master

Better physics, first person to third person transition
This commit is contained in:
Andrzej Kapolka 2013-06-13 12:07:06 -07:00
commit 78072fbde0
7 changed files with 263 additions and 140 deletions

View file

@ -244,7 +244,6 @@ static void renderMovingBug() {
}
float intensity = 0.5f;
float intensityIncrement = 0.1f;
const float MAX_INTENSITY = 1.0f;

View file

@ -62,8 +62,6 @@
using namespace std;
const bool TESTING_AVATAR_TOUCH = false;
// Starfield information
static char STAR_FILE[] = "https://s3-us-west-1.amazonaws.com/highfidelity/stars.txt";
static char STAR_CACHE_FILE[] = "cachedStars.txt";
@ -510,6 +508,9 @@ void Application::keyPressEvent(QKeyEvent* event) {
break;
case Qt::Key_E:
if (!_myAvatar.getDriveKeys(UP)) {
_myAvatar.jump();
}
_myAvatar.setDriveKeys(UP, 1);
break;
@ -720,6 +721,9 @@ void Application::mousePressEvent(QMouseEvent* event) {
if (event->button() == Qt::LeftButton) {
_mouseX = event->x();
_mouseY = event->y();
_mouseDragStartedX = _mouseX;
_mouseDragStartedY = _mouseY;
_mouseVoxelDragging = _mouseVoxel;
_mousePressed = true;
maybeEditVoxelUnderCursor();
@ -1012,6 +1016,12 @@ static void sendVoxelEditMessage(PACKET_HEADER header, VoxelDetail& detail) {
}
}
const glm::vec3 Application::getMouseVoxelWorldCoordinates(const VoxelDetail _mouseVoxel) {
return glm::vec3((_mouseVoxel.x + _mouseVoxel.s / 2.f) * TREE_SCALE,
(_mouseVoxel.y + _mouseVoxel.s / 2.f) * TREE_SCALE,
(_mouseVoxel.z + _mouseVoxel.s / 2.f) * TREE_SCALE);
}
void Application::decreaseVoxelSize() {
_mouseVoxelScale /= 2;
}
@ -1221,7 +1231,7 @@ void Application::initMenu() {
(_gyroLook = optionsMenu->addAction("Gyro Look"))->setCheckable(true);
_gyroLook->setChecked(false);
(_mouseLook = optionsMenu->addAction("Mouse Look"))->setCheckable(true);
_mouseLook->setChecked(false);
_mouseLook->setChecked(true);
(_showHeadMouse = optionsMenu->addAction("Head Mouse"))->setCheckable(true);
_showHeadMouse->setChecked(false);
(_transmitterDrives = optionsMenu->addAction("Transmitter Drive"))->setCheckable(true);
@ -1245,7 +1255,6 @@ void Application::initMenu() {
_renderAtmosphereOn->setShortcut(Qt::SHIFT | Qt::Key_A);
(_renderGroundPlaneOn = renderMenu->addAction("Ground Plane"))->setCheckable(true);
_renderGroundPlaneOn->setChecked(true);
_renderGroundPlaneOn->setShortcut(Qt::SHIFT | Qt::Key_G);
(_renderAvatarsOn = renderMenu->addAction("Avatars"))->setCheckable(true);
_renderAvatarsOn->setChecked(true);
(_renderAvatarBalls = renderMenu->addAction("Avatar as Balls"))->setCheckable(true);
@ -1441,6 +1450,26 @@ void Application::update(float deltaTime) {
// tell my avatar the posiion and direction of the ray projected ino the world based on the mouse position
_myAvatar.setMouseRay(mouseRayOrigin, mouseRayDirection);
// If we are dragging on a voxel, add thrust according to the amount the mouse is dragging
const float VOXEL_GRAB_THRUST = 5.0f;
if (_mousePressed && (_mouseVoxel.s != 0)) {
glm::vec2 mouseDrag(_mouseX - _mouseDragStartedX, _mouseY - _mouseDragStartedY);
glm::quat orientation = _myAvatar.getOrientation();
glm::vec3 front = orientation * IDENTITY_FRONT;
glm::vec3 up = orientation * IDENTITY_UP;
glm::vec3 towardVoxel = getMouseVoxelWorldCoordinates(_mouseVoxelDragging)
- _myAvatar.getCameraPosition();
towardVoxel = front * glm::length(towardVoxel);
glm::vec3 lateralToVoxel = glm::cross(up, glm::normalize(towardVoxel)) * glm::length(towardVoxel);
_voxelThrust = glm::vec3(0, 0, 0);
_voxelThrust += towardVoxel * VOXEL_GRAB_THRUST * deltaTime * mouseDrag.y;
_voxelThrust += lateralToVoxel * VOXEL_GRAB_THRUST * deltaTime * mouseDrag.x;
// Add thrust from voxel grabbing to the avatar
_myAvatar.addThrust(_voxelThrust);
}
_mouseVoxel.s = 0.0f;
if (checkedVoxelModeAction() != 0 &&
(fabs(_myAvatar.getVelocity().x) +
@ -1569,30 +1598,27 @@ void Application::update(float deltaTime) {
_myAvatar.simulate(deltaTime, NULL);
}
if (TESTING_AVATAR_TOUCH) {
if (_myCamera.getMode() != CAMERA_MODE_THIRD_PERSON) {
_myCamera.setMode(CAMERA_MODE_THIRD_PERSON);
_myCamera.setModeShiftRate(1.0f);
}
} else {
if (_myCamera.getMode() != CAMERA_MODE_MIRROR && !OculusManager::isConnected()) {
if (_manualFirstPerson->isChecked()) {
if (_myCamera.getMode() != CAMERA_MODE_FIRST_PERSON ) {
_myCamera.setMode(CAMERA_MODE_FIRST_PERSON);
_myCamera.setModeShiftRate(1.0f);
}
} else {
if (_myAvatar.getIsNearInteractingOther()) {
if (_myCamera.getMode() != CAMERA_MODE_FIRST_PERSON) {
_myCamera.setMode(CAMERA_MODE_FIRST_PERSON);
_myCamera.setModeShiftRate(1.0f);
}
} else {
if (_myCamera.getMode() != CAMERA_MODE_THIRD_PERSON) {
_myCamera.setMode(CAMERA_MODE_THIRD_PERSON);
_myCamera.setModeShiftRate(1.0f);
}
} else {
const float THIRD_PERSON_SHIFT_VELOCITY = 2.0f;
const float TIME_BEFORE_SHIFT_INTO_FIRST_PERSON = 0.75f;
const float TIME_BEFORE_SHIFT_INTO_THIRD_PERSON = 0.1f;
if ((_myAvatar.getElapsedTimeStopped() > TIME_BEFORE_SHIFT_INTO_FIRST_PERSON)
&& (_myCamera.getMode() != CAMERA_MODE_FIRST_PERSON)) {
_myCamera.setMode(CAMERA_MODE_FIRST_PERSON);
_myCamera.setModeShiftRate(1.0f);
}
if ((_myAvatar.getSpeed() > THIRD_PERSON_SHIFT_VELOCITY)
&& (_myAvatar.getElapsedTimeMoving() > TIME_BEFORE_SHIFT_INTO_THIRD_PERSON)
&& (_myCamera.getMode() != CAMERA_MODE_THIRD_PERSON)) {
_myCamera.setMode(CAMERA_MODE_THIRD_PERSON);
_myCamera.setModeShiftRate(1000.0f);
}
}
}
@ -1960,6 +1986,10 @@ void Application::displaySide(Camera& whichCamera) {
glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
// Enable to show line from me to the voxel I am touching
//renderLineToTouchedVoxel();
//renderThrustAtVoxel(_voxelThrust);
// draw a red sphere
float sphereRadius = 0.25f;
glColor3f(1,0,0);
@ -2175,6 +2205,32 @@ void Application::displayStats() {
}
}
void Application::renderThrustAtVoxel(const glm::vec3& thrust) {
if (_mousePressed) {
glColor3f(1, 0, 0);
glLineWidth(2.0f);
glBegin(GL_LINES);
glm::vec3 voxelTouched = getMouseVoxelWorldCoordinates(_mouseVoxelDragging);
glVertex3f(voxelTouched.x, voxelTouched.y, voxelTouched.z);
glVertex3f(voxelTouched.x + thrust.x, voxelTouched.y + thrust.y, voxelTouched.z + thrust.z);
glEnd();
}
}
void Application::renderLineToTouchedVoxel() {
// Draw a teal line to the voxel I am currently dragging on
if (_mousePressed) {
glColor3f(0, 1, 1);
glLineWidth(2.0f);
glBegin(GL_LINES);
glm::vec3 voxelTouched = getMouseVoxelWorldCoordinates(_mouseVoxelDragging);
glVertex3f(voxelTouched.x, voxelTouched.y, voxelTouched.z);
glm::vec3 headPosition = _myAvatar.getHeadJointPosition();
glVertex3fv(&headPosition.x);
glEnd();
}
}
/////////////////////////////////////////////////////////////////////////////////////
// renderViewFrustum()
//
@ -2451,6 +2507,8 @@ void Application::resetSensors() {
QCursor::setPos(_headMouseX, _headMouseY);
_myAvatar.reset();
_myTransmitter.resetLevels();
_myAvatar.setVelocity(glm::vec3(0,0,0));
_myAvatar.setThrust(glm::vec3(0,0,0));
}
static void setShortcutsEnabled(QWidget* widget, bool enabled) {

View file

@ -67,6 +67,8 @@ public:
void wheelEvent(QWheelEvent* event);
const glm::vec3 getMouseVoxelWorldCoordinates(const VoxelDetail _mouseVoxel);
Avatar* getAvatar() { return &_myAvatar; }
Camera* getCamera() { return &_myCamera; }
ViewFrustum* getViewFrustum() { return &_viewFrustum; }
@ -93,6 +95,9 @@ private slots:
void setRenderFirstPerson(bool firstPerson);
void renderThrustAtVoxel(const glm::vec3& thrust);
void renderLineToTouchedVoxel();
void setFrustumOffset(bool frustumOffset);
void cycleFrustumRenderMode();
@ -141,7 +146,7 @@ private:
void displayStats();
void renderViewFrustum(ViewFrustum& viewFrustum);
void setupPaintingVoxel();
void shiftPaintingColor();
void maybeEditVoxelUnderCursor();
@ -256,7 +261,12 @@ private:
int _mouseX;
int _mouseY;
int _mouseDragStartedX;
int _mouseDragStartedY;
VoxelDetail _mouseVoxelDragging;
glm::vec3 _voxelThrust;
bool _mousePressed; // true if mouse has been pressed (clear when finished)
VoxelDetail _mouseVoxel; // details of the voxel under the mouse cursor
float _mouseVoxelScale; // the scale for adding/removing voxels

View file

@ -77,6 +77,7 @@ Avatar::Avatar(Agent* owningAgent) :
_handHoldingPosition(0.0f, 0.0f, 0.0f),
_velocity(0.0f, 0.0f, 0.0f),
_thrust(0.0f, 0.0f, 0.0f),
_shouldJump(false),
_speed(0.0f),
_maxArmLength(0.0f),
_leanScale(0.5f),
@ -89,6 +90,9 @@ Avatar::Avatar(Agent* owningAgent) :
_mouseRayDirection(0.0f, 0.0f, 0.0f),
_interactingOther(NULL),
_isMouseTurningRight(false),
_elapsedTimeMoving(0.0f),
_elapsedTimeStopped(0.0f),
_elapsedTimeSinceCollision(0.0f),
_voxels(this)
{
// give the pointer to our head to inherited _headData variable from AvatarData
@ -316,40 +320,128 @@ glm::vec3 Avatar::getUprightHeadPosition() const {
void Avatar::updateFromMouse(int mouseX, int mouseY, int screenWidth, int screenHeight) {
// Update head yaw and pitch based on mouse input
const float MOUSE_MOVE_RADIUS = 0.3f;
const float MOUSE_ROTATE_SPEED = 4.0f;
const float MOUSE_PITCH_SPEED = 2.0f;
const float MOUSE_ROTATE_SPEED = 0.01f;
const float MOUSE_PITCH_SPEED = 0.02f;
const int TITLE_BAR_HEIGHT = 46;
float mouseLocationX = (float)mouseX / (float)screenWidth - 0.5f;
float mouseLocationY = (float)mouseY / (float)screenHeight - 0.5f;
if ((mouseX > 1) && (mouseX < screenWidth) && (mouseY > TITLE_BAR_HEIGHT) && (mouseY < screenHeight)) {
//
// Mouse must be inside screen (not at edge) and not on title bar for movement to happen
//
if (mouseLocationX > MOUSE_MOVE_RADIUS) {
_head.addYaw(-(mouseLocationX - MOUSE_MOVE_RADIUS) / (0.5f - MOUSE_MOVE_RADIUS) * MOUSE_ROTATE_SPEED);
} else if (mouseLocationX < -MOUSE_MOVE_RADIUS) {
_head.addYaw(-(mouseLocationX + MOUSE_MOVE_RADIUS) / (0.5f - MOUSE_MOVE_RADIUS) * MOUSE_ROTATE_SPEED);
}
if (mouseLocationY > MOUSE_MOVE_RADIUS) {
_head.addPitch(-(mouseLocationY - MOUSE_MOVE_RADIUS) / (0.5f - MOUSE_MOVE_RADIUS) * MOUSE_PITCH_SPEED);
} else if (mouseLocationY < -MOUSE_MOVE_RADIUS) {
_head.addPitch(-(mouseLocationY + MOUSE_MOVE_RADIUS) / (0.5f - MOUSE_MOVE_RADIUS) * MOUSE_PITCH_SPEED);
int pixelMoveThreshold = screenWidth / 6;
glm::vec2 mouseVector(mouseX - (screenWidth / 2), mouseY - (screenHeight / 2));
if (glm::length(mouseVector) > pixelMoveThreshold) {
mouseVector -= glm::normalize(mouseVector) * (float) pixelMoveThreshold;
_head.addYaw(-mouseVector.x * MOUSE_ROTATE_SPEED);
_head.addPitch(-mouseVector.y * MOUSE_PITCH_SPEED);
}
}
return;
}
void Avatar::updateThrust(float deltaTime, Transmitter * transmitter) {
//
// Gather thrust information from keyboard and sensors to apply to avatar motion
//
glm::quat orientation = 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_JUMP = 120.f;
// Add Thrusts from keyboard
if (_driveKeys[FWD ]) {_thrust += THRUST_MAG_FWD * deltaTime * front;}
if (_driveKeys[BACK ]) {_thrust -= THRUST_MAG_BACK * deltaTime * front;}
if (_driveKeys[RIGHT ]) {_thrust += THRUST_MAG_LATERAL * deltaTime * right;}
if (_driveKeys[LEFT ]) {_thrust -= THRUST_MAG_LATERAL * deltaTime * right;}
if (_driveKeys[UP ]) {_thrust += THRUST_MAG_UP * deltaTime * up;}
if (_driveKeys[DOWN ]) {_thrust -= THRUST_MAG_DOWN * deltaTime * up;}
if (_driveKeys[ROT_RIGHT]) {_bodyYawDelta -= YAW_MAG * deltaTime;}
if (_driveKeys[ROT_LEFT ]) {_bodyYawDelta += YAW_MAG * deltaTime;}
// Add one time jumping force if requested
if (_shouldJump) {
_thrust += THRUST_JUMP * up;
_shouldJump = false;
}
// Add thrusts from Transmitter
if (transmitter) {
transmitter->checkForLostTransmitter();
glm::vec3 rotation = transmitter->getEstimatedRotation();
const float TRANSMITTER_MIN_RATE = 1.f;
const float TRANSMITTER_MIN_YAW_RATE = 4.f;
const float TRANSMITTER_LATERAL_FORCE_SCALE = 5.f;
const float TRANSMITTER_FWD_FORCE_SCALE = 25.f;
const float TRANSMITTER_UP_FORCE_SCALE = 100.f;
const float TRANSMITTER_YAW_SCALE = 10.0f;
const float TRANSMITTER_LIFT_SCALE = 3.f;
const float TOUCH_POSITION_RANGE_HALF = 32767.f;
if (fabs(rotation.z) > TRANSMITTER_MIN_RATE) {
_thrust += rotation.z * TRANSMITTER_LATERAL_FORCE_SCALE * deltaTime * right;
}
if (fabs(rotation.x) > TRANSMITTER_MIN_RATE) {
_thrust += -rotation.x * TRANSMITTER_FWD_FORCE_SCALE * deltaTime * front;
}
if (fabs(rotation.y) > TRANSMITTER_MIN_YAW_RATE) {
_bodyYawDelta += rotation.y * TRANSMITTER_YAW_SCALE * deltaTime;
}
if (transmitter->getTouchState()->state == 'D') {
_thrust += TRANSMITTER_UP_FORCE_SCALE *
(float)(transmitter->getTouchState()->y - TOUCH_POSITION_RANGE_HALF) / TOUCH_POSITION_RANGE_HALF *
TRANSMITTER_LIFT_SCALE *
deltaTime *
up;
}
}
}
void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
//figure out if the mouse cursor is over any body spheres...
checkForMouseRayTouching();
glm::quat orientation = getOrientation();
glm::vec3 front = orientation * IDENTITY_FRONT;
glm::vec3 right = orientation * IDENTITY_RIGHT;
// Update movement timers
if (!_owningAgent) {
_elapsedTimeSinceCollision += deltaTime;
const float VELOCITY_MOVEMENT_TIMER_THRESHOLD = 0.2f;
if (glm::length(_velocity) < VELOCITY_MOVEMENT_TIMER_THRESHOLD) {
_elapsedTimeMoving = 0.f;
_elapsedTimeStopped += deltaTime;
} else {
_elapsedTimeStopped = 0.f;
_elapsedTimeMoving += deltaTime;
}
}
// Collect thrust forces from keyboard and devices
if (!_owningAgent) {
updateThrust(deltaTime, transmitter);
}
// copy velocity so we can use it later for acceleration
glm::vec3 oldVelocity = getVelocity();
if (!_owningAgent) {
// update position by velocity
_position += _velocity * deltaTime;
// calculate speed
_speed = glm::length(_velocity);
}
//figure out if the mouse cursor is over any body spheres...
if (!_owningAgent) {
checkForMouseRayTouching();
}
// update balls
if (_balls) { _balls->simulate(deltaTime); }
@ -391,12 +483,13 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
//update the movement of the hand and process handshaking with other avatars...
updateHandMovementAndTouching(deltaTime);
_avatarTouch.simulate(deltaTime);
// apply gravity and collision with the ground/floor
if (!_owningAgent && USING_AVATAR_GRAVITY) {
_velocity += _gravity * (GRAVITY_EARTH * deltaTime);
}
if (!_owningAgent) {
updateCollisionWithEnvironment();
}
@ -413,57 +506,11 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
updateCollisionWithVoxels();
}
glm::quat orientation = getOrientation();
glm::vec3 front = orientation * IDENTITY_FRONT;
glm::vec3 right = orientation * IDENTITY_RIGHT;
glm::vec3 up = orientation * IDENTITY_UP;
// driving the avatar around should only apply if this is my avatar (as opposed to an avatar being driven remotely)
const float THRUST_MAG = 600.0f;
if (!_owningAgent) {
_thrust = glm::vec3(0.0f, 0.0f, 0.0f);
// Add Thrusts from keyboard
if (_driveKeys[FWD ]) {_thrust += THRUST_MAG * deltaTime * front;}
if (_driveKeys[BACK ]) {_thrust -= THRUST_MAG * deltaTime * front;}
if (_driveKeys[RIGHT ]) {_thrust += THRUST_MAG * deltaTime * right;}
if (_driveKeys[LEFT ]) {_thrust -= THRUST_MAG * deltaTime * right;}
if (_driveKeys[UP ]) {_thrust += THRUST_MAG * deltaTime * up;}
if (_driveKeys[DOWN ]) {_thrust -= THRUST_MAG * deltaTime * up;}
if (_driveKeys[ROT_RIGHT]) {_bodyYawDelta -= YAW_MAG * deltaTime;}
if (_driveKeys[ROT_LEFT ]) {_bodyYawDelta += YAW_MAG * deltaTime;}
// Add thrusts from Transmitter
if (transmitter) {
transmitter->checkForLostTransmitter();
glm::vec3 rotation = transmitter->getEstimatedRotation();
const float TRANSMITTER_MIN_RATE = 1.f;
const float TRANSMITTER_MIN_YAW_RATE = 4.f;
const float TRANSMITTER_LATERAL_FORCE_SCALE = 25.f;
const float TRANSMITTER_FWD_FORCE_SCALE = 100.f;
const float TRANSMITTER_YAW_SCALE = 10.0f;
const float TRANSMITTER_LIFT_SCALE = 3.f;
const float TOUCH_POSITION_RANGE_HALF = 32767.f;
if (fabs(rotation.z) > TRANSMITTER_MIN_RATE) {
_thrust += rotation.z * TRANSMITTER_LATERAL_FORCE_SCALE * deltaTime * right;
}
if (fabs(rotation.x) > TRANSMITTER_MIN_RATE) {
_thrust += -rotation.x * TRANSMITTER_FWD_FORCE_SCALE * deltaTime * front;
}
if (fabs(rotation.y) > TRANSMITTER_MIN_YAW_RATE) {
_bodyYawDelta += rotation.y * TRANSMITTER_YAW_SCALE * deltaTime;
}
if (transmitter->getTouchState()->state == 'D') {
_thrust += THRUST_MAG *
(float)(transmitter->getTouchState()->y - TOUCH_POSITION_RANGE_HALF) / TOUCH_POSITION_RANGE_HALF *
TRANSMITTER_LIFT_SCALE *
deltaTime *
up;
}
}
// 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));
@ -475,12 +522,22 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
_bodyYawDelta *= bodySpinMomentum;
_bodyRollDelta *= bodySpinMomentum;
// add thrust to velocity
_velocity += _thrust * deltaTime;
// calculate speed
_speed = glm::length(_velocity);
// 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;
//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;
@ -500,29 +557,6 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
//the following will be used to make the avatar upright no matter what gravity is
setOrientation(computeRotationFromBodyToWorldUp(tiltDecay) * orientation);
// update position by velocity
_position += _velocity * deltaTime;
// decay velocity
const float VELOCITY_DECAY = 0.9;
float decay = 1.0 - VELOCITY_DECAY * deltaTime;
if ( decay < 0.0 ) {
_velocity = glm::vec3( 0.0f, 0.0f, 0.0f );
} else {
_velocity *= decay;
}
// If another avatar is near, dampen velocity as a function of closeness
if (_distanceToNearestAvatar < PERIPERSONAL_RADIUS) {
float closeness = 1.0f - (_distanceToNearestAvatar / PERIPERSONAL_RADIUS);
float drag = 1.0f - closeness * AVATAR_BRAKING_STRENGTH * deltaTime;
if ( drag > 0.0f ) {
_velocity *= drag;
} else {
_velocity = glm::vec3( 0.0f, 0.0f, 0.0f );
}
}
// Compute instantaneous acceleration
float forwardAcceleration = glm::length(glm::dot(getBodyFrontDirection(), getVelocity() - oldVelocity)) / deltaTime;
const float ACCELERATION_PITCH_DECAY = 0.4f;
@ -602,6 +636,10 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
} else {
_mode = AVATAR_MODE_INTERACTING;
}
// Zero thrust out now that we've added it to velocity in this frame
_thrust = glm::vec3(0, 0, 0);
}
void Avatar::checkForMouseRayTouching() {
@ -782,41 +820,52 @@ void Avatar::updateCollisionWithSphere(glm::vec3 position, float radius, float d
}
void Avatar::updateCollisionWithEnvironment() {
glm::vec3 up = getBodyUpDirection();
float radius = _height * 0.125f;
const float ENVIRONMENT_SURFACE_ELASTICITY = 1.0f;
const float ENVIRONMENT_SURFACE_DAMPING = 0.01;
glm::vec3 penetration;
if (Application::getInstance()->getEnvironment()->findCapsulePenetration(
_position - up * (_pelvisFloatingHeight - radius),
_position + up * (_height - _pelvisFloatingHeight - radius), radius, penetration)) {
applyCollisionWithScene(penetration);
applyHardCollision(penetration, ENVIRONMENT_SURFACE_ELASTICITY, ENVIRONMENT_SURFACE_DAMPING);
}
}
void Avatar::updateCollisionWithVoxels() {
float radius = _height * 0.125f;
const float VOXEL_ELASTICITY = 1.4f;
const float VOXEL_DAMPING = 0.0;
glm::vec3 penetration;
if (Application::getInstance()->getVoxels()->findCapsulePenetration(
_position - glm::vec3(0.0f, _pelvisFloatingHeight - radius, 0.0f),
_position + glm::vec3(0.0f, _height - _pelvisFloatingHeight - radius, 0.0f), radius, penetration)) {
applyCollisionWithScene(penetration);
applyHardCollision(penetration, VOXEL_ELASTICITY, VOXEL_DAMPING);
}
}
void Avatar::applyCollisionWithScene(const glm::vec3& penetration) {
void Avatar::applyHardCollision(const glm::vec3& penetration, float elasticity, float damping) {
//
// Update the avatar in response to a hard collision. Position will be reset exactly
// to outside the colliding surface. Velocity will be modified according to elasticity.
//
// if elasticity = 1.0, collision is inelastic.
// if elasticity > 1.0, collision is elastic.
//
_position -= penetration;
static float STATIC_FRICTION_VELOCITY = 0.15f;
static float STATIC_FRICTION_DAMPING = 0.0f;
static float KINETIC_FRICTION_DAMPING = 0.95f;
static float HALTING_VELOCITY = 0.2f;
// cancel out the velocity component in the direction of penetration
float penetrationLength = glm::length(penetration);
if (penetrationLength > EPSILON) {
_elapsedTimeSinceCollision = 0.0f;
glm::vec3 direction = penetration / penetrationLength;
_velocity -= glm::dot(_velocity, direction) * direction;
_velocity *= KINETIC_FRICTION_DAMPING;
// If velocity is quite low, apply static friction that takes away energy
if (glm::length(_velocity) < STATIC_FRICTION_VELOCITY) {
_velocity *= STATIC_FRICTION_DAMPING;
_velocity -= glm::dot(_velocity, direction) * direction * elasticity;
_velocity *= glm::clamp(1.f - damping, 0.0f, 1.0f);
if ((glm::length(_velocity) < HALTING_VELOCITY) && (glm::length(_thrust) == 0.f)) {
// If moving really slowly after a collision, and not applying forces, stop altogether
_velocity *= 0.f;
}
}
}
@ -839,7 +888,6 @@ void Avatar::updateAvatarCollisions(float deltaTime) {
// apply forces from collision
applyCollisionWithOtherAvatar(otherAvatar, deltaTime);
}
// test other avatar hand position for proximity
glm::vec3 v(_skeleton.joint[ AVATAR_JOINT_RIGHT_SHOULDER ].position);
v -= otherAvatar->getPosition();

View file

@ -85,6 +85,7 @@ public:
void init();
void reset();
void simulate(float deltaTime, Transmitter* transmitter);
void updateThrust(float deltaTime, Transmitter * transmitter);
void updateHeadFromGyros(float frametime, SerialInterface * serialInterface);
void updateFromMouse(int mouseX, int mouseY, int screenWidth, int screenHeight);
void addBodyYaw(float y) {_bodyYaw += y;};
@ -96,6 +97,7 @@ public:
void setMovedHandOffset (glm::vec3 movedHandOffset ) { _movedHandOffset = movedHandOffset;}
void setThrust (glm::vec3 newThrust ) { _thrust = newThrust; };
void setDisplayingLookatVectors(bool displayingLookatVectors) { _head.setRenderLookatVectors(displayingLookatVectors);}
void setVelocity (const glm::vec3 velocity ) { _velocity = velocity; };
void setLeanScale (float scale ) { _leanScale = scale;}
void setGravity (glm::vec3 gravity);
void setMouseRay (const glm::vec3 &origin, const glm::vec3 &direction);
@ -117,6 +119,9 @@ public:
float getHeight () const { return _height;}
AvatarMode getMode () const { return _mode;}
float getLeanScale () const { return _leanScale;}
float getElapsedTimeStopped () const { return _elapsedTimeStopped;}
float getElapsedTimeMoving () const { return _elapsedTimeMoving;}
float getElapsedTimeSinceCollision() const { return _elapsedTimeSinceCollision;}
float getAbsoluteHeadYaw () const;
float getAbsoluteHeadPitch () const;
Head& getHead () {return _head; }
@ -130,6 +135,7 @@ public:
// Set what driving keys are being pressed to control thrust levels
void setDriveKeys(int key, bool val) { _driveKeys[key] = val; };
bool getDriveKeys(int key) { return _driveKeys[key]; };
void jump() { _shouldJump = true; };
// Set/Get update the thrust that will move the avatar around
void addThrust(glm::vec3 newThrust) { _thrust += newThrust; };
@ -182,6 +188,7 @@ private:
glm::vec3 _handHoldingPosition;
glm::vec3 _velocity;
glm::vec3 _thrust;
bool _shouldJump;
float _speed;
float _maxArmLength;
float _leanScale;
@ -192,13 +199,16 @@ private:
float _height;
Balls* _balls;
AvatarTouch _avatarTouch;
float _distanceToNearestAvatar; // How close is the nearest avatar?
float _distanceToNearestAvatar; // How close is the nearest avatar?
glm::vec3 _gravity;
glm::vec3 _worldUpDirection;
glm::vec3 _mouseRayOrigin;
glm::vec3 _mouseRayDirection;
Avatar* _interactingOther;
bool _isMouseTurningRight;
float _elapsedTimeMoving; // Timers to drive camera transitions when moving
float _elapsedTimeStopped;
float _elapsedTimeSinceCollision;
AvatarVoxelSystem _voxels;
@ -218,7 +228,7 @@ private:
void updateCollisionWithSphere( glm::vec3 position, float radius, float deltaTime );
void updateCollisionWithEnvironment();
void updateCollisionWithVoxels();
void applyCollisionWithScene(const glm::vec3& penetration);
void applyHardCollision(const glm::vec3& penetration, float elasticity, float damping);
void applyCollisionWithOtherAvatar( Avatar * other, float deltaTime );
void checkForMouseRayTouching();
void renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2);

View file

@ -70,9 +70,7 @@ void Transmitter::processIncomingData(unsigned char* packetData, int numBytes) {
// Update estimated absolute position from rotation rates
_estimatedRotation += _lastRotationRate * DELTA_TIME;
printf("The accel %f, %f, %f\n", _lastAcceleration.x, _lastAcceleration.y, _lastAcceleration.z);
// Sensor Fusion! Slowly adjust estimated rotation to be relative to gravity (average acceleration)
const float GRAVITY_FOLLOW_RATE = 1.f;
float rollAngle = angleBetween(glm::vec3(_lastAcceleration.x, _lastAcceleration.y, 0.f), glm::vec3(0,-1,0)) *

View file

@ -103,8 +103,8 @@ public:
void setColor(const nodeColor& color);
const nodeColor& getTrueColor() const { return _trueColor; };
const nodeColor& getColor() const { return _currentColor; };
void setDensity(const float density) { _density = density; };
const float getDensity() const { return _density; };
void setDensity(float density) { _density = density; };
float getDensity() const { return _density; };
#else
void setFalseColor(colorPart red, colorPart green, colorPart blue) { /* no op */ };
void setFalseColored(bool isFalseColored) { /* no op */ };