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