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

This commit is contained in:
ZappoMan 2013-05-29 08:12:07 -07:00
commit 6b1d37599c
24 changed files with 806 additions and 479 deletions

View file

@ -905,7 +905,7 @@ void Application::idle() {
for(AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
if (agent->getLinkedData() != NULL) {
Avatar *avatar = (Avatar *)agent->getLinkedData();
avatar->simulate(deltaTime, false);
avatar->simulate(deltaTime, NULL);
avatar->setMouseRay(mouseRayOrigin, mouseRayDirection);
}
}
@ -919,39 +919,29 @@ void Application::idle() {
_myAvatar.simulate(deltaTime, NULL);
}
if (_myCamera.getMode() != CAMERA_MODE_MIRROR) {
if (_myCamera.getMode() != CAMERA_MODE_MIRROR && !OculusManager::isConnected()) {
if (_manualFirstPerson) {
if (_myCamera.getMode() != CAMERA_MODE_FIRST_PERSON ) {
Camera::CameraFollowingAttributes a;
a.upShift = 0.0f;
a.distance = 0.0f;
a.tightness = 100.0f;
_myCamera.setMode(CAMERA_MODE_FIRST_PERSON, a);
_myCamera.setMode(CAMERA_MODE_FIRST_PERSON);
_myCamera.setModeShiftRate(1.0f);
}
} else {
if (_myAvatar.getIsNearInteractingOther()) {
if (_myCamera.getMode() != CAMERA_MODE_FIRST_PERSON) {
Camera::CameraFollowingAttributes a;
a.upShift = 0.0f;
a.distance = 0.0f;
a.tightness = 100.0f;
_myCamera.setMode(CAMERA_MODE_FIRST_PERSON, a);
_myCamera.setMode(CAMERA_MODE_FIRST_PERSON);
_myCamera.setModeShiftRate(1.0f);
}
}
else {
if (_myCamera.getMode() != CAMERA_MODE_THIRD_PERSON) {
Camera::CameraFollowingAttributes a;
a.upShift = -0.2f;
a.distance = 1.5f;
a.tightness = 8.0f;
_myCamera.setMode(CAMERA_MODE_THIRD_PERSON, a);
_myCamera.setMode(CAMERA_MODE_THIRD_PERSON);
_myCamera.setModeShiftRate(1.0f);
}
}
}
}
// Update audio stats for procedural sounds
#ifndef _WIN32
_audio.setLastAcceleration(_myAvatar.getThrust());
@ -985,17 +975,11 @@ void Application::setHead(bool head) {
#endif
if (head) {
Camera::CameraFollowingAttributes a;
a.upShift = 0.0f;
a.distance = 0.2f;
a.tightness = 100.0f;
_myCamera.setMode(CAMERA_MODE_MIRROR, a);
_myCamera.setMode(CAMERA_MODE_MIRROR);
_myCamera.setModeShiftRate(100.0f);
} else {
Camera::CameraFollowingAttributes a;
a.upShift = -0.2f;
a.distance = 1.5f;
a.tightness = 8.0f;
_myCamera.setMode(CAMERA_MODE_THIRD_PERSON, a);
_myCamera.setMode(CAMERA_MODE_THIRD_PERSON);
_myCamera.setModeShiftRate(1.0f);
}
}
@ -1323,11 +1307,8 @@ void Application::init() {
_stars.readInput(STAR_FILE, STAR_CACHE_FILE, 0);
_myAvatar.setPosition(START_LOCATION);
Camera::CameraFollowingAttributes a;
a.upShift = -0.2f;
a.distance = 1.5f;
a.tightness = 8.0f;
_myCamera.setMode(CAMERA_MODE_THIRD_PERSON, a);
_myCamera.setMode(CAMERA_MODE_THIRD_PERSON );
_myCamera.setModeShiftRate(1.0f);
_myAvatar.setDisplayingLookatVectors(false);
QCursor::setPos(_headMouseX, _headMouseY);
@ -1374,7 +1355,7 @@ void Application::updateAvatar(float deltaTime) {
// Get audio loudness data from audio input device
#ifndef _WIN32
_myAvatar.setLoudness(_audio.getLastInputLoudness());
_myAvatar.getHead().setAudioLoudness(_audio.getLastInputLoudness());
#endif
// Update Avatar with latest camera and view frustum data...
@ -1707,7 +1688,6 @@ void Application::displaySide(Camera& whichCamera) {
glPopMatrix();
//draw a grid ground plane....
const float EDGE_SIZE_GROUND_PLANE = 20.f;
drawGroundPlaneGrid(EDGE_SIZE_GROUND_PLANE);
// Draw voxels

View file

@ -116,7 +116,7 @@ int audioCallback (const void* inputBuffer,
printLog("got output\n");
}
if (inputLeft != NULL) {
if (inputLeft) {
// Measure the loudness of the signal from the microphone and store in audio object
float loudness = 0;
@ -208,7 +208,7 @@ int audioCallback (const void* inputBuffer,
// if we haven't fired off the flange effect, check if we should
// TODO: lastMeasuredHeadYaw is now relative to body - check if this still works.
int lastYawMeasured = fabsf(interfaceAvatar->getLastMeasuredHeadYaw());
int lastYawMeasured = fabsf(interfaceAvatar->getHeadYawRate());
if (!::samplesLeftForFlange && lastYawMeasured > MIN_FLANGE_EFFECT_THRESHOLD) {
// we should flange for one second
@ -457,7 +457,7 @@ void Audio::addReceivedAudioToBuffer(unsigned char* receivedData, int receivedBy
gettimeofday(&_firstPlaybackTime, NULL);
}
_ringBuffer.parseData((unsigned char *)receivedData, PACKET_LENGTH_BYTES);
_ringBuffer.parseData((unsigned char*) receivedData, PACKET_LENGTH_BYTES + sizeof(PACKET_HEADER));
_lastReceiveTime = currentReceiveTime;
}

View file

@ -34,7 +34,7 @@ const float BODY_UPRIGHT_FORCE = 10.0;
const float VELOCITY_DECAY = 5.0;
const float MY_HAND_HOLDING_PULL = 0.2;
const float YOUR_HAND_HOLDING_PULL = 1.0;
const float BODY_SPRING_DEFAULT_TIGHTNESS = 1500.0f;
const float BODY_SPRING_DEFAULT_TIGHTNESS = 1000.0f;
const float BODY_SPRING_FORCE = 300.0f;
const float BODY_SPRING_DECAY = 16.0f;
const float COLLISION_RADIUS_SCALAR = 1.8;
@ -54,15 +54,14 @@ const float JOINT_TOUCH_RANGE = 0.0005f;
const float ANGULAR_RIGHTING_SPEED = 45.0f;
const float FLOATING_HEIGHT = 0.13f;
const bool USING_HEAD_LEAN = false;
const float LEAN_SENSITIVITY = 0.15;
const float LEAN_MAX = 0.45;
const float LEAN_AVERAGING = 10.0;
const float HEAD_RATE_MAX = 50.f;
const float SKIN_COLOR[] = {1.0, 0.84, 0.66};
const float DARK_SKIN_COLOR[] = {0.9, 0.78, 0.63};
const int NUM_BODY_CONE_SIDES = 9;
const float LEAN_SENSITIVITY = 0.15;
const float LEAN_MAX = 0.45;
const float LEAN_AVERAGING = 10.0;
const float HEAD_RATE_MAX = 50.f;
float skinColor [] = {1.0, 0.84, 0.66};
float darkSkinColor[] = {0.9, 0.78, 0.63};
float lightBlue [] = {0.7, 0.8, 1.0 };
bool usingBigSphereCollisionTest = true;
@ -80,8 +79,8 @@ Avatar::Avatar(Agent* owningAgent) :
_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),
_cameraPosition(0.0f, 0.0f, 0.0f),
_handHoldingPosition(0.0f, 0.0f, 0.0f),
_velocity(0.0f, 0.0f, 0.0f),
_thrust(0.0f, 0.0f, 0.0f),
@ -165,14 +164,6 @@ float Avatar::getAbsoluteHeadPitch() const {
return _bodyPitch + _head.getPitch();
}
void Avatar::setMousePressed(bool mousePressed) {
_mousePressed = mousePressed;
}
bool Avatar::getIsNearInteractingOther() {
return _avatarTouch.getAbleToReachOtherAvatar();
}
void Avatar::updateFromMouse(int mouseX, int mouseY, int screenWidth, int screenHeight) {
// Update yaw based on mouse behavior
const float MOUSE_MOVE_RADIUS = 0.15f;
@ -443,8 +434,7 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
_head.setBodyRotation (glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll));
_head.setPosition(_joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition);
_head.setScale (_joint[ AVATAR_JOINT_HEAD_BASE ].radius);
_head.setAudioLoudness(_audioLoudness);
_head.setSkinColor(glm::vec3(skinColor[0], skinColor[1], skinColor[2]));
_head.setSkinColor(glm::vec3(SKIN_COLOR[0], SKIN_COLOR[1], SKIN_COLOR[2]));
_head.simulate(deltaTime, !_owningAgent);
// use speed and angular velocity to determine walking vs. standing
@ -471,7 +461,8 @@ void Avatar::checkForMouseRayTouching() {
}
void Avatar::setMouseRay(const glm::vec3 &origin, const glm::vec3 &direction ) {
_mouseRayOrigin = origin; _mouseRayDirection = direction;
_mouseRayOrigin = origin;
_mouseRayDirection = direction;
}
void Avatar::updateHandMovementAndTouching(float deltaTime) {
@ -486,6 +477,7 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) {
if (!_owningAgent) {
_avatarTouch.setMyBodyPosition(_position);
_avatarTouch.setMyOrientation(_orientation);
float closestDistance = std::numeric_limits<float>::max();
@ -517,7 +509,9 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) {
if (_interactingOther) {
_avatarTouch.setHasInteractingOther(true);
_avatarTouch.setYourBodyPosition(_interactingOther->_position);
_avatarTouch.setYourOrientation (_interactingOther->_orientation);
_avatarTouch.setYourHandPosition(_interactingOther->_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].springyPosition);
_avatarTouch.setYourHandState (_interactingOther->_handState);
@ -568,6 +562,8 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) {
_velocity += vectorFromMyHandToYourHand * force;
}
}
} else {
_avatarTouch.setHasInteractingOther(false);
}
}//if (_isMine)
@ -640,11 +636,14 @@ void Avatar::updateCollisionWithVoxels() {
}
void Avatar::applyCollisionWithScene(const glm::vec3& penetration) {
_position += penetration;
_position -= penetration;
// reflect the velocity component in the direction of penetration
glm::vec3 direction = glm::normalize(penetration);
_velocity -= 2.0f * glm::dot(_velocity, direction) * direction * BOUNCE;
float penetrationLength = glm::length(penetration);
if (penetrationLength > EPSILON) {
glm::vec3 direction = penetration / penetrationLength;
_velocity -= 2.0f * glm::dot(_velocity, direction) * direction * BOUNCE;
}
}
void Avatar::updateAvatarCollisions(float deltaTime) {
@ -872,8 +871,8 @@ void Avatar::initializeSkeleton() {
_joint[ AVATAR_JOINT_PELVIS ].defaultPosePosition = glm::vec3( 0.0, 0.0, 0.0 );
_joint[ AVATAR_JOINT_TORSO ].defaultPosePosition = glm::vec3( 0.0, 0.09, 0.01 );
_joint[ AVATAR_JOINT_CHEST ].defaultPosePosition = glm::vec3( 0.0, 0.09, 0.01 );
_joint[ AVATAR_JOINT_NECK_BASE ].defaultPosePosition = glm::vec3( 0.0, 0.12, -0.01 );
_joint[ AVATAR_JOINT_HEAD_BASE ].defaultPosePosition = glm::vec3( 0.0, 0.08, 0.00 );
_joint[ AVATAR_JOINT_NECK_BASE ].defaultPosePosition = glm::vec3( 0.0, 0.14, -0.01 );
_joint[ AVATAR_JOINT_HEAD_BASE ].defaultPosePosition = glm::vec3( 0.0, 0.04, 0.00 );
_joint[ AVATAR_JOINT_LEFT_COLLAR ].defaultPosePosition = glm::vec3( -0.06, 0.04, -0.01 );
_joint[ AVATAR_JOINT_LEFT_SHOULDER ].defaultPosePosition = glm::vec3( -0.05, 0.0, -0.01 );
@ -926,31 +925,6 @@ void Avatar::initializeSkeleton() {
_joint[ AVATAR_JOINT_RIGHT_HEEL ].radius = 0.025;
_joint[ AVATAR_JOINT_RIGHT_TOES ].radius = 0.025;
// specify the tightness of the springy positions as far as attraction to rigid body
_joint[ AVATAR_JOINT_PELVIS ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 1.0;
_joint[ AVATAR_JOINT_TORSO ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.8;
_joint[ AVATAR_JOINT_CHEST ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.5;
_joint[ AVATAR_JOINT_NECK_BASE ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.4;
_joint[ AVATAR_JOINT_HEAD_BASE ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.3;
_joint[ AVATAR_JOINT_LEFT_COLLAR ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.5;
_joint[ AVATAR_JOINT_LEFT_SHOULDER ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.5;
_joint[ AVATAR_JOINT_LEFT_ELBOW ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.5;
_joint[ AVATAR_JOINT_LEFT_WRIST ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.3;
_joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.3;
_joint[ AVATAR_JOINT_RIGHT_COLLAR ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.5;
_joint[ AVATAR_JOINT_RIGHT_SHOULDER ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.5;
_joint[ AVATAR_JOINT_RIGHT_ELBOW ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.5;
_joint[ AVATAR_JOINT_RIGHT_WRIST ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.3;
_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS * 0.3;
_joint[ AVATAR_JOINT_LEFT_HIP ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS;
_joint[ AVATAR_JOINT_LEFT_KNEE ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS;
_joint[ AVATAR_JOINT_LEFT_HEEL ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS;
_joint[ AVATAR_JOINT_LEFT_TOES ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS;
_joint[ AVATAR_JOINT_RIGHT_HIP ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS;
_joint[ AVATAR_JOINT_RIGHT_KNEE ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS;
_joint[ AVATAR_JOINT_RIGHT_HEEL ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS;
_joint[ AVATAR_JOINT_RIGHT_TOES ].springBodyTightness = BODY_SPRING_DEFAULT_TIGHTNESS;
// to aid in hand-shaking and hand-holding, the right hand is not collidable
_joint[ AVATAR_JOINT_RIGHT_ELBOW ].isCollidable = false;
_joint[ AVATAR_JOINT_RIGHT_WRIST ].isCollidable = false;
@ -1100,15 +1074,6 @@ void Avatar::updateBodySprings(float deltaTime) {
}
}
const glm::vec3& Avatar::getSpringyHeadPosition() const {
return _joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition;
}
const glm::vec3& Avatar::getHeadPosition() const {
return _joint[ AVATAR_JOINT_HEAD_BASE ].position;
}
void Avatar::updateArmIKAndConstraints(float deltaTime) {
// determine the arm vector
@ -1168,48 +1133,53 @@ void Avatar::renderBody(bool lookingInMirror) {
if (_owningAgent || b == AVATAR_JOINT_RIGHT_ELBOW
|| b == AVATAR_JOINT_RIGHT_WRIST
|| b == AVATAR_JOINT_RIGHT_FINGERTIPS ) {
glColor3f(skinColor[0] + _joint[b].touchForce * 0.3f,
skinColor[1] - _joint[b].touchForce * 0.2f,
skinColor[2] - _joint[b].touchForce * 0.1f);
glColor3f(SKIN_COLOR[0] + _joint[b].touchForce * 0.3f,
SKIN_COLOR[1] - _joint[b].touchForce * 0.2f,
SKIN_COLOR[2] - _joint[b].touchForce * 0.1f);
} else {
glColor4f(skinColor[0] + _joint[b].touchForce * 0.3f,
skinColor[1] - _joint[b].touchForce * 0.2f,
skinColor[2] - _joint[b].touchForce * 0.1f,
glColor4f(SKIN_COLOR[0] + _joint[b].touchForce * 0.3f,
SKIN_COLOR[1] - _joint[b].touchForce * 0.2f,
SKIN_COLOR[2] - _joint[b].touchForce * 0.1f,
glm::clamp((distanceToCamera - RENDER_TRANSLUCENT_BEYOND)
/ (RENDER_OPAQUE_BEYOND - RENDER_TRANSLUCENT_BEYOND), 0.f, 1.f));
}
glPushMatrix();
glTranslatef(_joint[b].springyPosition.x, _joint[b].springyPosition.y, _joint[b].springyPosition.z);
glutSolidSphere(_joint[b].radius, 20.0f, 20.0f);
glPopMatrix();
// Render the cone connecting this joint to it's parent
if (_joint[b].parent != AVATAR_JOINT_NULL)
// Render the cone connecting this joint to its parent
if (_joint[b].parent != AVATAR_JOINT_NULL) {
if ((b != AVATAR_JOINT_HEAD_TOP )
&& (b != AVATAR_JOINT_HEAD_BASE )
&& (b != AVATAR_JOINT_PELVIS )
&& (b != AVATAR_JOINT_TORSO )
&& (b != AVATAR_JOINT_CHEST )
&& (b != AVATAR_JOINT_LEFT_COLLAR )
&& (b != AVATAR_JOINT_LEFT_SHOULDER )
&& (b != AVATAR_JOINT_RIGHT_COLLAR )
&& (b != AVATAR_JOINT_RIGHT_SHOULDER)) {
// Render cone sections connecting the joint positions
glColor3fv(darkSkinColor);
&& (b != AVATAR_JOINT_HEAD_BASE )
&& (b != AVATAR_JOINT_PELVIS )
&& (b != AVATAR_JOINT_TORSO )
&& (b != AVATAR_JOINT_CHEST )
&& (b != AVATAR_JOINT_LEFT_COLLAR )
&& (b != AVATAR_JOINT_LEFT_SHOULDER )
&& (b != AVATAR_JOINT_RIGHT_COLLAR )
&& (b != AVATAR_JOINT_RIGHT_SHOULDER)) {
glColor3fv(DARK_SKIN_COLOR);
float r1 = _joint[_joint[b].parent ].radius * 0.8;
float r2 = _joint[b ].radius * 0.8;
if (b == AVATAR_JOINT_HEAD_BASE) {
r1 *= 0.5f;
}
renderJointConnectingCone
(
_joint[_joint[b].parent ].springyPosition,
_joint[b ].springyPosition,
_joint[_joint[b].parent ].radius * 0.8,
_joint[b ].radius * 0.8
_joint[b ].springyPosition, r2, r2
);
}
}
}
}
}
}
void Avatar::setHeadFromGyros(glm::vec3* eulerAngles, glm::vec3* angularVelocity, float deltaTime, float smoothingTime) {
//
// Given absolute position and angular velocity information, update the avatar's head angles
@ -1275,34 +1245,37 @@ void Avatar::readAvatarDataFromFile() {
void Avatar::renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2) {
glBegin(GL_TRIANGLES);
int num = 10;
glm::vec3 axis = glm::normalize(position2 - position1);
glm::vec3 axis = position2 - position1;
float length = glm::length(axis);
if (length > 0.0f) {
glm::vec3 perpSin = glm::vec3(axis.y, axis.z, axis.x);
glm::vec3 perpCos = glm::vec3(axis.z, axis.x, axis.y);
float angle1 = 0.0;
float angle2 = 0.0;
for (int i = 0; i < num; i ++) {
axis /= length;
angle1 = angle2;
angle2 = ((float)(i+1) / (float)num) * PI * 2.0;
glm::vec3 perpSin = glm::vec3(1.0f, 0.0f, 0.0f);
glm::vec3 perpCos = glm::normalize(glm::cross(axis, perpSin));
perpSin = glm::cross(perpCos, axis);
float anglea = 0.0;
float angleb = 0.0;
for (int i = 0; i < NUM_BODY_CONE_SIDES; i ++) {
// the rectangles that comprise the sides of the cone section are
// referenced by "a" and "b" in one dimension, and "1", and "2" in the other dimension.
anglea = angleb;
angleb = ((float)(i+1) / (float)NUM_BODY_CONE_SIDES) * PI * 2.0f;
float s1 = sinf(angle1);
float s2 = sinf(angle2);
float c1 = cosf(angle1);
float c2 = cosf(angle2);
glm::vec3 p1a = position1 + perpSin * s1 * radius1 + perpCos * c1 * radius1;
glm::vec3 p1b = position1 + perpSin * s2 * radius1 + perpCos * c2 * radius1;
glm::vec3 p2a = position2 + perpSin * s1 * radius2 + perpCos * c1 * radius2;
glm::vec3 p2b = position2 + perpSin * s2 * radius2 + perpCos * c2 * radius2;
float sa = sinf(anglea);
float sb = sinf(angleb);
float ca = cosf(anglea);
float cb = cosf(angleb);
glm::vec3 p1a = position1 + perpSin * sa * radius1 + perpCos * ca * radius1;
glm::vec3 p1b = position1 + perpSin * sb * radius1 + perpCos * cb * radius1;
glm::vec3 p2a = position2 + perpSin * sa * radius2 + perpCos * ca * radius2;
glm::vec3 p2b = position2 + perpSin * sb * radius2 + perpCos * cb * radius2;
glVertex3f(p1a.x, p1a.y, p1a.z);
glVertex3f(p1b.x, p1b.y, p1b.z);

View file

@ -2,7 +2,6 @@
// Avatar.h
// interface
//
// Created by Philip Rosedale on 9/11/12.
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
//
@ -19,6 +18,7 @@
#include "SerialInterface.h"
#include "Balls.h"
#include "Head.h"
#include "Skeleton.h"
#include "Transmitter.h"
enum DriveKeys
@ -42,87 +42,52 @@ enum AvatarMode
NUM_AVATAR_MODES
};
enum AvatarJointID
{
AVATAR_JOINT_NULL = -1,
AVATAR_JOINT_PELVIS,
AVATAR_JOINT_TORSO,
AVATAR_JOINT_CHEST,
AVATAR_JOINT_NECK_BASE,
AVATAR_JOINT_HEAD_BASE,
AVATAR_JOINT_HEAD_TOP,
AVATAR_JOINT_LEFT_COLLAR,
AVATAR_JOINT_LEFT_SHOULDER,
AVATAR_JOINT_LEFT_ELBOW,
AVATAR_JOINT_LEFT_WRIST,
AVATAR_JOINT_LEFT_FINGERTIPS,
AVATAR_JOINT_RIGHT_COLLAR,
AVATAR_JOINT_RIGHT_SHOULDER,
AVATAR_JOINT_RIGHT_ELBOW,
AVATAR_JOINT_RIGHT_WRIST,
AVATAR_JOINT_RIGHT_FINGERTIPS,
AVATAR_JOINT_LEFT_HIP,
AVATAR_JOINT_LEFT_KNEE,
AVATAR_JOINT_LEFT_HEEL,
AVATAR_JOINT_LEFT_TOES,
AVATAR_JOINT_RIGHT_HIP,
AVATAR_JOINT_RIGHT_KNEE,
AVATAR_JOINT_RIGHT_HEEL,
AVATAR_JOINT_RIGHT_TOES,
NUM_AVATAR_JOINTS
};
class Avatar : public AvatarData {
public:
Avatar(Agent* owningAgent = NULL);
~Avatar();
void reset();
void updateHeadFromGyros(float frametime, SerialInterface * serialInterface, glm::vec3 * gravity);
void updateFromMouse(int mouseX, int mouseY, int screenWidth, int screenHeight);
void setNoise (float mag) {_head.noise = mag;}
float getLastMeasuredHeadYaw() const {return _head.yawRate;}
float getBodyYaw() {return _bodyYaw;};
void addBodyYaw(float y) {_bodyYaw += y;};
void setGravity(glm::vec3 gravity);
void setMouseRay(const glm::vec3 &origin, const glm::vec3 &direction );
bool getIsNearInteractingOther();
float getAbsoluteHeadYaw() const;
float getAbsoluteHeadPitch() const;
glm::vec3 caclulateAverageEyePosition() { return _head.caclulateAverageEyePosition(); } // get the position smack-dab between the eyes (for lookat)
const glm::vec3& getHeadPosition() const ; // get the position of the avatar's rigid body head
const glm::vec3& getSpringyHeadPosition() const ; // get the springy position of the avatar's head
const glm::vec3& getJointPosition(AvatarJointID j) const { return _joint[j].springyPosition; };
const glm::vec3& getBodyUpDirection() const { return _orientation.getUp(); };
float getSpeed() const { return _speed; }
const glm::vec3& getVelocity() const { return _velocity; };
float getGirth();
float getHeight() const { return _height; }
AvatarMode getMode() const { return _mode; }
Head& getHead() { return _head; }
void setMousePressed(bool pressed);
void render(bool lookingInMirror, glm::vec3 cameraPosition);
void renderBody(bool lookingInMirror);
void reset();
void simulate(float deltaTime, Transmitter* transmitter);
void setMovedHandOffset(glm::vec3 movedHandOffset) { _movedHandOffset = movedHandOffset; }
void updateArmIKAndConstraints( float deltaTime );
void setDisplayingLookatVectors(bool displayingLookatVectors) { _head.setRenderLookatVectors(displayingLookatVectors); }
void updateHeadFromGyros(float frametime, SerialInterface * serialInterface, glm::vec3 * gravity);
void updateFromMouse(int mouseX, int mouseY, int screenWidth, int screenHeight);
void addBodyYaw(float y) {_bodyYaw += y;};
void render(bool lookingInMirror, glm::vec3 cameraPosition);
//setters
void setMousePressed (bool mousePressed ) { _mousePressed = mousePressed;}
void setNoise (float mag ) { _head.noise = mag;}
void setMovedHandOffset (glm::vec3 movedHandOffset ) { _movedHandOffset = movedHandOffset;}
void setThrust (glm::vec3 newThrust ) { _thrust = newThrust; };
void setDisplayingLookatVectors(bool displayingLookatVectors) { _head.setRenderLookatVectors(displayingLookatVectors);}
void setGravity (glm::vec3 gravity);
void setMouseRay (const glm::vec3 &origin, const glm::vec3 &direction);
//getters
float getHeadYawRate () const { return _head.yawRate;}
float getBodyYaw () const { return _bodyYaw;}
bool getIsNearInteractingOther() const { return _avatarTouch.getAbleToReachOtherAvatar();}
const glm::vec3& getHeadPosition () const { return _joint[ AVATAR_JOINT_HEAD_BASE ].position;}
const glm::vec3& getSpringyHeadPosition () const { return _joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition;}
const glm::vec3& getJointPosition (AvatarJointID j) const { return _joint[j].springyPosition;}
const glm::vec3& getBodyUpDirection () const { return _orientation.getUp();}
const glm::vec3& getVelocity () const { return _velocity;}
float getSpeed () const { return _speed;}
float getHeight () const { return _height;}
AvatarMode getMode () const { return _mode;}
float getAbsoluteHeadYaw () const;
float getAbsoluteHeadPitch () const;
Head& getHead () {return _head; }
// 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]; };
// Set/Get update the thrust that will move the avatar around
void setThrust(glm::vec3 newThrust) { _thrust = newThrust; };
void addThrust(glm::vec3 newThrust) { _thrust += newThrust; };
glm::vec3 getThrust() { return _thrust; };
//read/write avatar data
void writeAvatarDataToFile();
void readAvatarDataFromFile();
@ -151,6 +116,7 @@ private:
};
Head _head;
Skeleton _skeleton;
float _TEST_bigSphereRadius;
glm::vec3 _TEST_bigSpherePosition;
bool _mousePressed;
@ -184,6 +150,8 @@ private:
bool _isMouseTurningRight;
// private methods...
glm::vec3 caclulateAverageEyePosition() { return _head.caclulateAverageEyePosition(); } // get the position smack-dab between the eyes (for lookat)
void renderBody(bool lookingInMirror);
void initializeSkeleton();
void updateSkeleton();
void initializeBodySprings();
@ -192,6 +160,7 @@ private:
void readSensors();
void updateHandMovementAndTouching(float deltaTime);
void updateAvatarCollisions(float deltaTime);
void updateArmIKAndConstraints( float deltaTime );
void updateCollisionWithSphere( glm::vec3 position, float radius, float deltaTime );
void updateCollisionWithEnvironment();
void updateCollisionWithVoxels();

View file

@ -13,6 +13,7 @@
const float THREAD_RADIUS = 0.007;
const float HANDS_CLOSE_ENOUGH_TO_GRASP = 0.2;
const float AVATAR_FACING_THRESHOLD = 0.1f; // (-1 to 1) (larger value indicates narrower angle of influence
AvatarTouch::AvatarTouch() {
@ -27,61 +28,49 @@ AvatarTouch::AvatarTouch() {
_weAreHoldingHands = false;
_canReachToOtherAvatar = false;
_handsCloseEnoughToGrasp = false;
_hasInteractingOther = false;
_myOrientation.setToIdentity();
_yourOrientation.setToIdentity();
for (int p=0; p<NUM_POINTS; p++) {
_point[p] = glm::vec3(0.0, 0.0, 0.0);
}
}
void AvatarTouch::setMyHandPosition(glm::vec3 position) {
_myHandPosition = position;
}
void AvatarTouch::setYourHandPosition(glm::vec3 position) {
_yourHandPosition = position;
}
void AvatarTouch::setMyBodyPosition(glm::vec3 position) {
_myBodyPosition = position;
}
void AvatarTouch::setYourBodyPosition(glm::vec3 position) {
_yourBodyPosition = position;
}
void AvatarTouch::setMyHandState(int state) {
_myHandState = state;
}
void AvatarTouch::setYourHandState(int state) {
_yourHandState = state;
}
void AvatarTouch::setReachableRadius(float r) {
_reachableRadius = r;
}
void AvatarTouch::simulate (float deltaTime) {
glm::vec3 vectorBetweenBodies = _yourBodyPosition - _myBodyPosition;
float distanceBetweenBodies = glm::length(vectorBetweenBodies);
_canReachToOtherAvatar = false; // default
if (distanceBetweenBodies < _reachableRadius) {
_vectorBetweenHands = _yourHandPosition - _myHandPosition;
if (_hasInteractingOther) {
glm::vec3 vectorBetweenBodies = _yourBodyPosition - _myBodyPosition;
float distanceBetweenBodies = glm::length(vectorBetweenBodies);
glm::vec3 directionBetweenBodies = vectorBetweenBodies / distanceBetweenBodies;
float distanceBetweenHands = glm::length(_vectorBetweenHands);
if (distanceBetweenHands < HANDS_CLOSE_ENOUGH_TO_GRASP) {
_handsCloseEnoughToGrasp = true;
} else {
_handsCloseEnoughToGrasp = false;
bool facingEachOther = false;
if (( glm::dot(_myOrientation.getFront(), _yourOrientation.getFront()) < -AVATAR_FACING_THRESHOLD) // we're facing each other
&& ( glm::dot(_myOrientation.getFront(), directionBetweenBodies ) > AVATAR_FACING_THRESHOLD)) { // I'm facing you
facingEachOther = true;
}
_canReachToOtherAvatar = true;
} else {
_canReachToOtherAvatar = false;
}
if ((distanceBetweenBodies < _reachableRadius)
&& (facingEachOther)) {
_canReachToOtherAvatar = true;
_vectorBetweenHands = _yourHandPosition - _myHandPosition;
float distanceBetweenHands = glm::length(_vectorBetweenHands);
if (distanceBetweenHands < HANDS_CLOSE_ENOUGH_TO_GRASP) {
_handsCloseEnoughToGrasp = true;
} else {
_handsCloseEnoughToGrasp = false;
}
}
}
}
void AvatarTouch::render(glm::vec3 cameraPosition) {
if (_canReachToOtherAvatar) {
@ -92,7 +81,7 @@ void AvatarTouch::render(glm::vec3 cameraPosition) {
p.y = 0.0005f;
renderCircle(p, _reachableRadius, glm::vec3(0.0f, 1.0f, 0.0f), 30);
// show is we are golding hands...
// show if we are holding hands...
if (_weAreHoldingHands) {
renderBeamBetweenHands();

View file

@ -9,6 +9,7 @@
#define __interface__AvatarTouch__
#include <glm/glm.hpp>
#include "Orientation.h"
enum AvatarHandState
{
@ -26,18 +27,18 @@ public:
void simulate(float deltaTime);
void render(glm::vec3 cameraPosition);
void setMyHandPosition (glm::vec3 position);
void setYourHandPosition(glm::vec3 position);
void setMyBodyPosition (glm::vec3 position);
void setYourBodyPosition(glm::vec3 position);
void setMyHandState (int state);
void setYourHandState (int state);
void setReachableRadius (float r);
void setAbleToReachOtherAvatar (bool a) {_canReachToOtherAvatar = a;}
void setHandsCloseEnoughToGrasp(bool h) {_handsCloseEnoughToGrasp = h;}
void setHoldingHands (bool h) {_weAreHoldingHands = h;}
void setHasInteractingOther(bool hasInteractingOther) { _hasInteractingOther = hasInteractingOther;}
void setMyHandPosition (glm::vec3 position ) { _myHandPosition = position;}
void setYourHandPosition (glm::vec3 position ) { _yourHandPosition = position;}
void setMyOrientation (Orientation orientation ) { _myOrientation = orientation;}
void setYourOrientation (Orientation orientation ) { _yourOrientation = orientation;}
void setMyBodyPosition (glm::vec3 position ) { _myBodyPosition = position;}
void setYourBodyPosition (glm::vec3 position ) { _yourBodyPosition = position;}
void setMyHandState (int state ) { _myHandState = state;}
void setYourHandState (int state ) { _yourHandState = state;}
void setReachableRadius (float radius ) { _reachableRadius = radius;}
void setHoldingHands (bool holding ) { _weAreHoldingHands = holding;}
bool getAbleToReachOtherAvatar () const {return _canReachToOtherAvatar; }
bool getHandsCloseEnoughToGrasp() const {return _handsCloseEnoughToGrasp;}
@ -47,18 +48,21 @@ private:
static const int NUM_POINTS = 100;
bool _weAreHoldingHands;
glm::vec3 _point [NUM_POINTS];
glm::vec3 _myBodyPosition;
glm::vec3 _yourBodyPosition;
glm::vec3 _myHandPosition;
glm::vec3 _yourHandPosition;
glm::vec3 _vectorBetweenHands;
int _myHandState;
int _yourHandState;
bool _canReachToOtherAvatar;
bool _handsCloseEnoughToGrasp;
float _reachableRadius;
bool _hasInteractingOther;
bool _weAreHoldingHands;
glm::vec3 _point [NUM_POINTS];
glm::vec3 _myBodyPosition;
glm::vec3 _yourBodyPosition;
glm::vec3 _myHandPosition;
glm::vec3 _yourHandPosition;
Orientation _myOrientation;
Orientation _yourOrientation;
glm::vec3 _vectorBetweenHands;
int _myHandState;
int _yourHandState;
bool _canReachToOtherAvatar;
bool _handsCloseEnoughToGrasp;
float _reachableRadius;
void renderBeamBetweenHands();
};

View file

@ -11,49 +11,51 @@
#include "Camera.h"
const float MODE_SHIFT_RATE = 6.0f;
const float CAMERA_MINIMUM_MODE_SHIFT_RATE = 0.5f;
const float CAMERA_FIRST_PERSON_MODE_UP_SHIFT = 0.0f;
const float CAMERA_FIRST_PERSON_MODE_DISTANCE = 0.0f;
const float CAMERA_FIRST_PERSON_MODE_TIGHTNESS = 100.0f;
const float CAMERA_THIRD_PERSON_MODE_UP_SHIFT = -0.2f;
const float CAMERA_THIRD_PERSON_MODE_DISTANCE = 1.5f;
const float CAMERA_THIRD_PERSON_MODE_TIGHTNESS = 8.0f;
const float CAMERA_MIRROR_MODE_UP_SHIFT = 0.0f;
const float CAMERA_MIRROR_MODE_DISTANCE = 0.2f;
const float CAMERA_MIRROR_MODE_TIGHTNESS = 100.0f;
Camera::Camera() {
_needsToInitialize = true;
_frustumNeedsReshape = true;
_modeShift = 0.0;
_mode = CAMERA_MODE_THIRD_PERSON;
_tightness = 10.0; // default
_fieldOfView = 60.0; // default
_nearClip = 0.08; // default
_farClip = 50.0 * TREE_SCALE; // default
_yaw = 0.0;
_pitch = 0.0;
_roll = 0.0;
_upShift = 0.0;
_distance = 0.0;
_idealYaw = 0.0;
_idealPitch = 0.0;
_idealRoll = 0.0;
_targetPosition = glm::vec3(0.0, 0.0, 0.0);
_position = glm::vec3(0.0, 0.0, 0.0);
_idealPosition = glm::vec3(0.0, 0.0, 0.0);
_modeShift = 0.0f;
_modeShiftRate = 1.0f;
_linearModeShift = 0.0f;
_mode = CAMERA_MODE_THIRD_PERSON;
_tightness = 10.0f; // default
_fieldOfView = 60.0f; // default
_nearClip = 0.08f; // default
_farClip = 50.0f * TREE_SCALE; // default
_yaw = 0.0f;
_pitch = 0.0f;
_roll = 0.0f;
_upShift = 0.0f;
_distance = 0.0f;
_previousUpShift = 0.0f;
_previousDistance = 0.0f;
_previousTightness = 0.0f;
_newUpShift = 0.0f;
_newDistance = 0.0f;
_newTightness = 0.0f;
_idealYaw = 0.0f;
_idealPitch = 0.0f;
_idealRoll = 0.0f;
_targetPosition = glm::vec3(0.0f, 0.0f, 0.0f);
_position = glm::vec3(0.0f, 0.0f, 0.0f);
_idealPosition = glm::vec3(0.0f, 0.0f, 0.0f);
_orientation.setToIdentity();
_attributes[CAMERA_MODE_FIRST_PERSON].upShift = CAMERA_DEFAULT_FIRST_PERSON_MODE_UP_SHIFT;
_attributes[CAMERA_MODE_FIRST_PERSON].distance = CAMERA_DEFAULT_FIRST_PERSON_MODE_DISTANCE;
_attributes[CAMERA_MODE_FIRST_PERSON].tightness = CAMERA_DEFAULT_FIRST_PERSON_MODE_TIGHTNESS;
_attributes[CAMERA_MODE_THIRD_PERSON].upShift = CAMERA_DEFAULT_THIRD_PERSON_MODE_UP_SHIFT;
_attributes[CAMERA_MODE_THIRD_PERSON].distance = CAMERA_DEFAULT_THIRD_PERSON_MODE_DISTANCE;
_attributes[CAMERA_MODE_THIRD_PERSON].tightness = CAMERA_DEFAULT_THIRD_PERSON_MODE_TIGHTNESS;
_attributes[CAMERA_MODE_MIRROR ].upShift = CAMERA_DEFAULT_MIRROR_MODE_UP_SHIFT;
_attributes[CAMERA_MODE_MIRROR ].distance = CAMERA_DEFAULT_MIRROR_MODE_DISTANCE;
_attributes[CAMERA_MODE_MIRROR ].tightness = CAMERA_DEFAULT_MIRROR_MODE_TIGHTNESS;
for (int m = 0; m < NUM_CAMERA_MODES; m ++) {
_previousAttributes[m].upShift = 0.0f;
_previousAttributes[m].distance = 0.0f;
_previousAttributes[m].tightness = 0.0f;
}
}
void Camera::update(float deltaTime) {
@ -67,7 +69,6 @@ void Camera::update(float deltaTime) {
generateOrientation();
}
// generate the ortho-normals for the orientation based on the three Euler angles
void Camera::generateOrientation() {
_orientation.setToIdentity();
@ -79,15 +80,26 @@ void Camera::generateOrientation() {
// use iterative forces to keep the camera at the desired position and angle
void Camera::updateFollowMode(float deltaTime) {
if (_modeShift < 1.0f) {
_modeShift += 5.0f * deltaTime;
if (_modeShift > 1.0f ) {
if (_linearModeShift < 1.0f) {
_linearModeShift += _modeShiftRate * deltaTime;
_modeShift = ONE_HALF - ONE_HALF * cosf(_linearModeShift * PIE );
_upShift = _previousUpShift * (1.0f - _modeShift) + _newUpShift * _modeShift;
_distance = _previousDistance * (1.0f - _modeShift) + _newDistance * _modeShift;
_tightness = _previousTightness * (1.0f - _modeShift) + _newTightness * _modeShift;
if (_linearModeShift > 1.0f ) {
_linearModeShift = 1.0f;
_modeShift = 1.0f;
_upShift = _newUpShift;
_distance = _newDistance;
_tightness = _newTightness;
}
}
// derive t from tightness
float t = _tightness * deltaTime;
float t = _tightness * _modeShift * deltaTime;
if (t > 1.0) {
t = 1.0;
}
@ -103,10 +115,6 @@ void Camera::updateFollowMode(float deltaTime) {
_pitch += (_idealPitch - _pitch) * t;
_roll += (_idealRoll - _roll ) * t;
}
_orientation.yaw (_yaw );
_orientation.pitch(_pitch);
_orientation.roll (_roll );
float radian = (_yaw / 180.0) * PIE;
@ -124,32 +132,45 @@ void Camera::updateFollowMode(float deltaTime) {
// force position towards ideal position
_position += (_idealPosition - _position) * t;
}
float inverseModeShift = 1.0f - _modeShift;
_upShift = _attributes[_mode].upShift * _modeShift + _previousAttributes[_mode].upShift * inverseModeShift;
_distance = _attributes[_mode].distance * _modeShift + _previousAttributes[_mode].distance * inverseModeShift;
_upShift = _attributes[_mode].upShift * _modeShift + _previousAttributes[_mode].upShift * inverseModeShift;
}
void Camera::setMode(CameraMode m, CameraFollowingAttributes a) {
_previousAttributes[m].upShift = _attributes[m].upShift;
_previousAttributes[m].distance = _attributes[m].distance;
_previousAttributes[m].tightness = _attributes[m].tightness;
_attributes[m].upShift = a.upShift;
_attributes[m].distance = a.distance;
_attributes[m].tightness = a.tightness;
void Camera::setModeShiftRate ( float rate ) {
setMode(m);
_modeShiftRate = rate;
if (_modeShiftRate < CAMERA_MINIMUM_MODE_SHIFT_RATE ) {
_modeShiftRate = CAMERA_MINIMUM_MODE_SHIFT_RATE;
}
}
void Camera::setMode(CameraMode m) {
void Camera::setMode(CameraMode m) {
_mode = m;
_modeShift = 0.0;
_linearModeShift = 0.0;
_previousUpShift = _upShift;
_previousDistance = _distance;
_previousTightness = _tightness;
if (_mode == CAMERA_MODE_THIRD_PERSON) {
_newUpShift = CAMERA_THIRD_PERSON_MODE_UP_SHIFT;
_newDistance = CAMERA_THIRD_PERSON_MODE_DISTANCE;
_newTightness = CAMERA_THIRD_PERSON_MODE_TIGHTNESS;
} else if (_mode == CAMERA_MODE_FIRST_PERSON) {
_newUpShift = CAMERA_FIRST_PERSON_MODE_UP_SHIFT;
_newDistance = CAMERA_FIRST_PERSON_MODE_DISTANCE;
_newTightness = CAMERA_FIRST_PERSON_MODE_TIGHTNESS;
} else if (_mode == CAMERA_MODE_MIRROR) {
_newUpShift = CAMERA_MIRROR_MODE_UP_SHIFT;
_newDistance = CAMERA_MIRROR_MODE_DISTANCE;
_newTightness = CAMERA_MIRROR_MODE_TIGHTNESS;
}
}
void Camera::setTargetRotation( float yaw, float pitch, float roll ) {
_idealYaw = yaw;
_idealPitch = pitch;

View file

@ -21,31 +21,11 @@ enum CameraMode
NUM_CAMERA_MODES
};
const float CAMERA_DEFAULT_FIRST_PERSON_MODE_UP_SHIFT = 0.0f;
const float CAMERA_DEFAULT_FIRST_PERSON_MODE_DISTANCE = 0.0f;
const float CAMERA_DEFAULT_FIRST_PERSON_MODE_TIGHTNESS = 100.0f;
const float CAMERA_DEFAULT_THIRD_PERSON_MODE_UP_SHIFT = -0.2f;
const float CAMERA_DEFAULT_THIRD_PERSON_MODE_DISTANCE = 1.5f;
const float CAMERA_DEFAULT_THIRD_PERSON_MODE_TIGHTNESS = 8.0f;
const float CAMERA_DEFAULT_MIRROR_MODE_UP_SHIFT = 0.0f;
const float CAMERA_DEFAULT_MIRROR_MODE_DISTANCE = 0.2f;
const float CAMERA_DEFAULT_MIRROR_MODE_TIGHTNESS = 100.0f;
class Camera
{
public:
Camera();
struct CameraFollowingAttributes
{
float upShift;
float distance;
float tightness;
};
void initialize(); // instantly put the camera at the ideal position and rotation.
void update( float deltaTime );
@ -62,7 +42,7 @@ public:
void setTargetRotation( float yaw, float pitch, float roll );
void setMode ( CameraMode m );
void setMode ( CameraMode m, CameraFollowingAttributes attributes );
void setModeShiftRate ( float r );
void setFieldOfView ( float f );
void setAspectRatio ( float a );
void setNearClip ( float n );
@ -102,18 +82,23 @@ private:
float _yaw;
float _pitch;
float _roll;
float _upShift;
float _idealYaw;
float _idealPitch;
float _idealRoll;
float _upShift;
float _distance;
float _tightness;
float _previousUpShift;
float _previousDistance;
float _previousTightness;
float _newUpShift;
float _newDistance;
float _newTightness;
Orientation _orientation;
float _modeShift;
float _linearModeShift;
float _modeShiftRate;
CameraFollowingAttributes _attributes[NUM_CAMERA_MODES];
CameraFollowingAttributes _previousAttributes[NUM_CAMERA_MODES];
void generateOrientation();
void updateFollowMode( float deltaTime );
};

View file

@ -60,8 +60,8 @@ void Environment::renderAtmospheres(Camera& camera) {
glm::vec3 Environment::getGravity (const glm::vec3& position) {
// the "original gravity"
glm::vec3 gravity;
if (position.x > 0.0f && position.x < 10.0f && position.y > 0.0f &&
position.y < 3.0f && position.z > 0.0f && position.z < 10.0f) {
if (position.x > 0.0f && position.x < EDGE_SIZE_GROUND_PLANE && position.y > 0.0f &&
position.y < 3.0f && position.z > 0.0f && position.z < EDGE_SIZE_GROUND_PLANE) {
gravity = glm::vec3(0.0f, -1.0f, 0.0f);
}
@ -101,13 +101,7 @@ const EnvironmentData Environment::getClosestData(const glm::vec3& position) {
bool Environment::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end,
float radius, glm::vec3& penetration) {
// collide with the "floor"
bool found = false;
penetration = glm::vec3(0.0f, 0.0f, 0.0f);
float floorDist = qMin(start.y, end.y) - radius;
if (floorDist < 0.0f) {
penetration.y = -floorDist;
found = true;
}
bool found = findCapsulePlanePenetration(start, end, radius, glm::vec4(0.0f, 1.0f, 0.0f, 0.0f), penetration);
// get the lock for the duration of the call
QMutexLocker locker(&_mutex);
@ -117,11 +111,10 @@ bool Environment::findCapsulePenetration(const glm::vec3& start, const glm::vec3
if (environmentData.getGravity() == 0.0f) {
continue; // don't bother colliding with gravity-less environments
}
glm::vec3 vector = computeVectorFromPointToSegment(environmentData.getAtmosphereCenter(), start, end);
float vectorLength = glm::length(vector);
float distance = vectorLength - environmentData.getAtmosphereInnerRadius() - radius;
if (distance < 0.0f) {
penetration += vector * (-distance / vectorLength);
glm::vec3 environmentPenetration;
if (findCapsuleSpherePenetration(start, end, radius, environmentData.getAtmosphereCenter(),
environmentData.getAtmosphereInnerRadius(), environmentPenetration)) {
penetration = addPenetrations(penetration, environmentPenetration);
found = true;
}
}

View file

@ -13,17 +13,17 @@
using namespace std;
const int MOHAWK_TRIANGLES = 50;
const bool USING_PHYSICAL_MOHAWK = true;
const float EYE_RIGHT_OFFSET = 0.27f;
const float EYE_UP_OFFSET = 0.36f;
const float EYE_FRONT_OFFSET = 0.8f;
const float EAR_RIGHT_OFFSET = 1.0;
const float MOUTH_FRONT_OFFSET = 0.9f;
//const float MOUTH_FRONT_OFFSET = 0.9f;
const float MOUTH_UP_OFFSET = -0.3f;
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;
@ -42,7 +42,6 @@ Head::Head(Avatar* owningAvatar) :
HeadData((AvatarData*)owningAvatar),
yawRate(0.0f),
_returnHeadToCenter(false),
_audioLoudness(0.0f),
_skinColor(0.0f, 0.0f, 0.0f),
_position(0.0f, 0.0f, 0.0f),
_rotation(0.0f, 0.0f, 0.0f),
@ -62,29 +61,32 @@ Head::Head(Avatar* owningAvatar) :
_audioAttack(0.0f),
_returnSpringScale(1.0f),
_bodyRotation(0.0f, 0.0f, 0.0f),
_renderLookatVectors(false),
_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].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);
}
_mohawkColors(NULL)
{
if (USING_PHYSICAL_MOHAWK) {
resetHairPhysics();
}
}
void Head::reset() {
_yaw = _pitch = _roll = 0.0f;
_leanForward = _leanSideways = 0.0f;
if (USING_PHYSICAL_MOHAWK) {
resetHairPhysics();
}
}
void Head::resetHairPhysics() {
for (int t = 0; t < NUM_HAIR_TUFTS; t ++) {
_hairTuft[t].length = HAIR_LENGTH;
_hairTuft[t].thickness = HAIR_THICKNESS;
_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;
@ -93,6 +95,7 @@ void Head::reset() {
}
}
void Head::simulate(float deltaTime, bool isMine) {
const float HEAD_MOTION_DECAY = 0.00;
@ -141,7 +144,9 @@ void Head::simulate(float deltaTime, bool isMine) {
// based on the nature of the lookat position, determine if the eyes can look / are looking at it.
determineIfLookingAtSomething();
updateHair(deltaTime);
if (USING_PHYSICAL_MOHAWK) {
updateHairPhysics(deltaTime);
}
}
void Head::determineIfLookingAtSomething() {
@ -196,7 +201,7 @@ void Head::calculateGeometry(bool lookingInMirror) {
//calculate the mouth position
_mouthPosition = _position + _orientation.getUp () * _scale * MOUTH_UP_OFFSET
+ _orientation.getFront() * _scale * MOUTH_FRONT_OFFSET;
+ _orientation.getFront() * _scale;
}
@ -207,19 +212,19 @@ void Head::render(bool lookingInMirror, glm::vec3 cameraPosition) {
glEnable(GL_DEPTH_TEST);
glEnable(GL_RESCALE_NORMAL);
renderMohawk(lookingInMirror);
renderMohawk(lookingInMirror, cameraPosition);
renderHeadSphere();
renderEyeBalls();
renderEars();
renderMouth();
renderEyeBrows();
renderHair(cameraPosition);
if (_renderLookatVectors && _lookingAtSomething) {
renderLookatVectors(_leftEyePosition, _rightEyePosition, _lookAtPosition);
}
}
void Head::createMohawk() {
uint16_t agentId = 0;
if (_owningAvatar->getOwningAgent()) {
@ -251,9 +256,41 @@ void Head::createMohawk() {
}
}
void Head::renderMohawk(bool lookingInMirror) {
void Head::renderMohawk(bool lookingInMirror, glm::vec3 cameraPosition) {
if (!_mohawkTriangleFan) {
createMohawk();
}
if (USING_PHYSICAL_MOHAWK) {
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;
glColor3f(_mohawkColors[t].x, _mohawkColors[t].y, _mohawkColors[t].z);
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();
}
} else {
glPushMatrix();
glTranslatef(_position.x, _position.y, _position.z);
@ -269,7 +306,7 @@ void Head::renderMohawk(bool lookingInMirror) {
}
glEnd();
glPopMatrix();
}
}
}
@ -305,6 +342,7 @@ void Head::renderMouth() {
glm::vec3 u = _orientation.getUp () * _scale * (0.05f + s * 0.0040f );
glm::vec3 f = _orientation.getFront() * _scale * 0.09f;
glm::vec3 middle = _mouthPosition;
glm::vec3 leftCorner = _mouthPosition - r * 1.0f;
glm::vec3 rightCorner = _mouthPosition + r * 1.0f;
glm::vec3 leftTop = _mouthPosition - r * 0.4f + u * 0.7f + f;
@ -314,6 +352,7 @@ void Head::renderMouth() {
// constrain all mouth vertices to a sphere slightly larger than the head...
float constrainedRadius = _scale + 0.001f;
middle = _position + glm::normalize(middle - _position) * constrainedRadius;
leftCorner = _position + glm::normalize(leftCorner - _position) * constrainedRadius;
rightCorner = _position + glm::normalize(rightCorner - _position) * constrainedRadius;
leftTop = _position + glm::normalize(leftTop - _position) * constrainedRadius;
@ -328,10 +367,16 @@ void Head::renderMouth() {
glVertex3f(leftBottom.x, leftBottom.y, leftBottom.z );
glVertex3f(leftTop.x, leftTop.y, leftTop.z );
glVertex3f(leftTop.x, leftTop.y, leftTop.z );
glVertex3f(middle.x, middle.y, middle.z );
glVertex3f(rightTop.x, rightTop.y, rightTop.z );
glVertex3f(leftTop.x, leftTop.y, leftTop.z );
glVertex3f(middle.x, middle.y, middle.z );
glVertex3f(leftBottom.x, leftBottom.y, leftBottom.z );
glVertex3f(leftBottom.x, leftBottom.y, leftBottom.z );
glVertex3f(middle.x, middle.y, middle.z );
glVertex3f(rightBottom.x, rightBottom.y, rightBottom.z);
glVertex3f(rightTop.x, rightTop.y, rightTop.z );
glVertex3f(leftBottom.x, leftBottom.y, leftBottom.z );
glVertex3f(middle.x, middle.y, middle.z );
glVertex3f(rightBottom.x, rightBottom.y, rightBottom.z);
glVertex3f(rightTop.x, rightTop.y, rightTop.z );
glVertex3f(rightBottom.x, rightBottom.y, rightBottom.z);
@ -526,7 +571,7 @@ void Head::renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosi
}
void Head::updateHair(float deltaTime) {
void Head::updateHairPhysics(float deltaTime) {
for (int t = 0; t < NUM_HAIR_TUFTS; t ++) {
@ -618,41 +663,3 @@ void Head::updateHair(float deltaTime) {
}
}
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();
}
}

View file

@ -25,7 +25,6 @@ enum eyeContactTargets
};
const int NUM_HAIR_TUFTS = 4;
const int NUM_HAIR_SEGMENTS = 4;
class Avatar;
@ -36,7 +35,7 @@ public:
void reset();
void simulate(float deltaTime, bool isMine);
void render(bool lookingInMirror, glm::vec3 cameraPosition);
void renderMohawk(bool lookingInMirror);
void renderMohawk(bool lookingInMirror, glm::vec3 cameraPosition);
void setScale (float scale ) { _scale = scale; }
void setPosition (glm::vec3 position ) { _position = position; }
@ -45,7 +44,6 @@ public:
void setSkinColor (glm::vec3 skinColor ) { _skinColor = skinColor; }
void setSpringScale (float returnSpringScale ) { _returnSpringScale = returnSpringScale; }
void setAverageLoudness(float averageLoudness ) { _averageLoudness = averageLoudness; }
void setAudioLoudness (float audioLoudness ) { _audioLoudness = audioLoudness; }
void setReturnToCenter (bool returnHeadToCenter) { _returnHeadToCenter = returnHeadToCenter; }
void setRenderLookatVectors(bool onOff ) { _renderLookatVectors = onOff; }
@ -74,7 +72,6 @@ private:
};
bool _returnHeadToCenter;
float _audioLoudness;
glm::vec3 _skinColor;
glm::vec3 _position;
glm::vec3 _rotation;
@ -110,8 +107,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);
void resetHairPhysics();
void updateHairPhysics(float deltaTime);
};
#endif

View file

@ -38,9 +38,11 @@ void OculusManager::connect() {
}
void OculusManager::updateYawOffset() {
#ifdef __APPLE__
float yaw, pitch, roll;
_sensorFusion.GetOrientation().GetEulerAngles<Axis_Y, Axis_X, Axis_Z, Rotate_CCW, Handed_R>(&yaw, &pitch, &roll);
_yawOffset = yaw;
#endif
}
void OculusManager::getEulerAngles(float& yaw, float& pitch, float& roll) {

View file

@ -0,0 +1,20 @@
//
// Skeleton.cpp
// interface
//
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
#include "Skeleton.h"
Skeleton::Skeleton() {
}
void Skeleton::initialize() {
}
void Skeleton::render() {
}
void Skeleton::simulate(float deltaTime) {
}

54
interface/src/Skeleton.h Normal file
View file

@ -0,0 +1,54 @@
//
// Skeleton.h
// interface
//
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#ifndef hifi_Skeleton_h
#define hifi_Skeleton_h
enum AvatarJointID
{
AVATAR_JOINT_NULL = -1,
AVATAR_JOINT_PELVIS,
AVATAR_JOINT_TORSO,
AVATAR_JOINT_CHEST,
AVATAR_JOINT_NECK_BASE,
AVATAR_JOINT_HEAD_BASE,
AVATAR_JOINT_HEAD_TOP,
AVATAR_JOINT_LEFT_COLLAR,
AVATAR_JOINT_LEFT_SHOULDER,
AVATAR_JOINT_LEFT_ELBOW,
AVATAR_JOINT_LEFT_WRIST,
AVATAR_JOINT_LEFT_FINGERTIPS,
AVATAR_JOINT_RIGHT_COLLAR,
AVATAR_JOINT_RIGHT_SHOULDER,
AVATAR_JOINT_RIGHT_ELBOW,
AVATAR_JOINT_RIGHT_WRIST,
AVATAR_JOINT_RIGHT_FINGERTIPS,
AVATAR_JOINT_LEFT_HIP,
AVATAR_JOINT_LEFT_KNEE,
AVATAR_JOINT_LEFT_HEEL,
AVATAR_JOINT_LEFT_TOES,
AVATAR_JOINT_RIGHT_HIP,
AVATAR_JOINT_RIGHT_KNEE,
AVATAR_JOINT_RIGHT_HEEL,
AVATAR_JOINT_RIGHT_TOES,
NUM_AVATAR_JOINTS
};
class Skeleton {
public:
Skeleton();
void initialize();
void simulate(float deltaTime);
void render();
private:
};
#endif

View file

@ -17,4 +17,6 @@ const float WORLD_SIZE = 10.0;
#define PIf 3.14159265f
#define GRAVITY_EARTH 9.80665f;
const float EDGE_SIZE_GROUND_PLANE = 20.f;
#endif

View file

@ -37,7 +37,6 @@ AvatarData::AvatarData(Agent* owningAgent) :
_bodyYaw(-90.0),
_bodyPitch(0.0),
_bodyRoll(0.0),
_audioLoudness(0),
_handState(0),
_cameraPosition(0,0,0),
_cameraDirection(0,0,0),
@ -53,6 +52,7 @@ AvatarData::AvatarData(Agent* owningAgent) :
_wantDelta(false),
_headData(NULL)
{
}
AvatarData::~AvatarData() {
@ -104,7 +104,7 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) {
destinationBuffer += sizeof(char);
// Instantaneous audio loudness (used to drive facial animation)
memcpy(destinationBuffer, &_audioLoudness, sizeof(float));
memcpy(destinationBuffer, &_headData->_audioLoudness, sizeof(float));
destinationBuffer += sizeof(float);
// camera details
@ -198,7 +198,7 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
sourceBuffer += sizeof(char);
// Instantaneous audio loudness (used to drive facial animation)
memcpy(&_audioLoudness, sourceBuffer, sizeof(float));
memcpy(&_headData->_audioLoudness, sourceBuffer, sizeof(float));
sourceBuffer += sizeof(float);
// camera details

View file

@ -51,11 +51,7 @@ public:
// Hand State
void setHandState(char s) { _handState = s; };
char getHandState() const {return _handState; };
// Instantaneous audio loudness to drive mouth/facial animation
void setLoudness(float l) { _audioLoudness = l; };
float getLoudness() const {return _audioLoudness; };
// getters for camera details
const glm::vec3& getCameraPosition() const { return _cameraPosition; };
const glm::vec3& getCameraDirection() const { return _cameraDirection; }
@ -103,9 +99,6 @@ protected:
float _bodyPitch;
float _bodyRoll;
// Audio loudness (used to drive facial animation)
float _audioLoudness;
// Hand state (are we grabbing something or not)
char _handState;

View file

@ -15,6 +15,7 @@ HeadData::HeadData(AvatarData* owningAvatar) :
_lookAtPosition(0.0f, 0.0f, 0.0f),
_leanSideways(0.0f),
_leanForward(0.0f),
_audioLoudness(0.0f),
_owningAvatar(owningAvatar)
{

View file

@ -41,6 +41,8 @@ public:
float getRoll() const { return _roll; }
void setRoll(float roll) { _roll = glm::clamp(roll, MIN_HEAD_ROLL, MAX_HEAD_ROLL); }
void setAudioLoudness(float audioLoudness) { _audioLoudness = audioLoudness; }
void addYaw(float yaw);
void addPitch(float pitch);
void addRoll(float roll);
@ -57,6 +59,7 @@ protected:
glm::vec3 _lookAtPosition;
float _leanSideways;
float _leanForward;
float _audioLoudness;
AvatarData* _owningAvatar;
private:
// privatize copy ctor and assignment operator so copies of this object cannot be made

View file

@ -11,6 +11,7 @@
#include "SharedUtil.h"
#include "AABox.h"
#include "GeometryUtil.h"
void AABox::scale(float scale) {
@ -82,6 +83,17 @@ bool AABox::contains(const glm::vec3& point) const {
isWithin(point.z, _corner.z, _size.z);
}
// determines whether a value is within the expanded extents
static bool isWithinExpanded(float value, float corner, float size, float expansion) {
return value >= corner - expansion && value <= corner + size + expansion;
}
bool AABox::expandedContains(const glm::vec3& point, float expansion) const {
return isWithinExpanded(point.x, _corner.x, _size.x, expansion) &&
isWithinExpanded(point.y, _corner.y, _size.y, expansion) &&
isWithinExpanded(point.z, _corner.z, _size.z, expansion);
}
// finds the intersection between a ray and the facing plane on one axis
static bool findIntersection(float origin, float direction, float corner, float size, float& distance) {
if (direction > EPSILON) {
@ -95,6 +107,30 @@ static bool findIntersection(float origin, float direction, float corner, float
return false;
}
bool AABox::expandedIntersectsSegment(const glm::vec3& start, const glm::vec3& end, float expansion) const {
// handle the trivial cases where the expanded box contains the start or end
if (expandedContains(start, expansion) || expandedContains(end, expansion)) {
return true;
}
// check each axis
glm::vec3 expandedCorner = _corner - glm::vec3(expansion, expansion, expansion);
glm::vec3 expandedSize = _size + glm::vec3(expansion, expansion, expansion) * 2.0f;
glm::vec3 direction = end - start;
float axisDistance;
return (findIntersection(start.x, direction.x, expandedCorner.x, expandedSize.x, axisDistance) &&
axisDistance >= 0.0f && axisDistance <= 1.0f &&
isWithin(start.y + axisDistance*direction.y, expandedCorner.y, expandedSize.y) &&
isWithin(start.z + axisDistance*direction.z, expandedCorner.z, expandedSize.z)) ||
(findIntersection(start.y, direction.y, expandedCorner.y, expandedSize.y, axisDistance) &&
axisDistance >= 0.0f && axisDistance <= 1.0f &&
isWithin(start.x + axisDistance*direction.x, expandedCorner.x, expandedSize.x) &&
isWithin(start.z + axisDistance*direction.z, expandedCorner.z, expandedSize.z)) ||
(findIntersection(start.z, direction.z, expandedCorner.z, expandedSize.z, axisDistance) &&
axisDistance >= 0.0f && axisDistance <= 1.0f &&
isWithin(start.y + axisDistance*direction.y, expandedCorner.y, expandedSize.y) &&
isWithin(start.x + axisDistance*direction.x, expandedCorner.x, expandedSize.x));
}
bool AABox::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const {
// handle the trivial case where the box contains the origin
if (contains(origin)) {
@ -126,3 +162,168 @@ bool AABox::findRayIntersection(const glm::vec3& origin, const glm::vec3& direct
}
return false;
}
bool AABox::findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) const {
glm::vec4 center4 = glm::vec4(center, 1.0f);
float minPenetrationLength = FLT_MAX;
for (int i = 0; i < FACE_COUNT; i++) {
glm::vec4 facePlane = getPlane((BoxFace)i);
glm::vec3 vector = getClosestPointOnFace(center, (BoxFace)i) - center;
if (glm::dot(center4, getPlane((BoxFace)i)) >= 0.0f) {
// outside this face, so use vector to closest point to determine penetration
return ::findSpherePenetration(vector, glm::vec3(-facePlane), radius, penetration);
}
float vectorLength = glm::length(vector);
if (vectorLength < minPenetrationLength) {
// remember the smallest penetration vector; if we're inside all faces, we'll use that
penetration = (vectorLength < EPSILON) ? glm::vec3(-facePlane) * radius :
vector * ((vectorLength + radius) / -vectorLength);
minPenetrationLength = vectorLength;
}
}
return true;
}
bool AABox::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration) const {
glm::vec4 start4 = glm::vec4(start, 1.0f);
glm::vec4 end4 = glm::vec4(end, 1.0f);
glm::vec4 startToEnd = glm::vec4(end - start, 0.0f);
float minPenetrationLength = FLT_MAX;
for (int i = 0; i < FACE_COUNT; i++) {
// find the vector from the segment to the closest point on the face (starting from deeper end)
glm::vec4 facePlane = getPlane((BoxFace)i);
glm::vec3 closest = (glm::dot(start4, facePlane) <= glm::dot(end4, facePlane)) ?
getClosestPointOnFace(start4, startToEnd, (BoxFace)i) : getClosestPointOnFace(end4, -startToEnd, (BoxFace)i);
glm::vec3 vector = -computeVectorFromPointToSegment(closest, start, end);
if (glm::dot(vector, glm::vec3(facePlane)) < 0.0f) {
// outside this face, so use vector to closest point to determine penetration
return ::findSpherePenetration(vector, glm::vec3(-facePlane), radius, penetration);
}
float vectorLength = glm::length(vector);
if (vectorLength < minPenetrationLength) {
// remember the smallest penetration vector; if we're inside all faces, we'll use that
penetration = (vectorLength < EPSILON) ? glm::vec3(-facePlane) * radius :
vector * ((vectorLength + radius) / -vectorLength);
minPenetrationLength = vectorLength;
}
}
return true;
}
glm::vec3 AABox::getClosestPointOnFace(const glm::vec3& point, BoxFace face) const {
switch (face) {
case MIN_X_FACE:
return glm::clamp(point, glm::vec3(_corner.x, _corner.y, _corner.z),
glm::vec3(_corner.x, _corner.y + _size.y, _corner.z + _size.z));
case MAX_X_FACE:
return glm::clamp(point, glm::vec3(_corner.x + _size.x, _corner.y, _corner.z),
glm::vec3(_corner.x + _size.x, _corner.y + _size.y, _corner.z + _size.z));
case MIN_Y_FACE:
return glm::clamp(point, glm::vec3(_corner.x, _corner.y, _corner.z),
glm::vec3(_corner.x + _size.x, _corner.y, _corner.z + _size.z));
case MAX_Y_FACE:
return glm::clamp(point, glm::vec3(_corner.x, _corner.y + _size.y, _corner.z),
glm::vec3(_corner.x + _size.x, _corner.y + _size.y, _corner.z + _size.z));
case MIN_Z_FACE:
return glm::clamp(point, glm::vec3(_corner.x, _corner.y, _corner.z),
glm::vec3(_corner.x + _size.x, _corner.y + _size.y, _corner.z));
case MAX_Z_FACE:
return glm::clamp(point, glm::vec3(_corner.x, _corner.y, _corner.z + _size.z),
glm::vec3(_corner.x + _size.x, _corner.y + _size.y, _corner.z + _size.z));
}
}
glm::vec3 AABox::getClosestPointOnFace(const glm::vec4& origin, const glm::vec4& direction, BoxFace face) const {
// check against the four planes that border the face
BoxFace oppositeFace = getOppositeFace(face);
bool anyOutside = false;
for (int i = 0; i < FACE_COUNT; i++) {
if (i == face || i == oppositeFace) {
continue;
}
glm::vec4 iPlane = getPlane((BoxFace)i);
float originDistance = glm::dot(origin, iPlane);
if (originDistance < 0.0f) {
continue; // inside the border
}
anyOutside = true;
float divisor = glm::dot(direction, iPlane);
if (fabs(divisor) < EPSILON) {
continue; // segment is parallel to plane
}
// find intersection and see if it lies within face bounds
float directionalDistance = -originDistance / divisor;
glm::vec4 intersection = origin + direction * directionalDistance;
BoxFace iOppositeFace = getOppositeFace((BoxFace)i);
for (int j = 0; j < FACE_COUNT; j++) {
if (j == face || j == oppositeFace || j == i || j == iOppositeFace) {
continue;
}
if (glm::dot(intersection, getPlane((BoxFace)j)) > 0.0f) {
goto outerContinue; // intersection is out of bounds
}
}
return getClosestPointOnFace(glm::vec3(intersection), face);
outerContinue: ;
}
// if we were outside any of the sides, we must check against the diagonals
if (anyOutside) {
int faceAxis = face / 2;
int secondAxis = (faceAxis + 1) % 3;
int thirdAxis = (faceAxis + 2) % 3;
glm::vec4 secondAxisMinPlane = getPlane((BoxFace)(secondAxis * 2));
glm::vec4 secondAxisMaxPlane = getPlane((BoxFace)(secondAxis * 2 + 1));
glm::vec4 thirdAxisMaxPlane = getPlane((BoxFace)(thirdAxis * 2 + 1));
glm::vec4 offset = glm::vec4(0.0f, 0.0f, 0.0f,
glm::dot(glm::vec3(secondAxisMaxPlane + thirdAxisMaxPlane), _size) * 0.5f);
glm::vec4 diagonals[] = { secondAxisMinPlane + thirdAxisMaxPlane + offset,
secondAxisMaxPlane + thirdAxisMaxPlane + offset };
for (int i = 0; i < sizeof(diagonals) / sizeof(diagonals[0]); i++) {
float divisor = glm::dot(direction, diagonals[i]);
if (fabs(divisor) < EPSILON) {
continue; // segment is parallel to diagonal plane
}
float directionalDistance = -glm::dot(origin, diagonals[i]) / divisor;
return getClosestPointOnFace(glm::vec3(origin + direction * directionalDistance), face);
}
}
// last resort or all inside: clamp origin to face
return getClosestPointOnFace(glm::vec3(origin), face);
}
glm::vec4 AABox::getPlane(BoxFace face) const {
switch (face) {
case MIN_X_FACE: return glm::vec4(-1.0f, 0.0f, 0.0f, _corner.x);
case MAX_X_FACE: return glm::vec4(1.0f, 0.0f, 0.0f, -_corner.x - _size.x);
case MIN_Y_FACE: return glm::vec4(0.0f, -1.0f, 0.0f, _corner.y);
case MAX_Y_FACE: return glm::vec4(0.0f, 1.0f, 0.0f, -_corner.y - _size.y);
case MIN_Z_FACE: return glm::vec4(0.0f, 0.0f, -1.0f, _corner.z);
case MAX_Z_FACE: return glm::vec4(0.0f, 0.0f, 1.0f, -_corner.z - _size.z);
}
}
BoxFace AABox::getOppositeFace(BoxFace face) {
switch (face) {
case MIN_X_FACE: return MAX_X_FACE;
case MAX_X_FACE: return MIN_X_FACE;
case MIN_Y_FACE: return MAX_Y_FACE;
case MAX_Y_FACE: return MIN_Y_FACE;
case MIN_Z_FACE: return MAX_Z_FACE;
case MAX_Z_FACE: return MIN_Z_FACE;
}
}

13
libraries/voxels/src/AABox.h Executable file → Normal file
View file

@ -22,6 +22,8 @@ enum BoxFace {
MAX_Z_FACE
};
const int FACE_COUNT = 6;
class AABox
{
@ -46,9 +48,20 @@ public:
const glm::vec3& getCenter() const { return _center; };
bool contains(const glm::vec3& point) const;
bool expandedContains(const glm::vec3& point, float expansion) const;
bool expandedIntersectsSegment(const glm::vec3& start, const glm::vec3& end, float expansion) const;
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const;
bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) const;
bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration) const;
private:
glm::vec3 getClosestPointOnFace(const glm::vec3& point, BoxFace face) const;
glm::vec3 getClosestPointOnFace(const glm::vec4& origin, const glm::vec4& direction, BoxFace face) const;
glm::vec4 getPlane(BoxFace face) const;
static BoxFace getOppositeFace(BoxFace face);
glm::vec3 _corner;
glm::vec3 _center;
glm::vec3 _size;

View file

@ -5,12 +5,18 @@
// Created by Andrzej Kapolka on 5/21/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
#include <SharedUtil.h>
#include "GeometryUtil.h"
glm::vec3 computeVectorFromPointToSegment(const glm::vec3& point, const glm::vec3& start, const glm::vec3& end) {
// compute the projection of the point vector onto the segment vector
glm::vec3 segmentVector = end - start;
float proj = glm::dot(point - start, segmentVector) / glm::dot(segmentVector, segmentVector);
float lengthSquared = glm::dot(segmentVector, segmentVector);
if (lengthSquared < EPSILON) {
return start - point; // start and end the same
}
float proj = glm::dot(point - start, segmentVector) / lengthSquared;
if (proj <= 0.0f) { // closest to the start
return start - point;
@ -21,3 +27,91 @@ glm::vec3 computeVectorFromPointToSegment(const glm::vec3& point, const glm::vec
return start + segmentVector*proj - point;
}
}
bool findSpherePenetration(const glm::vec3& penetratorToPenetratee, const glm::vec3& direction,
float combinedRadius, glm::vec3& penetration) {
float vectorLength = glm::length(penetratorToPenetratee);
if (vectorLength < EPSILON) {
penetration = direction * combinedRadius;
return true;
}
float distance = vectorLength - combinedRadius;
if (distance < 0.0f) {
penetration = penetratorToPenetratee * (-distance / vectorLength);
return true;
}
return false;
}
bool findSpherePointPenetration(const glm::vec3& penetratorCenter, float penetratorRadius,
const glm::vec3& penetrateeLocation, glm::vec3& penetration) {
return findSpherePenetration(penetrateeLocation - penetratorCenter, glm::vec3(0.0f, -1.0f, 0.0f),
penetratorRadius, penetration);
}
bool findSphereSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius,
const glm::vec3& penetrateeCenter, float penetrateeRadius, glm::vec3& penetration) {
return findSpherePointPenetration(penetratorCenter, penetratorRadius + penetrateeRadius, penetrateeCenter, penetration);
}
bool findSphereSegmentPenetration(const glm::vec3& penetratorCenter, float penetratorRadius,
const glm::vec3& penetrateeStart, const glm::vec3& penetrateeEnd, glm::vec3& penetration) {
return findSpherePenetration(computeVectorFromPointToSegment(penetratorCenter, penetrateeStart, penetrateeEnd),
glm::vec3(0.0f, -1.0f, 0.0f), penetratorRadius, penetration);
}
bool findSphereCapsulePenetration(const glm::vec3& penetratorCenter, float penetratorRadius, const glm::vec3& penetrateeStart,
const glm::vec3& penetrateeEnd, float penetrateeRadius, glm::vec3& penetration) {
return findSphereSegmentPenetration(penetratorCenter, penetratorRadius + penetrateeRadius,
penetrateeStart, penetrateeEnd, penetration);
}
bool findSpherePlanePenetration(const glm::vec3& penetratorCenter, float penetratorRadius,
const glm::vec4& penetrateePlane, glm::vec3& penetration) {
float distance = glm::dot(penetrateePlane, glm::vec4(penetratorCenter, 1.0f)) - penetratorRadius;
if (distance < 0.0f) {
penetration = glm::vec3(penetrateePlane) * distance;
return true;
}
return false;
}
bool findCapsuleSpherePenetration(const glm::vec3& penetratorStart, const glm::vec3& penetratorEnd, float penetratorRadius,
const glm::vec3& penetrateeCenter, float penetrateeRadius, glm::vec3& penetration) {
if (findSphereCapsulePenetration(penetrateeCenter, penetrateeRadius,
penetratorStart, penetratorEnd, penetratorRadius, penetration)) {
penetration = -penetration;
return true;
}
return false;
}
bool findCapsulePlanePenetration(const glm::vec3& penetratorStart, const glm::vec3& penetratorEnd, float penetratorRadius,
const glm::vec4& penetrateePlane, glm::vec3& penetration) {
float distance = glm::min(glm::dot(penetrateePlane, glm::vec4(penetratorStart, 1.0f)),
glm::dot(penetrateePlane, glm::vec4(penetratorEnd, 1.0f))) - penetratorRadius;
if (distance < 0.0f) {
penetration = glm::vec3(penetrateePlane) * distance;
return true;
}
return false;
}
glm::vec3 addPenetrations(const glm::vec3& currentPenetration, const glm::vec3& newPenetration) {
// find the component of the new penetration in the direction of the current
float currentLength = glm::length(currentPenetration);
if (currentLength == 0.0f) {
return newPenetration;
}
glm::vec3 currentDirection = currentPenetration / currentLength;
float directionalComponent = glm::dot(newPenetration, currentDirection);
// if orthogonal or in the opposite direction, we can simply add
if (directionalComponent <= 0.0f) {
return currentPenetration + newPenetration;
}
// otherwise, we need to take the maximum component of current and new
return currentDirection * glm::max(directionalComponent, currentLength) +
newPenetration - (currentDirection * directionalComponent);
}

View file

@ -13,4 +13,30 @@
glm::vec3 computeVectorFromPointToSegment(const glm::vec3& point, const glm::vec3& start, const glm::vec3& end);
bool findSpherePenetration(const glm::vec3& penetratorToPenetratee, const glm::vec3& direction,
float combinedRadius, glm::vec3& penetration);
bool findSpherePointPenetration(const glm::vec3& penetratorCenter, float penetratorRadius,
const glm::vec3& penetrateeLocation, glm::vec3& penetration);
bool findSphereSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius,
const glm::vec3& penetrateeCenter, float penetrateeRadius, glm::vec3& penetration);
bool findSphereSegmentPenetration(const glm::vec3& penetratorCenter, float penetratorRadius,
const glm::vec3& penetrateeStart, const glm::vec3& penetrateeEnd, glm::vec3& penetration);
bool findSphereCapsulePenetration(const glm::vec3& penetratorCenter, float penetratorRadius, const glm::vec3& penetrateeStart,
const glm::vec3& penetrateeEnd, float penetrateeRadius, glm::vec3& penetration);
bool findSpherePlanePenetration(const glm::vec3& penetratorCenter, float penetratorRadius,
const glm::vec4& penetrateePlane, glm::vec3& penetration);
bool findCapsuleSpherePenetration(const glm::vec3& penetratorStart, const glm::vec3& penetratorEnd, float penetratorRadius,
const glm::vec3& penetrateeCenter, float penetrateeRadius, glm::vec3& penetration);
bool findCapsulePlanePenetration(const glm::vec3& penetratorStart, const glm::vec3& penetratorEnd, float penetratorRadius,
const glm::vec4& penetrateePlane, glm::vec3& penetration);
glm::vec3 addPenetrations(const glm::vec3& currentPenetration, const glm::vec3& newPenetration);
#endif /* defined(__interface__GeometryUtil__) */

View file

@ -716,20 +716,20 @@ public:
bool findSpherePenetrationOp(VoxelNode* node, void* extraData) {
SphereArgs* args = static_cast<SphereArgs*>(extraData);
// currently, we treat each node as a sphere enveloping the box
const glm::vec3& nodeCenter = node->getCenter();
glm::vec3 vector = args->center - nodeCenter;
float vectorLength = glm::length(vector);
float distance = vectorLength - node->getEnclosingRadius() - args->radius;
if (distance >= 0.0f) {
// coarse check against bounds
const AABox& box = node->getAABox();
if (!box.expandedContains(args->center, args->radius)) {
return false;
}
if (!node->isLeaf()) {
return true; // recurse on children
}
if (node->isColored()) {
args->penetration += vector * (-distance * TREE_SCALE / vectorLength);
args->found = true;
glm::vec3 nodePenetration;
if (box.findSpherePenetration(args->center, args->radius, nodePenetration)) {
args->penetration = addPenetrations(args->penetration, nodePenetration * (float)TREE_SCALE);
args->found = true;
}
}
return false;
}
@ -753,20 +753,20 @@ public:
bool findCapsulePenetrationOp(VoxelNode* node, void* extraData) {
CapsuleArgs* args = static_cast<CapsuleArgs*>(extraData);
// currently, we treat each node as a sphere enveloping the box
const glm::vec3& nodeCenter = node->getCenter();
glm::vec3 vector = computeVectorFromPointToSegment(nodeCenter, args->start, args->end);
float vectorLength = glm::length(vector);
float distance = vectorLength - node->getEnclosingRadius() - args->radius;
if (distance >= 0.0f) {
// coarse check against bounds
const AABox& box = node->getAABox();
if (!box.expandedIntersectsSegment(args->start, args->end, args->radius)) {
return false;
}
if (!node->isLeaf()) {
return true; // recurse on children
}
if (node->isColored()) {
args->penetration += vector * (-distance * TREE_SCALE / vectorLength);
args->found = true;
glm::vec3 nodePenetration;
if (box.findCapsulePenetration(args->start, args->end, args->radius, nodePenetration)) {
args->penetration = addPenetrations(args->penetration, nodePenetration * (float)TREE_SCALE);
args->found = true;
}
}
return false;
}