| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856 |
- /*
- ---------------------------------------------------------------------------
- Open Asset Import Library (ASSIMP)
- ---------------------------------------------------------------------------
- Copyright (c) 2006-2008, ASSIMP Development Team
- All rights reserved.
- Redistribution and use of this software in source and binary forms,
- with or without modification, are permitted provided that the following
- conditions are met:
- * Redistributions of source code must retain the above
- copyright notice, this list of conditions and the
- following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the
- following disclaimer in the documentation and/or other
- materials provided with the distribution.
- * Neither the name of the ASSIMP team, nor the names of its
- contributors may be used to endorse or promote products
- derived from this software without specific prior
- written permission of the ASSIMP Development Team.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- ---------------------------------------------------------------------------
- */
- /** @file Implementation of the MDL importer class */
- #include "MaterialSystem.h"
- #include "MDLLoader.h"
- #include "MDLDefaultColorMap.h"
- #include "../include/DefaultLogger.h"
- #include "../include/IOStream.h"
- #include "../include/IOSystem.h"
- #include "../include/aiMesh.h"
- #include "../include/aiScene.h"
- #include "../include/aiAssert.h"
- #include <boost/scoped_ptr.hpp>
- using namespace Assimp;
- extern float g_avNormals[162][3];
- // ------------------------------------------------------------------------------------------------
- inline bool is_qnan(float p_fIn)
- {
- // NOTE: Comparison against qnan is generally problematic
- // because qnan == qnan is false AFAIK
- union FTOINT
- {
- float fFloat;
- int32_t iInt;
- } one, two;
- one.fFloat = std::numeric_limits<float>::quiet_NaN();
- two.fFloat = p_fIn;
- return (one.iInt == two.iInt);
- }
- // ------------------------------------------------------------------------------------------------
- inline bool is_not_qnan(float p_fIn)
- {
- return !is_qnan(p_fIn);
- }
- // ------------------------------------------------------------------------------------------------
- // Constructor to be privately used by Importer
- MDLImporter::MDLImporter()
- {
- // nothing to do here
- }
- // ------------------------------------------------------------------------------------------------
- // Destructor, private as well
- MDLImporter::~MDLImporter()
- {
- // nothing to do here
- }
- // ------------------------------------------------------------------------------------------------
- // Returns whether the class can handle the format of the given file.
- bool MDLImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
- {
- // simple check of file extension is enough for the moment
- std::string::size_type pos = pFile.find_last_of('.');
- // no file extension - can't read
- if( pos == std::string::npos)
- return false;
- std::string extension = pFile.substr( pos);
- if (extension.length() < 4)return false;
- if (extension[0] != '.')return false;
- if (extension[1] != 'm' && extension[1] != 'M')return false;
- if (extension[2] != 'd' && extension[2] != 'D')return false;
- if (extension[3] != 'l' && extension[3] != 'L')return false;
- return true;
- }
- // ------------------------------------------------------------------------------------------------
- // Imports the given file into the given scene structure.
- void MDLImporter::InternReadFile(
- const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
- {
- boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
- // Check whether we can read from the file
- if( file.get() == NULL)
- {
- throw new ImportErrorException( "Failed to open MDL file " + pFile + ".");
- }
- // check whether the ply file is large enough to contain
- // at least the file header
- size_t fileSize = file->FileSize();
- if( fileSize < sizeof(MDL::Header))
- {
- throw new ImportErrorException( ".mdl File is too small.");
- }
- // allocate storage and copy the contents of the file to a memory buffer
- this->pScene = pScene;
- this->pIOHandler = pIOHandler;
- this->mBuffer = new unsigned char[fileSize+1];
- file->Read( (void*)mBuffer, 1, fileSize);
- // determine the file subtype and call the appropriate member function
- // Original Quake1 format
- this->m_pcHeader = (const MDL::Header*)this->mBuffer;
- if (AI_MDL_MAGIC_NUMBER_BE == this->m_pcHeader->ident ||
- AI_MDL_MAGIC_NUMBER_LE == this->m_pcHeader->ident)
- {
- DefaultLogger::get()->debug("MDL subtype: Quake 1, magic word is IDPO");
- this->InternReadFile_Quake1();
- }
- // GameStudio A4 MDL3 format
- else if (AI_MDL_MAGIC_NUMBER_BE_GS4 == this->m_pcHeader->ident ||
- AI_MDL_MAGIC_NUMBER_LE_GS4 == this->m_pcHeader->ident)
- {
- DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A4, magic word is MDL3");
- this->iGSFileVersion = 3;
- this->InternReadFile_GameStudio();
- }
- // GameStudio A5+ MDL4 format
- else if (AI_MDL_MAGIC_NUMBER_BE_GS5a == this->m_pcHeader->ident ||
- AI_MDL_MAGIC_NUMBER_LE_GS5a == this->m_pcHeader->ident)
- {
- DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A4, magic word is MDL4");
- this->iGSFileVersion = 4;
- this->InternReadFile_GameStudio();
- }
- // GameStudio A5+ MDL5 format
- else if (AI_MDL_MAGIC_NUMBER_BE_GS5b == this->m_pcHeader->ident ||
- AI_MDL_MAGIC_NUMBER_LE_GS5b == this->m_pcHeader->ident)
- {
- DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A5, magic word is MDL5");
- this->iGSFileVersion = 5;
- this->InternReadFile_GameStudio();
- }
- // GameStudio A6+ MDL6 format
- else if (AI_MDL_MAGIC_NUMBER_BE_GS6 == this->m_pcHeader->ident ||
- AI_MDL_MAGIC_NUMBER_LE_GS6 == this->m_pcHeader->ident)
- {
- DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A6, magic word is MDL6");
- this->iGSFileVersion = 6;
- this->InternReadFile_GameStudio();
- }
- // GameStudio A7 MDL7 format
- else if (AI_MDL_MAGIC_NUMBER_BE_GS7 == this->m_pcHeader->ident ||
- AI_MDL_MAGIC_NUMBER_LE_GS7 == this->m_pcHeader->ident)
- {
- DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A7, magic word is MDL7");
- this->iGSFileVersion = 7;
- this->InternReadFile_GameStudioA7();
- }
- // IDST/IDSQ Format (CS:S/HL², etc ...)
- else if (AI_MDL_MAGIC_NUMBER_BE_HL2a == this->m_pcHeader->ident ||
- AI_MDL_MAGIC_NUMBER_LE_HL2a == this->m_pcHeader->ident ||
- AI_MDL_MAGIC_NUMBER_BE_HL2b == this->m_pcHeader->ident ||
- AI_MDL_MAGIC_NUMBER_LE_HL2b == this->m_pcHeader->ident)
- {
- DefaultLogger::get()->debug("MDL subtype: CS:S\\HL², magic word is IDST/IDSQ");
- this->InternReadFile_HL2();
- }
- else
- {
- // we're definitely unable to load this file
- throw new ImportErrorException( "Unknown MDL subformat " + pFile +
- ". Magic word is not known");
- }
- // make sure that the normals are facing outwards
- for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
- this->FlipNormals(pScene->mMeshes[i]);
- // delete the file buffer
- delete[] this->mBuffer;
- return;
- }
- // ------------------------------------------------------------------------------------------------
- void MDLImporter::SearchPalette(const unsigned char** pszColorMap)
- {
- // now try to find the color map in the current directory
- IOStream* pcStream = this->pIOHandler->Open("colormap.lmp","rb");
- const unsigned char* szColorMap = (const unsigned char*)::g_aclrDefaultColorMap;
- if(pcStream)
- {
- if (pcStream->FileSize() >= 768)
- {
- szColorMap = new unsigned char[256*3];
- pcStream->Read(const_cast<unsigned char*>(szColorMap),256*3,1);
- DefaultLogger::get()->info("Found valid colormap.lmp in directory. "
- "It will be used to decode embedded textures in palletized formats.");
- }
- delete pcStream;
- pcStream = NULL;
- }
- *pszColorMap = szColorMap;
- return;
- }
- // ------------------------------------------------------------------------------------------------
- void MDLImporter::FreePalette(const unsigned char* szColorMap)
- {
- if (szColorMap != (const unsigned char*)::g_aclrDefaultColorMap)
- {
- delete[] szColorMap;
- }
- return;
- }
- // ------------------------------------------------------------------------------------------------
- void MDLImporter::CreateTextureARGB8(const unsigned char* szData)
- {
- // allocate a new texture object
- aiTexture* pcNew = new aiTexture();
- pcNew->mWidth = this->m_pcHeader->skinwidth;
- pcNew->mHeight = this->m_pcHeader->skinheight;
- pcNew->pcData = new aiTexel[pcNew->mWidth * pcNew->mHeight];
- const unsigned char* szColorMap;
- this->SearchPalette(&szColorMap);
- // copy texture data
- for (unsigned int i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
- {
- const unsigned char val = szData[i];
- const unsigned char* sz = &szColorMap[val*3];
- pcNew->pcData[i].a = 0xFF;
- pcNew->pcData[i].r = *sz++;
- pcNew->pcData[i].g = *sz++;
- pcNew->pcData[i].b = *sz;
- }
- this->FreePalette(szColorMap);
- // store the texture
- aiTexture** pc = this->pScene->mTextures;
- this->pScene->mTextures = new aiTexture*[this->pScene->mNumTextures+1];
- for (unsigned int i = 0; i < this->pScene->mNumTextures;++i)
- this->pScene->mTextures[i] = pc[i];
- this->pScene->mTextures[this->pScene->mNumTextures] = pcNew;
- this->pScene->mNumTextures++;
- delete[] pc;
- return;
- }
- // ------------------------------------------------------------------------------------------------
- void MDLImporter::CreateTextureARGB8_GS4(const unsigned char* szData,
- unsigned int iType,
- unsigned int* piSkip)
- {
- ai_assert(NULL != piSkip);
- // allocate a new texture object
- aiTexture* pcNew = new aiTexture();
- pcNew->mWidth = this->m_pcHeader->skinwidth;
- pcNew->mHeight = this->m_pcHeader->skinheight;
- pcNew->pcData = new aiTexel[pcNew->mWidth * pcNew->mHeight];
- // 8 Bit paletized. Use Q1 default palette.
- if (0 == iType)
- {
- const unsigned char* szColorMap;
- this->SearchPalette(&szColorMap);
- // copy texture data
- unsigned int i = 0;
- for (; i < pcNew->mWidth*pcNew->mHeight;++i)
- {
- const unsigned char val = szData[i];
- const unsigned char* sz = &szColorMap[val*3];
- pcNew->pcData[i].a = 0xFF;
- pcNew->pcData[i].r = *sz++;
- pcNew->pcData[i].g = *sz++;
- pcNew->pcData[i].b = *sz;
- }
- *piSkip = i;
- this->FreePalette(szColorMap);
- }
- // R5G6B5 format
- else if (2 == iType)
- {
- // copy texture data
- unsigned int i = 0;
- for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
- {
- MDL::RGB565 val = ((MDL::RGB565*)szData)[i];
- pcNew->pcData[i].a = 0xFF;
- pcNew->pcData[i].r = (unsigned char)val.b << 3;
- pcNew->pcData[i].g = (unsigned char)val.g << 2;
- pcNew->pcData[i].b = (unsigned char)val.r << 3;
- }
- *piSkip = i * 2;
- }
- // ARGB4 format
- else if (3 == iType)
- {
- // copy texture data
- unsigned int i = 0;
- for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
- {
- MDL::ARGB4 val = ((MDL::ARGB4*)szData)[i];
- pcNew->pcData[i].a = (unsigned char)val.a << 4;
- pcNew->pcData[i].r = (unsigned char)val.r << 4;
- pcNew->pcData[i].g = (unsigned char)val.g << 4;
- pcNew->pcData[i].b = (unsigned char)val.b << 4;
- }
- *piSkip = i * 2;
- }
- // store the texture
- aiTexture** pc = this->pScene->mTextures;
- this->pScene->mTextures = new aiTexture*[this->pScene->mNumTextures+1];
- for (unsigned int i = 0; i < this->pScene->mNumTextures;++i)
- this->pScene->mTextures[i] = pc[i];
- this->pScene->mTextures[this->pScene->mNumTextures] = pcNew;
- this->pScene->mNumTextures++;
- delete[] pc;
- return;
- }
- // ------------------------------------------------------------------------------------------------
- void MDLImporter::ParseTextureColorData(const unsigned char* szData,
- unsigned int iType,
- unsigned int* piSkip,
- aiTexture* pcNew)
- {
- // allocate storage for the texture image
- pcNew->pcData = new aiTexel[pcNew->mWidth * pcNew->mHeight];
- // R5G6B5 format (with or without MIPs)
- if (2 == iType || 10 == iType)
- {
- // copy texture data
- unsigned int i = 0;
- for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
- {
- MDL::RGB565 val = ((MDL::RGB565*)szData)[i];
- pcNew->pcData[i].a = 0xFF;
- pcNew->pcData[i].r = (unsigned char)val.b << 3;
- pcNew->pcData[i].g = (unsigned char)val.g << 2;
- pcNew->pcData[i].b = (unsigned char)val.r << 3;
- }
- *piSkip = i * 2;
- // apply MIP maps
- if (10 == iType)
- {
- *piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 1;
- }
- }
- // ARGB4 format (with or without MIPs)
- else if (3 == iType || 11 == iType)
- {
- // copy texture data
- unsigned int i = 0;
- for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
- {
- MDL::ARGB4 val = ((MDL::ARGB4*)szData)[i];
- pcNew->pcData[i].a = (unsigned char)val.a << 4;
- pcNew->pcData[i].r = (unsigned char)val.r << 4;
- pcNew->pcData[i].g = (unsigned char)val.g << 4;
- pcNew->pcData[i].b = (unsigned char)val.b << 4;
- }
- *piSkip = i * 2;
- // apply MIP maps
- if (11 == iType)
- {
- *piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 1;
- }
- }
- // RGB8 format (with or without MIPs)
- else if (4 == iType || 12 == iType)
- {
- // copy texture data
- unsigned int i = 0;
- for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
- {
- const unsigned char* _szData = &szData[i*3];
- pcNew->pcData[i].a = 0xFF;
- pcNew->pcData[i].b = *_szData++;
- pcNew->pcData[i].g = *_szData++;
- pcNew->pcData[i].r = *_szData;
- }
- // apply MIP maps
- *piSkip = i * 3;
- if (12 == iType)
- {
- *piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) *3;
- }
- }
- // ARGB8 format (with ir without MIPs)
- else if (5 == iType || 13 == iType)
- {
- // copy texture data
- unsigned int i = 0;
- for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i)
- {
- const unsigned char* _szData = &szData[i*4];
- pcNew->pcData[i].b = *_szData++;
- pcNew->pcData[i].g = *_szData++;
- pcNew->pcData[i].r = *_szData++;
- pcNew->pcData[i].a = *_szData;
- }
- // apply MIP maps
- *piSkip = i << 2;
- if (13 == iType)
- {
- *piSkip += (i + (i >> 2) + (i >> 4) + (i >> 6)) << 2;
- }
- }
- // palletized 8 bit texture. As for Quake 1
- else if (0 == iType)
- {
- const unsigned char* szColorMap;
- this->SearchPalette(&szColorMap);
- // copy texture data
- unsigned int i = 0;
- for (; i < pcNew->mWidth*pcNew->mHeight;++i)
- {
- const unsigned char val = szData[i];
- const unsigned char* sz = &szColorMap[val*3];
- pcNew->pcData[i].a = 0xFF;
- pcNew->pcData[i].r = *sz++;
- pcNew->pcData[i].g = *sz++;
- pcNew->pcData[i].b = *sz;
- }
- *piSkip = i;
- this->FreePalette(szColorMap);
- }
- return;
- }
- // ------------------------------------------------------------------------------------------------
- void MDLImporter::CreateTextureARGB8_GS5(const unsigned char* szData,
- unsigned int iType,
- unsigned int* piSkip)
- {
- ai_assert(NULL != piSkip);
- // allocate a new texture object
- aiTexture* pcNew = new aiTexture();
- // first read the size of the texture
- pcNew->mWidth = *((uint32_t*)szData);
- szData += sizeof(uint32_t);
- pcNew->mHeight = *((uint32_t*)szData);
- szData += sizeof(uint32_t);
- if (6 == iType)
- {
- // this is a compressed texture in DDS format
- *piSkip = pcNew->mWidth;
- pcNew->mHeight = 0;
- pcNew->achFormatHint[0] = 'd';
- pcNew->achFormatHint[1] = 'd';
- pcNew->achFormatHint[2] = 's';
- pcNew->achFormatHint[3] = '\0';
- pcNew->pcData = (aiTexel*) new unsigned char[pcNew->mWidth];
- memcpy(pcNew->pcData,szData,pcNew->mWidth);
- }
- else
- {
- // parse the color data of the texture
- this->ParseTextureColorData(szData,iType,
- piSkip,pcNew);
- }
- *piSkip += sizeof(uint32_t) * 2;
- // store the texture
- aiTexture** pc = this->pScene->mTextures;
- this->pScene->mTextures = new aiTexture*[this->pScene->mNumTextures+1];
- for (unsigned int i = 0; i < this->pScene->mNumTextures;++i)
- this->pScene->mTextures[i] = pc[i];
- this->pScene->mTextures[this->pScene->mNumTextures] = pcNew;
- this->pScene->mNumTextures++;
- delete[] pc;
- return;
- }
- // ------------------------------------------------------------------------------------------------
- void MDLImporter::InternReadFile_Quake1( )
- {
- ai_assert(NULL != pScene);
- if(0 == this->m_pcHeader->num_frames)
- {
- throw new ImportErrorException( "[Quake 1 MDL] No frames found");
- }
- // allocate enough storage to hold all vertices and triangles
- aiMesh* pcMesh = new aiMesh();
- // current cursor position in the file
- const unsigned char* szCurrent = (const unsigned char*)(this->m_pcHeader+1);
- // need to read all textures
- for (unsigned int i = 0; i < (unsigned int)this->m_pcHeader->num_skins;++i)
- {
- union{const MDL::Skin* pcSkin;const MDL::GroupSkin* pcGroupSkin;};
- pcSkin = (const MDL::Skin*)szCurrent;
- if (0 == pcSkin->group)
- {
- // create one output image
- this->CreateTextureARGB8((unsigned char*)pcSkin + sizeof(uint32_t));
- // need to skip one image
- szCurrent += this->m_pcHeader->skinheight * this->m_pcHeader->skinwidth+ sizeof(uint32_t);
- }
- else
- {
- // need to skip multiple images
- const unsigned int iNumImages = (unsigned int)pcGroupSkin->nb;
- szCurrent += sizeof(uint32_t) * 2;
- if (0 != iNumImages)
- {
- // however, create only one output image (the first)
- this->CreateTextureARGB8(szCurrent + iNumImages * sizeof(float));
- for (unsigned int a = 0; a < iNumImages;++a)
- {
- szCurrent += this->m_pcHeader->skinheight * this->m_pcHeader->skinwidth +
- sizeof(float);
- }
- }
- }
- }
- // get a pointer to the texture coordinates
- const MDL::TexCoord* pcTexCoords = (const MDL::TexCoord*)szCurrent;
- szCurrent += sizeof(MDL::TexCoord) * this->m_pcHeader->num_verts;
- // get a pointer to the triangles
- const MDL::Triangle* pcTriangles = (const MDL::Triangle*)szCurrent;
- szCurrent += sizeof(MDL::Triangle) * this->m_pcHeader->num_tris;
- // now get a pointer to the first frame in the file
- const MDL::Frame* pcFrames = (const MDL::Frame*)szCurrent;
- const MDL::SimpleFrame* pcFirstFrame;
- if (0 == pcFrames->type)
- {
- // get address of single frame
- pcFirstFrame = &pcFrames->frame;
- }
- else
- {
- // get the first frame in the group
- const MDL::GroupFrame* pcFrames2 = (const MDL::GroupFrame*)pcFrames;
- pcFirstFrame = (const MDL::SimpleFrame*)(&pcFrames2->time + pcFrames->type);
- }
- const MDL::Vertex* pcVertices = (const MDL::Vertex*) ((pcFirstFrame->name) +
- sizeof(pcFirstFrame->name));
- pcMesh->mNumVertices = this->m_pcHeader->num_tris * 3;
- pcMesh->mNumFaces = this->m_pcHeader->num_tris;
- pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
- pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
- pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
- pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
- pcMesh->mNumUVComponents[0] = 2;
- // there won't be more than one mesh inside the file
- pScene->mNumMaterials = 1;
- pScene->mRootNode = new aiNode();
- pScene->mRootNode->mNumMeshes = 1;
- pScene->mRootNode->mMeshes = new unsigned int[1];
- pScene->mRootNode->mMeshes[0] = 0;
- pScene->mMaterials = new aiMaterial*[1];
- pScene->mMaterials[0] = new MaterialHelper();
- pScene->mNumMeshes = 1;
- pScene->mMeshes = new aiMesh*[1];
- pScene->mMeshes[0] = pcMesh;
- // setup the material properties
- const int iMode = (int)aiShadingMode_Gouraud;
- MaterialHelper* pcHelper = (MaterialHelper*)pScene->mMaterials[0];
- pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
- aiColor3D clr;
- clr.b = clr.g = clr.r = 1.0f;
- pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
- pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
- clr.b = clr.g = clr.r = 0.05f;
- pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
- if (0 != this->m_pcHeader->num_skins)
- {
- aiString szString;
- memcpy(szString.data,AI_MAKE_EMBEDDED_TEXNAME(0),3);
- szString.length = 2;
- pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0));
- }
- // now iterate through all triangles
- unsigned int iCurrent = 0;
- for (unsigned int i = 0; i < (unsigned int) this->m_pcHeader->num_tris;++i)
- {
- pcMesh->mFaces[i].mIndices = new unsigned int[3];
- pcMesh->mFaces[i].mNumIndices = 3;
- unsigned int iTemp = iCurrent;
- for (unsigned int c = 0; c < 3;++c,++iCurrent)
- {
- pcMesh->mFaces[i].mIndices[c] = iCurrent;
- // read vertices
- unsigned int iIndex = pcTriangles->vertex[c];
- if (iIndex >= (unsigned int)this->m_pcHeader->num_verts)
- {
- iIndex = this->m_pcHeader->num_verts-1;
-
- DefaultLogger::get()->warn("Index overflow in Q1-MDL vertex list.");
- }
- aiVector3D& vec = pcMesh->mVertices[iCurrent];
- vec.x = (float)pcVertices[iIndex].v[0] * this->m_pcHeader->scale[0];
- vec.x += this->m_pcHeader->translate[0];
- // (flip z and y component)
- vec.z = (float)pcVertices[iIndex].v[1] * this->m_pcHeader->scale[1];
- vec.z += this->m_pcHeader->translate[1];
- vec.y = (float)pcVertices[iIndex].v[2] * this->m_pcHeader->scale[2];
- vec.y += this->m_pcHeader->translate[2];
- // flip the Z-axis
- //pcMesh->mVertices[iBase+c].z *= -1.0f;
- // read the normal vector from the precalculated normal table
- pcMesh->mNormals[iCurrent] = *((const aiVector3D*)(&g_avNormals[std::min(
- int(pcVertices[iIndex].normalIndex),
- int(sizeof(g_avNormals) / sizeof(g_avNormals[0]))-1)]));
- //pcMesh->mNormals[iBase+c].z *= -1.0f;
- std::swap ( pcMesh->mNormals[iCurrent].y,pcMesh->mNormals[iCurrent].z );
- // read texture coordinates
- float s = (float)pcTexCoords[iIndex].s;
- float t = (float)pcTexCoords[iIndex].t;
- // translate texture coordinates
- if (0 == pcTriangles->facesfront &&
- 0 != pcTexCoords[iIndex].onseam)
- {
- s += this->m_pcHeader->skinwidth * 0.5f;
- }
- // Scale s and t to range from 0.0 to 1.0
- pcMesh->mTextureCoords[0][iCurrent].x = (s + 0.5f) / this->m_pcHeader->skinwidth;
- pcMesh->mTextureCoords[0][iCurrent].y = 1.0f-(t + 0.5f) / this->m_pcHeader->skinheight;
- }
- pcMesh->mFaces[i].mIndices[0] = iTemp+2;
- pcMesh->mFaces[i].mIndices[1] = iTemp+1;
- pcMesh->mFaces[i].mIndices[2] = iTemp+0;
- pcTriangles++;
- }
- return;
- }
- // ------------------------------------------------------------------------------------------------
- void MDLImporter::InternReadFile_GameStudio( )
- {
- ai_assert(NULL != pScene);
- if(0 == this->m_pcHeader->num_frames)
- {
- throw new ImportErrorException( "[3DGS MDL] No frames found");
- }
- // allocate enough storage to hold all vertices and triangles
- aiMesh* pcMesh = new aiMesh();
- // current cursor position in the file
- const unsigned char* szCurrent = (const unsigned char*)(this->m_pcHeader+1);
- // need to read all textures
- for (unsigned int i = 0; i < (unsigned int)this->m_pcHeader->num_skins;++i)
- {
- union{const MDL::Skin* pcSkin;const MDL::GroupSkin* pcGroupSkin;};
- pcSkin = (const MDL::Skin*)szCurrent;
-
- // create one output image
- unsigned int iSkip = 0;
- if (5 <= this->iGSFileVersion)
- {
- // MDL5 format could contain MIPmaps
- this->CreateTextureARGB8_GS5((unsigned char*)pcSkin + sizeof(uint32_t),
- pcSkin->group,&iSkip);
- }
- else
- {
- this->CreateTextureARGB8_GS4((unsigned char*)pcSkin + sizeof(uint32_t),
- pcSkin->group,&iSkip);
- }
- // need to skip one image
- szCurrent += iSkip + sizeof(uint32_t);
-
- }
- // get a pointer to the texture coordinates
- const MDL::TexCoord_MDL3* pcTexCoords = (const MDL::TexCoord_MDL3*)szCurrent;
- szCurrent += sizeof(MDL::TexCoord_MDL3) * this->m_pcHeader->synctype;
- // NOTE: for MDLn formats syntype corresponds to the number of UV coords
- // get a pointer to the triangles
- const MDL::Triangle_MDL3* pcTriangles = (const MDL::Triangle_MDL3*)szCurrent;
- szCurrent += sizeof(MDL::Triangle_MDL3) * this->m_pcHeader->num_tris;
- pcMesh->mNumVertices = this->m_pcHeader->num_tris * 3;
- pcMesh->mNumFaces = this->m_pcHeader->num_tris;
- pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
- pcMesh->mNumUVComponents[0] = 2;
- // there won't be more than one mesh inside the file
- pScene->mNumMaterials = 1;
- pScene->mRootNode = new aiNode();
- pScene->mRootNode->mNumMeshes = 1;
- pScene->mRootNode->mMeshes = new unsigned int[1];
- pScene->mRootNode->mMeshes[0] = 0;
- pScene->mMaterials = new aiMaterial*[1];
- pScene->mMaterials[0] = new MaterialHelper();
- pScene->mNumMeshes = 1;
- pScene->mMeshes = new aiMesh*[1];
- pScene->mMeshes[0] = pcMesh;
- std::vector<aiVector3D> vPositions;
- std::vector<aiVector3D> vTexCoords;
- std::vector<aiVector3D> vNormals;
- vPositions.resize(pScene->mMeshes[0]->mNumFaces*3,aiVector3D());
- vTexCoords.resize(pScene->mMeshes[0]->mNumFaces*3,aiVector3D());
- vNormals.resize(pScene->mMeshes[0]->mNumFaces*3,aiVector3D());
- // setup the material properties
- const int iMode = (int)aiShadingMode_Gouraud;
- MaterialHelper* pcHelper = (MaterialHelper*)pScene->mMaterials[0];
- pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
- aiColor3D clr;
- clr.b = clr.g = clr.r = 1.0f;
- pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
- pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
- clr.b = clr.g = clr.r = 0.05f;
- pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
- if (0 != this->m_pcHeader->num_skins)
- {
- aiString szString;
- memcpy(szString.data,AI_MAKE_EMBEDDED_TEXNAME(0),3);
- szString.length = 2;
- pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0));
- }
- // now get a pointer to the first frame in the file
- const MDL::Frame* pcFrames = (const MDL::Frame*)szCurrent;
- // byte packed vertices
- if (0 == pcFrames->type || 3 == this->iGSFileVersion)
- {
- const MDL::SimpleFrame* pcFirstFrame = (const MDL::SimpleFrame*)
- (szCurrent + sizeof(uint32_t));
- // get a pointer to the vertices
- const MDL::Vertex* pcVertices = (const MDL::Vertex*) ((pcFirstFrame->name) +
- sizeof(pcFirstFrame->name));
- // now iterate through all triangles
- unsigned int iCurrent = 0;
- for (unsigned int i = 0; i < (unsigned int) this->m_pcHeader->num_tris;++i)
- {
- pcMesh->mFaces[i].mIndices = new unsigned int[3];
- pcMesh->mFaces[i].mNumIndices = 3;
- unsigned int iTemp = iCurrent;
- for (unsigned int c = 0; c < 3;++c,++iCurrent)
- {
- // read vertices
- unsigned int iIndex = pcTriangles->index_xyz[c];
- if (iIndex >= (unsigned int)this->m_pcHeader->num_verts)
- {
- iIndex = this->m_pcHeader->num_verts-1;
- DefaultLogger::get()->warn("Index overflow in MDL3/4/5/6 vertex list");
- }
- aiVector3D& vec = vPositions[iCurrent];
- vec.x = (float)pcVertices[iIndex].v[0] * this->m_pcHeader->scale[0];
- vec.x += this->m_pcHeader->translate[0];
- // (flip z and y component)
- vec.z = (float)pcVertices[iIndex].v[1] * this->m_pcHeader->scale[1];
- vec.z += this->m_pcHeader->translate[1];
- vec.y = (float)pcVertices[iIndex].v[2] * this->m_pcHeader->scale[2];
- vec.y += this->m_pcHeader->translate[2];
- // read the normal vector from the precalculated normal table
- vNormals[iCurrent] = *((const aiVector3D*)(&g_avNormals[std::min(
- int(pcVertices[iIndex].normalIndex),
- int(sizeof(g_avNormals) / sizeof(g_avNormals[0]))-1)]));
- //vNormals[iBase+c].z *= -1.0f;
- std::swap ( vNormals[iCurrent].y,vNormals[iCurrent].z );
- // read texture coordinates
- iIndex = pcTriangles->index_uv[c];
- // validate UV indices
- if (iIndex >= (unsigned int)this->m_pcHeader->synctype)
- {
- iIndex = this->m_pcHeader->synctype-1;
- DefaultLogger::get()->warn("Index overflow in MDL3/4/5/6 UV coord list");
- }
- float s = (float)pcTexCoords[iIndex].u;
- float t = (float)pcTexCoords[iIndex].v;
- // Scale s and t to range from 0.0 to 1.0
- if (5 != this->iGSFileVersion &&
- this->m_pcHeader->skinwidth && this->m_pcHeader->skinheight)
- {
- s = (s + 0.5f) / this->m_pcHeader->skinwidth;
- t = 1.0f-(t + 0.5f) / this->m_pcHeader->skinheight;
- }
-
- vTexCoords[iCurrent].x = s;
- vTexCoords[iCurrent].y = t;
- }
- pcMesh->mFaces[i].mIndices[0] = iTemp+2;
- pcMesh->mFaces[i].mIndices[1] = iTemp+1;
- pcMesh->mFaces[i].mIndices[2] = iTemp+0;
- pcTriangles++;
- }
- }
- // short packed vertices (duplicating the code is smaller than using templates ....)
- else
- {
- // now get a pointer to the first frame in the file
- const MDL::SimpleFrame_MDLn_SP* pcFirstFrame = (const MDL::SimpleFrame_MDLn_SP*)
- (szCurrent + sizeof(uint32_t));
- // get a pointer to the vertices
- const MDL::Vertex_MDL4* pcVertices = (const MDL::Vertex_MDL4*) ((pcFirstFrame->name) +
- sizeof(pcFirstFrame->name));
- // now iterate through all triangles
- unsigned int iCurrent = 0;
- for (unsigned int i = 0; i < (unsigned int) this->m_pcHeader->num_tris;++i)
- {
- pcMesh->mFaces[i].mIndices = new unsigned int[3];
- pcMesh->mFaces[i].mNumIndices = 3;
- unsigned int iTemp = iCurrent;
- for (unsigned int c = 0; c < 3;++c,++iCurrent)
- {
- // read vertices
- unsigned int iIndex = pcTriangles->index_xyz[c];
- if (iIndex >= (unsigned int)this->m_pcHeader->num_verts)
- {
- iIndex = this->m_pcHeader->num_verts-1;
- DefaultLogger::get()->warn("Index overflow in MDL3/4/5/6 vertex list");
- }
- aiVector3D& vec = vPositions[iCurrent];
- vec.x = (float)pcVertices[iIndex].v[0] * this->m_pcHeader->scale[0];
- vec.x += this->m_pcHeader->translate[0];
- // (flip z and y component)
- vec.z = (float)pcVertices[iIndex].v[1] * this->m_pcHeader->scale[1];
- vec.z += this->m_pcHeader->translate[1];
- vec.y = (float)pcVertices[iIndex].v[2] * this->m_pcHeader->scale[2];
- vec.y += this->m_pcHeader->translate[2];
- // read the normal vector from the precalculated normal table
- vNormals[iCurrent] = *((const aiVector3D*)(&g_avNormals[std::min(
- int(pcVertices[iIndex].normalIndex),
- int(sizeof(g_avNormals) / sizeof(g_avNormals[0]))-1)]));
- std::swap ( vNormals[iCurrent].y,vNormals[iCurrent].z );
- // read texture coordinates
- iIndex = pcTriangles->index_uv[c];
- // validate UV indices
- if (iIndex >= (unsigned int) this->m_pcHeader->synctype)
- {
- iIndex = this->m_pcHeader->synctype-1;
- DefaultLogger::get()->warn("Index overflow in MDL3/4/5/6 UV coord list");
- }
- float s = (float)pcTexCoords[iIndex].u;
- float t = (float)pcTexCoords[iIndex].v;
-
- // Scale s and t to range from 0.0 to 1.0
- if (5 != this->iGSFileVersion &&
- this->m_pcHeader->skinwidth && this->m_pcHeader->skinheight)
- {
- s = (s + 0.5f) / this->m_pcHeader->skinwidth;
- t = 1.0f-(t + 0.5f) / this->m_pcHeader->skinheight;
- }
- vTexCoords[iCurrent].x = s;
- vTexCoords[iCurrent].y = t;
- }
- pcMesh->mFaces[i].mIndices[0] = iTemp+2;
- pcMesh->mFaces[i].mIndices[1] = iTemp+1;
- pcMesh->mFaces[i].mIndices[2] = iTemp+0;
- pcTriangles++;
- }
- }
- // For MDL5 we will need to build valid texture coordinates
- // basing upon the file loaded (only support one file as skin)
- if (5 == this->iGSFileVersion)
- {
- if (0 != this->m_pcHeader->num_skins && 0 != this->pScene->mNumTextures)
- {
- aiTexture* pcTex = this->pScene->mTextures[0];
- // if the file is loaded in DDS format: get the size of the
- // texture from the header of the DDS file
- // skip three DWORDs and read first height, then the width
- unsigned int iWidth, iHeight;
- if (0 == pcTex->mHeight)
- {
- uint32_t* piPtr = (uint32_t*)pcTex->pcData;
-
- piPtr += 3;
- iHeight = (unsigned int)*piPtr++;
- iWidth = (unsigned int)*piPtr;
- }
- else
- {
- iWidth = pcTex->mWidth;
- iHeight = pcTex->mHeight;
- }
- for (std::vector<aiVector3D>::iterator
- i = vTexCoords.begin();
- i != vTexCoords.end();++i)
- {
- (*i).x /= iWidth;
- (*i).y /= iHeight;
- (*i).y = 1.0f- (*i).y; // DX to OGL
- }
- }
- }
- // allocate output storage
- pScene->mMeshes[0]->mNumVertices = vPositions.size();
- pScene->mMeshes[0]->mVertices = new aiVector3D[vPositions.size()];
- pScene->mMeshes[0]->mNormals = new aiVector3D[vPositions.size()];
- pScene->mMeshes[0]->mTextureCoords[0] = new aiVector3D[vPositions.size()];
- // memcpy() the data to the c-syle arrays
- memcpy(pScene->mMeshes[0]->mVertices, &vPositions[0],
- vPositions.size() * sizeof(aiVector3D));
- memcpy(pScene->mMeshes[0]->mNormals, &vNormals[0],
- vPositions.size() * sizeof(aiVector3D));
- memcpy(pScene->mMeshes[0]->mTextureCoords[0], &vTexCoords[0],
- vPositions.size() * sizeof(aiVector3D));
- return;
- }
- // ------------------------------------------------------------------------------------------------
- void MDLImporter::ParseSkinLump_GameStudioA7(
- const unsigned char* szCurrent,
- const unsigned char** szCurrentOut,
- std::vector<MaterialHelper*>& pcMats)
- {
- ai_assert(NULL != szCurrent);
- ai_assert(NULL != szCurrentOut);
- *szCurrentOut = szCurrent;
- const MDL::Skin_MDL7* pcSkin = (const MDL::Skin_MDL7*)szCurrent;
- szCurrent += 12;
- // allocate an output material
- MaterialHelper* pcMatOut = new MaterialHelper();
- pcMats.push_back(pcMatOut);
- aiTexture* pcNew = NULL;
- // get the type of the skin
- unsigned int iMasked = (unsigned int)(pcSkin->typ & 0xF);
- // skip length of file name
- szCurrent += AI_MDL7_MAX_TEXNAMESIZE;
- if (0x1 == iMasked)
- {
- // ***** REFERENCE TO ANOTHER SKIN INDEX *****
- // NOTE: Documentation - if you can call it a documentation, I prefer
- // the expression "rubbish" - states it is currently unused. However,
- // I don't know what ideas the terrible developers of Conitec will
- // have tomorrow, so Im going to implement it.
- int referrer = pcSkin->width;
- pcMatOut->AddProperty<int>(&referrer,1,"quakquakquak");
- }
- else if (0x6 == iMasked)
- {
- // ***** EMBEDDED DDS FILE *****
- if (1 != pcSkin->height)
- {
- DefaultLogger::get()->warn("Found a reference to an embedded DDS texture, "
- "but texture height is not equal to 1, which is not supported by MED");
- }
- pcNew = new aiTexture();
- pcNew->mHeight = 0;
- pcNew->achFormatHint[0] = 'd';
- pcNew->achFormatHint[1] = 'd';
- pcNew->achFormatHint[2] = 's';
- pcNew->achFormatHint[3] = '\0';
- pcNew->pcData = (aiTexel*) new unsigned char[pcNew->mWidth];
- memcpy(pcNew->pcData,szCurrent,pcNew->mWidth);
- szCurrent += pcSkin->width;
- }
- if (0x7 == iMasked)
- {
- // ***** REFERENCE TO EXTERNAL FILE *****
- if (1 != pcSkin->height)
- {
- DefaultLogger::get()->warn("Found a reference to an external texture, "
- "but texture height is not equal to 1, which is not supported by MED");
- }
- aiString szFile;
- const size_t iLen = strlen((const char*)szCurrent);
- size_t iLen2 = iLen+1;
- iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2;
- memcpy(szFile.data,(const char*)szCurrent,iLen2);
- szFile.length = iLen;
- szCurrent += iLen2;
- // place this as diffuse texture
- pcMatOut->AddProperty(&szFile,AI_MATKEY_TEXTURE_DIFFUSE(0));
- }
- else if (0 != iMasked || 0 == pcSkin->typ)
- {
- // ***** STANDARD COLOR TEXTURE *****
- pcNew = new aiTexture();
- if (0 == pcSkin->height || 0 == pcSkin->width)
- {
- DefaultLogger::get()->warn("Found embedded texture, but its width "
- "an height are both 0. Is this a joke?");
- // generate an empty chess pattern
- pcNew->mWidth = pcNew->mHeight = 8;
- pcNew->pcData = new aiTexel[64];
- for (unsigned int x = 0; x < 8;++x)
- {
- for (unsigned int y = 0; y < 8;++y)
- {
- bool bSet = false;
- if (0 == x % 2 && 0 != y % 2 ||
- 0 != x % 2 && 0 == y % 2)bSet = true;
-
- aiTexel* pc = &pcNew->pcData[y * 8 + x];
- if (bSet)pc->r = pc->b = pc->g = 0xFF;
- else pc->r = pc->b = pc->g = 0;
- pc->a = 0xFF;
- }
- }
- }
- else
- {
- // it is a standard color texture. Fill in width and height
- // and call the same function we used for loading MDL5 files
- pcNew->mWidth = pcSkin->width;
- pcNew->mHeight = pcSkin->height;
- unsigned int iSkip = 0;
- this->ParseTextureColorData(szCurrent,iMasked,&iSkip,pcNew);
- // skip length of texture data
- szCurrent += iSkip;
- }
- }
-
- // check whether a material definition is contained in the skin
- if (pcSkin->typ & AI_MDL7_SKINTYPE_MATERIAL)
- {
- const MDL::Material_MDL7* pcMatIn = (const MDL::Material_MDL7*)szCurrent;
- szCurrent = (unsigned char*)(pcMatIn+1);
- aiColor4D clrTemp;
- // read diffuse color
- clrTemp.a = 1.0f; //pcMatIn->Diffuse.a;
- clrTemp.r = pcMatIn->Diffuse.r;
- clrTemp.g = pcMatIn->Diffuse.g;
- clrTemp.b = pcMatIn->Diffuse.b;
- pcMatOut->AddProperty<aiColor4D>(&clrTemp,1,AI_MATKEY_COLOR_DIFFUSE);
- // read specular color
- clrTemp.a = 1.0f; //pcMatIn->Specular.a;
- clrTemp.r = pcMatIn->Specular.r;
- clrTemp.g = pcMatIn->Specular.g;
- clrTemp.b = pcMatIn->Specular.b;
- pcMatOut->AddProperty<aiColor4D>(&clrTemp,1,AI_MATKEY_COLOR_SPECULAR);
- // read ambient color
- clrTemp.a = 1.0f; //pcMatIn->Ambient.a;
- clrTemp.r = pcMatIn->Ambient.r;
- clrTemp.g = pcMatIn->Ambient.g;
- clrTemp.b = pcMatIn->Ambient.b;
- pcMatOut->AddProperty<aiColor4D>(&clrTemp,1,AI_MATKEY_COLOR_AMBIENT);
- // read emissive color
- clrTemp.a = 1.0f; //pcMatIn->Emissive.a;
- clrTemp.r = pcMatIn->Emissive.r;
- clrTemp.g = pcMatIn->Emissive.g;
- clrTemp.b = pcMatIn->Emissive.b;
- pcMatOut->AddProperty<aiColor4D>(&clrTemp,1,AI_MATKEY_COLOR_EMISSIVE);
- // FIX: Take the opacity from the ambient color
- // the doc says something else, but it is fact that MED exports the
- // opacity like this .... ARRRGGHH!
- clrTemp.a = pcMatIn->Ambient.a;
- pcMatOut->AddProperty<float>(&clrTemp.a,1,AI_MATKEY_OPACITY);
- // read phong power
- int iShadingMode = (int)aiShadingMode_Gouraud;
- if (0.0f != pcMatIn->Power)
- {
- iShadingMode = (int)aiShadingMode_Phong;
- pcMatOut->AddProperty<float>(&pcMatIn->Power,1,AI_MATKEY_SHININESS);
- }
- pcMatOut->AddProperty<int>(&iShadingMode,1,AI_MATKEY_SHADING_MODEL);
- }
- // if an ASCII effect description (HLSL?) is contained in the file,
- // we can simply ignore it ...
- if (pcSkin->typ & AI_MDL7_SKINTYPE_MATERIAL_ASCDEF)
- {
- int32_t iMe = *((int32_t*)szCurrent);
- szCurrent += sizeof(char) * iMe + sizeof(int32_t);
- }
- // if an embedded texture has been loaded setup the corresponding
- // data structures in the aiScene instance
- if (NULL != pcNew)
- {
- // place this as diffuse texture
- char szCurrent[5];
- sprintf(szCurrent,"*%i",this->pScene->mNumTextures);
-
- aiString szFile;
- const size_t iLen = strlen((const char*)szCurrent);
- size_t iLen2 = iLen+1;
- iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2;
- memcpy(szFile.data,(const char*)szCurrent,iLen2);
- szFile.length = iLen;
- pcMatOut->AddProperty(&szFile,AI_MATKEY_TEXTURE_DIFFUSE(0));
- // store the texture
- aiTexture** pc = this->pScene->mTextures;
- this->pScene->mTextures = new aiTexture*[this->pScene->mNumTextures+1];
- for (unsigned int i = 0; i < this->pScene->mNumTextures;++i)
- this->pScene->mTextures[i] = pc[i];
- this->pScene->mTextures[this->pScene->mNumTextures] = pcNew;
- this->pScene->mNumTextures++;
- delete[] pc;
- }
- // place the name of the skin in the material
- const size_t iLen = strlen(pcSkin->texture_name);
- if (0 != iLen)
- {
- aiString szFile;
- memcpy(szFile.data,pcSkin->texture_name,sizeof(pcSkin->texture_name));
- szFile.length = iLen;
- pcMatOut->AddProperty(&szFile,AI_MATKEY_NAME);
- }
- *szCurrentOut = szCurrent;
- return;
- }
- #define _AI_MDL7_ACCESS(_data, _index, _limit, _type) \
- (*((const _type*)(((const char*)_data) + _index * _limit)))
- #define _AI_MDL7_ACCESS_VERT(_data, _index, _limit) \
- _AI_MDL7_ACCESS(_data,_index,_limit,MDL::Vertex_MDL7)
- // ------------------------------------------------------------------------------------------------
- void MDLImporter::ValidateHeader_GameStudioA7(const MDL::Header_MDL7* pcHeader)
- {
- ai_assert(NULL != pcHeader);
- if (sizeof(MDL::ColorValue_MDL7) != pcHeader->colorvalue_stc_size)
- {
- // LOG
- throw new ImportErrorException(
- "[3DGS MDL7] sizeof(MDL::ColorValue_MDL7) != pcHeader->colorvalue_stc_size");
- }
- if (sizeof(MDL::TexCoord_MDL7) != pcHeader->skinpoint_stc_size)
- {
- // LOG
- throw new ImportErrorException(
- "[3DGS MDL7] sizeof(MDL::TexCoord_MDL7) != pcHeader->skinpoint_stc_size");
- }
- if (sizeof(MDL::Skin_MDL7) != pcHeader->skin_stc_size)
- {
- // LOG
- throw new ImportErrorException(
- "sizeof(MDL::Skin_MDL7) != pcHeader->skin_stc_size");
- }
- // if there are no groups ... how should we load such a file?
- if(0 == pcHeader->groups_num)
- {
- // LOG
- throw new ImportErrorException( "[3DGS MDL7] No frames found");
- }
- return;
- }
- // ------------------------------------------------------------------------------------------------
- void MDLImporter::InternReadFile_GameStudioA7( )
- {
- ai_assert(NULL != pScene);
- // current cursor position in the file
- const MDL::Header_MDL7* pcHeader = (const MDL::Header_MDL7*)this->m_pcHeader;
- const unsigned char* szCurrent = (const unsigned char*)(pcHeader+1);
- // validate the header of the file. There are some structure
- // sizes that are expected by the loader to be constant
- this->ValidateHeader_GameStudioA7(pcHeader);
- // skip all bones
- szCurrent += sizeof(MDL::Bone_MDL7) * pcHeader->bones_num;
- // allocate a material list
- std::vector<MaterialHelper*> pcMats;
- // vector to hold all created meshes
- std::vector<aiMesh*> avOutList;
- avOutList.reserve(pcHeader->groups_num);
- // read all groups
- for (unsigned int iGroup = 0; iGroup < (unsigned int)pcHeader->groups_num;++iGroup)
- {
- const MDL::Group_MDL7* pcGroup = (const MDL::Group_MDL7*)szCurrent;
- szCurrent = (const unsigned char*)(pcGroup+1);
- if (1 != pcGroup->typ)
- {
- // Not a triangle-based mesh
- DefaultLogger::get()->warn("[3DGS MDL7] Mesh group is not basing on"
- "triangles. Continuing happily");
- }
- // read all skins
- pcMats.reserve(pcMats.size() + pcGroup->numskins);
- for (unsigned int iSkin = 0; iSkin < (unsigned int)pcGroup->numskins;++iSkin)
- {
- this->ParseSkinLump_GameStudioA7(szCurrent,&szCurrent,pcMats);
- }
- // if we have absolutely no skin loaded we need to generate a default material
- if (pcMats.empty())
- {
- const int iMode = (int)aiShadingMode_Gouraud;
- pcMats.push_back(new MaterialHelper());
- MaterialHelper* pcHelper = (MaterialHelper*)pcMats[0];
- pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
- aiColor3D clr;
- clr.b = clr.g = clr.r = 0.6f;
- pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
- pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
- clr.b = clr.g = clr.r = 0.05f;
- pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
- }
- // now get a pointer to all texture coords in the group
- const MDL::TexCoord_MDL7* pcGroupUVs = (const MDL::TexCoord_MDL7*)szCurrent;
- szCurrent += pcHeader->skinpoint_stc_size * pcGroup->num_stpts;
- // now get a pointer to all triangle in the group
- const MDL::Triangle_MDL7* pcGroupTris = (const MDL::Triangle_MDL7*)szCurrent;
- szCurrent += pcHeader->triangle_stc_size * pcGroup->numtris;
- // now get a pointer to all vertices in the group
- const MDL::Vertex_MDL7* pcGroupVerts = (const MDL::Vertex_MDL7*)szCurrent;
- szCurrent += pcHeader->mainvertex_stc_size * pcGroup->numverts;
- // build output vectors
- std::vector<aiVector3D> vPositions;
- vPositions.resize(pcGroup->numtris * 3);
- std::vector<aiVector3D> vNormals;
- vNormals.resize(pcGroup->numtris * 3);
- std::vector<aiVector3D> vTextureCoords1;
- vTextureCoords1.resize(pcGroup->numtris * 3,
- aiVector3D(std::numeric_limits<float>::quiet_NaN(),0.0f,0.0f));
- std::vector<aiVector3D> vTextureCoords2;
-
- bool bNeed2UV = false;
- if (pcHeader->triangle_stc_size >= sizeof(MDL::Triangle_MDL7))
- {
- vTextureCoords2.resize(pcGroup->numtris * 3,
- aiVector3D(std::numeric_limits<float>::quiet_NaN(),0.0f,0.0f));
- bNeed2UV = true;
- }
- MDL::IntFace_MDL7* pcFaces = new MDL::IntFace_MDL7[pcGroup->numtris];
- // iterate through all triangles and build valid display lists
- for (unsigned int iTriangle = 0; iTriangle < (unsigned int)pcGroup->numtris; ++iTriangle)
- {
- // iterate through all indices of the current triangle
- for (unsigned int c = 0; c < 3;++c)
- {
- // validate the vertex index
- unsigned int iIndex = pcGroupTris->v_index[c];
- if(iIndex > (unsigned int)pcGroup->numverts)
- {
- // LOG
- iIndex = pcGroup->numverts-1;
- DefaultLogger::get()->warn("Index overflow in MDL7 vertex list");
- }
- unsigned int iOutIndex = iTriangle * 3 + c;
- // write the output face index
- pcFaces[iTriangle].mIndices[c] = iTriangle * 3 + (2-c);
- // swap z and y axis
- vPositions[iOutIndex].x = _AI_MDL7_ACCESS_VERT(pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .x;
- vPositions[iOutIndex].z = _AI_MDL7_ACCESS_VERT(pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .y;
- vPositions[iOutIndex].y = _AI_MDL7_ACCESS_VERT(pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .z;
- // now read the normal vector
- if (AI_MDL7_FRAMEVERTEX030305_STCSIZE <= pcHeader->mainvertex_stc_size)
- {
- // read the full normal vector
- vNormals[iOutIndex].x = _AI_MDL7_ACCESS_VERT(pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[0];
- vNormals[iOutIndex].z = _AI_MDL7_ACCESS_VERT(pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[1];
- vNormals[iOutIndex].y = _AI_MDL7_ACCESS_VERT(pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[2];
- // FIX: It seems to be necessary to invert all normals
- vNormals[iOutIndex].x *= -1.0f;
- vNormals[iOutIndex].y *= -1.0f;
- vNormals[iOutIndex].z *= -1.0f;
- }
- else if (AI_MDL7_FRAMEVERTEX120503_STCSIZE <= pcHeader->mainvertex_stc_size)
- {
- // read the normal vector from Quake2's smart table
- vNormals[iOutIndex] = *((const aiVector3D*)(&g_avNormals[std::min(
- int(_AI_MDL7_ACCESS_VERT(pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm162index),
- int(sizeof(g_avNormals) / sizeof(g_avNormals[0]))-1)]));
- std::swap(vNormals[iOutIndex].z,vNormals[iOutIndex].y);
- }
-
- // validate and process the first uv coordinate set
- // *************************************************************
- const unsigned int iMin = sizeof(MDL::Triangle_MDL7)-
- sizeof(MDL::SkinSet_MDL7)-sizeof(uint32_t);
- const unsigned int iMin2 = sizeof(MDL::Triangle_MDL7)-
- sizeof(MDL::SkinSet_MDL7);
- if (pcHeader->triangle_stc_size >= iMin)
- {
- iIndex = pcGroupTris->skinsets[0].st_index[c];
- if(iIndex > (unsigned int)pcGroup->num_stpts)
- {
- iIndex = pcGroup->num_stpts-1;
- }
- float u = pcGroupUVs[iIndex].u;
- float v = 1.0f-pcGroupUVs[iIndex].v;
-
- vTextureCoords1[iOutIndex].x = u;
- vTextureCoords1[iOutIndex].y = v;
-
- // assign the material index, but only if it is existing
- if (pcHeader->triangle_stc_size >= iMin2)
- {
- pcFaces[iTriangle].iMatIndex[0] = pcGroupTris->skinsets[0].material;
- }
- }
- // validate and process the second uv coordinate set
- // *************************************************************
- if (pcHeader->triangle_stc_size >= sizeof(MDL::Triangle_MDL7))
- {
- iIndex = pcGroupTris->skinsets[1].st_index[c];
- if(iIndex > (unsigned int)pcGroup->num_stpts)
- {
- iIndex = pcGroup->num_stpts-1;
- }
- float u = pcGroupUVs[iIndex].u;
- float v = 1.0f-pcGroupUVs[iIndex].v;
- vTextureCoords2[iOutIndex].x = u;
- vTextureCoords2[iOutIndex].y = v;
-
- // check whether we do really need the second texture
- // coordinate set ... wastes memory and loading time
- if (0 != iIndex && (u != vTextureCoords1[iOutIndex].x ||
- v != vTextureCoords1[iOutIndex].y))
- {
- bNeed2UV = true;
- }
- // if the material differs, we need a second skin, too
- if (pcGroupTris->skinsets[1].material != pcGroupTris->skinsets[0].material)
- {
- bNeed2UV = true;
- }
- // assign the material index
- pcFaces[iTriangle].iMatIndex[1] = pcGroupTris->skinsets[1].material;
- }
- }
- // get the next triangle in the list
- pcGroupTris = (const MDL::Triangle_MDL7*)((const char*)pcGroupTris + pcHeader->triangle_stc_size);
- }
- // if we don't need a second set of texture coordinates there is no reason to keep it in memory ...
- std::vector<unsigned int>** aiSplit;
- unsigned int iNumMaterials = 0;
- if (!bNeed2UV)
- {
- vTextureCoords2.clear();
- // allocate the array
- aiSplit = new std::vector<unsigned int>*[pcMats.size()];
- iNumMaterials = pcMats.size();
- for (unsigned int m = 0; m < pcMats.size();++m)
- aiSplit[m] = new std::vector<unsigned int>();
- // iterate through all faces and sort by material
- for (unsigned int iFace = 0; iFace < (unsigned int)pcGroup->numtris;++iFace)
- {
- // check range
- if (pcFaces[iFace].iMatIndex[0] >= iNumMaterials)
- {
- // use the last material instead
- aiSplit[iNumMaterials-1]->push_back(iFace);
- // sometimes MED writes -1, but normally only if there is only
- // one skin assigned. No warning in this case
- if(0xFFFFFFFF != pcFaces[iFace].iMatIndex[0])
- DefaultLogger::get()->warn("Index overflow in MDL7 material list [#0]");
- }
- else aiSplit[pcFaces[iFace].iMatIndex[0]]->push_back(iFace);
- }
- }
- else
- {
- // we need to build combined materials for each combination of
- std::vector<MDL::IntMaterial_MDL7> avMats;
- avMats.reserve(pcMats.size()*2);
- std::vector<std::vector<unsigned int>* > aiTempSplit;
- aiTempSplit.reserve(pcMats.size()*2);
- for (unsigned int m = 0; m < pcMats.size();++m)
- aiTempSplit[m] = new std::vector<unsigned int>();
- // iterate through all faces and sort by material
- for (unsigned int iFace = 0; iFace < (unsigned int)pcGroup->numtris;++iFace)
- {
- // check range
- unsigned int iMatIndex = pcFaces[iFace].iMatIndex[0];
- if (iMatIndex >= iNumMaterials)
- {
- iMatIndex = iNumMaterials-1;
- // sometimes MED writes -1, but normally only if there is only
- // one skin assigned. No warning in this case
- if(0xFFFFFFFF != iMatIndex)
- DefaultLogger::get()->warn("Index overflow in MDL7 material list [#1]");
- }
- unsigned int iMatIndex2 = pcFaces[iFace].iMatIndex[1];
- if (iMatIndex2 >= iNumMaterials)
- {
- // sometimes MED writes -1, but normally only if there is only
- // one skin assigned. No warning in this case
- if(0xFFFFFFFF != iMatIndex2)
- DefaultLogger::get()->warn("Index overflow in MDL7 material list [#2]");
- }
- // do a slow O(log(n)*n) seach in the list ...
- unsigned int iNum = 0;
- bool bFound = false;
- for (std::vector<MDL::IntMaterial_MDL7>::iterator
- i = avMats.begin();
- i != avMats.end();++i,++iNum)
- {
- if ((*i).iOldMatIndices[0] == iMatIndex &&
- (*i).iOldMatIndices[1] == iMatIndex2)
- {
- // reuse this material
- bFound = true;
- break;
- }
- }
- if (!bFound)
- {
- // build a new material ...
- MDL::IntMaterial_MDL7 sHelper;
- sHelper.pcMat = new MaterialHelper();
- sHelper.iOldMatIndices[0] = iMatIndex;
- sHelper.iOldMatIndices[1] = iMatIndex2;
- this->JoinSkins_GameStudioA7(pcMats[iMatIndex],pcMats[iMatIndex2],sHelper.pcMat);
- // and add it to the list
- avMats.push_back(sHelper);
- iNum = avMats.size()-1;
- }
- // adjust the size of the file array
- if (iNum == aiTempSplit.size())
- {
- aiTempSplit.push_back(new std::vector<unsigned int>());
- }
- aiTempSplit[iNum]->push_back(iFace);
- }
- // now add the newly created materials to the old list
- if (0 == iGroup)
- {
- pcMats.resize(avMats.size());
- for (unsigned int o = 0; o < avMats.size();++o)
- pcMats[o] = avMats[o].pcMat;
- }
- else
- {
- // TODO: This might result in redundant materials ...
- unsigned int iOld = pcMats.size();
- pcMats.resize(pcMats.size() + avMats.size());
- for (unsigned int o = iOld; o < avMats.size();++o)
- pcMats[o] = avMats[o].pcMat;
- }
- iNumMaterials = pcMats.size();
- // and build the final face-to-material array
- aiSplit = new std::vector<unsigned int>*[aiTempSplit.size()];
- for (unsigned int m = 0; m < iNumMaterials;++m)
- aiSplit[m] = aiTempSplit[m];
- // no need to delete the member of aiTempSplit
- }
- // now generate output meshes
- unsigned int iOldSize = avOutList.size();
- this->GenerateOutputMeshes_GameStudioA7(
- (const std::vector<unsigned int>**)aiSplit,pcMats,
- avOutList,pcFaces,vPositions,vNormals, vTextureCoords1,vTextureCoords2);
- // store the group index temporarily
- ai_assert(AI_MAX_NUMBER_OF_TEXTURECOORDS >= 3);
- for (unsigned int l = iOldSize;l < avOutList.size();++l)
- {
- avOutList[l]->mNumUVComponents[2] = iGroup;
- }
- // delete the face-to-material helper array
- for (unsigned int m = 0; m < iNumMaterials;++m)
- delete aiSplit[m];
- delete[] aiSplit;
- // now we need to skip all faces
- for(unsigned int iFrame = 0; iFrame < (unsigned int)pcGroup->numframes;++iFrame)
- {
- const MDL::Frame_MDL7* pcFrame = (const MDL::Frame_MDL7*)szCurrent;
- unsigned int iAdd = pcHeader->frame_stc_size +
- pcFrame->vertices_count * pcHeader->framevertex_stc_size +
- pcFrame->transmatrix_count * pcHeader->bonetrans_stc_size;
- if (((unsigned int)szCurrent - (unsigned int)pcHeader) + iAdd > (unsigned int)pcHeader->data_size)
- {
- DefaultLogger::get()->warn("Index overflow in frame area. Ignoring frames");
- // don't parse more groups if we can't even read one
- goto __BREAK_OUT;
- }
- szCurrent += iAdd;
- }
- }
- __BREAK_OUT: // EVIL ;-)
- // now we need to build a final mesh list
- this->pScene->mNumMeshes = avOutList.size();
- this->pScene->mMeshes = new aiMesh*[avOutList.size()];
- for (unsigned int i = 0; i < avOutList.size();++i)
- {
- this->pScene->mMeshes[i] = avOutList[i];
- }
- // build a final material list. Offset all mesh material indices
- this->pScene->mNumMaterials = pcMats.size();
- this->pScene->mMaterials = new aiMaterial*[this->pScene->mNumMaterials];
- for (unsigned int i = 0; i < this->pScene->mNumMaterials;++i)
- this->pScene->mMaterials[i] = pcMats[i];
-
- // search for referrer materials
- for (unsigned int i = 0; i < this->pScene->mNumMaterials;++i)
- {
- int iIndex = 0;
- if (AI_SUCCESS == aiGetMaterialInteger(this->pScene->mMaterials[i],
- "quakquakquak", &iIndex) )
- {
- for (unsigned int a = 0; a < avOutList.size();++a)
- {
- if (i == avOutList[a]->mMaterialIndex)
- {
- avOutList[a]->mMaterialIndex = iIndex;
- }
- }
- // TODO: Remove the material from the list
- }
- }
- // now generate a nodegraph whose rootnode references all meshes
- this->pScene->mRootNode = new aiNode();
- this->pScene->mRootNode->mNumMeshes = this->pScene->mNumMeshes;
- this->pScene->mRootNode->mMeshes = new unsigned int[this->pScene->mRootNode->mNumMeshes];
- for (unsigned int i = 0; i < this->pScene->mRootNode->mNumMeshes;++i)
- this->pScene->mRootNode->mMeshes[i] = i;
- // seems we're finished now
- return;
- }
- // ------------------------------------------------------------------------------------------------
- void MDLImporter::GenerateOutputMeshes_GameStudioA7(
- const std::vector<unsigned int>** aiSplit,
- const std::vector<MaterialHelper*>& pcMats,
- std::vector<aiMesh*>& avOutList,
- const MDL::IntFace_MDL7* pcFaces,
- const std::vector<aiVector3D>& vPositions,
- const std::vector<aiVector3D>& vNormals,
- const std::vector<aiVector3D>& vTextureCoords1,
- const std::vector<aiVector3D>& vTextureCoords2)
- {
- ai_assert(NULL != aiSplit);
- ai_assert(NULL != pcFaces);
- for (unsigned int i = 0; i < pcMats.size();++i)
- {
- if (!aiSplit[i]->empty())
- {
- // allocate the output mesh
- aiMesh* pcMesh = new aiMesh();
- pcMesh->mNumUVComponents[0] = 2;
- pcMesh->mMaterialIndex = i;
- // allocate output storage
- pcMesh->mNumFaces = aiSplit[i]->size();
- pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
- pcMesh->mNumVertices = pcMesh->mNumFaces*3;
- pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
- pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
- pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
- if (!vTextureCoords2.empty())
- {
- pcMesh->mNumUVComponents[1] = 2;
- pcMesh->mTextureCoords[1] = new aiVector3D[pcMesh->mNumVertices];
- }
- // iterate through all faces and build an unique set of vertices
- unsigned int iCurrent = 0;
- for (unsigned int iFace = 0; iFace < pcMesh->mNumFaces;++iFace)
- {
- pcMesh->mFaces[iFace].mNumIndices = 3;
- pcMesh->mFaces[iFace].mIndices = new unsigned int[3];
- unsigned int iSrcFace = aiSplit[i]->operator[](iFace);
- const MDL::IntFace_MDL7& oldFace = pcFaces[iSrcFace];
- // iterate through all face indices
- for (unsigned int c = 0; c < 3;++c)
- {
- pcMesh->mVertices[iCurrent] = vPositions[oldFace.mIndices[c]];
- pcMesh->mNormals[iCurrent] = vNormals[oldFace.mIndices[c]];
- pcMesh->mTextureCoords[0][iCurrent] = vTextureCoords1[oldFace.mIndices[c]];
- if (!vTextureCoords2.empty())
- {
- pcMesh->mTextureCoords[1][iCurrent] = vTextureCoords2[oldFace.mIndices[c]];
- }
- pcMesh->mFaces[iFace].mIndices[c] = iCurrent;
- ++iCurrent;
- }
- }
- // add the mesh to the list of output meshes
- avOutList.push_back(pcMesh);
- }
- }
- return;
- }
- // ------------------------------------------------------------------------------------------------
- void MDLImporter::JoinSkins_GameStudioA7(
- MaterialHelper* pcMat1,
- MaterialHelper* pcMat2,
- MaterialHelper* pcMatOut)
- {
- ai_assert(NULL != pcMat1);
- ai_assert(NULL != pcMat2);
- ai_assert(NULL != pcMatOut);
- // first create a full copy of the first skin property set
- // and assign it to the output material
- MaterialHelper::CopyPropertyList(pcMatOut,pcMat1);
- int iVal = 0;
- pcMatOut->AddProperty<int>(&iVal,1,AI_MATKEY_UVWSRC_DIFFUSE(0));
- // then extract the diffuse texture from the second skin,
- // setup 1 as UV source and we have it
- aiString sString;
- if(AI_SUCCESS == aiGetMaterialString ( pcMat2, AI_MATKEY_TEXTURE_DIFFUSE(0),&sString ))
- {
- iVal = 1;
- pcMatOut->AddProperty<int>(&iVal,1,AI_MATKEY_UVWSRC_DIFFUSE(1));
- pcMatOut->AddProperty(&sString,AI_MATKEY_TEXTURE_DIFFUSE(1));
- }
- return;
- }
- // ------------------------------------------------------------------------------------------------
- void MDLImporter::FlipNormals(aiMesh* pcMesh)
- {
- ai_assert(NULL != pcMesh);
- // compute the bounding box of both the model vertices + normals and
- // the umodified model vertices. Then check whether the first BB
- // is smaller than the second. In this case we can assume that the
- // normals need to be flipped, although there are a few special cases ..
- // convex, concave, planar models ...
- aiVector3D vMin0(1e10f,1e10f,1e10f);
- aiVector3D vMin1(1e10f,1e10f,1e10f);
- aiVector3D vMax0(-1e10f,-1e10f,-1e10f);
- aiVector3D vMax1(-1e10f,-1e10f,-1e10f);
- for (unsigned int i = 0; i < pcMesh->mNumVertices;++i)
- {
- vMin1.x = std::min(vMin1.x,pcMesh->mVertices[i].x);
- vMin1.y = std::min(vMin1.y,pcMesh->mVertices[i].y);
- vMin1.z = std::min(vMin1.z,pcMesh->mVertices[i].z);
- vMax1.x = std::max(vMax1.x,pcMesh->mVertices[i].x);
- vMax1.y = std::max(vMax1.y,pcMesh->mVertices[i].y);
- vMax1.z = std::max(vMax1.z,pcMesh->mVertices[i].z);
- aiVector3D vWithNormal = pcMesh->mVertices[i] + pcMesh->mNormals[i];
- vMin0.x = std::min(vMin0.x,vWithNormal.x);
- vMin0.y = std::min(vMin0.y,vWithNormal.y);
- vMin0.z = std::min(vMin0.z,vWithNormal.z);
- vMax0.x = std::max(vMax0.x,vWithNormal.x);
- vMax0.y = std::max(vMax0.y,vWithNormal.y);
- vMax0.z = std::max(vMax0.z,vWithNormal.z);
- }
- if (fabsf((vMax0.x - vMin0.x) * (vMax0.y - vMin0.y) * (vMax0.z - vMin0.z)) <=
- fabsf((vMax1.x - vMin1.x) * (vMax1.y - vMin1.y) * (vMax1.z - vMin1.z)))
- {
- DefaultLogger::get()->info("The models normals are facing inwards "
- "(or the model is too planar or concave). Flipping the normal set ...");
- for (unsigned int i = 0; i < pcMesh->mNumVertices;++i)
- {
- pcMesh->mNormals[i] *= -1.0f;
- }
- }
- return;
- }
- // ------------------------------------------------------------------------------------------------
- void MDLImporter::InternReadFile_HL2( )
- {
- const MDL::Header_HL2* pcHeader = (const MDL::Header_HL2*)this->mBuffer;
- return;
- }
|