diff options
author | Dave Houlton <euclid@lindenlab.com> | 2022-06-01 14:37:20 -0600 |
---|---|---|
committer | Dave Houlton <euclid@lindenlab.com> | 2022-06-08 13:33:59 -0600 |
commit | c9ebb970ee916ace16e88508dc1a178336a91d52 (patch) | |
tree | 6d9bdfbbdb0197b9e9e2b3ab4f3112321e6b18a7 | |
parent | adaaccd3d74dd05b596693ef7de90aeef20b5f9d (diff) |
SL-17214 re-work gltf data organization
-rw-r--r-- | indra/llprimitive/llgltfloader.cpp | 138 | ||||
-rw-r--r-- | indra/llprimitive/llgltfloader.h | 70 |
2 files changed, 132 insertions, 76 deletions
diff --git a/indra/llprimitive/llgltfloader.cpp b/indra/llprimitive/llgltfloader.cpp index bc9c4760f7..3ec11f70c6 100644 --- a/indra/llprimitive/llgltfloader.cpp +++ b/indra/llprimitive/llgltfloader.cpp @@ -45,6 +45,9 @@ // TINYGLTF_NO_INCLUDE_STB_IMAGE_WRITE #include "tinygltf\tiny_gltf.h" + +// TODO: includes inherited from dae loader. Validate / prune + #include <boost/lexical_cast.hpp> #include "llsdserialize.h" @@ -120,9 +123,9 @@ bool LLGLTFLoader::OpenFile(const std::string &filename) if (!mGltfLoaded) { if (!warn_msg.empty()) - LL_WARNS() << "gltf load warning: " << warn_msg.c_str() << LL_ENDL; + LL_WARNS("GLTF_IMPORT") << "gltf load warning: " << warn_msg.c_str() << LL_ENDL; if (!error_msg.empty()) - LL_WARNS() << "gltf load error: " << error_msg.c_str() << LL_ENDL; + LL_WARNS("GLTF_IMPORT") << "gltf load error: " << error_msg.c_str() << LL_ENDL; return false; } @@ -251,10 +254,11 @@ bool LLGLTFLoader::parseMaterials() for (auto in_tex : mGltfModel.textures) { gltf_texture tex; - tex.image_idx = in_tex.source; - tex.sampler_idx = in_tex.sampler; + tex.imageIdx = in_tex.source; + tex.samplerIdx = in_tex.sampler; + tex.imageUuid.setNull(); - if (tex.image_idx >= mImages.size() || tex.sampler_idx >= mSamplers.size()) + if (tex.imageIdx >= mImages.size() || tex.samplerIdx >= mSamplers.size()) { LL_WARNS("GLTF_IMPORT") << "Texture sampler/image index error" << LL_ENDL; return false; @@ -269,53 +273,53 @@ bool LLGLTFLoader::parseMaterials() gltf_render_material mat; mat.name = gltf_material.name; + tinygltf::PbrMetallicRoughness& pbr = gltf_material.pbrMetallicRoughness; + mat.hasPBR = true; // Always true, for now + + mat.baseColor.set(pbr.baseColorFactor.data()); + mat.hasBaseTex = pbr.baseColorTexture.index >= 0; + mat.baseColorTexIdx = pbr.baseColorTexture.index; + mat.baseColorTexCoords = pbr.baseColorTexture.texCoord; + + mat.metalness = pbr.metallicFactor; + mat.roughness = pbr.roughnessFactor; + mat.hasMRTex = pbr.metallicRoughnessTexture.index >= 0; + mat.metalRoughTexIdx = pbr.metallicRoughnessTexture.index; + mat.metalRoughTexCoords = pbr.metallicRoughnessTexture.texCoord; + mat.normalScale = gltf_material.normalTexture.scale; - mat.hasNormalTex = gltf_material.normalTexture.index > 0; + mat.hasNormalTex = gltf_material.normalTexture.index >= 0; mat.normalTexIdx = gltf_material.normalTexture.index; - mat.normalTexCoordIdx = gltf_material.normalTexture.texCoord; + mat.normalTexCoords = gltf_material.normalTexture.texCoord; mat.occlusionScale = gltf_material.occlusionTexture.strength; - mat.hasOcclusionTex = gltf_material.occlusionTexture.index > 0; + mat.hasOcclusionTex = gltf_material.occlusionTexture.index >= 0; mat.occlusionTexIdx = gltf_material.occlusionTexture.index; - mat.occlusionTexCoordIdx = gltf_material.occlusionTexture.texCoord; + mat.occlusionTexCoords = gltf_material.occlusionTexture.texCoord; mat.emissiveColor.set(gltf_material.emissiveFactor.data()); - mat.hasEmissiveTex = gltf_material.emissiveTexture.index > 0; - mat.emissiveColorTexIdx = gltf_material.emissiveTexture.index; - mat.emissiveColorTexCoordIdx = gltf_material.emissiveTexture.texCoord; + mat.hasEmissiveTex = gltf_material.emissiveTexture.index >= 0; + mat.emissiveTexIdx = gltf_material.emissiveTexture.index; + mat.emissiveTexCoords = gltf_material.emissiveTexture.texCoord; mat.alphaMode = gltf_material.alphaMode; mat.alphaMask = gltf_material.alphaCutoff; - tinygltf::PbrMetallicRoughness& pbr = gltf_material.pbrMetallicRoughness; - mat.hasPBR = true; - - mat.pbr.baseColor.set(pbr.baseColorFactor.data()); - mat.pbr.hasBaseTex = pbr.baseColorTexture.index > 0; - mat.pbr.baseColorTexIdx = pbr.baseColorTexture.index; - mat.pbr.baseColorTexCoordIdx = pbr.baseColorTexture.texCoord; - - mat.pbr.metalness = pbr.metallicFactor; - mat.pbr.roughness = pbr.roughnessFactor; - mat.pbr.hasMRTex = pbr.metallicRoughnessTexture.index > 0; - mat.pbr.metalRoughTexIdx = pbr.metallicRoughnessTexture.index; - mat.pbr.metalRoughTexCoordIdx = pbr.metallicRoughnessTexture.texCoord; - - if ((mat.hasNormalTex && (mat.normalTexIdx >= mTextures.size())) || - (mat.hasOcclusionTex && (mat.occlusionTexIdx >= mTextures.size())) || - (mat.hasEmissiveTex && (mat.emissiveColorTexIdx >= mTextures.size())) || - (mat.pbr.hasBaseTex && (mat.pbr.baseColorTexIdx >= mTextures.size())) || - (mat.pbr.hasMRTex && (mat.pbr.metalRoughTexIdx >= mTextures.size()))) + if ((mat.hasNormalTex && (mat.normalTexIdx >= mTextures.size())) || + (mat.hasOcclusionTex && (mat.occlusionTexIdx >= mTextures.size())) || + (mat.hasEmissiveTex && (mat.emissiveTexIdx >= mTextures.size())) || + (mat.hasBaseTex && (mat.baseColorTexIdx >= mTextures.size())) || + (mat.hasMRTex && (mat.metalRoughTexIdx >= mTextures.size()))) { LL_WARNS("GLTF_IMPORT") << "Texture resource index error" << LL_ENDL; return false; } - if ((mat.hasNormalTex && (mat.normalTexCoordIdx > 2)) || // mesh can have up to 3 sets of UV - (mat.hasOcclusionTex && (mat.occlusionTexCoordIdx > 2)) || - (mat.hasEmissiveTex && (mat.emissiveColorTexCoordIdx > 2)) || - (mat.pbr.hasBaseTex && (mat.pbr.baseColorTexCoordIdx > 2)) || - (mat.pbr.hasMRTex && (mat.pbr.metalRoughTexCoordIdx > 2))) + if ((mat.hasNormalTex && (mat.normalTexCoords > 2)) || // mesh can have up to 3 sets of UV + (mat.hasOcclusionTex && (mat.occlusionTexCoords > 2)) || + (mat.hasEmissiveTex && (mat.emissiveTexCoords > 2)) || + (mat.hasBaseTex && (mat.baseColorTexCoords > 2)) || + (mat.hasMRTex && (mat.metalRoughTexCoords > 2))) { LL_WARNS("GLTF_IMPORT") << "Image texcoord index error" << LL_ENDL; return false; @@ -333,10 +337,68 @@ void LLGLTFLoader::uploadMeshes() llassert(0); } -// TODO: convert raw index buffers to UUIDs +// convert raw image buffers to texture UUIDs & assemble into a render material void LLGLTFLoader::uploadMaterials() { - //llassert(0); + for (gltf_render_material mat : mMaterials) // Initially 1 material per gltf file, but design for multiple + { + if (mat.hasBaseTex) + { + gltf_texture& gtex = mTextures[mat.baseColorTexIdx]; + if (gtex.imageUuid.isNull()) + { + gtex.imageUuid = imageBufferToTextureUUID(gtex); + } + } + + if (mat.hasMRTex) + { + gltf_texture& gtex = mTextures[mat.metalRoughTexIdx]; + if (gtex.imageUuid.isNull()) + { + gtex.imageUuid = imageBufferToTextureUUID(gtex); + } + } + + if (mat.hasNormalTex) + { + gltf_texture& gtex = mTextures[mat.normalTexIdx]; + if (gtex.imageUuid.isNull()) + { + gtex.imageUuid = imageBufferToTextureUUID(gtex); + } + } + if (mat.hasOcclusionTex) + { + gltf_texture& gtex = mTextures[mat.occlusionTexIdx]; + if (gtex.imageUuid.isNull()) + { + gtex.imageUuid = imageBufferToTextureUUID(gtex); + } + } + + if (mat.hasEmissiveTex) + { + gltf_texture& gtex = mTextures[mat.emissiveTexIdx]; + if (gtex.imageUuid.isNull()) + { + gtex.imageUuid = imageBufferToTextureUUID(gtex); + } + } + } } +LLUUID LLGLTFLoader::imageBufferToTextureUUID(const gltf_texture& tex) +{ + //gltf_image& image = mImages[tex.imageIdx]; + //gltf_sampler& sampler = mSamplers[tex.samplerIdx]; + + // fill an LLSD container with image+sampler data + + // upload texture + + // retrieve UUID + + return LLUUID::null; +} diff --git a/indra/llprimitive/llgltfloader.h b/indra/llprimitive/llgltfloader.h index 08e9836d07..24496f6324 100644 --- a/indra/llprimitive/llgltfloader.h +++ b/indra/llprimitive/llgltfloader.h @@ -32,19 +32,21 @@ #include "llglheaders.h" #include "llmodelloader.h" +// gltf_* structs are temporary, used to organize the subset of data that eventually goes into the material LLSD + typedef struct // gltf sampler { // Uses GL enums S32 minFilter; // GL_NEAREST, GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR or GL_LINEAR_MIPMAP_LINEAR S32 magFilter; // GL_NEAREST or GL_LINEAR S32 wrapS; // GL_CLAMP_TO_EDGE, GL_MIRRORED_REPEAT or GL_REPEAT S32 wrapT; // GL_CLAMP_TO_EDGE, GL_MIRRORED_REPEAT or GL_REPEAT - //S32 wrapR; // seen in some sample files, but not part of glTF 2.0 spec. Ignored. + //S32 wrapR; // Found in some sample files, but not part of glTF 2.0 spec. Ignored. std::string name; // optional, currently unused // extensions and extras are sampler optional fields that we don't support - at least initially } gltf_sampler; typedef struct // gltf image -{ // Note that glTF images are defined with row 0 at the top +{ // Note that glTF images are defined with row 0 at the top (opposite of OpenGL) U8* data; // ptr to decoded image data U32 size; // in bytes, regardless of channel width U32 width; @@ -56,34 +58,19 @@ typedef struct // gltf image typedef struct // texture { - U32 image_idx; - U32 sampler_idx; + U32 imageIdx; + U32 samplerIdx; + LLUUID imageUuid = LLUUID::null; } gltf_texture; - -// TODO: 2022-05 DJH add UUIDs for each texture -typedef struct // gltf_pbrMR_material -{ - // scalar values - LLColor4 baseColor; // linear encoding. Multiplied with vertex color, if present. - double metalness; - double roughness; - - // textures - U32 baseColorTexIdx; // always sRGB encoded - U32 baseColorTexCoordIdx; - - U32 metalRoughTexIdx; // always linear, roughness in G channel, metalness in B channel - U32 metalRoughTexCoordIdx; - - bool hasBaseTex, hasMRTex; -} gltf_pbr; - typedef struct // render material { std::string name; // scalar values + LLColor4 baseColor; // linear encoding. Multiplied with vertex color, if present. + double metalness; + double roughness; double normalScale; // scale applies only to X,Y components of normal double occlusionScale; // strength multiplier for occlusion LLColor4 emissiveColor; // emissive mulitiplier, assumed linear encoding (spec 2.0 is silent) @@ -91,20 +78,26 @@ typedef struct // render material double alphaMask; // textures - U32 normalTexIdx; // linear, valid range R[0-1], G[0-1], B[0.5-1]. Normal = texel * 2 - vec3(1.0) - U32 normalTexCoordIdx; - - U32 occlusionTexIdx; // linear, occlusion in R channel, 0 meaning fully occluded, 1 meaning not occluded - U32 occlusionTexCoordIdx; - - U32 emissiveColorTexIdx; // always stored as sRGB, in nits (candela / meter^2) - U32 emissiveColorTexCoordIdx; + U32 baseColorTexIdx; // always sRGB encoded + U32 metalRoughTexIdx; // always linear, roughness in G channel, metalness in B channel + U32 normalTexIdx; // linear, valid range R[0-1], G[0-1], B[0.5-1]. Normal = texel * 2 - vec3(1.0) + U32 occlusionTexIdx; // linear, occlusion in R channel, 0 meaning fully occluded, 1 meaning not occluded + U32 emissiveTexIdx; // always stored as sRGB, in nits (candela / meter^2) + + // texture coordinates + U32 baseColorTexCoords; + U32 metalRoughTexCoords; + U32 normalTexCoords; + U32 occlusionTexCoords; + U32 emissiveTexCoords; // TODO: Add traditional (diffuse, normal, specular) UUIDs here, or add this struct to LL_TextureEntry?? bool hasPBR; - bool hasNormalTex, hasOcclusionTex, hasEmissiveTex; - gltf_pbr pbr; + bool hasBaseTex, hasMRTex, hasNormalTex, hasOcclusionTex, hasEmissiveTex; + + // This field is populated after upload + LLUUID material_uuid = LLUUID::null; } gltf_render_material; @@ -112,7 +105,7 @@ typedef struct // gltf_mesh { std::string name; - // TODO DJH 2022-04 + // TODO add mesh import DJH 2022-04 } gltf_mesh; @@ -157,16 +150,17 @@ protected: std::vector<gltf_sampler> mSamplers; private: - U32 mGeneratedModelLimit; // Attempt to limit amount of generated submodels -// bool mPreprocessGLTF; - bool parseMeshes(); void uploadMeshes(); bool parseMaterials(); void uploadMaterials(); bool populateModelFromMesh(LLModel* pModel, const tinygltf::Mesh &mesh); + LLUUID imageBufferToTextureUUID(const gltf_texture& tex); + + U32 mGeneratedModelLimit; // Attempt to limit amount of generated submodels + // bool mPreprocessGLTF; - /* + /* Inherited from dae loader - unknown how useful here void processElement(gltfElement *element, bool &badElement, GLTF *gltf); void processGltfModel(LLModel *model, GLTF *gltf, gltfElement *pRoot, gltfMesh *mesh, gltfSkin *skin); |