mirror of
https://github.com/overte-org/overte.git
synced 2025-08-10 01:00:44 +02:00
remove old/unused eyetracker code.
This commit is contained in:
parent
5c570d28a0
commit
a288c0a52d
6 changed files with 284 additions and 162 deletions
|
@ -60,6 +60,7 @@
|
||||||
#include <shared/QtHelpers.h>
|
#include <shared/QtHelpers.h>
|
||||||
#include <shared/PlatformHelper.h>
|
#include <shared/PlatformHelper.h>
|
||||||
#include <shared/GlobalAppProperties.h>
|
#include <shared/GlobalAppProperties.h>
|
||||||
|
#include <GeometryUtil.h>
|
||||||
#include <StatTracker.h>
|
#include <StatTracker.h>
|
||||||
#include <Trace.h>
|
#include <Trace.h>
|
||||||
#include <ResourceScriptingInterface.h>
|
#include <ResourceScriptingInterface.h>
|
||||||
|
@ -154,7 +155,6 @@
|
||||||
#include <display-plugins/CompositorHelper.h>
|
#include <display-plugins/CompositorHelper.h>
|
||||||
#include <display-plugins/hmd/HmdDisplayPlugin.h>
|
#include <display-plugins/hmd/HmdDisplayPlugin.h>
|
||||||
#include <display-plugins/RefreshRateController.h>
|
#include <display-plugins/RefreshRateController.h>
|
||||||
#include <trackers/EyeTracker.h>
|
|
||||||
#include <avatars-renderer/ScriptAvatar.h>
|
#include <avatars-renderer/ScriptAvatar.h>
|
||||||
#include <RenderableEntityItem.h>
|
#include <RenderableEntityItem.h>
|
||||||
#include <RenderableTextEntityItem.h>
|
#include <RenderableTextEntityItem.h>
|
||||||
|
@ -878,7 +878,6 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
||||||
DependencyManager::set<DdeFaceTracker>();
|
DependencyManager::set<DdeFaceTracker>();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DependencyManager::set<EyeTracker>();
|
|
||||||
DependencyManager::set<AudioClient>();
|
DependencyManager::set<AudioClient>();
|
||||||
DependencyManager::set<AudioScope>();
|
DependencyManager::set<AudioScope>();
|
||||||
DependencyManager::set<DeferredLightingEffect>();
|
DependencyManager::set<DeferredLightingEffect>();
|
||||||
|
@ -1997,12 +1996,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
connect(ddeTracker.data(), &FaceTracker::muteToggled, this, &Application::faceTrackerMuteToggled);
|
connect(ddeTracker.data(), &FaceTracker::muteToggled, this, &Application::faceTrackerMuteToggled);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_IVIEWHMD
|
|
||||||
auto eyeTracker = DependencyManager::get<EyeTracker>();
|
|
||||||
eyeTracker->init();
|
|
||||||
setActiveEyeTracker();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// If launched from Steam, let it handle updates
|
// If launched from Steam, let it handle updates
|
||||||
const QString HIFI_NO_UPDATER_COMMAND_LINE_KEY = "--no-updater";
|
const QString HIFI_NO_UPDATER_COMMAND_LINE_KEY = "--no-updater";
|
||||||
bool noUpdater = arguments().indexOf(HIFI_NO_UPDATER_COMMAND_LINE_KEY) != -1;
|
bool noUpdater = arguments().indexOf(HIFI_NO_UPDATER_COMMAND_LINE_KEY) != -1;
|
||||||
|
@ -2746,9 +2739,6 @@ void Application::cleanupBeforeQuit() {
|
||||||
// Stop third party processes so that they're not left running in the event of a subsequent shutdown crash.
|
// Stop third party processes so that they're not left running in the event of a subsequent shutdown crash.
|
||||||
#ifdef HAVE_DDE
|
#ifdef HAVE_DDE
|
||||||
DependencyManager::get<DdeFaceTracker>()->setEnabled(false);
|
DependencyManager::get<DdeFaceTracker>()->setEnabled(false);
|
||||||
#endif
|
|
||||||
#ifdef HAVE_IVIEWHMD
|
|
||||||
DependencyManager::get<EyeTracker>()->setEnabled(false, true);
|
|
||||||
#endif
|
#endif
|
||||||
AnimDebugDraw::getInstance().shutdown();
|
AnimDebugDraw::getInstance().shutdown();
|
||||||
|
|
||||||
|
@ -2823,9 +2813,6 @@ void Application::cleanupBeforeQuit() {
|
||||||
#ifdef HAVE_DDE
|
#ifdef HAVE_DDE
|
||||||
DependencyManager::destroy<DdeFaceTracker>();
|
DependencyManager::destroy<DdeFaceTracker>();
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_IVIEWHMD
|
|
||||||
DependencyManager::destroy<EyeTracker>();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
DependencyManager::destroy<ContextOverlayInterface>(); // Must be destroyed before TabletScriptingInterface
|
DependencyManager::destroy<ContextOverlayInterface>(); // Must be destroyed before TabletScriptingInterface
|
||||||
|
|
||||||
|
@ -2834,7 +2821,7 @@ void Application::cleanupBeforeQuit() {
|
||||||
DependencyManager::destroy<TabletScriptingInterface>();
|
DependencyManager::destroy<TabletScriptingInterface>();
|
||||||
DependencyManager::destroy<ToolbarScriptingInterface>();
|
DependencyManager::destroy<ToolbarScriptingInterface>();
|
||||||
DependencyManager::destroy<OffscreenUi>();
|
DependencyManager::destroy<OffscreenUi>();
|
||||||
|
|
||||||
DependencyManager::destroy<OffscreenQmlSurfaceCache>();
|
DependencyManager::destroy<OffscreenQmlSurfaceCache>();
|
||||||
|
|
||||||
_snapshotSoundInjector = nullptr;
|
_snapshotSoundInjector = nullptr;
|
||||||
|
@ -5328,35 +5315,6 @@ void Application::setActiveFaceTracker() const {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_IVIEWHMD
|
|
||||||
void Application::setActiveEyeTracker() {
|
|
||||||
auto eyeTracker = DependencyManager::get<EyeTracker>();
|
|
||||||
if (!eyeTracker->isInitialized()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isEyeTracking = Menu::getInstance()->isOptionChecked(MenuOption::SMIEyeTracking);
|
|
||||||
bool isSimulating = Menu::getInstance()->isOptionChecked(MenuOption::SimulateEyeTracking);
|
|
||||||
eyeTracker->setEnabled(isEyeTracking, isSimulating);
|
|
||||||
|
|
||||||
Menu::getInstance()->getActionForOption(MenuOption::OnePointCalibration)->setEnabled(isEyeTracking && !isSimulating);
|
|
||||||
Menu::getInstance()->getActionForOption(MenuOption::ThreePointCalibration)->setEnabled(isEyeTracking && !isSimulating);
|
|
||||||
Menu::getInstance()->getActionForOption(MenuOption::FivePointCalibration)->setEnabled(isEyeTracking && !isSimulating);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::calibrateEyeTracker1Point() {
|
|
||||||
DependencyManager::get<EyeTracker>()->calibrate(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::calibrateEyeTracker3Points() {
|
|
||||||
DependencyManager::get<EyeTracker>()->calibrate(3);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::calibrateEyeTracker5Points() {
|
|
||||||
DependencyManager::get<EyeTracker>()->calibrate(5);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool Application::exportEntities(const QString& filename,
|
bool Application::exportEntities(const QString& filename,
|
||||||
const QVector<QUuid>& entityIDs,
|
const QVector<QUuid>& entityIDs,
|
||||||
const glm::vec3* givenOffset) {
|
const glm::vec3* givenOffset) {
|
||||||
|
@ -5830,8 +5788,8 @@ void Application::pushPostUpdateLambda(void* key, const std::function<void()>& f
|
||||||
_postUpdateLambdas[key] = func;
|
_postUpdateLambdas[key] = func;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called during Application::update immediately before AvatarManager::updateMyAvatar, updating my data that is then sent to everyone.
|
// Called during Application::update immediately before AvatarManager::updateMyAvatar, updating my data that is then sent
|
||||||
// (Maybe this code should be moved there?)
|
// to everyone.
|
||||||
// The principal result is to call updateLookAtTargetAvatar() and then setLookAtPosition().
|
// The principal result is to call updateLookAtTargetAvatar() and then setLookAtPosition().
|
||||||
// Note that it is called BEFORE we update position or joints based on sensors, etc.
|
// Note that it is called BEFORE we update position or joints based on sensors, etc.
|
||||||
void Application::updateMyAvatarLookAtPosition() {
|
void Application::updateMyAvatarLookAtPosition() {
|
||||||
|
@ -5840,91 +5798,8 @@ void Application::updateMyAvatarLookAtPosition() {
|
||||||
PerformanceWarning warn(showWarnings, "Application::updateMyAvatarLookAtPosition()");
|
PerformanceWarning warn(showWarnings, "Application::updateMyAvatarLookAtPosition()");
|
||||||
|
|
||||||
auto myAvatar = getMyAvatar();
|
auto myAvatar = getMyAvatar();
|
||||||
myAvatar->updateLookAtTargetAvatar();
|
|
||||||
FaceTracker* faceTracker = getActiveFaceTracker();
|
FaceTracker* faceTracker = getActiveFaceTracker();
|
||||||
auto eyeTracker = DependencyManager::get<EyeTracker>();
|
myAvatar->updateLookAtPosition(faceTracker, _myCamera);
|
||||||
|
|
||||||
bool isLookingAtSomeone = false;
|
|
||||||
bool isHMD = qApp->isHMDMode();
|
|
||||||
glm::vec3 lookAtSpot;
|
|
||||||
if (eyeTracker->isTracking() && (isHMD || eyeTracker->isSimulating())) {
|
|
||||||
// Look at the point that the user is looking at.
|
|
||||||
glm::vec3 lookAtPosition = eyeTracker->getLookAtPosition();
|
|
||||||
if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
|
|
||||||
lookAtPosition.x = -lookAtPosition.x;
|
|
||||||
}
|
|
||||||
if (isHMD) {
|
|
||||||
// TODO -- this code is probably wrong, getHeadPose() returns something in sensor frame, not avatar
|
|
||||||
glm::mat4 headPose = getActiveDisplayPlugin()->getHeadPose();
|
|
||||||
glm::quat hmdRotation = glm::quat_cast(headPose);
|
|
||||||
lookAtSpot = _myCamera.getPosition() + myAvatar->getWorldOrientation() * (hmdRotation * lookAtPosition);
|
|
||||||
} else {
|
|
||||||
lookAtSpot = myAvatar->getHead()->getEyePosition()
|
|
||||||
+ (myAvatar->getHead()->getFinalOrientationInWorldFrame() * lookAtPosition);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
AvatarSharedPointer lookingAt = myAvatar->getLookAtTargetAvatar().lock();
|
|
||||||
bool haveLookAtCandidate = lookingAt && myAvatar.get() != lookingAt.get();
|
|
||||||
auto avatar = static_pointer_cast<Avatar>(lookingAt);
|
|
||||||
bool mutualLookAtSnappingEnabled = avatar && avatar->getLookAtSnappingEnabled() && myAvatar->getLookAtSnappingEnabled();
|
|
||||||
if (haveLookAtCandidate && mutualLookAtSnappingEnabled) {
|
|
||||||
// If I am looking at someone else, look directly at one of their eyes
|
|
||||||
isLookingAtSomeone = true;
|
|
||||||
auto lookingAtHead = avatar->getHead();
|
|
||||||
|
|
||||||
const float MAXIMUM_FACE_ANGLE = 65.0f * RADIANS_PER_DEGREE;
|
|
||||||
glm::vec3 lookingAtFaceOrientation = lookingAtHead->getFinalOrientationInWorldFrame() * IDENTITY_FORWARD;
|
|
||||||
glm::vec3 fromLookingAtToMe = glm::normalize(myAvatar->getHead()->getEyePosition()
|
|
||||||
- lookingAtHead->getEyePosition());
|
|
||||||
float faceAngle = glm::angle(lookingAtFaceOrientation, fromLookingAtToMe);
|
|
||||||
|
|
||||||
if (faceAngle < MAXIMUM_FACE_ANGLE) {
|
|
||||||
// Randomly look back and forth between look targets
|
|
||||||
eyeContactTarget target = Menu::getInstance()->isOptionChecked(MenuOption::FixGaze) ?
|
|
||||||
LEFT_EYE : myAvatar->getEyeContactTarget();
|
|
||||||
switch (target) {
|
|
||||||
case LEFT_EYE:
|
|
||||||
lookAtSpot = lookingAtHead->getLeftEyePosition();
|
|
||||||
break;
|
|
||||||
case RIGHT_EYE:
|
|
||||||
lookAtSpot = lookingAtHead->getRightEyePosition();
|
|
||||||
break;
|
|
||||||
case MOUTH:
|
|
||||||
lookAtSpot = lookingAtHead->getMouthPosition();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Just look at their head (mid point between eyes)
|
|
||||||
lookAtSpot = lookingAtHead->getEyePosition();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// I am not looking at anyone else, so just look forward
|
|
||||||
auto headPose = myAvatar->getControllerPoseInWorldFrame(controller::Action::HEAD);
|
|
||||||
if (headPose.isValid()) {
|
|
||||||
lookAtSpot = transformPoint(headPose.getMatrix(), glm::vec3(0.0f, 0.0f, TREE_SCALE));
|
|
||||||
} else {
|
|
||||||
lookAtSpot = myAvatar->getHead()->getEyePosition() +
|
|
||||||
(myAvatar->getHead()->getFinalOrientationInWorldFrame() * glm::vec3(0.0f, 0.0f, -TREE_SCALE));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deflect the eyes a bit to match the detected gaze from the face tracker if active.
|
|
||||||
if (faceTracker && !faceTracker->isMuted()) {
|
|
||||||
float eyePitch = faceTracker->getEstimatedEyePitch();
|
|
||||||
float eyeYaw = faceTracker->getEstimatedEyeYaw();
|
|
||||||
const float GAZE_DEFLECTION_REDUCTION_DURING_EYE_CONTACT = 0.1f;
|
|
||||||
glm::vec3 origin = myAvatar->getHead()->getEyePosition();
|
|
||||||
float deflection = faceTracker->getEyeDeflection();
|
|
||||||
if (isLookingAtSomeone) {
|
|
||||||
deflection *= GAZE_DEFLECTION_REDUCTION_DURING_EYE_CONTACT;
|
|
||||||
}
|
|
||||||
lookAtSpot = origin + _myCamera.getOrientation() * glm::quat(glm::radians(glm::vec3(
|
|
||||||
eyePitch * deflection, eyeYaw * deflection, 0.0f))) *
|
|
||||||
glm::inverse(_myCamera.getOrientation()) * (lookAtSpot - origin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
myAvatar->getHead()->setLookAtPosition(lookAtSpot);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::updateThreads(float deltaTime) {
|
void Application::updateThreads(float deltaTime) {
|
||||||
|
@ -6496,7 +6371,10 @@ void Application::update(float deltaTime) {
|
||||||
controller::Action::LEFT_UP_LEG,
|
controller::Action::LEFT_UP_LEG,
|
||||||
controller::Action::RIGHT_UP_LEG,
|
controller::Action::RIGHT_UP_LEG,
|
||||||
controller::Action::LEFT_TOE_BASE,
|
controller::Action::LEFT_TOE_BASE,
|
||||||
controller::Action::RIGHT_TOE_BASE
|
controller::Action::RIGHT_TOE_BASE,
|
||||||
|
controller::Action::LEFT_EYE,
|
||||||
|
controller::Action::RIGHT_EYE
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// copy controller poses from userInputMapper to myAvatar.
|
// copy controller poses from userInputMapper to myAvatar.
|
||||||
|
@ -7171,8 +7049,7 @@ void Application::resetSensors(bool andReload) {
|
||||||
#ifdef HAVE_DDE
|
#ifdef HAVE_DDE
|
||||||
DependencyManager::get<DdeFaceTracker>()->reset();
|
DependencyManager::get<DdeFaceTracker>()->reset();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DependencyManager::get<EyeTracker>()->reset();
|
|
||||||
_overlayConductor.centerUI();
|
_overlayConductor.centerUI();
|
||||||
getActiveDisplayPlugin()->resetSensors();
|
getActiveDisplayPlugin()->resetSensors();
|
||||||
getMyAvatar()->reset(true, andReload);
|
getMyAvatar()->reset(true, andReload);
|
||||||
|
|
|
@ -772,6 +772,18 @@ void MyAvatar::update(float deltaTime) {
|
||||||
emit energyChanged(currentEnergy);
|
emit energyChanged(currentEnergy);
|
||||||
|
|
||||||
updateEyeContactTarget(deltaTime);
|
updateEyeContactTarget(deltaTime);
|
||||||
|
|
||||||
|
// if we're getting eye rotations from a tracker, disable observer-side procedural eye motions
|
||||||
|
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||||
|
bool eyesTracked =
|
||||||
|
userInputMapper->getPoseState(controller::Action::LEFT_EYE).valid &&
|
||||||
|
userInputMapper->getPoseState(controller::Action::RIGHT_EYE).valid;
|
||||||
|
|
||||||
|
int leftEyeJointIndex = getJointIndex("LeftEye");
|
||||||
|
int rightEyeJointIndex = getJointIndex("RightEye");
|
||||||
|
bool eyesAreOverridden = getIsJointOverridden(leftEyeJointIndex) || getIsJointOverridden(rightEyeJointIndex);
|
||||||
|
|
||||||
|
_headData->setHasProceduralEyeMovement(!(eyesTracked || eyesAreOverridden));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::updateEyeContactTarget(float deltaTime) {
|
void MyAvatar::updateEyeContactTarget(float deltaTime) {
|
||||||
|
@ -1454,8 +1466,50 @@ void MyAvatar::setEnableDebugDrawHandControllers(bool isEnabled) {
|
||||||
_enableDebugDrawHandControllers = isEnabled;
|
_enableDebugDrawHandControllers = isEnabled;
|
||||||
|
|
||||||
if (!isEnabled) {
|
if (!isEnabled) {
|
||||||
DebugDraw::getInstance().removeMarker("leftHandController");
|
DebugDraw::getInstance().removeMarker("LEFT_HAND");
|
||||||
DebugDraw::getInstance().removeMarker("rightHandController");
|
DebugDraw::getInstance().removeMarker("RIGHT_HAND");
|
||||||
|
|
||||||
|
DebugDraw::getInstance().removeMarker("LEFT_HAND_THUMB1");
|
||||||
|
DebugDraw::getInstance().removeMarker("LEFT_HAND_THUMB2");
|
||||||
|
DebugDraw::getInstance().removeMarker("LEFT_HAND_THUMB3");
|
||||||
|
DebugDraw::getInstance().removeMarker("LEFT_HAND_THUMB4");
|
||||||
|
DebugDraw::getInstance().removeMarker("LEFT_HAND_INDEX1");
|
||||||
|
DebugDraw::getInstance().removeMarker("LEFT_HAND_INDEX2");
|
||||||
|
DebugDraw::getInstance().removeMarker("LEFT_HAND_INDEX3");
|
||||||
|
DebugDraw::getInstance().removeMarker("LEFT_HAND_INDEX4");
|
||||||
|
DebugDraw::getInstance().removeMarker("LEFT_HAND_MIDDLE1");
|
||||||
|
DebugDraw::getInstance().removeMarker("LEFT_HAND_MIDDLE2");
|
||||||
|
DebugDraw::getInstance().removeMarker("LEFT_HAND_MIDDLE3");
|
||||||
|
DebugDraw::getInstance().removeMarker("LEFT_HAND_MIDDLE4");
|
||||||
|
DebugDraw::getInstance().removeMarker("LEFT_HAND_RING1");
|
||||||
|
DebugDraw::getInstance().removeMarker("LEFT_HAND_RING2");
|
||||||
|
DebugDraw::getInstance().removeMarker("LEFT_HAND_RING3");
|
||||||
|
DebugDraw::getInstance().removeMarker("LEFT_HAND_RING4");
|
||||||
|
DebugDraw::getInstance().removeMarker("LEFT_HAND_PINKY1");
|
||||||
|
DebugDraw::getInstance().removeMarker("LEFT_HAND_PINKY2");
|
||||||
|
DebugDraw::getInstance().removeMarker("LEFT_HAND_PINKY3");
|
||||||
|
DebugDraw::getInstance().removeMarker("LEFT_HAND_PINKY4");
|
||||||
|
|
||||||
|
DebugDraw::getInstance().removeMarker("RIGHT_HAND_THUMB1");
|
||||||
|
DebugDraw::getInstance().removeMarker("RIGHT_HAND_THUMB2");
|
||||||
|
DebugDraw::getInstance().removeMarker("RIGHT_HAND_THUMB3");
|
||||||
|
DebugDraw::getInstance().removeMarker("RIGHT_HAND_THUMB4");
|
||||||
|
DebugDraw::getInstance().removeMarker("RIGHT_HAND_INDEX1");
|
||||||
|
DebugDraw::getInstance().removeMarker("RIGHT_HAND_INDEX2");
|
||||||
|
DebugDraw::getInstance().removeMarker("RIGHT_HAND_INDEX3");
|
||||||
|
DebugDraw::getInstance().removeMarker("RIGHT_HAND_INDEX4");
|
||||||
|
DebugDraw::getInstance().removeMarker("RIGHT_HAND_MIDDLE1");
|
||||||
|
DebugDraw::getInstance().removeMarker("RIGHT_HAND_MIDDLE2");
|
||||||
|
DebugDraw::getInstance().removeMarker("RIGHT_HAND_MIDDLE3");
|
||||||
|
DebugDraw::getInstance().removeMarker("RIGHT_HAND_MIDDLE4");
|
||||||
|
DebugDraw::getInstance().removeMarker("RIGHT_HAND_RING1");
|
||||||
|
DebugDraw::getInstance().removeMarker("RIGHT_HAND_RING2");
|
||||||
|
DebugDraw::getInstance().removeMarker("RIGHT_HAND_RING3");
|
||||||
|
DebugDraw::getInstance().removeMarker("RIGHT_HAND_RING4");
|
||||||
|
DebugDraw::getInstance().removeMarker("RIGHT_HAND_PINKY1");
|
||||||
|
DebugDraw::getInstance().removeMarker("RIGHT_HAND_PINKY2");
|
||||||
|
DebugDraw::getInstance().removeMarker("RIGHT_HAND_PINKY3");
|
||||||
|
DebugDraw::getInstance().removeMarker("RIGHT_HAND_PINKY4");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3097,6 +3151,16 @@ void MyAvatar::animGraphLoaded() {
|
||||||
disconnect(&(_skeletonModel->getRig()), SIGNAL(onLoadComplete()), this, SLOT(animGraphLoaded()));
|
disconnect(&(_skeletonModel->getRig()), SIGNAL(onLoadComplete()), this, SLOT(animGraphLoaded()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MyAvatar::debugDrawPose(controller::Action action, const char* channelName, float size) {
|
||||||
|
auto pose = getControllerPoseInWorldFrame(action);
|
||||||
|
if (pose.isValid()) {
|
||||||
|
DebugDraw::getInstance().addMarker(channelName, pose.getRotation(), pose.getTranslation(), glm::vec4(1), size);
|
||||||
|
} else {
|
||||||
|
DebugDraw::getInstance().removeMarker(channelName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void MyAvatar::postUpdate(float deltaTime, const render::ScenePointer& scene) {
|
void MyAvatar::postUpdate(float deltaTime, const render::ScenePointer& scene) {
|
||||||
|
|
||||||
Avatar::postUpdate(deltaTime, scene);
|
Avatar::postUpdate(deltaTime, scene);
|
||||||
|
@ -3137,20 +3201,50 @@ void MyAvatar::postUpdate(float deltaTime, const render::ScenePointer& scene) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_enableDebugDrawHandControllers) {
|
if (_enableDebugDrawHandControllers) {
|
||||||
auto leftHandPose = getControllerPoseInWorldFrame(controller::Action::LEFT_HAND);
|
debugDrawPose(controller::Action::LEFT_HAND, "LEFT_HAND", 1.0);
|
||||||
auto rightHandPose = getControllerPoseInWorldFrame(controller::Action::RIGHT_HAND);
|
debugDrawPose(controller::Action::RIGHT_HAND, "RIGHT_HAND", 1.0);
|
||||||
|
|
||||||
if (leftHandPose.isValid()) {
|
debugDrawPose(controller::Action::LEFT_HAND_THUMB1, "LEFT_HAND_THUMB1", 0.1f);
|
||||||
DebugDraw::getInstance().addMarker("leftHandController", leftHandPose.getRotation(), leftHandPose.getTranslation(), glm::vec4(1));
|
debugDrawPose(controller::Action::LEFT_HAND_THUMB2, "LEFT_HAND_THUMB2", 0.1f);
|
||||||
} else {
|
debugDrawPose(controller::Action::LEFT_HAND_THUMB3, "LEFT_HAND_THUMB3", 0.1f);
|
||||||
DebugDraw::getInstance().removeMarker("leftHandController");
|
debugDrawPose(controller::Action::LEFT_HAND_THUMB4, "LEFT_HAND_THUMB4", 0.1f);
|
||||||
}
|
debugDrawPose(controller::Action::LEFT_HAND_INDEX1, "LEFT_HAND_INDEX1", 0.1f);
|
||||||
|
debugDrawPose(controller::Action::LEFT_HAND_INDEX2, "LEFT_HAND_INDEX2", 0.1f);
|
||||||
|
debugDrawPose(controller::Action::LEFT_HAND_INDEX3, "LEFT_HAND_INDEX3", 0.1f);
|
||||||
|
debugDrawPose(controller::Action::LEFT_HAND_INDEX4, "LEFT_HAND_INDEX4", 0.1f);
|
||||||
|
debugDrawPose(controller::Action::LEFT_HAND_MIDDLE1, "LEFT_HAND_MIDDLE1", 0.1f);
|
||||||
|
debugDrawPose(controller::Action::LEFT_HAND_MIDDLE2, "LEFT_HAND_MIDDLE2", 0.1f);
|
||||||
|
debugDrawPose(controller::Action::LEFT_HAND_MIDDLE3, "LEFT_HAND_MIDDLE3", 0.1f);
|
||||||
|
debugDrawPose(controller::Action::LEFT_HAND_MIDDLE4, "LEFT_HAND_MIDDLE4", 0.1f);
|
||||||
|
debugDrawPose(controller::Action::LEFT_HAND_RING1, "LEFT_HAND_RING1", 0.1f);
|
||||||
|
debugDrawPose(controller::Action::LEFT_HAND_RING2, "LEFT_HAND_RING2", 0.1f);
|
||||||
|
debugDrawPose(controller::Action::LEFT_HAND_RING3, "LEFT_HAND_RING3", 0.1f);
|
||||||
|
debugDrawPose(controller::Action::LEFT_HAND_RING4, "LEFT_HAND_RING4", 0.1f);
|
||||||
|
debugDrawPose(controller::Action::LEFT_HAND_PINKY1, "LEFT_HAND_PINKY1", 0.1f);
|
||||||
|
debugDrawPose(controller::Action::LEFT_HAND_PINKY2, "LEFT_HAND_PINKY2", 0.1f);
|
||||||
|
debugDrawPose(controller::Action::LEFT_HAND_PINKY3, "LEFT_HAND_PINKY3", 0.1f);
|
||||||
|
debugDrawPose(controller::Action::LEFT_HAND_PINKY4, "LEFT_HAND_PINKY4", 0.1f);
|
||||||
|
|
||||||
if (rightHandPose.isValid()) {
|
debugDrawPose(controller::Action::RIGHT_HAND_THUMB1, "RIGHT_HAND_THUMB1", 0.1f);
|
||||||
DebugDraw::getInstance().addMarker("rightHandController", rightHandPose.getRotation(), rightHandPose.getTranslation(), glm::vec4(1));
|
debugDrawPose(controller::Action::RIGHT_HAND_THUMB2, "RIGHT_HAND_THUMB2", 0.1f);
|
||||||
} else {
|
debugDrawPose(controller::Action::RIGHT_HAND_THUMB3, "RIGHT_HAND_THUMB3", 0.1f);
|
||||||
DebugDraw::getInstance().removeMarker("rightHandController");
|
debugDrawPose(controller::Action::RIGHT_HAND_THUMB4, "RIGHT_HAND_THUMB4", 0.1f);
|
||||||
}
|
debugDrawPose(controller::Action::RIGHT_HAND_INDEX1, "RIGHT_HAND_INDEX1", 0.1f);
|
||||||
|
debugDrawPose(controller::Action::RIGHT_HAND_INDEX2, "RIGHT_HAND_INDEX2", 0.1f);
|
||||||
|
debugDrawPose(controller::Action::RIGHT_HAND_INDEX3, "RIGHT_HAND_INDEX3", 0.1f);
|
||||||
|
debugDrawPose(controller::Action::RIGHT_HAND_INDEX4, "RIGHT_HAND_INDEX4", 0.1f);
|
||||||
|
debugDrawPose(controller::Action::RIGHT_HAND_MIDDLE1, "RIGHT_HAND_MIDDLE1", 0.1f);
|
||||||
|
debugDrawPose(controller::Action::RIGHT_HAND_MIDDLE2, "RIGHT_HAND_MIDDLE2", 0.1f);
|
||||||
|
debugDrawPose(controller::Action::RIGHT_HAND_MIDDLE3, "RIGHT_HAND_MIDDLE3", 0.1f);
|
||||||
|
debugDrawPose(controller::Action::RIGHT_HAND_MIDDLE4, "RIGHT_HAND_MIDDLE4", 0.1f);
|
||||||
|
debugDrawPose(controller::Action::RIGHT_HAND_RING1, "RIGHT_HAND_RING1", 0.1f);
|
||||||
|
debugDrawPose(controller::Action::RIGHT_HAND_RING2, "RIGHT_HAND_RING2", 0.1f);
|
||||||
|
debugDrawPose(controller::Action::RIGHT_HAND_RING3, "RIGHT_HAND_RING3", 0.1f);
|
||||||
|
debugDrawPose(controller::Action::RIGHT_HAND_RING4, "RIGHT_HAND_RING4", 0.1f);
|
||||||
|
debugDrawPose(controller::Action::RIGHT_HAND_PINKY1, "RIGHT_HAND_PINKY1", 0.1f);
|
||||||
|
debugDrawPose(controller::Action::RIGHT_HAND_PINKY2, "RIGHT_HAND_PINKY2", 0.1f);
|
||||||
|
debugDrawPose(controller::Action::RIGHT_HAND_PINKY3, "RIGHT_HAND_PINKY3", 0.1f);
|
||||||
|
debugDrawPose(controller::Action::RIGHT_HAND_PINKY4, "RIGHT_HAND_PINKY4", 0.1f);
|
||||||
}
|
}
|
||||||
|
|
||||||
DebugDraw::getInstance().updateMyAvatarPos(getWorldPosition());
|
DebugDraw::getInstance().updateMyAvatarPos(getWorldPosition());
|
||||||
|
@ -6290,3 +6384,125 @@ void MyAvatar::endSit(const glm::vec3& position, const glm::quat& rotation) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MyAvatar::getIsJointOverridden(int jointIndex) const {
|
||||||
|
// has this joint been set by a script?
|
||||||
|
return _skeletonModel->getIsJointOverridden(jointIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyAvatar::updateLookAtPosition(FaceTracker* faceTracker, Camera& myCamera) {
|
||||||
|
|
||||||
|
updateLookAtTargetAvatar();
|
||||||
|
|
||||||
|
bool isLookingAtSomeone = false;
|
||||||
|
glm::vec3 lookAtSpot;
|
||||||
|
|
||||||
|
const MyHead* myHead = getMyHead();
|
||||||
|
|
||||||
|
int leftEyeJointIndex = getJointIndex("LeftEye");
|
||||||
|
int rightEyeJointIndex = getJointIndex("RightEye");
|
||||||
|
bool eyesAreOverridden = getIsJointOverridden(leftEyeJointIndex) ||
|
||||||
|
getIsJointOverridden(rightEyeJointIndex);
|
||||||
|
if (eyesAreOverridden) {
|
||||||
|
// A script has set the eye rotations, so use these to set lookAtSpot
|
||||||
|
glm::quat leftEyeRotation = getAbsoluteJointRotationInObjectFrame(leftEyeJointIndex);
|
||||||
|
glm::quat rightEyeRotation = getAbsoluteJointRotationInObjectFrame(rightEyeJointIndex);
|
||||||
|
glm::vec3 leftVec = getWorldOrientation() * leftEyeRotation * IDENTITY_FORWARD;
|
||||||
|
glm::vec3 rightVec = getWorldOrientation() * rightEyeRotation * IDENTITY_FORWARD;
|
||||||
|
glm::vec3 leftEyePosition = myHead->getLeftEyePosition();
|
||||||
|
glm::vec3 rightEyePosition = myHead->getRightEyePosition();
|
||||||
|
float t1, t2;
|
||||||
|
bool success = findClosestApproachOfLines(leftEyePosition, leftVec, rightEyePosition, rightVec, t1, t2);
|
||||||
|
if (success) {
|
||||||
|
glm::vec3 leftFocus = leftEyePosition + leftVec * t1;
|
||||||
|
glm::vec3 rightFocus = rightEyePosition + rightVec * t2;
|
||||||
|
lookAtSpot = (leftFocus + rightFocus) / 2.0f; // average
|
||||||
|
} else {
|
||||||
|
lookAtSpot = myHead->getEyePosition() + glm::normalize(leftVec) * 1000.0f;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
controller::Pose leftEyePose = getControllerPoseInAvatarFrame(controller::Action::LEFT_EYE);
|
||||||
|
controller::Pose rightEyePose = getControllerPoseInAvatarFrame(controller::Action::RIGHT_EYE);
|
||||||
|
if (leftEyePose.isValid() && rightEyePose.isValid()) {
|
||||||
|
// an eye tracker is in use, set lookAtSpot from this
|
||||||
|
glm::vec3 leftVec = getWorldOrientation() * leftEyePose.rotation * glm::vec3(0.0f, 0.0f, -1.0f);
|
||||||
|
glm::vec3 rightVec = getWorldOrientation() * rightEyePose.rotation * glm::vec3(0.0f, 0.0f, -1.0f);
|
||||||
|
|
||||||
|
glm::vec3 leftEyePosition = myHead->getLeftEyePosition();
|
||||||
|
glm::vec3 rightEyePosition = myHead->getRightEyePosition();
|
||||||
|
float t1, t2;
|
||||||
|
bool success = findClosestApproachOfLines(leftEyePosition, leftVec, rightEyePosition, rightVec, t1, t2);
|
||||||
|
if (success) {
|
||||||
|
glm::vec3 leftFocus = leftEyePosition + leftVec * t1;
|
||||||
|
glm::vec3 rightFocus = rightEyePosition + rightVec * t2;
|
||||||
|
lookAtSpot = (leftFocus + rightFocus) / 2.0f; // average
|
||||||
|
} else {
|
||||||
|
lookAtSpot = myHead->getEyePosition() + glm::normalize(leftVec) * 1000.0f;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// no script override, no eye tracker, so do procedural eye motion
|
||||||
|
AvatarSharedPointer lookingAt = getLookAtTargetAvatar().lock();
|
||||||
|
bool haveLookAtCandidate = lookingAt && this != lookingAt.get();
|
||||||
|
auto avatar = static_pointer_cast<Avatar>(lookingAt);
|
||||||
|
bool mutualLookAtSnappingEnabled =
|
||||||
|
avatar && avatar->getLookAtSnappingEnabled() && getLookAtSnappingEnabled();
|
||||||
|
if (haveLookAtCandidate && mutualLookAtSnappingEnabled) {
|
||||||
|
// If I am looking at someone else, look directly at one of their eyes
|
||||||
|
isLookingAtSomeone = true;
|
||||||
|
auto lookingAtHead = avatar->getHead();
|
||||||
|
|
||||||
|
const float MAXIMUM_FACE_ANGLE = 65.0f * RADIANS_PER_DEGREE;
|
||||||
|
glm::vec3 lookingAtFaceOrientation = lookingAtHead->getFinalOrientationInWorldFrame() * IDENTITY_FORWARD;
|
||||||
|
glm::vec3 fromLookingAtToMe = glm::normalize(getHead()->getEyePosition()
|
||||||
|
- lookingAtHead->getEyePosition());
|
||||||
|
float faceAngle = glm::angle(lookingAtFaceOrientation, fromLookingAtToMe);
|
||||||
|
|
||||||
|
if (faceAngle < MAXIMUM_FACE_ANGLE) {
|
||||||
|
// Randomly look back and forth between look targets
|
||||||
|
eyeContactTarget target = Menu::getInstance()->isOptionChecked(MenuOption::FixGaze) ?
|
||||||
|
LEFT_EYE : getEyeContactTarget();
|
||||||
|
switch (target) {
|
||||||
|
case LEFT_EYE:
|
||||||
|
lookAtSpot = lookingAtHead->getLeftEyePosition();
|
||||||
|
break;
|
||||||
|
case RIGHT_EYE:
|
||||||
|
lookAtSpot = lookingAtHead->getRightEyePosition();
|
||||||
|
break;
|
||||||
|
case MOUTH:
|
||||||
|
lookAtSpot = lookingAtHead->getMouthPosition();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Just look at their head (mid point between eyes)
|
||||||
|
lookAtSpot = lookingAtHead->getEyePosition();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// I am not looking at anyone else, so just look forward
|
||||||
|
auto headPose = getControllerPoseInWorldFrame(controller::Action::HEAD);
|
||||||
|
if (headPose.isValid()) {
|
||||||
|
lookAtSpot = transformPoint(headPose.getMatrix(), glm::vec3(0.0f, 0.0f, TREE_SCALE));
|
||||||
|
} else {
|
||||||
|
lookAtSpot = myHead->getEyePosition() +
|
||||||
|
(getHead()->getFinalOrientationInWorldFrame() * glm::vec3(0.0f, 0.0f, -TREE_SCALE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deflect the eyes a bit to match the detected gaze from the face tracker if active.
|
||||||
|
if (faceTracker && !faceTracker->isMuted()) {
|
||||||
|
float eyePitch = faceTracker->getEstimatedEyePitch();
|
||||||
|
float eyeYaw = faceTracker->getEstimatedEyeYaw();
|
||||||
|
const float GAZE_DEFLECTION_REDUCTION_DURING_EYE_CONTACT = 0.1f;
|
||||||
|
glm::vec3 origin = myHead->getEyePosition();
|
||||||
|
float deflection = faceTracker->getEyeDeflection();
|
||||||
|
if (isLookingAtSomeone) {
|
||||||
|
deflection *= GAZE_DEFLECTION_REDUCTION_DURING_EYE_CONTACT;
|
||||||
|
}
|
||||||
|
lookAtSpot = origin + myCamera.getOrientation() * glm::quat(glm::radians(glm::vec3(
|
||||||
|
eyePitch * deflection, eyeYaw * deflection, 0.0f))) *
|
||||||
|
glm::inverse(myCamera.getOrientation()) * (lookAtSpot - origin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getHead()->setLookAtPosition(lookAtSpot);
|
||||||
|
}
|
||||||
|
|
|
@ -29,10 +29,12 @@
|
||||||
#include <ScriptEngine.h>
|
#include <ScriptEngine.h>
|
||||||
#include <SettingHandle.h>
|
#include <SettingHandle.h>
|
||||||
#include <Sound.h>
|
#include <Sound.h>
|
||||||
|
#include <shared/Camera.h>
|
||||||
|
|
||||||
#include "AtRestDetector.h"
|
#include "AtRestDetector.h"
|
||||||
#include "MyCharacterController.h"
|
#include "MyCharacterController.h"
|
||||||
#include "RingBufferHistory.h"
|
#include "RingBufferHistory.h"
|
||||||
|
#include "devices/DdeFaceTracker.h"
|
||||||
|
|
||||||
class AvatarActionHold;
|
class AvatarActionHold;
|
||||||
class ModelItemID;
|
class ModelItemID;
|
||||||
|
@ -1864,6 +1866,8 @@ public:
|
||||||
bool getFlowActive() const;
|
bool getFlowActive() const;
|
||||||
bool getNetworkGraphActive() const;
|
bool getNetworkGraphActive() const;
|
||||||
|
|
||||||
|
void updateLookAtPosition(FaceTracker* faceTracker, Camera& myCamera);
|
||||||
|
|
||||||
// sets the reaction enabled and triggered parameters of the passed in params
|
// sets the reaction enabled and triggered parameters of the passed in params
|
||||||
// also clears internal reaction triggers
|
// also clears internal reaction triggers
|
||||||
void updateRigControllerParameters(Rig::ControllerParameters& params);
|
void updateRigControllerParameters(Rig::ControllerParameters& params);
|
||||||
|
@ -1871,6 +1875,10 @@ public:
|
||||||
// Don't substitute verify-fail:
|
// Don't substitute verify-fail:
|
||||||
virtual const QUrl& getSkeletonModelURL() const override { return _skeletonModelURL; }
|
virtual const QUrl& getSkeletonModelURL() const override { return _skeletonModelURL; }
|
||||||
|
|
||||||
|
void debugDrawPose(controller::Action action, const char* channelName, float size);
|
||||||
|
|
||||||
|
bool getIsJointOverridden(int jointIndex) const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
|
|
|
@ -114,13 +114,12 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
||||||
|
|
||||||
Head* head = _owningAvatar->getHead();
|
Head* head = _owningAvatar->getHead();
|
||||||
|
|
||||||
// make sure lookAt is not too close to face (avoid crosseyes)
|
bool eyePosesValid = !head->getHasProceduralEyeMovement();
|
||||||
glm::vec3 lookAt = head->getLookAtPosition();
|
glm::vec3 lookAt;
|
||||||
glm::vec3 focusOffset = lookAt - _owningAvatar->getHead()->getEyePosition();
|
if (eyePosesValid) {
|
||||||
float focusDistance = glm::length(focusOffset);
|
lookAt = head->getLookAtPosition(); // don't apply no-crosseyes code when eyes are being tracked
|
||||||
const float MIN_LOOK_AT_FOCUS_DISTANCE = 1.0f;
|
} else {
|
||||||
if (focusDistance < MIN_LOOK_AT_FOCUS_DISTANCE && focusDistance > EPSILON) {
|
lookAt = avoidCrossedEyes(head->getLookAtPosition());
|
||||||
lookAt = _owningAvatar->getHead()->getEyePosition() + (MIN_LOOK_AT_FOCUS_DISTANCE / focusDistance) * focusOffset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MyAvatar* myAvatar = static_cast<MyAvatar*>(_owningAvatar);
|
MyAvatar* myAvatar = static_cast<MyAvatar*>(_owningAvatar);
|
||||||
|
|
|
@ -93,19 +93,30 @@ void SkeletonModel::initJointStates() {
|
||||||
emit skeletonLoaded();
|
emit skeletonLoaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::vec3 SkeletonModel::avoidCrossedEyes(const glm::vec3& lookAt) {
|
||||||
|
// make sure lookAt is not too close to face (avoid crosseyes)
|
||||||
|
glm::vec3 focusOffset = lookAt - _owningAvatar->getHead()->getEyePosition();
|
||||||
|
float focusDistance = glm::length(focusOffset);
|
||||||
|
const float MIN_LOOK_AT_FOCUS_DISTANCE = 1.0f;
|
||||||
|
if (focusDistance < MIN_LOOK_AT_FOCUS_DISTANCE && focusDistance > EPSILON) {
|
||||||
|
return _owningAvatar->getHead()->getEyePosition() + (MIN_LOOK_AT_FOCUS_DISTANCE / focusDistance) * focusOffset;
|
||||||
|
} else {
|
||||||
|
return lookAt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Called within Model::simulate call, below.
|
// Called within Model::simulate call, below.
|
||||||
void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
||||||
assert(!_owningAvatar->isMyAvatar());
|
assert(!_owningAvatar->isMyAvatar());
|
||||||
|
|
||||||
Head* head = _owningAvatar->getHead();
|
Head* head = _owningAvatar->getHead();
|
||||||
|
|
||||||
// make sure lookAt is not too close to face (avoid crosseyes)
|
bool eyePosesValid = !head->getHasProceduralEyeMovement();
|
||||||
glm::vec3 lookAt = head->getCorrectedLookAtPosition();
|
glm::vec3 lookAt;
|
||||||
glm::vec3 focusOffset = lookAt - _owningAvatar->getHead()->getEyePosition();
|
if (eyePosesValid) {
|
||||||
float focusDistance = glm::length(focusOffset);
|
lookAt = head->getLookAtPosition(); // don't apply no-crosseyes code etc when eyes are being tracked
|
||||||
const float MIN_LOOK_AT_FOCUS_DISTANCE = 1.0f;
|
} else {
|
||||||
if (focusDistance < MIN_LOOK_AT_FOCUS_DISTANCE && focusDistance > EPSILON) {
|
lookAt = avoidCrossedEyes(head->getCorrectedLookAtPosition());
|
||||||
lookAt = _owningAvatar->getHead()->getEyePosition() + (MIN_LOOK_AT_FOCUS_DISTANCE / focusDistance) * focusOffset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// no need to call Model::updateRig() because otherAvatars get their joint state
|
// no need to call Model::updateRig() because otherAvatars get their joint state
|
||||||
|
@ -288,6 +299,15 @@ bool SkeletonModel::getEyeModelPositions(glm::vec3& firstEyePosition, glm::vec3&
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SkeletonModel::getIsJointOverridden(int jointIndex) const {
|
||||||
|
// has this joint been set by a script?
|
||||||
|
if (!isLoaded() || _rig.jointStatesEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return _rig.getIsJointOverridden(jointIndex);
|
||||||
|
}
|
||||||
|
|
||||||
bool SkeletonModel::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const {
|
bool SkeletonModel::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const {
|
||||||
if (getEyeModelPositions(firstEyePosition, secondEyePosition)) {
|
if (getEyeModelPositions(firstEyePosition, secondEyePosition)) {
|
||||||
firstEyePosition = _translation + _rotation * firstEyePosition;
|
firstEyePosition = _translation + _rotation * firstEyePosition;
|
||||||
|
@ -352,4 +372,3 @@ bool SkeletonModel::hasSkeleton() {
|
||||||
|
|
||||||
void SkeletonModel::onInvalidate() {
|
void SkeletonModel::onInvalidate() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,9 +37,12 @@ public:
|
||||||
void initJointStates() override;
|
void initJointStates() override;
|
||||||
|
|
||||||
void simulate(float deltaTime, bool fullUpdate = true) override;
|
void simulate(float deltaTime, bool fullUpdate = true) override;
|
||||||
|
glm::vec3 avoidCrossedEyes(const glm::vec3& lookAt);
|
||||||
void updateRig(float deltaTime, glm::mat4 parentTransform) override;
|
void updateRig(float deltaTime, glm::mat4 parentTransform) override;
|
||||||
void updateAttitude(const glm::quat& orientation);
|
void updateAttitude(const glm::quat& orientation);
|
||||||
|
|
||||||
|
bool getIsJointOverridden(int jointIndex) const;
|
||||||
|
|
||||||
/// Returns the index of the left hand joint, or -1 if not found.
|
/// Returns the index of the left hand joint, or -1 if not found.
|
||||||
int getLeftHandJointIndex() const { return isActive() ? _rig.indexOfJoint("LeftHand") : -1; }
|
int getLeftHandJointIndex() const { return isActive() ? _rig.indexOfJoint("LeftHand") : -1; }
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue