1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765 |
- /*
- ---------------------------------------------------------------------------
- Free 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 "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)
- {
- 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)
- {
- 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)
- {
- 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)
- {
- 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)
- {
- 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)
- {
- this->iGSFileVersion = 7;
- this->InternReadFile_GameStudioA7();
- }
- else
- {
- // we're definitely unable to load this file
- throw new ImportErrorException( "Unknown MDL subformat " + pFile +
- ". Magic word is not known");
- }
- // 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);
- }
- 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;
- 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;
- }
- 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;
- for (unsigned int c = 0; c < 3;++c,++iCurrent)
- {
- pcMesh->mFaces[i].mIndices[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;
- }
- pcTriangles++;
- }
- }
- // short packed vertices
- 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;
- for (unsigned int c = 0; c < 3;++c,++iCurrent)
- {
- pcMesh->mFaces[i].mIndices[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;
- }
- 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;
- }
- }
- }
- // 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 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
- 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] = iOutIndex;
- // 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)
- {
- 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;
- }
|