diff options
author | Jonathan "Geenz" Goodman <geenz@geenzo.com> | 2025-04-28 03:33:03 -0400 |
---|---|---|
committer | Jonathan "Geenz" Goodman <geenz@geenzo.com> | 2025-04-28 03:33:03 -0400 |
commit | f6b066073e9a6318dc9ebac4b0137b81e2982f14 (patch) | |
tree | 755707899fc847c656c0491359f76168f9de2796 | |
parent | c8499b7f01ac3f46f0764ea8195c30a4a2ec27a8 (diff) |
Cursed stuff!
-rw-r--r-- | indra/newview/gltf/llgltfloader.cpp | 278 | ||||
-rw-r--r-- | indra/newview/gltf/llgltfloader.h | 7 |
2 files changed, 254 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; diff --git a/indra/newview/gltf/llgltfloader.h b/indra/newview/gltf/llgltfloader.h index 3b7147f588..cfb545be6f 100644 --- a/indra/newview/gltf/llgltfloader.h +++ b/indra/newview/gltf/llgltfloader.h @@ -139,6 +139,13 @@ class LLGLTFLoader : public LLModelLoader virtual bool OpenFile(const std::string &filename); + struct GLTFVertex + { + glm::vec3 position; + glm::vec3 normal; + glm::vec2 uv0; + }; + protected: LL::GLTF::Asset mGLTFAsset; tinygltf::Model mGltfModel; |