summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Houlton <euclid@lindenlab.com>2022-06-01 14:37:20 -0600
committerDave Houlton <euclid@lindenlab.com>2022-06-08 13:33:59 -0600
commitc9ebb970ee916ace16e88508dc1a178336a91d52 (patch)
tree6d9bdfbbdb0197b9e9e2b3ab4f3112321e6b18a7
parentadaaccd3d74dd05b596693ef7de90aeef20b5f9d (diff)
SL-17214 re-work gltf data organization
-rw-r--r--indra/llprimitive/llgltfloader.cpp138
-rw-r--r--indra/llprimitive/llgltfloader.h70
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);