summaryrefslogtreecommitdiff
path: root/indra/newview/gltf/asset.cpp
diff options
context:
space:
mode:
authorRunitaiLinden <davep@lindenlab.com>2024-04-24 09:51:15 -0500
committerGitHub <noreply@github.com>2024-04-24 09:51:15 -0500
commitcadc1a02cc7289dabd368dd1a1d237c042e9f82e (patch)
tree7493c7a7a8a8b395bc9fc98a1a9dd018098c4147 /indra/newview/gltf/asset.cpp
parentf1b7e806eb30a343876036eff5caef7c03309aa6 (diff)
1285 GLTF Animation Prototype
Diffstat (limited to 'indra/newview/gltf/asset.cpp')
-rw-r--r--indra/newview/gltf/asset.cpp375
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());
+}