From bc93177ea0788a245554882b6d721eae2e057206 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Wed, 17 Apr 2024 16:12:49 -0500 Subject: 1176 integrate llgltfnode with selection manager and llmaniptranslate/rotate (#1258) * #1176 Somewhat working GLTF Node support for translate tool * #1176 Missing file from last commit * #1176 Better translation for rotated nodes. * #1176 Fix for objects snapping back to original position * #1176 GLTF Samples compatibility pass -- attempt at improving rotation manip support, incidental cleanup, GLTF node debug display * #1176 Clean out some unused and not working functions. * #1176 Fix for mac build, incidental cleanup * Mac build fix --- indra/newview/gltf/asset.cpp | 128 ++++++++++++++++++++++++++++ indra/newview/gltf/asset.h | 68 +++------------ indra/newview/gltf/primitive.cpp | 180 +++++++++++++++++++++++++++++++-------- 3 files changed, 286 insertions(+), 90 deletions(-) (limited to 'indra/newview/gltf') diff --git a/indra/newview/gltf/asset.cpp b/indra/newview/gltf/asset.cpp index 092b6e5d4b..7181c5fa53 100644 --- a/indra/newview/gltf/asset.cpp +++ b/indra/newview/gltf/asset.cpp @@ -69,9 +69,12 @@ void Node::updateTransforms(Asset& asset, const LLMatrix4a& parentMatrix) matMul(mMatrix, parentMatrix, mAssetMatrix); mAssetMatrixInv = inverse(mAssetMatrix); + S32 my_index = this - &asset.mNodes[0]; + for (auto& childIndex : mChildren) { Node& child = asset.mNodes[childIndex]; + child.mParent = my_index; child.updateTransforms(asset, mAssetMatrix); } } @@ -208,4 +211,129 @@ S32 Asset::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, return node_hit; } +const Node& Node::operator=(const tinygltf::Node& src) +{ + F32* dstMatrix = mMatrix.getF32ptr(); + + if (src.matrix.size() == 16) + { + // Node has a transformation matrix, just copy it + for (U32 i = 0; i < 16; ++i) + { + dstMatrix[i] = (F32)src.matrix[i]; + } + } + 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]); + } + + glh::vec3f translation; + if (src.translation.size() == 3) + { + translation = 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]); + } + else + { + scale.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); + } + else + { + // node specifies no transformation, set to identity + mMatrix.setIdentity(); + } + + mChildren = src.children; + mMesh = src.mesh; + mName = src.name; + + return *this; +} + +void Asset::render(bool opaque) +{ + for (auto& node : mNodes) + { + if (node.mMesh != INVALID_INDEX) + { + Mesh& mesh = mMeshes[node.mMesh]; + for (auto& primitive : mesh.mPrimitives) + { + gGL.loadMatrix((F32*)node.mRenderMatrix.mMatrix); + bool cull = true; + if (primitive.mMaterial != INVALID_INDEX) + { + Material& material = mMaterials[primitive.mMaterial]; + + if ((material.mMaterial->mAlphaMode == LLGLTFMaterial::ALPHA_MODE_BLEND) == opaque) + { + continue; + } + material.mMaterial->bind(); + cull = !material.mMaterial->mDoubleSided; + } + else + { + if (!opaque) + { + continue; + } + LLFetchedGLTFMaterial::sDefault.bind(); + } + + LLGLDisable cull_face(!cull ? GL_CULL_FACE : 0); + + primitive.mVertexBuffer->setBuffer(); + if (primitive.mVertexBuffer->getNumIndices() > 0) + { + primitive.mVertexBuffer->draw(primitive.mGLMode, primitive.mVertexBuffer->getNumIndices(), 0); + } + else + { + primitive.mVertexBuffer->drawArrays(primitive.mGLMode, 0, primitive.mVertexBuffer->getNumVerts()); + } + + } + } + } +} + +void Asset::renderOpaque() +{ + render(true); +} + +void Asset::renderTransparent() +{ + render(false); +} + diff --git a/indra/newview/gltf/asset.h b/indra/newview/gltf/asset.h index 0f1d4e8993..acf9ba77df 100644 --- a/indra/newview/gltf/asset.h +++ b/indra/newview/gltf/asset.h @@ -171,31 +171,12 @@ namespace LL LLMatrix4a mAssetMatrixInv; //transform from asset to local space std::vector mChildren; + S32 mParent = INVALID_INDEX; + S32 mMesh = INVALID_INDEX; std::string mName; - const Node& operator=(const tinygltf::Node& src) - { - F32* dstMatrix = mMatrix.getF32ptr(); - - if (src.matrix.size() != 16) - { - mMatrix.setIdentity(); - } - else - { - for (U32 i = 0; i < 16; ++i) - { - dstMatrix[i] = (F32)src.matrix[i]; - } - } - - mChildren = src.children; - mMesh = src.mesh; - mName = src.name; - - return *this; - } + const Node& operator=(const tinygltf::Node& src); // Set mRenderMatrix to a transform that can be used for the current render pass // modelview -- parent's render matrix @@ -314,21 +295,23 @@ namespace LL void allocateGLResources(const std::string& filename, const tinygltf::Model& model) { - for (auto& mesh : mMeshes) - { - mesh.allocateGLResources(*this); - } - + // 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); + } } // update asset-to-node and node-to-asset transforms @@ -337,34 +320,9 @@ namespace LL // update node render transforms void updateRenderTransforms(const LLMatrix4a& modelview); - void renderOpaque() - { - for (auto& node : mNodes) - { - if (node.mMesh != INVALID_INDEX) - { - Mesh& mesh = mMeshes[node.mMesh]; - for (auto& primitive : mesh.mPrimitives) - { - gGL.loadMatrix((F32*)node.mRenderMatrix.mMatrix); - if (primitive.mMaterial != INVALID_INDEX) - { - Material& material = mMaterials[primitive.mMaterial]; - material.mMaterial->bind(); - } - primitive.mVertexBuffer->setBuffer(); - if (primitive.mVertexBuffer->getNumIndices() > 0) - { - primitive.mVertexBuffer->draw(primitive.mGLMode, primitive.mVertexBuffer->getNumIndices(), 0); - } - else - { - primitive.mVertexBuffer->drawArrays(primitive.mGLMode, 0, primitive.mVertexBuffer->getNumVerts()); - } - } - } - } - } + void render(bool opaque); + void renderOpaque(); + void renderTransparent(); // return the index of the node that the line segment intersects with, or -1 if no hit // input and output values must be in this asset's local coordinate frame diff --git a/indra/newview/gltf/primitive.cpp b/indra/newview/gltf/primitive.cpp index 71654dcfdd..b5d59e1b24 100644 --- a/indra/newview/gltf/primitive.cpp +++ b/indra/newview/gltf/primitive.cpp @@ -162,10 +162,25 @@ void Primitive::copyAttribute(Asset& asset, S32 accessorIdx, LLStrider& dst) { copyAttributeArray(asset, accessor, (const U32*)src, dst, bufferView.mByteStride); } + else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE) + { + copyAttributeArray(asset, accessor, (const U8*)src, dst, bufferView.mByteStride); + } + else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_SHORT) + { + copyAttributeArray(asset, accessor, (const S16*)src, dst, bufferView.mByteStride); + } + else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_BYTE) + { + copyAttributeArray(asset, accessor, (const S8*)src, dst, bufferView.mByteStride); + } + else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_DOUBLE) + { + copyAttributeArray(asset, accessor, (const F64*)src, dst, bufferView.mByteStride); + } else - { - LL_ERRS() << "Unsupported component type" << LL_ENDL; + LL_ERRS("GLTF") << "Unsupported component type" << LL_ENDL; } } @@ -179,11 +194,11 @@ void Primitive::allocateGLResources(Asset& asset) // get the number of vertices U32 numVertices = 0; - for (auto& it : mAttributes) + if (!mAttributes.empty()) { - const Accessor& accessor = asset.mAccessors[it.second]; + auto it = mAttributes.begin(); + const Accessor& accessor = asset.mAccessors[it->second]; numVertices = accessor.mCount; - break; } // get the number of indices @@ -294,6 +309,14 @@ void Primitive::allocateGLResources(Asset& asset) src += sizeof(U16); } } + else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE) + { + for (U32 i = 0; i < numIndices; ++i) + { + *(dst++) = *(U8*)src; + src += sizeof(U8); + } + } else { LL_ERRS("GLTF") << "Unsupported component type for indices" << LL_ENDL; @@ -317,6 +340,22 @@ void Primitive::allocateGLResources(Asset& asset) } } + // bake material basecolor into color array + if (mMaterial != INVALID_INDEX) + { + const Material& material = asset.mMaterials[mMaterial]; + LLColor4 baseColor = material.mMaterial->mBaseColor; + LLStrider dst; + mVertexBuffer->getColorStrider(dst); + + for (U32 i = 0; i < numVertices; ++i) + { + LLColor4 col = *dst; + *dst = LLColor4U(baseColor * col); + dst++; + } + } + if (needs_texcoord) { // set default texcoord LLStrider dst; @@ -368,15 +407,51 @@ void Primitive::allocateGLResources(Asset& asset) mVertexBuffer->unmapBuffer(); } +void initOctreeTriangle(LLVolumeTriangle* tri, F32 scaler, S32 i0, S32 i1, S32 i2, const LLVector4a& v0, const LLVector4a& v1, const LLVector4a& v2) +{ + //store pointers to vertex data + tri->mV[0] = &v0; + tri->mV[1] = &v1; + tri->mV[2] = &v2; + + //store indices + tri->mIndex[0] = i0; + tri->mIndex[1] = i1; + tri->mIndex[2] = i2; + + //get minimum point + LLVector4a min = v0; + min.setMin(min, v1); + min.setMin(min, v2); + + //get maximum point + LLVector4a max = v0; + max.setMax(max, v1); + max.setMax(max, v2); + + //compute center + LLVector4a center; + center.setAdd(min, max); + center.mul(0.5f); + + tri->mPositionGroup = center; + + //compute "radius" + LLVector4a size; + size.setSub(max, min); + + tri->mRadius = size.getLength3().getF32() * scaler; +} + void Primitive::createOctree() { // create octree mOctree = new LLVolumeOctree(); + F32 scaler = 0.25f; + if (mMode == TINYGLTF_MODE_TRIANGLES) { - F32 scaler = 0.25f; - const U32 num_triangles = mVertexBuffer->getNumIndices() / 3; // Initialize all the triangles we need mOctreeTriangles.resize(num_triangles); @@ -388,47 +463,82 @@ void Primitive::createOctree() { //for each triangle const U32 index = triangle_index * 3; LLVolumeTriangle* tri = &mOctreeTriangles[triangle_index]; - const LLVector4a& v0 = pos[indices[index]]; - const LLVector4a& v1 = pos[indices[index + 1]]; - const LLVector4a& v2 = pos[indices[index + 2]]; + S32 i0 = indices[index]; + S32 i1 = indices[index + 1]; + S32 i2 = indices[index + 2]; + + const LLVector4a& v0 = pos[i0]; + const LLVector4a& v1 = pos[i1]; + const LLVector4a& v2 = pos[i2]; + + initOctreeTriangle(tri, scaler, i0, i1, i2, v0, v1, v2); + + //insert + mOctree->insert(tri); + } + } + else if (mMode == TINYGLTF_MODE_TRIANGLE_STRIP) + { + const U32 num_triangles = mVertexBuffer->getNumIndices() - 2; + // Initialize all the triangles we need + mOctreeTriangles.resize(num_triangles); - //store pointers to vertex data - tri->mV[0] = &v0; - tri->mV[1] = &v1; - tri->mV[2] = &v2; + LLVector4a* pos = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_VERTEX)); + U16* indices = (U16*)mVertexBuffer->getMappedIndices(); - //store indices - tri->mIndex[0] = indices[index]; - tri->mIndex[1] = indices[index + 1]; - tri->mIndex[2] = indices[index + 2]; + for (U32 triangle_index = 0; triangle_index < num_triangles; ++triangle_index) + { //for each triangle + const U32 index = triangle_index + 2; + LLVolumeTriangle* tri = &mOctreeTriangles[triangle_index]; + S32 i0 = indices[index]; + S32 i1 = indices[index - 1]; + S32 i2 = indices[index - 2]; + + const LLVector4a& v0 = pos[i0]; + const LLVector4a& v1 = pos[i1]; + const LLVector4a& v2 = pos[i2]; - //get minimum point - LLVector4a min = v0; - min.setMin(min, v1); - min.setMin(min, v2); + initOctreeTriangle(tri, scaler, i0, i1, i2, v0, v1, v2); - //get maximum point - LLVector4a max = v0; - max.setMax(max, v1); - max.setMax(max, v2); + //insert + mOctree->insert(tri); + } + } + else if (mMode == TINYGLTF_MODE_TRIANGLE_FAN) + { + const U32 num_triangles = mVertexBuffer->getNumIndices() - 2; + // Initialize all the triangles we need + mOctreeTriangles.resize(num_triangles); - //compute center - LLVector4a center; - center.setAdd(min, max); - center.mul(0.5f); + LLVector4a* pos = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_VERTEX)); + U16* indices = (U16*)mVertexBuffer->getMappedIndices(); - tri->mPositionGroup = center; + for (U32 triangle_index = 0; triangle_index < num_triangles; ++triangle_index) + { //for each triangle + const U32 index = triangle_index + 2; + LLVolumeTriangle* tri = &mOctreeTriangles[triangle_index]; + S32 i0 = indices[0]; + S32 i1 = indices[index - 1]; + S32 i2 = indices[index - 2]; - //compute "radius" - LLVector4a size; - size.setSub(max, min); + const LLVector4a& v0 = pos[i0]; + const LLVector4a& v1 = pos[i1]; + const LLVector4a& v2 = pos[i2]; - tri->mRadius = size.getLength3().getF32() * scaler; + initOctreeTriangle(tri, scaler, i0, i1, i2, v0, v1, v2); //insert mOctree->insert(tri); } } + else if (mMode == TINYGLTF_MODE_POINTS || + mMode == TINYGLTF_MODE_LINE || + mMode == TINYGLTF_MODE_LINE_LOOP || + mMode == TINYGLTF_MODE_LINE_STRIP) + { + // nothing to do, no volume... maybe add some collision geometry around these primitive types? + } + else { LL_ERRS() << "Unsupported Primitive mode" << LL_ENDL; -- cgit v1.2.3