SL-17214 re-work gltf data organization
parent
adaaccd3d7
commit
c9ebb970ee
|
|
@ -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 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)
|
||||
|
||||
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;
|
||||
// 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);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue