summaryrefslogtreecommitdiff
path: root/indra/llprimitive/llmodelloader.h
blob: 637dabe08a714fdc47792da92872b7f0704a35ee (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
208
209
210
211
212
213
214
215
216
217
218
/**
 * @file llmodelloader.h
 * @brief LLModelLoader class definition
 *
 * $LicenseInfo:firstyear=2004&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, 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_LLMODELLOADER_H
#define LL_LLMODELLOADER_H

#include "llmodel.h"
#include "llthread.h"
#include <boost/function.hpp>
#include <list>

class LLJoint;

typedef std::map<std::string, LLMatrix4> JointTransformMap;
typedef std::map<std::string, LLMatrix4>::iterator JointTransformMapIt;
typedef std::map<std::string, std::string> JointMap;
typedef std::deque<std::string> JointNameSet;

const S32 SLM_SUPPORTED_VERSION = 3;
const S32 NUM_LOD = 4;

const U32 LEGACY_RIG_OK = 0;
const U32 LEGACY_RIG_FLAG_TOO_MANY_JOINTS = 1;
const U32 LEGACY_RIG_FLAG_UNKNOWN_JOINT = 2;

class LLModelLoader : public LLThread
{
public:

    typedef std::map<std::string, LLImportMaterial> material_map;
    typedef std::vector<LLPointer<LLModel>> model_list;
    typedef std::vector<LLModelInstance> model_instance_list;
    typedef std::map<LLMatrix4, model_instance_list> scene;

    // Callback with loaded model data and loaded LoD
    //
    typedef boost::function<void (scene&, model_list&, S32, void*)> load_callback_t;

    // Function to provide joint lookup by name
    // (within preview avi skeleton, for example)
    //
    typedef boost::function<LLJoint* (const std::string&, void*)> joint_lookup_func_t;

    // Func to load and associate material with all it's textures,
    // returned value is the number of textures loaded
    // intentionally non-const so func can modify material to
    // store platform-specific data
    //
    typedef boost::function<U32 (LLImportMaterial&, void*)> texture_load_func_t;

    // Callback to inform client of state changes
    // during loading process (errors will be reported
    // as state changes here as well)
    //
    typedef boost::function<void (U32, void*)> state_callback_t;

    typedef enum
    {
        STARTING = 0,
        READING_FILE,
        CREATING_FACES,
        GENERATING_VERTEX_BUFFERS,
        GENERATING_LOD,
        DONE,
        WARNING_BIND_SHAPE_ORIENTATION,
        ERROR_PARSING, //basically loading failed
        ERROR_MATERIALS,
        ERROR_PASSWORD_REQUIRED,
        ERROR_NEED_MORE_MEMORY,
        ERROR_INVALID_FILE,
        ERROR_LOADER_SETUP,
        ERROR_INVALID_PARAMETERS,
        ERROR_OUT_OF_RANGE,
        ERROR_FILE_VERSION_INVALID,
        ERROR_MODEL // this error should always be last in this list, error code is passed as ERROR_MODEL+error_code
    } eLoadState;

    U32 mState;
    std::string mFilename;

    S32 mLod;

    LLMatrix4 mTransform;
    bool mFirstTransform;
    LLVector3 mExtents[2];

    bool mTrySLM;
    bool mCacheOnlyHitIfRigged; // ignore cached SLM if it does not contain rig info (and we want rig info)

    model_list      mModelList;
    scene               mScene;

    typedef std::queue<LLPointer<LLModel> > model_queue;

    //queue of models that need a physics rep
    model_queue mPhysicsQ;

    //map of avatar joints as named in COLLADA assets to internal joint names
    JointMap            mJointMap;
    JointTransformMap&  mJointList;
    JointNameSet&       mJointsFromNode;
    U32                 mMaxJointsPerMesh;

    LLModelLoader(
        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,
        JointMap&                           legalJointNamesMap,
        U32                                 maxJointsPerMesh);
    virtual ~LLModelLoader();

    virtual void setNoNormalize() { mNoNormalize = true; }
    virtual void setNoOptimize() { mNoOptimize = true; }

    virtual void run();

    static bool getSLMFilename(const std::string& model_filename, std::string& slm_filename);

    // Will try SLM or derived class OpenFile as appropriate
    //
    virtual bool doLoadModel();

    // Derived classes need to provide their parsing of files here
    //
    virtual bool OpenFile(const std::string& filename) = 0;

    bool loadFromSLM(const std::string& filename);

    void loadModelCallback();
    void loadTextures(); // called in the main thread.
    void setLoadState(U32 state);

    void stretch_extents(const LLModel* model, const LLMatrix4& mat);

    S32 mNumOfFetchingTextures; // updated in the main thread
    bool areTexturesReady() { return !mNumOfFetchingTextures; } // called in the main thread.

    bool verifyCount( int expected, int result );

    //Determines the viability of an asset to be used as an avatar rig (w or w/o joint upload caps)
    void critiqueRigForUploadApplicability( const std::vector<std::string> &jointListFromAsset );

    //Determines if a rig is a legacy from the joint list
    U32 determineRigLegacyFlags( const std::vector<std::string> &jointListFromAsset );

    //Determines if a rig is suitable for upload
    bool isRigSuitableForJointPositionUpload( const std::vector<std::string> &jointListFromAsset );

    const bool isRigValidForJointPositionUpload( void ) const { return mRigValidJointUpload; }
    void setRigValidForJointPositionUpload( bool rigValid ) { mRigValidJointUpload = rigValid; }

    const bool isLegacyRigValid(void) const { return mLegacyRigFlags == 0; }
    U32 getLegacyRigFlags() const { return mLegacyRigFlags; }
    void setLegacyRigFlags( U32 rigFlags ) { mLegacyRigFlags = rigFlags; }

    //-----------------------------------------------------------------------------
    // isNodeAJoint()
    //-----------------------------------------------------------------------------
    bool isNodeAJoint(const char* name)
    {
        return name != NULL && mJointMap.find(name) != mJointMap.end();
    }

    const LLSD logOut() const { return mWarningsArray; }
    void clearLog() { mWarningsArray.clear(); }

protected:

    LLModelLoader::load_callback_t      mLoadCallback;
    LLModelLoader::joint_lookup_func_t  mJointLookupFunc;
    LLModelLoader::texture_load_func_t  mTextureLoadFunc;
    LLModelLoader::state_callback_t     mStateCallback;
    void*                               mOpaqueData;

    bool        mRigValidJointUpload;
    U32         mLegacyRigFlags;

    bool        mNoNormalize;
    bool        mNoOptimize;

    JointTransformMap   mJointTransformMap;

    LLSD mWarningsArray; // preview floater will pull logs from here

    static std::list<LLModelLoader*> sActiveLoaderList;
    static bool isAlive(LLModelLoader* loader);
};

#endif  // LL_LLMODELLOADER_H