207 lines
7.9 KiB
C++
207 lines
7.9 KiB
C++
/**
|
|
* @file LLGLTFLoader.h
|
|
* @brief LLGLTFLoader class definition
|
|
*
|
|
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
|
|
* Second Life Viewer Source Code
|
|
* Copyright (C) 2022, Linden Research, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation;
|
|
* version 2.1 of the License only.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
|
* $/LicenseInfo$
|
|
*/
|
|
|
|
#ifndef LL_LLGLTFLoader_H
|
|
#define LL_LLGLTFLoader_H
|
|
|
|
#include "tinygltf/tiny_gltf.h"
|
|
|
|
#include "llglheaders.h"
|
|
#include "llmodelloader.h"
|
|
|
|
// gltf_* structs are temporary, used to organize the subset of data that eventually goes into the material LLSD
|
|
|
|
class gltf_sampler
|
|
{
|
|
public:
|
|
// 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; // 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
|
|
};
|
|
|
|
class gltf_image
|
|
{
|
|
public:// 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;
|
|
U32 height;
|
|
U32 numChannels; // range 1..4
|
|
U32 bytesPerChannel; // converted from gltf "bits", expects only 8, 16 or 32 as input
|
|
U32 pixelType; // one of (TINYGLTF_COMPONENT_TYPE)_UNSIGNED_BYTE, _UNSIGNED_SHORT, _UNSIGNED_INT, or _FLOAT
|
|
};
|
|
|
|
class gltf_texture
|
|
{
|
|
public:
|
|
U32 imageIdx;
|
|
U32 samplerIdx;
|
|
LLUUID imageUuid = LLUUID::null;
|
|
};
|
|
|
|
class gltf_render_material
|
|
{
|
|
public:
|
|
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)
|
|
std::string alphaMode; // "OPAQUE", "MASK" or "BLEND"
|
|
double alphaMask; // alpha cut-off
|
|
|
|
// textures
|
|
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 hasBaseTex, hasMRTex, hasNormalTex, hasOcclusionTex, hasEmissiveTex;
|
|
|
|
// This field is populated after upload
|
|
LLUUID material_uuid = LLUUID::null;
|
|
|
|
};
|
|
|
|
class gltf_mesh
|
|
{
|
|
public:
|
|
std::string name;
|
|
|
|
// TODO add mesh import DJH 2022-04
|
|
|
|
};
|
|
|
|
class LLGLTFLoader : public LLModelLoader
|
|
{
|
|
public:
|
|
typedef std::map<std::string, LLImportMaterial> material_map;
|
|
|
|
LLGLTFLoader(std::string filename,
|
|
S32 lod,
|
|
LLModelLoader::load_callback_t load_cb,
|
|
LLModelLoader::joint_lookup_func_t joint_lookup_func,
|
|
LLModelLoader::texture_load_func_t texture_load_func,
|
|
LLModelLoader::state_callback_t state_cb,
|
|
void * opaque_userdata,
|
|
JointTransformMap & jointTransformMap,
|
|
JointNameSet & jointsFromNodes,
|
|
std::map<std::string, std::string> &jointAliasMap,
|
|
U32 maxJointsPerMesh,
|
|
U32 modelLimit); //,
|
|
//bool preprocess );
|
|
virtual ~LLGLTFLoader();
|
|
|
|
virtual bool OpenFile(const std::string &filename);
|
|
|
|
protected:
|
|
tinygltf::Model mGltfModel;
|
|
bool mGltfLoaded;
|
|
bool mMeshesLoaded;
|
|
bool mMaterialsLoaded;
|
|
|
|
std::vector<gltf_mesh> mMeshes;
|
|
std::vector<gltf_render_material> mMaterials;
|
|
|
|
std::vector<gltf_texture> mTextures;
|
|
std::vector<gltf_image> mImages;
|
|
std::vector<gltf_sampler> mSamplers;
|
|
|
|
private:
|
|
bool parseMeshes();
|
|
void uploadMeshes();
|
|
bool parseMaterials();
|
|
void uploadMaterials();
|
|
bool populateModelFromMesh(LLModel* pModel, const tinygltf::Mesh &mesh);
|
|
LLUUID imageBufferToTextureUUID(const gltf_texture& tex);
|
|
|
|
// bool mPreprocessGLTF;
|
|
|
|
/* Below inherited from dae loader - unknown if/how useful here
|
|
|
|
void processElement(gltfElement *element, bool &badElement, GLTF *gltf);
|
|
void processGltfModel(LLModel *model, GLTF *gltf, gltfElement *pRoot, gltfMesh *mesh, gltfSkin *skin);
|
|
|
|
material_map getMaterials(LLModel *model, gltfInstance_geometry *instance_geo, GLTF *gltf);
|
|
LLImportMaterial profileToMaterial(gltfProfile_COMMON *material, GLTF *gltf);
|
|
LLColor4 getGltfColor(gltfElement *element);
|
|
|
|
gltfElement *getChildFromElement(gltfElement *pElement, std::string const &name);
|
|
|
|
bool isNodeAJoint(gltfNode *pNode);
|
|
void processJointNode(gltfNode *pNode, std::map<std::string, LLMatrix4> &jointTransforms);
|
|
void extractTranslation(gltfTranslate *pTranslate, LLMatrix4 &transform);
|
|
void extractTranslationViaElement(gltfElement *pTranslateElement, LLMatrix4 &transform);
|
|
void extractTranslationViaSID(gltfElement *pElement, LLMatrix4 &transform);
|
|
void buildJointToNodeMappingFromScene(gltfElement *pRoot);
|
|
void processJointToNodeMapping(gltfNode *pNode);
|
|
void processChildJoints(gltfNode *pParentNode);
|
|
|
|
bool verifyCount(int expected, int result);
|
|
|
|
// Verify that a controller matches vertex counts
|
|
bool verifyController(gltfController *pController);
|
|
|
|
static bool addVolumeFacesFromGltfMesh(LLModel *model, gltfMesh *mesh, LLSD &log_msg);
|
|
static bool createVolumeFacesFromGltfMesh(LLModel *model, gltfMesh *mesh);
|
|
|
|
static LLModel *loadModelFromGltfMesh(gltfMesh *mesh);
|
|
|
|
// Loads a mesh breaking it into one or more models as necessary
|
|
// to get around volume face limitations while retaining >8 materials
|
|
//
|
|
bool loadModelsFromGltfMesh(gltfMesh *mesh, std::vector<LLModel *> &models_out, U32 submodel_limit);
|
|
|
|
static std::string getElementLabel(gltfElement *element);
|
|
static size_t getSuffixPosition(std::string label);
|
|
static std::string getLodlessLabel(gltfElement *element);
|
|
|
|
static std::string preprocessGLTF(std::string filename);
|
|
*/
|
|
|
|
};
|
|
#endif // LL_LLGLTFLLOADER_H
|