rev |
line source |
nuclear@0
|
1 /*
|
nuclear@0
|
2 ---------------------------------------------------------------------------
|
nuclear@0
|
3 Open Asset Import Library (assimp)
|
nuclear@0
|
4 ---------------------------------------------------------------------------
|
nuclear@0
|
5
|
nuclear@0
|
6 Copyright (c) 2006-2012, assimp team
|
nuclear@0
|
7
|
nuclear@0
|
8 All rights reserved.
|
nuclear@0
|
9
|
nuclear@0
|
10 Redistribution and use of this software in source and binary forms,
|
nuclear@0
|
11 with or without modification, are permitted provided that the following
|
nuclear@0
|
12 conditions are met:
|
nuclear@0
|
13
|
nuclear@0
|
14 * Redistributions of source code must retain the above
|
nuclear@0
|
15 copyright notice, this list of conditions and the
|
nuclear@0
|
16 following disclaimer.
|
nuclear@0
|
17
|
nuclear@0
|
18 * Redistributions in binary form must reproduce the above
|
nuclear@0
|
19 copyright notice, this list of conditions and the
|
nuclear@0
|
20 following disclaimer in the documentation and/or other
|
nuclear@0
|
21 materials provided with the distribution.
|
nuclear@0
|
22
|
nuclear@0
|
23 * Neither the name of the assimp team, nor the names of its
|
nuclear@0
|
24 contributors may be used to endorse or promote products
|
nuclear@0
|
25 derived from this software without specific prior
|
nuclear@0
|
26 written permission of the assimp team.
|
nuclear@0
|
27
|
nuclear@0
|
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
nuclear@0
|
29 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
nuclear@0
|
30 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
nuclear@0
|
31 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
nuclear@0
|
32 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
nuclear@0
|
33 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
nuclear@0
|
34 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
nuclear@0
|
35 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
nuclear@0
|
36 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
nuclear@0
|
37 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
nuclear@0
|
38 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
nuclear@0
|
39 ---------------------------------------------------------------------------
|
nuclear@0
|
40 */
|
nuclear@0
|
41
|
nuclear@0
|
42 /** @file Implementation of the MDC importer class */
|
nuclear@0
|
43
|
nuclear@0
|
44 #include "AssimpPCH.h"
|
nuclear@0
|
45 #ifndef ASSIMP_BUILD_NO_MDC_IMPORTER
|
nuclear@0
|
46
|
nuclear@0
|
47 // internal headers
|
nuclear@0
|
48 #include "MDCLoader.h"
|
nuclear@0
|
49 #include "MD3FileData.h"
|
nuclear@0
|
50 #include "MDCNormalTable.h" // shouldn't be included by other units
|
nuclear@0
|
51
|
nuclear@0
|
52 using namespace Assimp;
|
nuclear@0
|
53 using namespace Assimp::MDC;
|
nuclear@0
|
54
|
nuclear@0
|
55 static const aiImporterDesc desc = {
|
nuclear@0
|
56 "Return To Castle Wolfenstein Mesh Importer",
|
nuclear@0
|
57 "",
|
nuclear@0
|
58 "",
|
nuclear@0
|
59 "",
|
nuclear@0
|
60 aiImporterFlags_SupportBinaryFlavour,
|
nuclear@0
|
61 0,
|
nuclear@0
|
62 0,
|
nuclear@0
|
63 0,
|
nuclear@0
|
64 0,
|
nuclear@0
|
65 "mdc"
|
nuclear@0
|
66 };
|
nuclear@0
|
67
|
nuclear@0
|
68 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
69 void MDC::BuildVertex(const Frame& frame,
|
nuclear@0
|
70 const BaseVertex& bvert,
|
nuclear@0
|
71 const CompressedVertex& cvert,
|
nuclear@0
|
72 aiVector3D& vXYZOut,
|
nuclear@0
|
73 aiVector3D& vNorOut)
|
nuclear@0
|
74 {
|
nuclear@0
|
75 // compute the position
|
nuclear@0
|
76 const float xd = (cvert.xd - AI_MDC_CVERT_BIAS) * AI_MDC_DELTA_SCALING;
|
nuclear@0
|
77 const float yd = (cvert.yd - AI_MDC_CVERT_BIAS) * AI_MDC_DELTA_SCALING;
|
nuclear@0
|
78 const float zd = (cvert.zd - AI_MDC_CVERT_BIAS) * AI_MDC_DELTA_SCALING;
|
nuclear@0
|
79 vXYZOut.x = frame.localOrigin.x + AI_MDC_BASE_SCALING * (bvert.x + xd);
|
nuclear@0
|
80 vXYZOut.y = frame.localOrigin.y + AI_MDC_BASE_SCALING * (bvert.y + yd);
|
nuclear@0
|
81 vXYZOut.z = frame.localOrigin.z + AI_MDC_BASE_SCALING * (bvert.z + zd);
|
nuclear@0
|
82
|
nuclear@0
|
83 // compute the normal vector .. ehm ... lookup it in the table :-)
|
nuclear@0
|
84 vNorOut.x = mdcNormals[cvert.nd][0];
|
nuclear@0
|
85 vNorOut.y = mdcNormals[cvert.nd][1];
|
nuclear@0
|
86 vNorOut.z = mdcNormals[cvert.nd][2];
|
nuclear@0
|
87 }
|
nuclear@0
|
88
|
nuclear@0
|
89 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
90 // Constructor to be privately used by Importer
|
nuclear@0
|
91 MDCImporter::MDCImporter()
|
nuclear@0
|
92 {
|
nuclear@0
|
93 }
|
nuclear@0
|
94
|
nuclear@0
|
95 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
96 // Destructor, private as well
|
nuclear@0
|
97 MDCImporter::~MDCImporter()
|
nuclear@0
|
98 {
|
nuclear@0
|
99 }
|
nuclear@0
|
100 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
101 // Returns whether the class can handle the format of the given file.
|
nuclear@0
|
102 bool MDCImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
|
nuclear@0
|
103 {
|
nuclear@0
|
104 const std::string extension = GetExtension(pFile);
|
nuclear@0
|
105 if (extension == "mdc")
|
nuclear@0
|
106 return true;
|
nuclear@0
|
107
|
nuclear@0
|
108 // if check for extension is not enough, check for the magic tokens
|
nuclear@0
|
109 if (!extension.length() || checkSig) {
|
nuclear@0
|
110 uint32_t tokens[1];
|
nuclear@0
|
111 tokens[0] = AI_MDC_MAGIC_NUMBER_LE;
|
nuclear@0
|
112 return CheckMagicToken(pIOHandler,pFile,tokens,1);
|
nuclear@0
|
113 }
|
nuclear@0
|
114 return false;
|
nuclear@0
|
115 }
|
nuclear@0
|
116
|
nuclear@0
|
117 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
118 const aiImporterDesc* MDCImporter::GetInfo () const
|
nuclear@0
|
119 {
|
nuclear@0
|
120 return &desc;
|
nuclear@0
|
121 }
|
nuclear@0
|
122
|
nuclear@0
|
123 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
124 // Validate the header of the given MDC file
|
nuclear@0
|
125 void MDCImporter::ValidateHeader()
|
nuclear@0
|
126 {
|
nuclear@0
|
127 AI_SWAP4( this->pcHeader->ulVersion );
|
nuclear@0
|
128 AI_SWAP4( this->pcHeader->ulFlags );
|
nuclear@0
|
129 AI_SWAP4( this->pcHeader->ulNumFrames );
|
nuclear@0
|
130 AI_SWAP4( this->pcHeader->ulNumTags );
|
nuclear@0
|
131 AI_SWAP4( this->pcHeader->ulNumSurfaces );
|
nuclear@0
|
132 AI_SWAP4( this->pcHeader->ulNumSkins );
|
nuclear@0
|
133 AI_SWAP4( this->pcHeader->ulOffsetBorderFrames );
|
nuclear@0
|
134
|
nuclear@0
|
135 if (pcHeader->ulIdent != AI_MDC_MAGIC_NUMBER_BE &&
|
nuclear@0
|
136 pcHeader->ulIdent != AI_MDC_MAGIC_NUMBER_LE)
|
nuclear@0
|
137 {
|
nuclear@0
|
138 char szBuffer[5];
|
nuclear@0
|
139 szBuffer[0] = ((char*)&pcHeader->ulIdent)[0];
|
nuclear@0
|
140 szBuffer[1] = ((char*)&pcHeader->ulIdent)[1];
|
nuclear@0
|
141 szBuffer[2] = ((char*)&pcHeader->ulIdent)[2];
|
nuclear@0
|
142 szBuffer[3] = ((char*)&pcHeader->ulIdent)[3];
|
nuclear@0
|
143 szBuffer[4] = '\0';
|
nuclear@0
|
144
|
nuclear@0
|
145 throw DeadlyImportError("Invalid MDC magic word: should be IDPC, the "
|
nuclear@0
|
146 "magic word found is " + std::string( szBuffer ));
|
nuclear@0
|
147 }
|
nuclear@0
|
148
|
nuclear@0
|
149 if (pcHeader->ulVersion != AI_MDC_VERSION)
|
nuclear@0
|
150 DefaultLogger::get()->warn("Unsupported MDC file version (2 (AI_MDC_VERSION) was expected)");
|
nuclear@0
|
151
|
nuclear@0
|
152 if (pcHeader->ulOffsetBorderFrames + pcHeader->ulNumFrames * sizeof(MDC::Frame) > this->fileSize ||
|
nuclear@0
|
153 pcHeader->ulOffsetSurfaces + pcHeader->ulNumSurfaces * sizeof(MDC::Surface) > this->fileSize)
|
nuclear@0
|
154 {
|
nuclear@0
|
155 throw DeadlyImportError("Some of the offset values in the MDC header are invalid "
|
nuclear@0
|
156 "and point to something behind the file.");
|
nuclear@0
|
157 }
|
nuclear@0
|
158
|
nuclear@0
|
159 if (this->configFrameID >= this->pcHeader->ulNumFrames)
|
nuclear@0
|
160 throw DeadlyImportError("The requested frame is not available");
|
nuclear@0
|
161 }
|
nuclear@0
|
162
|
nuclear@0
|
163 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
164 // Validate the header of a given MDC file surface
|
nuclear@0
|
165 void MDCImporter::ValidateSurfaceHeader(BE_NCONST MDC::Surface* pcSurf)
|
nuclear@0
|
166 {
|
nuclear@0
|
167 AI_SWAP4(pcSurf->ulFlags);
|
nuclear@0
|
168 AI_SWAP4(pcSurf->ulNumCompFrames);
|
nuclear@0
|
169 AI_SWAP4(pcSurf->ulNumBaseFrames);
|
nuclear@0
|
170 AI_SWAP4(pcSurf->ulNumShaders);
|
nuclear@0
|
171 AI_SWAP4(pcSurf->ulNumVertices);
|
nuclear@0
|
172 AI_SWAP4(pcSurf->ulNumTriangles);
|
nuclear@0
|
173 AI_SWAP4(pcSurf->ulOffsetTriangles);
|
nuclear@0
|
174 AI_SWAP4(pcSurf->ulOffsetTexCoords);
|
nuclear@0
|
175 AI_SWAP4(pcSurf->ulOffsetBaseVerts);
|
nuclear@0
|
176 AI_SWAP4(pcSurf->ulOffsetCompVerts);
|
nuclear@0
|
177 AI_SWAP4(pcSurf->ulOffsetFrameBaseFrames);
|
nuclear@0
|
178 AI_SWAP4(pcSurf->ulOffsetFrameCompFrames);
|
nuclear@0
|
179 AI_SWAP4(pcSurf->ulOffsetEnd);
|
nuclear@0
|
180
|
nuclear@0
|
181 const unsigned int iMax = this->fileSize - (unsigned int)((int8_t*)pcSurf-(int8_t*)pcHeader);
|
nuclear@0
|
182
|
nuclear@0
|
183 if (pcSurf->ulOffsetBaseVerts + pcSurf->ulNumVertices * sizeof(MDC::BaseVertex) > iMax ||
|
nuclear@0
|
184 (pcSurf->ulNumCompFrames && pcSurf->ulOffsetCompVerts + pcSurf->ulNumVertices * sizeof(MDC::CompressedVertex) > iMax) ||
|
nuclear@0
|
185 pcSurf->ulOffsetTriangles + pcSurf->ulNumTriangles * sizeof(MDC::Triangle) > iMax ||
|
nuclear@0
|
186 pcSurf->ulOffsetTexCoords + pcSurf->ulNumVertices * sizeof(MDC::TexturCoord) > iMax ||
|
nuclear@0
|
187 pcSurf->ulOffsetShaders + pcSurf->ulNumShaders * sizeof(MDC::Shader) > iMax ||
|
nuclear@0
|
188 pcSurf->ulOffsetFrameBaseFrames + pcSurf->ulNumBaseFrames * 2 > iMax ||
|
nuclear@0
|
189 (pcSurf->ulNumCompFrames && pcSurf->ulOffsetFrameCompFrames + pcSurf->ulNumCompFrames * 2 > iMax))
|
nuclear@0
|
190 {
|
nuclear@0
|
191 throw DeadlyImportError("Some of the offset values in the MDC surface header "
|
nuclear@0
|
192 "are invalid and point somewhere behind the file.");
|
nuclear@0
|
193 }
|
nuclear@0
|
194 }
|
nuclear@0
|
195
|
nuclear@0
|
196 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
197 // Setup configuration properties
|
nuclear@0
|
198 void MDCImporter::SetupProperties(const Importer* pImp)
|
nuclear@0
|
199 {
|
nuclear@0
|
200 // The AI_CONFIG_IMPORT_MDC_KEYFRAME option overrides the
|
nuclear@0
|
201 // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option.
|
nuclear@0
|
202 if(static_cast<unsigned int>(-1) == (configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MDC_KEYFRAME,-1))){
|
nuclear@0
|
203 configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
|
nuclear@0
|
204 }
|
nuclear@0
|
205 }
|
nuclear@0
|
206
|
nuclear@0
|
207 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
208 // Imports the given file into the given scene structure.
|
nuclear@0
|
209 void MDCImporter::InternReadFile(
|
nuclear@0
|
210 const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
|
nuclear@0
|
211 {
|
nuclear@0
|
212 boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
|
nuclear@0
|
213
|
nuclear@0
|
214 // Check whether we can read from the file
|
nuclear@0
|
215 if( file.get() == NULL)
|
nuclear@0
|
216 throw DeadlyImportError( "Failed to open MDC file " + pFile + ".");
|
nuclear@0
|
217
|
nuclear@0
|
218 // check whether the mdc file is large enough to contain the file header
|
nuclear@0
|
219 fileSize = (unsigned int)file->FileSize();
|
nuclear@0
|
220 if( fileSize < sizeof(MDC::Header))
|
nuclear@0
|
221 throw DeadlyImportError( "MDC File is too small.");
|
nuclear@0
|
222
|
nuclear@0
|
223 std::vector<unsigned char> mBuffer2(fileSize);
|
nuclear@0
|
224 file->Read( &mBuffer2[0], 1, fileSize);
|
nuclear@0
|
225 mBuffer = &mBuffer2[0];
|
nuclear@0
|
226
|
nuclear@0
|
227 // validate the file header
|
nuclear@0
|
228 this->pcHeader = (BE_NCONST MDC::Header*)this->mBuffer;
|
nuclear@0
|
229 this->ValidateHeader();
|
nuclear@0
|
230
|
nuclear@0
|
231 std::vector<std::string> aszShaders;
|
nuclear@0
|
232
|
nuclear@0
|
233 // get a pointer to the frame we want to read
|
nuclear@0
|
234 BE_NCONST MDC::Frame* pcFrame = (BE_NCONST MDC::Frame*)(this->mBuffer+
|
nuclear@0
|
235 this->pcHeader->ulOffsetBorderFrames);
|
nuclear@0
|
236
|
nuclear@0
|
237 // no need to swap the other members, we won't need them
|
nuclear@0
|
238 pcFrame += configFrameID;
|
nuclear@0
|
239 AI_SWAP4( pcFrame->localOrigin[0] );
|
nuclear@0
|
240 AI_SWAP4( pcFrame->localOrigin[1] );
|
nuclear@0
|
241 AI_SWAP4( pcFrame->localOrigin[2] );
|
nuclear@0
|
242
|
nuclear@0
|
243 // get the number of valid surfaces
|
nuclear@0
|
244 BE_NCONST MDC::Surface* pcSurface, *pcSurface2;
|
nuclear@0
|
245 pcSurface = pcSurface2 = new (mBuffer + pcHeader->ulOffsetSurfaces) MDC::Surface;
|
nuclear@0
|
246 unsigned int iNumShaders = 0;
|
nuclear@0
|
247 for (unsigned int i = 0; i < pcHeader->ulNumSurfaces;++i)
|
nuclear@0
|
248 {
|
nuclear@0
|
249 // validate the surface header
|
nuclear@0
|
250 this->ValidateSurfaceHeader(pcSurface2);
|
nuclear@0
|
251
|
nuclear@0
|
252 if (pcSurface2->ulNumVertices && pcSurface2->ulNumTriangles)++pScene->mNumMeshes;
|
nuclear@0
|
253 iNumShaders += pcSurface2->ulNumShaders;
|
nuclear@0
|
254 pcSurface2 = new ((int8_t*)pcSurface2 + pcSurface2->ulOffsetEnd) MDC::Surface;
|
nuclear@0
|
255 }
|
nuclear@0
|
256 aszShaders.reserve(iNumShaders);
|
nuclear@0
|
257 pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
|
nuclear@0
|
258
|
nuclear@0
|
259 // necessary that we don't crash if an exception occurs
|
nuclear@0
|
260 for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
|
nuclear@0
|
261 pScene->mMeshes[i] = NULL;
|
nuclear@0
|
262
|
nuclear@0
|
263 // now read all surfaces
|
nuclear@0
|
264 unsigned int iDefaultMatIndex = UINT_MAX;
|
nuclear@0
|
265 for (unsigned int i = 0, iNum = 0; i < pcHeader->ulNumSurfaces;++i)
|
nuclear@0
|
266 {
|
nuclear@0
|
267 if (!pcSurface->ulNumVertices || !pcSurface->ulNumTriangles)continue;
|
nuclear@0
|
268 aiMesh* pcMesh = pScene->mMeshes[iNum++] = new aiMesh();
|
nuclear@0
|
269
|
nuclear@0
|
270 pcMesh->mNumFaces = pcSurface->ulNumTriangles;
|
nuclear@0
|
271 pcMesh->mNumVertices = pcMesh->mNumFaces * 3;
|
nuclear@0
|
272
|
nuclear@0
|
273 // store the name of the surface for use as node name.
|
nuclear@0
|
274 // FIX: make sure there is a 0 termination
|
nuclear@0
|
275 const_cast<char&>(pcSurface->ucName[AI_MDC_MAXQPATH-1]) = '\0';
|
nuclear@0
|
276 pcMesh->mTextureCoords[3] = (aiVector3D*)pcSurface->ucName;
|
nuclear@0
|
277
|
nuclear@0
|
278 // go to the first shader in the file. ignore the others.
|
nuclear@0
|
279 if (pcSurface->ulNumShaders)
|
nuclear@0
|
280 {
|
nuclear@0
|
281 const MDC::Shader* pcShader = (const MDC::Shader*)((int8_t*)pcSurface + pcSurface->ulOffsetShaders);
|
nuclear@0
|
282 pcMesh->mMaterialIndex = (unsigned int)aszShaders.size();
|
nuclear@0
|
283
|
nuclear@0
|
284 // create a new shader
|
nuclear@0
|
285 aszShaders.push_back(std::string( pcShader->ucName, std::min(
|
nuclear@0
|
286 ::strlen(pcShader->ucName),sizeof(pcShader->ucName)) ));
|
nuclear@0
|
287 }
|
nuclear@0
|
288 // need to create a default material
|
nuclear@0
|
289 else if (UINT_MAX == iDefaultMatIndex)
|
nuclear@0
|
290 {
|
nuclear@0
|
291 pcMesh->mMaterialIndex = iDefaultMatIndex = (unsigned int)aszShaders.size();
|
nuclear@0
|
292 aszShaders.push_back(std::string());
|
nuclear@0
|
293 }
|
nuclear@0
|
294 // otherwise assign a reference to the default material
|
nuclear@0
|
295 else pcMesh->mMaterialIndex = iDefaultMatIndex;
|
nuclear@0
|
296
|
nuclear@0
|
297 // allocate output storage for the mesh
|
nuclear@0
|
298 aiVector3D* pcVertCur = pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices];
|
nuclear@0
|
299 aiVector3D* pcNorCur = pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices];
|
nuclear@0
|
300 aiVector3D* pcUVCur = pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices];
|
nuclear@0
|
301 aiFace* pcFaceCur = pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
|
nuclear@0
|
302
|
nuclear@0
|
303 // create all vertices/faces
|
nuclear@0
|
304 BE_NCONST MDC::Triangle* pcTriangle = (BE_NCONST MDC::Triangle*)
|
nuclear@0
|
305 ((int8_t*)pcSurface+pcSurface->ulOffsetTriangles);
|
nuclear@0
|
306
|
nuclear@0
|
307 BE_NCONST MDC::TexturCoord* const pcUVs = (BE_NCONST MDC::TexturCoord*)
|
nuclear@0
|
308 ((int8_t*)pcSurface+pcSurface->ulOffsetTexCoords);
|
nuclear@0
|
309
|
nuclear@0
|
310 // get a pointer to the uncompressed vertices
|
nuclear@0
|
311 int16_t iOfs = *((int16_t*) ((int8_t*) pcSurface +
|
nuclear@0
|
312 pcSurface->ulOffsetFrameBaseFrames) + this->configFrameID);
|
nuclear@0
|
313
|
nuclear@0
|
314 AI_SWAP2(iOfs);
|
nuclear@0
|
315
|
nuclear@0
|
316 BE_NCONST MDC::BaseVertex* const pcVerts = (BE_NCONST MDC::BaseVertex*)
|
nuclear@0
|
317 ((int8_t*)pcSurface+pcSurface->ulOffsetBaseVerts) +
|
nuclear@0
|
318 ((int)iOfs * pcSurface->ulNumVertices * 4);
|
nuclear@0
|
319
|
nuclear@0
|
320 // do the main swapping stuff ...
|
nuclear@0
|
321 #if (defined AI_BUILD_BIG_ENDIAN)
|
nuclear@0
|
322
|
nuclear@0
|
323 // swap all triangles
|
nuclear@0
|
324 for (unsigned int i = 0; i < pcSurface->ulNumTriangles;++i)
|
nuclear@0
|
325 {
|
nuclear@0
|
326 AI_SWAP4( pcTriangle[i].aiIndices[0] );
|
nuclear@0
|
327 AI_SWAP4( pcTriangle[i].aiIndices[1] );
|
nuclear@0
|
328 AI_SWAP4( pcTriangle[i].aiIndices[2] );
|
nuclear@0
|
329 }
|
nuclear@0
|
330
|
nuclear@0
|
331 // swap all vertices
|
nuclear@0
|
332 for (unsigned int i = 0; i < pcSurface->ulNumVertices*pcSurface->ulNumBaseFrames;++i)
|
nuclear@0
|
333 {
|
nuclear@0
|
334 AI_SWAP2( pcVerts->normal );
|
nuclear@0
|
335 AI_SWAP2( pcVerts->x );
|
nuclear@0
|
336 AI_SWAP2( pcVerts->y );
|
nuclear@0
|
337 AI_SWAP2( pcVerts->z );
|
nuclear@0
|
338 }
|
nuclear@0
|
339
|
nuclear@0
|
340 // swap all texture coordinates
|
nuclear@0
|
341 for (unsigned int i = 0; i < pcSurface->ulNumVertices;++i)
|
nuclear@0
|
342 {
|
nuclear@0
|
343 AI_SWAP4( pcUVs->v );
|
nuclear@0
|
344 AI_SWAP4( pcUVs->v );
|
nuclear@0
|
345 }
|
nuclear@0
|
346
|
nuclear@0
|
347 #endif
|
nuclear@0
|
348
|
nuclear@0
|
349 const MDC::CompressedVertex* pcCVerts = NULL;
|
nuclear@0
|
350 int16_t* mdcCompVert = NULL;
|
nuclear@0
|
351
|
nuclear@0
|
352 // access compressed frames for large frame numbers, but never for the first
|
nuclear@0
|
353 if( this->configFrameID && pcSurface->ulNumCompFrames > 0 )
|
nuclear@0
|
354 {
|
nuclear@0
|
355 mdcCompVert = (int16_t*) ((int8_t*)pcSurface+pcSurface->ulOffsetFrameCompFrames) + this->configFrameID;
|
nuclear@0
|
356 AI_SWAP2P(mdcCompVert);
|
nuclear@0
|
357 if( *mdcCompVert >= 0 )
|
nuclear@0
|
358 {
|
nuclear@0
|
359 pcCVerts = (const MDC::CompressedVertex*)((int8_t*)pcSurface +
|
nuclear@0
|
360 pcSurface->ulOffsetCompVerts) + *mdcCompVert * pcSurface->ulNumVertices;
|
nuclear@0
|
361 }
|
nuclear@0
|
362 else mdcCompVert = NULL;
|
nuclear@0
|
363 }
|
nuclear@0
|
364
|
nuclear@0
|
365 // copy all faces
|
nuclear@0
|
366 for (unsigned int iFace = 0; iFace < pcSurface->ulNumTriangles;++iFace,
|
nuclear@0
|
367 ++pcTriangle,++pcFaceCur)
|
nuclear@0
|
368 {
|
nuclear@0
|
369 const unsigned int iOutIndex = iFace*3;
|
nuclear@0
|
370 pcFaceCur->mNumIndices = 3;
|
nuclear@0
|
371 pcFaceCur->mIndices = new unsigned int[3];
|
nuclear@0
|
372
|
nuclear@0
|
373 for (unsigned int iIndex = 0; iIndex < 3;++iIndex,
|
nuclear@0
|
374 ++pcVertCur,++pcUVCur,++pcNorCur)
|
nuclear@0
|
375 {
|
nuclear@0
|
376 uint32_t quak = pcTriangle->aiIndices[iIndex];
|
nuclear@0
|
377 if (quak >= pcSurface->ulNumVertices)
|
nuclear@0
|
378 {
|
nuclear@0
|
379 DefaultLogger::get()->error("MDC vertex index is out of range");
|
nuclear@0
|
380 quak = pcSurface->ulNumVertices-1;
|
nuclear@0
|
381 }
|
nuclear@0
|
382
|
nuclear@0
|
383 // compressed vertices?
|
nuclear@0
|
384 if (mdcCompVert)
|
nuclear@0
|
385 {
|
nuclear@0
|
386 MDC::BuildVertex(*pcFrame,pcVerts[quak],pcCVerts[quak],
|
nuclear@0
|
387 *pcVertCur,*pcNorCur);
|
nuclear@0
|
388 }
|
nuclear@0
|
389 else
|
nuclear@0
|
390 {
|
nuclear@0
|
391 // copy position
|
nuclear@0
|
392 pcVertCur->x = pcVerts[quak].x * AI_MDC_BASE_SCALING;
|
nuclear@0
|
393 pcVertCur->y = pcVerts[quak].y * AI_MDC_BASE_SCALING;
|
nuclear@0
|
394 pcVertCur->z = pcVerts[quak].z * AI_MDC_BASE_SCALING;
|
nuclear@0
|
395
|
nuclear@0
|
396 // copy normals
|
nuclear@0
|
397 MD3::LatLngNormalToVec3( pcVerts[quak].normal, &pcNorCur->x );
|
nuclear@0
|
398
|
nuclear@0
|
399 // copy texture coordinates
|
nuclear@0
|
400 pcUVCur->x = pcUVs[quak].u;
|
nuclear@0
|
401 pcUVCur->y = 1.0f-pcUVs[quak].v; // DX to OGL
|
nuclear@0
|
402 }
|
nuclear@0
|
403 pcVertCur->x += pcFrame->localOrigin[0] ;
|
nuclear@0
|
404 pcVertCur->y += pcFrame->localOrigin[1] ;
|
nuclear@0
|
405 pcVertCur->z += pcFrame->localOrigin[2] ;
|
nuclear@0
|
406 }
|
nuclear@0
|
407
|
nuclear@0
|
408 // swap the face order - DX to OGL
|
nuclear@0
|
409 pcFaceCur->mIndices[0] = iOutIndex + 2;
|
nuclear@0
|
410 pcFaceCur->mIndices[1] = iOutIndex + 1;
|
nuclear@0
|
411 pcFaceCur->mIndices[2] = iOutIndex + 0;
|
nuclear@0
|
412 }
|
nuclear@0
|
413
|
nuclear@0
|
414 pcSurface = new ((int8_t*)pcSurface + pcSurface->ulOffsetEnd) MDC::Surface;
|
nuclear@0
|
415 }
|
nuclear@0
|
416
|
nuclear@0
|
417 // create a flat node graph with a root node and one child for each surface
|
nuclear@0
|
418 if (!pScene->mNumMeshes)
|
nuclear@0
|
419 throw DeadlyImportError( "Invalid MDC file: File contains no valid mesh");
|
nuclear@0
|
420 else if (1 == pScene->mNumMeshes)
|
nuclear@0
|
421 {
|
nuclear@0
|
422 pScene->mRootNode = new aiNode();
|
nuclear@0
|
423 pScene->mRootNode->mName.Set(std::string((const char*)pScene->mMeshes[0]->mTextureCoords[3]));
|
nuclear@0
|
424 pScene->mRootNode->mNumMeshes = 1;
|
nuclear@0
|
425 pScene->mRootNode->mMeshes = new unsigned int[1];
|
nuclear@0
|
426 pScene->mRootNode->mMeshes[0] = 0;
|
nuclear@0
|
427 }
|
nuclear@0
|
428 else
|
nuclear@0
|
429 {
|
nuclear@0
|
430 pScene->mRootNode = new aiNode();
|
nuclear@0
|
431 pScene->mRootNode->mNumChildren = pScene->mNumMeshes;
|
nuclear@0
|
432 pScene->mRootNode->mChildren = new aiNode*[pScene->mNumMeshes];
|
nuclear@0
|
433 pScene->mRootNode->mName.Set("<root>");
|
nuclear@0
|
434 for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
|
nuclear@0
|
435 {
|
nuclear@0
|
436 aiNode* pcNode = pScene->mRootNode->mChildren[i] = new aiNode();
|
nuclear@0
|
437 pcNode->mParent = pScene->mRootNode;
|
nuclear@0
|
438 pcNode->mName.Set(std::string((const char*)pScene->mMeshes[i]->mTextureCoords[3]));
|
nuclear@0
|
439 pcNode->mNumMeshes = 1;
|
nuclear@0
|
440 pcNode->mMeshes = new unsigned int[1];
|
nuclear@0
|
441 pcNode->mMeshes[0] = i;
|
nuclear@0
|
442 }
|
nuclear@0
|
443 }
|
nuclear@0
|
444
|
nuclear@0
|
445 // make sure we invalidate the pointer to the mesh name
|
nuclear@0
|
446 for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
|
nuclear@0
|
447 pScene->mMeshes[i]->mTextureCoords[3] = NULL;
|
nuclear@0
|
448
|
nuclear@0
|
449 // create materials
|
nuclear@0
|
450 pScene->mNumMaterials = (unsigned int)aszShaders.size();
|
nuclear@0
|
451 pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
|
nuclear@0
|
452 for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
|
nuclear@0
|
453 {
|
nuclear@0
|
454 aiMaterial* pcMat = new aiMaterial();
|
nuclear@0
|
455 pScene->mMaterials[i] = pcMat;
|
nuclear@0
|
456
|
nuclear@0
|
457 const std::string& name = aszShaders[i];
|
nuclear@0
|
458
|
nuclear@0
|
459 int iMode = (int)aiShadingMode_Gouraud;
|
nuclear@0
|
460 pcMat->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
|
nuclear@0
|
461
|
nuclear@0
|
462 // add a small ambient color value - RtCW seems to have one
|
nuclear@0
|
463 aiColor3D clr;
|
nuclear@0
|
464 clr.b = clr.g = clr.r = 0.05f;
|
nuclear@0
|
465 pcMat->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
|
nuclear@0
|
466
|
nuclear@0
|
467 if (name.length())clr.b = clr.g = clr.r = 1.0f;
|
nuclear@0
|
468 else clr.b = clr.g = clr.r = 0.6f;
|
nuclear@0
|
469
|
nuclear@0
|
470 pcMat->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
|
nuclear@0
|
471 pcMat->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
|
nuclear@0
|
472
|
nuclear@0
|
473 if (name.length())
|
nuclear@0
|
474 {
|
nuclear@0
|
475 aiString path;
|
nuclear@0
|
476 path.Set(name);
|
nuclear@0
|
477 pcMat->AddProperty(&path,AI_MATKEY_TEXTURE_DIFFUSE(0));
|
nuclear@0
|
478 }
|
nuclear@0
|
479 }
|
nuclear@0
|
480 }
|
nuclear@0
|
481
|
nuclear@0
|
482 #endif // !! ASSIMP_BUILD_NO_MDC_IMPORTER
|