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 MDL importer class */
|
nuclear@0
|
43
|
nuclear@0
|
44 #include "AssimpPCH.h"
|
nuclear@0
|
45 #ifndef ASSIMP_BUILD_NO_HMP_IMPORTER
|
nuclear@0
|
46
|
nuclear@0
|
47 // internal headers
|
nuclear@0
|
48 #include "HMPLoader.h"
|
nuclear@0
|
49 #include "MD2FileData.h"
|
nuclear@0
|
50
|
nuclear@0
|
51 using namespace Assimp;
|
nuclear@0
|
52
|
nuclear@0
|
53 static const aiImporterDesc desc = {
|
nuclear@0
|
54 "3D GameStudio Heightmap (HMP) Importer",
|
nuclear@0
|
55 "",
|
nuclear@0
|
56 "",
|
nuclear@0
|
57 "",
|
nuclear@0
|
58 aiImporterFlags_SupportBinaryFlavour,
|
nuclear@0
|
59 0,
|
nuclear@0
|
60 0,
|
nuclear@0
|
61 0,
|
nuclear@0
|
62 0,
|
nuclear@0
|
63 "hmp"
|
nuclear@0
|
64 };
|
nuclear@0
|
65
|
nuclear@0
|
66 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
67 // Constructor to be privately used by Importer
|
nuclear@0
|
68 HMPImporter::HMPImporter()
|
nuclear@0
|
69 {
|
nuclear@0
|
70 // nothing to do here
|
nuclear@0
|
71 }
|
nuclear@0
|
72
|
nuclear@0
|
73 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
74 // Destructor, private as well
|
nuclear@0
|
75 HMPImporter::~HMPImporter()
|
nuclear@0
|
76 {
|
nuclear@0
|
77 // nothing to do here
|
nuclear@0
|
78 }
|
nuclear@0
|
79
|
nuclear@0
|
80 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
81 // Returns whether the class can handle the format of the given file.
|
nuclear@0
|
82 bool HMPImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool cs) const
|
nuclear@0
|
83 {
|
nuclear@0
|
84 const std::string extension = GetExtension(pFile);
|
nuclear@0
|
85 if (extension == "hmp" )
|
nuclear@0
|
86 return true;
|
nuclear@0
|
87
|
nuclear@0
|
88 // if check for extension is not enough, check for the magic tokens
|
nuclear@0
|
89 if (!extension.length() || cs) {
|
nuclear@0
|
90 uint32_t tokens[3];
|
nuclear@0
|
91 tokens[0] = AI_HMP_MAGIC_NUMBER_LE_4;
|
nuclear@0
|
92 tokens[1] = AI_HMP_MAGIC_NUMBER_LE_5;
|
nuclear@0
|
93 tokens[2] = AI_HMP_MAGIC_NUMBER_LE_7;
|
nuclear@0
|
94 return CheckMagicToken(pIOHandler,pFile,tokens,3,0);
|
nuclear@0
|
95 }
|
nuclear@0
|
96 return false;
|
nuclear@0
|
97 }
|
nuclear@0
|
98
|
nuclear@0
|
99 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
100 // Get list of all file extensions that are handled by this loader
|
nuclear@0
|
101 const aiImporterDesc* HMPImporter::GetInfo () const
|
nuclear@0
|
102 {
|
nuclear@0
|
103 return &desc;
|
nuclear@0
|
104 }
|
nuclear@0
|
105
|
nuclear@0
|
106 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
107 // Imports the given file into the given scene structure.
|
nuclear@0
|
108 void HMPImporter::InternReadFile( const std::string& pFile,
|
nuclear@0
|
109 aiScene* _pScene, IOSystem* _pIOHandler)
|
nuclear@0
|
110 {
|
nuclear@0
|
111 pScene = _pScene;
|
nuclear@0
|
112 pIOHandler = _pIOHandler;
|
nuclear@0
|
113 boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
|
nuclear@0
|
114
|
nuclear@0
|
115 // Check whether we can read from the file
|
nuclear@0
|
116 if( file.get() == NULL)
|
nuclear@0
|
117 throw DeadlyImportError( "Failed to open HMP file " + pFile + ".");
|
nuclear@0
|
118
|
nuclear@0
|
119 // Check whether the HMP file is large enough to contain
|
nuclear@0
|
120 // at least the file header
|
nuclear@0
|
121 const size_t fileSize = file->FileSize();
|
nuclear@0
|
122 if( fileSize < 50)
|
nuclear@0
|
123 throw DeadlyImportError( "HMP File is too small.");
|
nuclear@0
|
124
|
nuclear@0
|
125 // Allocate storage and copy the contents of the file to a memory buffer
|
nuclear@0
|
126 std::vector<uint8_t> buffer(fileSize);
|
nuclear@0
|
127 mBuffer = &buffer[0];
|
nuclear@0
|
128 file->Read( (void*)mBuffer, 1, fileSize);
|
nuclear@0
|
129 iFileSize = (unsigned int)fileSize;
|
nuclear@0
|
130
|
nuclear@0
|
131 // Determine the file subtype and call the appropriate member function
|
nuclear@0
|
132 const uint32_t iMagic = *((uint32_t*)this->mBuffer);
|
nuclear@0
|
133
|
nuclear@0
|
134 // HMP4 format
|
nuclear@0
|
135 if (AI_HMP_MAGIC_NUMBER_LE_4 == iMagic ||
|
nuclear@0
|
136 AI_HMP_MAGIC_NUMBER_BE_4 == iMagic)
|
nuclear@0
|
137 {
|
nuclear@0
|
138 DefaultLogger::get()->debug("HMP subtype: 3D GameStudio A4, magic word is HMP4");
|
nuclear@0
|
139 InternReadFile_HMP4();
|
nuclear@0
|
140 }
|
nuclear@0
|
141 // HMP5 format
|
nuclear@0
|
142 else if (AI_HMP_MAGIC_NUMBER_LE_5 == iMagic ||
|
nuclear@0
|
143 AI_HMP_MAGIC_NUMBER_BE_5 == iMagic)
|
nuclear@0
|
144 {
|
nuclear@0
|
145 DefaultLogger::get()->debug("HMP subtype: 3D GameStudio A5, magic word is HMP5");
|
nuclear@0
|
146 InternReadFile_HMP5();
|
nuclear@0
|
147 }
|
nuclear@0
|
148 // HMP7 format
|
nuclear@0
|
149 else if (AI_HMP_MAGIC_NUMBER_LE_7 == iMagic ||
|
nuclear@0
|
150 AI_HMP_MAGIC_NUMBER_BE_7 == iMagic)
|
nuclear@0
|
151 {
|
nuclear@0
|
152 DefaultLogger::get()->debug("HMP subtype: 3D GameStudio A7, magic word is HMP7");
|
nuclear@0
|
153 InternReadFile_HMP7();
|
nuclear@0
|
154 }
|
nuclear@0
|
155 else
|
nuclear@0
|
156 {
|
nuclear@0
|
157 // Print the magic word to the logger
|
nuclear@0
|
158 char szBuffer[5];
|
nuclear@0
|
159 szBuffer[0] = ((char*)&iMagic)[0];
|
nuclear@0
|
160 szBuffer[1] = ((char*)&iMagic)[1];
|
nuclear@0
|
161 szBuffer[2] = ((char*)&iMagic)[2];
|
nuclear@0
|
162 szBuffer[3] = ((char*)&iMagic)[3];
|
nuclear@0
|
163 szBuffer[4] = '\0';
|
nuclear@0
|
164
|
nuclear@0
|
165 // We're definitely unable to load this file
|
nuclear@0
|
166 throw DeadlyImportError( "Unknown HMP subformat " + pFile +
|
nuclear@0
|
167 ". Magic word (" + szBuffer + ") is not known");
|
nuclear@0
|
168 }
|
nuclear@0
|
169
|
nuclear@0
|
170 // Set the AI_SCENE_FLAGS_TERRAIN bit
|
nuclear@0
|
171 pScene->mFlags |= AI_SCENE_FLAGS_TERRAIN;
|
nuclear@0
|
172
|
nuclear@0
|
173 // File buffer destructs automatically now
|
nuclear@0
|
174 }
|
nuclear@0
|
175
|
nuclear@0
|
176 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
177 void HMPImporter::ValidateHeader_HMP457( )
|
nuclear@0
|
178 {
|
nuclear@0
|
179 const HMP::Header_HMP5* const pcHeader = (const HMP::Header_HMP5*)mBuffer;
|
nuclear@0
|
180
|
nuclear@0
|
181 if (120 > iFileSize)
|
nuclear@0
|
182 {
|
nuclear@0
|
183 throw DeadlyImportError("HMP file is too small (header size is "
|
nuclear@0
|
184 "120 bytes, this file is smaller)");
|
nuclear@0
|
185 }
|
nuclear@0
|
186
|
nuclear@0
|
187 if (!pcHeader->ftrisize_x || !pcHeader->ftrisize_y)
|
nuclear@0
|
188 throw DeadlyImportError("Size of triangles in either x or y direction is zero");
|
nuclear@0
|
189
|
nuclear@0
|
190 if(pcHeader->fnumverts_x < 1.0f || (pcHeader->numverts/pcHeader->fnumverts_x) < 1.0f)
|
nuclear@0
|
191 throw DeadlyImportError("Number of triangles in either x or y direction is zero");
|
nuclear@0
|
192
|
nuclear@0
|
193 if(!pcHeader->numframes)
|
nuclear@0
|
194 throw DeadlyImportError("There are no frames. At least one should be there");
|
nuclear@0
|
195
|
nuclear@0
|
196 }
|
nuclear@0
|
197
|
nuclear@0
|
198 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
199 void HMPImporter::InternReadFile_HMP4( )
|
nuclear@0
|
200 {
|
nuclear@0
|
201 throw DeadlyImportError("HMP4 is currently not supported");
|
nuclear@0
|
202 }
|
nuclear@0
|
203
|
nuclear@0
|
204 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
205 void HMPImporter::InternReadFile_HMP5( )
|
nuclear@0
|
206 {
|
nuclear@0
|
207 // read the file header and skip everything to byte 84
|
nuclear@0
|
208 const HMP::Header_HMP5* pcHeader = (const HMP::Header_HMP5*)mBuffer;
|
nuclear@0
|
209 const unsigned char* szCurrent = (const unsigned char*)(mBuffer+84);
|
nuclear@0
|
210 ValidateHeader_HMP457();
|
nuclear@0
|
211
|
nuclear@0
|
212 // generate an output mesh
|
nuclear@0
|
213 pScene->mNumMeshes = 1;
|
nuclear@0
|
214 pScene->mMeshes = new aiMesh*[1];
|
nuclear@0
|
215 aiMesh* pcMesh = pScene->mMeshes[0] = new aiMesh();
|
nuclear@0
|
216
|
nuclear@0
|
217 pcMesh->mMaterialIndex = 0;
|
nuclear@0
|
218 pcMesh->mVertices = new aiVector3D[pcHeader->numverts];
|
nuclear@0
|
219 pcMesh->mNormals = new aiVector3D[pcHeader->numverts];
|
nuclear@0
|
220
|
nuclear@0
|
221 const unsigned int height = (unsigned int)(pcHeader->numverts / pcHeader->fnumverts_x);
|
nuclear@0
|
222 const unsigned int width = (unsigned int)pcHeader->fnumverts_x;
|
nuclear@0
|
223
|
nuclear@0
|
224 // generate/load a material for the terrain
|
nuclear@0
|
225 CreateMaterial(szCurrent,&szCurrent);
|
nuclear@0
|
226
|
nuclear@0
|
227 // goto offset 120, I don't know why ...
|
nuclear@0
|
228 // (fixme) is this the frame header? I assume yes since it starts with 2.
|
nuclear@0
|
229 szCurrent += 36;
|
nuclear@0
|
230 SizeCheck(szCurrent + sizeof(const HMP::Vertex_HMP7)*height*width);
|
nuclear@0
|
231
|
nuclear@0
|
232 // now load all vertices from the file
|
nuclear@0
|
233 aiVector3D* pcVertOut = pcMesh->mVertices;
|
nuclear@0
|
234 aiVector3D* pcNorOut = pcMesh->mNormals;
|
nuclear@0
|
235 const HMP::Vertex_HMP5* src = (const HMP::Vertex_HMP5*) szCurrent;
|
nuclear@0
|
236 for (unsigned int y = 0; y < height;++y)
|
nuclear@0
|
237 {
|
nuclear@0
|
238 for (unsigned int x = 0; x < width;++x)
|
nuclear@0
|
239 {
|
nuclear@0
|
240 pcVertOut->x = x * pcHeader->ftrisize_x;
|
nuclear@0
|
241 pcVertOut->y = y * pcHeader->ftrisize_y;
|
nuclear@0
|
242 pcVertOut->z = (((float)src->z / 0xffff)-0.5f) * pcHeader->ftrisize_x * 8.0f;
|
nuclear@0
|
243 MD2::LookupNormalIndex(src->normals162index, *pcNorOut );
|
nuclear@0
|
244 ++pcVertOut;++pcNorOut;++src;
|
nuclear@0
|
245 }
|
nuclear@0
|
246 }
|
nuclear@0
|
247
|
nuclear@0
|
248 // generate texture coordinates if necessary
|
nuclear@0
|
249 if (pcHeader->numskins)
|
nuclear@0
|
250 GenerateTextureCoords(width,height);
|
nuclear@0
|
251
|
nuclear@0
|
252 // now build a list of faces
|
nuclear@0
|
253 CreateOutputFaceList(width,height);
|
nuclear@0
|
254
|
nuclear@0
|
255 // there is no nodegraph in HMP files. Simply assign the one mesh
|
nuclear@0
|
256 // (no, not the one ring) to the root node
|
nuclear@0
|
257 pScene->mRootNode = new aiNode();
|
nuclear@0
|
258 pScene->mRootNode->mName.Set("terrain_root");
|
nuclear@0
|
259 pScene->mRootNode->mNumMeshes = 1;
|
nuclear@0
|
260 pScene->mRootNode->mMeshes = new unsigned int[1];
|
nuclear@0
|
261 pScene->mRootNode->mMeshes[0] = 0;
|
nuclear@0
|
262 }
|
nuclear@0
|
263
|
nuclear@0
|
264 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
265 void HMPImporter::InternReadFile_HMP7( )
|
nuclear@0
|
266 {
|
nuclear@0
|
267 // read the file header and skip everything to byte 84
|
nuclear@0
|
268 const HMP::Header_HMP5* const pcHeader = (const HMP::Header_HMP5*)mBuffer;
|
nuclear@0
|
269 const unsigned char* szCurrent = (const unsigned char*)(mBuffer+84);
|
nuclear@0
|
270 ValidateHeader_HMP457();
|
nuclear@0
|
271
|
nuclear@0
|
272 // generate an output mesh
|
nuclear@0
|
273 pScene->mNumMeshes = 1;
|
nuclear@0
|
274 pScene->mMeshes = new aiMesh*[1];
|
nuclear@0
|
275 aiMesh* pcMesh = pScene->mMeshes[0] = new aiMesh();
|
nuclear@0
|
276
|
nuclear@0
|
277 pcMesh->mMaterialIndex = 0;
|
nuclear@0
|
278 pcMesh->mVertices = new aiVector3D[pcHeader->numverts];
|
nuclear@0
|
279 pcMesh->mNormals = new aiVector3D[pcHeader->numverts];
|
nuclear@0
|
280
|
nuclear@0
|
281 const unsigned int height = (unsigned int)(pcHeader->numverts / pcHeader->fnumverts_x);
|
nuclear@0
|
282 const unsigned int width = (unsigned int)pcHeader->fnumverts_x;
|
nuclear@0
|
283
|
nuclear@0
|
284 // generate/load a material for the terrain
|
nuclear@0
|
285 CreateMaterial(szCurrent,&szCurrent);
|
nuclear@0
|
286
|
nuclear@0
|
287 // goto offset 120, I don't know why ...
|
nuclear@0
|
288 // (fixme) is this the frame header? I assume yes since it starts with 2.
|
nuclear@0
|
289 szCurrent += 36;
|
nuclear@0
|
290
|
nuclear@0
|
291 SizeCheck(szCurrent + sizeof(const HMP::Vertex_HMP7)*height*width);
|
nuclear@0
|
292
|
nuclear@0
|
293 // now load all vertices from the file
|
nuclear@0
|
294 aiVector3D* pcVertOut = pcMesh->mVertices;
|
nuclear@0
|
295 aiVector3D* pcNorOut = pcMesh->mNormals;
|
nuclear@0
|
296 const HMP::Vertex_HMP7* src = (const HMP::Vertex_HMP7*) szCurrent;
|
nuclear@0
|
297 for (unsigned int y = 0; y < height;++y)
|
nuclear@0
|
298 {
|
nuclear@0
|
299 for (unsigned int x = 0; x < width;++x)
|
nuclear@0
|
300 {
|
nuclear@0
|
301 pcVertOut->x = x * pcHeader->ftrisize_x;
|
nuclear@0
|
302 pcVertOut->y = y * pcHeader->ftrisize_y;
|
nuclear@0
|
303
|
nuclear@0
|
304 // FIXME: What exctly is the correct scaling factor to use?
|
nuclear@0
|
305 // possibly pcHeader->scale_origin[2] in combination with a
|
nuclear@0
|
306 // signed interpretation of src->z?
|
nuclear@0
|
307 pcVertOut->z = (((float)src->z / 0xffff)-0.5f) * pcHeader->ftrisize_x * 8.0f;
|
nuclear@0
|
308
|
nuclear@0
|
309 pcNorOut->x = ((float)src->normal_x / 0x80 ); // * pcHeader->scale_origin[0];
|
nuclear@0
|
310 pcNorOut->y = ((float)src->normal_y / 0x80 ); // * pcHeader->scale_origin[1];
|
nuclear@0
|
311 pcNorOut->z = 1.0f;
|
nuclear@0
|
312 pcNorOut->Normalize();
|
nuclear@0
|
313
|
nuclear@0
|
314 ++pcVertOut;++pcNorOut;++src;
|
nuclear@0
|
315 }
|
nuclear@0
|
316 }
|
nuclear@0
|
317
|
nuclear@0
|
318 // generate texture coordinates if necessary
|
nuclear@0
|
319 if (pcHeader->numskins)GenerateTextureCoords(width,height);
|
nuclear@0
|
320
|
nuclear@0
|
321 // now build a list of faces
|
nuclear@0
|
322 CreateOutputFaceList(width,height);
|
nuclear@0
|
323
|
nuclear@0
|
324 // there is no nodegraph in HMP files. Simply assign the one mesh
|
nuclear@0
|
325 // (no, not the One Ring) to the root node
|
nuclear@0
|
326 pScene->mRootNode = new aiNode();
|
nuclear@0
|
327 pScene->mRootNode->mName.Set("terrain_root");
|
nuclear@0
|
328 pScene->mRootNode->mNumMeshes = 1;
|
nuclear@0
|
329 pScene->mRootNode->mMeshes = new unsigned int[1];
|
nuclear@0
|
330 pScene->mRootNode->mMeshes[0] = 0;
|
nuclear@0
|
331 }
|
nuclear@0
|
332
|
nuclear@0
|
333 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
334 void HMPImporter::CreateMaterial(const unsigned char* szCurrent,
|
nuclear@0
|
335 const unsigned char** szCurrentOut)
|
nuclear@0
|
336 {
|
nuclear@0
|
337 aiMesh* const pcMesh = pScene->mMeshes[0];
|
nuclear@0
|
338 const HMP::Header_HMP5* const pcHeader = (const HMP::Header_HMP5*)mBuffer;
|
nuclear@0
|
339
|
nuclear@0
|
340 // we don't need to generate texture coordinates if
|
nuclear@0
|
341 // we have no textures in the file ...
|
nuclear@0
|
342 if (pcHeader->numskins)
|
nuclear@0
|
343 {
|
nuclear@0
|
344 pcMesh->mTextureCoords[0] = new aiVector3D[pcHeader->numverts];
|
nuclear@0
|
345 pcMesh->mNumUVComponents[0] = 2;
|
nuclear@0
|
346
|
nuclear@0
|
347 // now read the first skin and skip all others
|
nuclear@0
|
348 ReadFirstSkin(pcHeader->numskins,szCurrent,&szCurrent);
|
nuclear@0
|
349 }
|
nuclear@0
|
350 else
|
nuclear@0
|
351 {
|
nuclear@0
|
352 // generate a default material
|
nuclear@0
|
353 const int iMode = (int)aiShadingMode_Gouraud;
|
nuclear@0
|
354 aiMaterial* pcHelper = new aiMaterial();
|
nuclear@0
|
355 pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
|
nuclear@0
|
356
|
nuclear@0
|
357 aiColor3D clr;
|
nuclear@0
|
358 clr.b = clr.g = clr.r = 0.6f;
|
nuclear@0
|
359 pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
|
nuclear@0
|
360 pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
|
nuclear@0
|
361
|
nuclear@0
|
362 clr.b = clr.g = clr.r = 0.05f;
|
nuclear@0
|
363 pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
|
nuclear@0
|
364
|
nuclear@0
|
365 aiString szName;
|
nuclear@0
|
366 szName.Set(AI_DEFAULT_MATERIAL_NAME);
|
nuclear@0
|
367 pcHelper->AddProperty(&szName,AI_MATKEY_NAME);
|
nuclear@0
|
368
|
nuclear@0
|
369 // add the material to the scene
|
nuclear@0
|
370 pScene->mNumMaterials = 1;
|
nuclear@0
|
371 pScene->mMaterials = new aiMaterial*[1];
|
nuclear@0
|
372 pScene->mMaterials[0] = pcHelper;
|
nuclear@0
|
373 }
|
nuclear@0
|
374 *szCurrentOut = szCurrent;
|
nuclear@0
|
375 }
|
nuclear@0
|
376
|
nuclear@0
|
377 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
378 void HMPImporter::CreateOutputFaceList(unsigned int width,unsigned int height)
|
nuclear@0
|
379 {
|
nuclear@0
|
380 aiMesh* const pcMesh = this->pScene->mMeshes[0];
|
nuclear@0
|
381
|
nuclear@0
|
382 // Allocate enough storage
|
nuclear@0
|
383 pcMesh->mNumFaces = (width-1) * (height-1);
|
nuclear@0
|
384 pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
|
nuclear@0
|
385
|
nuclear@0
|
386 pcMesh->mNumVertices = pcMesh->mNumFaces*4;
|
nuclear@0
|
387 aiVector3D* pcVertices = new aiVector3D[pcMesh->mNumVertices];
|
nuclear@0
|
388 aiVector3D* pcNormals = new aiVector3D[pcMesh->mNumVertices];
|
nuclear@0
|
389
|
nuclear@0
|
390 aiFace* pcFaceOut(pcMesh->mFaces);
|
nuclear@0
|
391 aiVector3D* pcVertOut = pcVertices;
|
nuclear@0
|
392 aiVector3D* pcNorOut = pcNormals;
|
nuclear@0
|
393
|
nuclear@0
|
394 aiVector3D* pcUVs = pcMesh->mTextureCoords[0] ? new aiVector3D[pcMesh->mNumVertices] : NULL;
|
nuclear@0
|
395 aiVector3D* pcUVOut(pcUVs);
|
nuclear@0
|
396
|
nuclear@0
|
397 // Build the terrain square
|
nuclear@0
|
398 unsigned int iCurrent = 0;
|
nuclear@0
|
399 for (unsigned int y = 0; y < height-1;++y) {
|
nuclear@0
|
400 for (unsigned int x = 0; x < width-1;++x,++pcFaceOut) {
|
nuclear@0
|
401 pcFaceOut->mNumIndices = 4;
|
nuclear@0
|
402 pcFaceOut->mIndices = new unsigned int[4];
|
nuclear@0
|
403
|
nuclear@0
|
404 *pcVertOut++ = pcMesh->mVertices[y*width+x];
|
nuclear@0
|
405 *pcVertOut++ = pcMesh->mVertices[(y+1)*width+x];
|
nuclear@0
|
406 *pcVertOut++ = pcMesh->mVertices[(y+1)*width+x+1];
|
nuclear@0
|
407 *pcVertOut++ = pcMesh->mVertices[y*width+x+1];
|
nuclear@0
|
408
|
nuclear@0
|
409
|
nuclear@0
|
410 *pcNorOut++ = pcMesh->mNormals[y*width+x];
|
nuclear@0
|
411 *pcNorOut++ = pcMesh->mNormals[(y+1)*width+x];
|
nuclear@0
|
412 *pcNorOut++ = pcMesh->mNormals[(y+1)*width+x+1];
|
nuclear@0
|
413 *pcNorOut++ = pcMesh->mNormals[y*width+x+1];
|
nuclear@0
|
414
|
nuclear@0
|
415 if (pcMesh->mTextureCoords[0])
|
nuclear@0
|
416 {
|
nuclear@0
|
417 *pcUVOut++ = pcMesh->mTextureCoords[0][y*width+x];
|
nuclear@0
|
418 *pcUVOut++ = pcMesh->mTextureCoords[0][(y+1)*width+x];
|
nuclear@0
|
419 *pcUVOut++ = pcMesh->mTextureCoords[0][(y+1)*width+x+1];
|
nuclear@0
|
420 *pcUVOut++ = pcMesh->mTextureCoords[0][y*width+x+1];
|
nuclear@0
|
421 }
|
nuclear@0
|
422
|
nuclear@0
|
423 for (unsigned int i = 0; i < 4;++i)
|
nuclear@0
|
424 pcFaceOut->mIndices[i] = iCurrent++;
|
nuclear@0
|
425 }
|
nuclear@0
|
426 }
|
nuclear@0
|
427 delete[] pcMesh->mVertices;
|
nuclear@0
|
428 pcMesh->mVertices = pcVertices;
|
nuclear@0
|
429
|
nuclear@0
|
430 delete[] pcMesh->mNormals;
|
nuclear@0
|
431 pcMesh->mNormals = pcNormals;
|
nuclear@0
|
432
|
nuclear@0
|
433 if (pcMesh->mTextureCoords[0])
|
nuclear@0
|
434 {
|
nuclear@0
|
435 delete[] pcMesh->mTextureCoords[0];
|
nuclear@0
|
436 pcMesh->mTextureCoords[0] = pcUVs;
|
nuclear@0
|
437 }
|
nuclear@0
|
438 }
|
nuclear@0
|
439
|
nuclear@0
|
440 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
441 void HMPImporter::ReadFirstSkin(unsigned int iNumSkins, const unsigned char* szCursor,
|
nuclear@0
|
442 const unsigned char** szCursorOut)
|
nuclear@0
|
443 {
|
nuclear@0
|
444 ai_assert(0 != iNumSkins && NULL != szCursor);
|
nuclear@0
|
445
|
nuclear@0
|
446 // read the type of the skin ...
|
nuclear@0
|
447 // sometimes we need to skip 12 bytes here, I don't know why ...
|
nuclear@0
|
448 uint32_t iType = *((uint32_t*)szCursor);szCursor += sizeof(uint32_t);
|
nuclear@0
|
449 if (0 == iType)
|
nuclear@0
|
450 {
|
nuclear@0
|
451 szCursor += sizeof(uint32_t) * 2;
|
nuclear@0
|
452 iType = *((uint32_t*)szCursor);szCursor += sizeof(uint32_t);
|
nuclear@0
|
453 if (!iType)
|
nuclear@0
|
454 throw DeadlyImportError("Unable to read HMP7 skin chunk");
|
nuclear@0
|
455
|
nuclear@0
|
456 }
|
nuclear@0
|
457 // read width and height
|
nuclear@0
|
458 uint32_t iWidth = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t);
|
nuclear@0
|
459 uint32_t iHeight = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t);
|
nuclear@0
|
460
|
nuclear@0
|
461 // allocate an output material
|
nuclear@0
|
462 aiMaterial* pcMat = new aiMaterial();
|
nuclear@0
|
463
|
nuclear@0
|
464 // read the skin, this works exactly as for MDL7
|
nuclear@0
|
465 ParseSkinLump_3DGS_MDL7(szCursor,&szCursor,
|
nuclear@0
|
466 pcMat,iType,iWidth,iHeight);
|
nuclear@0
|
467
|
nuclear@0
|
468 // now we need to skip any other skins ...
|
nuclear@0
|
469 for (unsigned int i = 1; i< iNumSkins;++i)
|
nuclear@0
|
470 {
|
nuclear@0
|
471 iType = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t);
|
nuclear@0
|
472 iWidth = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t);
|
nuclear@0
|
473 iHeight = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t);
|
nuclear@0
|
474
|
nuclear@0
|
475 SkipSkinLump_3DGS_MDL7(szCursor,&szCursor,iType,iWidth,iHeight);
|
nuclear@0
|
476 SizeCheck(szCursor);
|
nuclear@0
|
477 }
|
nuclear@0
|
478
|
nuclear@0
|
479 // setup the material ...
|
nuclear@0
|
480 pScene->mNumMaterials = 1;
|
nuclear@0
|
481 pScene->mMaterials = new aiMaterial*[1];
|
nuclear@0
|
482 pScene->mMaterials[0] = pcMat;
|
nuclear@0
|
483
|
nuclear@0
|
484 *szCursorOut = szCursor;
|
nuclear@0
|
485 }
|
nuclear@0
|
486
|
nuclear@0
|
487 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
488 // Generate proepr texture coords
|
nuclear@0
|
489 void HMPImporter::GenerateTextureCoords(
|
nuclear@0
|
490 const unsigned int width, const unsigned int height)
|
nuclear@0
|
491 {
|
nuclear@0
|
492 ai_assert(NULL != pScene->mMeshes && NULL != pScene->mMeshes[0] &&
|
nuclear@0
|
493 NULL != pScene->mMeshes[0]->mTextureCoords[0]);
|
nuclear@0
|
494
|
nuclear@0
|
495 aiVector3D* uv = pScene->mMeshes[0]->mTextureCoords[0];
|
nuclear@0
|
496
|
nuclear@0
|
497 const float fY = (1.0f / height) + (1.0f / height) / (height-1);
|
nuclear@0
|
498 const float fX = (1.0f / width) + (1.0f / width) / (width-1);
|
nuclear@0
|
499
|
nuclear@0
|
500 for (unsigned int y = 0; y < height;++y) {
|
nuclear@0
|
501 for (unsigned int x = 0; x < width;++x,++uv) {
|
nuclear@0
|
502 uv->y = fY*y;
|
nuclear@0
|
503 uv->x = fX*x;
|
nuclear@0
|
504 uv->z = 0.0f;
|
nuclear@0
|
505 }
|
nuclear@0
|
506 }
|
nuclear@0
|
507 }
|
nuclear@0
|
508
|
nuclear@0
|
509 #endif // !! ASSIMP_BUILD_NO_HMP_IMPORTER
|