mirror of
https://github.com/overte-org/overte.git
synced 2025-08-04 11:35:20 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into decouple-avatar-updates
This commit is contained in:
commit
73a5714d66
19 changed files with 297 additions and 199 deletions
|
@ -14,7 +14,7 @@ Script.load("selectAudioDevice.js");
|
|||
Script.load("inspect.js");
|
||||
Script.load("notifications.js");
|
||||
Script.load("users.js");
|
||||
Script.load("handControllerGrab.js");
|
||||
Script.load("controllers/handControllerGrab.js");
|
||||
Script.load("grab.js");
|
||||
Script.load("directory.js");
|
||||
Script.load("dialTone.js");
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
if (_this.injector == null) {
|
||||
_this.injector = Audio.playSound(_this.song, {
|
||||
position: props.position, // position of boombox entity
|
||||
volume: 0.5,
|
||||
volume: 0.1,
|
||||
loop: true
|
||||
});
|
||||
} else {
|
||||
|
|
|
@ -96,20 +96,44 @@ mergeObjects = function(proto, custom) {
|
|||
return result;
|
||||
}
|
||||
|
||||
LOG_WARN = 1;
|
||||
|
||||
logWarn = function(str) {
|
||||
print(str);
|
||||
if (LOG_WARN) {
|
||||
print(str);
|
||||
}
|
||||
}
|
||||
|
||||
LOG_ERROR = 1;
|
||||
|
||||
logError = function(str) {
|
||||
print(str);
|
||||
if (LOG_ERROR) {
|
||||
print(str);
|
||||
}
|
||||
}
|
||||
|
||||
LOG_INFO = 1;
|
||||
|
||||
logInfo = function(str) {
|
||||
print(str);
|
||||
if (LOG_INFO) {
|
||||
print(str);
|
||||
}
|
||||
}
|
||||
|
||||
LOG_DEBUG = 0;
|
||||
|
||||
logDebug = function(str) {
|
||||
print(str);
|
||||
if (LOG_DEBUG) {
|
||||
print(str);
|
||||
}
|
||||
}
|
||||
|
||||
LOG_TRACE = 0;
|
||||
|
||||
logTrace = function(str) {
|
||||
if (LOG_TRACE) {
|
||||
print(str);
|
||||
}
|
||||
}
|
||||
|
||||
// Computes the penetration between a point and a sphere (centered at the origin)
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
this.collisionWithEntity = function(myID, otherID, collision) {
|
||||
//if(Entites.getEntityProperties(otherID).userData.objectType==='') { merge bubbles?}
|
||||
Entities.deleteEntity(myID);
|
||||
// Entities.deleteEntity(myID);
|
||||
// this.burstBubbleSound(collision.contactPoint)
|
||||
|
||||
};
|
||||
|
|
|
@ -35,7 +35,7 @@ var wand = Entities.addEntity({
|
|||
});
|
||||
|
||||
function cleanup() {
|
||||
//Entities.deleteEntity(wand);
|
||||
Entities.deleteEntity(wand);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -761,7 +761,7 @@ void MyAvatar::setEnableDebugDrawAnimPose(bool isEnabled) {
|
|||
_enableDebugDrawAnimPose = isEnabled;
|
||||
|
||||
if (!isEnabled) {
|
||||
AnimDebugDraw::getInstance().removeAnimNode("myAvatar");
|
||||
AnimDebugDraw::getInstance().removePoses("myAvatar");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1274,8 +1274,6 @@ void MyAvatar::initAnimGraph() {
|
|||
|
||||
void MyAvatar::destroyAnimGraph() {
|
||||
_rig->destroyAnimGraph();
|
||||
AnimDebugDraw::getInstance().removeSkeleton("myAvatar");
|
||||
AnimDebugDraw::getInstance().removeAnimNode("myAvatar");
|
||||
}
|
||||
|
||||
void MyAvatar::preRender(RenderArgs* renderArgs) {
|
||||
|
@ -1287,26 +1285,35 @@ void MyAvatar::preRender(RenderArgs* renderArgs) {
|
|||
initHeadBones();
|
||||
_skeletonModel.setCauterizeBoneSet(_headBoneSet);
|
||||
initAnimGraph();
|
||||
_debugDrawSkeleton = std::make_shared<AnimSkeleton>(_skeletonModel.getGeometry()->getFBXGeometry());
|
||||
}
|
||||
|
||||
if (_enableDebugDrawBindPose || _enableDebugDrawAnimPose) {
|
||||
|
||||
AnimSkeleton::ConstPointer animSkeleton = _rig->getAnimSkeleton();
|
||||
AnimNode::ConstPointer animNode = _rig->getAnimNode();
|
||||
|
||||
// bones space is rotated
|
||||
// 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());
|
||||
|
||||
if (animSkeleton && _enableDebugDrawBindPose) {
|
||||
if (_enableDebugDrawBindPose && _debugDrawSkeleton) {
|
||||
glm::vec4 gray(0.2f, 0.2f, 0.2f, 0.2f);
|
||||
AnimDebugDraw::getInstance().addSkeleton("myAvatar", animSkeleton, xform, gray);
|
||||
AnimDebugDraw::getInstance().addSkeleton("myAvatar", _debugDrawSkeleton, xform, gray);
|
||||
}
|
||||
|
||||
// This only works for when new anim system is enabled, at the moment.
|
||||
if (animNode && animSkeleton && _enableDebugDrawAnimPose && _rig->getEnableAnimGraph()) {
|
||||
if (_enableDebugDrawAnimPose && _debugDrawSkeleton) {
|
||||
glm::vec4 cyan(0.1f, 0.6f, 0.6f, 1.0f);
|
||||
AnimDebugDraw::getInstance().addAnimNode("myAvatar", animNode, xform, cyan);
|
||||
|
||||
// build AnimPoseVec from JointStates.
|
||||
AnimPoseVec poses;
|
||||
poses.reserve(_debugDrawSkeleton->getNumJoints());
|
||||
for (int i = 0; i < _debugDrawSkeleton->getNumJoints(); i++) {
|
||||
AnimPose pose = _debugDrawSkeleton->getRelativeBindPose(i);
|
||||
glm::quat jointRot;
|
||||
_rig->getJointRotationInConstrainedFrame(i, jointRot);
|
||||
pose.rot = pose.rot * jointRot;
|
||||
poses.push_back(pose);
|
||||
}
|
||||
|
||||
AnimDebugDraw::getInstance().addPoses("myAvatar", _debugDrawSkeleton, poses, xform, cyan);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -323,6 +323,7 @@ private:
|
|||
|
||||
bool _enableDebugDrawBindPose = false;
|
||||
bool _enableDebugDrawAnimPose = false;
|
||||
AnimSkeleton::ConstPointer _debugDrawSkeleton = nullptr;
|
||||
};
|
||||
|
||||
#endif // hifi_MyAvatar_h
|
||||
|
|
|
@ -103,13 +103,15 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|||
_rig->computeMotionAnimationState(deltaTime, _owningAvatar->getPosition(), _owningAvatar->getVelocity(), _owningAvatar->getOrientation());
|
||||
}
|
||||
Model::updateRig(deltaTime, parentTransform);
|
||||
Head* head = _owningAvatar->getHead();
|
||||
if (_owningAvatar->isMyAvatar()) {
|
||||
MyAvatar* myAvatar = static_cast<MyAvatar*>(_owningAvatar);
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
Head* head = _owningAvatar->getHead();
|
||||
|
||||
Rig::HeadParameters params;
|
||||
params.modelRotation = getRotation();
|
||||
params.modelTranslation = getTranslation();
|
||||
params.enableLean = qApp->isHMDMode() && !myAvatar->getStandingHMDSensorMode();
|
||||
params.leanSideways = head->getFinalLeanSideways();
|
||||
params.leanForward = head->getFinalLeanForward();
|
||||
params.torsoTwist = head->getTorsoTwist();
|
||||
|
@ -133,7 +135,6 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|||
// However, in the !isLookingAtMe case, the eyes aren't rotating the way they should right now.
|
||||
// We will revisit that as priorities allow, and particularly after the new rig/animation/joints.
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
Head* head = _owningAvatar->getHead();
|
||||
// If the head is not positioned, updateEyeJoints won't get the math right
|
||||
glm::quat headOrientation;
|
||||
_rig->getJointRotation(geometry.headJointIndex, headOrientation);
|
||||
|
@ -548,14 +549,24 @@ void SkeletonModel::computeBoundingShape() {
|
|||
totalExtents.addPoint(glm::vec3(0.0f));
|
||||
int numStates = _rig->getJointStateCount();
|
||||
for (int i = 0; i < numStates; i++) {
|
||||
// compute the default transform of this joint
|
||||
const JointState& state = _rig->getJointState(i);
|
||||
|
||||
// Each joint contributes a sphere at its position
|
||||
glm::vec3 axis(state.getBoneRadius());
|
||||
glm::vec3 jointPosition = state.getPosition();
|
||||
totalExtents.addPoint(jointPosition + axis);
|
||||
totalExtents.addPoint(jointPosition - axis);
|
||||
const glm::mat4& jointTransform = state.getTransform();
|
||||
float scale = extractUniformScale(jointTransform);
|
||||
|
||||
// Each joint contributes a capsule defined by FBXJoint.shapeInfo.
|
||||
// For totalExtents we use the capsule endpoints expanded by the radius.
|
||||
const FBXJointShapeInfo& shapeInfo = geometry.joints.at(i).shapeInfo;
|
||||
for (int j = 0; j < shapeInfo.points.size(); ++j) {
|
||||
glm::vec3 transformedPoint = extractTranslation(jointTransform * glm::translate(shapeInfo.points[j]));
|
||||
vec3 radius(scale * shapeInfo.radius);
|
||||
totalExtents.addPoint(transformedPoint + radius);
|
||||
totalExtents.addPoint(transformedPoint - radius);
|
||||
}
|
||||
// HACK so that default legless robot doesn't knuckle-drag
|
||||
if (shapeInfo.points.size() == 0 && (state.getName() == "LeftFoot" || state.getName() == "RightFoot")) {
|
||||
totalExtents.addPoint(extractTranslation(jointTransform));
|
||||
}
|
||||
}
|
||||
|
||||
// compute bounding shape parameters
|
||||
|
|
|
@ -58,7 +58,52 @@ AnimPose::operator glm::mat4() const {
|
|||
glm::vec4(zAxis, 0.0f), glm::vec4(trans, 1.0f));
|
||||
}
|
||||
|
||||
AnimSkeleton::AnimSkeleton(const FBXGeometry& fbxGeometry) {
|
||||
// convert to std::vector of joints
|
||||
std::vector<FBXJoint> joints;
|
||||
joints.reserve(fbxGeometry.joints.size());
|
||||
for (auto& joint : fbxGeometry.joints) {
|
||||
joints.push_back(joint);
|
||||
}
|
||||
|
||||
AnimPose geometryOffset(fbxGeometry.offset);
|
||||
buildSkeletonFromJoints(joints, geometryOffset);
|
||||
}
|
||||
|
||||
AnimSkeleton::AnimSkeleton(const std::vector<FBXJoint>& joints, const AnimPose& geometryOffset) {
|
||||
buildSkeletonFromJoints(joints, geometryOffset);
|
||||
}
|
||||
|
||||
int AnimSkeleton::nameToJointIndex(const QString& jointName) const {
|
||||
for (size_t i = 0; i < _joints.size(); i++) {
|
||||
if (_joints[i].name == jointName) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int AnimSkeleton::getNumJoints() const {
|
||||
return _joints.size();
|
||||
}
|
||||
|
||||
const AnimPose& AnimSkeleton::getAbsoluteBindPose(int jointIndex) const {
|
||||
return _absoluteBindPoses[jointIndex];
|
||||
}
|
||||
|
||||
const AnimPose& AnimSkeleton::getRelativeBindPose(int jointIndex) const {
|
||||
return _relativeBindPoses[jointIndex];
|
||||
}
|
||||
|
||||
int AnimSkeleton::getParentIndex(int jointIndex) const {
|
||||
return _joints[jointIndex].parentIndex;
|
||||
}
|
||||
|
||||
const QString& AnimSkeleton::getJointName(int jointIndex) const {
|
||||
return _joints[jointIndex].name;
|
||||
}
|
||||
|
||||
void AnimSkeleton::buildSkeletonFromJoints(const std::vector<FBXJoint>& joints, const AnimPose& geometryOffset) {
|
||||
_joints = joints;
|
||||
|
||||
// build a cache of bind poses
|
||||
|
@ -113,35 +158,6 @@ AnimSkeleton::AnimSkeleton(const std::vector<FBXJoint>& joints, const AnimPose&
|
|||
}
|
||||
}
|
||||
|
||||
int AnimSkeleton::nameToJointIndex(const QString& jointName) const {
|
||||
for (size_t i = 0; i < _joints.size(); i++) {
|
||||
if (_joints[i].name == jointName) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int AnimSkeleton::getNumJoints() const {
|
||||
return _joints.size();
|
||||
}
|
||||
|
||||
AnimPose AnimSkeleton::getAbsoluteBindPose(int jointIndex) const {
|
||||
return _absoluteBindPoses[jointIndex];
|
||||
}
|
||||
|
||||
AnimPose AnimSkeleton::getRelativeBindPose(int jointIndex) const {
|
||||
return _relativeBindPoses[jointIndex];
|
||||
}
|
||||
|
||||
int AnimSkeleton::getParentIndex(int jointIndex) const {
|
||||
return _joints[jointIndex].parentIndex;
|
||||
}
|
||||
|
||||
const QString& AnimSkeleton::getJointName(int jointIndex) const {
|
||||
return _joints[jointIndex].name;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void AnimSkeleton::dump() const {
|
||||
qCDebug(animation) << "[";
|
||||
|
|
|
@ -47,16 +47,17 @@ public:
|
|||
using Pointer = std::shared_ptr<AnimSkeleton>;
|
||||
using ConstPointer = std::shared_ptr<const AnimSkeleton>;
|
||||
|
||||
AnimSkeleton(const FBXGeometry& fbxGeometry);
|
||||
AnimSkeleton(const std::vector<FBXJoint>& joints, const AnimPose& geometryOffset);
|
||||
int nameToJointIndex(const QString& jointName) const;
|
||||
const QString& getJointName(int jointIndex) const;
|
||||
int getNumJoints() const;
|
||||
|
||||
// absolute pose, not relative to parent
|
||||
AnimPose getAbsoluteBindPose(int jointIndex) const;
|
||||
const AnimPose& getAbsoluteBindPose(int jointIndex) const;
|
||||
|
||||
// relative to parent pose
|
||||
AnimPose getRelativeBindPose(int jointIndex) const;
|
||||
const AnimPose& getRelativeBindPose(int jointIndex) const;
|
||||
|
||||
int getParentIndex(int jointIndex) const;
|
||||
|
||||
|
@ -66,6 +67,8 @@ public:
|
|||
#endif
|
||||
|
||||
protected:
|
||||
void buildSkeletonFromJoints(const std::vector<FBXJoint>& joints, const AnimPose& geometryOffset);
|
||||
|
||||
std::vector<FBXJoint> _joints;
|
||||
AnimPoseVec _absoluteBindPoses;
|
||||
AnimPoseVec _relativeBindPoses;
|
||||
|
|
|
@ -41,7 +41,6 @@ void JointState::copyState(const JointState& other) {
|
|||
// DO NOT copy _constraint
|
||||
_name = other._name;
|
||||
_isFree = other._isFree;
|
||||
_boneRadius = other._boneRadius;
|
||||
_parentIndex = other._parentIndex;
|
||||
_defaultRotation = other._defaultRotation;
|
||||
_inverseDefaultRotation = other._inverseDefaultRotation;
|
||||
|
@ -58,7 +57,6 @@ JointState::JointState(const FBXJoint& joint) {
|
|||
_rotationInConstrainedFrame = joint.rotation;
|
||||
_name = joint.name;
|
||||
_isFree = joint.isFree;
|
||||
_boneRadius = joint.boneRadius;
|
||||
_parentIndex = joint.parentIndex;
|
||||
_translation = joint.translation;
|
||||
_defaultRotation = joint.rotation;
|
||||
|
|
|
@ -118,7 +118,6 @@ public:
|
|||
const glm::quat& getDefaultRotation() const { return _defaultRotation; }
|
||||
const glm::quat& getInverseDefaultRotation() const { return _inverseDefaultRotation; }
|
||||
const QString& getName() const { return _name; }
|
||||
float getBoneRadius() const { return _boneRadius; }
|
||||
bool getIsFree() const { return _isFree; }
|
||||
float getAnimationPriority() const { return _animationPriority; }
|
||||
void setAnimationPriority(float priority) { _animationPriority = priority; }
|
||||
|
@ -149,7 +148,6 @@ private:
|
|||
QString _name;
|
||||
int _parentIndex;
|
||||
bool _isFree;
|
||||
float _boneRadius;
|
||||
glm::vec3 _rotationMin;
|
||||
glm::vec3 _rotationMax;
|
||||
glm::quat _preRotation;
|
||||
|
|
|
@ -477,7 +477,7 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
|
|||
}
|
||||
|
||||
if (glm::length(localVel) > moveThresh) {
|
||||
if (fabs(forwardSpeed) > 0.5f * fabs(lateralSpeed)) {
|
||||
if (fabsf(forwardSpeed) > 0.5f * fabsf(lateralSpeed)) {
|
||||
if (forwardSpeed > 0.0f) {
|
||||
// forward
|
||||
_animVars.set("isMovingForward", true);
|
||||
|
@ -501,7 +501,7 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
|
|||
}
|
||||
_state = RigRole::Move;
|
||||
} else {
|
||||
if (fabs(turningSpeed) > turnThresh) {
|
||||
if (fabsf(turningSpeed) > turnThresh) {
|
||||
if (turningSpeed > 0.0f) {
|
||||
// turning right
|
||||
_animVars.set("isTurningRight", true);
|
||||
|
@ -901,19 +901,20 @@ glm::quat Rig::setJointRotationInConstrainedFrame(int jointIndex, glm::quat targ
|
|||
return endRotation;
|
||||
}
|
||||
|
||||
bool Rig::getJointRotationInConstrainedFrame(int jointIndex, glm::quat& quatOut) const {
|
||||
if (jointIndex == -1 || _jointStates.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
quatOut = _jointStates[jointIndex].getRotationInConstrainedFrame();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Rig::updateVisibleJointStates() {
|
||||
for (int i = 0; i < _jointStates.size(); i++) {
|
||||
_jointStates[i].slaveVisibleTransform();
|
||||
}
|
||||
}
|
||||
|
||||
void Rig::setJointTransform(int jointIndex, glm::mat4 newTransform) {
|
||||
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
|
||||
return;
|
||||
}
|
||||
_jointStates[jointIndex].setTransform(newTransform);
|
||||
}
|
||||
|
||||
void Rig::setJointVisibleTransform(int jointIndex, glm::mat4 newTransform) {
|
||||
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
|
||||
return;
|
||||
|
@ -936,7 +937,9 @@ glm::quat Rig::getJointDefaultRotationInParentFrame(int jointIndex) {
|
|||
}
|
||||
|
||||
void Rig::updateFromHeadParameters(const HeadParameters& params) {
|
||||
updateLeanJoint(params.leanJointIndex, params.leanSideways, params.leanForward, params.torsoTwist);
|
||||
if (params.enableLean) {
|
||||
updateLeanJoint(params.leanJointIndex, params.leanSideways, params.leanForward, params.torsoTwist);
|
||||
}
|
||||
updateNeckJoint(params.neckJointIndex, params.localHeadOrientation, params.leanSideways, params.leanForward, params.torsoTwist);
|
||||
updateEyeJoints(params.leftEyeJointIndex, params.rightEyeJointIndex, params.modelTranslation, params.modelRotation,
|
||||
params.worldHeadOrientation, params.eyeLookAt, params.eyeSaccade);
|
||||
|
@ -1010,16 +1013,7 @@ void Rig::initAnimGraph(const QUrl& url, const FBXGeometry& fbxGeometry) {
|
|||
return;
|
||||
}
|
||||
|
||||
// convert to std::vector of joints
|
||||
std::vector<FBXJoint> joints;
|
||||
joints.reserve(fbxGeometry.joints.size());
|
||||
for (auto& joint : fbxGeometry.joints) {
|
||||
joints.push_back(joint);
|
||||
}
|
||||
|
||||
// create skeleton
|
||||
AnimPose geometryOffset(fbxGeometry.offset);
|
||||
_animSkeleton = std::make_shared<AnimSkeleton>(joints, geometryOffset);
|
||||
_animSkeleton = std::make_shared<AnimSkeleton>(fbxGeometry);
|
||||
|
||||
// load the anim graph
|
||||
_animLoader.reset(new AnimNodeLoader(url));
|
||||
|
|
|
@ -50,13 +50,13 @@ class Rig;
|
|||
typedef std::shared_ptr<Rig> RigPointer;
|
||||
|
||||
class Rig : public QObject, public std::enable_shared_from_this<Rig> {
|
||||
|
||||
public:
|
||||
|
||||
struct HeadParameters {
|
||||
float leanSideways = 0.0f; // degrees
|
||||
float leanForward = 0.0f; // degrees
|
||||
float torsoTwist = 0.0f; // degrees
|
||||
bool enableLean = false;
|
||||
glm::quat modelRotation = glm::quat();
|
||||
glm::quat localHeadOrientation = glm::quat();
|
||||
glm::quat worldHeadOrientation = glm::quat();
|
||||
|
@ -133,7 +133,6 @@ public:
|
|||
glm::vec3 translation, glm::quat rotation) const;
|
||||
bool getVisibleJointRotationInWorldFrame(int jointIndex, glm::quat& result, glm::quat rotation) const;
|
||||
glm::mat4 getJointTransform(int jointIndex) const;
|
||||
void setJointTransform(int jointIndex, glm::mat4 newTransform);
|
||||
glm::mat4 getJointVisibleTransform(int jointIndex) const;
|
||||
void setJointVisibleTransform(int jointIndex, glm::mat4 newTransform);
|
||||
// Start or stop animations as needed.
|
||||
|
@ -153,6 +152,7 @@ public:
|
|||
glm::vec3 getJointDefaultTranslationInConstrainedFrame(int jointIndex);
|
||||
glm::quat setJointRotationInConstrainedFrame(int jointIndex, glm::quat targetRotation,
|
||||
float priority, bool constrain = false, float mix = 1.0f);
|
||||
bool getJointRotationInConstrainedFrame(int jointIndex, glm::quat& rotOut) const;
|
||||
glm::quat getJointDefaultRotationInParentFrame(int jointIndex);
|
||||
void updateVisibleJointStates();
|
||||
|
||||
|
|
|
@ -1257,21 +1257,7 @@ QString getString(const QVariant& value) {
|
|||
return list.isEmpty() ? value.toString() : list.at(0).toString();
|
||||
}
|
||||
|
||||
class JointShapeInfo {
|
||||
public:
|
||||
JointShapeInfo() : numVertices(0),
|
||||
sumVertexWeights(0.0f), sumWeightedRadii(0.0f), numVertexWeights(0),
|
||||
boneBegin(0.0f), averageRadius(0.0f) {
|
||||
}
|
||||
|
||||
// NOTE: the points here are in the "joint frame" which has the "jointEnd" at the origin
|
||||
int numVertices; // num vertices from contributing meshes
|
||||
float sumVertexWeights; // sum of all vertex weights
|
||||
float sumWeightedRadii; // sum of weighted vertices
|
||||
int numVertexWeights; // num vertices that contributed to sums
|
||||
glm::vec3 boneBegin; // parent joint location (in joint frame)
|
||||
float averageRadius;
|
||||
};
|
||||
typedef std::vector<glm::vec3> ShapeVertices;
|
||||
|
||||
class AnimationCurve {
|
||||
public:
|
||||
|
@ -2282,22 +2268,21 @@ FBXGeometry* extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping
|
|||
joint.postTransform = model.postTransform;
|
||||
joint.rotationMin = model.rotationMin;
|
||||
joint.rotationMax = model.rotationMax;
|
||||
glm::quat combinedRotation = model.preRotation * model.rotation * model.postRotation;
|
||||
glm::quat combinedRotation = joint.preRotation * joint.rotation * joint.postRotation;
|
||||
if (joint.parentIndex == -1) {
|
||||
joint.transform = geometry.offset * glm::translate(model.translation) * model.preTransform *
|
||||
glm::mat4_cast(combinedRotation) * model.postTransform;
|
||||
joint.transform = geometry.offset * glm::translate(joint.translation) * joint.preTransform *
|
||||
glm::mat4_cast(combinedRotation) * joint.postTransform;
|
||||
joint.inverseDefaultRotation = glm::inverse(combinedRotation);
|
||||
joint.distanceToParent = 0.0f;
|
||||
joint.distanceToParent = 0.0f;
|
||||
|
||||
} else {
|
||||
const FBXJoint& parentJoint = geometry.joints.at(joint.parentIndex);
|
||||
joint.transform = parentJoint.transform * glm::translate(model.translation) *
|
||||
model.preTransform * glm::mat4_cast(combinedRotation) * model.postTransform;
|
||||
joint.transform = parentJoint.transform * glm::translate(joint.translation) *
|
||||
joint.preTransform * glm::mat4_cast(combinedRotation) * joint.postTransform;
|
||||
joint.inverseDefaultRotation = glm::inverse(combinedRotation) * parentJoint.inverseDefaultRotation;
|
||||
joint.distanceToParent = glm::distance(extractTranslation(parentJoint.transform),
|
||||
extractTranslation(joint.transform));
|
||||
}
|
||||
joint.boneRadius = 0.0f;
|
||||
joint.inverseBindRotation = joint.inverseDefaultRotation;
|
||||
joint.name = model.name;
|
||||
|
||||
|
@ -2326,9 +2311,10 @@ FBXGeometry* extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping
|
|||
zCurve.values.isEmpty() ? defaultValues.z : zCurve.values.at(i % zCurve.values.size()))));
|
||||
}
|
||||
}
|
||||
// for each joint we allocate a JointShapeInfo in which we'll store collision shape info
|
||||
QVector<JointShapeInfo> jointShapeInfos;
|
||||
jointShapeInfos.resize(geometry.joints.size());
|
||||
|
||||
// NOTE: shapeVertices are in joint-frame
|
||||
QVector<ShapeVertices> shapeVertices;
|
||||
shapeVertices.resize(geometry.joints.size());
|
||||
|
||||
// find our special joints
|
||||
geometry.leftEyeJointIndex = modelIDs.indexOf(jointEyeLeftID);
|
||||
|
@ -2585,8 +2571,10 @@ FBXGeometry* extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping
|
|||
boneDirection /= boneLength;
|
||||
}
|
||||
}
|
||||
float radiusScale = extractUniformScale(joint.transform * fbxCluster.inverseBindMatrix);
|
||||
JointShapeInfo& jointShapeInfo = jointShapeInfos[jointIndex];
|
||||
|
||||
float clusterScale = extractUniformScale(fbxCluster.inverseBindMatrix);
|
||||
glm::mat4 meshToJoint = glm::inverse(joint.bindTransform) * modelTransform;
|
||||
ShapeVertices& points = shapeVertices[jointIndex];
|
||||
|
||||
float totalWeight = 0.0f;
|
||||
for (int j = 0; j < cluster.indices.size(); j++) {
|
||||
|
@ -2595,18 +2583,13 @@ FBXGeometry* extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping
|
|||
totalWeight += weight;
|
||||
for (QMultiHash<int, int>::const_iterator it = extracted.newIndices.constFind(oldIndex);
|
||||
it != extracted.newIndices.end() && it.key() == oldIndex; it++) {
|
||||
// expand the bone radius for vertices with at least 1/4 weight
|
||||
|
||||
// remember vertices with at least 1/4 weight
|
||||
const float EXPANSION_WEIGHT_THRESHOLD = 0.25f;
|
||||
if (weight > EXPANSION_WEIGHT_THRESHOLD) {
|
||||
const glm::vec3& vertex = extracted.mesh.vertices.at(it.value());
|
||||
float proj = glm::dot(boneDirection, boneEnd - vertex);
|
||||
float radiusWeight = (proj < 0.0f || proj > boneLength) ? 0.5f * weight : weight;
|
||||
|
||||
jointShapeInfo.sumVertexWeights += radiusWeight;
|
||||
jointShapeInfo.sumWeightedRadii += radiusWeight * radiusScale * glm::distance(vertex, boneEnd - boneDirection * proj);
|
||||
++jointShapeInfo.numVertexWeights;
|
||||
|
||||
++jointShapeInfo.numVertices;
|
||||
// transform to joint-frame and save for later
|
||||
const glm::mat4 vertexTransform = meshToJoint * glm::translate(extracted.mesh.vertices.at(it.value()));
|
||||
points.push_back(extractTranslation(vertexTransform) * clusterScale);
|
||||
}
|
||||
|
||||
// look for an unused slot in the weights vector
|
||||
|
@ -2649,54 +2632,16 @@ FBXGeometry* extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping
|
|||
// this is a single-mesh joint
|
||||
int jointIndex = maxJointIndex;
|
||||
FBXJoint& joint = geometry.joints[jointIndex];
|
||||
JointShapeInfo& jointShapeInfo = jointShapeInfos[jointIndex];
|
||||
|
||||
glm::mat4 transformJointToMesh = inverseModelTransform * joint.bindTransform;
|
||||
glm::vec3 boneEnd = extractTranslation(transformJointToMesh);
|
||||
glm::vec3 boneBegin = boneEnd;
|
||||
|
||||
glm::vec3 boneDirection;
|
||||
float boneLength = 0.0f;
|
||||
if (joint.parentIndex != -1) {
|
||||
boneBegin = extractTranslation(inverseModelTransform * geometry.joints[joint.parentIndex].bindTransform);
|
||||
boneDirection = boneEnd - boneBegin;
|
||||
boneLength = glm::length(boneDirection);
|
||||
if (boneLength > EPSILON) {
|
||||
boneDirection /= boneLength;
|
||||
}
|
||||
}
|
||||
float radiusScale = extractUniformScale(joint.transform * firstFBXCluster.inverseBindMatrix);
|
||||
|
||||
// compute average vertex
|
||||
glm::vec3 averageVertex(0.0f);
|
||||
// transform cluster vertices to joint-frame and save for later
|
||||
float clusterScale = extractUniformScale(firstFBXCluster.inverseBindMatrix);
|
||||
glm::mat4 meshToJoint = glm::inverse(joint.bindTransform) * modelTransform;
|
||||
ShapeVertices& points = shapeVertices[jointIndex];
|
||||
foreach (const glm::vec3& vertex, extracted.mesh.vertices) {
|
||||
float proj = glm::dot(boneDirection, boneEnd - vertex);
|
||||
float radiusWeight = (proj < 0.0f || proj > boneLength) ? 0.5f : 1.0f;
|
||||
jointShapeInfo.sumVertexWeights += radiusWeight;
|
||||
jointShapeInfo.sumWeightedRadii += radiusWeight * radiusScale * glm::distance(vertex, boneEnd - boneDirection * proj);
|
||||
++jointShapeInfo.numVertexWeights;
|
||||
averageVertex += vertex;
|
||||
const glm::mat4 vertexTransform = meshToJoint * glm::translate(vertex);
|
||||
points.push_back(extractTranslation(vertexTransform) * clusterScale);
|
||||
}
|
||||
|
||||
// compute joint's radius
|
||||
int numVertices = extracted.mesh.vertices.size();
|
||||
jointShapeInfo.numVertices = numVertices;
|
||||
if (numVertices > 0) {
|
||||
// compute average radius
|
||||
averageVertex /= (float)jointShapeInfo.numVertices;
|
||||
float averageRadius = 0.0f;
|
||||
foreach (const glm::vec3& vertex, extracted.mesh.vertices) {
|
||||
averageRadius += glm::distance(vertex, averageVertex);
|
||||
}
|
||||
averageRadius *= radiusScale / (float)jointShapeInfo.numVertices;
|
||||
|
||||
// final radius is minimum of average and weighted
|
||||
float weightedRadius = jointShapeInfo.sumWeightedRadii / jointShapeInfo.sumVertexWeights;
|
||||
jointShapeInfo.averageRadius = glm::min(weightedRadius, averageRadius);
|
||||
}
|
||||
|
||||
// clear sumVertexWeights (this flags it as a single-mesh joint for later)
|
||||
jointShapeInfo.sumVertexWeights = 0.0f;
|
||||
}
|
||||
extracted.mesh.isEye = (maxJointIndex == geometry.leftEyeJointIndex || maxJointIndex == geometry.rightEyeJointIndex);
|
||||
|
||||
|
@ -2721,24 +2666,59 @@ FBXGeometry* extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping
|
|||
glm::vec3 defaultCapsuleAxis(0.0f, 1.0f, 0.0f);
|
||||
for (int i = 0; i < geometry.joints.size(); ++i) {
|
||||
FBXJoint& joint = geometry.joints[i];
|
||||
JointShapeInfo& jointShapeInfo = jointShapeInfos[i];
|
||||
|
||||
if (joint.parentIndex == -1) {
|
||||
jointShapeInfo.boneBegin = glm::vec3(0.0f);
|
||||
// NOTE: points are in joint-frame
|
||||
// compute average point
|
||||
ShapeVertices& points = shapeVertices[i];
|
||||
glm::vec3 avgPoint = glm::vec3(0.0f);
|
||||
for (uint32_t j = 0; j < points.size(); ++j) {
|
||||
avgPoint += points[j];
|
||||
}
|
||||
avgPoint /= (float)points.size();
|
||||
|
||||
// compute axis from begin to avgPoint
|
||||
glm::vec3 begin(0.0f);
|
||||
glm::vec3 end = avgPoint;
|
||||
glm::vec3 axis = end - begin;
|
||||
float axisLength = glm::length(axis);
|
||||
if (axisLength > EPSILON) {
|
||||
axis /= axisLength;
|
||||
} else {
|
||||
const FBXJoint& parentJoint = geometry.joints[joint.parentIndex];
|
||||
glm::quat inverseRotation = glm::inverse(extractRotation(joint.transform));
|
||||
jointShapeInfo.boneBegin = inverseRotation * (extractTranslation(parentJoint.transform) - extractTranslation(joint.transform));
|
||||
axis = glm::vec3(0.0f);
|
||||
}
|
||||
|
||||
if (jointShapeInfo.sumVertexWeights > 0.0f) {
|
||||
// mutiple meshes contributed to the bone radius and now that all
|
||||
// contributing meshes are done we can finally compute the boneRadius
|
||||
joint.boneRadius = jointShapeInfo.sumWeightedRadii / jointShapeInfo.sumVertexWeights;
|
||||
} else {
|
||||
// single-mesh joint
|
||||
joint.boneRadius = jointShapeInfo.averageRadius;
|
||||
// measure average cylindrical radius
|
||||
float avgRadius = 0.0f;
|
||||
if (points.size() > 0) {
|
||||
float minProjection = FLT_MAX;
|
||||
float maxProjection = -FLT_MIN;
|
||||
for (uint32_t j = 0; j < points.size(); ++j) {
|
||||
glm::vec3 offset = points[j] - avgPoint;
|
||||
float projection = glm::dot(offset, axis);
|
||||
maxProjection = glm::max(maxProjection, projection);
|
||||
minProjection = glm::min(minProjection, projection);
|
||||
avgRadius += glm::length(offset - projection * axis);
|
||||
}
|
||||
avgRadius /= (float)points.size();
|
||||
|
||||
// compute endpoints of capsule in joint-frame
|
||||
glm::vec3 capsuleBegin = avgPoint;
|
||||
glm::vec3 capsuleEnd = avgPoint;
|
||||
if (maxProjection - minProjection < 2.0f * avgRadius) {
|
||||
// the mesh-as-cylinder approximation is too short to collide as a capsule
|
||||
// so we'll collapse it to a sphere (although that isn't a very good approximation)
|
||||
capsuleBegin = avgPoint + 0.5f * (maxProjection + minProjection) * axis;
|
||||
capsuleEnd = capsuleBegin;
|
||||
} else {
|
||||
capsuleBegin = avgPoint + (minProjection + avgRadius) * axis;
|
||||
capsuleEnd = avgPoint + (maxProjection - avgRadius) * axis;
|
||||
}
|
||||
|
||||
// save points for later
|
||||
joint.shapeInfo.points.push_back(capsuleBegin);
|
||||
joint.shapeInfo.points.push_back(capsuleEnd);
|
||||
}
|
||||
joint.shapeInfo.radius = avgRadius;
|
||||
}
|
||||
geometry.palmDirection = parseVec3(mapping.value("palmDirection", "0, -1, 0").toString());
|
||||
|
||||
|
|
|
@ -55,15 +55,21 @@ public:
|
|||
QVector<glm::vec3> normals;
|
||||
};
|
||||
|
||||
struct FBXJointShapeInfo {
|
||||
// same units and frame as FBXJoint.translation
|
||||
QVector<glm::vec3> points;
|
||||
float radius;
|
||||
};
|
||||
|
||||
/// A single joint (transformation node) extracted from an FBX document.
|
||||
class FBXJoint {
|
||||
public:
|
||||
|
||||
bool isFree;
|
||||
FBXJointShapeInfo shapeInfo;
|
||||
QVector<int> freeLineage;
|
||||
bool isFree;
|
||||
int parentIndex;
|
||||
float distanceToParent;
|
||||
float boneRadius;
|
||||
|
||||
// http://download.autodesk.com/us/fbx/20112/FBX_SDK_HELP/SDKRef/a00209.html
|
||||
|
||||
|
|
|
@ -441,7 +441,6 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping,
|
|||
geometry.joints[0].isFree = false;
|
||||
geometry.joints[0].parentIndex = -1;
|
||||
geometry.joints[0].distanceToParent = 0;
|
||||
geometry.joints[0].boneRadius = 0;
|
||||
geometry.joints[0].translation = glm::vec3(0, 0, 0);
|
||||
geometry.joints[0].rotationMin = glm::vec3(0, 0, 0);
|
||||
geometry.joints[0].rotationMax = glm::vec3(0, 0, 0);
|
||||
|
@ -617,7 +616,6 @@ void fbxDebugDump(const FBXGeometry& fbxgeo) {
|
|||
qCDebug(modelformat) << " freeLineage" << joint.freeLineage;
|
||||
qCDebug(modelformat) << " parentIndex" << joint.parentIndex;
|
||||
qCDebug(modelformat) << " distanceToParent" << joint.distanceToParent;
|
||||
qCDebug(modelformat) << " boneRadius" << joint.boneRadius;
|
||||
qCDebug(modelformat) << " translation" << joint.translation;
|
||||
qCDebug(modelformat) << " preTransform" << joint.preTransform;
|
||||
qCDebug(modelformat) << " preRotation" << joint.preRotation;
|
||||
|
|
|
@ -152,22 +152,30 @@ AnimDebugDraw::~AnimDebugDraw() {
|
|||
}
|
||||
}
|
||||
|
||||
void AnimDebugDraw::addSkeleton(std::string key, AnimSkeleton::ConstPointer skeleton, const AnimPose& rootPose, const glm::vec4& color) {
|
||||
void AnimDebugDraw::addSkeleton(const std::string& key, AnimSkeleton::ConstPointer skeleton, const AnimPose& rootPose, const glm::vec4& color) {
|
||||
_skeletons[key] = SkeletonInfo(skeleton, rootPose, color);
|
||||
}
|
||||
|
||||
void AnimDebugDraw::removeSkeleton(std::string key) {
|
||||
void AnimDebugDraw::removeSkeleton(const std::string& key) {
|
||||
_skeletons.erase(key);
|
||||
}
|
||||
|
||||
void AnimDebugDraw::addAnimNode(std::string key, AnimNode::ConstPointer animNode, const AnimPose& rootPose, const glm::vec4& color) {
|
||||
void AnimDebugDraw::addAnimNode(const std::string& key, AnimNode::ConstPointer animNode, const AnimPose& rootPose, const glm::vec4& color) {
|
||||
_animNodes[key] = AnimNodeInfo(animNode, rootPose, color);
|
||||
}
|
||||
|
||||
void AnimDebugDraw::removeAnimNode(std::string key) {
|
||||
void AnimDebugDraw::removeAnimNode(const std::string& key) {
|
||||
_animNodes.erase(key);
|
||||
}
|
||||
|
||||
void AnimDebugDraw::addPoses(const std::string& key, AnimSkeleton::ConstPointer skeleton, const AnimPoseVec& poses, const AnimPose& rootPose, const glm::vec4& color) {
|
||||
_poses[key] = PosesInfo(skeleton, poses, rootPose, color);
|
||||
}
|
||||
|
||||
void AnimDebugDraw::removePoses(const std::string& key) {
|
||||
_poses.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);
|
||||
|
@ -176,6 +184,8 @@ const int NUM_CIRCLE_SLICES = 24;
|
|||
|
||||
static void addBone(const AnimPose& rootPose, const AnimPose& pose, float radius, Vertex*& v) {
|
||||
|
||||
const float XYZ_AXIS_LENGTH = radius * 4.0f;
|
||||
|
||||
AnimPose finalPose = rootPose * pose;
|
||||
glm::vec3 base = rootPose * pose.trans;
|
||||
|
||||
|
@ -195,7 +205,7 @@ static void addBone(const AnimPose& rootPose, const AnimPose& pose, float radius
|
|||
v->pos = base;
|
||||
v->rgba = red;
|
||||
v++;
|
||||
v->pos = finalPose * glm::vec3(radius * 2.0f, 0.0f, 0.0f);
|
||||
v->pos = finalPose * glm::vec3(XYZ_AXIS_LENGTH, 0.0f, 0.0f);
|
||||
v->rgba = red;
|
||||
v++;
|
||||
|
||||
|
@ -213,7 +223,7 @@ static void addBone(const AnimPose& rootPose, const AnimPose& pose, float radius
|
|||
v->pos = base;
|
||||
v->rgba = green;
|
||||
v++;
|
||||
v->pos = finalPose * glm::vec3(0.0f, radius * 2.0f, 0.0f);
|
||||
v->pos = finalPose * glm::vec3(0.0f, XYZ_AXIS_LENGTH, 0.0f);
|
||||
v->rgba = green;
|
||||
v++;
|
||||
|
||||
|
@ -231,7 +241,7 @@ static void addBone(const AnimPose& rootPose, const AnimPose& pose, float radius
|
|||
v->pos = base;
|
||||
v->rgba = blue;
|
||||
v++;
|
||||
v->pos = finalPose * glm::vec3(0.0f, 0.0f, radius * 2.0f);
|
||||
v->pos = finalPose * glm::vec3(0.0f, 0.0f, XYZ_AXIS_LENGTH);
|
||||
v->rgba = blue;
|
||||
v++;
|
||||
|
||||
|
@ -322,11 +332,11 @@ void AnimDebugDraw::update() {
|
|||
const size_t VERTICES_PER_BONE = (6 + (NUM_CIRCLE_SLICES * 2) * 3);
|
||||
const size_t VERTICES_PER_LINK = 8 * 2;
|
||||
|
||||
const float BONE_RADIUS = 0.0075f;
|
||||
const float BONE_RADIUS = 0.01f; // 1 cm
|
||||
|
||||
// figure out how many verts we will need.
|
||||
int numVerts = 0;
|
||||
for (auto&& iter : _skeletons) {
|
||||
for (auto& iter : _skeletons) {
|
||||
AnimSkeleton::ConstPointer& skeleton = std::get<0>(iter.second);
|
||||
numVerts += skeleton->getNumJoints() * VERTICES_PER_BONE;
|
||||
for (int i = 0; i < skeleton->getNumJoints(); i++) {
|
||||
|
@ -337,7 +347,7 @@ void AnimDebugDraw::update() {
|
|||
}
|
||||
}
|
||||
|
||||
for (auto&& iter : _animNodes) {
|
||||
for (auto& iter : _animNodes) {
|
||||
AnimNode::ConstPointer& animNode = std::get<0>(iter.second);
|
||||
auto poses = animNode->getPosesInternal();
|
||||
numVerts += poses.size() * VERTICES_PER_BONE;
|
||||
|
@ -350,10 +360,21 @@ void AnimDebugDraw::update() {
|
|||
}
|
||||
}
|
||||
|
||||
for (auto& iter : _poses) {
|
||||
AnimSkeleton::ConstPointer& skeleton = std::get<0>(iter.second);
|
||||
numVerts += skeleton->getNumJoints() * VERTICES_PER_BONE;
|
||||
for (int i = 0; i < skeleton->getNumJoints(); i++) {
|
||||
auto parentIndex = skeleton->getParentIndex(i);
|
||||
if (parentIndex >= 0) {
|
||||
numVerts += VERTICES_PER_LINK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data._vertexBuffer->resize(sizeof(Vertex) * numVerts);
|
||||
Vertex* verts = (Vertex*)data._vertexBuffer->editData();
|
||||
Vertex* v = verts;
|
||||
for (auto&& iter : _skeletons) {
|
||||
for (auto& iter : _skeletons) {
|
||||
AnimSkeleton::ConstPointer& skeleton = std::get<0>(iter.second);
|
||||
AnimPose rootPose = std::get<1>(iter.second);
|
||||
int hipsIndex = skeleton->nameToJointIndex("Hips");
|
||||
|
@ -380,7 +401,7 @@ void AnimDebugDraw::update() {
|
|||
}
|
||||
}
|
||||
|
||||
for (auto&& iter : _animNodes) {
|
||||
for (auto& iter : _animNodes) {
|
||||
AnimNode::ConstPointer& animNode = std::get<0>(iter.second);
|
||||
AnimPose rootPose = std::get<1>(iter.second);
|
||||
if (animNode->_skeleton) {
|
||||
|
@ -418,6 +439,42 @@ void AnimDebugDraw::update() {
|
|||
}
|
||||
}
|
||||
|
||||
for (auto& iter : _poses) {
|
||||
AnimSkeleton::ConstPointer& skeleton = std::get<0>(iter.second);
|
||||
AnimPoseVec& poses = std::get<1>(iter.second);
|
||||
AnimPose rootPose = std::get<2>(iter.second);
|
||||
int hipsIndex = skeleton->nameToJointIndex("Hips");
|
||||
if (hipsIndex >= 0) {
|
||||
rootPose.trans -= skeleton->getRelativeBindPose(hipsIndex).trans;
|
||||
}
|
||||
glm::vec4 color = std::get<3>(iter.second);
|
||||
|
||||
std::vector<AnimPose> absAnimPose;
|
||||
absAnimPose.resize(skeleton->getNumJoints());
|
||||
|
||||
for (int i = 0; i < skeleton->getNumJoints(); i++) {
|
||||
const AnimPose& pose = poses[i];
|
||||
|
||||
const float radius = BONE_RADIUS / (pose.scale.x * rootPose.scale.x);
|
||||
|
||||
auto parentIndex = skeleton->getParentIndex(i);
|
||||
if (parentIndex >= 0) {
|
||||
absAnimPose[i] = absAnimPose[parentIndex] * pose;
|
||||
} else {
|
||||
absAnimPose[i] = pose;
|
||||
}
|
||||
|
||||
// draw bone
|
||||
addBone(rootPose, absAnimPose[i], radius, v);
|
||||
|
||||
// draw link to parent
|
||||
if (parentIndex >= 0) {
|
||||
assert(parentIndex < skeleton->getNumJoints());
|
||||
addLink(rootPose, absAnimPose[i], absAnimPose[parentIndex], radius, color, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert(numVerts == (v - verts));
|
||||
|
||||
data._indexBuffer->resize(sizeof(uint16_t) * numVerts);
|
||||
|
|
|
@ -27,11 +27,14 @@ public:
|
|||
AnimDebugDraw();
|
||||
~AnimDebugDraw();
|
||||
|
||||
void addSkeleton(std::string key, AnimSkeleton::ConstPointer skeleton, const AnimPose& rootPose, const glm::vec4& color);
|
||||
void removeSkeleton(std::string key);
|
||||
void addSkeleton(const std::string& key, AnimSkeleton::ConstPointer skeleton, const AnimPose& rootPose, const glm::vec4& color);
|
||||
void removeSkeleton(const std::string& key);
|
||||
|
||||
void addAnimNode(std::string key, AnimNode::ConstPointer animNode, const AnimPose& rootPose, const glm::vec4& color);
|
||||
void removeAnimNode(std::string key);
|
||||
void addAnimNode(const std::string& key, AnimNode::ConstPointer animNode, const AnimPose& rootPose, const glm::vec4& color);
|
||||
void removeAnimNode(const std::string& key);
|
||||
|
||||
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);
|
||||
|
||||
void update();
|
||||
|
||||
|
@ -44,9 +47,11 @@ 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;
|
||||
|
||||
std::unordered_map<std::string, SkeletonInfo> _skeletons;
|
||||
std::unordered_map<std::string, AnimNodeInfo> _animNodes;
|
||||
std::unordered_map<std::string, PosesInfo> _poses;
|
||||
|
||||
// no copies
|
||||
AnimDebugDraw(const AnimDebugDraw&) = delete;
|
||||
|
|
Loading…
Reference in a new issue