WIP checkin

* AnimManipulator: added absolute and relative position and translation support
* Rig: added _overrideFlags and _overridePoses for script overrides.
This commit is contained in:
Anthony J. Thibault 2015-11-16 18:49:47 -08:00
parent 516aff2ee0
commit 80eb247b9c
10 changed files with 258 additions and 87 deletions

View file

@ -75,7 +75,7 @@ function updateJoints(factor){
for (var i = 0; i < startPoseAndTransition.length; i++){ for (var i = 0; i < startPoseAndTransition.length; i++){
var scaledTransition = Vec3.multiply(startPoseAndTransition[i].transition, factor); var scaledTransition = Vec3.multiply(startPoseAndTransition[i].transition, factor);
var rotation = Vec3.sum(startPoseAndTransition[i].start, scaledTransition); var rotation = Vec3.sum(startPoseAndTransition[i].start, scaledTransition);
MyAvatar.setJointData(startPoseAndTransition[i].joint, Quat.fromVec3Degrees( rotation )); MyAvatar.setJointRotation(startPoseAndTransition[i].joint, Quat.fromVec3Degrees( rotation ));
} }
} }
@ -282,7 +282,8 @@ function update(deltaTime){
MyAvatar.position.z != avatarOldPosition.z || MyAvatar.position.z != avatarOldPosition.z ||
locationChanged) { locationChanged) {
avatarOldPosition = MyAvatar.position; avatarOldPosition = MyAvatar.position;
/*
var SEARCH_RADIUS = 50; var SEARCH_RADIUS = 50;
var foundModels = Entities.findEntities(MyAvatar.position, SEARCH_RADIUS); var foundModels = Entities.findEntities(MyAvatar.position, SEARCH_RADIUS);
// Let's remove indicator that got out of radius // Let's remove indicator that got out of radius
@ -306,6 +307,7 @@ function update(deltaTime){
if (hiddingSeats && passedTime >= animationLenght) { if (hiddingSeats && passedTime >= animationLenght) {
showIndicators(true); showIndicators(true);
} }
*/
} }
} }
var oldHost = location.hostname; var oldHost = location.hostname;

View file

@ -104,7 +104,7 @@
"data": { "data": {
"alpha": 0.0, "alpha": 0.0,
"joints": [ "joints": [
{ "var": "lean", "jointName": "Spine" } { "type": "absoluteRotation", "jointName": "Spine", "var": "lean" }
] ]
}, },
"children": [] "children": []

View file

@ -605,9 +605,9 @@ void SkeletonModel::computeBoundingShape() {
*/ */
// AJT: REMOVE HARDCODED BOUNDING VOLUME // AJT: REMOVE HARDCODED BOUNDING VOLUME
_boundingCapsuleRadius = 0.5f; _boundingCapsuleRadius = 0.3f;
_boundingCapsuleHeight = 2.0f; _boundingCapsuleHeight = 1.3f;
_boundingCapsuleLocalOffset = glm::vec3(0.0f, 1.0f, 0.0f); _boundingCapsuleLocalOffset = glm::vec3(0.0f, -0.25f, 0.0f);
} }
void SkeletonModel::renderBoundingCollisionShapes(gpu::Batch& batch, float alpha) { void SkeletonModel::renderBoundingCollisionShapes(gpu::Batch& batch, float alpha) {

View file

@ -46,39 +46,15 @@ const AnimPoseVec& AnimManipulator::overlay(const AnimVariantMap& animVars, floa
if (jointVar.jointIndex >= 0) { if (jointVar.jointIndex >= 0) {
AnimPose defaultAbsPose; // use the underPose as our default value if we can.
AnimPose defaultRelPose; AnimPose defaultRelPose;
AnimPose parentAbsPose = AnimPose::identity;
if (jointVar.jointIndex <= (int)underPoses.size()) { if (jointVar.jointIndex <= (int)underPoses.size()) {
// jointVar is an absolute rotation, if it is not set we will use the underPose as our default value
defaultRelPose = underPoses[jointVar.jointIndex]; defaultRelPose = underPoses[jointVar.jointIndex];
defaultAbsPose = _skeleton->getAbsolutePose(jointVar.jointIndex, underPoses);
defaultAbsPose.rot = animVars.lookup(jointVar.var, defaultAbsPose.rot);
// because jointVar is absolute, we must use an absolute parent frame to convert into a relative pose.
int parentIndex = _skeleton->getParentIndex(jointVar.jointIndex);
if (parentIndex >= 0) {
parentAbsPose = _skeleton->getAbsolutePose(parentIndex, underPoses);
}
} else { } else {
// jointVar is an absolute rotation, if it is not set we will use the bindPose as our default value
defaultRelPose = AnimPose::identity; defaultRelPose = AnimPose::identity;
defaultAbsPose = _skeleton->getAbsoluteBindPose(jointVar.jointIndex);
defaultAbsPose.rot = animVars.lookup(jointVar.var, defaultAbsPose.rot);
// because jointVar is absolute, we must use an absolute parent frame to convert into a relative pose
// here we use the bind pose
int parentIndex = _skeleton->getParentIndex(jointVar.jointIndex);
if (parentIndex >= 0) {
parentAbsPose = _skeleton->getAbsoluteBindPose(parentIndex);
}
} }
// convert from absolute to relative AnimPose relPose = computeRelativePoseFromJointVar(animVars, jointVar, defaultRelPose, underPoses);
AnimPose relPose = parentAbsPose.inverse() * defaultAbsPose;
// blend with underPose // blend with underPose
::blend(1, &defaultRelPose, &relPose, _alpha, &_poses[jointVar.jointIndex]); ::blend(1, &defaultRelPose, &relPose, _alpha, &_poses[jointVar.jointIndex]);
@ -114,3 +90,44 @@ const AnimPoseVec& AnimManipulator::getPosesInternal() const {
void AnimManipulator::addJointVar(const JointVar& jointVar) { void AnimManipulator::addJointVar(const JointVar& jointVar) {
_jointVars.push_back(jointVar); _jointVars.push_back(jointVar);
} }
void AnimManipulator::removeAllJointVars() {
_jointVars.clear();
}
AnimPose AnimManipulator::computeRelativePoseFromJointVar(const AnimVariantMap& animVars, const JointVar& jointVar,
const AnimPose& defaultRelPose, const AnimPoseVec& underPoses) {
AnimPose defaultAbsPose = _skeleton->getAbsolutePose(jointVar.jointIndex, underPoses);
if (jointVar.type == JointVar::Type::AbsoluteRotation || jointVar.type == JointVar::Type::AbsolutePosition) {
if (jointVar.type == JointVar::Type::AbsoluteRotation) {
defaultAbsPose.rot = animVars.lookup(jointVar.var, defaultAbsPose.rot);
} else if (jointVar.type == JointVar::Type::AbsolutePosition) {
defaultAbsPose.trans = animVars.lookup(jointVar.var, defaultAbsPose.trans);
}
// because jointVar is absolute, we must use an absolute parent frame to convert into a relative pose.
AnimPose parentAbsPose = AnimPose::identity;
int parentIndex = _skeleton->getParentIndex(jointVar.jointIndex);
if (parentIndex >= 0) {
parentAbsPose = _skeleton->getAbsolutePose(parentIndex, underPoses);
}
// convert from absolute to relative
return parentAbsPose.inverse() * defaultAbsPose;
} else {
// override the default rel pose
AnimPose relPose = defaultRelPose;
if (jointVar.type == JointVar::Type::RelativeRotation) {
relPose.rot = animVars.lookup(jointVar.var, defaultRelPose.rot);
} else if (jointVar.type == JointVar::Type::RelativePosition) {
relPose.trans = animVars.lookup(jointVar.var, defaultRelPose.trans);
}
return relPose;
}
}

View file

@ -30,19 +30,33 @@ public:
virtual void setSkeletonInternal(AnimSkeleton::ConstPointer skeleton) override; virtual void setSkeletonInternal(AnimSkeleton::ConstPointer skeleton) override;
struct JointVar { struct JointVar {
JointVar(const QString& varIn, const QString& jointNameIn) : var(varIn), jointName(jointNameIn), jointIndex(-1), hasPerformedJointLookup(false) {} enum class Type {
AbsoluteRotation = 0,
AbsolutePosition,
RelativeRotation,
RelativePosition,
NumTypes
};
JointVar(const QString& varIn, const QString& jointNameIn, Type typeIn) : var(varIn), jointName(jointNameIn), type(typeIn), jointIndex(-1), hasPerformedJointLookup(false) {}
QString var = ""; QString var = "";
QString jointName = ""; QString jointName = "";
Type type = Type::AbsoluteRotation;
int jointIndex = -1; int jointIndex = -1;
bool hasPerformedJointLookup = false; bool hasPerformedJointLookup = false;
bool isRelative = false;
}; };
void addJointVar(const JointVar& jointVar); void addJointVar(const JointVar& jointVar);
void removeAllJointVars();
protected: protected:
// for AnimDebugDraw rendering // for AnimDebugDraw rendering
virtual const AnimPoseVec& getPosesInternal() const override; virtual const AnimPoseVec& getPosesInternal() const override;
AnimPose computeRelativePoseFromJointVar(const AnimVariantMap& animVars, const JointVar& jointVar,
const AnimPose& defaultRelPose, const AnimPoseVec& underPoses);
AnimPoseVec _poses; AnimPoseVec _poses;
float _alpha; float _alpha;
QString _alphaVar; QString _alphaVar;

View file

@ -55,6 +55,41 @@ static const char* animNodeTypeToString(AnimNode::Type type) {
return nullptr; return nullptr;
} }
static AnimNode::Type stringToAnimNodeType(const QString& str) {
// O(n), move to map when number of types becomes large.
const int NUM_TYPES = static_cast<int>(AnimNode::Type::NumTypes);
for (int i = 0; i < NUM_TYPES; i++) {
AnimNode::Type type = static_cast<AnimNode::Type>(i);
if (str == animNodeTypeToString(type)) {
return type;
}
}
return AnimNode::Type::NumTypes;
}
static const char* animManipulatorJointVarTypeToString(AnimManipulator::JointVar::Type type) {
switch (type) {
case AnimManipulator::JointVar::Type::AbsoluteRotation: return "absoluteRotation";
case AnimManipulator::JointVar::Type::AbsolutePosition: return "absolutePosition";
case AnimManipulator::JointVar::Type::RelativeRotation: return "relativeRotation";
case AnimManipulator::JointVar::Type::RelativePosition: return "relativePosition";
case AnimManipulator::JointVar::Type::NumTypes: return nullptr;
};
return nullptr;
}
static AnimManipulator::JointVar::Type stringToAnimManipulatorJointVarType(const QString& str) {
// O(n), move to map when number of types becomes large.
const int NUM_TYPES = static_cast<int>(AnimManipulator::JointVar::Type::NumTypes);
for (int i = 0; i < NUM_TYPES; i++) {
AnimManipulator::JointVar::Type type = static_cast<AnimManipulator::JointVar::Type>(i);
if (str == animManipulatorJointVarTypeToString(type)) {
return type;
}
}
return AnimManipulator::JointVar::Type::NumTypes;
}
static NodeLoaderFunc animNodeTypeToLoaderFunc(AnimNode::Type type) { static NodeLoaderFunc animNodeTypeToLoaderFunc(AnimNode::Type type) {
switch (type) { switch (type) {
case AnimNode::Type::Clip: return loadClipNode; case AnimNode::Type::Clip: return loadClipNode;
@ -120,17 +155,6 @@ static NodeProcessFunc animNodeTypeToProcessFunc(AnimNode::Type type) {
} \ } \
float NAME = (float)NAME##_VAL.toDouble() float NAME = (float)NAME##_VAL.toDouble()
static AnimNode::Type stringToEnum(const QString& str) {
// O(n), move to map when number of types becomes large.
const int NUM_TYPES = static_cast<int>(AnimNode::Type::NumTypes);
for (int i = 0; i < NUM_TYPES; i++) {
AnimNode::Type type = static_cast<AnimNode::Type>(i);
if (str == animNodeTypeToString(type)) {
return type;
}
}
return AnimNode::Type::NumTypes;
}
static AnimNode::Pointer loadNode(const QJsonObject& jsonObj, const QUrl& jsonUrl) { static AnimNode::Pointer loadNode(const QJsonObject& jsonObj, const QUrl& jsonUrl) {
auto idVal = jsonObj.value("id"); auto idVal = jsonObj.value("id");
@ -146,7 +170,7 @@ static AnimNode::Pointer loadNode(const QJsonObject& jsonObj, const QUrl& jsonUr
return nullptr; return nullptr;
} }
QString typeStr = typeVal.toString(); QString typeStr = typeVal.toString();
AnimNode::Type type = stringToEnum(typeStr); AnimNode::Type type = stringToAnimNodeType(typeStr);
if (type == AnimNode::Type::NumTypes) { if (type == AnimNode::Type::NumTypes) {
qCCritical(animation) << "AnimNodeLoader, unknown node type" << typeStr << ", id =" << id << ", url =" << jsonUrl.toDisplayString(); qCCritical(animation) << "AnimNodeLoader, unknown node type" << typeStr << ", id =" << id << ", url =" << jsonUrl.toDisplayString();
return nullptr; return nullptr;
@ -355,10 +379,17 @@ static AnimNode::Pointer loadManipulatorNode(const QJsonObject& jsonObj, const Q
} }
auto jointObj = jointValue.toObject(); auto jointObj = jointValue.toObject();
READ_STRING(var, jointObj, id, jsonUrl, nullptr); READ_STRING(type, jointObj, id, jsonUrl, nullptr);
READ_STRING(jointName, jointObj, id, jsonUrl, nullptr); READ_STRING(jointName, jointObj, id, jsonUrl, nullptr);
READ_STRING(var, jointObj, id, jsonUrl, nullptr);
AnimManipulator::JointVar jointVar(var, jointName); AnimManipulator::JointVar::Type jointVarType = stringToAnimManipulatorJointVarType(type);
if (jointVarType == AnimManipulator::JointVar::Type::NumTypes) {
qCCritical(animation) << "AnimNodeLoader, bad type in \"joints\", id =" << id << ", url =" << jsonUrl.toDisplayString();
return nullptr;
}
AnimManipulator::JointVar jointVar(var, jointName, jointVarType);
node->addJointVar(jointVar); node->addJointVar(jointVar);
}; };

View file

@ -78,25 +78,40 @@ void AvatarRig::setHandPosition(int jointIndex,
void AvatarRig::setJointTranslation(int index, bool valid, const glm::vec3& translation, float priority) { void AvatarRig::setJointTranslation(int index, bool valid, const glm::vec3& translation, float priority) {
if (index != -1 && index < _jointStates.size()) { if (index != -1 && index < _jointStates.size()) {
JointState& state = _jointStates[index];
if (valid) { // AJT: LEGACY
state.setTranslation(translation, priority); {
} else { JointState& state = _jointStates[index];
state.restoreTranslation(1.0f, priority); if (valid) {
state.setTranslation(translation, priority);
} else {
state.restoreTranslation(1.0f, priority);
}
} }
_overrideFlags[index] = true;
_overridePoses[index].trans = translation;
} }
} }
void AvatarRig::setJointState(int index, bool valid, const glm::quat& rotation, const glm::vec3& translation, float priority) { void AvatarRig::setJointState(int index, bool valid, const glm::quat& rotation, const glm::vec3& translation, float priority) {
if (index != -1 && index < _jointStates.size()) { if (index != -1 && index < _jointStates.size()) {
JointState& state = _jointStates[index];
if (valid) { // AJT: LEGACY
state.setRotationInConstrainedFrame(rotation, priority); {
state.setTranslation(translation, priority); JointState& state = _jointStates[index];
} else { if (valid) {
state.restoreRotation(1.0f, priority); state.setRotationInConstrainedFrame(rotation, priority);
state.restoreTranslation(1.0f, priority); state.setTranslation(translation, priority);
} else {
state.restoreRotation(1.0f, priority);
state.restoreTranslation(1.0f, priority);
}
} }
_overrideFlags[index] = true;
_overridePoses[index].rot = rotation;
_overridePoses[index].trans = translation;
} }
} }

View file

@ -13,13 +13,20 @@
void EntityRig::setJointState(int index, bool valid, const glm::quat& rotation, const glm::vec3& translation, float priority) { void EntityRig::setJointState(int index, bool valid, const glm::quat& rotation, const glm::vec3& translation, float priority) {
if (index != -1 && index < _jointStates.size()) { if (index != -1 && index < _jointStates.size()) {
JointState& state = _jointStates[index];
if (valid) { // AJT: LEGACY
state.setRotationInConstrainedFrame(rotation, priority); {
// state.setTranslation(translation, priority); JointState& state = _jointStates[index];
} else { if (valid) {
state.restoreRotation(1.0f, priority); state.setRotationInConstrainedFrame(rotation, priority);
// state.restoreTranslation(1.0f, priority); // state.setTranslation(translation, priority);
} else {
state.restoreRotation(1.0f, priority);
// state.restoreTranslation(1.0f, priority);
}
} }
_overrideFlags[index] = true;
_overridePoses[index].rot = rotation;
} }
} }

View file

@ -23,16 +23,28 @@
#include "AnimClip.h" #include "AnimClip.h"
#include "IKTarget.h" #include "IKTarget.h"
#ifdef NDEBUG
#define ASSERT()
#else
#define ASSERT(cond) \
do { \
if (!(cond)) { \
int* ptr = nullptr; \
*ptr = 10; \
} \
} while (0)
#endif
void Rig::overrideAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame) { void Rig::overrideAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame) {
// find an unused AnimClip clipNode // find an unused AnimClip clipNode
std::shared_ptr<AnimClip> clip; std::shared_ptr<AnimClip> clip;
if (_userAnimState == UserAnimState::None || _userAnimState == UserAnimState::B) { if (_userAnimState == UserAnimState::None || _userAnimState == UserAnimState::B) {
_userAnimState = UserAnimState::A; _userAnimState = UserAnimState::A;
clip = std::dynamic_pointer_cast<AnimClip>(_animNode->getChild((int)_userAnimState)); clip = std::dynamic_pointer_cast<AnimClip>(_animNode->findByName("userAnimA"));
} else if (_userAnimState == UserAnimState::A) { } else if (_userAnimState == UserAnimState::A) {
_userAnimState = UserAnimState::B; _userAnimState = UserAnimState::B;
clip = std::dynamic_pointer_cast<AnimClip>(_animNode->getChild((int)_userAnimState)); clip = std::dynamic_pointer_cast<AnimClip>(_animNode->findByName("userAnimB"));
} }
// set parameters // set parameters
@ -132,6 +144,10 @@ void Rig::destroyAnimGraph() {
_animSkeleton = nullptr; _animSkeleton = nullptr;
_animLoader = nullptr; _animLoader = nullptr;
_animNode = nullptr; _animNode = nullptr;
_relativePoses.clear();
_absolutePoses.clear();
_overridePoses.clear();
_overrideFlags.clear();
} }
void Rig::initJointStates(const FBXGeometry& geometry, glm::mat4 modelOffset, int rootJointIndex, void Rig::initJointStates(const FBXGeometry& geometry, glm::mat4 modelOffset, int rootJointIndex,
@ -139,7 +155,18 @@ void Rig::initJointStates(const FBXGeometry& geometry, glm::mat4 modelOffset, in
int rightHandJointIndex, int rightElbowJointIndex, int rightShoulderJointIndex) { int rightHandJointIndex, int rightElbowJointIndex, int rightShoulderJointIndex) {
_animSkeleton = std::make_shared<AnimSkeleton>(geometry); _animSkeleton = std::make_shared<AnimSkeleton>(geometry);
_relativePoses.resize(_animSkeleton->getNumJoints());
_relativePoses.clear();
_relativePoses.resize(_animSkeleton->getNumJoints(), AnimPose::identity);
_absolutePoses.clear();
_absolutePoses.resize(_animSkeleton->getNumJoints(), AnimPose::identity);
_overridePoses.clear();
_overridePoses.resize(_animSkeleton->getNumJoints(), AnimPose::identity);
_overrideFlags.clear();
_overrideFlags.resize(_animSkeleton->getNumJoints(), true);
// AJT: LEGACY // AJT: LEGACY
{ {
@ -264,14 +291,25 @@ bool Rig::getJointStateTranslation(int index, glm::vec3& translation) const {
void Rig::clearJointState(int index) { void Rig::clearJointState(int index) {
if (index != -1 && index < _jointStates.size()) { if (index != -1 && index < _jointStates.size()) {
// AJT: REMOVE
/*
JointState& state = _jointStates[index]; JointState& state = _jointStates[index];
state.setRotationInConstrainedFrame(glm::quat(), 0.0f); state.setRotationInConstrainedFrame(glm::quat(), 0.0f);
state.setTranslation(state.getDefaultTranslationInConstrainedFrame(), 0.0f); state.setTranslation(state.getDefaultTranslationInConstrainedFrame(), 0.0f);
*/
_overrideFlags[index] = false;
} }
} }
void Rig::clearJointStates() { void Rig::clearJointStates() {
_jointStates.clear(); // AJT: LEGACY
/*
{
_jointStates.clear();
}
*/
_overrideFlags.clear();
_overrideFlags.resize(_animSkeleton->getNumJoints());
} }
void Rig::clearJointAnimationPriority(int index) { void Rig::clearJointAnimationPriority(int index) {
@ -375,12 +413,33 @@ glm::mat4 Rig::getJointTransform(int jointIndex) const {
if (jointIndex == -1 || jointIndex >= _jointStates.size()) { if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
return glm::mat4(); return glm::mat4();
} }
/*
// AJT: test if _absolutePoses are the same as jointTransforms
glm::mat4 newMat = _absolutePoses[jointIndex];
glm::mat4 oldMat = _jointStates[jointIndex].getTransform();
const float EPSILON = 0.0001f;
if (glm::length(newMat[0] - oldMat[0]) > EPSILON ||
glm::length(newMat[1] - oldMat[1]) > EPSILON ||
glm::length(newMat[2] - oldMat[2]) > EPSILON ||
glm::length(newMat[3] - oldMat[3]) > EPSILON) {
// error?
qCDebug(animation) << "AJT: mismatch for joint[" << jointIndex;
qCDebug(animation) << "AJT: oldMat = " << AnimPose(oldMat);
qCDebug(animation) << "AJT: newMat = " << AnimPose(newMat);
}
*/
// AJT: LEGACY
return _jointStates[jointIndex].getTransform(); return _jointStates[jointIndex].getTransform();
} }
void Rig::calcAnimAlpha(float speed, const std::vector<float>& referenceSpeeds, float* alphaOut) const { void Rig::calcAnimAlpha(float speed, const std::vector<float>& referenceSpeeds, float* alphaOut) const {
assert(referenceSpeeds.size() > 0); ASSERT(referenceSpeeds.size() > 0);
// calculate alpha from linear combination of referenceSpeeds. // calculate alpha from linear combination of referenceSpeeds.
float alpha = 0.0f; float alpha = 0.0f;
@ -664,33 +723,38 @@ void Rig::updateAnimations(float deltaTime, glm::mat4 rootTransform) {
// evaluate the animation // evaluate the animation
AnimNode::Triggers triggersOut; AnimNode::Triggers triggersOut;
AnimPoseVec poses = _animNode->evaluate(_animVars, deltaTime, triggersOut); _relativePoses = _animNode->evaluate(_animVars, deltaTime, triggersOut);
if (_relativePoses.size() != _animSkeleton->getNumJoints()) {
// animations haven't been loaded yet.
_relativePoses.resize(_animSkeleton->getNumJoints(), AnimPose::identity);
}
_animVars.clearTriggers(); _animVars.clearTriggers();
for (auto& trigger : triggersOut) { for (auto& trigger : triggersOut) {
_animVars.setTrigger(trigger); _animVars.setTrigger(trigger);
} }
clearJointStatePriorities(); // AJT: LEGACY
{
clearJointStatePriorities();
// copy poses into jointStates // copy poses into jointStates
const float PRIORITY = 1.0f; const float PRIORITY = 1.0f;
for (size_t i = 0; i < poses.size(); i++) { for (size_t i = 0; i < _relativePoses.size(); i++) {
setJointRotationInConstrainedFrame((int)i, glm::inverse(_animSkeleton->getRelativeBindPose(i).rot) * poses[i].rot, PRIORITY, 1.0f); setJointRotationInConstrainedFrame((int)i, glm::inverse(_animSkeleton->getRelativeBindPose(i).rot) * _relativePoses[i].rot, PRIORITY, 1.0f);
setJointTranslation((int)i, true, poses[i].trans, PRIORITY); setJointTranslation((int)i, true, _relativePoses[i].trans, PRIORITY);
}
} }
} }
// AJT: REMOVE
/*
for (int i = 0; i < _jointStates.size(); i++) {
updateJointState(i, rootTransform);
}
*/
setModelOffset(rootTransform); setModelOffset(rootTransform);
//applyOverridePoses();
buildAbsolutePoses(); buildAbsolutePoses();
for (int i = 0; i < _jointStates.size(); i++) { // AJT: LEGACY
_jointStates[i].resetTransformChanged(); {
for (int i = 0; i < _jointStates.size(); i++) {
_jointStates[i].resetTransformChanged();
}
} }
} }
@ -1154,12 +1218,29 @@ bool Rig::getModelOffset(glm::vec3& modelOffsetOut) const {
} }
} }
void Rig::applyOverridePoses() {
if (!_animSkeleton) {
return;
}
ASSERT(_animSkeleton->getNumJoints() == _relativePoses.size());
ASSERT(_animSkeleton->getNumJoints() == _overrideFlags.size());
ASSERT(_animSkeleton->getNumJoints() == _overridePoses.size());
for (size_t i = 0; i < _overrideFlags.size(); i++) {
if (_overrideFlags[i]) {
_relativePoses[i] = _overridePoses[i];
}
}
}
void Rig::buildAbsolutePoses() { void Rig::buildAbsolutePoses() {
if (!_animSkeleton) { if (!_animSkeleton) {
return; return;
} }
assert(_animSkeleton->getNumJoints() == _relativePoses.size()); ASSERT(_animSkeleton->getNumJoints() == _relativePoses.size());
_absolutePoses.resize(_relativePoses.size()); _absolutePoses.resize(_relativePoses.size());
for (int i = 0; i < (int)_relativePoses.size(); i++) { for (int i = 0; i < (int)_relativePoses.size(); i++) {
int parentIndex = _animSkeleton->getParentIndex(i); int parentIndex = _animSkeleton->getParentIndex(i);

View file

@ -17,6 +17,7 @@
#include <QObject> #include <QObject>
#include <QMutex> #include <QMutex>
#include <QScriptValue> #include <QScriptValue>
#include <vector>
#include "JointState.h" // We might want to change this (later) to something that doesn't depend on gpu, fbx and model. -HRS #include "JointState.h" // We might want to change this (later) to something that doesn't depend on gpu, fbx and model. -HRS
@ -165,6 +166,7 @@ public:
protected: protected:
void updateAnimationStateHandlers(); void updateAnimationStateHandlers();
void applyOverridePoses();
void buildAbsolutePoses(); void buildAbsolutePoses();
void updateLeanJoint(int index, float leanSideways, float leanForward, float torsoTwist); void updateLeanJoint(int index, float leanSideways, float leanForward, float torsoTwist);
@ -178,6 +180,8 @@ public:
AnimPose _modelOffset; AnimPose _modelOffset;
AnimPoseVec _relativePoses; AnimPoseVec _relativePoses;
AnimPoseVec _absolutePoses; AnimPoseVec _absolutePoses;
AnimPoseVec _overridePoses;
std::vector<bool> _overrideFlags;
int _rootJointIndex { -1 }; int _rootJointIndex { -1 };