diff options
| -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);  | 
