summaryrefslogtreecommitdiff
path: root/indra/llprimitive/llgltfloader.h
blob: 9bffeef4ab1615cbbe5634538536fd809e60357f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/**
 * @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 "llmodelloader.h"

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.
    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
    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
} gltf_image;

typedef struct // texture
{
    U32 image_idx;
    U32 sampler_idx;
} 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;
} gltf_pbr;

typedef struct // render material
{
    std::string name;

    // scalar values
    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;      

    // 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;

    // TODO: Add traditional (diffuse, normal, specular) UUIDs here, or add this struct to LL_TextureEntry??

    bool        hasPBR;
    gltf_pbr    pbr;

} gltf_render_material;

typedef struct  // gltf_mesh
{
    std::string name;

    // TODO DJH 2022-04

} gltf_mesh;

class LLGLTFLoader : public LLModelLoader
{
  public:
    typedef std::map<std::string, LLImportMaterial> material_map;
    typedef void gltfElement;   // TBD
    typedef void GLTF;          // TBD

    // typedef std::map<gltfElement*, std::vector<LLPointer<LLModel> > >	gltf_model_map;
    // gltf_model_map	mModelsMap;

    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:
    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);

    /*
    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