diff options
Diffstat (limited to 'indra/newview/llviewerobject.cpp')
-rw-r--r-- | indra/newview/llviewerobject.cpp | 176 |
1 files changed, 174 insertions, 2 deletions
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index d71814bd3f..b66d4b1dab 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -391,6 +391,13 @@ LLViewerObject::~LLViewerObject() sNumObjects--; sNumZombieObjects--; llassert(mChildList.size() == 0); + llassert(mControlAvatar.isNull()); // Should have been cleaned by now + if (mControlAvatar.notNull()) + { + mControlAvatar->markForDeath(); + mControlAvatar = NULL; + LL_WARNS() << "Dead object owned a live control avatar" << LL_ENDL; + } clearInventoryListeners(); } @@ -3108,6 +3115,10 @@ void LLViewerObject::updateControlAvatar() return; } + // caller isn't supposed to operate on a dead object, + // avatar was already cleaned up + llassert(!isDead()); + bool should_have_control_avatar = false; if (is_animated_object) { @@ -3191,7 +3202,6 @@ void LLViewerObject::unlinkControlAvatar() if (mControlAvatar) { mControlAvatar->markForDeath(); - mControlAvatar->mRootVolp = NULL; mControlAvatar = NULL; } } @@ -4364,6 +4374,168 @@ const LLVector3 &LLViewerObject::getPositionAgent() const return mPositionAgent; } +LLMatrix4a LLViewerObject::getGLTFAssetToAgentTransform() const +{ + LLMatrix4 root; + root.initScale(getScale()); + root.rotate(getRenderRotation()); + root.translate(getPositionAgent()); + + LLMatrix4a mat; + mat.loadu((F32*)root.mMatrix); + + return mat; +} + +LLVector3 LLViewerObject::getGLTFNodePositionAgent(S32 node_index) const +{ + LLVector3 ret; + getGLTFNodeTransformAgent(node_index, &ret, nullptr, nullptr); + return ret; + +} + +LLMatrix4a LLViewerObject::getAgentToGLTFAssetTransform() const +{ + LLMatrix4 root; + LLVector3 scale = getScale(); + scale.mV[0] = 1.f / scale.mV[0]; + scale.mV[1] = 1.f / scale.mV[1]; + scale.mV[2] = 1.f / scale.mV[2]; + + root.translate(-getPositionAgent()); + root.rotate(~getRenderRotation()); + + LLMatrix4 scale_mat; + scale_mat.initScale(scale); + + root *= scale_mat; + LLMatrix4a mat; + mat.loadu((F32*)root.mMatrix); + + return mat; +} + +LLMatrix4a LLViewerObject::getGLTFNodeTransformAgent(S32 node_index) const +{ + LLMatrix4a mat; + + if (mGLTFAsset.notNull() && node_index >= 0 && node_index < mGLTFAsset->mNodes.size()) + { + auto& node = mGLTFAsset->mNodes[node_index]; + + LLMatrix4a asset_to_agent = getGLTFAssetToAgentTransform(); + LLMatrix4a node_to_agent; + matMul(node.mAssetMatrix, asset_to_agent, node_to_agent); + + mat = node_to_agent; + } + else + { + mat.setIdentity(); + } + + return mat; +} +void LLViewerObject::getGLTFNodeTransformAgent(S32 node_index, LLVector3* position, LLQuaternion* rotation, LLVector3* scale) const +{ + LLMatrix4a node_to_agent = getGLTFNodeTransformAgent(node_index); + + if (position) + { + LLVector4a p = node_to_agent.getTranslation(); + position->set(p.getF32ptr()); + } + + if (rotation) + { + rotation->set(node_to_agent.asMatrix4()); + } + + if (scale) + { + scale->mV[0] = node_to_agent.mMatrix[0].getLength3().getF32(); + scale->mV[1] = node_to_agent.mMatrix[1].getLength3().getF32(); + scale->mV[2] = node_to_agent.mMatrix[2].getLength3().getF32(); + } +} + +void decomposeMatrix(const LLMatrix4a& mat, LLVector3& position, LLQuaternion& rotation, LLVector3& scale) +{ + LLVector4a p = mat.getTranslation(); + position.set(p.getF32ptr()); + + rotation.set(mat.asMatrix4()); + + scale.mV[0] = mat.mMatrix[0].getLength3().getF32(); + scale.mV[1] = mat.mMatrix[1].getLength3().getF32(); + scale.mV[2] = mat.mMatrix[2].getLength3().getF32(); +} + +void LLViewerObject::setGLTFNodeRotationAgent(S32 node_index, const LLQuaternion& rotation) +{ + if (mGLTFAsset.notNull() && node_index >= 0 && node_index < mGLTFAsset->mNodes.size()) + { + auto& node = mGLTFAsset->mNodes[node_index]; + + LLMatrix4a agent_to_asset = getAgentToGLTFAssetTransform(); + LLMatrix4a agent_to_node = agent_to_asset; + + if (node.mParent != -1) + { + auto& parent = mGLTFAsset->mNodes[node.mParent]; + matMul(agent_to_asset, parent.mAssetMatrixInv, agent_to_node); + } + + LLQuaternion agent_to_node_rot(agent_to_node.asMatrix4()); + LLQuaternion new_rot; + + new_rot = rotation * agent_to_node_rot; + new_rot.normalize(); + + LLVector3 pos; + LLQuaternion rot; + LLVector3 scale; + decomposeMatrix(node.mMatrix, pos, rot, scale); + + node.mMatrix.asMatrix4().initAll(scale, new_rot, pos); + + mGLTFAsset->updateTransforms(); + } +} + +void LLViewerObject::moveGLTFNode(S32 node_index, const LLVector3& offset) +{ + if (mGLTFAsset.notNull() && node_index >= 0 && node_index < mGLTFAsset->mNodes.size()) + { + auto& node = mGLTFAsset->mNodes[node_index]; + + LLMatrix4a agent_to_asset = getAgentToGLTFAssetTransform(); + LLMatrix4a agent_to_node; + matMul(agent_to_asset, node.mAssetMatrixInv, agent_to_node); + + LLVector4a origin = LLVector4a::getZero(); + LLVector4a offset_v; + offset_v.load3(offset.mV); + + + agent_to_node.affineTransform(offset_v, offset_v); + agent_to_node.affineTransform(origin, origin); + + offset_v.sub(origin); + offset_v.getF32ptr()[3] = 1.f; + + LLMatrix4a trans; + trans.setIdentity(); + trans.mMatrix[3] = offset_v; + + matMul(trans, node.mMatrix, node.mMatrix); + + // TODO -- only update transforms for this node and its children (or use a dirty flag) + mGLTFAsset->updateTransforms(); + } +} + const LLVector3 &LLViewerObject::getPositionRegion() const { if (!isRoot()) @@ -5121,7 +5293,7 @@ void LLViewerObject::setTEImage(const U8 te, LLViewerTexture *imagep) S32 LLViewerObject::setTETextureCore(const U8 te, LLViewerTexture *image) { LLUUID old_image_id = getTE(te)->getID(); - const LLUUID& uuid = image->getID(); + const LLUUID& uuid = image ? image->getID() : LLUUID::null; S32 retval = 0; if (uuid != getTE(te)->getID() || uuid == LLUUID::null) |