rev |
line source |
nuclear@0
|
1 /*
|
nuclear@0
|
2 Open Asset Import Library (assimp)
|
nuclear@0
|
3 ----------------------------------------------------------------------
|
nuclear@0
|
4
|
nuclear@0
|
5 Copyright (c) 2006-2012, assimp team
|
nuclear@0
|
6 All rights reserved.
|
nuclear@0
|
7
|
nuclear@0
|
8 Redistribution and use of this software in source and binary forms,
|
nuclear@0
|
9 with or without modification, are permitted provided that the
|
nuclear@0
|
10 following conditions are met:
|
nuclear@0
|
11
|
nuclear@0
|
12 * Redistributions of source code must retain the above
|
nuclear@0
|
13 copyright notice, this list of conditions and the
|
nuclear@0
|
14 following disclaimer.
|
nuclear@0
|
15
|
nuclear@0
|
16 * Redistributions in binary form must reproduce the above
|
nuclear@0
|
17 copyright notice, this list of conditions and the
|
nuclear@0
|
18 following disclaimer in the documentation and/or other
|
nuclear@0
|
19 materials provided with the distribution.
|
nuclear@0
|
20
|
nuclear@0
|
21 * Neither the name of the assimp team, nor the names of its
|
nuclear@0
|
22 contributors may be used to endorse or promote products
|
nuclear@0
|
23 derived from this software without specific prior
|
nuclear@0
|
24 written permission of the assimp team.
|
nuclear@0
|
25
|
nuclear@0
|
26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
nuclear@0
|
27 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
nuclear@0
|
28 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
nuclear@0
|
29 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
nuclear@0
|
30 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
nuclear@0
|
31 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
nuclear@0
|
32 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
nuclear@0
|
33 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
nuclear@0
|
34 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
nuclear@0
|
35 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
nuclear@0
|
36 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
nuclear@0
|
37
|
nuclear@0
|
38 ----------------------------------------------------------------------
|
nuclear@0
|
39 */
|
nuclear@0
|
40
|
nuclear@0
|
41 /** @file MaterialSystem.cpp
|
nuclear@0
|
42 * @brief Implementation of the material system of the library
|
nuclear@0
|
43 */
|
nuclear@0
|
44
|
nuclear@0
|
45 #include "AssimpPCH.h"
|
nuclear@0
|
46
|
nuclear@0
|
47 #include "Hash.h"
|
nuclear@0
|
48 #include "fast_atof.h"
|
nuclear@0
|
49 #include "ParsingUtils.h"
|
nuclear@0
|
50 #include "MaterialSystem.h"
|
nuclear@0
|
51
|
nuclear@0
|
52 using namespace Assimp;
|
nuclear@0
|
53
|
nuclear@0
|
54 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
55 // Get a specific property from a material
|
nuclear@0
|
56 aiReturn aiGetMaterialProperty(const aiMaterial* pMat,
|
nuclear@0
|
57 const char* pKey,
|
nuclear@0
|
58 unsigned int type,
|
nuclear@0
|
59 unsigned int index,
|
nuclear@0
|
60 const aiMaterialProperty** pPropOut)
|
nuclear@0
|
61 {
|
nuclear@0
|
62 ai_assert (pMat != NULL);
|
nuclear@0
|
63 ai_assert (pKey != NULL);
|
nuclear@0
|
64 ai_assert (pPropOut != NULL);
|
nuclear@0
|
65
|
nuclear@0
|
66 /* Just search for a property with exactly this name ..
|
nuclear@0
|
67 * could be improved by hashing, but it's possibly
|
nuclear@0
|
68 * no worth the effort (we're bound to C structures,
|
nuclear@0
|
69 * thus std::map or derivates are not applicable. */
|
nuclear@0
|
70 for (unsigned int i = 0; i < pMat->mNumProperties;++i) {
|
nuclear@0
|
71 aiMaterialProperty* prop = pMat->mProperties[i];
|
nuclear@0
|
72
|
nuclear@0
|
73 if (prop /* just for safety ... */
|
nuclear@0
|
74 && 0 == strcmp( prop->mKey.data, pKey )
|
nuclear@0
|
75 && (UINT_MAX == type || prop->mSemantic == type) /* UINT_MAX is a wildcard, but this is undocumented :-) */
|
nuclear@0
|
76 && (UINT_MAX == index || prop->mIndex == index))
|
nuclear@0
|
77 {
|
nuclear@0
|
78 *pPropOut = pMat->mProperties[i];
|
nuclear@0
|
79 return AI_SUCCESS;
|
nuclear@0
|
80 }
|
nuclear@0
|
81 }
|
nuclear@0
|
82 *pPropOut = NULL;
|
nuclear@0
|
83 return AI_FAILURE;
|
nuclear@0
|
84 }
|
nuclear@0
|
85
|
nuclear@0
|
86 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
87 // Get an array of floating-point values from the material.
|
nuclear@0
|
88 aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat,
|
nuclear@0
|
89 const char* pKey,
|
nuclear@0
|
90 unsigned int type,
|
nuclear@0
|
91 unsigned int index,
|
nuclear@0
|
92 float* pOut,
|
nuclear@0
|
93 unsigned int* pMax)
|
nuclear@0
|
94 {
|
nuclear@0
|
95 ai_assert (pOut != NULL);
|
nuclear@0
|
96 ai_assert (pMat != NULL);
|
nuclear@0
|
97
|
nuclear@0
|
98 const aiMaterialProperty* prop;
|
nuclear@0
|
99 aiGetMaterialProperty(pMat,pKey,type,index, (const aiMaterialProperty**) &prop);
|
nuclear@0
|
100 if (!prop) {
|
nuclear@0
|
101 return AI_FAILURE;
|
nuclear@0
|
102 }
|
nuclear@0
|
103
|
nuclear@0
|
104 // data is given in floats, simply copy it
|
nuclear@0
|
105 unsigned int iWrite;
|
nuclear@0
|
106 if( aiPTI_Float == prop->mType || aiPTI_Buffer == prop->mType) {
|
nuclear@0
|
107 iWrite = prop->mDataLength / sizeof(float);
|
nuclear@0
|
108 if (pMax) {
|
nuclear@0
|
109 iWrite = std::min(*pMax,iWrite); ;
|
nuclear@0
|
110 }
|
nuclear@0
|
111 for (unsigned int a = 0; a < iWrite;++a) {
|
nuclear@0
|
112 pOut[a] = static_cast<float> ( reinterpret_cast<float*>(prop->mData)[a] );
|
nuclear@0
|
113 }
|
nuclear@0
|
114 if (pMax) {
|
nuclear@0
|
115 *pMax = iWrite;
|
nuclear@0
|
116 }
|
nuclear@0
|
117 }
|
nuclear@0
|
118 // data is given in ints, convert to float
|
nuclear@0
|
119 else if( aiPTI_Integer == prop->mType) {
|
nuclear@0
|
120 iWrite = prop->mDataLength / sizeof(int32_t);
|
nuclear@0
|
121 if (pMax) {
|
nuclear@0
|
122 iWrite = std::min(*pMax,iWrite); ;
|
nuclear@0
|
123 }
|
nuclear@0
|
124 for (unsigned int a = 0; a < iWrite;++a) {
|
nuclear@0
|
125 pOut[a] = static_cast<float> ( reinterpret_cast<int32_t*>(prop->mData)[a] );
|
nuclear@0
|
126 }
|
nuclear@0
|
127 if (pMax) {
|
nuclear@0
|
128 *pMax = iWrite;
|
nuclear@0
|
129 }
|
nuclear@0
|
130 }
|
nuclear@0
|
131 // a string ... read floats separated by spaces
|
nuclear@0
|
132 else {
|
nuclear@0
|
133 if (pMax) {
|
nuclear@0
|
134 iWrite = *pMax;
|
nuclear@0
|
135 }
|
nuclear@0
|
136 // strings are zero-terminated with a 32 bit length prefix, so this is safe
|
nuclear@0
|
137 const char* cur = prop->mData+4;
|
nuclear@0
|
138 ai_assert(prop->mDataLength>=5 && !prop->mData[prop->mDataLength-1]);
|
nuclear@0
|
139 for (unsigned int a = 0; ;++a) {
|
nuclear@0
|
140 cur = fast_atoreal_move<float>(cur,pOut[a]);
|
nuclear@0
|
141 if(a==iWrite-1) {
|
nuclear@0
|
142 break;
|
nuclear@0
|
143 }
|
nuclear@0
|
144 if(!IsSpace(*cur)) {
|
nuclear@0
|
145 DefaultLogger::get()->error("Material property" + std::string(pKey) +
|
nuclear@0
|
146 " is a string; failed to parse a float array out of it.");
|
nuclear@0
|
147 return AI_FAILURE;
|
nuclear@0
|
148 }
|
nuclear@0
|
149 }
|
nuclear@0
|
150
|
nuclear@0
|
151 if (pMax) {
|
nuclear@0
|
152 *pMax = iWrite;
|
nuclear@0
|
153 }
|
nuclear@0
|
154 }
|
nuclear@0
|
155 return AI_SUCCESS;
|
nuclear@0
|
156
|
nuclear@0
|
157 }
|
nuclear@0
|
158
|
nuclear@0
|
159 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
160 // Get an array if integers from the material
|
nuclear@0
|
161 aiReturn aiGetMaterialIntegerArray(const aiMaterial* pMat,
|
nuclear@0
|
162 const char* pKey,
|
nuclear@0
|
163 unsigned int type,
|
nuclear@0
|
164 unsigned int index,
|
nuclear@0
|
165 int* pOut,
|
nuclear@0
|
166 unsigned int* pMax)
|
nuclear@0
|
167 {
|
nuclear@0
|
168 ai_assert (pOut != NULL);
|
nuclear@0
|
169 ai_assert (pMat != NULL);
|
nuclear@0
|
170
|
nuclear@0
|
171 const aiMaterialProperty* prop;
|
nuclear@0
|
172 aiGetMaterialProperty(pMat,pKey,type,index,(const aiMaterialProperty**) &prop);
|
nuclear@0
|
173 if (!prop) {
|
nuclear@0
|
174 return AI_FAILURE;
|
nuclear@0
|
175 }
|
nuclear@0
|
176
|
nuclear@0
|
177 // data is given in ints, simply copy it
|
nuclear@0
|
178 unsigned int iWrite;
|
nuclear@0
|
179 if( aiPTI_Integer == prop->mType || aiPTI_Buffer == prop->mType) {
|
nuclear@0
|
180 iWrite = prop->mDataLength / sizeof(int32_t);
|
nuclear@0
|
181 if (pMax) {
|
nuclear@0
|
182 iWrite = std::min(*pMax,iWrite); ;
|
nuclear@0
|
183 }
|
nuclear@0
|
184 for (unsigned int a = 0; a < iWrite;++a) {
|
nuclear@0
|
185 pOut[a] = static_cast<int>(reinterpret_cast<int32_t*>(prop->mData)[a]);
|
nuclear@0
|
186 }
|
nuclear@0
|
187 if (pMax) {
|
nuclear@0
|
188 *pMax = iWrite;
|
nuclear@0
|
189 }
|
nuclear@0
|
190 }
|
nuclear@0
|
191 // data is given in floats convert to int
|
nuclear@0
|
192 else if( aiPTI_Float == prop->mType) {
|
nuclear@0
|
193 iWrite = prop->mDataLength / sizeof(float);
|
nuclear@0
|
194 if (pMax) {
|
nuclear@0
|
195 iWrite = std::min(*pMax,iWrite); ;
|
nuclear@0
|
196 }
|
nuclear@0
|
197 for (unsigned int a = 0; a < iWrite;++a) {
|
nuclear@0
|
198 pOut[a] = static_cast<int>(reinterpret_cast<float*>(prop->mData)[a]);
|
nuclear@0
|
199 }
|
nuclear@0
|
200 if (pMax) {
|
nuclear@0
|
201 *pMax = iWrite;
|
nuclear@0
|
202 }
|
nuclear@0
|
203 }
|
nuclear@0
|
204 // it is a string ... no way to read something out of this
|
nuclear@0
|
205 else {
|
nuclear@0
|
206 if (pMax) {
|
nuclear@0
|
207 iWrite = *pMax;
|
nuclear@0
|
208 }
|
nuclear@0
|
209 // strings are zero-terminated with a 32 bit length prefix, so this is safe
|
nuclear@0
|
210 const char* cur = prop->mData+4;
|
nuclear@0
|
211 ai_assert(prop->mDataLength>=5 && !prop->mData[prop->mDataLength-1]);
|
nuclear@0
|
212 for (unsigned int a = 0; ;++a) {
|
nuclear@0
|
213 pOut[a] = strtol10(cur,&cur);
|
nuclear@0
|
214 if(a==iWrite-1) {
|
nuclear@0
|
215 break;
|
nuclear@0
|
216 }
|
nuclear@0
|
217 if(!IsSpace(*cur)) {
|
nuclear@0
|
218 DefaultLogger::get()->error("Material property" + std::string(pKey) +
|
nuclear@0
|
219 " is a string; failed to parse an integer array out of it.");
|
nuclear@0
|
220 return AI_FAILURE;
|
nuclear@0
|
221 }
|
nuclear@0
|
222 }
|
nuclear@0
|
223
|
nuclear@0
|
224 if (pMax) {
|
nuclear@0
|
225 *pMax = iWrite;
|
nuclear@0
|
226 }
|
nuclear@0
|
227 }
|
nuclear@0
|
228 return AI_SUCCESS;
|
nuclear@0
|
229 }
|
nuclear@0
|
230
|
nuclear@0
|
231 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
232 // Get a color (3 or 4 floats) from the material
|
nuclear@0
|
233 aiReturn aiGetMaterialColor(const aiMaterial* pMat,
|
nuclear@0
|
234 const char* pKey,
|
nuclear@0
|
235 unsigned int type,
|
nuclear@0
|
236 unsigned int index,
|
nuclear@0
|
237 aiColor4D* pOut)
|
nuclear@0
|
238 {
|
nuclear@0
|
239 unsigned int iMax = 4;
|
nuclear@0
|
240 const aiReturn eRet = aiGetMaterialFloatArray(pMat,pKey,type,index,(float*)pOut,&iMax);
|
nuclear@0
|
241
|
nuclear@0
|
242 // if no alpha channel is defined: set it to 1.0
|
nuclear@0
|
243 if (3 == iMax) {
|
nuclear@0
|
244 pOut->a = 1.0f;
|
nuclear@0
|
245 }
|
nuclear@0
|
246
|
nuclear@0
|
247 return eRet;
|
nuclear@0
|
248 }
|
nuclear@0
|
249
|
nuclear@0
|
250 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
251 // Get a string from the material
|
nuclear@0
|
252 aiReturn aiGetMaterialString(const aiMaterial* pMat,
|
nuclear@0
|
253 const char* pKey,
|
nuclear@0
|
254 unsigned int type,
|
nuclear@0
|
255 unsigned int index,
|
nuclear@0
|
256 aiString* pOut)
|
nuclear@0
|
257 {
|
nuclear@0
|
258 ai_assert (pOut != NULL);
|
nuclear@0
|
259
|
nuclear@0
|
260 const aiMaterialProperty* prop;
|
nuclear@0
|
261 aiGetMaterialProperty(pMat,pKey,type,index,(const aiMaterialProperty**)&prop);
|
nuclear@0
|
262 if (!prop) {
|
nuclear@0
|
263 return AI_FAILURE;
|
nuclear@0
|
264 }
|
nuclear@0
|
265
|
nuclear@0
|
266 if( aiPTI_String == prop->mType) {
|
nuclear@0
|
267 ai_assert(prop->mDataLength>=5);
|
nuclear@0
|
268
|
nuclear@0
|
269 // The string is stored as 32 but length prefix followed by zero-terminated UTF8 data
|
nuclear@0
|
270 pOut->length = static_cast<unsigned int>(*reinterpret_cast<uint32_t*>(prop->mData));
|
nuclear@0
|
271
|
nuclear@0
|
272 ai_assert(pOut->length+1+4==prop->mDataLength && !prop->mData[prop->mDataLength-1]);
|
nuclear@0
|
273 memcpy(pOut->data,prop->mData+4,pOut->length+1);
|
nuclear@0
|
274 }
|
nuclear@0
|
275 else {
|
nuclear@0
|
276 // TODO - implement lexical cast as well
|
nuclear@0
|
277 DefaultLogger::get()->error("Material property" + std::string(pKey) +
|
nuclear@0
|
278 " was found, but is no string" );
|
nuclear@0
|
279 return AI_FAILURE;
|
nuclear@0
|
280 }
|
nuclear@0
|
281 return AI_SUCCESS;
|
nuclear@0
|
282 }
|
nuclear@0
|
283
|
nuclear@0
|
284 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
285 // Get the number of textures on a particular texture stack
|
nuclear@0
|
286 ASSIMP_API unsigned int aiGetMaterialTextureCount(const C_STRUCT aiMaterial* pMat,
|
nuclear@0
|
287 C_ENUM aiTextureType type)
|
nuclear@0
|
288 {
|
nuclear@0
|
289 ai_assert (pMat != NULL);
|
nuclear@0
|
290
|
nuclear@0
|
291 /* Textures are always stored with ascending indices (ValidateDS provides a check, so we don't need to do it again) */
|
nuclear@0
|
292 unsigned int max = 0;
|
nuclear@0
|
293 for (unsigned int i = 0; i < pMat->mNumProperties;++i) {
|
nuclear@0
|
294 aiMaterialProperty* prop = pMat->mProperties[i];
|
nuclear@0
|
295
|
nuclear@0
|
296 if (prop /* just a sanity check ... */
|
nuclear@0
|
297 && 0 == strcmp( prop->mKey.data, _AI_MATKEY_TEXTURE_BASE )
|
nuclear@0
|
298 && prop->mSemantic == type) {
|
nuclear@0
|
299
|
nuclear@0
|
300 max = std::max(max,prop->mIndex+1);
|
nuclear@0
|
301 }
|
nuclear@0
|
302 }
|
nuclear@0
|
303 return max;
|
nuclear@0
|
304 }
|
nuclear@0
|
305
|
nuclear@0
|
306 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
307 aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* mat,
|
nuclear@0
|
308 aiTextureType type,
|
nuclear@0
|
309 unsigned int index,
|
nuclear@0
|
310 C_STRUCT aiString* path,
|
nuclear@0
|
311 aiTextureMapping* _mapping /*= NULL*/,
|
nuclear@0
|
312 unsigned int* uvindex /*= NULL*/,
|
nuclear@0
|
313 float* blend /*= NULL*/,
|
nuclear@0
|
314 aiTextureOp* op /*= NULL*/,
|
nuclear@0
|
315 aiTextureMapMode* mapmode /*= NULL*/,
|
nuclear@0
|
316 unsigned int* flags /*= NULL*/
|
nuclear@0
|
317 )
|
nuclear@0
|
318 {
|
nuclear@0
|
319 ai_assert(NULL != mat && NULL != path);
|
nuclear@0
|
320
|
nuclear@0
|
321 // Get the path to the texture
|
nuclear@0
|
322 if (AI_SUCCESS != aiGetMaterialString(mat,AI_MATKEY_TEXTURE(type,index),path)) {
|
nuclear@0
|
323 return AI_FAILURE;
|
nuclear@0
|
324 }
|
nuclear@0
|
325 // Determine mapping type
|
nuclear@0
|
326 aiTextureMapping mapping = aiTextureMapping_UV;
|
nuclear@0
|
327 aiGetMaterialInteger(mat,AI_MATKEY_MAPPING(type,index),(int*)&mapping);
|
nuclear@0
|
328 if (_mapping)
|
nuclear@0
|
329 *_mapping = mapping;
|
nuclear@0
|
330
|
nuclear@0
|
331 // Get UV index
|
nuclear@0
|
332 if (aiTextureMapping_UV == mapping && uvindex) {
|
nuclear@0
|
333 aiGetMaterialInteger(mat,AI_MATKEY_UVWSRC(type,index),(int*)uvindex);
|
nuclear@0
|
334 }
|
nuclear@0
|
335 // Get blend factor
|
nuclear@0
|
336 if (blend) {
|
nuclear@0
|
337 aiGetMaterialFloat(mat,AI_MATKEY_TEXBLEND(type,index),blend);
|
nuclear@0
|
338 }
|
nuclear@0
|
339 // Get texture operation
|
nuclear@0
|
340 if (op){
|
nuclear@0
|
341 aiGetMaterialInteger(mat,AI_MATKEY_TEXOP(type,index),(int*)op);
|
nuclear@0
|
342 }
|
nuclear@0
|
343 // Get texture mapping modes
|
nuclear@0
|
344 if (mapmode) {
|
nuclear@0
|
345 aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_U(type,index),(int*)&mapmode[0]);
|
nuclear@0
|
346 aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_V(type,index),(int*)&mapmode[1]);
|
nuclear@0
|
347 }
|
nuclear@0
|
348 // Get texture flags
|
nuclear@0
|
349 if (flags){
|
nuclear@0
|
350 aiGetMaterialInteger(mat,AI_MATKEY_TEXFLAGS(type,index),(int*)flags);
|
nuclear@0
|
351 }
|
nuclear@0
|
352 return AI_SUCCESS;
|
nuclear@0
|
353 }
|
nuclear@0
|
354
|
nuclear@0
|
355 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
356 // Construction. Actually the one and only way to get an aiMaterial instance
|
nuclear@0
|
357 aiMaterial::aiMaterial()
|
nuclear@0
|
358 {
|
nuclear@0
|
359 // Allocate 5 entries by default
|
nuclear@0
|
360 mNumProperties = 0;
|
nuclear@0
|
361 mNumAllocated = 5;
|
nuclear@0
|
362 mProperties = new aiMaterialProperty*[5];
|
nuclear@0
|
363 }
|
nuclear@0
|
364
|
nuclear@0
|
365 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
366 aiMaterial::~aiMaterial()
|
nuclear@0
|
367 {
|
nuclear@0
|
368 Clear();
|
nuclear@0
|
369
|
nuclear@0
|
370 delete[] mProperties;
|
nuclear@0
|
371 }
|
nuclear@0
|
372
|
nuclear@0
|
373 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
374 void aiMaterial::Clear()
|
nuclear@0
|
375 {
|
nuclear@0
|
376 for (unsigned int i = 0; i < mNumProperties;++i) {
|
nuclear@0
|
377 // delete this entry
|
nuclear@0
|
378 delete mProperties[i];
|
nuclear@0
|
379 AI_DEBUG_INVALIDATE_PTR(mProperties[i]);
|
nuclear@0
|
380 }
|
nuclear@0
|
381 mNumProperties = 0;
|
nuclear@0
|
382
|
nuclear@0
|
383 // The array remains allocated, we just invalidated its contents
|
nuclear@0
|
384 }
|
nuclear@0
|
385
|
nuclear@0
|
386 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
387 aiReturn aiMaterial::RemoveProperty (const char* pKey,unsigned int type,
|
nuclear@0
|
388 unsigned int index
|
nuclear@0
|
389 )
|
nuclear@0
|
390 {
|
nuclear@0
|
391 ai_assert(NULL != pKey);
|
nuclear@0
|
392
|
nuclear@0
|
393 for (unsigned int i = 0; i < mNumProperties;++i) {
|
nuclear@0
|
394 aiMaterialProperty* prop = mProperties[i];
|
nuclear@0
|
395
|
nuclear@0
|
396 if (prop && !strcmp( prop->mKey.data, pKey ) &&
|
nuclear@0
|
397 prop->mSemantic == type && prop->mIndex == index)
|
nuclear@0
|
398 {
|
nuclear@0
|
399 // Delete this entry
|
nuclear@0
|
400 delete mProperties[i];
|
nuclear@0
|
401
|
nuclear@0
|
402 // collapse the array behind --.
|
nuclear@0
|
403 --mNumProperties;
|
nuclear@0
|
404 for (unsigned int a = i; a < mNumProperties;++a) {
|
nuclear@0
|
405 mProperties[a] = mProperties[a+1];
|
nuclear@0
|
406 }
|
nuclear@0
|
407 return AI_SUCCESS;
|
nuclear@0
|
408 }
|
nuclear@0
|
409 }
|
nuclear@0
|
410
|
nuclear@0
|
411 return AI_FAILURE;
|
nuclear@0
|
412 }
|
nuclear@0
|
413
|
nuclear@0
|
414 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
415 aiReturn aiMaterial::AddBinaryProperty (const void* pInput,
|
nuclear@0
|
416 unsigned int pSizeInBytes,
|
nuclear@0
|
417 const char* pKey,
|
nuclear@0
|
418 unsigned int type,
|
nuclear@0
|
419 unsigned int index,
|
nuclear@0
|
420 aiPropertyTypeInfo pType
|
nuclear@0
|
421 )
|
nuclear@0
|
422 {
|
nuclear@0
|
423 ai_assert (pInput != NULL);
|
nuclear@0
|
424 ai_assert (pKey != NULL);
|
nuclear@0
|
425 ai_assert (0 != pSizeInBytes);
|
nuclear@0
|
426
|
nuclear@0
|
427 // first search the list whether there is already an entry with this key
|
nuclear@0
|
428 unsigned int iOutIndex = UINT_MAX;
|
nuclear@0
|
429 for (unsigned int i = 0; i < mNumProperties;++i) {
|
nuclear@0
|
430 aiMaterialProperty* prop = mProperties[i];
|
nuclear@0
|
431
|
nuclear@0
|
432 if (prop /* just for safety */ && !strcmp( prop->mKey.data, pKey ) &&
|
nuclear@0
|
433 prop->mSemantic == type && prop->mIndex == index){
|
nuclear@0
|
434
|
nuclear@0
|
435 delete mProperties[i];
|
nuclear@0
|
436 iOutIndex = i;
|
nuclear@0
|
437 }
|
nuclear@0
|
438 }
|
nuclear@0
|
439
|
nuclear@0
|
440 // Allocate a new material property
|
nuclear@0
|
441 aiMaterialProperty* pcNew = new aiMaterialProperty();
|
nuclear@0
|
442
|
nuclear@0
|
443 // .. and fill it
|
nuclear@0
|
444 pcNew->mType = pType;
|
nuclear@0
|
445 pcNew->mSemantic = type;
|
nuclear@0
|
446 pcNew->mIndex = index;
|
nuclear@0
|
447
|
nuclear@0
|
448 pcNew->mDataLength = pSizeInBytes;
|
nuclear@0
|
449 pcNew->mData = new char[pSizeInBytes];
|
nuclear@0
|
450 memcpy (pcNew->mData,pInput,pSizeInBytes);
|
nuclear@0
|
451
|
nuclear@0
|
452 pcNew->mKey.length = ::strlen(pKey);
|
nuclear@0
|
453 ai_assert ( MAXLEN > pcNew->mKey.length);
|
nuclear@0
|
454 strcpy( pcNew->mKey.data, pKey );
|
nuclear@0
|
455
|
nuclear@0
|
456 if (UINT_MAX != iOutIndex) {
|
nuclear@0
|
457 mProperties[iOutIndex] = pcNew;
|
nuclear@0
|
458 return AI_SUCCESS;
|
nuclear@0
|
459 }
|
nuclear@0
|
460
|
nuclear@0
|
461 // resize the array ... double the storage allocated
|
nuclear@0
|
462 if (mNumProperties == mNumAllocated) {
|
nuclear@0
|
463 const unsigned int iOld = mNumAllocated;
|
nuclear@0
|
464 mNumAllocated *= 2;
|
nuclear@0
|
465
|
nuclear@0
|
466 aiMaterialProperty** ppTemp;
|
nuclear@0
|
467 try {
|
nuclear@0
|
468 ppTemp = new aiMaterialProperty*[mNumAllocated];
|
nuclear@0
|
469 } catch (std::bad_alloc&) {
|
nuclear@0
|
470 return AI_OUTOFMEMORY;
|
nuclear@0
|
471 }
|
nuclear@0
|
472
|
nuclear@0
|
473 // just copy all items over; then replace the old array
|
nuclear@0
|
474 memcpy (ppTemp,mProperties,iOld * sizeof(void*));
|
nuclear@0
|
475
|
nuclear@0
|
476 delete[] mProperties;
|
nuclear@0
|
477 mProperties = ppTemp;
|
nuclear@0
|
478 }
|
nuclear@0
|
479 // push back ...
|
nuclear@0
|
480 mProperties[mNumProperties++] = pcNew;
|
nuclear@0
|
481 return AI_SUCCESS;
|
nuclear@0
|
482 }
|
nuclear@0
|
483
|
nuclear@0
|
484 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
485 aiReturn aiMaterial::AddProperty (const aiString* pInput,
|
nuclear@0
|
486 const char* pKey,
|
nuclear@0
|
487 unsigned int type,
|
nuclear@0
|
488 unsigned int index)
|
nuclear@0
|
489 {
|
nuclear@0
|
490 // We don't want to add the whole buffer .. write a 32 bit length
|
nuclear@0
|
491 // prefix followed by the zero-terminated UTF8 string.
|
nuclear@0
|
492 // (HACK) I don't want to break the ABI now, but we definitely
|
nuclear@0
|
493 // ought to change aiString::mLength to uint32_t one day.
|
nuclear@0
|
494 if (sizeof(size_t) == 8) {
|
nuclear@0
|
495 aiString copy = *pInput;
|
nuclear@0
|
496 uint32_t* s = reinterpret_cast<uint32_t*>(©.length);
|
nuclear@0
|
497 s[1] = static_cast<uint32_t>(pInput->length);
|
nuclear@0
|
498
|
nuclear@0
|
499 return AddBinaryProperty(s+1,
|
nuclear@0
|
500 pInput->length+1+4,
|
nuclear@0
|
501 pKey,
|
nuclear@0
|
502 type,
|
nuclear@0
|
503 index,
|
nuclear@0
|
504 aiPTI_String);
|
nuclear@0
|
505 }
|
nuclear@0
|
506 ai_assert(sizeof(size_t)==4);
|
nuclear@0
|
507 return AddBinaryProperty(pInput,
|
nuclear@0
|
508 pInput->length+1+4,
|
nuclear@0
|
509 pKey,
|
nuclear@0
|
510 type,
|
nuclear@0
|
511 index,
|
nuclear@0
|
512 aiPTI_String);
|
nuclear@0
|
513 }
|
nuclear@0
|
514
|
nuclear@0
|
515 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
516 uint32_t Assimp :: ComputeMaterialHash(const aiMaterial* mat, bool includeMatName /*= false*/)
|
nuclear@0
|
517 {
|
nuclear@0
|
518 uint32_t hash = 1503; // magic start value, chosen to be my birthday :-)
|
nuclear@0
|
519 for (unsigned int i = 0; i < mat->mNumProperties;++i) {
|
nuclear@0
|
520 aiMaterialProperty* prop;
|
nuclear@0
|
521
|
nuclear@0
|
522 // Exclude all properties whose first character is '?' from the hash
|
nuclear@0
|
523 // See doc for aiMaterialProperty.
|
nuclear@0
|
524 if ((prop = mat->mProperties[i]) && (includeMatName || prop->mKey.data[0] != '?')) {
|
nuclear@0
|
525
|
nuclear@0
|
526 hash = SuperFastHash(prop->mKey.data,(unsigned int)prop->mKey.length,hash);
|
nuclear@0
|
527 hash = SuperFastHash(prop->mData,prop->mDataLength,hash);
|
nuclear@0
|
528
|
nuclear@0
|
529 // Combine the semantic and the index with the hash
|
nuclear@0
|
530 hash = SuperFastHash((const char*)&prop->mSemantic,sizeof(unsigned int),hash);
|
nuclear@0
|
531 hash = SuperFastHash((const char*)&prop->mIndex,sizeof(unsigned int),hash);
|
nuclear@0
|
532 }
|
nuclear@0
|
533 }
|
nuclear@0
|
534 return hash;
|
nuclear@0
|
535 }
|
nuclear@0
|
536
|
nuclear@0
|
537 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
538 void aiMaterial::CopyPropertyList(aiMaterial* pcDest,
|
nuclear@0
|
539 const aiMaterial* pcSrc
|
nuclear@0
|
540 )
|
nuclear@0
|
541 {
|
nuclear@0
|
542 ai_assert(NULL != pcDest);
|
nuclear@0
|
543 ai_assert(NULL != pcSrc);
|
nuclear@0
|
544
|
nuclear@0
|
545 unsigned int iOldNum = pcDest->mNumProperties;
|
nuclear@0
|
546 pcDest->mNumAllocated += pcSrc->mNumAllocated;
|
nuclear@0
|
547 pcDest->mNumProperties += pcSrc->mNumProperties;
|
nuclear@0
|
548
|
nuclear@0
|
549 aiMaterialProperty** pcOld = pcDest->mProperties;
|
nuclear@0
|
550 pcDest->mProperties = new aiMaterialProperty*[pcDest->mNumAllocated];
|
nuclear@0
|
551
|
nuclear@0
|
552 if (iOldNum && pcOld) {
|
nuclear@0
|
553 for (unsigned int i = 0; i < iOldNum;++i) {
|
nuclear@0
|
554 pcDest->mProperties[i] = pcOld[i];
|
nuclear@0
|
555 }
|
nuclear@0
|
556
|
nuclear@0
|
557 delete[] pcOld;
|
nuclear@0
|
558 }
|
nuclear@0
|
559 for (unsigned int i = iOldNum; i< pcDest->mNumProperties;++i) {
|
nuclear@0
|
560 aiMaterialProperty* propSrc = pcSrc->mProperties[i];
|
nuclear@0
|
561
|
nuclear@0
|
562 // search whether we have already a property with this name -> if yes, overwrite it
|
nuclear@0
|
563 aiMaterialProperty* prop;
|
nuclear@0
|
564 for (unsigned int q = 0; q < iOldNum;++q) {
|
nuclear@0
|
565 prop = pcDest->mProperties[q];
|
nuclear@0
|
566 if (prop /* just for safety */ && prop->mKey == propSrc->mKey && prop->mSemantic == propSrc->mSemantic
|
nuclear@0
|
567 && prop->mIndex == propSrc->mIndex) {
|
nuclear@0
|
568 delete prop;
|
nuclear@0
|
569
|
nuclear@0
|
570 // collapse the whole array ...
|
nuclear@0
|
571 memmove(&pcDest->mProperties[q],&pcDest->mProperties[q+1],i-q);
|
nuclear@0
|
572 i--;
|
nuclear@0
|
573 pcDest->mNumProperties--;
|
nuclear@0
|
574 }
|
nuclear@0
|
575 }
|
nuclear@0
|
576
|
nuclear@0
|
577 // Allocate the output property and copy the source property
|
nuclear@0
|
578 prop = pcDest->mProperties[i] = new aiMaterialProperty();
|
nuclear@0
|
579 prop->mKey = propSrc->mKey;
|
nuclear@0
|
580 prop->mDataLength = propSrc->mDataLength;
|
nuclear@0
|
581 prop->mType = propSrc->mType;
|
nuclear@0
|
582 prop->mSemantic = propSrc->mSemantic;
|
nuclear@0
|
583 prop->mIndex = propSrc->mIndex;
|
nuclear@0
|
584
|
nuclear@0
|
585 prop->mData = new char[propSrc->mDataLength];
|
nuclear@0
|
586 memcpy(prop->mData,propSrc->mData,prop->mDataLength);
|
nuclear@0
|
587 }
|
nuclear@0
|
588 return;
|
nuclear@0
|
589 }
|
nuclear@0
|
590
|