diff options
author | RunitaiLinden <davep@lindenlab.com> | 2024-04-24 09:51:15 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-24 09:51:15 -0500 |
commit | cadc1a02cc7289dabd368dd1a1d237c042e9f82e (patch) | |
tree | 7493c7a7a8a8b395bc9fc98a1a9dd018098c4147 /indra/newview/gltf/asset.cpp | |
parent | f1b7e806eb30a343876036eff5caef7c03309aa6 (diff) |
1285 GLTF Animation Prototype
Diffstat (limited to 'indra/newview/gltf/asset.cpp')
-rw-r--r-- | indra/newview/gltf/asset.cpp | 375 |
1 files changed, 350 insertions, 25 deletions
diff --git a/indra/newview/gltf/asset.cpp b/indra/newview/gltf/asset.cpp index 7181c5fa53..313e82bf01 100644 --- a/indra/newview/gltf/asset.cpp +++ b/indra/newview/gltf/asset.cpp @@ -28,6 +28,8 @@ #include "asset.h" #include "llvolumeoctree.h" +#include "../llviewershadermgr.h" +#include "../llviewercontrol.h" using namespace LL::GLTF; @@ -66,6 +68,7 @@ LLMatrix4a inverse(const LLMatrix4a& mat); void Node::updateTransforms(Asset& asset, const LLMatrix4a& parentMatrix) { + makeMatrixValid(); matMul(mMatrix, parentMatrix, mAssetMatrix); mAssetMatrixInv = inverse(mAssetMatrix); @@ -99,7 +102,7 @@ void Asset::updateRenderTransforms(const LLMatrix4a& modelview) // use mAssetMatrix to update render transforms from node list for (auto& node : mNodes) { - if (node.mMesh != INVALID_INDEX) + //if (node.mMesh != INVALID_INDEX) { matMul(node.mAssetMatrix, modelview, node.mRenderMatrix); } @@ -211,6 +214,67 @@ S32 Asset::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, return node_hit; } + +void Node::makeMatrixValid() +{ + if (!mMatrixValid && mTRSValid) + { + glh::matrix4f rot; + mRotation.get_value(rot); + + glh::matrix4f trans; + trans.set_translate(mTranslation); + + glh::matrix4f sc; + sc.set_scale(mScale); + + glh::matrix4f t; + //t = sc * rot * trans; + //t = trans * rot * sc; // best so far, still wrong on negative scale + //t = sc * trans * rot; + t = trans * sc * rot; + + mMatrix.loadu(t.m); + mMatrixValid = true; + } +} + +void Node::makeTRSValid() +{ + if (!mTRSValid && mMatrixValid) + { + glh::matrix4f t(mMatrix.getF32ptr()); + + glh::vec4f p = t.get_column(3); + mTranslation.set_value(p.v[0], p.v[1], p.v[2]); + + mScale.set_value(t.get_column(0).length(), t.get_column(1).length(), t.get_column(2).length()); + mRotation.set_value(t); + mTRSValid = true; + } +} + +void Node::setRotation(const glh::quaternionf& q) +{ + makeTRSValid(); + mRotation = q; + mMatrixValid = false; +} + +void Node::setTranslation(const glh::vec3f& t) +{ + makeTRSValid(); + mTranslation = t; + mMatrixValid = false; +} + +void Node::setScale(const glh::vec3f& s) +{ + makeTRSValid(); + mScale = s; + mMatrixValid = false; +} + const Node& Node::operator=(const tinygltf::Node& src) { F32* dstMatrix = mMatrix.getF32ptr(); @@ -222,48 +286,33 @@ const Node& Node::operator=(const tinygltf::Node& src) { dstMatrix[i] = (F32)src.matrix[i]; } + + mMatrixValid = true; } else if (!src.rotation.empty() || !src.translation.empty() || !src.scale.empty()) { // node has rotation/translation/scale, convert to matrix - glh::quaternionf rotation; if (src.rotation.size() == 4) { - rotation = glh::quaternionf((F32)src.rotation[0], (F32)src.rotation[1], (F32)src.rotation[2], (F32)src.rotation[3]); + mRotation = glh::quaternionf((F32)src.rotation[0], (F32)src.rotation[1], (F32)src.rotation[2], (F32)src.rotation[3]); } - glh::vec3f translation; if (src.translation.size() == 3) { - translation = glh::vec3f((F32)src.translation[0], (F32)src.translation[1], (F32)src.translation[2]); + mTranslation = glh::vec3f((F32)src.translation[0], (F32)src.translation[1], (F32)src.translation[2]); } glh::vec3f scale; if (src.scale.size() == 3) { - scale = glh::vec3f((F32)src.scale[0], (F32)src.scale[1], (F32)src.scale[2]); + mScale = glh::vec3f((F32)src.scale[0], (F32)src.scale[1], (F32)src.scale[2]); } else { - scale.set_value(1.f, 1.f, 1.f); + mScale.set_value(1.f, 1.f, 1.f); } - glh::matrix4f rot; - rotation.get_value(rot); - - glh::matrix4f trans; - trans.set_translate(translation); - - glh::matrix4f sc; - sc.set_scale(scale); - - glh::matrix4f t; - //t = sc * rot * trans; - //t = trans * rot * sc; // best so far, still wrong on negative scale - //t = sc * trans * rot; - t = trans * sc * rot; - - mMatrix.loadu(t.m); + mTRSValid = true; } else { @@ -273,21 +322,50 @@ const Node& Node::operator=(const tinygltf::Node& src) mChildren = src.children; mMesh = src.mesh; + mSkin = src.skin; mName = src.name; return *this; } -void Asset::render(bool opaque) +void Asset::render(bool opaque, bool rigged) { + if (rigged) + { + gGL.loadIdentity(); + } + for (auto& node : mNodes) { + if (node.mSkin != INVALID_INDEX) + { + if (rigged) + { + Skin& skin = mSkins[node.mSkin]; + skin.uploadMatrixPalette(*this, node); + } + else + { + //skip static nodes if we're rendering rigged + continue; + } + } + else if (rigged) + { + // skip rigged nodes if we're not rendering rigged + continue; + } + + if (node.mMesh != INVALID_INDEX) { Mesh& mesh = mMeshes[node.mMesh]; for (auto& primitive : mesh.mPrimitives) { - gGL.loadMatrix((F32*)node.mRenderMatrix.mMatrix); + if (!rigged) + { + gGL.loadMatrix((F32*)node.mRenderMatrix.mMatrix); + } bool cull = true; if (primitive.mMaterial != INVALID_INDEX) { @@ -336,4 +414,251 @@ void Asset::renderTransparent() render(false); } +void Asset::update() +{ + F32 dt = gFrameTimeSeconds - mLastUpdateTime; + + if (dt > 0.f) + { + mLastUpdateTime = gFrameTimeSeconds; + if (mAnimations.size() > 0) + { + static LLCachedControl<U32> anim_idx(gSavedSettings, "GLTFAnimationIndex", 0); + static LLCachedControl<F32> anim_speed(gSavedSettings, "GLTFAnimationSpeed", 1.f); + + U32 idx = llclamp(anim_idx(), 0U, mAnimations.size() - 1); + mAnimations[idx].update(*this, dt*anim_speed); + } + + updateTransforms(); + } +} + +void Asset::allocateGLResources(const std::string& filename, const tinygltf::Model& model) +{ + // do images first as materials may depend on images + for (auto& image : mImages) + { + image.allocateGLResources(); + } + + // do materials before meshes as meshes may depend on materials + for (U32 i = 0; i < mMaterials.size(); ++i) + { + mMaterials[i].allocateGLResources(*this); + LLTinyGLTFHelper::getMaterialFromModel(filename, model, i, mMaterials[i].mMaterial, mMaterials[i].mName, true); + } + + for (auto& mesh : mMeshes) + { + mesh.allocateGLResources(*this); + } + + for (auto& animation : mAnimations) + { + animation.allocateGLResources(*this); + } + + for (auto& skin : mSkins) + { + skin.allocateGLResources(*this); + } +} + +const Asset& Asset::operator=(const tinygltf::Model& src) +{ + mScenes.resize(src.scenes.size()); + for (U32 i = 0; i < src.scenes.size(); ++i) + { + mScenes[i] = src.scenes[i]; + } + + mNodes.resize(src.nodes.size()); + for (U32 i = 0; i < src.nodes.size(); ++i) + { + mNodes[i] = src.nodes[i]; + } + + mMeshes.resize(src.meshes.size()); + for (U32 i = 0; i < src.meshes.size(); ++i) + { + mMeshes[i] = src.meshes[i]; + } + + mMaterials.resize(src.materials.size()); + for (U32 i = 0; i < src.materials.size(); ++i) + { + mMaterials[i] = src.materials[i]; + } + + mBuffers.resize(src.buffers.size()); + for (U32 i = 0; i < src.buffers.size(); ++i) + { + mBuffers[i] = src.buffers[i]; + } + + mBufferViews.resize(src.bufferViews.size()); + for (U32 i = 0; i < src.bufferViews.size(); ++i) + { + mBufferViews[i] = src.bufferViews[i]; + } + + mTextures.resize(src.textures.size()); + for (U32 i = 0; i < src.textures.size(); ++i) + { + mTextures[i] = src.textures[i]; + } + + mSamplers.resize(src.samplers.size()); + for (U32 i = 0; i < src.samplers.size(); ++i) + { + mSamplers[i] = src.samplers[i]; + } + + mImages.resize(src.images.size()); + for (U32 i = 0; i < src.images.size(); ++i) + { + mImages[i] = src.images[i]; + } + + mAccessors.resize(src.accessors.size()); + for (U32 i = 0; i < src.accessors.size(); ++i) + { + mAccessors[i] = src.accessors[i]; + } + + mAnimations.resize(src.animations.size()); + for (U32 i = 0; i < src.animations.size(); ++i) + { + mAnimations[i] = src.animations[i]; + } + + mSkins.resize(src.skins.size()); + for (U32 i = 0; i < src.skins.size(); ++i) + { + mSkins[i] = src.skins[i]; + } + + return *this; +} + +const Material& Material::operator=(const tinygltf::Material& src) +{ + mName = src.name; + return *this; +} + +void Material::allocateGLResources(Asset& asset) +{ + // allocate material + mMaterial = new LLFetchedGLTFMaterial(); +} + +const Mesh& Mesh::operator=(const tinygltf::Mesh& src) +{ + mPrimitives.resize(src.primitives.size()); + for (U32 i = 0; i < src.primitives.size(); ++i) + { + mPrimitives[i] = src.primitives[i]; + } + + mWeights = src.weights; + mName = src.name; + + return *this; +} + +void Mesh::allocateGLResources(Asset& asset) +{ + for (auto& primitive : mPrimitives) + { + primitive.allocateGLResources(asset); + } +} + +const Scene& Scene::operator=(const tinygltf::Scene& src) +{ + mNodes = src.nodes; + mName = src.name; + + return *this; +} + +const Texture& Texture::operator=(const tinygltf::Texture& src) +{ + mSampler = src.sampler; + mSource = src.source; + mName = src.name; + + return *this; +} + +const Sampler& Sampler::operator=(const tinygltf::Sampler& src) +{ + mMagFilter = src.magFilter; + mMinFilter = src.minFilter; + mWrapS = src.wrapS; + mWrapT = src.wrapT; + mName = src.name; + + return *this; +} + +void Skin::uploadMatrixPalette(Asset& asset, Node& node) +{ + // prepare matrix palette + + // modelview will be applied by the shader, so assume matrix palette is in asset space + std::vector<glh::matrix4f> t_mp; + + t_mp.resize(mJoints.size()); + + for (U32 i = 0; i < mJoints.size(); ++i) + { + Node& joint = asset.mNodes[mJoints[i]]; + + //t_mp[i].set_value(joint.mRenderMatrix.getF32ptr()); + //t_mp[i] = t_mp[i] * mInverseBindMatricesData[i]; + + //t_mp[i].set_value(joint.mRenderMatrix.getF32ptr()); + //t_mp[i] = mInverseBindMatricesData[i] * t_mp[i]; + + t_mp[i].set_value(joint.mRenderMatrix.getF32ptr()); + t_mp[i] = t_mp[i] * mInverseBindMatricesData[i]; + + } + + std::vector<F32> glmp; + + glmp.resize(mJoints.size() * 12); + + F32* mp = glmp.data(); + + for (U32 i = 0; i < mJoints.size(); ++i) + { + F32* m = (F32*)t_mp[i].m; + + U32 idx = i * 12; + + mp[idx + 0] = m[0]; + mp[idx + 1] = m[1]; + mp[idx + 2] = m[2]; + mp[idx + 3] = m[12]; + + mp[idx + 4] = m[4]; + mp[idx + 5] = m[5]; + mp[idx + 6] = m[6]; + mp[idx + 7] = m[13]; + + mp[idx + 8] = m[8]; + mp[idx + 9] = m[9]; + mp[idx + 10] = m[10]; + mp[idx + 11] = m[14]; + } + + LLGLSLShader::sCurBoundShaderPtr->uniformMatrix3x4fv(LLViewerShaderMgr::AVATAR_MATRIX, + mJoints.size(), + FALSE, + (GLfloat*)glmp.data()); +} |