Skip to content
Snippets Groups Projects
Commit c9ebb970 authored by Dave Houlton's avatar Dave Houlton
Browse files

SL-17214 re-work gltf data organization

parent adaaccd3
No related branches found
No related tags found
2 merge requests!3Update to main branch,!2Rebase onto current main branch
......@@ -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;
}
......@@ -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 @@ class LLGLTFLoader : public LLModelLoader
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);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment