vrshoot
diff libs/assimp/MDLMaterialLoader.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/MDLMaterialLoader.cpp Sat Feb 01 19:58:19 2014 +0200 1.3 @@ -0,0 +1,827 @@ 1.4 +/* 1.5 +--------------------------------------------------------------------------- 1.6 +Open Asset Import Library (assimp) 1.7 +--------------------------------------------------------------------------- 1.8 + 1.9 +Copyright (c) 2006-2012, assimp team 1.10 + 1.11 +All rights reserved. 1.12 + 1.13 +Redistribution and use of this software in source and binary forms, 1.14 +with or without modification, are permitted provided that the following 1.15 +conditions are met: 1.16 + 1.17 +* Redistributions of source code must retain the above 1.18 + copyright notice, this list of conditions and the 1.19 + following disclaimer. 1.20 + 1.21 +* Redistributions in binary form must reproduce the above 1.22 + copyright notice, this list of conditions and the 1.23 + following disclaimer in the documentation and/or other 1.24 + materials provided with the distribution. 1.25 + 1.26 +* Neither the name of the assimp team, nor the names of its 1.27 + contributors may be used to endorse or promote products 1.28 + derived from this software without specific prior 1.29 + written permission of the assimp team. 1.30 + 1.31 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.32 +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.33 +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.34 +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.35 +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.36 +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.37 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.38 +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.39 +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.40 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.41 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.42 +--------------------------------------------------------------------------- 1.43 +*/ 1.44 + 1.45 +/** @file Implementation of the material part of the MDL importer class */ 1.46 + 1.47 +#include "AssimpPCH.h" 1.48 +#ifndef ASSIMP_BUILD_NO_MDL_IMPORTER 1.49 + 1.50 +// internal headers 1.51 +#include "MDLLoader.h" 1.52 +#include "MDLDefaultColorMap.h" 1.53 + 1.54 +using namespace Assimp; 1.55 +static aiTexel* const bad_texel = reinterpret_cast<aiTexel*>(SIZE_MAX); 1.56 + 1.57 +// ------------------------------------------------------------------------------------------------ 1.58 +// Find a suitable pallette file or take teh default one 1.59 +void MDLImporter::SearchPalette(const unsigned char** pszColorMap) 1.60 +{ 1.61 + // now try to find the color map in the current directory 1.62 + IOStream* pcStream = pIOHandler->Open(configPalette,"rb"); 1.63 + 1.64 + const unsigned char* szColorMap = (const unsigned char*)::g_aclrDefaultColorMap; 1.65 + if(pcStream) 1.66 + { 1.67 + if (pcStream->FileSize() >= 768) 1.68 + { 1.69 + unsigned char* colorMap = new unsigned char[256*3]; 1.70 + szColorMap = colorMap; 1.71 + pcStream->Read(colorMap,256*3,1); 1.72 + DefaultLogger::get()->info("Found valid colormap.lmp in directory. " 1.73 + "It will be used to decode embedded textures in palletized formats."); 1.74 + } 1.75 + delete pcStream; 1.76 + pcStream = NULL; 1.77 + } 1.78 + *pszColorMap = szColorMap; 1.79 +} 1.80 + 1.81 +// ------------------------------------------------------------------------------------------------ 1.82 +// Free the palette again 1.83 +void MDLImporter::FreePalette(const unsigned char* szColorMap) 1.84 +{ 1.85 + if (szColorMap != (const unsigned char*)::g_aclrDefaultColorMap) 1.86 + delete[] szColorMap; 1.87 +} 1.88 + 1.89 +// ------------------------------------------------------------------------------------------------ 1.90 +// Check whether we can replace a texture with a single color 1.91 +aiColor4D MDLImporter::ReplaceTextureWithColor(const aiTexture* pcTexture) 1.92 +{ 1.93 + ai_assert(NULL != pcTexture); 1.94 + 1.95 + aiColor4D clrOut; 1.96 + clrOut.r = get_qnan(); 1.97 + if (!pcTexture->mHeight || !pcTexture->mWidth) 1.98 + return clrOut; 1.99 + 1.100 + const unsigned int iNumPixels = pcTexture->mHeight*pcTexture->mWidth; 1.101 + const aiTexel* pcTexel = pcTexture->pcData+1; 1.102 + const aiTexel* const pcTexelEnd = &pcTexture->pcData[iNumPixels]; 1.103 + 1.104 + while (pcTexel != pcTexelEnd) 1.105 + { 1.106 + if (*pcTexel != *(pcTexel-1)) 1.107 + { 1.108 + pcTexel = NULL; 1.109 + break; 1.110 + } 1.111 + ++pcTexel; 1.112 + } 1.113 + if (pcTexel) 1.114 + { 1.115 + clrOut.r = pcTexture->pcData->r / 255.0f; 1.116 + clrOut.g = pcTexture->pcData->g / 255.0f; 1.117 + clrOut.b = pcTexture->pcData->b / 255.0f; 1.118 + clrOut.a = pcTexture->pcData->a / 255.0f; 1.119 + } 1.120 + return clrOut; 1.121 +} 1.122 + 1.123 +// ------------------------------------------------------------------------------------------------ 1.124 +// Read a texture from a MDL3 file 1.125 +void MDLImporter::CreateTextureARGB8_3DGS_MDL3(const unsigned char* szData) 1.126 +{ 1.127 + const MDL::Header *pcHeader = (const MDL::Header*)mBuffer; //the endianess is allready corrected in the InternReadFile_3DGS_MDL345 function 1.128 + 1.129 + VALIDATE_FILE_SIZE(szData + pcHeader->skinwidth * 1.130 + pcHeader->skinheight); 1.131 + 1.132 + // allocate a new texture object 1.133 + aiTexture* pcNew = new aiTexture(); 1.134 + pcNew->mWidth = pcHeader->skinwidth; 1.135 + pcNew->mHeight = pcHeader->skinheight; 1.136 + 1.137 + pcNew->pcData = new aiTexel[pcNew->mWidth * pcNew->mHeight]; 1.138 + 1.139 + const unsigned char* szColorMap; 1.140 + this->SearchPalette(&szColorMap); 1.141 + 1.142 + // copy texture data 1.143 + for (unsigned int i = 0; i < pcNew->mWidth*pcNew->mHeight;++i) 1.144 + { 1.145 + const unsigned char val = szData[i]; 1.146 + const unsigned char* sz = &szColorMap[val*3]; 1.147 + 1.148 + pcNew->pcData[i].a = 0xFF; 1.149 + pcNew->pcData[i].r = *sz++; 1.150 + pcNew->pcData[i].g = *sz++; 1.151 + pcNew->pcData[i].b = *sz; 1.152 + } 1.153 + 1.154 + FreePalette(szColorMap); 1.155 + 1.156 + // store the texture 1.157 + aiTexture** pc = this->pScene->mTextures; 1.158 + this->pScene->mTextures = new aiTexture*[pScene->mNumTextures+1]; 1.159 + for (unsigned int i = 0; i <pScene->mNumTextures;++i) 1.160 + pScene->mTextures[i] = pc[i]; 1.161 + 1.162 + pScene->mTextures[this->pScene->mNumTextures] = pcNew; 1.163 + pScene->mNumTextures++; 1.164 + delete[] pc; 1.165 + return; 1.166 +} 1.167 + 1.168 +// ------------------------------------------------------------------------------------------------ 1.169 +// Read a texture from a MDL4 file 1.170 +void MDLImporter::CreateTexture_3DGS_MDL4(const unsigned char* szData, 1.171 + unsigned int iType, 1.172 + unsigned int* piSkip) 1.173 +{ 1.174 + ai_assert(NULL != piSkip); 1.175 + 1.176 + const MDL::Header *pcHeader = (const MDL::Header*)mBuffer; //the endianess is allready corrected in the InternReadFile_3DGS_MDL345 function 1.177 + 1.178 + if (iType == 1 || iType > 3) 1.179 + { 1.180 + DefaultLogger::get()->error("Unsupported texture file format"); 1.181 + return; 1.182 + } 1.183 + 1.184 + const bool bNoRead = *piSkip == UINT_MAX; 1.185 + 1.186 + // allocate a new texture object 1.187 + aiTexture* pcNew = new aiTexture(); 1.188 + pcNew->mWidth = pcHeader->skinwidth; 1.189 + pcNew->mHeight = pcHeader->skinheight; 1.190 + 1.191 + if (bNoRead)pcNew->pcData = bad_texel; 1.192 + ParseTextureColorData(szData,iType,piSkip,pcNew); 1.193 + 1.194 + // store the texture 1.195 + if (!bNoRead) 1.196 + { 1.197 + if (!this->pScene->mNumTextures) 1.198 + { 1.199 + pScene->mNumTextures = 1; 1.200 + pScene->mTextures = new aiTexture*[1]; 1.201 + pScene->mTextures[0] = pcNew; 1.202 + } 1.203 + else 1.204 + { 1.205 + aiTexture** pc = pScene->mTextures; 1.206 + pScene->mTextures = new aiTexture*[pScene->mNumTextures+1]; 1.207 + for (unsigned int i = 0; i < this->pScene->mNumTextures;++i) 1.208 + pScene->mTextures[i] = pc[i]; 1.209 + pScene->mTextures[pScene->mNumTextures] = pcNew; 1.210 + pScene->mNumTextures++; 1.211 + delete[] pc; 1.212 + } 1.213 + } 1.214 + else { 1.215 + pcNew->pcData = NULL; 1.216 + delete pcNew; 1.217 + } 1.218 + return; 1.219 +} 1.220 + 1.221 +// ------------------------------------------------------------------------------------------------ 1.222 +// Load color data of a texture and convert it to our output format 1.223 +void MDLImporter::ParseTextureColorData(const unsigned char* szData, 1.224 + unsigned int iType, 1.225 + unsigned int* piSkip, 1.226 + aiTexture* pcNew) 1.227 +{ 1.228 + const bool do_read = bad_texel != pcNew->pcData; 1.229 + 1.230 + // allocate storage for the texture image 1.231 + if (do_read) { 1.232 + pcNew->pcData = new aiTexel[pcNew->mWidth * pcNew->mHeight]; 1.233 + } 1.234 + 1.235 + // R5G6B5 format (with or without MIPs) 1.236 + // **************************************************************** 1.237 + if (2 == iType || 10 == iType) 1.238 + { 1.239 + VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*2); 1.240 + 1.241 + // copy texture data 1.242 + unsigned int i; 1.243 + if (do_read) 1.244 + { 1.245 + for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i) 1.246 + { 1.247 + MDL::RGB565 val = ((MDL::RGB565*)szData)[i]; 1.248 + AI_SWAP2(val); 1.249 + 1.250 + pcNew->pcData[i].a = 0xFF; 1.251 + pcNew->pcData[i].r = (unsigned char)val.b << 3; 1.252 + pcNew->pcData[i].g = (unsigned char)val.g << 2; 1.253 + pcNew->pcData[i].b = (unsigned char)val.r << 3; 1.254 + } 1.255 + } 1.256 + else i = pcNew->mWidth*pcNew->mHeight; 1.257 + *piSkip = i * 2; 1.258 + 1.259 + // apply MIP maps 1.260 + if (10 == iType) 1.261 + { 1.262 + *piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 1; 1.263 + VALIDATE_FILE_SIZE(szData + *piSkip); 1.264 + } 1.265 + } 1.266 + // ARGB4 format (with or without MIPs) 1.267 + // **************************************************************** 1.268 + else if (3 == iType || 11 == iType) 1.269 + { 1.270 + VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*4); 1.271 + 1.272 + // copy texture data 1.273 + unsigned int i; 1.274 + if (do_read) 1.275 + { 1.276 + for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i) 1.277 + { 1.278 + MDL::ARGB4 val = ((MDL::ARGB4*)szData)[i]; 1.279 + AI_SWAP2(val); 1.280 + 1.281 + pcNew->pcData[i].a = (unsigned char)val.a << 4; 1.282 + pcNew->pcData[i].r = (unsigned char)val.r << 4; 1.283 + pcNew->pcData[i].g = (unsigned char)val.g << 4; 1.284 + pcNew->pcData[i].b = (unsigned char)val.b << 4; 1.285 + } 1.286 + } 1.287 + else i = pcNew->mWidth*pcNew->mHeight; 1.288 + *piSkip = i * 2; 1.289 + 1.290 + // apply MIP maps 1.291 + if (11 == iType) 1.292 + { 1.293 + *piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 1; 1.294 + VALIDATE_FILE_SIZE(szData + *piSkip); 1.295 + } 1.296 + } 1.297 + // RGB8 format (with or without MIPs) 1.298 + // **************************************************************** 1.299 + else if (4 == iType || 12 == iType) 1.300 + { 1.301 + VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*3); 1.302 + 1.303 + // copy texture data 1.304 + unsigned int i; 1.305 + if (do_read) 1.306 + { 1.307 + for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i) 1.308 + { 1.309 + const unsigned char* _szData = &szData[i*3]; 1.310 + 1.311 + pcNew->pcData[i].a = 0xFF; 1.312 + pcNew->pcData[i].b = *_szData++; 1.313 + pcNew->pcData[i].g = *_szData++; 1.314 + pcNew->pcData[i].r = *_szData; 1.315 + } 1.316 + } 1.317 + else i = pcNew->mWidth*pcNew->mHeight; 1.318 + 1.319 + 1.320 + // apply MIP maps 1.321 + *piSkip = i * 3; 1.322 + if (12 == iType) 1.323 + { 1.324 + *piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) *3; 1.325 + VALIDATE_FILE_SIZE(szData + *piSkip); 1.326 + } 1.327 + } 1.328 + // ARGB8 format (with ir without MIPs) 1.329 + // **************************************************************** 1.330 + else if (5 == iType || 13 == iType) 1.331 + { 1.332 + VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*4); 1.333 + 1.334 + // copy texture data 1.335 + unsigned int i; 1.336 + if (do_read) 1.337 + { 1.338 + for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i) 1.339 + { 1.340 + const unsigned char* _szData = &szData[i*4]; 1.341 + 1.342 + pcNew->pcData[i].b = *_szData++; 1.343 + pcNew->pcData[i].g = *_szData++; 1.344 + pcNew->pcData[i].r = *_szData++; 1.345 + pcNew->pcData[i].a = *_szData; 1.346 + } 1.347 + } 1.348 + else i = pcNew->mWidth*pcNew->mHeight; 1.349 + 1.350 + // apply MIP maps 1.351 + *piSkip = i << 2; 1.352 + if (13 == iType) 1.353 + { 1.354 + *piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 2; 1.355 + } 1.356 + } 1.357 + // palletized 8 bit texture. As for Quake 1 1.358 + // **************************************************************** 1.359 + else if (0 == iType) 1.360 + { 1.361 + VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight); 1.362 + 1.363 + // copy texture data 1.364 + unsigned int i; 1.365 + if (do_read) 1.366 + { 1.367 + 1.368 + const unsigned char* szColorMap; 1.369 + SearchPalette(&szColorMap); 1.370 + 1.371 + for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i) 1.372 + { 1.373 + const unsigned char val = szData[i]; 1.374 + const unsigned char* sz = &szColorMap[val*3]; 1.375 + 1.376 + pcNew->pcData[i].a = 0xFF; 1.377 + pcNew->pcData[i].r = *sz++; 1.378 + pcNew->pcData[i].g = *sz++; 1.379 + pcNew->pcData[i].b = *sz; 1.380 + } 1.381 + this->FreePalette(szColorMap); 1.382 + 1.383 + } 1.384 + else i = pcNew->mWidth*pcNew->mHeight; 1.385 + *piSkip = i; 1.386 + 1.387 + // FIXME: Also support for MIP maps? 1.388 + } 1.389 +} 1.390 + 1.391 +// ------------------------------------------------------------------------------------------------ 1.392 +// Get a texture from a MDL5 file 1.393 +void MDLImporter::CreateTexture_3DGS_MDL5(const unsigned char* szData, 1.394 + unsigned int iType, 1.395 + unsigned int* piSkip) 1.396 +{ 1.397 + ai_assert(NULL != piSkip); 1.398 + bool bNoRead = *piSkip == UINT_MAX; 1.399 + 1.400 + // allocate a new texture object 1.401 + aiTexture* pcNew = new aiTexture(); 1.402 + 1.403 + VALIDATE_FILE_SIZE(szData+8); 1.404 + 1.405 + // first read the size of the texture 1.406 + pcNew->mWidth = *((uint32_t*)szData); 1.407 + AI_SWAP4(pcNew->mWidth); 1.408 + szData += sizeof(uint32_t); 1.409 + 1.410 + pcNew->mHeight = *((uint32_t*)szData); 1.411 + AI_SWAP4(pcNew->mHeight); 1.412 + szData += sizeof(uint32_t); 1.413 + 1.414 + if (bNoRead) { 1.415 + pcNew->pcData = bad_texel; 1.416 + } 1.417 + 1.418 + // this should not occur - at least the docs say it shouldn't. 1.419 + // however, one can easily try out what MED does if you have 1.420 + // a model with a DDS texture and export it to MDL5 ... 1.421 + // yeah, it embedds the DDS file. 1.422 + if (6 == iType) 1.423 + { 1.424 + // this is a compressed texture in DDS format 1.425 + *piSkip = pcNew->mWidth; 1.426 + VALIDATE_FILE_SIZE(szData + *piSkip); 1.427 + 1.428 + if (!bNoRead) 1.429 + { 1.430 + // place a hint and let the application know that this is a DDS file 1.431 + pcNew->mHeight = 0; 1.432 + pcNew->achFormatHint[0] = 'd'; 1.433 + pcNew->achFormatHint[1] = 'd'; 1.434 + pcNew->achFormatHint[2] = 's'; 1.435 + pcNew->achFormatHint[3] = '\0'; 1.436 + 1.437 + pcNew->pcData = (aiTexel*) new unsigned char[pcNew->mWidth]; 1.438 + ::memcpy(pcNew->pcData,szData,pcNew->mWidth); 1.439 + } 1.440 + } 1.441 + else 1.442 + { 1.443 + // parse the color data of the texture 1.444 + ParseTextureColorData(szData,iType,piSkip,pcNew); 1.445 + } 1.446 + *piSkip += sizeof(uint32_t) * 2; 1.447 + 1.448 + if (!bNoRead) 1.449 + { 1.450 + // store the texture 1.451 + if (!this->pScene->mNumTextures) 1.452 + { 1.453 + pScene->mNumTextures = 1; 1.454 + pScene->mTextures = new aiTexture*[1]; 1.455 + pScene->mTextures[0] = pcNew; 1.456 + } 1.457 + else 1.458 + { 1.459 + aiTexture** pc = pScene->mTextures; 1.460 + pScene->mTextures = new aiTexture*[pScene->mNumTextures+1]; 1.461 + for (unsigned int i = 0; i < pScene->mNumTextures;++i) 1.462 + this->pScene->mTextures[i] = pc[i]; 1.463 + 1.464 + pScene->mTextures[pScene->mNumTextures] = pcNew; 1.465 + pScene->mNumTextures++; 1.466 + delete[] pc; 1.467 + } 1.468 + } 1.469 + else { 1.470 + pcNew->pcData = NULL; 1.471 + delete pcNew; 1.472 + } 1.473 + return; 1.474 +} 1.475 + 1.476 +// ------------------------------------------------------------------------------------------------ 1.477 +// Get a skin from a MDL7 file - more complex than all other subformats 1.478 +void MDLImporter::ParseSkinLump_3DGS_MDL7( 1.479 + const unsigned char* szCurrent, 1.480 + const unsigned char** szCurrentOut, 1.481 + aiMaterial* pcMatOut, 1.482 + unsigned int iType, 1.483 + unsigned int iWidth, 1.484 + unsigned int iHeight) 1.485 +{ 1.486 + aiTexture* pcNew = NULL; 1.487 + 1.488 + // get the type of the skin 1.489 + unsigned int iMasked = (unsigned int)(iType & 0xF); 1.490 + 1.491 + if (0x1 == iMasked) 1.492 + { 1.493 + // ***** REFERENCE TO ANOTHER SKIN INDEX ***** 1.494 + int referrer = (int)iWidth; 1.495 + pcMatOut->AddProperty<int>(&referrer,1,AI_MDL7_REFERRER_MATERIAL); 1.496 + } 1.497 + else if (0x6 == iMasked) 1.498 + { 1.499 + // ***** EMBEDDED DDS FILE ***** 1.500 + if (1 != iHeight) 1.501 + { 1.502 + DefaultLogger::get()->warn("Found a reference to an embedded DDS texture, " 1.503 + "but texture height is not equal to 1, which is not supported by MED"); 1.504 + } 1.505 + 1.506 + pcNew = new aiTexture(); 1.507 + pcNew->mHeight = 0; 1.508 + pcNew->mWidth = iWidth; 1.509 + 1.510 + // place a proper format hint 1.511 + pcNew->achFormatHint[0] = 'd'; 1.512 + pcNew->achFormatHint[1] = 'd'; 1.513 + pcNew->achFormatHint[2] = 's'; 1.514 + pcNew->achFormatHint[3] = '\0'; 1.515 + 1.516 + pcNew->pcData = (aiTexel*) new unsigned char[pcNew->mWidth]; 1.517 + memcpy(pcNew->pcData,szCurrent,pcNew->mWidth); 1.518 + szCurrent += iWidth; 1.519 + } 1.520 + if (0x7 == iMasked) 1.521 + { 1.522 + // ***** REFERENCE TO EXTERNAL FILE ***** 1.523 + if (1 != iHeight) 1.524 + { 1.525 + DefaultLogger::get()->warn("Found a reference to an external texture, " 1.526 + "but texture height is not equal to 1, which is not supported by MED"); 1.527 + } 1.528 + 1.529 + aiString szFile; 1.530 + const size_t iLen = strlen((const char*)szCurrent); 1.531 + size_t iLen2 = iLen+1; 1.532 + iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2; 1.533 + memcpy(szFile.data,(const char*)szCurrent,iLen2); 1.534 + szFile.length = iLen; 1.535 + 1.536 + szCurrent += iLen2; 1.537 + 1.538 + // place this as diffuse texture 1.539 + pcMatOut->AddProperty(&szFile,AI_MATKEY_TEXTURE_DIFFUSE(0)); 1.540 + } 1.541 + else if (iMasked || !iType || (iType && iWidth && iHeight)) 1.542 + { 1.543 + // ***** STANDARD COLOR TEXTURE ***** 1.544 + pcNew = new aiTexture(); 1.545 + if (!iHeight || !iWidth) 1.546 + { 1.547 + DefaultLogger::get()->warn("Found embedded texture, but its width " 1.548 + "an height are both 0. Is this a joke?"); 1.549 + 1.550 + // generate an empty chess pattern 1.551 + pcNew->mWidth = pcNew->mHeight = 8; 1.552 + pcNew->pcData = new aiTexel[64]; 1.553 + for (unsigned int x = 0; x < 8;++x) 1.554 + { 1.555 + for (unsigned int y = 0; y < 8;++y) 1.556 + { 1.557 + const bool bSet = ((0 == x % 2 && 0 != y % 2) || 1.558 + (0 != x % 2 && 0 == y % 2)); 1.559 + 1.560 + aiTexel* pc = &pcNew->pcData[y * 8 + x]; 1.561 + pc->r = pc->b = pc->g = (bSet?0xFF:0); 1.562 + pc->a = 0xFF; 1.563 + } 1.564 + } 1.565 + } 1.566 + else 1.567 + { 1.568 + // it is a standard color texture. Fill in width and height 1.569 + // and call the same function we used for loading MDL5 files 1.570 + 1.571 + pcNew->mWidth = iWidth; 1.572 + pcNew->mHeight = iHeight; 1.573 + 1.574 + unsigned int iSkip = 0; 1.575 + ParseTextureColorData(szCurrent,iMasked,&iSkip,pcNew); 1.576 + 1.577 + // skip length of texture data 1.578 + szCurrent += iSkip; 1.579 + } 1.580 + } 1.581 + 1.582 + // sometimes there are MDL7 files which have a monochrome 1.583 + // texture instead of material colors ... posssible they have 1.584 + // been converted to MDL7 from other formats, such as MDL5 1.585 + aiColor4D clrTexture; 1.586 + if (pcNew)clrTexture = ReplaceTextureWithColor(pcNew); 1.587 + else clrTexture.r = get_qnan(); 1.588 + 1.589 + // check whether a material definition is contained in the skin 1.590 + if (iType & AI_MDL7_SKINTYPE_MATERIAL) 1.591 + { 1.592 + BE_NCONST MDL::Material_MDL7* pcMatIn = (BE_NCONST MDL::Material_MDL7*)szCurrent; 1.593 + szCurrent = (unsigned char*)(pcMatIn+1); 1.594 + VALIDATE_FILE_SIZE(szCurrent); 1.595 + 1.596 + aiColor3D clrTemp; 1.597 + 1.598 +#define COLOR_MULTIPLY_RGB() \ 1.599 + if (is_not_qnan(clrTexture.r)) \ 1.600 + { \ 1.601 + clrTemp.r *= clrTexture.r; \ 1.602 + clrTemp.g *= clrTexture.g; \ 1.603 + clrTemp.b *= clrTexture.b; \ 1.604 + } 1.605 + 1.606 + // read diffuse color 1.607 + clrTemp.r = pcMatIn->Diffuse.r; 1.608 + AI_SWAP4(clrTemp.r); 1.609 + clrTemp.g = pcMatIn->Diffuse.g; 1.610 + AI_SWAP4(clrTemp.g); 1.611 + clrTemp.b = pcMatIn->Diffuse.b; 1.612 + AI_SWAP4(clrTemp.b); 1.613 + COLOR_MULTIPLY_RGB(); 1.614 + pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_DIFFUSE); 1.615 + 1.616 + // read specular color 1.617 + clrTemp.r = pcMatIn->Specular.r; 1.618 + AI_SWAP4(clrTemp.r); 1.619 + clrTemp.g = pcMatIn->Specular.g; 1.620 + AI_SWAP4(clrTemp.g); 1.621 + clrTemp.b = pcMatIn->Specular.b; 1.622 + AI_SWAP4(clrTemp.b); 1.623 + COLOR_MULTIPLY_RGB(); 1.624 + pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_SPECULAR); 1.625 + 1.626 + // read ambient color 1.627 + clrTemp.r = pcMatIn->Ambient.r; 1.628 + AI_SWAP4(clrTemp.r); 1.629 + clrTemp.g = pcMatIn->Ambient.g; 1.630 + AI_SWAP4(clrTemp.g); 1.631 + clrTemp.b = pcMatIn->Ambient.b; 1.632 + AI_SWAP4(clrTemp.b); 1.633 + COLOR_MULTIPLY_RGB(); 1.634 + pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_AMBIENT); 1.635 + 1.636 + // read emissive color 1.637 + clrTemp.r = pcMatIn->Emissive.r; 1.638 + AI_SWAP4(clrTemp.r); 1.639 + clrTemp.g = pcMatIn->Emissive.g; 1.640 + AI_SWAP4(clrTemp.g); 1.641 + clrTemp.b = pcMatIn->Emissive.b; 1.642 + AI_SWAP4(clrTemp.b); 1.643 + pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_EMISSIVE); 1.644 + 1.645 +#undef COLOR_MULITPLY_RGB 1.646 + 1.647 + // FIX: Take the opacity from the ambient color. 1.648 + // The doc say something else, but it is fact that MED exports the 1.649 + // opacity like this .... oh well. 1.650 + clrTemp.r = pcMatIn->Ambient.a; 1.651 + AI_SWAP4(clrTemp.r); 1.652 + if (is_not_qnan(clrTexture.r)) { 1.653 + clrTemp.r *= clrTexture.a; 1.654 + } 1.655 + pcMatOut->AddProperty<float>(&clrTemp.r,1,AI_MATKEY_OPACITY); 1.656 + 1.657 + // read phong power 1.658 + int iShadingMode = (int)aiShadingMode_Gouraud; 1.659 + AI_SWAP4(pcMatIn->Power); 1.660 + if (0.0f != pcMatIn->Power) 1.661 + { 1.662 + iShadingMode = (int)aiShadingMode_Phong; 1.663 + pcMatOut->AddProperty<float>(&pcMatIn->Power,1,AI_MATKEY_SHININESS); 1.664 + } 1.665 + pcMatOut->AddProperty<int>(&iShadingMode,1,AI_MATKEY_SHADING_MODEL); 1.666 + } 1.667 + else if (is_not_qnan(clrTexture.r)) 1.668 + { 1.669 + pcMatOut->AddProperty<aiColor4D>(&clrTexture,1,AI_MATKEY_COLOR_DIFFUSE); 1.670 + pcMatOut->AddProperty<aiColor4D>(&clrTexture,1,AI_MATKEY_COLOR_SPECULAR); 1.671 + } 1.672 + // if the texture could be replaced by a single material color 1.673 + // we don't need the texture anymore 1.674 + if (is_not_qnan(clrTexture.r)) 1.675 + { 1.676 + delete pcNew; 1.677 + pcNew = NULL; 1.678 + } 1.679 + 1.680 + // If an ASCII effect description (HLSL?) is contained in the file, 1.681 + // we can simply ignore it ... 1.682 + if (iType & AI_MDL7_SKINTYPE_MATERIAL_ASCDEF) 1.683 + { 1.684 + VALIDATE_FILE_SIZE(szCurrent); 1.685 + int32_t iMe = *((int32_t*)szCurrent); 1.686 + AI_SWAP4(iMe); 1.687 + szCurrent += sizeof(char) * iMe + sizeof(int32_t); 1.688 + VALIDATE_FILE_SIZE(szCurrent); 1.689 + } 1.690 + 1.691 + // If an embedded texture has been loaded setup the corresponding 1.692 + // data structures in the aiScene instance 1.693 + if (pcNew && pScene->mNumTextures <= 999) 1.694 + { 1.695 + 1.696 + // place this as diffuse texture 1.697 + char szCurrent[5]; 1.698 + ::sprintf(szCurrent,"*%i",this->pScene->mNumTextures); 1.699 + 1.700 + aiString szFile; 1.701 + const size_t iLen = strlen((const char*)szCurrent); 1.702 + ::memcpy(szFile.data,(const char*)szCurrent,iLen+1); 1.703 + szFile.length = iLen; 1.704 + 1.705 + pcMatOut->AddProperty(&szFile,AI_MATKEY_TEXTURE_DIFFUSE(0)); 1.706 + 1.707 + // store the texture 1.708 + if (!pScene->mNumTextures) 1.709 + { 1.710 + pScene->mNumTextures = 1; 1.711 + pScene->mTextures = new aiTexture*[1]; 1.712 + pScene->mTextures[0] = pcNew; 1.713 + } 1.714 + else 1.715 + { 1.716 + aiTexture** pc = pScene->mTextures; 1.717 + pScene->mTextures = new aiTexture*[pScene->mNumTextures+1]; 1.718 + for (unsigned int i = 0; i < pScene->mNumTextures;++i) { 1.719 + pScene->mTextures[i] = pc[i]; 1.720 + } 1.721 + 1.722 + pScene->mTextures[pScene->mNumTextures] = pcNew; 1.723 + pScene->mNumTextures++; 1.724 + delete[] pc; 1.725 + } 1.726 + } 1.727 + VALIDATE_FILE_SIZE(szCurrent); 1.728 + *szCurrentOut = szCurrent; 1.729 +} 1.730 + 1.731 +// ------------------------------------------------------------------------------------------------ 1.732 +// Skip a skin lump 1.733 +void MDLImporter::SkipSkinLump_3DGS_MDL7( 1.734 + const unsigned char* szCurrent, 1.735 + const unsigned char** szCurrentOut, 1.736 + unsigned int iType, 1.737 + unsigned int iWidth, 1.738 + unsigned int iHeight) 1.739 +{ 1.740 + // get the type of the skin 1.741 + const unsigned int iMasked = (unsigned int)(iType & 0xF); 1.742 + 1.743 + if (0x6 == iMasked) 1.744 + { 1.745 + szCurrent += iWidth; 1.746 + } 1.747 + if (0x7 == iMasked) 1.748 + { 1.749 + const size_t iLen = ::strlen((const char*)szCurrent); 1.750 + szCurrent += iLen+1; 1.751 + } 1.752 + else if (iMasked || !iType) 1.753 + { 1.754 + if (iMasked || !iType || (iType && iWidth && iHeight)) 1.755 + { 1.756 + // ParseTextureColorData(..., aiTexture::pcData == bad_texel) will simply 1.757 + // return the size of the color data in bytes in iSkip 1.758 + unsigned int iSkip = 0; 1.759 + 1.760 + aiTexture tex; 1.761 + tex.pcData = bad_texel; 1.762 + tex.mHeight = iHeight; 1.763 + tex.mWidth = iWidth; 1.764 + ParseTextureColorData(szCurrent,iMasked,&iSkip,&tex); 1.765 + 1.766 + // FIX: Important, otherwise the destructor will crash 1.767 + tex.pcData = NULL; 1.768 + 1.769 + // skip length of texture data 1.770 + szCurrent += iSkip; 1.771 + } 1.772 + } 1.773 + 1.774 + // check whether a material definition is contained in the skin 1.775 + if (iType & AI_MDL7_SKINTYPE_MATERIAL) 1.776 + { 1.777 + BE_NCONST MDL::Material_MDL7* pcMatIn = (BE_NCONST MDL::Material_MDL7*)szCurrent; 1.778 + szCurrent = (unsigned char*)(pcMatIn+1); 1.779 + } 1.780 + 1.781 + // if an ASCII effect description (HLSL?) is contained in the file, 1.782 + // we can simply ignore it ... 1.783 + if (iType & AI_MDL7_SKINTYPE_MATERIAL_ASCDEF) 1.784 + { 1.785 + int32_t iMe = *((int32_t*)szCurrent); 1.786 + AI_SWAP4(iMe); 1.787 + szCurrent += sizeof(char) * iMe + sizeof(int32_t); 1.788 + } 1.789 + *szCurrentOut = szCurrent; 1.790 +} 1.791 + 1.792 +// ------------------------------------------------------------------------------------------------ 1.793 +void MDLImporter::ParseSkinLump_3DGS_MDL7( 1.794 + const unsigned char* szCurrent, 1.795 + const unsigned char** szCurrentOut, 1.796 + std::vector<aiMaterial*>& pcMats) 1.797 +{ 1.798 + ai_assert(NULL != szCurrent); 1.799 + ai_assert(NULL != szCurrentOut); 1.800 + 1.801 + *szCurrentOut = szCurrent; 1.802 + BE_NCONST MDL::Skin_MDL7* pcSkin = (BE_NCONST MDL::Skin_MDL7*)szCurrent; 1.803 + AI_SWAP4(pcSkin->width); 1.804 + AI_SWAP4(pcSkin->height); 1.805 + szCurrent += 12; 1.806 + 1.807 + // allocate an output material 1.808 + aiMaterial* pcMatOut = new aiMaterial(); 1.809 + pcMats.push_back(pcMatOut); 1.810 + 1.811 + // skip length of file name 1.812 + szCurrent += AI_MDL7_MAX_TEXNAMESIZE; 1.813 + 1.814 + ParseSkinLump_3DGS_MDL7(szCurrent,szCurrentOut,pcMatOut, 1.815 + pcSkin->typ,pcSkin->width,pcSkin->height); 1.816 + 1.817 + // place the name of the skin in the material 1.818 + if (pcSkin->texture_name[0]) 1.819 + { 1.820 + // the 0 termination could be there or not - we can't know 1.821 + aiString szFile; 1.822 + ::memcpy(szFile.data,pcSkin->texture_name,sizeof(pcSkin->texture_name)); 1.823 + szFile.data[sizeof(pcSkin->texture_name)] = '\0'; 1.824 + szFile.length = ::strlen(szFile.data); 1.825 + 1.826 + pcMatOut->AddProperty(&szFile,AI_MATKEY_NAME); 1.827 + } 1.828 +} 1.829 + 1.830 +#endif // !! ASSIMP_BUILD_NO_MDL_IMPORTER