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*>(&copy.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 +