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; | 
