mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 18:50:00 +02:00
Merge remote-tracking branch 'upstream/master' into one-liner
This commit is contained in:
commit
c31c14c56e
22 changed files with 610 additions and 261 deletions
|
@ -901,7 +901,7 @@ void Application::idle() {
|
||||||
for(AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
|
for(AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
|
||||||
if (agent->getLinkedData() != NULL) {
|
if (agent->getLinkedData() != NULL) {
|
||||||
Avatar *avatar = (Avatar *)agent->getLinkedData();
|
Avatar *avatar = (Avatar *)agent->getLinkedData();
|
||||||
avatar->simulate(deltaTime, false);
|
avatar->simulate(deltaTime, NULL);
|
||||||
avatar->setMouseRay(mouseRayOrigin, mouseRayDirection);
|
avatar->setMouseRay(mouseRayOrigin, mouseRayDirection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -915,7 +915,7 @@ void Application::idle() {
|
||||||
_myAvatar.simulate(deltaTime, NULL);
|
_myAvatar.simulate(deltaTime, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_myCamera.getMode() != CAMERA_MODE_MIRROR) {
|
if (_myCamera.getMode() != CAMERA_MODE_MIRROR && !OculusManager::isConnected()) {
|
||||||
if (_manualFirstPerson) {
|
if (_manualFirstPerson) {
|
||||||
if (_myCamera.getMode() != CAMERA_MODE_FIRST_PERSON ) {
|
if (_myCamera.getMode() != CAMERA_MODE_FIRST_PERSON ) {
|
||||||
_myCamera.setMode(CAMERA_MODE_FIRST_PERSON);
|
_myCamera.setMode(CAMERA_MODE_FIRST_PERSON);
|
||||||
|
@ -937,7 +937,7 @@ void Application::idle() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update audio stats for procedural sounds
|
// Update audio stats for procedural sounds
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
_audio.setLastAcceleration(_myAvatar.getThrust());
|
_audio.setLastAcceleration(_myAvatar.getThrust());
|
||||||
|
@ -1317,7 +1317,7 @@ void Application::updateAvatar(float deltaTime) {
|
||||||
|
|
||||||
// Get audio loudness data from audio input device
|
// Get audio loudness data from audio input device
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
_myAvatar.setLoudness(_audio.getLastInputLoudness());
|
_myAvatar.getHead().setAudioLoudness(_audio.getLastInputLoudness());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Update Avatar with latest camera and view frustum data...
|
// Update Avatar with latest camera and view frustum data...
|
||||||
|
@ -1650,7 +1650,6 @@ void Application::displaySide(Camera& whichCamera) {
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
|
||||||
//draw a grid ground plane....
|
//draw a grid ground plane....
|
||||||
const float EDGE_SIZE_GROUND_PLANE = 20.f;
|
|
||||||
drawGroundPlaneGrid(EDGE_SIZE_GROUND_PLANE);
|
drawGroundPlaneGrid(EDGE_SIZE_GROUND_PLANE);
|
||||||
|
|
||||||
// Draw voxels
|
// Draw voxels
|
||||||
|
|
|
@ -116,7 +116,7 @@ int audioCallback (const void* inputBuffer,
|
||||||
printLog("got output\n");
|
printLog("got output\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inputLeft != NULL) {
|
if (inputLeft) {
|
||||||
|
|
||||||
// Measure the loudness of the signal from the microphone and store in audio object
|
// Measure the loudness of the signal from the microphone and store in audio object
|
||||||
float loudness = 0;
|
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
|
// 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.
|
// 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) {
|
if (!::samplesLeftForFlange && lastYawMeasured > MIN_FLANGE_EFFECT_THRESHOLD) {
|
||||||
// we should flange for one second
|
// we should flange for one second
|
||||||
|
@ -457,7 +457,7 @@ void Audio::addReceivedAudioToBuffer(unsigned char* receivedData, int receivedBy
|
||||||
gettimeofday(&_firstPlaybackTime, NULL);
|
gettimeofday(&_firstPlaybackTime, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
_ringBuffer.parseData((unsigned char *)receivedData, PACKET_LENGTH_BYTES);
|
_ringBuffer.parseData((unsigned char*) receivedData, PACKET_LENGTH_BYTES + sizeof(PACKET_HEADER));
|
||||||
|
|
||||||
_lastReceiveTime = currentReceiveTime;
|
_lastReceiveTime = currentReceiveTime;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ const float BODY_UPRIGHT_FORCE = 10.0;
|
||||||
const float VELOCITY_DECAY = 5.0;
|
const float VELOCITY_DECAY = 5.0;
|
||||||
const float MY_HAND_HOLDING_PULL = 0.2;
|
const float MY_HAND_HOLDING_PULL = 0.2;
|
||||||
const float YOUR_HAND_HOLDING_PULL = 1.0;
|
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_FORCE = 300.0f;
|
||||||
const float BODY_SPRING_DECAY = 16.0f;
|
const float BODY_SPRING_DECAY = 16.0f;
|
||||||
const float COLLISION_RADIUS_SCALAR = 1.8;
|
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 ANGULAR_RIGHTING_SPEED = 45.0f;
|
||||||
const float FLOATING_HEIGHT = 0.13f;
|
const float FLOATING_HEIGHT = 0.13f;
|
||||||
const bool USING_HEAD_LEAN = false;
|
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;
|
bool usingBigSphereCollisionTest = true;
|
||||||
|
|
||||||
|
@ -80,8 +79,8 @@ Avatar::Avatar(Agent* owningAgent) :
|
||||||
_bodyRollDelta(0.0f),
|
_bodyRollDelta(0.0f),
|
||||||
_movedHandOffset(0.0f, 0.0f, 0.0f),
|
_movedHandOffset(0.0f, 0.0f, 0.0f),
|
||||||
_rotation(0.0f, 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),
|
_mode(AVATAR_MODE_STANDING),
|
||||||
|
_cameraPosition(0.0f, 0.0f, 0.0f),
|
||||||
_handHoldingPosition(0.0f, 0.0f, 0.0f),
|
_handHoldingPosition(0.0f, 0.0f, 0.0f),
|
||||||
_velocity(0.0f, 0.0f, 0.0f),
|
_velocity(0.0f, 0.0f, 0.0f),
|
||||||
_thrust(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();
|
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) {
|
void Avatar::updateFromMouse(int mouseX, int mouseY, int screenWidth, int screenHeight) {
|
||||||
// Update yaw based on mouse behavior
|
// Update yaw based on mouse behavior
|
||||||
const float MOUSE_MOVE_RADIUS = 0.15f;
|
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.setBodyRotation (glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll));
|
||||||
_head.setPosition(_joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition);
|
_head.setPosition(_joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition);
|
||||||
_head.setScale (_joint[ AVATAR_JOINT_HEAD_BASE ].radius);
|
_head.setScale (_joint[ AVATAR_JOINT_HEAD_BASE ].radius);
|
||||||
_head.setAudioLoudness(_audioLoudness);
|
_head.setSkinColor(glm::vec3(SKIN_COLOR[0], SKIN_COLOR[1], SKIN_COLOR[2]));
|
||||||
_head.setSkinColor(glm::vec3(skinColor[0], skinColor[1], skinColor[2]));
|
|
||||||
_head.simulate(deltaTime, !_owningAgent);
|
_head.simulate(deltaTime, !_owningAgent);
|
||||||
|
|
||||||
// use speed and angular velocity to determine walking vs. standing
|
// 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 ) {
|
void Avatar::setMouseRay(const glm::vec3 &origin, const glm::vec3 &direction ) {
|
||||||
_mouseRayOrigin = origin; _mouseRayDirection = direction;
|
_mouseRayOrigin = origin;
|
||||||
|
_mouseRayDirection = direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::updateHandMovementAndTouching(float deltaTime) {
|
void Avatar::updateHandMovementAndTouching(float deltaTime) {
|
||||||
|
@ -518,6 +509,7 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) {
|
||||||
|
|
||||||
if (_interactingOther) {
|
if (_interactingOther) {
|
||||||
|
|
||||||
|
_avatarTouch.setHasInteractingOther(true);
|
||||||
_avatarTouch.setYourBodyPosition(_interactingOther->_position);
|
_avatarTouch.setYourBodyPosition(_interactingOther->_position);
|
||||||
_avatarTouch.setYourOrientation (_interactingOther->_orientation);
|
_avatarTouch.setYourOrientation (_interactingOther->_orientation);
|
||||||
_avatarTouch.setYourHandPosition(_interactingOther->_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].springyPosition);
|
_avatarTouch.setYourHandPosition(_interactingOther->_joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].springyPosition);
|
||||||
|
@ -570,6 +562,8 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) {
|
||||||
_velocity += vectorFromMyHandToYourHand * force;
|
_velocity += vectorFromMyHandToYourHand * force;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
_avatarTouch.setHasInteractingOther(false);
|
||||||
}
|
}
|
||||||
}//if (_isMine)
|
}//if (_isMine)
|
||||||
|
|
||||||
|
@ -642,11 +636,14 @@ void Avatar::updateCollisionWithVoxels() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::applyCollisionWithScene(const glm::vec3& penetration) {
|
void Avatar::applyCollisionWithScene(const glm::vec3& penetration) {
|
||||||
_position += penetration;
|
_position -= penetration;
|
||||||
|
|
||||||
// reflect the velocity component in the direction of penetration
|
// reflect the velocity component in the direction of penetration
|
||||||
glm::vec3 direction = glm::normalize(penetration);
|
float penetrationLength = glm::length(penetration);
|
||||||
_velocity -= 2.0f * glm::dot(_velocity, direction) * direction * BOUNCE;
|
if (penetrationLength > EPSILON) {
|
||||||
|
glm::vec3 direction = penetration / penetrationLength;
|
||||||
|
_velocity -= 2.0f * glm::dot(_velocity, direction) * direction * BOUNCE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::updateAvatarCollisions(float deltaTime) {
|
void Avatar::updateAvatarCollisions(float deltaTime) {
|
||||||
|
@ -928,31 +925,6 @@ void Avatar::initializeSkeleton() {
|
||||||
_joint[ AVATAR_JOINT_RIGHT_HEEL ].radius = 0.025;
|
_joint[ AVATAR_JOINT_RIGHT_HEEL ].radius = 0.025;
|
||||||
_joint[ AVATAR_JOINT_RIGHT_TOES ].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
|
// 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_ELBOW ].isCollidable = false;
|
||||||
_joint[ AVATAR_JOINT_RIGHT_WRIST ].isCollidable = false;
|
_joint[ AVATAR_JOINT_RIGHT_WRIST ].isCollidable = false;
|
||||||
|
@ -1102,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) {
|
void Avatar::updateArmIKAndConstraints(float deltaTime) {
|
||||||
|
|
||||||
// determine the arm vector
|
// determine the arm vector
|
||||||
|
@ -1151,12 +1114,15 @@ void Avatar::updateArmIKAndConstraints(float deltaTime) {
|
||||||
|
|
||||||
void Avatar::renderBody(bool lookingInMirror) {
|
void Avatar::renderBody(bool lookingInMirror) {
|
||||||
|
|
||||||
const float RENDER_OPAQUE_BEYOND = 1.2f; // Meters beyond which body is shown opaque
|
const float RENDER_OPAQUE_BEYOND = 1.0f; // Meters beyond which body is shown opaque
|
||||||
const float RENDER_TRANSLUCENT_BEYOND = 0.5f;
|
const float RENDER_TRANSLUCENT_BEYOND = 0.5f;
|
||||||
|
|
||||||
// Render the body as balls and cones
|
// Render the body as balls and cones
|
||||||
for (int b = 0; b < NUM_AVATAR_JOINTS; b++) {
|
for (int b = 0; b < NUM_AVATAR_JOINTS; b++) {
|
||||||
float distanceToCamera = glm::length(_cameraPosition - _joint[b].position);
|
float distanceToCamera = glm::length(_cameraPosition - _joint[b].position);
|
||||||
|
|
||||||
|
float alpha = glm::clamp((distanceToCamera - RENDER_TRANSLUCENT_BEYOND) / (RENDER_OPAQUE_BEYOND - RENDER_TRANSLUCENT_BEYOND), 0.f, 1.f);
|
||||||
|
|
||||||
// Always render other people, and render myself when beyond threshold distance
|
// Always render other people, and render myself when beyond threshold distance
|
||||||
if (b == AVATAR_JOINT_HEAD_BASE) { // the head is rendered as a special
|
if (b == AVATAR_JOINT_HEAD_BASE) { // the head is rendered as a special
|
||||||
if (lookingInMirror || _owningAgent || distanceToCamera > RENDER_OPAQUE_BEYOND * 0.5) {
|
if (lookingInMirror || _owningAgent || distanceToCamera > RENDER_OPAQUE_BEYOND * 0.5) {
|
||||||
|
@ -1170,21 +1136,23 @@ void Avatar::renderBody(bool lookingInMirror) {
|
||||||
if (_owningAgent || b == AVATAR_JOINT_RIGHT_ELBOW
|
if (_owningAgent || b == AVATAR_JOINT_RIGHT_ELBOW
|
||||||
|| b == AVATAR_JOINT_RIGHT_WRIST
|
|| b == AVATAR_JOINT_RIGHT_WRIST
|
||||||
|| b == AVATAR_JOINT_RIGHT_FINGERTIPS ) {
|
|| b == AVATAR_JOINT_RIGHT_FINGERTIPS ) {
|
||||||
glColor3f(skinColor[0] + _joint[b].touchForce * 0.3f,
|
glColor3f(SKIN_COLOR[0] + _joint[b].touchForce * 0.3f,
|
||||||
skinColor[1] - _joint[b].touchForce * 0.2f,
|
SKIN_COLOR[1] - _joint[b].touchForce * 0.2f,
|
||||||
skinColor[2] - _joint[b].touchForce * 0.1f);
|
SKIN_COLOR[2] - _joint[b].touchForce * 0.1f);
|
||||||
} else {
|
} else {
|
||||||
glColor4f(skinColor[0] + _joint[b].touchForce * 0.3f,
|
glColor4f(SKIN_COLOR[0] + _joint[b].touchForce * 0.3f,
|
||||||
skinColor[1] - _joint[b].touchForce * 0.2f,
|
SKIN_COLOR[1] - _joint[b].touchForce * 0.2f,
|
||||||
skinColor[2] - _joint[b].touchForce * 0.1f,
|
SKIN_COLOR[2] - _joint[b].touchForce * 0.1f,
|
||||||
glm::clamp((distanceToCamera - RENDER_TRANSLUCENT_BEYOND)
|
alpha);
|
||||||
/ (RENDER_OPAQUE_BEYOND - RENDER_TRANSLUCENT_BEYOND), 0.f, 1.f));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
glPushMatrix();
|
if ((b != AVATAR_JOINT_HEAD_TOP )
|
||||||
glTranslatef(_joint[b].springyPosition.x, _joint[b].springyPosition.y, _joint[b].springyPosition.z);
|
&& (b != AVATAR_JOINT_HEAD_BASE )) {
|
||||||
glutSolidSphere(_joint[b].radius, 20.0f, 20.0f);
|
glPushMatrix();
|
||||||
glPopMatrix();
|
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 its parent
|
// Render the cone connecting this joint to its parent
|
||||||
if (_joint[b].parent != AVATAR_JOINT_NULL) {
|
if (_joint[b].parent != AVATAR_JOINT_NULL) {
|
||||||
|
@ -1197,7 +1165,7 @@ void Avatar::renderBody(bool lookingInMirror) {
|
||||||
&& (b != AVATAR_JOINT_LEFT_SHOULDER )
|
&& (b != AVATAR_JOINT_LEFT_SHOULDER )
|
||||||
&& (b != AVATAR_JOINT_RIGHT_COLLAR )
|
&& (b != AVATAR_JOINT_RIGHT_COLLAR )
|
||||||
&& (b != AVATAR_JOINT_RIGHT_SHOULDER)) {
|
&& (b != AVATAR_JOINT_RIGHT_SHOULDER)) {
|
||||||
glColor3fv(darkSkinColor);
|
glColor3fv(DARK_SKIN_COLOR);
|
||||||
|
|
||||||
float r1 = _joint[_joint[b].parent ].radius * 0.8;
|
float r1 = _joint[_joint[b].parent ].radius * 0.8;
|
||||||
float r2 = _joint[b ].radius * 0.8;
|
float r2 = _joint[b ].radius * 0.8;
|
||||||
|
@ -1282,34 +1250,37 @@ void Avatar::readAvatarDataFromFile() {
|
||||||
void Avatar::renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2) {
|
void Avatar::renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2) {
|
||||||
|
|
||||||
glBegin(GL_TRIANGLES);
|
glBegin(GL_TRIANGLES);
|
||||||
|
|
||||||
int num = 10;
|
glm::vec3 axis = position2 - position1;
|
||||||
|
|
||||||
glm::vec3 axis = glm::normalize(position2 - position1);
|
|
||||||
float length = glm::length(axis);
|
float length = glm::length(axis);
|
||||||
|
|
||||||
if (length > 0.0f) {
|
if (length > 0.0f) {
|
||||||
|
|
||||||
glm::vec3 perpSin = glm::vec3(axis.y, axis.z, axis.x);
|
axis /= length;
|
||||||
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 ++) {
|
|
||||||
|
|
||||||
angle1 = angle2;
|
glm::vec3 perpSin = glm::vec3(1.0f, 0.0f, 0.0f);
|
||||||
angle2 = ((float)(i+1) / (float)num) * PI * 2.0;
|
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 sa = sinf(anglea);
|
||||||
float s2 = sinf(angle2);
|
float sb = sinf(angleb);
|
||||||
float c1 = cosf(angle1);
|
float ca = cosf(anglea);
|
||||||
float c2 = cosf(angle2);
|
float cb = cosf(angleb);
|
||||||
|
|
||||||
glm::vec3 p1a = position1 + perpSin * s1 * radius1 + perpCos * c1 * radius1;
|
glm::vec3 p1a = position1 + perpSin * sa * radius1 + perpCos * ca * radius1;
|
||||||
glm::vec3 p1b = position1 + perpSin * s2 * radius1 + perpCos * c2 * radius1;
|
glm::vec3 p1b = position1 + perpSin * sb * radius1 + perpCos * cb * radius1;
|
||||||
glm::vec3 p2a = position2 + perpSin * s1 * radius2 + perpCos * c1 * radius2;
|
glm::vec3 p2a = position2 + perpSin * sa * radius2 + perpCos * ca * radius2;
|
||||||
glm::vec3 p2b = position2 + perpSin * s2 * radius2 + perpCos * c2 * radius2;
|
glm::vec3 p2b = position2 + perpSin * sb * radius2 + perpCos * cb * radius2;
|
||||||
|
|
||||||
glVertex3f(p1a.x, p1a.y, p1a.z);
|
glVertex3f(p1a.x, p1a.y, p1a.z);
|
||||||
glVertex3f(p1b.x, p1b.y, p1b.z);
|
glVertex3f(p1b.x, p1b.y, p1b.z);
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
// Avatar.h
|
// Avatar.h
|
||||||
// interface
|
// interface
|
||||||
//
|
//
|
||||||
// Created by Philip Rosedale on 9/11/12.
|
|
||||||
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
|
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
@ -19,6 +18,7 @@
|
||||||
#include "SerialInterface.h"
|
#include "SerialInterface.h"
|
||||||
#include "Balls.h"
|
#include "Balls.h"
|
||||||
#include "Head.h"
|
#include "Head.h"
|
||||||
|
#include "Skeleton.h"
|
||||||
#include "Transmitter.h"
|
#include "Transmitter.h"
|
||||||
|
|
||||||
enum DriveKeys
|
enum DriveKeys
|
||||||
|
@ -42,87 +42,52 @@ enum AvatarMode
|
||||||
NUM_AVATAR_MODES
|
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 {
|
class Avatar : public AvatarData {
|
||||||
public:
|
public:
|
||||||
Avatar(Agent* owningAgent = NULL);
|
Avatar(Agent* owningAgent = NULL);
|
||||||
~Avatar();
|
~Avatar();
|
||||||
|
|
||||||
void reset();
|
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 simulate(float deltaTime, Transmitter* transmitter);
|
void simulate(float deltaTime, Transmitter* transmitter);
|
||||||
void setMovedHandOffset(glm::vec3 movedHandOffset) { _movedHandOffset = movedHandOffset; }
|
void updateHeadFromGyros(float frametime, SerialInterface * serialInterface, glm::vec3 * gravity);
|
||||||
void updateArmIKAndConstraints( float deltaTime );
|
void updateFromMouse(int mouseX, int mouseY, int screenWidth, int screenHeight);
|
||||||
void setDisplayingLookatVectors(bool displayingLookatVectors) { _head.setRenderLookatVectors(displayingLookatVectors); }
|
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
|
// Set what driving keys are being pressed to control thrust levels
|
||||||
void setDriveKeys(int key, bool val) { _driveKeys[key] = val; };
|
void setDriveKeys(int key, bool val) { _driveKeys[key] = val; };
|
||||||
bool getDriveKeys(int key) { return _driveKeys[key]; };
|
bool getDriveKeys(int key) { return _driveKeys[key]; };
|
||||||
|
|
||||||
// Set/Get update the thrust that will move the avatar around
|
// 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; };
|
void addThrust(glm::vec3 newThrust) { _thrust += newThrust; };
|
||||||
glm::vec3 getThrust() { return _thrust; };
|
glm::vec3 getThrust() { return _thrust; };
|
||||||
|
|
||||||
|
//read/write avatar data
|
||||||
void writeAvatarDataToFile();
|
void writeAvatarDataToFile();
|
||||||
void readAvatarDataFromFile();
|
void readAvatarDataFromFile();
|
||||||
|
|
||||||
|
@ -151,6 +116,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
Head _head;
|
Head _head;
|
||||||
|
Skeleton _skeleton;
|
||||||
float _TEST_bigSphereRadius;
|
float _TEST_bigSphereRadius;
|
||||||
glm::vec3 _TEST_bigSpherePosition;
|
glm::vec3 _TEST_bigSpherePosition;
|
||||||
bool _mousePressed;
|
bool _mousePressed;
|
||||||
|
@ -184,6 +150,8 @@ private:
|
||||||
bool _isMouseTurningRight;
|
bool _isMouseTurningRight;
|
||||||
|
|
||||||
// private methods...
|
// 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 initializeSkeleton();
|
||||||
void updateSkeleton();
|
void updateSkeleton();
|
||||||
void initializeBodySprings();
|
void initializeBodySprings();
|
||||||
|
@ -192,6 +160,7 @@ private:
|
||||||
void readSensors();
|
void readSensors();
|
||||||
void updateHandMovementAndTouching(float deltaTime);
|
void updateHandMovementAndTouching(float deltaTime);
|
||||||
void updateAvatarCollisions(float deltaTime);
|
void updateAvatarCollisions(float deltaTime);
|
||||||
|
void updateArmIKAndConstraints( float deltaTime );
|
||||||
void updateCollisionWithSphere( glm::vec3 position, float radius, float deltaTime );
|
void updateCollisionWithSphere( glm::vec3 position, float radius, float deltaTime );
|
||||||
void updateCollisionWithEnvironment();
|
void updateCollisionWithEnvironment();
|
||||||
void updateCollisionWithVoxels();
|
void updateCollisionWithVoxels();
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
const float THREAD_RADIUS = 0.007;
|
const float THREAD_RADIUS = 0.007;
|
||||||
const float HANDS_CLOSE_ENOUGH_TO_GRASP = 0.2;
|
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() {
|
AvatarTouch::AvatarTouch() {
|
||||||
|
|
||||||
|
@ -27,44 +28,49 @@ AvatarTouch::AvatarTouch() {
|
||||||
_weAreHoldingHands = false;
|
_weAreHoldingHands = false;
|
||||||
_canReachToOtherAvatar = false;
|
_canReachToOtherAvatar = false;
|
||||||
_handsCloseEnoughToGrasp = false;
|
_handsCloseEnoughToGrasp = false;
|
||||||
|
_hasInteractingOther = false;
|
||||||
_myOrientation.setToIdentity();
|
_myOrientation.setToIdentity();
|
||||||
_yourOrientation.setToIdentity();
|
_yourOrientation.setToIdentity();
|
||||||
|
|
||||||
for (int p=0; p<NUM_POINTS; p++) {
|
for (int p=0; p<NUM_PARTICLE_POINTS; p++) {
|
||||||
_point[p] = glm::vec3(0.0, 0.0, 0.0);
|
_point[p] = glm::vec3(0.0, 0.0, 0.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarTouch::simulate (float deltaTime) {
|
void AvatarTouch::simulate (float deltaTime) {
|
||||||
|
|
||||||
glm::vec3 vectorBetweenBodies = _yourBodyPosition - _myBodyPosition;
|
_canReachToOtherAvatar = false; // default
|
||||||
float distanceBetweenBodies = glm::length(vectorBetweenBodies);
|
|
||||||
glm::vec3 directionBetweenBodies = vectorBetweenBodies / distanceBetweenBodies;
|
|
||||||
|
|
||||||
bool facingEachOther = false;
|
|
||||||
|
|
||||||
if (( glm::dot(_myOrientation.getFront(), _yourOrientation.getFront()) < -0.1f)
|
|
||||||
&& ( glm::dot(_myOrientation.getFront(), directionBetweenBodies ) > 0.1f)) {
|
|
||||||
facingEachOther = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((distanceBetweenBodies < _reachableRadius)
|
if (_hasInteractingOther) {
|
||||||
&& (facingEachOther)) {
|
|
||||||
_vectorBetweenHands = _yourHandPosition - _myHandPosition;
|
glm::vec3 vectorBetweenBodies = _yourBodyPosition - _myBodyPosition;
|
||||||
|
float distanceBetweenBodies = glm::length(vectorBetweenBodies);
|
||||||
|
glm::vec3 directionBetweenBodies = vectorBetweenBodies / distanceBetweenBodies;
|
||||||
|
|
||||||
float distanceBetweenHands = glm::length(_vectorBetweenHands);
|
bool facingEachOther = false;
|
||||||
if (distanceBetweenHands < HANDS_CLOSE_ENOUGH_TO_GRASP) {
|
|
||||||
_handsCloseEnoughToGrasp = true;
|
if (( glm::dot(_myOrientation.getFront(), _yourOrientation.getFront()) < -AVATAR_FACING_THRESHOLD) // we're facing each other
|
||||||
} else {
|
&& ( glm::dot(_myOrientation.getFront(), directionBetweenBodies ) > AVATAR_FACING_THRESHOLD)) { // I'm facing you
|
||||||
_handsCloseEnoughToGrasp = false;
|
facingEachOther = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_canReachToOtherAvatar = true;
|
if ((distanceBetweenBodies < _reachableRadius)
|
||||||
} else {
|
&& (facingEachOther)) {
|
||||||
_canReachToOtherAvatar = false;
|
_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) {
|
void AvatarTouch::render(glm::vec3 cameraPosition) {
|
||||||
|
|
||||||
if (_canReachToOtherAvatar) {
|
if (_canReachToOtherAvatar) {
|
||||||
|
@ -130,7 +136,6 @@ void AvatarTouch::render(glm::vec3 cameraPosition) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void AvatarTouch::renderBeamBetweenHands() {
|
void AvatarTouch::renderBeamBetweenHands() {
|
||||||
|
|
||||||
glm::vec3 v1(_myHandPosition);
|
glm::vec3 v1(_myHandPosition);
|
||||||
|
@ -144,9 +149,9 @@ void AvatarTouch::renderBeamBetweenHands() {
|
||||||
glEnd();
|
glEnd();
|
||||||
|
|
||||||
glColor3f(0.5f, 0.3f, 0.0f);
|
glColor3f(0.5f, 0.3f, 0.0f);
|
||||||
for (int p=0; p<NUM_POINTS; p++) {
|
for (int p=0; p<NUM_PARTICLE_POINTS; p++) {
|
||||||
|
|
||||||
_point[p] = _myHandPosition + _vectorBetweenHands * ((float)p / (float)NUM_POINTS);
|
_point[p] = _myHandPosition + _vectorBetweenHands * ((float)p / (float)NUM_PARTICLE_POINTS);
|
||||||
_point[p].x += randFloatInRange(-THREAD_RADIUS, THREAD_RADIUS);
|
_point[p].x += randFloatInRange(-THREAD_RADIUS, THREAD_RADIUS);
|
||||||
_point[p].y += randFloatInRange(-THREAD_RADIUS, THREAD_RADIUS);
|
_point[p].y += randFloatInRange(-THREAD_RADIUS, THREAD_RADIUS);
|
||||||
_point[p].z += randFloatInRange(-THREAD_RADIUS, THREAD_RADIUS);
|
_point[p].z += randFloatInRange(-THREAD_RADIUS, THREAD_RADIUS);
|
||||||
|
|
|
@ -28,16 +28,17 @@ public:
|
||||||
void simulate(float deltaTime);
|
void simulate(float deltaTime);
|
||||||
void render(glm::vec3 cameraPosition);
|
void render(glm::vec3 cameraPosition);
|
||||||
|
|
||||||
void setMyHandPosition (glm::vec3 position ) { _myHandPosition = position; }
|
void setHasInteractingOther(bool hasInteractingOther) { _hasInteractingOther = hasInteractingOther;}
|
||||||
void setYourHandPosition(glm::vec3 position ) { _yourHandPosition = position; }
|
void setMyHandPosition (glm::vec3 position ) { _myHandPosition = position;}
|
||||||
void setMyOrientation (Orientation orientation) { _myOrientation = orientation; }
|
void setYourHandPosition (glm::vec3 position ) { _yourHandPosition = position;}
|
||||||
void setYourOrientation (Orientation orientation) { _yourOrientation = orientation; }
|
void setMyOrientation (Orientation orientation ) { _myOrientation = orientation;}
|
||||||
void setMyBodyPosition (glm::vec3 position ) { _myBodyPosition = position; }
|
void setYourOrientation (Orientation orientation ) { _yourOrientation = orientation;}
|
||||||
void setYourBodyPosition(glm::vec3 position ) { _yourBodyPosition = position; }
|
void setMyBodyPosition (glm::vec3 position ) { _myBodyPosition = position;}
|
||||||
void setMyHandState (int state ) { _myHandState = state; }
|
void setYourBodyPosition (glm::vec3 position ) { _yourBodyPosition = position;}
|
||||||
void setYourHandState (int state ) { _yourHandState = state; }
|
void setMyHandState (int state ) { _myHandState = state;}
|
||||||
void setReachableRadius (float radius ) { _reachableRadius = radius; }
|
void setYourHandState (int state ) { _yourHandState = state;}
|
||||||
void setHoldingHands (bool holding ) { _weAreHoldingHands = holding; }
|
void setReachableRadius (float radius ) { _reachableRadius = radius;}
|
||||||
|
void setHoldingHands (bool holding ) { _weAreHoldingHands = holding;}
|
||||||
|
|
||||||
bool getAbleToReachOtherAvatar () const {return _canReachToOtherAvatar; }
|
bool getAbleToReachOtherAvatar () const {return _canReachToOtherAvatar; }
|
||||||
bool getHandsCloseEnoughToGrasp() const {return _handsCloseEnoughToGrasp;}
|
bool getHandsCloseEnoughToGrasp() const {return _handsCloseEnoughToGrasp;}
|
||||||
|
@ -45,10 +46,11 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static const int NUM_POINTS = 100;
|
static const int NUM_PARTICLE_POINTS = 100;
|
||||||
|
|
||||||
|
bool _hasInteractingOther;
|
||||||
bool _weAreHoldingHands;
|
bool _weAreHoldingHands;
|
||||||
glm::vec3 _point [NUM_POINTS];
|
glm::vec3 _point [NUM_PARTICLE_POINTS];
|
||||||
glm::vec3 _myBodyPosition;
|
glm::vec3 _myBodyPosition;
|
||||||
glm::vec3 _yourBodyPosition;
|
glm::vec3 _yourBodyPosition;
|
||||||
glm::vec3 _myHandPosition;
|
glm::vec3 _myHandPosition;
|
||||||
|
|
|
@ -60,8 +60,8 @@ void Environment::renderAtmospheres(Camera& camera) {
|
||||||
glm::vec3 Environment::getGravity (const glm::vec3& position) {
|
glm::vec3 Environment::getGravity (const glm::vec3& position) {
|
||||||
// the "original gravity"
|
// the "original gravity"
|
||||||
glm::vec3 gravity;
|
glm::vec3 gravity;
|
||||||
if (position.x > 0.0f && position.x < 10.0f && position.y > 0.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 < 10.0f) {
|
position.y < 3.0f && position.z > 0.0f && position.z < EDGE_SIZE_GROUND_PLANE) {
|
||||||
gravity = glm::vec3(0.0f, -1.0f, 0.0f);
|
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,
|
bool Environment::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end,
|
||||||
float radius, glm::vec3& penetration) {
|
float radius, glm::vec3& penetration) {
|
||||||
// collide with the "floor"
|
// collide with the "floor"
|
||||||
bool found = false;
|
bool found = findCapsulePlanePenetration(start, end, radius, glm::vec4(0.0f, 1.0f, 0.0f, 0.0f), penetration);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the lock for the duration of the call
|
// get the lock for the duration of the call
|
||||||
QMutexLocker locker(&_mutex);
|
QMutexLocker locker(&_mutex);
|
||||||
|
@ -117,11 +111,10 @@ bool Environment::findCapsulePenetration(const glm::vec3& start, const glm::vec3
|
||||||
if (environmentData.getGravity() == 0.0f) {
|
if (environmentData.getGravity() == 0.0f) {
|
||||||
continue; // don't bother colliding with gravity-less environments
|
continue; // don't bother colliding with gravity-less environments
|
||||||
}
|
}
|
||||||
glm::vec3 vector = computeVectorFromPointToSegment(environmentData.getAtmosphereCenter(), start, end);
|
glm::vec3 environmentPenetration;
|
||||||
float vectorLength = glm::length(vector);
|
if (findCapsuleSpherePenetration(start, end, radius, environmentData.getAtmosphereCenter(),
|
||||||
float distance = vectorLength - environmentData.getAtmosphereInnerRadius() - radius;
|
environmentData.getAtmosphereInnerRadius(), environmentPenetration)) {
|
||||||
if (distance < 0.0f) {
|
penetration = addPenetrations(penetration, environmentPenetration);
|
||||||
penetration += vector * (-distance / vectorLength);
|
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,9 +40,9 @@ vector<unsigned char> irisTexture;
|
||||||
|
|
||||||
Head::Head(Avatar* owningAvatar) :
|
Head::Head(Avatar* owningAvatar) :
|
||||||
HeadData((AvatarData*)owningAvatar),
|
HeadData((AvatarData*)owningAvatar),
|
||||||
|
_renderAlpha(0.0),
|
||||||
yawRate(0.0f),
|
yawRate(0.0f),
|
||||||
_returnHeadToCenter(false),
|
_returnHeadToCenter(false),
|
||||||
_audioLoudness(0.0f),
|
|
||||||
_skinColor(0.0f, 0.0f, 0.0f),
|
_skinColor(0.0f, 0.0f, 0.0f),
|
||||||
_position(0.0f, 0.0f, 0.0f),
|
_position(0.0f, 0.0f, 0.0f),
|
||||||
_rotation(0.0f, 0.0f, 0.0f),
|
_rotation(0.0f, 0.0f, 0.0f),
|
||||||
|
@ -62,10 +62,10 @@ Head::Head(Avatar* owningAvatar) :
|
||||||
_audioAttack(0.0f),
|
_audioAttack(0.0f),
|
||||||
_returnSpringScale(1.0f),
|
_returnSpringScale(1.0f),
|
||||||
_bodyRotation(0.0f, 0.0f, 0.0f),
|
_bodyRotation(0.0f, 0.0f, 0.0f),
|
||||||
|
_renderLookatVectors(false),
|
||||||
_mohawkTriangleFan(NULL),
|
_mohawkTriangleFan(NULL),
|
||||||
_mohawkColors(NULL),
|
_mohawkColors(NULL)
|
||||||
_renderLookatVectors(false) {
|
{
|
||||||
|
|
||||||
if (USING_PHYSICAL_MOHAWK) {
|
if (USING_PHYSICAL_MOHAWK) {
|
||||||
resetHairPhysics();
|
resetHairPhysics();
|
||||||
}
|
}
|
||||||
|
@ -206,8 +206,10 @@ void Head::calculateGeometry(bool lookingInMirror) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Head::render(bool lookingInMirror, glm::vec3 cameraPosition) {
|
void Head::render(bool lookingInMirror, glm::vec3 cameraPosition, float alpha) {
|
||||||
|
|
||||||
|
_renderAlpha = alpha;
|
||||||
|
|
||||||
calculateGeometry(lookingInMirror);
|
calculateGeometry(lookingInMirror);
|
||||||
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
@ -315,7 +317,7 @@ void Head::renderHeadSphere() {
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glTranslatef(_position.x, _position.y, _position.z); //translate to head position
|
glTranslatef(_position.x, _position.y, _position.z); //translate to head position
|
||||||
glScalef(_scale, _scale, _scale); //scale to head size
|
glScalef(_scale, _scale, _scale); //scale to head size
|
||||||
glColor3f(_skinColor.x, _skinColor.y, _skinColor.z);
|
glColor4f(_skinColor.x, _skinColor.y, _skinColor.z, _renderAlpha);
|
||||||
glutSolidSphere(1, 30, 30);
|
glutSolidSphere(1, 30, 30);
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
|
@ -323,13 +325,13 @@ void Head::renderHeadSphere() {
|
||||||
void Head::renderEars() {
|
void Head::renderEars() {
|
||||||
|
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glColor3f(_skinColor.x, _skinColor.y, _skinColor.z);
|
glColor4f(_skinColor.x, _skinColor.y, _skinColor.z, _renderAlpha);
|
||||||
glTranslatef(_leftEarPosition.x, _leftEarPosition.y, _leftEarPosition.z);
|
glTranslatef(_leftEarPosition.x, _leftEarPosition.y, _leftEarPosition.z);
|
||||||
glutSolidSphere(0.02, 30, 30);
|
glutSolidSphere(0.02, 30, 30);
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glColor3f(_skinColor.x, _skinColor.y, _skinColor.z);
|
glColor4f(_skinColor.x, _skinColor.y, _skinColor.z, _renderAlpha);
|
||||||
glTranslatef(_rightEarPosition.x, _rightEarPosition.y, _rightEarPosition.z);
|
glTranslatef(_rightEarPosition.x, _rightEarPosition.y, _rightEarPosition.z);
|
||||||
glutSolidSphere(0.02, 30, 30);
|
glutSolidSphere(0.02, 30, 30);
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
|
|
@ -34,7 +34,7 @@ public:
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
void simulate(float deltaTime, bool isMine);
|
void simulate(float deltaTime, bool isMine);
|
||||||
void render(bool lookingInMirror, glm::vec3 cameraPosition);
|
void render(bool lookingInMirror, glm::vec3 cameraPosition, float alpha);
|
||||||
void renderMohawk(bool lookingInMirror, glm::vec3 cameraPosition);
|
void renderMohawk(bool lookingInMirror, glm::vec3 cameraPosition);
|
||||||
|
|
||||||
void setScale (float scale ) { _scale = scale; }
|
void setScale (float scale ) { _scale = scale; }
|
||||||
|
@ -44,7 +44,6 @@ public:
|
||||||
void setSkinColor (glm::vec3 skinColor ) { _skinColor = skinColor; }
|
void setSkinColor (glm::vec3 skinColor ) { _skinColor = skinColor; }
|
||||||
void setSpringScale (float returnSpringScale ) { _returnSpringScale = returnSpringScale; }
|
void setSpringScale (float returnSpringScale ) { _returnSpringScale = returnSpringScale; }
|
||||||
void setAverageLoudness(float averageLoudness ) { _averageLoudness = averageLoudness; }
|
void setAverageLoudness(float averageLoudness ) { _averageLoudness = averageLoudness; }
|
||||||
void setAudioLoudness (float audioLoudness ) { _audioLoudness = audioLoudness; }
|
|
||||||
void setReturnToCenter (bool returnHeadToCenter) { _returnHeadToCenter = returnHeadToCenter; }
|
void setReturnToCenter (bool returnHeadToCenter) { _returnHeadToCenter = returnHeadToCenter; }
|
||||||
void setRenderLookatVectors(bool onOff ) { _renderLookatVectors = onOff; }
|
void setRenderLookatVectors(bool onOff ) { _renderLookatVectors = onOff; }
|
||||||
|
|
||||||
|
@ -72,8 +71,8 @@ private:
|
||||||
glm::vec3 endVelocity;
|
glm::vec3 endVelocity;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
float _renderAlpha;
|
||||||
bool _returnHeadToCenter;
|
bool _returnHeadToCenter;
|
||||||
float _audioLoudness;
|
|
||||||
glm::vec3 _skinColor;
|
glm::vec3 _skinColor;
|
||||||
glm::vec3 _position;
|
glm::vec3 _position;
|
||||||
glm::vec3 _rotation;
|
glm::vec3 _rotation;
|
||||||
|
|
|
@ -38,9 +38,11 @@ void OculusManager::connect() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OculusManager::updateYawOffset() {
|
void OculusManager::updateYawOffset() {
|
||||||
|
#ifdef __APPLE__
|
||||||
float yaw, pitch, roll;
|
float yaw, pitch, roll;
|
||||||
_sensorFusion.GetOrientation().GetEulerAngles<Axis_Y, Axis_X, Axis_Z, Rotate_CCW, Handed_R>(&yaw, &pitch, &roll);
|
_sensorFusion.GetOrientation().GetEulerAngles<Axis_Y, Axis_X, Axis_Z, Rotate_CCW, Handed_R>(&yaw, &pitch, &roll);
|
||||||
_yawOffset = yaw;
|
_yawOffset = yaw;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void OculusManager::getEulerAngles(float& yaw, float& pitch, float& roll) {
|
void OculusManager::getEulerAngles(float& yaw, float& pitch, float& roll) {
|
||||||
|
|
20
interface/src/Skeleton.cpp
Normal file
20
interface/src/Skeleton.cpp
Normal 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
54
interface/src/Skeleton.h
Normal 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
|
|
@ -17,4 +17,6 @@ const float WORLD_SIZE = 10.0;
|
||||||
#define PIf 3.14159265f
|
#define PIf 3.14159265f
|
||||||
#define GRAVITY_EARTH 9.80665f;
|
#define GRAVITY_EARTH 9.80665f;
|
||||||
|
|
||||||
|
const float EDGE_SIZE_GROUND_PLANE = 20.f;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -37,7 +37,6 @@ AvatarData::AvatarData(Agent* owningAgent) :
|
||||||
_bodyYaw(-90.0),
|
_bodyYaw(-90.0),
|
||||||
_bodyPitch(0.0),
|
_bodyPitch(0.0),
|
||||||
_bodyRoll(0.0),
|
_bodyRoll(0.0),
|
||||||
_audioLoudness(0),
|
|
||||||
_handState(0),
|
_handState(0),
|
||||||
_cameraPosition(0,0,0),
|
_cameraPosition(0,0,0),
|
||||||
_cameraDirection(0,0,0),
|
_cameraDirection(0,0,0),
|
||||||
|
@ -53,6 +52,7 @@ AvatarData::AvatarData(Agent* owningAgent) :
|
||||||
_wantDelta(false),
|
_wantDelta(false),
|
||||||
_headData(NULL)
|
_headData(NULL)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AvatarData::~AvatarData() {
|
AvatarData::~AvatarData() {
|
||||||
|
@ -104,7 +104,7 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) {
|
||||||
destinationBuffer += sizeof(char);
|
destinationBuffer += sizeof(char);
|
||||||
|
|
||||||
// Instantaneous audio loudness (used to drive facial animation)
|
// Instantaneous audio loudness (used to drive facial animation)
|
||||||
memcpy(destinationBuffer, &_audioLoudness, sizeof(float));
|
memcpy(destinationBuffer, &_headData->_audioLoudness, sizeof(float));
|
||||||
destinationBuffer += sizeof(float);
|
destinationBuffer += sizeof(float);
|
||||||
|
|
||||||
// camera details
|
// camera details
|
||||||
|
@ -198,7 +198,7 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
|
||||||
sourceBuffer += sizeof(char);
|
sourceBuffer += sizeof(char);
|
||||||
|
|
||||||
// Instantaneous audio loudness (used to drive facial animation)
|
// Instantaneous audio loudness (used to drive facial animation)
|
||||||
memcpy(&_audioLoudness, sourceBuffer, sizeof(float));
|
memcpy(&_headData->_audioLoudness, sourceBuffer, sizeof(float));
|
||||||
sourceBuffer += sizeof(float);
|
sourceBuffer += sizeof(float);
|
||||||
|
|
||||||
// camera details
|
// camera details
|
||||||
|
|
|
@ -51,11 +51,7 @@ public:
|
||||||
// Hand State
|
// Hand State
|
||||||
void setHandState(char s) { _handState = s; };
|
void setHandState(char s) { _handState = s; };
|
||||||
char getHandState() const {return _handState; };
|
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
|
// getters for camera details
|
||||||
const glm::vec3& getCameraPosition() const { return _cameraPosition; };
|
const glm::vec3& getCameraPosition() const { return _cameraPosition; };
|
||||||
const glm::vec3& getCameraDirection() const { return _cameraDirection; }
|
const glm::vec3& getCameraDirection() const { return _cameraDirection; }
|
||||||
|
@ -103,9 +99,6 @@ protected:
|
||||||
float _bodyPitch;
|
float _bodyPitch;
|
||||||
float _bodyRoll;
|
float _bodyRoll;
|
||||||
|
|
||||||
// Audio loudness (used to drive facial animation)
|
|
||||||
float _audioLoudness;
|
|
||||||
|
|
||||||
// Hand state (are we grabbing something or not)
|
// Hand state (are we grabbing something or not)
|
||||||
char _handState;
|
char _handState;
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ HeadData::HeadData(AvatarData* owningAvatar) :
|
||||||
_lookAtPosition(0.0f, 0.0f, 0.0f),
|
_lookAtPosition(0.0f, 0.0f, 0.0f),
|
||||||
_leanSideways(0.0f),
|
_leanSideways(0.0f),
|
||||||
_leanForward(0.0f),
|
_leanForward(0.0f),
|
||||||
|
_audioLoudness(0.0f),
|
||||||
_owningAvatar(owningAvatar)
|
_owningAvatar(owningAvatar)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,8 @@ public:
|
||||||
float getRoll() const { return _roll; }
|
float getRoll() const { return _roll; }
|
||||||
void setRoll(float roll) { _roll = glm::clamp(roll, MIN_HEAD_ROLL, MAX_HEAD_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 addYaw(float yaw);
|
||||||
void addPitch(float pitch);
|
void addPitch(float pitch);
|
||||||
void addRoll(float roll);
|
void addRoll(float roll);
|
||||||
|
@ -57,6 +59,7 @@ protected:
|
||||||
glm::vec3 _lookAtPosition;
|
glm::vec3 _lookAtPosition;
|
||||||
float _leanSideways;
|
float _leanSideways;
|
||||||
float _leanForward;
|
float _leanForward;
|
||||||
|
float _audioLoudness;
|
||||||
AvatarData* _owningAvatar;
|
AvatarData* _owningAvatar;
|
||||||
private:
|
private:
|
||||||
// privatize copy ctor and assignment operator so copies of this object cannot be made
|
// privatize copy ctor and assignment operator so copies of this object cannot be made
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "SharedUtil.h"
|
#include "SharedUtil.h"
|
||||||
|
|
||||||
#include "AABox.h"
|
#include "AABox.h"
|
||||||
|
#include "GeometryUtil.h"
|
||||||
|
|
||||||
|
|
||||||
void AABox::scale(float scale) {
|
void AABox::scale(float scale) {
|
||||||
|
@ -82,6 +83,17 @@ bool AABox::contains(const glm::vec3& point) const {
|
||||||
isWithin(point.z, _corner.z, _size.z);
|
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
|
// 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) {
|
static bool findIntersection(float origin, float direction, float corner, float size, float& distance) {
|
||||||
if (direction > EPSILON) {
|
if (direction > EPSILON) {
|
||||||
|
@ -95,6 +107,30 @@ static bool findIntersection(float origin, float direction, float corner, float
|
||||||
return false;
|
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 {
|
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
|
// handle the trivial case where the box contains the origin
|
||||||
if (contains(origin)) {
|
if (contains(origin)) {
|
||||||
|
@ -126,3 +162,168 @@ bool AABox::findRayIntersection(const glm::vec3& origin, const glm::vec3& direct
|
||||||
}
|
}
|
||||||
return false;
|
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
13
libraries/voxels/src/AABox.h
Executable file → Normal file
|
@ -22,6 +22,8 @@ enum BoxFace {
|
||||||
MAX_Z_FACE
|
MAX_Z_FACE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const int FACE_COUNT = 6;
|
||||||
|
|
||||||
class AABox
|
class AABox
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -46,9 +48,20 @@ public:
|
||||||
const glm::vec3& getCenter() const { return _center; };
|
const glm::vec3& getCenter() const { return _center; };
|
||||||
|
|
||||||
bool contains(const glm::vec3& point) const;
|
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 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:
|
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 _corner;
|
||||||
glm::vec3 _center;
|
glm::vec3 _center;
|
||||||
glm::vec3 _size;
|
glm::vec3 _size;
|
||||||
|
|
|
@ -5,12 +5,18 @@
|
||||||
// Created by Andrzej Kapolka on 5/21/13.
|
// Created by Andrzej Kapolka on 5/21/13.
|
||||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||||
|
|
||||||
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
#include "GeometryUtil.h"
|
#include "GeometryUtil.h"
|
||||||
|
|
||||||
glm::vec3 computeVectorFromPointToSegment(const glm::vec3& point, const glm::vec3& start, const glm::vec3& end) {
|
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
|
// compute the projection of the point vector onto the segment vector
|
||||||
glm::vec3 segmentVector = end - start;
|
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
|
if (proj <= 0.0f) { // closest to the start
|
||||||
return start - point;
|
return start - point;
|
||||||
|
|
||||||
|
@ -21,3 +27,91 @@ glm::vec3 computeVectorFromPointToSegment(const glm::vec3& point, const glm::vec
|
||||||
return start + segmentVector*proj - point;
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -13,4 +13,30 @@
|
||||||
|
|
||||||
glm::vec3 computeVectorFromPointToSegment(const glm::vec3& point, const glm::vec3& start, const glm::vec3& end);
|
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__) */
|
#endif /* defined(__interface__GeometryUtil__) */
|
||||||
|
|
|
@ -716,20 +716,20 @@ public:
|
||||||
bool findSpherePenetrationOp(VoxelNode* node, void* extraData) {
|
bool findSpherePenetrationOp(VoxelNode* node, void* extraData) {
|
||||||
SphereArgs* args = static_cast<SphereArgs*>(extraData);
|
SphereArgs* args = static_cast<SphereArgs*>(extraData);
|
||||||
|
|
||||||
// currently, we treat each node as a sphere enveloping the box
|
// coarse check against bounds
|
||||||
const glm::vec3& nodeCenter = node->getCenter();
|
const AABox& box = node->getAABox();
|
||||||
glm::vec3 vector = args->center - nodeCenter;
|
if (!box.expandedContains(args->center, args->radius)) {
|
||||||
float vectorLength = glm::length(vector);
|
|
||||||
float distance = vectorLength - node->getEnclosingRadius() - args->radius;
|
|
||||||
if (distance >= 0.0f) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!node->isLeaf()) {
|
if (!node->isLeaf()) {
|
||||||
return true; // recurse on children
|
return true; // recurse on children
|
||||||
}
|
}
|
||||||
if (node->isColored()) {
|
if (node->isColored()) {
|
||||||
args->penetration += vector * (-distance * TREE_SCALE / vectorLength);
|
glm::vec3 nodePenetration;
|
||||||
args->found = true;
|
if (box.findSpherePenetration(args->center, args->radius, nodePenetration)) {
|
||||||
|
args->penetration = addPenetrations(args->penetration, nodePenetration * (float)TREE_SCALE);
|
||||||
|
args->found = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -753,20 +753,20 @@ public:
|
||||||
bool findCapsulePenetrationOp(VoxelNode* node, void* extraData) {
|
bool findCapsulePenetrationOp(VoxelNode* node, void* extraData) {
|
||||||
CapsuleArgs* args = static_cast<CapsuleArgs*>(extraData);
|
CapsuleArgs* args = static_cast<CapsuleArgs*>(extraData);
|
||||||
|
|
||||||
// currently, we treat each node as a sphere enveloping the box
|
// coarse check against bounds
|
||||||
const glm::vec3& nodeCenter = node->getCenter();
|
const AABox& box = node->getAABox();
|
||||||
glm::vec3 vector = computeVectorFromPointToSegment(nodeCenter, args->start, args->end);
|
if (!box.expandedIntersectsSegment(args->start, args->end, args->radius)) {
|
||||||
float vectorLength = glm::length(vector);
|
|
||||||
float distance = vectorLength - node->getEnclosingRadius() - args->radius;
|
|
||||||
if (distance >= 0.0f) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!node->isLeaf()) {
|
if (!node->isLeaf()) {
|
||||||
return true; // recurse on children
|
return true; // recurse on children
|
||||||
}
|
}
|
||||||
if (node->isColored()) {
|
if (node->isColored()) {
|
||||||
args->penetration += vector * (-distance * TREE_SCALE / vectorLength);
|
glm::vec3 nodePenetration;
|
||||||
args->found = true;
|
if (box.findCapsulePenetration(args->start, args->end, args->radius, nodePenetration)) {
|
||||||
|
args->penetration = addPenetrations(args->penetration, nodePenetration * (float)TREE_SCALE);
|
||||||
|
args->found = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue