Merge pull request #9 from hyperlogic/ajt/cauterize-head-fix

Remove cauterize code from Rig and move it back into Model.
This commit is contained in:
Howard Stearns 2015-07-29 09:09:28 -07:00
commit 711dce4edc
7 changed files with 98 additions and 107 deletions

View file

@ -969,12 +969,8 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
Avatar::setSkeletonModelURL(skeletonModelURL);
render::ScenePointer scene = Application::getInstance()->getMain3DScene();
_billboardValid = false;
if (_useFullAvatar) {
_skeletonModel.setVisibleInScene(_prevShouldDrawHead, scene);
} else {
_skeletonModel.setVisibleInScene(true, scene);
}
_skeletonModel.setVisibleInScene(true, scene);
_headBoneSet.clear();
}
void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelName) {
@ -1184,17 +1180,45 @@ void MyAvatar::setVisibleInSceneIfReady(Model* model, render::ScenePointer scene
}
}
void MyAvatar::initHeadBones() {
int neckJointIndex = -1;
if (_skeletonModel.getGeometry()) {
neckJointIndex = _skeletonModel.getGeometry()->getFBXGeometry().neckJointIndex;
}
if (neckJointIndex == -1) {
return;
}
_headBoneSet.clear();
std::queue<int> q;
q.push(neckJointIndex);
_headBoneSet.insert(neckJointIndex);
// fbxJoints only hold links to parents not children, so we have to do a bit of extra work here.
while (q.size() > 0) {
int jointIndex = q.front();
for (int i = 0; i < _skeletonModel.getJointStateCount(); i++) {
if (jointIndex == _skeletonModel.getParentJointIndex(i)) {
_headBoneSet.insert(i);
q.push(i);
}
}
q.pop();
}
}
void MyAvatar::preRender(RenderArgs* renderArgs) {
render::ScenePointer scene = Application::getInstance()->getMain3DScene();
const bool shouldDrawHead = shouldRenderHead(renderArgs);
_skeletonModel.initWhenReady(scene);
if (_skeletonModel.initWhenReady(scene)) {
initHeadBones();
_skeletonModel.setCauterizeBoneSet(_headBoneSet);
}
if (shouldDrawHead != _prevShouldDrawHead) {
if (_useFullAvatar) {
_skeletonModel.setVisibleInScene(true, scene);
_rig->setFirstPerson(!shouldDrawHead);
_skeletonModel.setCauterizeBones(!shouldDrawHead);
} else {
getHead()->getFaceModel().setVisibleInScene(shouldDrawHead, scene);
}

View file

@ -273,7 +273,8 @@ private:
void updatePosition(float deltaTime);
void updateCollisionSound(const glm::vec3& penetration, float deltaTime, float frequency);
void maybeUpdateBillboard();
void initHeadBones();
// Avatar Preferences
bool _useFullAvatar = false;
QUrl _fullAvatarURLFromPreferences;
@ -286,6 +287,7 @@ private:
RigPointer _rig;
bool _prevShouldDrawHead;
std::unordered_set<int> _headBoneSet;
};
#endif // hifi_MyAvatar_h

View file

@ -51,7 +51,7 @@ SkeletonModel::~SkeletonModel() {
void SkeletonModel::initJointStates(QVector<JointState> states) {
const FBXGeometry& geometry = _geometry->getFBXGeometry();
glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
_boundingRadius = _rig->initJointStates(states, parentTransform, geometry.neckJointIndex);
_boundingRadius = _rig->initJointStates(states, parentTransform);
// Determine the default eye position for avatar scale = 1.0
int headJointIndex = _geometry->getFBXGeometry().headJointIndex;
@ -175,14 +175,6 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) {
restoreRightHandPosition(HAND_RESTORATION_RATE, PALM_PRIORITY);
}
}
// if (_isFirstPerson) {
// cauterizeHead();
// updateClusterMatrices();
// }
if (_rig->getJointsAreDirty()) {
updateClusterMatrices();
}
}
void SkeletonModel::renderIKConstraints(gpu::Batch& batch) {

View file

@ -124,9 +124,8 @@ void Rig::deleteAnimations() {
_animationHandles.clear();
}
float Rig::initJointStates(QVector<JointState> states, glm::mat4 parentTransform, int neckJointIndex) {
float Rig::initJointStates(QVector<JointState> states, glm::mat4 parentTransform) {
_jointStates = states;
_neckJointIndex = neckJointIndex;
initJointTransforms(parentTransform);
int numStates = _jointStates.size();
@ -142,8 +141,6 @@ float Rig::initJointStates(QVector<JointState> states, glm::mat4 parentTransform
_jointStates[i].slaveVisibleTransform();
}
initHeadBones();
return radius;
}
@ -195,8 +192,7 @@ JointState Rig::getJointState(int jointIndex) const {
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
return JointState();
}
// return _jointStates[jointIndex];
return maybeCauterizeHead(jointIndex);
return _jointStates[jointIndex];
}
bool Rig::getJointStateRotation(int index, glm::quat& rotation) const {
@ -270,8 +266,7 @@ bool Rig::getJointPositionInWorldFrame(int jointIndex, glm::vec3& position,
return false;
}
// position is in world-frame
// position = translation + rotation * _jointStates[jointIndex].getPosition();
position = translation + rotation * maybeCauterizeHead(jointIndex).getPosition();
position = translation + rotation * _jointStates[jointIndex].getPosition();
return true;
}
@ -280,7 +275,7 @@ bool Rig::getJointPosition(int jointIndex, glm::vec3& position) const {
return false;
}
// position is in model-frame
position = extractTranslation(maybeCauterizeHead(jointIndex).getTransform());
position = extractTranslation(_jointStates[jointIndex].getTransform());
return true;
}
@ -288,7 +283,7 @@ bool Rig::getJointRotationInWorldFrame(int jointIndex, glm::quat& result, const
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
return false;
}
result = rotation * maybeCauterizeHead(jointIndex).getRotation();
result = rotation * _jointStates[jointIndex].getRotation();
return true;
}
@ -296,7 +291,7 @@ bool Rig::getJointRotation(int jointIndex, glm::quat& rotation) const {
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
return false;
}
rotation = maybeCauterizeHead(jointIndex).getRotation();
rotation = _jointStates[jointIndex].getRotation();
return true;
}
@ -304,7 +299,7 @@ bool Rig::getJointCombinedRotation(int jointIndex, glm::quat& result, const glm:
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
return false;
}
result = rotation * maybeCauterizeHead(jointIndex).getRotation();
result = rotation * _jointStates[jointIndex].getRotation();
return true;
}
@ -315,7 +310,7 @@ bool Rig::getVisibleJointPositionInWorldFrame(int jointIndex, glm::vec3& positio
return false;
}
// position is in world-frame
position = translation + rotation * maybeCauterizeHead(jointIndex).getVisiblePosition();
position = translation + rotation * _jointStates[jointIndex].getVisiblePosition();
return true;
}
@ -323,7 +318,7 @@ bool Rig::getVisibleJointRotationInWorldFrame(int jointIndex, glm::quat& result,
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
return false;
}
result = rotation * maybeCauterizeHead(jointIndex).getVisibleRotation();
result = rotation * _jointStates[jointIndex].getVisibleRotation();
return true;
}
@ -331,14 +326,14 @@ glm::mat4 Rig::getJointTransform(int jointIndex) const {
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
return glm::mat4();
}
return maybeCauterizeHead(jointIndex).getTransform();
return _jointStates[jointIndex].getTransform();
}
glm::mat4 Rig::getJointVisibleTransform(int jointIndex) const {
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
return glm::mat4();
}
return maybeCauterizeHead(jointIndex).getVisibleTransform();
return _jointStates[jointIndex].getVisibleTransform();
}
void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPosition, const glm::vec3& worldVelocity, const glm::quat& worldRotation) {
@ -624,7 +619,7 @@ glm::vec3 Rig::getJointDefaultTranslationInConstrainedFrame(int jointIndex) {
if (jointIndex == -1 || _jointStates.isEmpty()) {
return glm::vec3();
}
return maybeCauterizeHead(jointIndex).getDefaultTranslationInConstrainedFrame();
return _jointStates[jointIndex].getDefaultTranslationInConstrainedFrame();
}
glm::quat Rig::setJointRotationInConstrainedFrame(int jointIndex, glm::quat targetRotation, float priority, bool constrain) {
@ -669,53 +664,5 @@ glm::quat Rig::getJointDefaultRotationInParentFrame(int jointIndex) {
if (jointIndex == -1 || _jointStates.isEmpty()) {
return glm::quat();
}
return maybeCauterizeHead(jointIndex).getDefaultRotationInParentFrame();
}
void Rig::initHeadBones() {
if (_neckJointIndex == -1) {
return;
}
_headBones.clear();
std::queue<int> q;
q.push(_neckJointIndex);
_headBones.push_back(_neckJointIndex);
// fbxJoints only hold links to parents not children, so we have to do a bit of extra work here.
while (q.size() > 0) {
int jointIndex = q.front();
for (int i = 0; i < _jointStates.size(); i++) {
const FBXJoint& fbxJoint = _jointStates[i].getFBXJoint();
if (jointIndex == fbxJoint.parentIndex) {
_headBones.push_back(i);
q.push(i);
}
}
q.pop();
}
}
JointState Rig::maybeCauterizeHead(int jointIndex) const {
// if (_headBones.contains(jointIndex)) {
// XXX fix this... make _headBones a hash? add a flag to JointState?
if (_neckJointIndex != -1 &&
_isFirstPerson &&
std::find(_headBones.begin(), _headBones.end(), jointIndex) != _headBones.end()) {
glm::vec4 trans = _jointStates[jointIndex].getTransform()[3];
glm::vec4 zero(0, 0, 0, 0);
glm::mat4 newXform(zero, zero, zero, trans);
JointState jointStateCopy = _jointStates[jointIndex];
jointStateCopy.setTransform(newXform);
jointStateCopy.setVisibleTransform(newXform);
return jointStateCopy;
} else {
return _jointStates[jointIndex];
}
}
void Rig::setFirstPerson(bool isFirstPerson) {
if (_isFirstPerson != isFirstPerson) {
_isFirstPerson = isFirstPerson;
_jointsAreDirty = true;
}
return _jointStates[jointIndex].getDefaultRotationInParentFrame();
}

View file

@ -75,7 +75,7 @@ public:
float priority = 1.0f, bool loop = false, bool hold = false, float firstFrame = 0.0f,
float lastFrame = FLT_MAX, const QStringList& maskedJoints = QStringList(), bool startAutomatically = false);
float initJointStates(QVector<JointState> states, glm::mat4 parentTransform, int neckJointIndex);
float initJointStates(QVector<JointState> states, glm::mat4 parentTransform);
bool jointStatesEmpty() { return _jointStates.isEmpty(); };
int getJointStateCount() const { return _jointStates.size(); }
int indexOfJoint(const QString& jointName) ;
@ -131,10 +131,6 @@ public:
virtual void updateJointState(int index, glm::mat4 parentTransform) = 0;
virtual void updateFaceJointState(int index, glm::mat4 parentTransform) = 0;
virtual void setFirstPerson(bool isFirstPerson);
virtual bool getIsFirstPerson() const { return _isFirstPerson; }
bool getJointsAreDirty() { return _jointsAreDirty; }
void setEnableRig(bool isEnabled) { _enableRig = isEnabled; }
protected:
@ -143,13 +139,6 @@ public:
QList<AnimationHandlePointer> _animationHandles;
QList<AnimationHandlePointer> _runningAnimations;
JointState maybeCauterizeHead(int jointIndex) const;
void initHeadBones();
bool _isFirstPerson = false;
std::vector<int> _headBones;
bool _jointsAreDirty = false;
int _neckJointIndex = -1;
bool _enableRig;
bool _isWalking;
bool _isTurning;

View file

@ -67,6 +67,7 @@ Model::Model(RigPointer rig, QObject* parent) :
_snapModelToRegistrationPoint(false),
_snappedToRegistrationPoint(false),
_showTrueJointTransforms(true),
_cauterizeBones(false),
_lodDistance(0.0f),
_pupilDilation(0.0f),
_url("http://invalid.com"),
@ -452,6 +453,7 @@ bool Model::updateGeometry() {
foreach (const FBXMesh& mesh, fbxGeometry.meshes) {
MeshState state;
state.clusterMatrices.resize(mesh.clusters.size());
state.cauterizedClusterMatrices.resize(mesh.clusters.size());
_meshStates.append(state);
auto buffer = std::make_shared<gpu::Buffer>();
@ -472,7 +474,7 @@ bool Model::updateGeometry() {
void Model::initJointStates(QVector<JointState> states) {
const FBXGeometry& geometry = _geometry->getFBXGeometry();
glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
_boundingRadius = _rig->initJointStates(states, parentTransform, geometry.neckJointIndex);
_boundingRadius = _rig->initJointStates(states, parentTransform);
}
bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance,
@ -1337,6 +1339,12 @@ void Model::simulateInternal(float deltaTime) {
glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
updateRig(deltaTime, parentTransform);
glm::mat4 zeroScale(glm::vec4(0.0f, 0.0f, 0.0f, 0.0f),
glm::vec4(0.0f, 0.0f, 0.0f, 0.0f),
glm::vec4(0.0f, 0.0f, 0.0f, 0.0f),
glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
auto cauterizeMatrix = _rig->getJointTransform(geometry.neckJointIndex) * zeroScale;
glm::mat4 modelToWorld = glm::mat4_cast(_rotation);
for (int i = 0; i < _meshStates.size(); i++) {
MeshState& state = _meshStates[i];
@ -1344,14 +1352,30 @@ void Model::simulateInternal(float deltaTime) {
if (_showTrueJointTransforms) {
for (int j = 0; j < mesh.clusters.size(); j++) {
const FBXCluster& cluster = mesh.clusters.at(j);
state.clusterMatrices[j] =
modelToWorld * _rig->getJointTransform(cluster.jointIndex) * cluster.inverseBindMatrix;
auto jointMatrix =_rig->getJointTransform(cluster.jointIndex);
state.clusterMatrices[j] = modelToWorld * jointMatrix * cluster.inverseBindMatrix;
// as an optimization, don't build cautrizedClusterMatrices if the boneSet is empty.
if (!_cauterizeBoneSet.empty()) {
if (_cauterizeBoneSet.find(cluster.jointIndex) != _cauterizeBoneSet.end()) {
jointMatrix = cauterizeMatrix;
}
state.cauterizedClusterMatrices[j] = modelToWorld * jointMatrix * cluster.inverseBindMatrix;
}
}
} else {
for (int j = 0; j < mesh.clusters.size(); j++) {
const FBXCluster& cluster = mesh.clusters.at(j);
state.clusterMatrices[j] =
modelToWorld * _rig->getJointVisibleTransform(cluster.jointIndex) * cluster.inverseBindMatrix;
auto jointMatrix = _rig->getJointVisibleTransform(cluster.jointIndex);
state.clusterMatrices[j] = modelToWorld * jointMatrix * cluster.inverseBindMatrix;
// as an optimization, don't build cautrizedClusterMatrices if the boneSet is empty.
if (!_cauterizeBoneSet.empty()) {
if (_cauterizeBoneSet.find(cluster.jointIndex) != _cauterizeBoneSet.end()) {
jointMatrix = cauterizeMatrix;
}
state.cauterizedClusterMatrices[j] = modelToWorld * jointMatrix * cluster.inverseBindMatrix;
}
}
}
}
@ -1611,8 +1635,11 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran
}
if (isSkinned) {
batch._glUniformMatrix4fv(locations->clusterMatrices, state.clusterMatrices.size(), false,
(const float*)state.clusterMatrices.constData());
const float* bones = (const float*)state.clusterMatrices.constData();
if (_cauterizeBones) {
bones = (const float*)state.cauterizedClusterMatrices.constData();
}
batch._glUniformMatrix4fv(locations->clusterMatrices, state.clusterMatrices.size(), false, bones);
_transforms[0] = Transform();
_transforms[0].preTranslate(_translation);
} else {

View file

@ -18,6 +18,7 @@
#include <QMutex>
#include <unordered_map>
#include <unordered_set>
#include <functional>
#include <AABox.h>
@ -172,6 +173,9 @@ public:
/// \return true if joint exists
bool getJointRotation(int jointIndex, glm::quat& rotation) const;
/// Returns the index of the parent of the indexed joint, or -1 if not found.
int getParentJointIndex(int jointIndex) const;
void inverseKinematics(int jointIndex, glm::vec3 position, const glm::quat& rotation, float priority);
/// Returns the extents of the model in its bind pose.
@ -187,6 +191,12 @@ public:
bool getIsScaledToFit() const { return _scaledToFit; } /// is model scaled to fit
const glm::vec3& getScaleToFitDimensions() const { return _scaleToFitDimensions; } /// the dimensions model is scaled to
void setCauterizeBones(bool flag) { _cauterizeBones = flag; }
bool getCauterizeBones() const { return _cauterizeBones; }
const std::unordered_set<int>& getCauterizeBoneSet() const { return _cauterizeBoneSet; }
void setCauterizeBoneSet(const std::unordered_set<int>& boneSet) { _cauterizeBoneSet = boneSet; }
protected:
void setPupilDilation(float dilation) { _pupilDilation = dilation; }
@ -218,9 +228,6 @@ protected:
/// Clear the joint states
void clearJointState(int index);
/// Returns the index of the parent of the indexed joint, or -1 if not found.
int getParentJointIndex(int jointIndex) const;
/// Returns the index of the last free ancestor of the indexed joint, or -1 if not found.
int getLastFreeJointIndex(int jointIndex) const;
@ -255,9 +262,12 @@ protected:
class MeshState {
public:
QVector<glm::mat4> clusterMatrices;
QVector<glm::mat4> cauterizedClusterMatrices;
};
QVector<MeshState> _meshStates;
std::unordered_set<int> _cauterizeBoneSet;
bool _cauterizeBones;
// returns 'true' if needs fullUpdate after geometry change
bool updateGeometry();