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