summaryrefslogtreecommitdiff
path: root/indra/newview/gltf/llgltfloader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/gltf/llgltfloader.cpp')
-rw-r--r--indra/newview/gltf/llgltfloader.cpp278
1 files changed, 247 insertions, 31 deletions
diff --git a/indra/newview/gltf/llgltfloader.cpp b/indra/newview/gltf/llgltfloader.cpp
index 106c20d4d3..ce87a9594f 100644
--- a/indra/newview/gltf/llgltfloader.cpp
+++ b/indra/newview/gltf/llgltfloader.cpp
@@ -25,6 +25,7 @@
*/
#include "llgltfloader.h"
+#include "meshoptimizer.h"
// Import & define single-header gltf import/export lib
#define TINYGLTF_IMPLEMENTATION
@@ -152,20 +153,19 @@ bool LLGLTFLoader::parseMeshes()
if (populateModelFromMesh(pModel, mesh, mats) && (LLModel::NO_ERRORS == pModel->getStatus()) && validate_model(pModel))
{
mModelList.push_back(pModel);
- LLVector3 mesh_scale_vector;
- LLVector3 mesh_translation_vector;
- pModel->getNormalizedScaleTranslation(mesh_scale_vector, mesh_translation_vector);
+ LLVector3 mesh_scale_vector = LLVector3(node.mScale);
+ LLVector3 mesh_translation_vector = LLVector3(node.mTranslation);
LLMatrix4 mesh_translation;
mesh_translation.setTranslation(mesh_translation_vector);
mesh_translation *= transform;
- transform = mesh_translation;
-
+ transform = LLMatrix4((float*)&node.mAssetMatrix[0][0]);
+ /*
LLMatrix4 mesh_scale;
mesh_scale.initScale(mesh_scale_vector);
mesh_scale *= transform;
transform = mesh_scale;
-
+ */
mScene[transform].push_back(LLModelInstance(pModel, node.mName, transform, mats));
}
@@ -189,47 +189,263 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh &
auto prims = mesh.mPrimitives;
for (auto prim : prims)
{
- // So primitives already have all of the data we need for a given face in SL land.
- // Primitives may only ever have a single material assigned to them - as the relation is 1:1 in terms of intended draw call count.
- // Just go ahead and populate faces direct from the GLTF primitives here.
- // -Geenz 2025-04-07
- LLVolumeFace face;
- LLVolumeFace::VertexMapData::PointMap point_map;
+ // Unfortunately, SLM does not support 32 bit indices. Filter out anything that goes beyond 16 bit.
+ if (prim.getVertexCount() < USHRT_MAX)
+ {
+ // So primitives already have all of the data we need for a given face in SL land.
+ // Primitives may only ever have a single material assigned to them - as the relation is 1:1 in terms of intended draw call
+ // count. Just go ahead and populate faces direct from the GLTF primitives here. -Geenz 2025-04-07
+ LLVolumeFace face;
+ LLVolumeFace::VertexMapData::PointMap point_map;
+
+ std::vector<GLTFVertex> vertices;
+ std::vector<U16> indices;
+
+ LLImportMaterial impMat;
+
+ LL::GLTF::Material* material = nullptr;
+
+ if (prim.mMaterial >= 0)
+ material = &mGLTFAsset.mMaterials[prim.mMaterial];
+
+ impMat.mDiffuseColor = LLColor4::white;
+
+ for (U32 i = 0; i < prim.getVertexCount(); i++)
+ {
+ GLTFVertex vert;
+ vert.position = glm::vec3(prim.mPositions[i][0], prim.mPositions[i][1], prim.mPositions[i][2]);
+ vert.normal = glm::vec3(prim.mNormals[i][0], prim.mNormals[i][1], prim.mNormals[2][i]);
+ vert.uv0 = glm::vec2(prim.mTexCoords0[i][0], prim.mTexCoords0[i][1]);
+ vertices.push_back(vert);
+ }
+
+ for (U32 i = 0; i < prim.getIndexCount(); i++)
+ {
+ indices.push_back(prim.mIndexArray[i]);
+ }
+
+ std::vector<LLVolumeFace::VertexData> faceVertices;
+
+ for (U32 i = 0; i < vertices.size(); i++)
+ {
+ LLVolumeFace::VertexData vert;
+ LLVector4a position = LLVector4a(vertices[i].position.x, vertices[i].position.y, vertices[i].position.z);
+ LLVector4a normal = LLVector4a(vertices[i].normal.x, vertices[i].normal.y, vertices[i].normal.z);
+ vert.setPosition(position);
+ vert.setNormal(normal);
+ vert.mTexCoord = LLVector2(vertices[i].uv0.x, vertices[i].uv0.y);
+ faceVertices.push_back(vert);
+ }
+
+ face.fillFromLegacyData(faceVertices, indices);
+
+ pModel->getVolumeFaces().push_back(face);
+ pModel->getMaterialList().push_back("mat" + std::to_string(prim.mMaterial));
+ mats["mat" + std::to_string(prim.mMaterial)] = impMat;
+ }
+ }
+
+ return true;
+}
+/*
+LLModel::EModelStatus loadFaceFromGLTFModel(LLModel* pModel, const LL::GLTF::Mesh& mesh, material_map& mats, LLSD& log_msg)
+{
+ LLVolumeFace face;
+ std::vector<LLVolumeFace::VertexData> verts;
+ std::vector<U16> indices;
+
+ S32 pos_offset = -1;
+ S32 tc_offset = -1;
+ S32 norm_offset = -1;
+
+ auto pos_source = mesh.mPrimitives[0].mPositions;
+ auto tc_source = mesh.mPrimitives[0].mNormals;
+ auto norm_source = mesh.mPrimitives[0].mTexCoords0;
+
+ S32 idx_stride = 0;
+
+ if (pos_source.size() > USHRT_MAX)
+ {
+ LL_WARNS() << "Unable to process mesh due to 16-bit index limits; invalid model; invalid model." << LL_ENDL;
+ LLSD args;
+ args["Message"] = "ParsingErrorBadElement";
+ log_msg.append(args);
+ return LLModel::BAD_ELEMENT;
+
+ }
+
+ std::vector<U32> idx = mesh.mPrimitives[0].mIndexArray;
+
+ domListOfFloats dummy;
+ domListOfFloats& v = pos_source ? pos_source->getFloat_array()->getValue() : dummy;
+ domListOfFloats& tc = tc_source ? tc_source->getFloat_array()->getValue() : dummy;
+ domListOfFloats& n = norm_source ? norm_source->getFloat_array()->getValue() : dummy;
+
+ if (pos_source.size() == 0)
+ {
+ return LLModel::BAD_ELEMENT;
+ }
+
+ // VFExtents change
+ face.mExtents[0].set(pos_source[0][0], pos_source[0][1], pos_source[0][2]);
+ face.mExtents[1].set(pos_source[0][0], pos_source[0][1], pos_source[0][2]);
+
+ LLVolumeFace::VertexMapData::PointMap point_map;
+
+ if (idx_stride <= 0 || (pos_source && pos_offset >= idx_stride) || (tc_source && tc_offset >= idx_stride) ||
+ (norm_source && norm_offset >= idx_stride))
+ {
+ // Looks like these offsets should fit inside idx_stride
+ // Might be good idea to also check idx.getCount()%idx_stride != 0
+ LL_WARNS() << "Invalid pos_offset " << pos_offset << ", tc_offset " << tc_offset << " or norm_offset " << norm_offset << LL_ENDL;
+ return LLModel::BAD_ELEMENT;
+ }
+
+ for (U32 i = 0; i < idx.getCount(); i += idx_stride)
+ {
+ LLVolumeFace::VertexData cv;
+ if (pos_source)
+ {
+ cv.setPosition(
+ LLVector4a((F32)v[idx[i + pos_offset] * 3 + 0], (F32)v[idx[i + pos_offset] * 3 + 1], (F32)v[idx[i + pos_offset] * 3 + 2]));
+ }
- std::vector<LLVolumeFace::VertexData> vertices;
- std::vector<U16> indices;
+ if (tc_source)
+ {
+ cv.mTexCoord.setVec((F32)tc[idx[i + tc_offset] * 2 + 0], (F32)tc[idx[i + tc_offset] * 2 + 1]);
+ }
- LLImportMaterial impMat;
+ if (norm_source)
+ {
+ cv.setNormal(LLVector4a((F32)n[idx[i + norm_offset] * 3 + 0],
+ (F32)n[idx[i + norm_offset] * 3 + 1],
+ (F32)n[idx[i + norm_offset] * 3 + 2]));
+ }
- auto material = mGLTFAsset.mMaterials[prim.mMaterial];
+ bool found = false;
- impMat.mDiffuseColor = LLColor4::white;
+ LLVolumeFace::VertexMapData::PointMap::iterator point_iter;
+ point_iter = point_map.find(LLVector3(cv.getPosition().getF32ptr()));
+ if (point_iter != point_map.end())
+ {
+ for (U32 j = 0; j < point_iter->second.size(); ++j)
+ {
+ // We have a matching loc
+ //
+ if ((point_iter->second)[j] == cv)
+ {
+ U16 shared_index = (point_iter->second)[j].mIndex;
+
+ // Don't share verts within the same tri, degenerate
+ //
+ U32 indx_size = static_cast<U32>(indices.size());
+ U32 verts_new_tri = indx_size % 3;
+ if ((verts_new_tri < 1 || indices[indx_size - 1] != shared_index) &&
+ (verts_new_tri < 2 || indices[indx_size - 2] != shared_index))
+ {
+ found = true;
+ indices.push_back(shared_index);
+ }
+ break;
+ }
+ }
+ }
- for (U32 i = 0; i < prim.getVertexCount(); i++)
+ if (!found)
{
- LLVolumeFace::VertexData vert;
- vert.setPosition(prim.mPositions[i]);
- vert.setNormal(prim.mNormals[i]);
- vert.mTexCoord = prim.mTexCoords0[i];
- vertices.push_back(vert);
+ // VFExtents change
+ update_min_max(face.mExtents[0], face.mExtents[1], cv.getPosition());
+ verts.push_back(cv);
+ if (verts.size() >= 65535)
+ {
+ // llerrs << "Attempted to write model exceeding 16-bit index buffer limitation." << LL_ENDL;
+ return LLModel::VERTEX_NUMBER_OVERFLOW;
+ }
+ U16 index = (U16)(verts.size() - 1);
+ indices.push_back(index);
+
+ LLVolumeFace::VertexMapData d;
+ d.setPosition(cv.getPosition());
+ d.mTexCoord = cv.mTexCoord;
+ d.setNormal(cv.getNormal());
+ d.mIndex = index;
+ if (point_iter != point_map.end())
+ {
+ point_iter->second.push_back(d);
+ }
+ else
+ {
+ point_map[LLVector3(d.getPosition().getF32ptr())].push_back(d);
+ }
}
- for (S32 i = 0; i < prim.mIndexArray.size(); i++)
+ if (indices.size() % 3 == 0 && verts.size() >= 65532)
{
- indices.push_back(prim.mIndexArray[i]);
+ std::string material;
+
+ if (tri->getMaterial())
+ {
+ material = std::string(tri->getMaterial());
+ }
+
+ materials.push_back(material);
+ face_list.push_back(face);
+ face_list.rbegin()->fillFromLegacyData(verts, indices);
+ LLVolumeFace& new_face = *face_list.rbegin();
+ if (!norm_source)
+ {
+ // ll_aligned_free_16(new_face.mNormals);
+ new_face.mNormals = NULL;
+ }
+
+ if (!tc_source)
+ {
+ // ll_aligned_free_16(new_face.mTexCoords);
+ new_face.mTexCoords = NULL;
+ }
+
+ face = LLVolumeFace();
+ // VFExtents change
+ face.mExtents[0].set((F32)v[0], (F32)v[1], (F32)v[2]);
+ face.mExtents[1].set((F32)v[0], (F32)v[1], (F32)v[2]);
+
+ verts.clear();
+ indices.clear();
+ point_map.clear();
}
+ }
- face.fillFromLegacyData(vertices, indices);
+ if (!verts.empty())
+ {
+ std::string material;
- pModel->getVolumeFaces().push_back(face);
- pModel->getMaterialList().push_back("mat" + std::to_string(prim.mMaterial));
- mats["mat" + std::to_string(prim.mMaterial)] = impMat;
+ if (tri->getMaterial())
+ {
+ material = std::string(tri->getMaterial());
+ }
+
+ materials.push_back(material);
+ face_list.push_back(face);
+
+ face_list.rbegin()->fillFromLegacyData(verts, indices);
+ LLVolumeFace& new_face = *face_list.rbegin();
+ if (!norm_source)
+ {
+ // ll_aligned_free_16(new_face.mNormals);
+ new_face.mNormals = NULL;
+ }
+
+ if (!tc_source)
+ {
+ // ll_aligned_free_16(new_face.mTexCoords);
+ new_face.mTexCoords = NULL;
+ }
}
- return true;
+ return LLModel::NO_ERRORS;
}
-
+*/
bool LLGLTFLoader::parseMaterials()
{
return true;