summaryrefslogtreecommitdiff
path: root/indra/llprimitive/llmodelloader.h
blob: 6dac0d5a34464a12e7ea4b0e593dc6af8dd467aa (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
/**
 * @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"

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

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

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,
		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
	} 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;	
	JointSet&			mJointsFromNode;

	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&						jointMap,
		JointSet&									jointsFromNodes);
	virtual ~LLModelLoader() ;

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

	virtual void run();
	
	// 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);

	

	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 );
	void critiqueJointToNodeMappingFromScene( void  );

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

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

	void setRigWithSceneParity( bool state ) { mRigParityWithScene = state; }
	const bool getRigWithSceneParity( void ) const { return mRigParityWithScene; }

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

	const bool isLegacyRigValid( void ) const { return mLegacyRigValid; }
	void setLegacyRigValid( bool rigValid ) { mLegacyRigValid = rigValid; }		

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

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		mRigParityWithScene;
	bool		mRigValidJointUpload;
	bool		mLegacyRigValid;

	bool		mNoNormalize;
	bool		mNoOptimize;

	JointSet				mMasterJointList;
	JointSet				mMasterLegacyJointList;
	JointTransformMap	mJointTransformMap;

	static std::list<LLModelLoader*> sActiveLoaderList;
	static bool isAlive(LLModelLoader* loader) ;
};
class LLMatrix4a;
void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4a& max, BOOL& first_transform);
void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3& max, BOOL& first_transform);

#endif  // LL_LLMODELLOADER_H