vrshoot

annotate libs/assimp/MaterialSystem.cpp @ 0:b2f14e535253

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 01 Feb 2014 19:58:19 +0200
parents
children
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*>(&copy.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