mirror of
https://github.com/overte-org/overte.git
synced 2025-04-23 13:53:30 +02:00
Merge pull request #5883 from hyperlogic/tony/lean-threshold
Better Head IK when in HMD mode
This commit is contained in:
commit
14bfdebdca
14 changed files with 265 additions and 49 deletions
interface
resources/meshes/defaultAvatar_full
src
libraries
animation/src
render-utils/src
shared/src
tests/animation/src/data
|
@ -23,6 +23,11 @@
|
|||
"positionVar": "leftHandPosition",
|
||||
"rotationVar": "leftHandRotation"
|
||||
},
|
||||
{
|
||||
"jointName": "Neck",
|
||||
"positionVar": "neckPosition",
|
||||
"rotationVar": "neckRotation"
|
||||
},
|
||||
{
|
||||
"jointName": "Head",
|
||||
"positionVar": "headPosition",
|
||||
|
|
|
@ -794,6 +794,8 @@ void Application::cleanupBeforeQuit() {
|
|||
DependencyManager::get<EyeTracker>()->setEnabled(false, true);
|
||||
#endif
|
||||
|
||||
AnimDebugDraw::getInstance().shutdown();
|
||||
|
||||
if (_keyboardFocusHighlightID > 0) {
|
||||
getOverlays().deleteOverlay(_keyboardFocusHighlightID);
|
||||
_keyboardFocusHighlightID = -1;
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "Recorder.h"
|
||||
#include "Util.h"
|
||||
#include "InterfaceLogging.h"
|
||||
#include "DebugDraw.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -1333,7 +1334,7 @@ void MyAvatar::preRender(RenderArgs* renderArgs) {
|
|||
|
||||
// bones are aligned such that z is forward, not -z.
|
||||
glm::quat rotY180 = glm::angleAxis((float)M_PI, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
AnimPose xform(glm::vec3(1), rotY180 * getOrientation(), getPosition());
|
||||
AnimPose xform(glm::vec3(1), getOrientation() * rotY180, getPosition());
|
||||
|
||||
if (_enableDebugDrawBindPose && _debugDrawSkeleton) {
|
||||
glm::vec4 gray(0.2f, 0.2f, 0.2f, 0.2f);
|
||||
|
@ -1358,6 +1359,9 @@ void MyAvatar::preRender(RenderArgs* renderArgs) {
|
|||
}
|
||||
}
|
||||
|
||||
DebugDraw::getInstance().updateMyAvatarPos(getPosition());
|
||||
DebugDraw::getInstance().updateMyAvatarRot(getOrientation());
|
||||
|
||||
if (shouldDrawHead != _prevShouldDrawHead) {
|
||||
_skeletonModel.setCauterizeBones(!shouldDrawHead);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "SkeletonModel.h"
|
||||
#include "Util.h"
|
||||
#include "InterfaceLogging.h"
|
||||
#include "AnimDebugDraw.h"
|
||||
|
||||
SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent, RigPointer rig) :
|
||||
Model(rig, parent),
|
||||
|
@ -126,19 +127,35 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|||
headParams.leanSideways = head->getFinalLeanSideways();
|
||||
headParams.leanForward = head->getFinalLeanForward();
|
||||
headParams.torsoTwist = head->getTorsoTwist();
|
||||
headParams.localHeadOrientation = head->getFinalOrientationInLocalFrame();
|
||||
headParams.localHeadPitch = head->getFinalPitch();
|
||||
headParams.localHeadYaw = head->getFinalYaw();
|
||||
headParams.localHeadRoll = head->getFinalRoll();
|
||||
headParams.isInHMD = qApp->getAvatarUpdater()->isHMDMode();
|
||||
|
||||
// get HMD position from sensor space into world space, and back into model space
|
||||
glm::mat4 worldToModel = glm::inverse(createMatFromQuatAndPos(myAvatar->getOrientation(), myAvatar->getPosition()));
|
||||
glm::vec3 yAxis(0.0f, 1.0f, 0.0f);
|
||||
glm::vec3 hmdPosition = glm::angleAxis((float)M_PI, yAxis) * transformPoint(worldToModel * myAvatar->getSensorToWorldMatrix(), myAvatar->getHMDSensorPosition());
|
||||
headParams.localHeadPosition = hmdPosition;
|
||||
if (qApp->getAvatarUpdater()->isHMDMode()) {
|
||||
headParams.isInHMD = true;
|
||||
|
||||
// get HMD position from sensor space into world space, and back into model space
|
||||
AnimPose avatarToWorld(glm::vec3(1), myAvatar->getOrientation(), myAvatar->getPosition());
|
||||
glm::mat4 worldToAvatar = glm::inverse((glm::mat4)avatarToWorld);
|
||||
glm::mat4 worldHMDMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
|
||||
glm::mat4 hmdMat = worldToAvatar * worldHMDMat;
|
||||
|
||||
// in local avatar space (i.e. relative to avatar pos/orientation.)
|
||||
glm::vec3 hmdPosition = extractTranslation(hmdMat);
|
||||
glm::quat hmdOrientation = extractRotation(hmdMat);
|
||||
|
||||
headParams.localHeadPosition = hmdPosition;
|
||||
headParams.localHeadOrientation = hmdOrientation;
|
||||
|
||||
headParams.worldHeadOrientation = extractRotation(worldHMDMat);
|
||||
} else {
|
||||
headParams.isInHMD = false;
|
||||
|
||||
// We don't have a valid localHeadPosition.
|
||||
headParams.localHeadOrientation = head->getFinalOrientationInLocalFrame();
|
||||
headParams.worldHeadOrientation = head->getFinalOrientationInWorldFrame();
|
||||
}
|
||||
|
||||
headParams.worldHeadOrientation = head->getFinalOrientationInWorldFrame();
|
||||
headParams.eyeLookAt = head->getLookAtPosition();
|
||||
headParams.eyeSaccade = head->getSaccade();
|
||||
headParams.leanJointIndex = geometry.leanJointIndex;
|
||||
|
|
|
@ -29,6 +29,12 @@ const AnimPoseVec& AnimManipulator::evaluate(const AnimVariantMap& animVars, flo
|
|||
const AnimPoseVec& AnimManipulator::overlay(const AnimVariantMap& animVars, float dt, Triggers& triggersOut, const AnimPoseVec& underPoses) {
|
||||
_alpha = animVars.lookup(_alphaVar, _alpha);
|
||||
|
||||
_poses = underPoses;
|
||||
|
||||
if (underPoses.size() == 0) {
|
||||
return _poses;
|
||||
}
|
||||
|
||||
for (auto& jointVar : _jointVars) {
|
||||
if (!jointVar.hasPerformedJointLookup) {
|
||||
jointVar.jointIndex = _skeleton->nameToJointIndex(jointVar.jointName);
|
||||
|
|
|
@ -61,7 +61,7 @@ public:
|
|||
// hierarchy accessors
|
||||
void addChild(Pointer child) { _children.push_back(child); }
|
||||
void removeChild(Pointer child);
|
||||
|
||||
|
||||
Pointer getChild(int i) const;
|
||||
int getChildCount() const { return (int)_children.size(); }
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ const AnimPose AnimPose::identity = AnimPose(glm::vec3(1.0f),
|
|||
|
||||
AnimPose::AnimPose(const glm::mat4& mat) {
|
||||
scale = extractScale(mat);
|
||||
rot = extractRotation(mat);
|
||||
rot = glm::normalize(glm::quat_cast(mat));
|
||||
trans = extractTranslation(mat);
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, fl
|
|||
if (_duringInterp) {
|
||||
_alpha += _alphaVel * dt;
|
||||
if (_alpha < 1.0f) {
|
||||
if (_poses.size() > 0) {
|
||||
if (_poses.size() > 0 && _nextPoses.size() > 0 && _prevPoses.size() > 0) {
|
||||
::blend(_poses.size(), &_prevPoses[0], &_nextPoses[0], _alpha, &_poses[0]);
|
||||
}
|
||||
} else {
|
||||
|
@ -77,8 +77,6 @@ void AnimStateMachine::addState(State::Pointer state) {
|
|||
|
||||
void AnimStateMachine::switchState(const AnimVariantMap& animVars, State::Pointer desiredState) {
|
||||
|
||||
qCDebug(animation) << "AnimStateMachine::switchState:" << _currentState->getID() << "->" << desiredState->getID();
|
||||
|
||||
const float FRAMES_PER_SECOND = 30.0f;
|
||||
|
||||
auto prevStateNode = _currentState->getNode();
|
||||
|
@ -96,6 +94,8 @@ void AnimStateMachine::switchState(const AnimVariantMap& animVars, State::Pointe
|
|||
Triggers triggers;
|
||||
_nextPoses = nextStateNode->evaluate(animVars, dt, triggers);
|
||||
|
||||
qCDebug(animation) << "AnimStateMachine::switchState:" << _currentState->getID() << "->" << desiredState->getID() << "duration =" << duration << "targetFrame =" << desiredState->_interpTarget;
|
||||
|
||||
_currentState = desiredState;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,9 +14,11 @@
|
|||
#include <glm/gtx/vector_angle.hpp>
|
||||
#include <queue>
|
||||
|
||||
#include "NumericalConstants.h"
|
||||
#include "AnimationHandle.h"
|
||||
#include "AnimationLogging.h"
|
||||
#include "AnimSkeleton.h"
|
||||
#include "DebugDraw.h"
|
||||
|
||||
#include "Rig.h"
|
||||
|
||||
|
@ -984,21 +986,97 @@ void Rig::updateLeanJoint(int index, float leanSideways, float leanForward, floa
|
|||
}
|
||||
}
|
||||
|
||||
static AnimPose avatarToBonePose(AnimPose pose, AnimSkeleton::ConstPointer skeleton) {
|
||||
AnimPose rootPose = skeleton->getAbsoluteBindPose(skeleton->nameToJointIndex("Hips"));
|
||||
AnimPose rotY180(glm::vec3(1), glm::angleAxis((float)PI, glm::vec3(0.0f, 1.0f, 0.0f)), glm::vec3(0));
|
||||
return rootPose * rotY180 * pose;
|
||||
}
|
||||
|
||||
static AnimPose boneToAvatarPose(AnimPose pose, AnimSkeleton::ConstPointer skeleton) {
|
||||
AnimPose rootPose = skeleton->getAbsoluteBindPose(skeleton->nameToJointIndex("Hips"));
|
||||
AnimPose rotY180(glm::vec3(1), glm::angleAxis((float)PI, glm::vec3(0.0f, 1.0f, 0.0f)), glm::vec3(0));
|
||||
return (rootPose * rotY180).inverse() * pose;
|
||||
}
|
||||
|
||||
static void computeHeadNeckAnimVars(AnimSkeleton::ConstPointer skeleton, const AnimPose& avatarHMDPose,
|
||||
glm::vec3& headPositionOut, glm::quat& headOrientationOut,
|
||||
glm::vec3& neckPositionOut, glm::quat& neckOrientationOut) {
|
||||
|
||||
// the input hmd values are in avatar space
|
||||
// we need to transform them into bone space.
|
||||
AnimPose hmdPose = avatarToBonePose(avatarHMDPose, skeleton);
|
||||
const glm::vec3 hmdPosition = hmdPose.trans;
|
||||
const glm::quat rotY180 = glm::angleAxis((float)PI, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
const glm::quat hmdOrientation = hmdPose.rot * rotY180; // rotY180 will make z forward not -z
|
||||
|
||||
// TODO: cache jointIndices
|
||||
|
||||
// Use absolute bindPose positions just in case the relBindPose have rotations we don't expect.
|
||||
glm::vec3 absRightEyePos = skeleton->getAbsoluteBindPose(skeleton->nameToJointIndex("RightEye")).trans;
|
||||
glm::vec3 absLeftEyePos = skeleton->getAbsoluteBindPose(skeleton->nameToJointIndex("LeftEye")).trans;
|
||||
glm::vec3 absHeadPos = skeleton->getAbsoluteBindPose(skeleton->nameToJointIndex("Head")).trans;
|
||||
glm::vec3 absNeckPos = skeleton->getAbsoluteBindPose(skeleton->nameToJointIndex("Neck")).trans;
|
||||
|
||||
glm::vec3 absCenterEyePos = (absRightEyePos + absLeftEyePos) / 2.0f;
|
||||
glm::vec3 eyeOffset = absCenterEyePos - absHeadPos;
|
||||
glm::vec3 headOffset = absHeadPos - absNeckPos;
|
||||
|
||||
// apply simplistic head/neck model
|
||||
|
||||
// head
|
||||
headPositionOut = hmdPosition - hmdOrientation * eyeOffset;
|
||||
headOrientationOut = hmdOrientation;
|
||||
|
||||
// neck
|
||||
neckPositionOut = hmdPosition - hmdOrientation * (headOffset + eyeOffset);
|
||||
|
||||
// slerp between bind orientation and hmdOrientation
|
||||
neckOrientationOut = safeMix(hmdOrientation, skeleton->getRelativeBindPose(skeleton->nameToJointIndex("Neck")).rot, 0.5f);
|
||||
}
|
||||
|
||||
void Rig::updateNeckJoint(int index, const HeadParameters& params) {
|
||||
if (index >= 0 && _jointStates[index].getParentIndex() >= 0) {
|
||||
if (_enableAnimGraph && _animSkeleton && _animNode) {
|
||||
// the params.localHeadOrientation is composed incorrectly, so re-compose it correctly from pitch, yaw and roll.
|
||||
glm::quat realLocalHeadOrientation = (glm::angleAxis(glm::radians(-params.localHeadRoll), Z_AXIS) *
|
||||
glm::angleAxis(glm::radians(params.localHeadYaw), Y_AXIS) *
|
||||
glm::angleAxis(glm::radians(-params.localHeadPitch), X_AXIS));
|
||||
_animVars.set("headRotation", realLocalHeadOrientation);
|
||||
if (_enableAnimGraph && _animSkeleton) {
|
||||
|
||||
if (params.isInHMD) {
|
||||
int headIndex = _animSkeleton->nameToJointIndex("Head");
|
||||
AnimPose rootPose = _animNode->getRootPose(headIndex);
|
||||
_animVars.set("headPosition", rootPose.trans + params.localHeadPosition); // rootPose.rot is handled in params?d
|
||||
glm::vec3 headPos, neckPos;
|
||||
glm::quat headRot, neckRot;
|
||||
|
||||
AnimPose avatarHMDPose(glm::vec3(1), params.localHeadOrientation, params.localHeadPosition);
|
||||
computeHeadNeckAnimVars(_animSkeleton, avatarHMDPose, headPos, headRot, neckPos, neckRot);
|
||||
|
||||
// debug rendering
|
||||
/*
|
||||
const glm::vec4 red(1.0f, 0.0f, 0.0f, 1.0f);
|
||||
const glm::vec4 green(0.0f, 1.0f, 0.0f, 1.0f);
|
||||
|
||||
// transform from bone into avatar space
|
||||
AnimPose headPose(glm::vec3(1), headRot, headPos);
|
||||
headPose = boneToAvatarPose(headPose, _animSkeleton);
|
||||
DebugDraw::getInstance().addMyAvatarMarker("headTarget", headPose.rot, headPose.trans, red);
|
||||
|
||||
// transform from bone into avatar space
|
||||
AnimPose neckPose(glm::vec3(1), neckRot, neckPos);
|
||||
neckPose = boneToAvatarPose(neckPose, _animSkeleton);
|
||||
DebugDraw::getInstance().addMyAvatarMarker("neckTarget", neckPose.rot, neckPose.trans, green);
|
||||
*/
|
||||
|
||||
_animVars.set("headPosition", headPos);
|
||||
_animVars.set("headRotation", headRot);
|
||||
_animVars.set("neckPosition", neckPos);
|
||||
_animVars.set("neckRotation", neckRot);
|
||||
|
||||
} else {
|
||||
|
||||
// the params.localHeadOrientation is composed incorrectly, so re-compose it correctly from pitch, yaw and roll.
|
||||
glm::quat realLocalHeadOrientation = (glm::angleAxis(glm::radians(-params.localHeadRoll), Z_AXIS) *
|
||||
glm::angleAxis(glm::radians(params.localHeadYaw), Y_AXIS) *
|
||||
glm::angleAxis(glm::radians(-params.localHeadPitch), X_AXIS));
|
||||
|
||||
_animVars.unset("headPosition");
|
||||
_animVars.set("headRotation", realLocalHeadOrientation);
|
||||
_animVars.unset("neckPosition");
|
||||
_animVars.unset("neckRotation");
|
||||
}
|
||||
} else if (!_enableAnimGraph) {
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "AbstractViewStateInterface.h"
|
||||
#include "RenderUtilsLogging.h"
|
||||
#include "GLMHelpers.h"
|
||||
#include "DebugDraw.h"
|
||||
|
||||
#include "AnimDebugDraw.h"
|
||||
|
||||
|
@ -67,13 +68,9 @@ namespace render {
|
|||
}
|
||||
}
|
||||
|
||||
static AnimDebugDraw* instance = nullptr;
|
||||
|
||||
AnimDebugDraw& AnimDebugDraw::getInstance() {
|
||||
if (!instance) {
|
||||
instance = new AnimDebugDraw();
|
||||
}
|
||||
return *instance;
|
||||
static AnimDebugDraw instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
static uint32_t toRGBA(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
|
||||
|
@ -144,6 +141,10 @@ AnimDebugDraw::AnimDebugDraw() :
|
|||
}
|
||||
|
||||
AnimDebugDraw::~AnimDebugDraw() {
|
||||
}
|
||||
|
||||
void AnimDebugDraw::shutdown() {
|
||||
// remove renderItem from main 3d scene.
|
||||
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
|
||||
if (scene && _itemID) {
|
||||
render::PendingChanges pendingChanges;
|
||||
|
@ -176,14 +177,6 @@ void AnimDebugDraw::removePoses(const std::string& key) {
|
|||
_poses.erase(key);
|
||||
}
|
||||
|
||||
void AnimDebugDraw::addPose(const std::string& key, const AnimPose& pose, const AnimPose& rootPose) {
|
||||
_singlePoses[key] = SinglePoseInfo(pose, rootPose);
|
||||
}
|
||||
|
||||
void AnimDebugDraw::removePose(const std::string& key) {
|
||||
_singlePoses.erase(key);
|
||||
}
|
||||
|
||||
static const uint32_t red = toRGBA(255, 0, 0, 255);
|
||||
static const uint32_t green = toRGBA(0, 255, 0, 255);
|
||||
static const uint32_t blue = toRGBA(0, 0, 255, 255);
|
||||
|
@ -380,7 +373,11 @@ void AnimDebugDraw::update() {
|
|||
}
|
||||
}
|
||||
|
||||
numVerts += _singlePoses.size() * VERTICES_PER_BONE;
|
||||
// count marker verts from shared DebugDraw singleton
|
||||
auto markerMap = DebugDraw::getInstance().getMarkerMap();
|
||||
numVerts += markerMap.size() * VERTICES_PER_BONE;
|
||||
auto myAvatarMarkerMap = DebugDraw::getInstance().getMyAvatarMarkerMap();
|
||||
numVerts += myAvatarMarkerMap.size() * VERTICES_PER_BONE;
|
||||
|
||||
data._vertexBuffer->resize(sizeof(Vertex) * numVerts);
|
||||
Vertex* verts = (Vertex*)data._vertexBuffer->editData();
|
||||
|
@ -486,11 +483,22 @@ void AnimDebugDraw::update() {
|
|||
}
|
||||
}
|
||||
|
||||
for (auto& iter : _singlePoses) {
|
||||
AnimPose pose = std::get<0>(iter.second);
|
||||
AnimPose rootPose = std::get<1>(iter.second);
|
||||
const float radius = POSE_RADIUS / (pose.scale.x * rootPose.scale.x);
|
||||
addBone(rootPose, pose, radius, v);
|
||||
// draw markers from shared DebugDraw singleton
|
||||
for (auto& iter : markerMap) {
|
||||
glm::quat rot = std::get<0>(iter.second);
|
||||
glm::vec3 pos = std::get<1>(iter.second);
|
||||
glm::vec4 color = std::get<2>(iter.second); // TODO: currently ignored.
|
||||
const float radius = POSE_RADIUS;
|
||||
addBone(AnimPose::identity, AnimPose(glm::vec3(1), rot, pos), radius, v);
|
||||
}
|
||||
|
||||
AnimPose myAvatarPose(glm::vec3(1), DebugDraw::getInstance().getMyAvatarRot(), DebugDraw::getInstance().getMyAvatarPos());
|
||||
for (auto& iter : myAvatarMarkerMap) {
|
||||
glm::quat rot = std::get<0>(iter.second);
|
||||
glm::vec3 pos = std::get<1>(iter.second);
|
||||
glm::vec4 color = std::get<2>(iter.second); // TODO: currently ignored.
|
||||
const float radius = POSE_RADIUS;
|
||||
addBone(myAvatarPose, AnimPose(glm::vec3(1), rot, pos), radius, v);
|
||||
}
|
||||
|
||||
assert(numVerts == (v - verts));
|
||||
|
|
|
@ -27,6 +27,8 @@ public:
|
|||
AnimDebugDraw();
|
||||
~AnimDebugDraw();
|
||||
|
||||
void shutdown();
|
||||
|
||||
// draw a skeleton bind pose
|
||||
void addSkeleton(const std::string& key, AnimSkeleton::ConstPointer skeleton, const AnimPose& rootPose, const glm::vec4& color);
|
||||
void removeSkeleton(const std::string& key);
|
||||
|
@ -39,10 +41,6 @@ public:
|
|||
void addPoses(const std::string& key, AnimSkeleton::ConstPointer skeleton, const AnimPoseVec& poses, const AnimPose& rootPose, const glm::vec4& color);
|
||||
void removePoses(const std::string& key);
|
||||
|
||||
// draw a single pose
|
||||
void addPose(const std::string& key, const AnimPose& rootPose, const AnimPose& pose);
|
||||
void removePose(const std::string& key);
|
||||
|
||||
void update();
|
||||
|
||||
protected:
|
||||
|
@ -55,12 +53,10 @@ protected:
|
|||
typedef std::tuple<AnimSkeleton::ConstPointer, AnimPose, glm::vec4> SkeletonInfo;
|
||||
typedef std::tuple<AnimNode::ConstPointer, AnimPose, glm::vec4> AnimNodeInfo;
|
||||
typedef std::tuple<AnimSkeleton::ConstPointer, AnimPoseVec, AnimPose, glm::vec4> PosesInfo;
|
||||
typedef std::tuple<AnimPose, AnimPose> SinglePoseInfo;
|
||||
|
||||
std::unordered_map<std::string, SkeletonInfo> _skeletons;
|
||||
std::unordered_map<std::string, AnimNodeInfo> _animNodes;
|
||||
std::unordered_map<std::string, PosesInfo> _poses;
|
||||
std::unordered_map<std::string, SinglePoseInfo> _singlePoses;
|
||||
|
||||
// no copies
|
||||
AnimDebugDraw(const AnimDebugDraw&) = delete;
|
||||
|
|
40
libraries/shared/src/DebugDraw.cpp
Normal file
40
libraries/shared/src/DebugDraw.cpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// DebugDraw.cpp
|
||||
//
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "DebugDraw.h"
|
||||
|
||||
DebugDraw& DebugDraw::getInstance() {
|
||||
static DebugDraw instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
DebugDraw::DebugDraw() {
|
||||
|
||||
}
|
||||
|
||||
DebugDraw::~DebugDraw() {
|
||||
|
||||
}
|
||||
|
||||
void DebugDraw::addMarker(const std::string& key, const glm::quat& rotation, const glm::vec3& position, const glm::vec4& color) {
|
||||
_markers[key] = MarkerInfo(rotation, position, color);
|
||||
}
|
||||
|
||||
void DebugDraw::removeMarker(const std::string& key) {
|
||||
_markers.erase(key);
|
||||
}
|
||||
|
||||
void DebugDraw::addMyAvatarMarker(const std::string& key, const glm::quat& rotation, const glm::vec3& position, const glm::vec4& color) {
|
||||
_myAvatarMarkers[key] = MarkerInfo(rotation, position, color);
|
||||
}
|
||||
|
||||
void DebugDraw::removeMyAvatarMarker(const std::string& key) {
|
||||
_myAvatarMarkers.erase(key);
|
||||
}
|
||||
|
55
libraries/shared/src/DebugDraw.h
Normal file
55
libraries/shared/src/DebugDraw.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
//
|
||||
// DebugDraw.h
|
||||
//
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_DebugDraw_h
|
||||
#define hifi_DebugDraw_h
|
||||
|
||||
#include <unordered_map>
|
||||
#include <tuple>
|
||||
#include <string>
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
class DebugDraw {
|
||||
public:
|
||||
static DebugDraw& getInstance();
|
||||
|
||||
DebugDraw();
|
||||
~DebugDraw();
|
||||
|
||||
// world space maker
|
||||
void addMarker(const std::string& key, const glm::quat& rotation, const glm::vec3& position, const glm::vec4& color);
|
||||
void removeMarker(const std::string& key);
|
||||
|
||||
// myAvatar relative marker
|
||||
void addMyAvatarMarker(const std::string& key, const glm::quat& rotation, const glm::vec3& position, const glm::vec4& color);
|
||||
void removeMyAvatarMarker(const std::string& key);
|
||||
|
||||
using MarkerInfo = std::tuple<glm::quat, glm::vec3, glm::vec4>;
|
||||
using MarkerMap = std::unordered_map<std::string, MarkerInfo>;
|
||||
|
||||
//
|
||||
// accessors used by renderer
|
||||
//
|
||||
|
||||
const MarkerMap& getMarkerMap() const { return _markers; }
|
||||
const MarkerMap& getMyAvatarMarkerMap() const { return _myAvatarMarkers; }
|
||||
void updateMyAvatarPos(const glm::vec3& pos) { _myAvatarPos = pos; }
|
||||
const glm::vec3& getMyAvatarPos() const { return _myAvatarPos; }
|
||||
void updateMyAvatarRot(const glm::quat& rot) { _myAvatarRot = rot; }
|
||||
const glm::quat& getMyAvatarRot() const { return _myAvatarRot; }
|
||||
|
||||
protected:
|
||||
MarkerMap _markers;
|
||||
MarkerMap _myAvatarMarkers;
|
||||
glm::quat _myAvatarRot;
|
||||
glm::vec3 _myAvatarPos;
|
||||
};
|
||||
|
||||
#endif // hifi_DebugDraw_h
|
|
@ -23,6 +23,11 @@
|
|||
"positionVar": "leftHandPosition",
|
||||
"rotationVar": "leftHandRotation"
|
||||
},
|
||||
{
|
||||
"jointName": "Neck",
|
||||
"positionVar": "neckPosition",
|
||||
"rotationVar": "neckRotation"
|
||||
},
|
||||
{
|
||||
"jointName": "Head",
|
||||
"positionVar": "headPosition",
|
||||
|
|
Loading…
Reference in a new issue