mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 04:44:11 +02:00
Merge pull request #2024 from AndrewMeadows/cleanup
Cleanup hand and head
This commit is contained in:
commit
4c33296dc0
21 changed files with 228 additions and 208 deletions
|
@ -450,22 +450,22 @@ void Application::paintGL() {
|
|||
_myCamera.setUpShift(0.0f);
|
||||
_myCamera.setDistance(0.0f);
|
||||
_myCamera.setTightness(0.0f); // Camera is directly connected to head without smoothing
|
||||
_myCamera.setTargetPosition(_myAvatar->getHead().calculateAverageEyePosition());
|
||||
_myCamera.setTargetRotation(_myAvatar->getHead().getOrientation());
|
||||
_myCamera.setTargetPosition(_myAvatar->getHead()->calculateAverageEyePosition());
|
||||
_myCamera.setTargetRotation(_myAvatar->getHead()->getOrientation());
|
||||
|
||||
} else if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
|
||||
_myCamera.setTightness(0.0f); // In first person, camera follows (untweaked) head exactly without delay
|
||||
_myCamera.setTargetPosition(_myAvatar->getHead().calculateAverageEyePosition());
|
||||
_myCamera.setTargetRotation(_myAvatar->getHead().getCameraOrientation());
|
||||
_myCamera.setTargetPosition(_myAvatar->getHead()->calculateAverageEyePosition());
|
||||
_myCamera.setTargetRotation(_myAvatar->getHead()->getCameraOrientation());
|
||||
|
||||
} else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
|
||||
_myCamera.setTightness(0.0f); // Camera is directly connected to head without smoothing
|
||||
_myCamera.setTargetPosition(_myAvatar->getUprightHeadPosition());
|
||||
_myCamera.setTargetRotation(_myAvatar->getHead().getCameraOrientation());
|
||||
_myCamera.setTargetRotation(_myAvatar->getHead()->getCameraOrientation());
|
||||
|
||||
} else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
|
||||
_myCamera.setTightness(0.0f);
|
||||
float headHeight = _myAvatar->getHead().calculateAverageEyePosition().y - _myAvatar->getPosition().y;
|
||||
float headHeight = _myAvatar->getHead()->calculateAverageEyePosition().y - _myAvatar->getPosition().y;
|
||||
_myCamera.setDistance(MIRROR_FULLSCREEN_DISTANCE * _myAvatar->getScale());
|
||||
_myCamera.setTargetPosition(_myAvatar->getPosition() + glm::vec3(0, headHeight, 0));
|
||||
_myCamera.setTargetRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PIf, 0.0f)));
|
||||
|
@ -529,14 +529,14 @@ void Application::paintGL() {
|
|||
_mirrorCamera.setTargetPosition(_myAvatar->getChestPosition());
|
||||
} else { // HEAD zoom level
|
||||
_mirrorCamera.setDistance(MIRROR_REARVIEW_DISTANCE * _myAvatar->getScale());
|
||||
if (_myAvatar->getSkeletonModel().isActive() && _myAvatar->getHead().getFaceModel().isActive()) {
|
||||
if (_myAvatar->getSkeletonModel().isActive() && _myAvatar->getHead()->getFaceModel().isActive()) {
|
||||
// as a hack until we have a better way of dealing with coordinate precision issues, reposition the
|
||||
// face/body so that the average eye position lies at the origin
|
||||
eyeRelativeCamera = true;
|
||||
_mirrorCamera.setTargetPosition(glm::vec3());
|
||||
|
||||
} else {
|
||||
_mirrorCamera.setTargetPosition(_myAvatar->getHead().calculateAverageEyePosition());
|
||||
_mirrorCamera.setTargetPosition(_myAvatar->getHead()->calculateAverageEyePosition());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -558,26 +558,26 @@ void Application::paintGL() {
|
|||
if (eyeRelativeCamera) {
|
||||
// save absolute translations
|
||||
glm::vec3 absoluteSkeletonTranslation = _myAvatar->getSkeletonModel().getTranslation();
|
||||
glm::vec3 absoluteFaceTranslation = _myAvatar->getHead().getFaceModel().getTranslation();
|
||||
glm::vec3 absoluteFaceTranslation = _myAvatar->getHead()->getFaceModel().getTranslation();
|
||||
|
||||
// get the eye positions relative to the neck and use them to set the face translation
|
||||
glm::vec3 leftEyePosition, rightEyePosition;
|
||||
_myAvatar->getHead().getFaceModel().setTranslation(glm::vec3());
|
||||
_myAvatar->getHead().getFaceModel().getEyePositions(leftEyePosition, rightEyePosition);
|
||||
_myAvatar->getHead().getFaceModel().setTranslation((leftEyePosition + rightEyePosition) * -0.5f);
|
||||
_myAvatar->getHead()->getFaceModel().setTranslation(glm::vec3());
|
||||
_myAvatar->getHead()->getFaceModel().getEyePositions(leftEyePosition, rightEyePosition);
|
||||
_myAvatar->getHead()->getFaceModel().setTranslation((leftEyePosition + rightEyePosition) * -0.5f);
|
||||
|
||||
// get the neck position relative to the body and use it to set the skeleton translation
|
||||
glm::vec3 neckPosition;
|
||||
_myAvatar->getSkeletonModel().setTranslation(glm::vec3());
|
||||
_myAvatar->getSkeletonModel().getNeckPosition(neckPosition);
|
||||
_myAvatar->getSkeletonModel().setTranslation(_myAvatar->getHead().getFaceModel().getTranslation() -
|
||||
_myAvatar->getSkeletonModel().setTranslation(_myAvatar->getHead()->getFaceModel().getTranslation() -
|
||||
neckPosition);
|
||||
|
||||
displaySide(_mirrorCamera, true);
|
||||
|
||||
// restore absolute translations
|
||||
_myAvatar->getSkeletonModel().setTranslation(absoluteSkeletonTranslation);
|
||||
_myAvatar->getHead().getFaceModel().setTranslation(absoluteFaceTranslation);
|
||||
_myAvatar->getHead()->getFaceModel().setTranslation(absoluteFaceTranslation);
|
||||
} else {
|
||||
displaySide(_mirrorCamera, true);
|
||||
}
|
||||
|
@ -1864,7 +1864,7 @@ void Application::init() {
|
|||
// TODO: move _myAvatar out of Application. Move relevant code to MyAvataar or AvatarManager
|
||||
_avatarManager.init();
|
||||
_myCamera.setMode(CAMERA_MODE_FIRST_PERSON);
|
||||
_myCamera.setModeShiftRate(1.0f);
|
||||
_myCamera.setModeShiftPeriod(1.0f);
|
||||
|
||||
_mirrorCamera.setMode(CAMERA_MODE_MIRROR);
|
||||
_mirrorCamera.setAspectRatio((float)MIRROR_VIEW_WIDTH / (float)MIRROR_VIEW_HEIGHT);
|
||||
|
@ -1975,8 +1975,8 @@ const float MAX_VOXEL_EDIT_DISTANCE = 50.0f;
|
|||
const float HEAD_SPHERE_RADIUS = 0.07f;
|
||||
|
||||
bool Application::isLookingAtMyAvatar(Avatar* avatar) {
|
||||
glm::vec3 theirLookat = avatar->getHead().getLookAtPosition();
|
||||
glm::vec3 myHeadPosition = _myAvatar->getHead().getPosition();
|
||||
glm::vec3 theirLookat = avatar->getHead()->getLookAtPosition();
|
||||
glm::vec3 myHeadPosition = _myAvatar->getHead()->getPosition();
|
||||
|
||||
if (pointInSphere(theirLookat, myHeadPosition, HEAD_SPHERE_RADIUS * _myAvatar->getScale())) {
|
||||
return true;
|
||||
|
@ -2037,7 +2037,7 @@ void Application::updateFaceshift() {
|
|||
|
||||
// Copy angular velocity if measured by faceshift, to the head
|
||||
if (_faceshift.isActive()) {
|
||||
_myAvatar->getHead().setAngularVelocity(_faceshift.getHeadAngularVelocity());
|
||||
_myAvatar->getHead()->setAngularVelocity(_faceshift.getHeadAngularVelocity());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2063,7 +2063,7 @@ void Application::updateMyAvatarLookAtPosition(glm::vec3& lookAtSpot) {
|
|||
float distance = TREE_SCALE;
|
||||
if (_myAvatar->getLookAtTargetAvatar()) {
|
||||
distance = glm::distance(_mouseRayOrigin,
|
||||
static_cast<Avatar*>(_myAvatar->getLookAtTargetAvatar())->getHead().calculateAverageEyePosition());
|
||||
static_cast<Avatar*>(_myAvatar->getLookAtTargetAvatar())->getHead()->calculateAverageEyePosition());
|
||||
|
||||
} else if (_isHoverVoxel) {
|
||||
distance = glm::distance(_mouseRayOrigin, getMouseVoxelWorldCoordinates(_hoverVoxel));
|
||||
|
@ -2084,14 +2084,14 @@ void Application::updateMyAvatarLookAtPosition(glm::vec3& lookAtSpot) {
|
|||
}
|
||||
if (trackerActive) {
|
||||
// deflect using Faceshift gaze data
|
||||
glm::vec3 origin = _myAvatar->getHead().calculateAverageEyePosition();
|
||||
glm::vec3 origin = _myAvatar->getHead()->calculateAverageEyePosition();
|
||||
float pitchSign = (_myCamera.getMode() == CAMERA_MODE_MIRROR) ? -1.0f : 1.0f;
|
||||
float deflection = Menu::getInstance()->getFaceshiftEyeDeflection();
|
||||
lookAtSpot = origin + _myCamera.getRotation() * glm::quat(glm::radians(glm::vec3(
|
||||
eyePitch * pitchSign * deflection, eyeYaw * deflection, 0.0f))) *
|
||||
glm::inverse(_myCamera.getRotation()) * (lookAtSpot - origin);
|
||||
}
|
||||
_myAvatar->getHead().setLookAtPosition(lookAtSpot);
|
||||
_myAvatar->getHead()->setLookAtPosition(lookAtSpot);
|
||||
}
|
||||
|
||||
void Application::updateHoverVoxels(float deltaTime, float& distance, BoxFace& face) {
|
||||
|
@ -2247,17 +2247,17 @@ void Application::cameraMenuChanged() {
|
|||
if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) {
|
||||
if (_myCamera.getMode() != CAMERA_MODE_MIRROR) {
|
||||
_myCamera.setMode(CAMERA_MODE_MIRROR);
|
||||
_myCamera.setModeShiftRate(100.0f);
|
||||
_myCamera.setModeShiftPeriod(0.00f);
|
||||
}
|
||||
} else if (Menu::getInstance()->isOptionChecked(MenuOption::FirstPerson)) {
|
||||
if (_myCamera.getMode() != CAMERA_MODE_FIRST_PERSON) {
|
||||
_myCamera.setMode(CAMERA_MODE_FIRST_PERSON);
|
||||
_myCamera.setModeShiftRate(1.0f);
|
||||
_myCamera.setModeShiftPeriod(1.0f);
|
||||
}
|
||||
} else {
|
||||
if (_myCamera.getMode() != CAMERA_MODE_THIRD_PERSON) {
|
||||
_myCamera.setMode(CAMERA_MODE_THIRD_PERSON);
|
||||
_myCamera.setModeShiftRate(1.0f);
|
||||
_myCamera.setModeShiftPeriod(1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -467,8 +467,8 @@ void Audio::handleAudioInput() {
|
|||
|
||||
if (audioMixer && audioMixer->getActiveSocket()) {
|
||||
MyAvatar* interfaceAvatar = Application::getInstance()->getAvatar();
|
||||
glm::vec3 headPosition = interfaceAvatar->getHead().getPosition();
|
||||
glm::quat headOrientation = interfaceAvatar->getHead().getOrientation();
|
||||
glm::vec3 headPosition = interfaceAvatar->getHead()->getPosition();
|
||||
glm::quat headOrientation = interfaceAvatar->getHead()->getOrientation();
|
||||
|
||||
// we need the amount of bytes in the buffer + 1 for type
|
||||
// + 12 for 3 floats for position + float for bearing + 1 attenuation byte
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
#include "Menu.h"
|
||||
#include "Util.h"
|
||||
|
||||
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;
|
||||
|
@ -57,7 +55,7 @@ Camera::Camera() :
|
|||
_newTightness(0.0f),
|
||||
_modeShift(1.0f),
|
||||
_linearModeShift(0.0f),
|
||||
_modeShiftRate(1.0f),
|
||||
_modeShiftPeriod(1.0f),
|
||||
_scale(1.0f),
|
||||
_lookingAt(0.0f, 0.0f, 0.0f),
|
||||
_isKeepLookingAt(false)
|
||||
|
@ -75,18 +73,18 @@ void Camera::update(float deltaTime) {
|
|||
// use iterative forces to keep the camera at the desired position and angle
|
||||
void Camera::updateFollowMode(float deltaTime) {
|
||||
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;
|
||||
|
||||
_linearModeShift += deltaTime / _modeShiftPeriod;
|
||||
if (_needsToInitialize || _linearModeShift > 1.0f) {
|
||||
_linearModeShift = 1.0f;
|
||||
_modeShift = 1.0f;
|
||||
_upShift = _newUpShift;
|
||||
_distance = _newDistance;
|
||||
_tightness = _newTightness;
|
||||
} else {
|
||||
_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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,13 +119,10 @@ float Camera::getFarClip() const {
|
|||
: std::numeric_limits<int16_t>::max() - 1;
|
||||
}
|
||||
|
||||
void Camera::setModeShiftRate ( float rate ) {
|
||||
|
||||
_modeShiftRate = rate;
|
||||
|
||||
if (_modeShiftRate < CAMERA_MINIMUM_MODE_SHIFT_RATE ) {
|
||||
_modeShiftRate = CAMERA_MINIMUM_MODE_SHIFT_RATE;
|
||||
}
|
||||
void Camera::setModeShiftPeriod (float period) {
|
||||
const float MIN_PERIOD = 0.001f;
|
||||
const float MAX_PERIOD = 3.0f;
|
||||
_modeShiftPeriod = glm::clamp(period, MIN_PERIOD, MAX_PERIOD);
|
||||
}
|
||||
|
||||
void Camera::setMode(CameraMode m) {
|
||||
|
@ -307,7 +302,8 @@ void CameraScriptableObject::setMode(const QString& mode) {
|
|||
}
|
||||
if (currentMode != targetMode) {
|
||||
_camera->setMode(targetMode);
|
||||
_camera->setModeShiftRate(10.0f);
|
||||
const float DEFAULT_MODE_SHIFT_PERIOD = 0.5f; // half second
|
||||
_camera->setModeShiftPeriod(DEFAULT_MODE_SHIFT_PERIOD);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ public:
|
|||
void setTargetRotation(const glm::quat& rotation);
|
||||
|
||||
void setMode(CameraMode m);
|
||||
void setModeShiftRate(float r);
|
||||
void setModeShiftPeriod(float r);
|
||||
void setFieldOfView(float f);
|
||||
void setAspectRatio(float a);
|
||||
void setNearClip(float n);
|
||||
|
@ -109,7 +109,7 @@ private:
|
|||
float _newTightness;
|
||||
float _modeShift;
|
||||
float _linearModeShift;
|
||||
float _modeShiftRate;
|
||||
float _modeShiftPeriod;
|
||||
float _scale;
|
||||
|
||||
glm::vec3 _lookingAt;
|
||||
|
|
|
@ -327,7 +327,8 @@ Menu::Menu() :
|
|||
QMenu* avatarOptionsMenu = developerMenu->addMenu("Avatar Options");
|
||||
|
||||
addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::Avatars, 0, true);
|
||||
addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::CollisionProxies);
|
||||
addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::RenderSkeletonCollisionProxies);
|
||||
addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::RenderHeadCollisionProxies);
|
||||
|
||||
addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::LookAtVectors, 0, false);
|
||||
addCheckableActionToQMenuAndActionHash(avatarOptionsMenu,
|
||||
|
@ -772,7 +773,7 @@ void Menu::editPreferences() {
|
|||
QFormLayout* form = new QFormLayout();
|
||||
layout->addLayout(form, 1);
|
||||
|
||||
QString faceURLString = applicationInstance->getAvatar()->getHead().getFaceModel().getURL().toString();
|
||||
QString faceURLString = applicationInstance->getAvatar()->getHead()->getFaceModel().getURL().toString();
|
||||
QLineEdit* faceURLEdit = new QLineEdit(faceURLString);
|
||||
faceURLEdit->setMinimumWidth(QLINE_MINIMUM_WIDTH);
|
||||
faceURLEdit->setPlaceholderText(DEFAULT_HEAD_MODEL_URL.toString());
|
||||
|
@ -785,7 +786,7 @@ void Menu::editPreferences() {
|
|||
form->addRow("Skeleton URL:", skeletonURLEdit);
|
||||
|
||||
QSlider* pupilDilation = new QSlider(Qt::Horizontal);
|
||||
pupilDilation->setValue(applicationInstance->getAvatar()->getHead().getPupilDilation() * pupilDilation->maximum());
|
||||
pupilDilation->setValue(applicationInstance->getAvatar()->getHead()->getPupilDilation() * pupilDilation->maximum());
|
||||
form->addRow("Pupil Dilation:", pupilDilation);
|
||||
|
||||
QSlider* faceshiftEyeDeflection = new QSlider(Qt::Horizontal);
|
||||
|
@ -861,7 +862,7 @@ void Menu::editPreferences() {
|
|||
applicationInstance->getAvatar()->sendIdentityPacket();
|
||||
}
|
||||
|
||||
applicationInstance->getAvatar()->getHead().setPupilDilation(pupilDilation->value() / (float)pupilDilation->maximum());
|
||||
applicationInstance->getAvatar()->getHead()->setPupilDilation(pupilDilation->value() / (float)pupilDilation->maximum());
|
||||
|
||||
_maxVoxels = maxVoxels->value();
|
||||
applicationInstance->getVoxels()->setMaxVoxels(_maxVoxels);
|
||||
|
|
|
@ -185,7 +185,6 @@ namespace MenuOption {
|
|||
const QString Bandwidth = "Bandwidth Display";
|
||||
const QString BandwidthDetails = "Bandwidth Details";
|
||||
const QString ChatCircling = "Chat Circling";
|
||||
const QString CollisionProxies = "Collision Proxies";
|
||||
const QString Collisions = "Collisions";
|
||||
const QString CollideWithAvatars = "Collide With Avatars";
|
||||
const QString CollideWithParticles = "Collide With Particles";
|
||||
|
@ -267,6 +266,8 @@ namespace MenuOption {
|
|||
const QString Preferences = "Preferences...";
|
||||
const QString RandomizeVoxelColors = "Randomize Voxel TRUE Colors";
|
||||
const QString ReloadAllScripts = "Reload All Scripts";
|
||||
const QString RenderSkeletonCollisionProxies = "Skeleton Collision Proxies";
|
||||
const QString RenderHeadCollisionProxies = "Head Collision Proxies";
|
||||
const QString ResetAvatarSize = "Reset Avatar Size";
|
||||
const QString ResetSwatchColors = "Reset Swatch Colors";
|
||||
const QString RunTimingTests = "Run Timing Tests";
|
||||
|
|
|
@ -59,8 +59,6 @@ const float CHAT_MESSAGE_HEIGHT = 0.1f;
|
|||
|
||||
Avatar::Avatar() :
|
||||
AvatarData(),
|
||||
_head(this),
|
||||
_hand(this),
|
||||
_skeletonModel(this),
|
||||
_bodyYawDelta(0.0f),
|
||||
_mode(AVATAR_MODE_STANDING),
|
||||
|
@ -81,18 +79,16 @@ Avatar::Avatar() :
|
|||
moveToThread(Application::getInstance()->thread());
|
||||
|
||||
// give the pointer to our head to inherited _headData variable from AvatarData
|
||||
_headData = &_head;
|
||||
_handData = &_hand;
|
||||
_headData = static_cast<HeadData*>(new Head(this));
|
||||
_handData = static_cast<HandData*>(new Hand(this));
|
||||
}
|
||||
|
||||
Avatar::~Avatar() {
|
||||
_headData = NULL;
|
||||
_handData = NULL;
|
||||
}
|
||||
|
||||
void Avatar::init() {
|
||||
_head.init();
|
||||
_hand.init();
|
||||
getHead()->init();
|
||||
getHand()->init();
|
||||
_skeletonModel.init();
|
||||
_initialized = true;
|
||||
}
|
||||
|
@ -115,16 +111,17 @@ void Avatar::simulate(float deltaTime) {
|
|||
// copy velocity so we can use it later for acceleration
|
||||
glm::vec3 oldVelocity = getVelocity();
|
||||
|
||||
_hand.simulate(deltaTime, false);
|
||||
getHand()->simulate(deltaTime, false);
|
||||
_skeletonModel.simulate(deltaTime);
|
||||
_head.setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll));
|
||||
Head* head = getHead();
|
||||
head->setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll));
|
||||
glm::vec3 headPosition;
|
||||
if (!_skeletonModel.getHeadPosition(headPosition)) {
|
||||
headPosition = _position;
|
||||
}
|
||||
_head.setPosition(headPosition);
|
||||
_head.setScale(_scale);
|
||||
_head.simulate(deltaTime, false);
|
||||
head->setPosition(headPosition);
|
||||
head->setScale(_scale);
|
||||
getHead()->simulate(deltaTime, false);
|
||||
|
||||
// use speed and angular velocity to determine walking vs. standing
|
||||
if (_speed + fabs(_bodyYawDelta) > 0.2) {
|
||||
|
@ -160,11 +157,12 @@ void Avatar::render(bool forceRenderHead) {
|
|||
Glower glower(_moving && glm::length(toTarget) > GLOW_DISTANCE ? 1.0f : 0.0f);
|
||||
|
||||
// render body
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::CollisionProxies)) {
|
||||
_skeletonModel.renderCollisionProxies(1.f);
|
||||
//_head.getFaceModel().renderCollisionProxies(0.5f);
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::RenderSkeletonCollisionProxies)) {
|
||||
_skeletonModel.renderCollisionProxies(0.7f);
|
||||
}
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::RenderHeadCollisionProxies)) {
|
||||
getHead()->getFaceModel().renderCollisionProxies(0.7f);
|
||||
}
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Avatars)) {
|
||||
renderBody(forceRenderHead);
|
||||
}
|
||||
|
@ -172,7 +170,7 @@ void Avatar::render(bool forceRenderHead) {
|
|||
// render sphere when far away
|
||||
const float MAX_ANGLE = 10.f;
|
||||
float height = getHeight();
|
||||
glm::vec3 delta = height * (_head.getCameraOrientation() * IDENTITY_UP) / 2.f;
|
||||
glm::vec3 delta = height * (getHead()->getCameraOrientation() * IDENTITY_UP) / 2.f;
|
||||
float angle = abs(angleBetween(toTarget + delta, toTarget - delta));
|
||||
|
||||
if (angle < MAX_ANGLE) {
|
||||
|
@ -180,7 +178,7 @@ void Avatar::render(bool forceRenderHead) {
|
|||
glPushMatrix();
|
||||
glTranslatef(_position.x, _position.y, _position.z);
|
||||
glScalef(height / 2.f, height / 2.f, height / 2.f);
|
||||
glutSolidSphere(1.2f + _head.getAverageLoudness() * .0005f, 20, 20);
|
||||
glutSolidSphere(1.2f + getHead()->getAverageLoudness() * .0005f, 20, 20);
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
@ -194,7 +192,7 @@ void Avatar::render(bool forceRenderHead) {
|
|||
}
|
||||
glPushMatrix();
|
||||
|
||||
glm::vec3 chatPosition = getHead().getEyePosition() + getBodyUpDirection() * CHAT_MESSAGE_HEIGHT * _scale;
|
||||
glm::vec3 chatPosition = getHead()->getEyePosition() + getBodyUpDirection() * CHAT_MESSAGE_HEIGHT * _scale;
|
||||
glTranslatef(chatPosition.x, chatPosition.y, chatPosition.z);
|
||||
glm::quat chatRotation = Application::getInstance()->getCamera()->getRotation();
|
||||
glm::vec3 chatAxis = glm::axis(chatRotation);
|
||||
|
@ -251,9 +249,9 @@ void Avatar::renderBody(bool forceRenderHead) {
|
|||
//printf("Render other at %.3f, %.2f, %.2f\n", pos.x, pos.y, pos.z);
|
||||
_skeletonModel.render(1.0f);
|
||||
if (forceRenderHead) {
|
||||
_head.render(1.0f);
|
||||
getHead()->render(1.0f);
|
||||
}
|
||||
_hand.render(false);
|
||||
getHand()->render(false);
|
||||
}
|
||||
|
||||
bool Avatar::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const {
|
||||
|
@ -262,7 +260,7 @@ bool Avatar::findRayIntersection(const glm::vec3& origin, const glm::vec3& direc
|
|||
if (_skeletonModel.findRayIntersection(origin, direction, modelDistance)) {
|
||||
minDistance = qMin(minDistance, modelDistance);
|
||||
}
|
||||
if (_head.getFaceModel().findRayIntersection(origin, direction, modelDistance)) {
|
||||
if (getHead()->getFaceModel().findRayIntersection(origin, direction, modelDistance)) {
|
||||
minDistance = qMin(minDistance, modelDistance);
|
||||
}
|
||||
if (minDistance < FLT_MAX) {
|
||||
|
@ -277,7 +275,7 @@ bool Avatar::findSphereCollisions(const glm::vec3& penetratorCenter, float penet
|
|||
// Temporarily disabling collisions against the skeleton because the collision proxies up
|
||||
// near the neck are bad and prevent the hand from hitting the face.
|
||||
//return _skeletonModel.findSphereCollisions(penetratorCenter, penetratorRadius, collisions, 1.0f, skeletonSkipIndex);
|
||||
return _head.getFaceModel().findSphereCollisions(penetratorCenter, penetratorRadius, collisions);
|
||||
return getHead()->getFaceModel().findSphereCollisions(penetratorCenter, penetratorRadius, collisions);
|
||||
}
|
||||
|
||||
bool Avatar::findParticleCollisions(const glm::vec3& particleCenter, float particleRadius, CollisionList& collisions) {
|
||||
|
@ -356,7 +354,7 @@ bool Avatar::findParticleCollisions(const glm::vec3& particleCenter, float parti
|
|||
void Avatar::setFaceModelURL(const QUrl &faceModelURL) {
|
||||
AvatarData::setFaceModelURL(faceModelURL);
|
||||
const QUrl DEFAULT_FACE_MODEL_URL = QUrl::fromLocalFile("resources/meshes/defaultAvatar_head.fst");
|
||||
_head.getFaceModel().setURL(_faceModelURL, DEFAULT_FACE_MODEL_URL);
|
||||
getHead()->getFaceModel().setURL(_faceModelURL, DEFAULT_FACE_MODEL_URL);
|
||||
}
|
||||
|
||||
void Avatar::setSkeletonModelURL(const QUrl &skeletonModelURL) {
|
||||
|
@ -467,7 +465,7 @@ bool Avatar::collisionWouldMoveAvatar(CollisionInfo& collision) const {
|
|||
return false;
|
||||
//return _skeletonModel.collisionHitsMoveableJoint(collision);
|
||||
}
|
||||
if (model == &(_head.getFaceModel())) {
|
||||
if (model == &(getHead()->getFaceModel())) {
|
||||
// ATM we always handle MODEL_COLLISIONS against the face.
|
||||
return true;
|
||||
}
|
||||
|
@ -480,8 +478,8 @@ void Avatar::applyCollision(CollisionInfo& collision) {
|
|||
}
|
||||
// TODO: make skeleton also respond to collisions
|
||||
Model* model = static_cast<Model*>(collision._data);
|
||||
if (model == &(_head.getFaceModel())) {
|
||||
_head.applyCollision(collision);
|
||||
if (model == &(getHead()->getFaceModel())) {
|
||||
getHead()->applyCollision(collision);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -490,6 +488,6 @@ float Avatar::getPelvisFloatingHeight() const {
|
|||
}
|
||||
|
||||
float Avatar::getPelvisToHeadLength() const {
|
||||
return glm::distance(_position, _head.getPosition());
|
||||
return glm::distance(_position, getHead()->getPosition());
|
||||
}
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ public:
|
|||
void render(bool forceRenderHead);
|
||||
|
||||
//setters
|
||||
void setDisplayingLookatVectors(bool displayingLookatVectors) { _head.setRenderLookatVectors(displayingLookatVectors); }
|
||||
void setDisplayingLookatVectors(bool displayingLookatVectors) { getHead()->setRenderLookatVectors(displayingLookatVectors); }
|
||||
void setMouseRay(const glm::vec3 &origin, const glm::vec3 &direction);
|
||||
|
||||
//getters
|
||||
|
@ -83,8 +83,9 @@ public:
|
|||
glm::vec3 getChestPosition() const;
|
||||
float getScale() const { return _scale; }
|
||||
const glm::vec3& getVelocity() const { return _velocity; }
|
||||
Head& getHead() { return _head; }
|
||||
Hand& getHand() { return _hand; }
|
||||
const Head* getHead() const { return static_cast<const Head*>(_headData); }
|
||||
Head* getHead() { return static_cast<Head*>(_headData); }
|
||||
Hand* getHand() { return static_cast<Hand*>(_handData); }
|
||||
glm::quat getWorldAlignedOrientation() const;
|
||||
|
||||
Node* getOwningAvatarMixer() { return _owningAvatarMixer.data(); }
|
||||
|
@ -129,8 +130,6 @@ public slots:
|
|||
void updateCollisionFlags();
|
||||
|
||||
protected:
|
||||
Head _head;
|
||||
Hand _hand;
|
||||
SkeletonModel _skeletonModel;
|
||||
float _bodyYawDelta;
|
||||
AvatarMode _mode;
|
||||
|
|
|
@ -48,9 +48,6 @@ bool FaceModel::render(float alpha) {
|
|||
if (!Model::render(alpha)) {
|
||||
return false;
|
||||
}
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::CollisionProxies)) {
|
||||
renderCollisionProxies(alpha);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -125,6 +125,41 @@ void Hand::simulate(float deltaTime, bool isMine) {
|
|||
}
|
||||
}
|
||||
|
||||
void Hand::playSlaps(PalmData& palm, Avatar* avatar)
|
||||
{
|
||||
// Check for palm collisions
|
||||
glm::vec3 myPalmPosition = palm.getPosition();
|
||||
float palmCollisionDistance = 0.1f;
|
||||
bool wasColliding = palm.getIsCollidingWithPalm();
|
||||
palm.setIsCollidingWithPalm(false);
|
||||
// If 'Play Slaps' is enabled, look for palm-to-palm collisions and make sound
|
||||
for (size_t j = 0; j < avatar->getHand()->getNumPalms(); j++) {
|
||||
PalmData& otherPalm = avatar->getHand()->getPalms()[j];
|
||||
if (!otherPalm.isActive()) {
|
||||
continue;
|
||||
}
|
||||
glm::vec3 otherPalmPosition = otherPalm.getPosition();
|
||||
if (glm::length(otherPalmPosition - myPalmPosition) < palmCollisionDistance) {
|
||||
palm.setIsCollidingWithPalm(true);
|
||||
if (!wasColliding) {
|
||||
const float PALM_COLLIDE_VOLUME = 1.f;
|
||||
const float PALM_COLLIDE_FREQUENCY = 1000.f;
|
||||
const float PALM_COLLIDE_DURATION_MAX = 0.75f;
|
||||
const float PALM_COLLIDE_DECAY_PER_SAMPLE = 0.01f;
|
||||
Application::getInstance()->getAudio()->startDrumSound(PALM_COLLIDE_VOLUME,
|
||||
PALM_COLLIDE_FREQUENCY,
|
||||
PALM_COLLIDE_DURATION_MAX,
|
||||
PALM_COLLIDE_DECAY_PER_SAMPLE);
|
||||
// If the other person's palm is in motion, move mine downward to show I was hit
|
||||
const float MIN_VELOCITY_FOR_SLAP = 0.05f;
|
||||
if (glm::length(otherPalm.getVelocity()) > MIN_VELOCITY_FOR_SLAP) {
|
||||
// add slapback here
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We create a static CollisionList that is recycled for each collision test.
|
||||
const float MAX_COLLISIONS_PER_AVATAR = 32;
|
||||
static CollisionList handCollisions(MAX_COLLISIONS_PER_AVATAR);
|
||||
|
@ -139,41 +174,12 @@ void Hand::collideAgainstAvatar(Avatar* avatar, bool isMyHand) {
|
|||
PalmData& palm = getPalms()[i];
|
||||
if (!palm.isActive()) {
|
||||
continue;
|
||||
}
|
||||
glm::vec3 totalPenetration;
|
||||
if (isMyHand && Menu::getInstance()->isOptionChecked(MenuOption::PlaySlaps)) {
|
||||
// Check for palm collisions
|
||||
glm::vec3 myPalmPosition = palm.getPosition();
|
||||
float palmCollisionDistance = 0.1f;
|
||||
bool wasColliding = palm.getIsCollidingWithPalm();
|
||||
palm.setIsCollidingWithPalm(false);
|
||||
// If 'Play Slaps' is enabled, look for palm-to-palm collisions and make sound
|
||||
for (size_t j = 0; j < avatar->getHand().getNumPalms(); j++) {
|
||||
PalmData& otherPalm = avatar->getHand().getPalms()[j];
|
||||
if (!otherPalm.isActive()) {
|
||||
continue;
|
||||
}
|
||||
glm::vec3 otherPalmPosition = otherPalm.getPosition();
|
||||
if (glm::length(otherPalmPosition - myPalmPosition) < palmCollisionDistance) {
|
||||
palm.setIsCollidingWithPalm(true);
|
||||
if (!wasColliding) {
|
||||
const float PALM_COLLIDE_VOLUME = 1.f;
|
||||
const float PALM_COLLIDE_FREQUENCY = 1000.f;
|
||||
const float PALM_COLLIDE_DURATION_MAX = 0.75f;
|
||||
const float PALM_COLLIDE_DECAY_PER_SAMPLE = 0.01f;
|
||||
Application::getInstance()->getAudio()->startDrumSound(PALM_COLLIDE_VOLUME,
|
||||
PALM_COLLIDE_FREQUENCY,
|
||||
PALM_COLLIDE_DURATION_MAX,
|
||||
PALM_COLLIDE_DECAY_PER_SAMPLE);
|
||||
// If the other person's palm is in motion, move mine downward to show I was hit
|
||||
const float MIN_VELOCITY_FOR_SLAP = 0.05f;
|
||||
if (glm::length(otherPalm.getVelocity()) > MIN_VELOCITY_FOR_SLAP) {
|
||||
// add slapback here
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isMyHand && Menu::getInstance()->isOptionChecked(MenuOption::PlaySlaps)) {
|
||||
playSlaps(palm, avatar);
|
||||
}
|
||||
|
||||
glm::vec3 totalPenetration;
|
||||
handCollisions.clear();
|
||||
if (avatar->findSphereCollisions(palm.getPosition(), scaledPalmRadius, handCollisions)) {
|
||||
for (int j = 0; j < handCollisions.size(); ++j) {
|
||||
|
@ -307,7 +313,8 @@ void Hand::render(bool isMine) {
|
|||
_buckyBalls.render();
|
||||
}
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::CollisionProxies)) {
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::RenderSkeletonCollisionProxies)) {
|
||||
// draw a green sphere at hand joint location, which is actually near the wrist)
|
||||
for (size_t i = 0; i < getNumPalms(); i++) {
|
||||
PalmData& palm = getPalms()[i];
|
||||
if (!palm.isActive()) {
|
||||
|
|
|
@ -93,6 +93,8 @@ private:
|
|||
void calculateGeometry();
|
||||
|
||||
void handleVoxelCollision(PalmData* palm, const glm::vec3& fingerTipPosition, VoxelTreeElement* voxel, float deltaTime);
|
||||
|
||||
void playSlaps(PalmData& palm, Avatar* avatar);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -53,7 +53,6 @@ MyAvatar::MyAvatar() :
|
|||
_elapsedTimeSinceCollision(0.0f),
|
||||
_lastCollisionPosition(0, 0, 0),
|
||||
_speedBrakes(false),
|
||||
_isCollisionsOn(true),
|
||||
_isThrustOn(false),
|
||||
_thrustMultiplier(1.0f),
|
||||
_moveTarget(0,0,0),
|
||||
|
@ -73,8 +72,8 @@ void MyAvatar::reset() {
|
|||
// TODO? resurrect headMouse stuff?
|
||||
//_headMouseX = _glWidget->width() / 2;
|
||||
//_headMouseY = _glWidget->height() / 2;
|
||||
_head.reset();
|
||||
_hand.reset();
|
||||
getHead()->reset();
|
||||
getHand()->reset();
|
||||
|
||||
setVelocity(glm::vec3(0,0,0));
|
||||
setThrust(glm::vec3(0,0,0));
|
||||
|
@ -131,19 +130,20 @@ void MyAvatar::update(float deltaTime) {
|
|||
//_headMouseY = glm::clamp(_headMouseY, 0, _glWidget->height());
|
||||
}
|
||||
|
||||
Head* head = getHead();
|
||||
if (OculusManager::isConnected()) {
|
||||
float yaw, pitch, roll;
|
||||
OculusManager::getEulerAngles(yaw, pitch, roll);
|
||||
|
||||
_head.setYaw(yaw);
|
||||
_head.setPitch(pitch);
|
||||
_head.setRoll(roll);
|
||||
head->setYaw(yaw);
|
||||
head->setPitch(pitch);
|
||||
head->setRoll(roll);
|
||||
}
|
||||
|
||||
// Get audio loudness data from audio input device
|
||||
Audio* audio = Application::getInstance()->getAudio();
|
||||
_head.setAudioLoudness(audio->getLastInputLoudness());
|
||||
_head.setAudioAverageLoudness(audio->getAudioAverageInputLoudness());
|
||||
head->setAudioLoudness(audio->getLastInputLoudness());
|
||||
head->setAudioAverageLoudness(audio->getAudioAverageInputLoudness());
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Gravity)) {
|
||||
setGravity(Application::getInstance()->getEnvironment()->getGravity(getPosition()));
|
||||
|
@ -267,7 +267,7 @@ void MyAvatar::simulate(float deltaTime) {
|
|||
|
||||
if (!Application::getInstance()->getFaceshift()->isActive() && OculusManager::isConnected() &&
|
||||
fabsf(forwardAcceleration) > OCULUS_ACCELERATION_PULL_THRESHOLD &&
|
||||
fabs(_head.getYaw()) > OCULUS_YAW_OFFSET_THRESHOLD) {
|
||||
fabs(getHead()->getYaw()) > OCULUS_YAW_OFFSET_THRESHOLD) {
|
||||
|
||||
// if we're wearing the oculus
|
||||
// and this acceleration is above the pull threshold
|
||||
|
@ -277,7 +277,7 @@ void MyAvatar::simulate(float deltaTime) {
|
|||
_bodyYaw = getAbsoluteHeadYaw();
|
||||
|
||||
// set the head yaw to zero for this draw
|
||||
_head.setYaw(0);
|
||||
getHead()->setYaw(0);
|
||||
|
||||
// correct the oculus yaw offset
|
||||
OculusManager::updateYawOffset();
|
||||
|
@ -315,17 +315,20 @@ void MyAvatar::simulate(float deltaTime) {
|
|||
_position += _velocity * deltaTime;
|
||||
|
||||
// update avatar skeleton and simulate hand and head
|
||||
_hand.collideAgainstOurself();
|
||||
_hand.simulate(deltaTime, true);
|
||||
getHand()->collideAgainstOurself();
|
||||
getHand()->simulate(deltaTime, true);
|
||||
|
||||
_skeletonModel.simulate(deltaTime);
|
||||
_head.setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll));
|
||||
|
||||
Head* head = getHead();
|
||||
head->setBodyRotation(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll));
|
||||
glm::vec3 headPosition;
|
||||
if (!_skeletonModel.getHeadPosition(headPosition)) {
|
||||
headPosition = _position;
|
||||
}
|
||||
_head.setPosition(headPosition);
|
||||
_head.setScale(_scale);
|
||||
_head.simulate(deltaTime, true);
|
||||
head->setPosition(headPosition);
|
||||
head->setScale(_scale);
|
||||
head->simulate(deltaTime, true);
|
||||
|
||||
// Zero thrust out now that we've added it to velocity in this frame
|
||||
_thrust = glm::vec3(0, 0, 0);
|
||||
|
@ -351,6 +354,8 @@ void MyAvatar::updateFromGyros(float deltaTime) {
|
|||
estimatedRotation = safeEulerAngles(visage->getHeadRotation());
|
||||
trackerActive = true;
|
||||
}
|
||||
|
||||
Head* head = getHead();
|
||||
if (trackerActive) {
|
||||
// Rotate the body if the head is turned beyond the screen
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::TurnWithHead)) {
|
||||
|
@ -370,10 +375,10 @@ void MyAvatar::updateFromGyros(float deltaTime) {
|
|||
// restore rotation, lean to neutral positions
|
||||
const float RESTORE_PERIOD = 1.f; // seconds
|
||||
float restorePercentage = glm::clamp(deltaTime/RESTORE_PERIOD, 0.f, 1.f);
|
||||
_head.setYaw(glm::mix(_head.getYaw(), 0.0f, restorePercentage));
|
||||
_head.setRoll(glm::mix(_head.getRoll(), 0.0f, restorePercentage));
|
||||
_head.setLeanSideways(glm::mix(_head.getLeanSideways(), 0.0f, restorePercentage));
|
||||
_head.setLeanForward(glm::mix(_head.getLeanForward(), 0.0f, restorePercentage));
|
||||
head->setYaw(glm::mix(head->getYaw(), 0.0f, restorePercentage));
|
||||
head->setRoll(glm::mix(head->getRoll(), 0.0f, restorePercentage));
|
||||
head->setLeanSideways(glm::mix(head->getLeanSideways(), 0.0f, restorePercentage));
|
||||
head->setLeanForward(glm::mix(head->getLeanForward(), 0.0f, restorePercentage));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -382,17 +387,17 @@ void MyAvatar::updateFromGyros(float deltaTime) {
|
|||
const float AVATAR_HEAD_PITCH_MAGNIFY = 1.0f;
|
||||
const float AVATAR_HEAD_YAW_MAGNIFY = 1.0f;
|
||||
const float AVATAR_HEAD_ROLL_MAGNIFY = 1.0f;
|
||||
_head.tweakPitch(estimatedRotation.x * AVATAR_HEAD_PITCH_MAGNIFY);
|
||||
_head.tweakYaw(estimatedRotation.y * AVATAR_HEAD_YAW_MAGNIFY);
|
||||
_head.tweakRoll(estimatedRotation.z * AVATAR_HEAD_ROLL_MAGNIFY);
|
||||
head->tweakPitch(estimatedRotation.x * AVATAR_HEAD_PITCH_MAGNIFY);
|
||||
head->tweakYaw(estimatedRotation.y * AVATAR_HEAD_YAW_MAGNIFY);
|
||||
head->tweakRoll(estimatedRotation.z * AVATAR_HEAD_ROLL_MAGNIFY);
|
||||
|
||||
// Update torso lean distance based on accelerometer data
|
||||
const float TORSO_LENGTH = 0.5f;
|
||||
glm::vec3 relativePosition = estimatedPosition - glm::vec3(0.0f, -TORSO_LENGTH, 0.0f);
|
||||
const float MAX_LEAN = 45.0f;
|
||||
_head.setLeanSideways(glm::clamp(glm::degrees(atanf(relativePosition.x * _leanScale / TORSO_LENGTH)),
|
||||
head->setLeanSideways(glm::clamp(glm::degrees(atanf(relativePosition.x * _leanScale / TORSO_LENGTH)),
|
||||
-MAX_LEAN, MAX_LEAN));
|
||||
_head.setLeanForward(glm::clamp(glm::degrees(atanf(relativePosition.z * _leanScale / TORSO_LENGTH)),
|
||||
head->setLeanForward(glm::clamp(glm::degrees(atanf(relativePosition.z * _leanScale / TORSO_LENGTH)),
|
||||
-MAX_LEAN, MAX_LEAN));
|
||||
|
||||
// if Faceshift drive is enabled, set the avatar drive based on the head position
|
||||
|
@ -401,11 +406,11 @@ void MyAvatar::updateFromGyros(float deltaTime) {
|
|||
}
|
||||
|
||||
// Move with Lean by applying thrust proportional to leaning
|
||||
glm::quat orientation = _head.getCameraOrientation();
|
||||
glm::quat orientation = head->getCameraOrientation();
|
||||
glm::vec3 front = orientation * IDENTITY_FRONT;
|
||||
glm::vec3 right = orientation * IDENTITY_RIGHT;
|
||||
float leanForward = _head.getLeanForward();
|
||||
float leanSideways = _head.getLeanSideways();
|
||||
float leanForward = head->getLeanForward();
|
||||
float leanSideways = head->getLeanSideways();
|
||||
|
||||
// Degrees of 'dead zone' when leaning, and amount of acceleration to apply to lean angle
|
||||
const float LEAN_FWD_DEAD_ZONE = 15.f;
|
||||
|
@ -436,7 +441,7 @@ static TextRenderer* textRenderer() {
|
|||
|
||||
void MyAvatar::renderDebugBodyPoints() {
|
||||
glm::vec3 torsoPosition(getPosition());
|
||||
glm::vec3 headPosition(getHead().getEyePosition());
|
||||
glm::vec3 headPosition(getHead()->getEyePosition());
|
||||
float torsoToHead = glm::length(headPosition - torsoPosition);
|
||||
glm::vec3 position;
|
||||
printf("head-above-torso %.2f, scale = %0.2f\n", torsoToHead, getScale());
|
||||
|
@ -462,7 +467,10 @@ void MyAvatar::renderDebugBodyPoints() {
|
|||
void MyAvatar::render(bool forceRenderHead) {
|
||||
|
||||
// render body
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::CollisionProxies)) {
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::RenderSkeletonCollisionProxies)) {
|
||||
_skeletonModel.renderCollisionProxies(1.f);
|
||||
}
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::RenderHeadCollisionProxies)) {
|
||||
_skeletonModel.renderCollisionProxies(1.f);
|
||||
}
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Avatars)) {
|
||||
|
@ -479,7 +487,7 @@ void MyAvatar::render(bool forceRenderHead) {
|
|||
}
|
||||
glPushMatrix();
|
||||
|
||||
glm::vec3 chatPosition = getHead().getEyePosition() + getBodyUpDirection() * CHAT_MESSAGE_HEIGHT * _scale;
|
||||
glm::vec3 chatPosition = getHead()->getEyePosition() + getBodyUpDirection() * CHAT_MESSAGE_HEIGHT * _scale;
|
||||
glTranslatef(chatPosition.x, chatPosition.y, chatPosition.z);
|
||||
glm::quat chatRotation = Application::getInstance()->getCamera()->getRotation();
|
||||
glm::vec3 chatAxis = glm::axis(chatRotation);
|
||||
|
@ -589,13 +597,13 @@ void MyAvatar::saveData(QSettings* settings) {
|
|||
settings->setValue("bodyPitch", _bodyPitch);
|
||||
settings->setValue("bodyRoll", _bodyRoll);
|
||||
|
||||
settings->setValue("headPitch", _head.getPitch());
|
||||
settings->setValue("headPitch", getHead()->getPitch());
|
||||
|
||||
settings->setValue("position_x", _position.x);
|
||||
settings->setValue("position_y", _position.y);
|
||||
settings->setValue("position_z", _position.z);
|
||||
|
||||
settings->setValue("pupilDilation", _head.getPupilDilation());
|
||||
settings->setValue("pupilDilation", getHead()->getPupilDilation());
|
||||
|
||||
settings->setValue("leanScale", _leanScale);
|
||||
settings->setValue("scale", _targetScale);
|
||||
|
@ -614,13 +622,13 @@ void MyAvatar::loadData(QSettings* settings) {
|
|||
_bodyPitch = loadSetting(settings, "bodyPitch", 0.0f);
|
||||
_bodyRoll = loadSetting(settings, "bodyRoll", 0.0f);
|
||||
|
||||
_head.setPitch(loadSetting(settings, "headPitch", 0.0f));
|
||||
getHead()->setPitch(loadSetting(settings, "headPitch", 0.0f));
|
||||
|
||||
_position.x = loadSetting(settings, "position_x", 0.0f);
|
||||
_position.y = loadSetting(settings, "position_y", 0.0f);
|
||||
_position.z = loadSetting(settings, "position_z", 0.0f);
|
||||
|
||||
_head.setPupilDilation(loadSetting(settings, "pupilDilation", 0.0f));
|
||||
getHead()->setPupilDilation(loadSetting(settings, "pupilDilation", 0.0f));
|
||||
|
||||
_leanScale = loadSetting(settings, "leanScale", 0.05f);
|
||||
_targetScale = loadSetting(settings, "scale", 1.0f);
|
||||
|
@ -655,9 +663,9 @@ void MyAvatar::orbit(const glm::vec3& position, int deltaX, int deltaY) {
|
|||
setOrientation(orientation);
|
||||
|
||||
// then vertically
|
||||
float oldPitch = _head.getPitch();
|
||||
_head.setPitch(oldPitch + deltaY * -ANGULAR_SCALE);
|
||||
rotation = glm::angleAxis(_head.getPitch() - oldPitch, orientation * IDENTITY_RIGHT);
|
||||
float oldPitch = getHead()->getPitch();
|
||||
getHead()->setPitch(oldPitch + deltaY * -ANGULAR_SCALE);
|
||||
rotation = glm::angleAxis(getHead()->getPitch() - oldPitch, orientation * IDENTITY_RIGHT);
|
||||
|
||||
setPosition(position + rotation * (getPosition() - position));
|
||||
}
|
||||
|
@ -677,8 +685,8 @@ void MyAvatar::updateLookAtTargetAvatar(glm::vec3 &eyePosition) {
|
|||
float distance;
|
||||
if (avatar->findRayIntersection(mouseOrigin, mouseDirection, distance)) {
|
||||
// rescale to compensate for head embiggening
|
||||
eyePosition = (avatar->getHead().calculateAverageEyePosition() - avatar->getHead().getScalePivot()) *
|
||||
(avatar->getScale() / avatar->getHead().getScale()) + avatar->getHead().getScalePivot();
|
||||
eyePosition = (avatar->getHead()->calculateAverageEyePosition() - avatar->getHead()->getScalePivot()) *
|
||||
(avatar->getScale() / avatar->getHead()->getScale()) + avatar->getHead()->getScalePivot();
|
||||
_lookAtTargetAvatar = avatarPointer;
|
||||
return;
|
||||
}
|
||||
|
@ -692,7 +700,8 @@ void MyAvatar::clearLookAtTargetAvatar() {
|
|||
}
|
||||
|
||||
float MyAvatar::getAbsoluteHeadYaw() const {
|
||||
return glm::yaw(_head.getOrientation());
|
||||
const Head* head = static_cast<const Head*>(_headData);
|
||||
return glm::yaw(head->getOrientation());
|
||||
}
|
||||
|
||||
glm::vec3 MyAvatar::getUprightHeadPosition() const {
|
||||
|
@ -706,17 +715,17 @@ void MyAvatar::renderBody(bool forceRenderHead) {
|
|||
// Render head so long as the camera isn't inside it
|
||||
const float RENDER_HEAD_CUTOFF_DISTANCE = 0.10f;
|
||||
Camera* myCamera = Application::getInstance()->getCamera();
|
||||
if (forceRenderHead || (glm::length(myCamera->getPosition() - _head.calculateAverageEyePosition()) > RENDER_HEAD_CUTOFF_DISTANCE)) {
|
||||
_head.render(1.0f);
|
||||
if (forceRenderHead || (glm::length(myCamera->getPosition() - getHead()->calculateAverageEyePosition()) > RENDER_HEAD_CUTOFF_DISTANCE)) {
|
||||
getHead()->render(1.0f);
|
||||
}
|
||||
_hand.render(true);
|
||||
getHand()->render(true);
|
||||
}
|
||||
|
||||
void MyAvatar::updateThrust(float deltaTime) {
|
||||
//
|
||||
// Gather thrust information from keyboard and sensors to apply to avatar motion
|
||||
//
|
||||
glm::quat orientation = getHead().getCameraOrientation();
|
||||
glm::quat orientation = getHead()->getCameraOrientation();
|
||||
glm::vec3 front = orientation * IDENTITY_FRONT;
|
||||
glm::vec3 right = orientation * IDENTITY_RIGHT;
|
||||
glm::vec3 up = orientation * IDENTITY_UP;
|
||||
|
@ -737,7 +746,7 @@ void MyAvatar::updateThrust(float deltaTime) {
|
|||
_thrust -= _driveKeys[DOWN] * _scale * THRUST_MAG_DOWN * _thrustMultiplier * deltaTime * up;
|
||||
_bodyYawDelta -= _driveKeys[ROT_RIGHT] * YAW_MAG * deltaTime;
|
||||
_bodyYawDelta += _driveKeys[ROT_LEFT] * YAW_MAG * deltaTime;
|
||||
_head.setPitch(_head.getPitch() + (_driveKeys[ROT_UP] - _driveKeys[ROT_DOWN]) * PITCH_MAG * deltaTime);
|
||||
getHead()->setPitch(getHead()->getPitch() + (_driveKeys[ROT_UP] - _driveKeys[ROT_DOWN]) * PITCH_MAG * deltaTime);
|
||||
|
||||
// If thrust keys are being held down, slowly increase thrust to allow reaching great speeds
|
||||
if (_driveKeys[FWD] || _driveKeys[BACK] || _driveKeys[RIGHT] || _driveKeys[LEFT] || _driveKeys[UP] || _driveKeys[DOWN]) {
|
||||
|
@ -1002,10 +1011,10 @@ void MyAvatar::updateCollisionWithAvatars(float deltaTime) {
|
|||
}
|
||||
|
||||
// collide our hands against them
|
||||
_hand.collideAgainstAvatar(avatar, true);
|
||||
getHand()->collideAgainstAvatar(avatar, true);
|
||||
|
||||
// collide their hands against us
|
||||
avatar->getHand().collideAgainstAvatar(this, false);
|
||||
avatar->getHand()->collideAgainstAvatar(this, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1120,7 +1129,7 @@ void MyAvatar::updateChatCircle(float deltaTime) {
|
|||
|
||||
void MyAvatar::setGravity(glm::vec3 gravity) {
|
||||
_gravity = gravity;
|
||||
_head.setGravity(_gravity);
|
||||
getHead()->setGravity(_gravity);
|
||||
|
||||
// use the gravity to determine the new world up direction, if possible
|
||||
float gravityLength = glm::length(gravity);
|
||||
|
|
|
@ -86,7 +86,6 @@ public:
|
|||
|
||||
public slots:
|
||||
void goHome();
|
||||
void setWantCollisionsOn(bool wantCollisionsOn) { _isCollisionsOn = wantCollisionsOn; }
|
||||
void increaseSize();
|
||||
void decreaseSize();
|
||||
void resetSize();
|
||||
|
@ -110,7 +109,6 @@ private:
|
|||
float _elapsedTimeSinceCollision;
|
||||
glm::vec3 _lastCollisionPosition;
|
||||
bool _speedBrakes;
|
||||
bool _isCollisionsOn;
|
||||
bool _isThrustOn;
|
||||
float _thrustMultiplier;
|
||||
glm::vec3 _moveTarget;
|
||||
|
|
|
@ -8,10 +8,9 @@
|
|||
|
||||
#include <glm/gtx/transform.hpp>
|
||||
|
||||
#include <HandData.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "Avatar.h"
|
||||
#include "Hand.h"
|
||||
#include "Menu.h"
|
||||
#include "SkeletonModel.h"
|
||||
|
||||
|
@ -33,8 +32,8 @@ void SkeletonModel::simulate(float deltaTime) {
|
|||
|
||||
// find the left and rightmost active Leap palms
|
||||
int leftPalmIndex, rightPalmIndex;
|
||||
HandData& hand = _owningAvatar->getHand();
|
||||
hand.getLeftRightPalmIndices(leftPalmIndex, rightPalmIndex);
|
||||
Hand* hand = _owningAvatar->getHand();
|
||||
hand->getLeftRightPalmIndices(leftPalmIndex, rightPalmIndex);
|
||||
|
||||
const float HAND_RESTORATION_PERIOD = 1.f; // seconds
|
||||
float handRestorePercent = glm::clamp(deltaTime / HAND_RESTORATION_PERIOD, 0.f, 1.f);
|
||||
|
@ -52,14 +51,14 @@ void SkeletonModel::simulate(float deltaTime) {
|
|||
} else if (leftPalmIndex == rightPalmIndex) {
|
||||
// right hand only
|
||||
applyPalmData(geometry.rightHandJointIndex, geometry.rightFingerJointIndices, geometry.rightFingertipJointIndices,
|
||||
hand.getPalms()[leftPalmIndex]);
|
||||
hand->getPalms()[leftPalmIndex]);
|
||||
restoreLeftHandPosition(handRestorePercent);
|
||||
|
||||
} else {
|
||||
applyPalmData(geometry.leftHandJointIndex, geometry.leftFingerJointIndices, geometry.leftFingertipJointIndices,
|
||||
hand.getPalms()[leftPalmIndex]);
|
||||
hand->getPalms()[leftPalmIndex]);
|
||||
applyPalmData(geometry.rightHandJointIndex, geometry.rightFingerJointIndices, geometry.rightFingertipJointIndices,
|
||||
hand.getPalms()[rightPalmIndex]);
|
||||
hand->getPalms()[rightPalmIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -182,8 +181,8 @@ void SkeletonModel::maybeUpdateLeanRotation(const JointState& parentState, const
|
|||
glm::mat3 axes = glm::mat3_cast(_rotation);
|
||||
glm::mat3 inverse = glm::mat3(glm::inverse(parentState.transform * glm::translate(state.translation) *
|
||||
joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation)));
|
||||
state.rotation = glm::angleAxis(-_owningAvatar->getHead().getLeanSideways(), glm::normalize(inverse * axes[2])) *
|
||||
glm::angleAxis(-_owningAvatar->getHead().getLeanForward(), glm::normalize(inverse * axes[0])) * joint.rotation;
|
||||
state.rotation = glm::angleAxis(-_owningAvatar->getHead()->getLeanSideways(), glm::normalize(inverse * axes[2])) *
|
||||
glm::angleAxis(-_owningAvatar->getHead()->getLeanForward(), glm::normalize(inverse * axes[0])) * joint.rotation;
|
||||
}
|
||||
|
||||
void SkeletonModel::stretchArm(int jointIndex, const glm::vec3& position) {
|
||||
|
|
|
@ -45,7 +45,7 @@ void SixenseManager::update(float deltaTime) {
|
|||
return;
|
||||
}
|
||||
MyAvatar* avatar = Application::getInstance()->getAvatar();
|
||||
Hand& hand = avatar->getHand();
|
||||
Hand* hand = avatar->getHand();
|
||||
|
||||
int maxControllers = sixenseGetMaxControllers();
|
||||
for (int i = 0; i < maxControllers; i++) {
|
||||
|
@ -60,16 +60,16 @@ void SixenseManager::update(float deltaTime) {
|
|||
// Either find a palm matching the sixense controller, or make a new one
|
||||
PalmData* palm;
|
||||
bool foundHand = false;
|
||||
for (int j = 0; j < hand.getNumPalms(); j++) {
|
||||
if (hand.getPalms()[j].getSixenseID() == data.controller_index) {
|
||||
palm = &hand.getPalms()[j];
|
||||
for (int j = 0; j < hand->getNumPalms(); j++) {
|
||||
if (hand->getPalms()[j].getSixenseID() == data.controller_index) {
|
||||
palm = &(hand->getPalms()[j]);
|
||||
foundHand = true;
|
||||
}
|
||||
}
|
||||
if (!foundHand) {
|
||||
PalmData newPalm(&hand);
|
||||
hand.getPalms().push_back(newPalm);
|
||||
palm = &hand.getPalms()[hand.getNumPalms() - 1];
|
||||
PalmData newPalm(hand);
|
||||
hand->getPalms().push_back(newPalm);
|
||||
palm = &(hand->getPalms()[hand->getNumPalms() - 1]);
|
||||
palm->setSixenseID(data.controller_index);
|
||||
printf("Found new Sixense controller, ID %i\n", data.controller_index);
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ void SixenseManager::update(float deltaTime) {
|
|||
}
|
||||
|
||||
// initialize the "finger" based on the direction
|
||||
FingerData finger(palm, &hand);
|
||||
FingerData finger(palm, hand);
|
||||
finger.setActive(true);
|
||||
finger.setRawRootPosition(position);
|
||||
const float FINGER_LENGTH = 300.0f; // Millimeters
|
||||
|
@ -130,7 +130,7 @@ void SixenseManager::update(float deltaTime) {
|
|||
// if the controllers haven't been moved in a while, disable
|
||||
const int MOVEMENT_DISABLE_DURATION = 30 * 1000 * 1000;
|
||||
if (usecTimestampNow() - _lastMovement > MOVEMENT_DISABLE_DURATION) {
|
||||
for (vector<PalmData>::iterator it = hand.getPalms().begin(); it != hand.getPalms().end(); it++) {
|
||||
for (vector<PalmData>::iterator it = hand->getPalms().begin(); it != hand->getPalms().end(); it++) {
|
||||
it->setActive(false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1405,6 +1405,11 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
|||
cluster.jointIndex = 0;
|
||||
}
|
||||
extracted.mesh.clusters.append(cluster);
|
||||
// BUG: joints that fall into this context do not get their bindTransform and
|
||||
// inverseBindRotation data members properly set. This causes bad boneRadius
|
||||
// and boneLength calculations for collision proxies. Affected joints are usually:
|
||||
// hair, teeth, tongue. I tried to figure out how to fix this but was going
|
||||
// crosseyed trying to understand FBX so I gave up for the time being -- Andrew.
|
||||
}
|
||||
|
||||
// whether we're skinned depends on how many clusters are attached
|
||||
|
|
|
@ -64,7 +64,7 @@ void Snapshot::saveSnapshot(QGLWidget* widget, Profile* profile, Avatar* avatar)
|
|||
QImage shot = widget->grabFrameBuffer();
|
||||
|
||||
glm::vec3 location = avatar->getPosition();
|
||||
glm::quat orientation = avatar->getHead().getOrientation();
|
||||
glm::quat orientation = avatar->getHead()->getOrientation();
|
||||
|
||||
// add metadata
|
||||
shot.setText(LOCATION_X, QString::number(location.x));
|
||||
|
|
|
@ -63,10 +63,6 @@ QByteArray AvatarData::toByteArray() {
|
|||
if (!_headData) {
|
||||
_headData = new HeadData(this);
|
||||
}
|
||||
// lazily allocate memory for HandData in case we're not an Avatar instance
|
||||
if (!_handData) {
|
||||
_handData = new HandData(this);
|
||||
}
|
||||
|
||||
QByteArray avatarDataByteArray;
|
||||
avatarDataByteArray.resize(MAX_PACKET_SIZE);
|
||||
|
@ -152,8 +148,8 @@ QByteArray AvatarData::toByteArray() {
|
|||
// pupil dilation
|
||||
destinationBuffer += packFloatToByte(destinationBuffer, _headData->_pupilDilation, 1.0f);
|
||||
|
||||
// leap hand data
|
||||
destinationBuffer += _handData->encodeRemoteData(destinationBuffer);
|
||||
// hand data
|
||||
destinationBuffer += HandData::encodeData(_handData, destinationBuffer);
|
||||
|
||||
return avatarDataByteArray.left(destinationBuffer - startPosition);
|
||||
}
|
||||
|
@ -259,7 +255,7 @@ int AvatarData::parseData(const QByteArray& packet) {
|
|||
// pupil dilation
|
||||
sourceBuffer += unpackFloatFromByte(sourceBuffer, _headData->_pupilDilation, 1.0f);
|
||||
|
||||
// leap hand data
|
||||
// hand data
|
||||
if (sourceBuffer - startPosition < packet.size()) {
|
||||
// check passed, bytes match
|
||||
sourceBuffer += _handData->decodeRemoteData(packet.mid(sourceBuffer - startPosition));
|
||||
|
|
|
@ -139,9 +139,6 @@ public:
|
|||
const HeadData* getHeadData() const { return _headData; }
|
||||
const HandData* getHandData() const { return _handData; }
|
||||
|
||||
void setHeadData(HeadData* headData) { _headData = headData; }
|
||||
void setHandData(HandData* handData) { _handData = handData; }
|
||||
|
||||
virtual const glm::vec3& getVelocity() const { return vec3Zero; }
|
||||
|
||||
virtual bool findParticleCollisions(const glm::vec3& particleCenter, float particleRadius, CollisionList& collisions) {
|
||||
|
|
|
@ -113,17 +113,30 @@ _owningHandData(owningHandData)
|
|||
setTrailLength(standardTrailLength);
|
||||
}
|
||||
|
||||
// static
|
||||
int HandData::encodeData(HandData* hand, unsigned char* destinationBuffer) {
|
||||
if (hand) {
|
||||
return hand->encodeRemoteData(destinationBuffer);
|
||||
}
|
||||
// else encode empty data:
|
||||
// One byte for zero hands
|
||||
// One byte for error checking.
|
||||
*destinationBuffer = 0;
|
||||
*(destinationBuffer + 1) = 1;
|
||||
return 2;
|
||||
}
|
||||
|
||||
int HandData::encodeRemoteData(unsigned char* destinationBuffer) {
|
||||
const unsigned char* startPosition = destinationBuffer;
|
||||
|
||||
unsigned int numHands = 0;
|
||||
unsigned int numPalms = 0;
|
||||
for (unsigned int handIndex = 0; handIndex < getNumPalms(); ++handIndex) {
|
||||
PalmData& palm = getPalms()[handIndex];
|
||||
if (palm.isActive()) {
|
||||
numHands++;
|
||||
numPalms++;
|
||||
}
|
||||
}
|
||||
*destinationBuffer++ = numHands;
|
||||
*destinationBuffer++ = numPalms;
|
||||
|
||||
for (unsigned int handIndex = 0; handIndex < getNumPalms(); ++handIndex) {
|
||||
PalmData& palm = getPalms()[handIndex];
|
||||
|
@ -162,9 +175,9 @@ int HandData::encodeRemoteData(unsigned char* destinationBuffer) {
|
|||
int HandData::decodeRemoteData(const QByteArray& dataByteArray) {
|
||||
const unsigned char* startPosition;
|
||||
const unsigned char* sourceBuffer = startPosition = reinterpret_cast<const unsigned char*>(dataByteArray.data());
|
||||
unsigned int numHands = *sourceBuffer++;
|
||||
unsigned int numPalms = *sourceBuffer++;
|
||||
|
||||
for (unsigned int handIndex = 0; handIndex < numHands; ++handIndex) {
|
||||
for (unsigned int handIndex = 0; handIndex < numPalms; ++handIndex) {
|
||||
if (handIndex >= getNumPalms())
|
||||
addNewPalm();
|
||||
PalmData& palm = getPalms()[handIndex];
|
||||
|
@ -203,7 +216,7 @@ int HandData::decodeRemoteData(const QByteArray& dataByteArray) {
|
|||
}
|
||||
}
|
||||
// Turn off any hands which weren't used.
|
||||
for (unsigned int handIndex = numHands; handIndex < getNumPalms(); ++handIndex) {
|
||||
for (unsigned int handIndex = numPalms; handIndex < getNumPalms(); ++handIndex) {
|
||||
PalmData& palm = getPalms()[handIndex];
|
||||
palm.setActive(false);
|
||||
}
|
||||
|
|
|
@ -71,6 +71,8 @@ public:
|
|||
void setFingerTrailLength(unsigned int length);
|
||||
void updateFingerTrails();
|
||||
|
||||
static int encodeData(HandData* hand, unsigned char* destinationBuffer);
|
||||
|
||||
// Use these for sending and receiving hand data
|
||||
int encodeRemoteData(unsigned char* destinationBuffer);
|
||||
int decodeRemoteData(const QByteArray& dataByteArray);
|
||||
|
|
Loading…
Reference in a new issue