vrshoot
diff 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 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libs/assimp/MaterialSystem.cpp Sat Feb 01 19:58:19 2014 +0200 1.3 @@ -0,0 +1,590 @@ 1.4 +/* 1.5 +Open Asset Import Library (assimp) 1.6 +---------------------------------------------------------------------- 1.7 + 1.8 +Copyright (c) 2006-2012, assimp team 1.9 +All rights reserved. 1.10 + 1.11 +Redistribution and use of this software in source and binary forms, 1.12 +with or without modification, are permitted provided that the 1.13 +following conditions are met: 1.14 + 1.15 +* Redistributions of source code must retain the above 1.16 + copyright notice, this list of conditions and the 1.17 + following disclaimer. 1.18 + 1.19 +* Redistributions in binary form must reproduce the above 1.20 + copyright notice, this list of conditions and the 1.21 + following disclaimer in the documentation and/or other 1.22 + materials provided with the distribution. 1.23 + 1.24 +* Neither the name of the assimp team, nor the names of its 1.25 + contributors may be used to endorse or promote products 1.26 + derived from this software without specific prior 1.27 + written permission of the assimp team. 1.28 + 1.29 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.30 +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.31 +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.32 +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.33 +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.34 +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.35 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.36 +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.37 +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.38 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.39 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.40 + 1.41 +---------------------------------------------------------------------- 1.42 +*/ 1.43 + 1.44 +/** @file MaterialSystem.cpp 1.45 + * @brief Implementation of the material system of the library 1.46 + */ 1.47 + 1.48 +#include "AssimpPCH.h" 1.49 + 1.50 +#include "Hash.h" 1.51 +#include "fast_atof.h" 1.52 +#include "ParsingUtils.h" 1.53 +#include "MaterialSystem.h" 1.54 + 1.55 +using namespace Assimp; 1.56 + 1.57 +// ------------------------------------------------------------------------------------------------ 1.58 +// Get a specific property from a material 1.59 +aiReturn aiGetMaterialProperty(const aiMaterial* pMat, 1.60 + const char* pKey, 1.61 + unsigned int type, 1.62 + unsigned int index, 1.63 + const aiMaterialProperty** pPropOut) 1.64 +{ 1.65 + ai_assert (pMat != NULL); 1.66 + ai_assert (pKey != NULL); 1.67 + ai_assert (pPropOut != NULL); 1.68 + 1.69 + /* Just search for a property with exactly this name .. 1.70 + * could be improved by hashing, but it's possibly 1.71 + * no worth the effort (we're bound to C structures, 1.72 + * thus std::map or derivates are not applicable. */ 1.73 + for (unsigned int i = 0; i < pMat->mNumProperties;++i) { 1.74 + aiMaterialProperty* prop = pMat->mProperties[i]; 1.75 + 1.76 + if (prop /* just for safety ... */ 1.77 + && 0 == strcmp( prop->mKey.data, pKey ) 1.78 + && (UINT_MAX == type || prop->mSemantic == type) /* UINT_MAX is a wildcard, but this is undocumented :-) */ 1.79 + && (UINT_MAX == index || prop->mIndex == index)) 1.80 + { 1.81 + *pPropOut = pMat->mProperties[i]; 1.82 + return AI_SUCCESS; 1.83 + } 1.84 + } 1.85 + *pPropOut = NULL; 1.86 + return AI_FAILURE; 1.87 +} 1.88 + 1.89 +// ------------------------------------------------------------------------------------------------ 1.90 +// Get an array of floating-point values from the material. 1.91 +aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat, 1.92 + const char* pKey, 1.93 + unsigned int type, 1.94 + unsigned int index, 1.95 + float* pOut, 1.96 + unsigned int* pMax) 1.97 +{ 1.98 + ai_assert (pOut != NULL); 1.99 + ai_assert (pMat != NULL); 1.100 + 1.101 + const aiMaterialProperty* prop; 1.102 + aiGetMaterialProperty(pMat,pKey,type,index, (const aiMaterialProperty**) &prop); 1.103 + if (!prop) { 1.104 + return AI_FAILURE; 1.105 + } 1.106 + 1.107 + // data is given in floats, simply copy it 1.108 + unsigned int iWrite; 1.109 + if( aiPTI_Float == prop->mType || aiPTI_Buffer == prop->mType) { 1.110 + iWrite = prop->mDataLength / sizeof(float); 1.111 + if (pMax) { 1.112 + iWrite = std::min(*pMax,iWrite); ; 1.113 + } 1.114 + for (unsigned int a = 0; a < iWrite;++a) { 1.115 + pOut[a] = static_cast<float> ( reinterpret_cast<float*>(prop->mData)[a] ); 1.116 + } 1.117 + if (pMax) { 1.118 + *pMax = iWrite; 1.119 + } 1.120 + } 1.121 + // data is given in ints, convert to float 1.122 + else if( aiPTI_Integer == prop->mType) { 1.123 + iWrite = prop->mDataLength / sizeof(int32_t); 1.124 + if (pMax) { 1.125 + iWrite = std::min(*pMax,iWrite); ; 1.126 + } 1.127 + for (unsigned int a = 0; a < iWrite;++a) { 1.128 + pOut[a] = static_cast<float> ( reinterpret_cast<int32_t*>(prop->mData)[a] ); 1.129 + } 1.130 + if (pMax) { 1.131 + *pMax = iWrite; 1.132 + } 1.133 + } 1.134 + // a string ... read floats separated by spaces 1.135 + else { 1.136 + if (pMax) { 1.137 + iWrite = *pMax; 1.138 + } 1.139 + // strings are zero-terminated with a 32 bit length prefix, so this is safe 1.140 + const char* cur = prop->mData+4; 1.141 + ai_assert(prop->mDataLength>=5 && !prop->mData[prop->mDataLength-1]); 1.142 + for (unsigned int a = 0; ;++a) { 1.143 + cur = fast_atoreal_move<float>(cur,pOut[a]); 1.144 + if(a==iWrite-1) { 1.145 + break; 1.146 + } 1.147 + if(!IsSpace(*cur)) { 1.148 + DefaultLogger::get()->error("Material property" + std::string(pKey) + 1.149 + " is a string; failed to parse a float array out of it."); 1.150 + return AI_FAILURE; 1.151 + } 1.152 + } 1.153 + 1.154 + if (pMax) { 1.155 + *pMax = iWrite; 1.156 + } 1.157 + } 1.158 + return AI_SUCCESS; 1.159 + 1.160 +} 1.161 + 1.162 +// ------------------------------------------------------------------------------------------------ 1.163 +// Get an array if integers from the material 1.164 +aiReturn aiGetMaterialIntegerArray(const aiMaterial* pMat, 1.165 + const char* pKey, 1.166 + unsigned int type, 1.167 + unsigned int index, 1.168 + int* pOut, 1.169 + unsigned int* pMax) 1.170 +{ 1.171 + ai_assert (pOut != NULL); 1.172 + ai_assert (pMat != NULL); 1.173 + 1.174 + const aiMaterialProperty* prop; 1.175 + aiGetMaterialProperty(pMat,pKey,type,index,(const aiMaterialProperty**) &prop); 1.176 + if (!prop) { 1.177 + return AI_FAILURE; 1.178 + } 1.179 + 1.180 + // data is given in ints, simply copy it 1.181 + unsigned int iWrite; 1.182 + if( aiPTI_Integer == prop->mType || aiPTI_Buffer == prop->mType) { 1.183 + iWrite = prop->mDataLength / sizeof(int32_t); 1.184 + if (pMax) { 1.185 + iWrite = std::min(*pMax,iWrite); ; 1.186 + } 1.187 + for (unsigned int a = 0; a < iWrite;++a) { 1.188 + pOut[a] = static_cast<int>(reinterpret_cast<int32_t*>(prop->mData)[a]); 1.189 + } 1.190 + if (pMax) { 1.191 + *pMax = iWrite; 1.192 + } 1.193 + } 1.194 + // data is given in floats convert to int 1.195 + else if( aiPTI_Float == prop->mType) { 1.196 + iWrite = prop->mDataLength / sizeof(float); 1.197 + if (pMax) { 1.198 + iWrite = std::min(*pMax,iWrite); ; 1.199 + } 1.200 + for (unsigned int a = 0; a < iWrite;++a) { 1.201 + pOut[a] = static_cast<int>(reinterpret_cast<float*>(prop->mData)[a]); 1.202 + } 1.203 + if (pMax) { 1.204 + *pMax = iWrite; 1.205 + } 1.206 + } 1.207 + // it is a string ... no way to read something out of this 1.208 + else { 1.209 + if (pMax) { 1.210 + iWrite = *pMax; 1.211 + } 1.212 + // strings are zero-terminated with a 32 bit length prefix, so this is safe 1.213 + const char* cur = prop->mData+4; 1.214 + ai_assert(prop->mDataLength>=5 && !prop->mData[prop->mDataLength-1]); 1.215 + for (unsigned int a = 0; ;++a) { 1.216 + pOut[a] = strtol10(cur,&cur); 1.217 + if(a==iWrite-1) { 1.218 + break; 1.219 + } 1.220 + if(!IsSpace(*cur)) { 1.221 + DefaultLogger::get()->error("Material property" + std::string(pKey) + 1.222 + " is a string; failed to parse an integer array out of it."); 1.223 + return AI_FAILURE; 1.224 + } 1.225 + } 1.226 + 1.227 + if (pMax) { 1.228 + *pMax = iWrite; 1.229 + } 1.230 + } 1.231 + return AI_SUCCESS; 1.232 +} 1.233 + 1.234 +// ------------------------------------------------------------------------------------------------ 1.235 +// Get a color (3 or 4 floats) from the material 1.236 +aiReturn aiGetMaterialColor(const aiMaterial* pMat, 1.237 + const char* pKey, 1.238 + unsigned int type, 1.239 + unsigned int index, 1.240 + aiColor4D* pOut) 1.241 +{ 1.242 + unsigned int iMax = 4; 1.243 + const aiReturn eRet = aiGetMaterialFloatArray(pMat,pKey,type,index,(float*)pOut,&iMax); 1.244 + 1.245 + // if no alpha channel is defined: set it to 1.0 1.246 + if (3 == iMax) { 1.247 + pOut->a = 1.0f; 1.248 + } 1.249 + 1.250 + return eRet; 1.251 +} 1.252 + 1.253 +// ------------------------------------------------------------------------------------------------ 1.254 +// Get a string from the material 1.255 +aiReturn aiGetMaterialString(const aiMaterial* pMat, 1.256 + const char* pKey, 1.257 + unsigned int type, 1.258 + unsigned int index, 1.259 + aiString* pOut) 1.260 +{ 1.261 + ai_assert (pOut != NULL); 1.262 + 1.263 + const aiMaterialProperty* prop; 1.264 + aiGetMaterialProperty(pMat,pKey,type,index,(const aiMaterialProperty**)&prop); 1.265 + if (!prop) { 1.266 + return AI_FAILURE; 1.267 + } 1.268 + 1.269 + if( aiPTI_String == prop->mType) { 1.270 + ai_assert(prop->mDataLength>=5); 1.271 + 1.272 + // The string is stored as 32 but length prefix followed by zero-terminated UTF8 data 1.273 + pOut->length = static_cast<unsigned int>(*reinterpret_cast<uint32_t*>(prop->mData)); 1.274 + 1.275 + ai_assert(pOut->length+1+4==prop->mDataLength && !prop->mData[prop->mDataLength-1]); 1.276 + memcpy(pOut->data,prop->mData+4,pOut->length+1); 1.277 + } 1.278 + else { 1.279 + // TODO - implement lexical cast as well 1.280 + DefaultLogger::get()->error("Material property" + std::string(pKey) + 1.281 + " was found, but is no string" ); 1.282 + return AI_FAILURE; 1.283 + } 1.284 + return AI_SUCCESS; 1.285 +} 1.286 + 1.287 +// ------------------------------------------------------------------------------------------------ 1.288 +// Get the number of textures on a particular texture stack 1.289 +ASSIMP_API unsigned int aiGetMaterialTextureCount(const C_STRUCT aiMaterial* pMat, 1.290 + C_ENUM aiTextureType type) 1.291 +{ 1.292 + ai_assert (pMat != NULL); 1.293 + 1.294 + /* Textures are always stored with ascending indices (ValidateDS provides a check, so we don't need to do it again) */ 1.295 + unsigned int max = 0; 1.296 + for (unsigned int i = 0; i < pMat->mNumProperties;++i) { 1.297 + aiMaterialProperty* prop = pMat->mProperties[i]; 1.298 + 1.299 + if (prop /* just a sanity check ... */ 1.300 + && 0 == strcmp( prop->mKey.data, _AI_MATKEY_TEXTURE_BASE ) 1.301 + && prop->mSemantic == type) { 1.302 + 1.303 + max = std::max(max,prop->mIndex+1); 1.304 + } 1.305 + } 1.306 + return max; 1.307 +} 1.308 + 1.309 +// ------------------------------------------------------------------------------------------------ 1.310 +aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* mat, 1.311 + aiTextureType type, 1.312 + unsigned int index, 1.313 + C_STRUCT aiString* path, 1.314 + aiTextureMapping* _mapping /*= NULL*/, 1.315 + unsigned int* uvindex /*= NULL*/, 1.316 + float* blend /*= NULL*/, 1.317 + aiTextureOp* op /*= NULL*/, 1.318 + aiTextureMapMode* mapmode /*= NULL*/, 1.319 + unsigned int* flags /*= NULL*/ 1.320 + ) 1.321 +{ 1.322 + ai_assert(NULL != mat && NULL != path); 1.323 + 1.324 + // Get the path to the texture 1.325 + if (AI_SUCCESS != aiGetMaterialString(mat,AI_MATKEY_TEXTURE(type,index),path)) { 1.326 + return AI_FAILURE; 1.327 + } 1.328 + // Determine mapping type 1.329 + aiTextureMapping mapping = aiTextureMapping_UV; 1.330 + aiGetMaterialInteger(mat,AI_MATKEY_MAPPING(type,index),(int*)&mapping); 1.331 + if (_mapping) 1.332 + *_mapping = mapping; 1.333 + 1.334 + // Get UV index 1.335 + if (aiTextureMapping_UV == mapping && uvindex) { 1.336 + aiGetMaterialInteger(mat,AI_MATKEY_UVWSRC(type,index),(int*)uvindex); 1.337 + } 1.338 + // Get blend factor 1.339 + if (blend) { 1.340 + aiGetMaterialFloat(mat,AI_MATKEY_TEXBLEND(type,index),blend); 1.341 + } 1.342 + // Get texture operation 1.343 + if (op){ 1.344 + aiGetMaterialInteger(mat,AI_MATKEY_TEXOP(type,index),(int*)op); 1.345 + } 1.346 + // Get texture mapping modes 1.347 + if (mapmode) { 1.348 + aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_U(type,index),(int*)&mapmode[0]); 1.349 + aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_V(type,index),(int*)&mapmode[1]); 1.350 + } 1.351 + // Get texture flags 1.352 + if (flags){ 1.353 + aiGetMaterialInteger(mat,AI_MATKEY_TEXFLAGS(type,index),(int*)flags); 1.354 + } 1.355 + return AI_SUCCESS; 1.356 +} 1.357 + 1.358 +// ------------------------------------------------------------------------------------------------ 1.359 +// Construction. Actually the one and only way to get an aiMaterial instance 1.360 +aiMaterial::aiMaterial() 1.361 +{ 1.362 + // Allocate 5 entries by default 1.363 + mNumProperties = 0; 1.364 + mNumAllocated = 5; 1.365 + mProperties = new aiMaterialProperty*[5]; 1.366 +} 1.367 + 1.368 +// ------------------------------------------------------------------------------------------------ 1.369 +aiMaterial::~aiMaterial() 1.370 +{ 1.371 + Clear(); 1.372 + 1.373 + delete[] mProperties; 1.374 +} 1.375 + 1.376 +// ------------------------------------------------------------------------------------------------ 1.377 +void aiMaterial::Clear() 1.378 +{ 1.379 + for (unsigned int i = 0; i < mNumProperties;++i) { 1.380 + // delete this entry 1.381 + delete mProperties[i]; 1.382 + AI_DEBUG_INVALIDATE_PTR(mProperties[i]); 1.383 + } 1.384 + mNumProperties = 0; 1.385 + 1.386 + // The array remains allocated, we just invalidated its contents 1.387 +} 1.388 + 1.389 +// ------------------------------------------------------------------------------------------------ 1.390 +aiReturn aiMaterial::RemoveProperty (const char* pKey,unsigned int type, 1.391 + unsigned int index 1.392 + ) 1.393 +{ 1.394 + ai_assert(NULL != pKey); 1.395 + 1.396 + for (unsigned int i = 0; i < mNumProperties;++i) { 1.397 + aiMaterialProperty* prop = mProperties[i]; 1.398 + 1.399 + if (prop && !strcmp( prop->mKey.data, pKey ) && 1.400 + prop->mSemantic == type && prop->mIndex == index) 1.401 + { 1.402 + // Delete this entry 1.403 + delete mProperties[i]; 1.404 + 1.405 + // collapse the array behind --. 1.406 + --mNumProperties; 1.407 + for (unsigned int a = i; a < mNumProperties;++a) { 1.408 + mProperties[a] = mProperties[a+1]; 1.409 + } 1.410 + return AI_SUCCESS; 1.411 + } 1.412 + } 1.413 + 1.414 + return AI_FAILURE; 1.415 +} 1.416 + 1.417 +// ------------------------------------------------------------------------------------------------ 1.418 +aiReturn aiMaterial::AddBinaryProperty (const void* pInput, 1.419 + unsigned int pSizeInBytes, 1.420 + const char* pKey, 1.421 + unsigned int type, 1.422 + unsigned int index, 1.423 + aiPropertyTypeInfo pType 1.424 + ) 1.425 +{ 1.426 + ai_assert (pInput != NULL); 1.427 + ai_assert (pKey != NULL); 1.428 + ai_assert (0 != pSizeInBytes); 1.429 + 1.430 + // first search the list whether there is already an entry with this key 1.431 + unsigned int iOutIndex = UINT_MAX; 1.432 + for (unsigned int i = 0; i < mNumProperties;++i) { 1.433 + aiMaterialProperty* prop = mProperties[i]; 1.434 + 1.435 + if (prop /* just for safety */ && !strcmp( prop->mKey.data, pKey ) && 1.436 + prop->mSemantic == type && prop->mIndex == index){ 1.437 + 1.438 + delete mProperties[i]; 1.439 + iOutIndex = i; 1.440 + } 1.441 + } 1.442 + 1.443 + // Allocate a new material property 1.444 + aiMaterialProperty* pcNew = new aiMaterialProperty(); 1.445 + 1.446 + // .. and fill it 1.447 + pcNew->mType = pType; 1.448 + pcNew->mSemantic = type; 1.449 + pcNew->mIndex = index; 1.450 + 1.451 + pcNew->mDataLength = pSizeInBytes; 1.452 + pcNew->mData = new char[pSizeInBytes]; 1.453 + memcpy (pcNew->mData,pInput,pSizeInBytes); 1.454 + 1.455 + pcNew->mKey.length = ::strlen(pKey); 1.456 + ai_assert ( MAXLEN > pcNew->mKey.length); 1.457 + strcpy( pcNew->mKey.data, pKey ); 1.458 + 1.459 + if (UINT_MAX != iOutIndex) { 1.460 + mProperties[iOutIndex] = pcNew; 1.461 + return AI_SUCCESS; 1.462 + } 1.463 + 1.464 + // resize the array ... double the storage allocated 1.465 + if (mNumProperties == mNumAllocated) { 1.466 + const unsigned int iOld = mNumAllocated; 1.467 + mNumAllocated *= 2; 1.468 + 1.469 + aiMaterialProperty** ppTemp; 1.470 + try { 1.471 + ppTemp = new aiMaterialProperty*[mNumAllocated]; 1.472 + } catch (std::bad_alloc&) { 1.473 + return AI_OUTOFMEMORY; 1.474 + } 1.475 + 1.476 + // just copy all items over; then replace the old array 1.477 + memcpy (ppTemp,mProperties,iOld * sizeof(void*)); 1.478 + 1.479 + delete[] mProperties; 1.480 + mProperties = ppTemp; 1.481 + } 1.482 + // push back ... 1.483 + mProperties[mNumProperties++] = pcNew; 1.484 + return AI_SUCCESS; 1.485 +} 1.486 + 1.487 +// ------------------------------------------------------------------------------------------------ 1.488 +aiReturn aiMaterial::AddProperty (const aiString* pInput, 1.489 + const char* pKey, 1.490 + unsigned int type, 1.491 + unsigned int index) 1.492 +{ 1.493 + // We don't want to add the whole buffer .. write a 32 bit length 1.494 + // prefix followed by the zero-terminated UTF8 string. 1.495 + // (HACK) I don't want to break the ABI now, but we definitely 1.496 + // ought to change aiString::mLength to uint32_t one day. 1.497 + if (sizeof(size_t) == 8) { 1.498 + aiString copy = *pInput; 1.499 + uint32_t* s = reinterpret_cast<uint32_t*>(©.length); 1.500 + s[1] = static_cast<uint32_t>(pInput->length); 1.501 + 1.502 + return AddBinaryProperty(s+1, 1.503 + pInput->length+1+4, 1.504 + pKey, 1.505 + type, 1.506 + index, 1.507 + aiPTI_String); 1.508 + } 1.509 + ai_assert(sizeof(size_t)==4); 1.510 + return AddBinaryProperty(pInput, 1.511 + pInput->length+1+4, 1.512 + pKey, 1.513 + type, 1.514 + index, 1.515 + aiPTI_String); 1.516 +} 1.517 + 1.518 +// ------------------------------------------------------------------------------------------------ 1.519 +uint32_t Assimp :: ComputeMaterialHash(const aiMaterial* mat, bool includeMatName /*= false*/) 1.520 +{ 1.521 + uint32_t hash = 1503; // magic start value, chosen to be my birthday :-) 1.522 + for (unsigned int i = 0; i < mat->mNumProperties;++i) { 1.523 + aiMaterialProperty* prop; 1.524 + 1.525 + // Exclude all properties whose first character is '?' from the hash 1.526 + // See doc for aiMaterialProperty. 1.527 + if ((prop = mat->mProperties[i]) && (includeMatName || prop->mKey.data[0] != '?')) { 1.528 + 1.529 + hash = SuperFastHash(prop->mKey.data,(unsigned int)prop->mKey.length,hash); 1.530 + hash = SuperFastHash(prop->mData,prop->mDataLength,hash); 1.531 + 1.532 + // Combine the semantic and the index with the hash 1.533 + hash = SuperFastHash((const char*)&prop->mSemantic,sizeof(unsigned int),hash); 1.534 + hash = SuperFastHash((const char*)&prop->mIndex,sizeof(unsigned int),hash); 1.535 + } 1.536 + } 1.537 + return hash; 1.538 +} 1.539 + 1.540 +// ------------------------------------------------------------------------------------------------ 1.541 +void aiMaterial::CopyPropertyList(aiMaterial* pcDest, 1.542 + const aiMaterial* pcSrc 1.543 + ) 1.544 +{ 1.545 + ai_assert(NULL != pcDest); 1.546 + ai_assert(NULL != pcSrc); 1.547 + 1.548 + unsigned int iOldNum = pcDest->mNumProperties; 1.549 + pcDest->mNumAllocated += pcSrc->mNumAllocated; 1.550 + pcDest->mNumProperties += pcSrc->mNumProperties; 1.551 + 1.552 + aiMaterialProperty** pcOld = pcDest->mProperties; 1.553 + pcDest->mProperties = new aiMaterialProperty*[pcDest->mNumAllocated]; 1.554 + 1.555 + if (iOldNum && pcOld) { 1.556 + for (unsigned int i = 0; i < iOldNum;++i) { 1.557 + pcDest->mProperties[i] = pcOld[i]; 1.558 + } 1.559 + 1.560 + delete[] pcOld; 1.561 + } 1.562 + for (unsigned int i = iOldNum; i< pcDest->mNumProperties;++i) { 1.563 + aiMaterialProperty* propSrc = pcSrc->mProperties[i]; 1.564 + 1.565 + // search whether we have already a property with this name -> if yes, overwrite it 1.566 + aiMaterialProperty* prop; 1.567 + for (unsigned int q = 0; q < iOldNum;++q) { 1.568 + prop = pcDest->mProperties[q]; 1.569 + if (prop /* just for safety */ && prop->mKey == propSrc->mKey && prop->mSemantic == propSrc->mSemantic 1.570 + && prop->mIndex == propSrc->mIndex) { 1.571 + delete prop; 1.572 + 1.573 + // collapse the whole array ... 1.574 + memmove(&pcDest->mProperties[q],&pcDest->mProperties[q+1],i-q); 1.575 + i--; 1.576 + pcDest->mNumProperties--; 1.577 + } 1.578 + } 1.579 + 1.580 + // Allocate the output property and copy the source property 1.581 + prop = pcDest->mProperties[i] = new aiMaterialProperty(); 1.582 + prop->mKey = propSrc->mKey; 1.583 + prop->mDataLength = propSrc->mDataLength; 1.584 + prop->mType = propSrc->mType; 1.585 + prop->mSemantic = propSrc->mSemantic; 1.586 + prop->mIndex = propSrc->mIndex; 1.587 + 1.588 + prop->mData = new char[propSrc->mDataLength]; 1.589 + memcpy(prop->mData,propSrc->mData,prop->mDataLength); 1.590 + } 1.591 + return; 1.592 +} 1.593 +