vrshoot

annotate 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
rev   line source
nuclear@0 1 /*
nuclear@0 2 ---------------------------------------------------------------------------
nuclear@0 3 Open Asset Import Library (assimp)
nuclear@0 4 ---------------------------------------------------------------------------
nuclear@0 5
nuclear@0 6 Copyright (c) 2006-2012, assimp team
nuclear@0 7
nuclear@0 8 All rights reserved.
nuclear@0 9
nuclear@0 10 Redistribution and use of this software in source and binary forms,
nuclear@0 11 with or without modification, are permitted provided that the following
nuclear@0 12 conditions are met:
nuclear@0 13
nuclear@0 14 * Redistributions of source code must retain the above
nuclear@0 15 copyright notice, this list of conditions and the
nuclear@0 16 following disclaimer.
nuclear@0 17
nuclear@0 18 * Redistributions in binary form must reproduce the above
nuclear@0 19 copyright notice, this list of conditions and the
nuclear@0 20 following disclaimer in the documentation and/or other
nuclear@0 21 materials provided with the distribution.
nuclear@0 22
nuclear@0 23 * Neither the name of the assimp team, nor the names of its
nuclear@0 24 contributors may be used to endorse or promote products
nuclear@0 25 derived from this software without specific prior
nuclear@0 26 written permission of the assimp team.
nuclear@0 27
nuclear@0 28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
nuclear@0 29 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
nuclear@0 30 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
nuclear@0 31 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
nuclear@0 32 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
nuclear@0 33 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
nuclear@0 34 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
nuclear@0 35 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
nuclear@0 36 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
nuclear@0 37 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
nuclear@0 38 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
nuclear@0 39 ---------------------------------------------------------------------------
nuclear@0 40 */
nuclear@0 41
nuclear@0 42 /** @file Implementation of the material part of the MDL importer class */
nuclear@0 43
nuclear@0 44 #include "AssimpPCH.h"
nuclear@0 45 #ifndef ASSIMP_BUILD_NO_MDL_IMPORTER
nuclear@0 46
nuclear@0 47 // internal headers
nuclear@0 48 #include "MDLLoader.h"
nuclear@0 49 #include "MDLDefaultColorMap.h"
nuclear@0 50
nuclear@0 51 using namespace Assimp;
nuclear@0 52 static aiTexel* const bad_texel = reinterpret_cast<aiTexel*>(SIZE_MAX);
nuclear@0 53
nuclear@0 54 // ------------------------------------------------------------------------------------------------
nuclear@0 55 // Find a suitable pallette file or take teh default one
nuclear@0 56 void MDLImporter::SearchPalette(const unsigned char** pszColorMap)
nuclear@0 57 {
nuclear@0 58 // now try to find the color map in the current directory
nuclear@0 59 IOStream* pcStream = pIOHandler->Open(configPalette,"rb");
nuclear@0 60
nuclear@0 61 const unsigned char* szColorMap = (const unsigned char*)::g_aclrDefaultColorMap;
nuclear@0 62 if(pcStream)
nuclear@0 63 {
nuclear@0 64 if (pcStream->FileSize() >= 768)
nuclear@0 65 {
nuclear@0 66 unsigned char* colorMap = new unsigned char[256*3];
nuclear@0 67 szColorMap = colorMap;
nuclear@0 68 pcStream->Read(colorMap,256*3,1);
nuclear@0 69 DefaultLogger::get()->info("Found valid colormap.lmp in directory. "
nuclear@0 70 "It will be used to decode embedded textures in palletized formats.");
nuclear@0 71 }
nuclear@0 72 delete pcStream;
nuclear@0 73 pcStream = NULL;
nuclear@0 74 }
nuclear@0 75 *pszColorMap = szColorMap;
nuclear@0 76 }
nuclear@0 77
nuclear@0 78 // ------------------------------------------------------------------------------------------------
nuclear@0 79 // Free the palette again
nuclear@0 80 void MDLImporter::FreePalette(const unsigned char* szColorMap)
nuclear@0 81 {
nuclear@0 82 if (szColorMap != (const unsigned char*)::g_aclrDefaultColorMap)
nuclear@0 83 delete[] szColorMap;
nuclear@0 84 }
nuclear@0 85
nuclear@0 86 // ------------------------------------------------------------------------------------------------
nuclear@0 87 // Check whether we can replace a texture with a single color
nuclear@0 88 aiColor4D MDLImporter::ReplaceTextureWithColor(const aiTexture* pcTexture)
nuclear@0 89 {
nuclear@0 90 ai_assert(NULL != pcTexture);
nuclear@0 91
nuclear@0 92 aiColor4D clrOut;
nuclear@0 93 clrOut.r = get_qnan();
nuclear@0 94 if (!pcTexture->mHeight || !pcTexture->mWidth)
nuclear@0 95 return clrOut;
nuclear@0 96
nuclear@0 97 const unsigned int iNumPixels = pcTexture->mHeight*pcTexture->mWidth;
nuclear@0 98 const aiTexel* pcTexel = pcTexture->pcData+1;
nuclear@0 99 const aiTexel* const pcTexelEnd = &pcTexture->pcData[iNumPixels];
nuclear@0 100
nuclear@0 101 while (pcTexel != pcTexelEnd)
nuclear@0 102 {
nuclear@0 103 if (*pcTexel != *(pcTexel-1))
nuclear@0 104 {
nuclear@0 105 pcTexel = NULL;
nuclear@0 106 break;
nuclear@0 107 }
nuclear@0 108 ++pcTexel;
nuclear@0 109 }
nuclear@0 110 if (pcTexel)
nuclear@0 111 {
nuclear@0 112 clrOut.r = pcTexture->pcData->r / 255.0f;
nuclear@0 113 clrOut.g = pcTexture->pcData->g / 255.0f;
nuclear@0 114 clrOut.b = pcTexture->pcData->b / 255.0f;
nuclear@0 115 clrOut.a = pcTexture->pcData->a / 255.0f;
nuclear@0 116 }
nuclear@0 117 return clrOut;
nuclear@0 118 }
nuclear@0 119
nuclear@0 120 // ------------------------------------------------------------------------------------------------
nuclear@0 121 // Read a texture from a MDL3 file
nuclear@0 122 void MDLImporter::CreateTextureARGB8_3DGS_MDL3(const unsigned char* szData)
nuclear@0 123 {
nuclear@0 124 const MDL::Header *pcHeader = (const MDL::Header*)mBuffer; //the endianess is allready corrected in the InternReadFile_3DGS_MDL345 function
nuclear@0 125
nuclear@0 126 VALIDATE_FILE_SIZE(szData + pcHeader->skinwidth *
nuclear@0 127 pcHeader->skinheight);
nuclear@0 128
nuclear@0 129 // allocate a new texture object
nuclear@0 130 aiTexture* pcNew = new aiTexture();
nuclear@0 131 pcNew->mWidth = pcHeader->skinwidth;
nuclear@0 132 pcNew->mHeight = pcHeader->skinheight;
nuclear@0 133
nuclear@0 134 pcNew->pcData = new aiTexel[pcNew->mWidth * pcNew->mHeight];
nuclear@0 135
nuclear@0 136 const unsigned char* szColorMap;
nuclear@0 137 this->SearchPalette(&szColorMap);
nuclear@0 138
nuclear@0 139 // copy texture data
nuclear@0 140 for (unsigned int i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
nuclear@0 141 {
nuclear@0 142 const unsigned char val = szData[i];
nuclear@0 143 const unsigned char* sz = &szColorMap[val*3];
nuclear@0 144
nuclear@0 145 pcNew->pcData[i].a = 0xFF;
nuclear@0 146 pcNew->pcData[i].r = *sz++;
nuclear@0 147 pcNew->pcData[i].g = *sz++;
nuclear@0 148 pcNew->pcData[i].b = *sz;
nuclear@0 149 }
nuclear@0 150
nuclear@0 151 FreePalette(szColorMap);
nuclear@0 152
nuclear@0 153 // store the texture
nuclear@0 154 aiTexture** pc = this->pScene->mTextures;
nuclear@0 155 this->pScene->mTextures = new aiTexture*[pScene->mNumTextures+1];
nuclear@0 156 for (unsigned int i = 0; i <pScene->mNumTextures;++i)
nuclear@0 157 pScene->mTextures[i] = pc[i];
nuclear@0 158
nuclear@0 159 pScene->mTextures[this->pScene->mNumTextures] = pcNew;
nuclear@0 160 pScene->mNumTextures++;
nuclear@0 161 delete[] pc;
nuclear@0 162 return;
nuclear@0 163 }
nuclear@0 164
nuclear@0 165 // ------------------------------------------------------------------------------------------------
nuclear@0 166 // Read a texture from a MDL4 file
nuclear@0 167 void MDLImporter::CreateTexture_3DGS_MDL4(const unsigned char* szData,
nuclear@0 168 unsigned int iType,
nuclear@0 169 unsigned int* piSkip)
nuclear@0 170 {
nuclear@0 171 ai_assert(NULL != piSkip);
nuclear@0 172
nuclear@0 173 const MDL::Header *pcHeader = (const MDL::Header*)mBuffer; //the endianess is allready corrected in the InternReadFile_3DGS_MDL345 function
nuclear@0 174
nuclear@0 175 if (iType == 1 || iType > 3)
nuclear@0 176 {
nuclear@0 177 DefaultLogger::get()->error("Unsupported texture file format");
nuclear@0 178 return;
nuclear@0 179 }
nuclear@0 180
nuclear@0 181 const bool bNoRead = *piSkip == UINT_MAX;
nuclear@0 182
nuclear@0 183 // allocate a new texture object
nuclear@0 184 aiTexture* pcNew = new aiTexture();
nuclear@0 185 pcNew->mWidth = pcHeader->skinwidth;
nuclear@0 186 pcNew->mHeight = pcHeader->skinheight;
nuclear@0 187
nuclear@0 188 if (bNoRead)pcNew->pcData = bad_texel;
nuclear@0 189 ParseTextureColorData(szData,iType,piSkip,pcNew);
nuclear@0 190
nuclear@0 191 // store the texture
nuclear@0 192 if (!bNoRead)
nuclear@0 193 {
nuclear@0 194 if (!this->pScene->mNumTextures)
nuclear@0 195 {
nuclear@0 196 pScene->mNumTextures = 1;
nuclear@0 197 pScene->mTextures = new aiTexture*[1];
nuclear@0 198 pScene->mTextures[0] = pcNew;
nuclear@0 199 }
nuclear@0 200 else
nuclear@0 201 {
nuclear@0 202 aiTexture** pc = pScene->mTextures;
nuclear@0 203 pScene->mTextures = new aiTexture*[pScene->mNumTextures+1];
nuclear@0 204 for (unsigned int i = 0; i < this->pScene->mNumTextures;++i)
nuclear@0 205 pScene->mTextures[i] = pc[i];
nuclear@0 206 pScene->mTextures[pScene->mNumTextures] = pcNew;
nuclear@0 207 pScene->mNumTextures++;
nuclear@0 208 delete[] pc;
nuclear@0 209 }
nuclear@0 210 }
nuclear@0 211 else {
nuclear@0 212 pcNew->pcData = NULL;
nuclear@0 213 delete pcNew;
nuclear@0 214 }
nuclear@0 215 return;
nuclear@0 216 }
nuclear@0 217
nuclear@0 218 // ------------------------------------------------------------------------------------------------
nuclear@0 219 // Load color data of a texture and convert it to our output format
nuclear@0 220 void MDLImporter::ParseTextureColorData(const unsigned char* szData,
nuclear@0 221 unsigned int iType,
nuclear@0 222 unsigned int* piSkip,
nuclear@0 223 aiTexture* pcNew)
nuclear@0 224 {
nuclear@0 225 const bool do_read = bad_texel != pcNew->pcData;
nuclear@0 226
nuclear@0 227 // allocate storage for the texture image
nuclear@0 228 if (do_read) {
nuclear@0 229 pcNew->pcData = new aiTexel[pcNew->mWidth * pcNew->mHeight];
nuclear@0 230 }
nuclear@0 231
nuclear@0 232 // R5G6B5 format (with or without MIPs)
nuclear@0 233 // ****************************************************************
nuclear@0 234 if (2 == iType || 10 == iType)
nuclear@0 235 {
nuclear@0 236 VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*2);
nuclear@0 237
nuclear@0 238 // copy texture data
nuclear@0 239 unsigned int i;
nuclear@0 240 if (do_read)
nuclear@0 241 {
nuclear@0 242 for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
nuclear@0 243 {
nuclear@0 244 MDL::RGB565 val = ((MDL::RGB565*)szData)[i];
nuclear@0 245 AI_SWAP2(val);
nuclear@0 246
nuclear@0 247 pcNew->pcData[i].a = 0xFF;
nuclear@0 248 pcNew->pcData[i].r = (unsigned char)val.b << 3;
nuclear@0 249 pcNew->pcData[i].g = (unsigned char)val.g << 2;
nuclear@0 250 pcNew->pcData[i].b = (unsigned char)val.r << 3;
nuclear@0 251 }
nuclear@0 252 }
nuclear@0 253 else i = pcNew->mWidth*pcNew->mHeight;
nuclear@0 254 *piSkip = i * 2;
nuclear@0 255
nuclear@0 256 // apply MIP maps
nuclear@0 257 if (10 == iType)
nuclear@0 258 {
nuclear@0 259 *piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 1;
nuclear@0 260 VALIDATE_FILE_SIZE(szData + *piSkip);
nuclear@0 261 }
nuclear@0 262 }
nuclear@0 263 // ARGB4 format (with or without MIPs)
nuclear@0 264 // ****************************************************************
nuclear@0 265 else if (3 == iType || 11 == iType)
nuclear@0 266 {
nuclear@0 267 VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*4);
nuclear@0 268
nuclear@0 269 // copy texture data
nuclear@0 270 unsigned int i;
nuclear@0 271 if (do_read)
nuclear@0 272 {
nuclear@0 273 for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
nuclear@0 274 {
nuclear@0 275 MDL::ARGB4 val = ((MDL::ARGB4*)szData)[i];
nuclear@0 276 AI_SWAP2(val);
nuclear@0 277
nuclear@0 278 pcNew->pcData[i].a = (unsigned char)val.a << 4;
nuclear@0 279 pcNew->pcData[i].r = (unsigned char)val.r << 4;
nuclear@0 280 pcNew->pcData[i].g = (unsigned char)val.g << 4;
nuclear@0 281 pcNew->pcData[i].b = (unsigned char)val.b << 4;
nuclear@0 282 }
nuclear@0 283 }
nuclear@0 284 else i = pcNew->mWidth*pcNew->mHeight;
nuclear@0 285 *piSkip = i * 2;
nuclear@0 286
nuclear@0 287 // apply MIP maps
nuclear@0 288 if (11 == iType)
nuclear@0 289 {
nuclear@0 290 *piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 1;
nuclear@0 291 VALIDATE_FILE_SIZE(szData + *piSkip);
nuclear@0 292 }
nuclear@0 293 }
nuclear@0 294 // RGB8 format (with or without MIPs)
nuclear@0 295 // ****************************************************************
nuclear@0 296 else if (4 == iType || 12 == iType)
nuclear@0 297 {
nuclear@0 298 VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*3);
nuclear@0 299
nuclear@0 300 // copy texture data
nuclear@0 301 unsigned int i;
nuclear@0 302 if (do_read)
nuclear@0 303 {
nuclear@0 304 for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
nuclear@0 305 {
nuclear@0 306 const unsigned char* _szData = &szData[i*3];
nuclear@0 307
nuclear@0 308 pcNew->pcData[i].a = 0xFF;
nuclear@0 309 pcNew->pcData[i].b = *_szData++;
nuclear@0 310 pcNew->pcData[i].g = *_szData++;
nuclear@0 311 pcNew->pcData[i].r = *_szData;
nuclear@0 312 }
nuclear@0 313 }
nuclear@0 314 else i = pcNew->mWidth*pcNew->mHeight;
nuclear@0 315
nuclear@0 316
nuclear@0 317 // apply MIP maps
nuclear@0 318 *piSkip = i * 3;
nuclear@0 319 if (12 == iType)
nuclear@0 320 {
nuclear@0 321 *piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) *3;
nuclear@0 322 VALIDATE_FILE_SIZE(szData + *piSkip);
nuclear@0 323 }
nuclear@0 324 }
nuclear@0 325 // ARGB8 format (with ir without MIPs)
nuclear@0 326 // ****************************************************************
nuclear@0 327 else if (5 == iType || 13 == iType)
nuclear@0 328 {
nuclear@0 329 VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*4);
nuclear@0 330
nuclear@0 331 // copy texture data
nuclear@0 332 unsigned int i;
nuclear@0 333 if (do_read)
nuclear@0 334 {
nuclear@0 335 for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
nuclear@0 336 {
nuclear@0 337 const unsigned char* _szData = &szData[i*4];
nuclear@0 338
nuclear@0 339 pcNew->pcData[i].b = *_szData++;
nuclear@0 340 pcNew->pcData[i].g = *_szData++;
nuclear@0 341 pcNew->pcData[i].r = *_szData++;
nuclear@0 342 pcNew->pcData[i].a = *_szData;
nuclear@0 343 }
nuclear@0 344 }
nuclear@0 345 else i = pcNew->mWidth*pcNew->mHeight;
nuclear@0 346
nuclear@0 347 // apply MIP maps
nuclear@0 348 *piSkip = i << 2;
nuclear@0 349 if (13 == iType)
nuclear@0 350 {
nuclear@0 351 *piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 2;
nuclear@0 352 }
nuclear@0 353 }
nuclear@0 354 // palletized 8 bit texture. As for Quake 1
nuclear@0 355 // ****************************************************************
nuclear@0 356 else if (0 == iType)
nuclear@0 357 {
nuclear@0 358 VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight);
nuclear@0 359
nuclear@0 360 // copy texture data
nuclear@0 361 unsigned int i;
nuclear@0 362 if (do_read)
nuclear@0 363 {
nuclear@0 364
nuclear@0 365 const unsigned char* szColorMap;
nuclear@0 366 SearchPalette(&szColorMap);
nuclear@0 367
nuclear@0 368 for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
nuclear@0 369 {
nuclear@0 370 const unsigned char val = szData[i];
nuclear@0 371 const unsigned char* sz = &szColorMap[val*3];
nuclear@0 372
nuclear@0 373 pcNew->pcData[i].a = 0xFF;
nuclear@0 374 pcNew->pcData[i].r = *sz++;
nuclear@0 375 pcNew->pcData[i].g = *sz++;
nuclear@0 376 pcNew->pcData[i].b = *sz;
nuclear@0 377 }
nuclear@0 378 this->FreePalette(szColorMap);
nuclear@0 379
nuclear@0 380 }
nuclear@0 381 else i = pcNew->mWidth*pcNew->mHeight;
nuclear@0 382 *piSkip = i;
nuclear@0 383
nuclear@0 384 // FIXME: Also support for MIP maps?
nuclear@0 385 }
nuclear@0 386 }
nuclear@0 387
nuclear@0 388 // ------------------------------------------------------------------------------------------------
nuclear@0 389 // Get a texture from a MDL5 file
nuclear@0 390 void MDLImporter::CreateTexture_3DGS_MDL5(const unsigned char* szData,
nuclear@0 391 unsigned int iType,
nuclear@0 392 unsigned int* piSkip)
nuclear@0 393 {
nuclear@0 394 ai_assert(NULL != piSkip);
nuclear@0 395 bool bNoRead = *piSkip == UINT_MAX;
nuclear@0 396
nuclear@0 397 // allocate a new texture object
nuclear@0 398 aiTexture* pcNew = new aiTexture();
nuclear@0 399
nuclear@0 400 VALIDATE_FILE_SIZE(szData+8);
nuclear@0 401
nuclear@0 402 // first read the size of the texture
nuclear@0 403 pcNew->mWidth = *((uint32_t*)szData);
nuclear@0 404 AI_SWAP4(pcNew->mWidth);
nuclear@0 405 szData += sizeof(uint32_t);
nuclear@0 406
nuclear@0 407 pcNew->mHeight = *((uint32_t*)szData);
nuclear@0 408 AI_SWAP4(pcNew->mHeight);
nuclear@0 409 szData += sizeof(uint32_t);
nuclear@0 410
nuclear@0 411 if (bNoRead) {
nuclear@0 412 pcNew->pcData = bad_texel;
nuclear@0 413 }
nuclear@0 414
nuclear@0 415 // this should not occur - at least the docs say it shouldn't.
nuclear@0 416 // however, one can easily try out what MED does if you have
nuclear@0 417 // a model with a DDS texture and export it to MDL5 ...
nuclear@0 418 // yeah, it embedds the DDS file.
nuclear@0 419 if (6 == iType)
nuclear@0 420 {
nuclear@0 421 // this is a compressed texture in DDS format
nuclear@0 422 *piSkip = pcNew->mWidth;
nuclear@0 423 VALIDATE_FILE_SIZE(szData + *piSkip);
nuclear@0 424
nuclear@0 425 if (!bNoRead)
nuclear@0 426 {
nuclear@0 427 // place a hint and let the application know that this is a DDS file
nuclear@0 428 pcNew->mHeight = 0;
nuclear@0 429 pcNew->achFormatHint[0] = 'd';
nuclear@0 430 pcNew->achFormatHint[1] = 'd';
nuclear@0 431 pcNew->achFormatHint[2] = 's';
nuclear@0 432 pcNew->achFormatHint[3] = '\0';
nuclear@0 433
nuclear@0 434 pcNew->pcData = (aiTexel*) new unsigned char[pcNew->mWidth];
nuclear@0 435 ::memcpy(pcNew->pcData,szData,pcNew->mWidth);
nuclear@0 436 }
nuclear@0 437 }
nuclear@0 438 else
nuclear@0 439 {
nuclear@0 440 // parse the color data of the texture
nuclear@0 441 ParseTextureColorData(szData,iType,piSkip,pcNew);
nuclear@0 442 }
nuclear@0 443 *piSkip += sizeof(uint32_t) * 2;
nuclear@0 444
nuclear@0 445 if (!bNoRead)
nuclear@0 446 {
nuclear@0 447 // store the texture
nuclear@0 448 if (!this->pScene->mNumTextures)
nuclear@0 449 {
nuclear@0 450 pScene->mNumTextures = 1;
nuclear@0 451 pScene->mTextures = new aiTexture*[1];
nuclear@0 452 pScene->mTextures[0] = pcNew;
nuclear@0 453 }
nuclear@0 454 else
nuclear@0 455 {
nuclear@0 456 aiTexture** pc = pScene->mTextures;
nuclear@0 457 pScene->mTextures = new aiTexture*[pScene->mNumTextures+1];
nuclear@0 458 for (unsigned int i = 0; i < pScene->mNumTextures;++i)
nuclear@0 459 this->pScene->mTextures[i] = pc[i];
nuclear@0 460
nuclear@0 461 pScene->mTextures[pScene->mNumTextures] = pcNew;
nuclear@0 462 pScene->mNumTextures++;
nuclear@0 463 delete[] pc;
nuclear@0 464 }
nuclear@0 465 }
nuclear@0 466 else {
nuclear@0 467 pcNew->pcData = NULL;
nuclear@0 468 delete pcNew;
nuclear@0 469 }
nuclear@0 470 return;
nuclear@0 471 }
nuclear@0 472
nuclear@0 473 // ------------------------------------------------------------------------------------------------
nuclear@0 474 // Get a skin from a MDL7 file - more complex than all other subformats
nuclear@0 475 void MDLImporter::ParseSkinLump_3DGS_MDL7(
nuclear@0 476 const unsigned char* szCurrent,
nuclear@0 477 const unsigned char** szCurrentOut,
nuclear@0 478 aiMaterial* pcMatOut,
nuclear@0 479 unsigned int iType,
nuclear@0 480 unsigned int iWidth,
nuclear@0 481 unsigned int iHeight)
nuclear@0 482 {
nuclear@0 483 aiTexture* pcNew = NULL;
nuclear@0 484
nuclear@0 485 // get the type of the skin
nuclear@0 486 unsigned int iMasked = (unsigned int)(iType & 0xF);
nuclear@0 487
nuclear@0 488 if (0x1 == iMasked)
nuclear@0 489 {
nuclear@0 490 // ***** REFERENCE TO ANOTHER SKIN INDEX *****
nuclear@0 491 int referrer = (int)iWidth;
nuclear@0 492 pcMatOut->AddProperty<int>(&referrer,1,AI_MDL7_REFERRER_MATERIAL);
nuclear@0 493 }
nuclear@0 494 else if (0x6 == iMasked)
nuclear@0 495 {
nuclear@0 496 // ***** EMBEDDED DDS FILE *****
nuclear@0 497 if (1 != iHeight)
nuclear@0 498 {
nuclear@0 499 DefaultLogger::get()->warn("Found a reference to an embedded DDS texture, "
nuclear@0 500 "but texture height is not equal to 1, which is not supported by MED");
nuclear@0 501 }
nuclear@0 502
nuclear@0 503 pcNew = new aiTexture();
nuclear@0 504 pcNew->mHeight = 0;
nuclear@0 505 pcNew->mWidth = iWidth;
nuclear@0 506
nuclear@0 507 // place a proper format hint
nuclear@0 508 pcNew->achFormatHint[0] = 'd';
nuclear@0 509 pcNew->achFormatHint[1] = 'd';
nuclear@0 510 pcNew->achFormatHint[2] = 's';
nuclear@0 511 pcNew->achFormatHint[3] = '\0';
nuclear@0 512
nuclear@0 513 pcNew->pcData = (aiTexel*) new unsigned char[pcNew->mWidth];
nuclear@0 514 memcpy(pcNew->pcData,szCurrent,pcNew->mWidth);
nuclear@0 515 szCurrent += iWidth;
nuclear@0 516 }
nuclear@0 517 if (0x7 == iMasked)
nuclear@0 518 {
nuclear@0 519 // ***** REFERENCE TO EXTERNAL FILE *****
nuclear@0 520 if (1 != iHeight)
nuclear@0 521 {
nuclear@0 522 DefaultLogger::get()->warn("Found a reference to an external texture, "
nuclear@0 523 "but texture height is not equal to 1, which is not supported by MED");
nuclear@0 524 }
nuclear@0 525
nuclear@0 526 aiString szFile;
nuclear@0 527 const size_t iLen = strlen((const char*)szCurrent);
nuclear@0 528 size_t iLen2 = iLen+1;
nuclear@0 529 iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2;
nuclear@0 530 memcpy(szFile.data,(const char*)szCurrent,iLen2);
nuclear@0 531 szFile.length = iLen;
nuclear@0 532
nuclear@0 533 szCurrent += iLen2;
nuclear@0 534
nuclear@0 535 // place this as diffuse texture
nuclear@0 536 pcMatOut->AddProperty(&szFile,AI_MATKEY_TEXTURE_DIFFUSE(0));
nuclear@0 537 }
nuclear@0 538 else if (iMasked || !iType || (iType && iWidth && iHeight))
nuclear@0 539 {
nuclear@0 540 // ***** STANDARD COLOR TEXTURE *****
nuclear@0 541 pcNew = new aiTexture();
nuclear@0 542 if (!iHeight || !iWidth)
nuclear@0 543 {
nuclear@0 544 DefaultLogger::get()->warn("Found embedded texture, but its width "
nuclear@0 545 "an height are both 0. Is this a joke?");
nuclear@0 546
nuclear@0 547 // generate an empty chess pattern
nuclear@0 548 pcNew->mWidth = pcNew->mHeight = 8;
nuclear@0 549 pcNew->pcData = new aiTexel[64];
nuclear@0 550 for (unsigned int x = 0; x < 8;++x)
nuclear@0 551 {
nuclear@0 552 for (unsigned int y = 0; y < 8;++y)
nuclear@0 553 {
nuclear@0 554 const bool bSet = ((0 == x % 2 && 0 != y % 2) ||
nuclear@0 555 (0 != x % 2 && 0 == y % 2));
nuclear@0 556
nuclear@0 557 aiTexel* pc = &pcNew->pcData[y * 8 + x];
nuclear@0 558 pc->r = pc->b = pc->g = (bSet?0xFF:0);
nuclear@0 559 pc->a = 0xFF;
nuclear@0 560 }
nuclear@0 561 }
nuclear@0 562 }
nuclear@0 563 else
nuclear@0 564 {
nuclear@0 565 // it is a standard color texture. Fill in width and height
nuclear@0 566 // and call the same function we used for loading MDL5 files
nuclear@0 567
nuclear@0 568 pcNew->mWidth = iWidth;
nuclear@0 569 pcNew->mHeight = iHeight;
nuclear@0 570
nuclear@0 571 unsigned int iSkip = 0;
nuclear@0 572 ParseTextureColorData(szCurrent,iMasked,&iSkip,pcNew);
nuclear@0 573
nuclear@0 574 // skip length of texture data
nuclear@0 575 szCurrent += iSkip;
nuclear@0 576 }
nuclear@0 577 }
nuclear@0 578
nuclear@0 579 // sometimes there are MDL7 files which have a monochrome
nuclear@0 580 // texture instead of material colors ... posssible they have
nuclear@0 581 // been converted to MDL7 from other formats, such as MDL5
nuclear@0 582 aiColor4D clrTexture;
nuclear@0 583 if (pcNew)clrTexture = ReplaceTextureWithColor(pcNew);
nuclear@0 584 else clrTexture.r = get_qnan();
nuclear@0 585
nuclear@0 586 // check whether a material definition is contained in the skin
nuclear@0 587 if (iType & AI_MDL7_SKINTYPE_MATERIAL)
nuclear@0 588 {
nuclear@0 589 BE_NCONST MDL::Material_MDL7* pcMatIn = (BE_NCONST MDL::Material_MDL7*)szCurrent;
nuclear@0 590 szCurrent = (unsigned char*)(pcMatIn+1);
nuclear@0 591 VALIDATE_FILE_SIZE(szCurrent);
nuclear@0 592
nuclear@0 593 aiColor3D clrTemp;
nuclear@0 594
nuclear@0 595 #define COLOR_MULTIPLY_RGB() \
nuclear@0 596 if (is_not_qnan(clrTexture.r)) \
nuclear@0 597 { \
nuclear@0 598 clrTemp.r *= clrTexture.r; \
nuclear@0 599 clrTemp.g *= clrTexture.g; \
nuclear@0 600 clrTemp.b *= clrTexture.b; \
nuclear@0 601 }
nuclear@0 602
nuclear@0 603 // read diffuse color
nuclear@0 604 clrTemp.r = pcMatIn->Diffuse.r;
nuclear@0 605 AI_SWAP4(clrTemp.r);
nuclear@0 606 clrTemp.g = pcMatIn->Diffuse.g;
nuclear@0 607 AI_SWAP4(clrTemp.g);
nuclear@0 608 clrTemp.b = pcMatIn->Diffuse.b;
nuclear@0 609 AI_SWAP4(clrTemp.b);
nuclear@0 610 COLOR_MULTIPLY_RGB();
nuclear@0 611 pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_DIFFUSE);
nuclear@0 612
nuclear@0 613 // read specular color
nuclear@0 614 clrTemp.r = pcMatIn->Specular.r;
nuclear@0 615 AI_SWAP4(clrTemp.r);
nuclear@0 616 clrTemp.g = pcMatIn->Specular.g;
nuclear@0 617 AI_SWAP4(clrTemp.g);
nuclear@0 618 clrTemp.b = pcMatIn->Specular.b;
nuclear@0 619 AI_SWAP4(clrTemp.b);
nuclear@0 620 COLOR_MULTIPLY_RGB();
nuclear@0 621 pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_SPECULAR);
nuclear@0 622
nuclear@0 623 // read ambient color
nuclear@0 624 clrTemp.r = pcMatIn->Ambient.r;
nuclear@0 625 AI_SWAP4(clrTemp.r);
nuclear@0 626 clrTemp.g = pcMatIn->Ambient.g;
nuclear@0 627 AI_SWAP4(clrTemp.g);
nuclear@0 628 clrTemp.b = pcMatIn->Ambient.b;
nuclear@0 629 AI_SWAP4(clrTemp.b);
nuclear@0 630 COLOR_MULTIPLY_RGB();
nuclear@0 631 pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_AMBIENT);
nuclear@0 632
nuclear@0 633 // read emissive color
nuclear@0 634 clrTemp.r = pcMatIn->Emissive.r;
nuclear@0 635 AI_SWAP4(clrTemp.r);
nuclear@0 636 clrTemp.g = pcMatIn->Emissive.g;
nuclear@0 637 AI_SWAP4(clrTemp.g);
nuclear@0 638 clrTemp.b = pcMatIn->Emissive.b;
nuclear@0 639 AI_SWAP4(clrTemp.b);
nuclear@0 640 pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_EMISSIVE);
nuclear@0 641
nuclear@0 642 #undef COLOR_MULITPLY_RGB
nuclear@0 643
nuclear@0 644 // FIX: Take the opacity from the ambient color.
nuclear@0 645 // The doc say something else, but it is fact that MED exports the
nuclear@0 646 // opacity like this .... oh well.
nuclear@0 647 clrTemp.r = pcMatIn->Ambient.a;
nuclear@0 648 AI_SWAP4(clrTemp.r);
nuclear@0 649 if (is_not_qnan(clrTexture.r)) {
nuclear@0 650 clrTemp.r *= clrTexture.a;
nuclear@0 651 }
nuclear@0 652 pcMatOut->AddProperty<float>(&clrTemp.r,1,AI_MATKEY_OPACITY);
nuclear@0 653
nuclear@0 654 // read phong power
nuclear@0 655 int iShadingMode = (int)aiShadingMode_Gouraud;
nuclear@0 656 AI_SWAP4(pcMatIn->Power);
nuclear@0 657 if (0.0f != pcMatIn->Power)
nuclear@0 658 {
nuclear@0 659 iShadingMode = (int)aiShadingMode_Phong;
nuclear@0 660 pcMatOut->AddProperty<float>(&pcMatIn->Power,1,AI_MATKEY_SHININESS);
nuclear@0 661 }
nuclear@0 662 pcMatOut->AddProperty<int>(&iShadingMode,1,AI_MATKEY_SHADING_MODEL);
nuclear@0 663 }
nuclear@0 664 else if (is_not_qnan(clrTexture.r))
nuclear@0 665 {
nuclear@0 666 pcMatOut->AddProperty<aiColor4D>(&clrTexture,1,AI_MATKEY_COLOR_DIFFUSE);
nuclear@0 667 pcMatOut->AddProperty<aiColor4D>(&clrTexture,1,AI_MATKEY_COLOR_SPECULAR);
nuclear@0 668 }
nuclear@0 669 // if the texture could be replaced by a single material color
nuclear@0 670 // we don't need the texture anymore
nuclear@0 671 if (is_not_qnan(clrTexture.r))
nuclear@0 672 {
nuclear@0 673 delete pcNew;
nuclear@0 674 pcNew = NULL;
nuclear@0 675 }
nuclear@0 676
nuclear@0 677 // If an ASCII effect description (HLSL?) is contained in the file,
nuclear@0 678 // we can simply ignore it ...
nuclear@0 679 if (iType & AI_MDL7_SKINTYPE_MATERIAL_ASCDEF)
nuclear@0 680 {
nuclear@0 681 VALIDATE_FILE_SIZE(szCurrent);
nuclear@0 682 int32_t iMe = *((int32_t*)szCurrent);
nuclear@0 683 AI_SWAP4(iMe);
nuclear@0 684 szCurrent += sizeof(char) * iMe + sizeof(int32_t);
nuclear@0 685 VALIDATE_FILE_SIZE(szCurrent);
nuclear@0 686 }
nuclear@0 687
nuclear@0 688 // If an embedded texture has been loaded setup the corresponding
nuclear@0 689 // data structures in the aiScene instance
nuclear@0 690 if (pcNew && pScene->mNumTextures <= 999)
nuclear@0 691 {
nuclear@0 692
nuclear@0 693 // place this as diffuse texture
nuclear@0 694 char szCurrent[5];
nuclear@0 695 ::sprintf(szCurrent,"*%i",this->pScene->mNumTextures);
nuclear@0 696
nuclear@0 697 aiString szFile;
nuclear@0 698 const size_t iLen = strlen((const char*)szCurrent);
nuclear@0 699 ::memcpy(szFile.data,(const char*)szCurrent,iLen+1);
nuclear@0 700 szFile.length = iLen;
nuclear@0 701
nuclear@0 702 pcMatOut->AddProperty(&szFile,AI_MATKEY_TEXTURE_DIFFUSE(0));
nuclear@0 703
nuclear@0 704 // store the texture
nuclear@0 705 if (!pScene->mNumTextures)
nuclear@0 706 {
nuclear@0 707 pScene->mNumTextures = 1;
nuclear@0 708 pScene->mTextures = new aiTexture*[1];
nuclear@0 709 pScene->mTextures[0] = pcNew;
nuclear@0 710 }
nuclear@0 711 else
nuclear@0 712 {
nuclear@0 713 aiTexture** pc = pScene->mTextures;
nuclear@0 714 pScene->mTextures = new aiTexture*[pScene->mNumTextures+1];
nuclear@0 715 for (unsigned int i = 0; i < pScene->mNumTextures;++i) {
nuclear@0 716 pScene->mTextures[i] = pc[i];
nuclear@0 717 }
nuclear@0 718
nuclear@0 719 pScene->mTextures[pScene->mNumTextures] = pcNew;
nuclear@0 720 pScene->mNumTextures++;
nuclear@0 721 delete[] pc;
nuclear@0 722 }
nuclear@0 723 }
nuclear@0 724 VALIDATE_FILE_SIZE(szCurrent);
nuclear@0 725 *szCurrentOut = szCurrent;
nuclear@0 726 }
nuclear@0 727
nuclear@0 728 // ------------------------------------------------------------------------------------------------
nuclear@0 729 // Skip a skin lump
nuclear@0 730 void MDLImporter::SkipSkinLump_3DGS_MDL7(
nuclear@0 731 const unsigned char* szCurrent,
nuclear@0 732 const unsigned char** szCurrentOut,
nuclear@0 733 unsigned int iType,
nuclear@0 734 unsigned int iWidth,
nuclear@0 735 unsigned int iHeight)
nuclear@0 736 {
nuclear@0 737 // get the type of the skin
nuclear@0 738 const unsigned int iMasked = (unsigned int)(iType & 0xF);
nuclear@0 739
nuclear@0 740 if (0x6 == iMasked)
nuclear@0 741 {
nuclear@0 742 szCurrent += iWidth;
nuclear@0 743 }
nuclear@0 744 if (0x7 == iMasked)
nuclear@0 745 {
nuclear@0 746 const size_t iLen = ::strlen((const char*)szCurrent);
nuclear@0 747 szCurrent += iLen+1;
nuclear@0 748 }
nuclear@0 749 else if (iMasked || !iType)
nuclear@0 750 {
nuclear@0 751 if (iMasked || !iType || (iType && iWidth && iHeight))
nuclear@0 752 {
nuclear@0 753 // ParseTextureColorData(..., aiTexture::pcData == bad_texel) will simply
nuclear@0 754 // return the size of the color data in bytes in iSkip
nuclear@0 755 unsigned int iSkip = 0;
nuclear@0 756
nuclear@0 757 aiTexture tex;
nuclear@0 758 tex.pcData = bad_texel;
nuclear@0 759 tex.mHeight = iHeight;
nuclear@0 760 tex.mWidth = iWidth;
nuclear@0 761 ParseTextureColorData(szCurrent,iMasked,&iSkip,&tex);
nuclear@0 762
nuclear@0 763 // FIX: Important, otherwise the destructor will crash
nuclear@0 764 tex.pcData = NULL;
nuclear@0 765
nuclear@0 766 // skip length of texture data
nuclear@0 767 szCurrent += iSkip;
nuclear@0 768 }
nuclear@0 769 }
nuclear@0 770
nuclear@0 771 // check whether a material definition is contained in the skin
nuclear@0 772 if (iType & AI_MDL7_SKINTYPE_MATERIAL)
nuclear@0 773 {
nuclear@0 774 BE_NCONST MDL::Material_MDL7* pcMatIn = (BE_NCONST MDL::Material_MDL7*)szCurrent;
nuclear@0 775 szCurrent = (unsigned char*)(pcMatIn+1);
nuclear@0 776 }
nuclear@0 777
nuclear@0 778 // if an ASCII effect description (HLSL?) is contained in the file,
nuclear@0 779 // we can simply ignore it ...
nuclear@0 780 if (iType & AI_MDL7_SKINTYPE_MATERIAL_ASCDEF)
nuclear@0 781 {
nuclear@0 782 int32_t iMe = *((int32_t*)szCurrent);
nuclear@0 783 AI_SWAP4(iMe);
nuclear@0 784 szCurrent += sizeof(char) * iMe + sizeof(int32_t);
nuclear@0 785 }
nuclear@0 786 *szCurrentOut = szCurrent;
nuclear@0 787 }
nuclear@0 788
nuclear@0 789 // ------------------------------------------------------------------------------------------------
nuclear@0 790 void MDLImporter::ParseSkinLump_3DGS_MDL7(
nuclear@0 791 const unsigned char* szCurrent,
nuclear@0 792 const unsigned char** szCurrentOut,
nuclear@0 793 std::vector<aiMaterial*>& pcMats)
nuclear@0 794 {
nuclear@0 795 ai_assert(NULL != szCurrent);
nuclear@0 796 ai_assert(NULL != szCurrentOut);
nuclear@0 797
nuclear@0 798 *szCurrentOut = szCurrent;
nuclear@0 799 BE_NCONST MDL::Skin_MDL7* pcSkin = (BE_NCONST MDL::Skin_MDL7*)szCurrent;
nuclear@0 800 AI_SWAP4(pcSkin->width);
nuclear@0 801 AI_SWAP4(pcSkin->height);
nuclear@0 802 szCurrent += 12;
nuclear@0 803
nuclear@0 804 // allocate an output material
nuclear@0 805 aiMaterial* pcMatOut = new aiMaterial();
nuclear@0 806 pcMats.push_back(pcMatOut);
nuclear@0 807
nuclear@0 808 // skip length of file name
nuclear@0 809 szCurrent += AI_MDL7_MAX_TEXNAMESIZE;
nuclear@0 810
nuclear@0 811 ParseSkinLump_3DGS_MDL7(szCurrent,szCurrentOut,pcMatOut,
nuclear@0 812 pcSkin->typ,pcSkin->width,pcSkin->height);
nuclear@0 813
nuclear@0 814 // place the name of the skin in the material
nuclear@0 815 if (pcSkin->texture_name[0])
nuclear@0 816 {
nuclear@0 817 // the 0 termination could be there or not - we can't know
nuclear@0 818 aiString szFile;
nuclear@0 819 ::memcpy(szFile.data,pcSkin->texture_name,sizeof(pcSkin->texture_name));
nuclear@0 820 szFile.data[sizeof(pcSkin->texture_name)] = '\0';
nuclear@0 821 szFile.length = ::strlen(szFile.data);
nuclear@0 822
nuclear@0 823 pcMatOut->AddProperty(&szFile,AI_MATKEY_NAME);
nuclear@0 824 }
nuclear@0 825 }
nuclear@0 826
nuclear@0 827 #endif // !! ASSIMP_BUILD_NO_MDL_IMPORTER