vrshoot

view libs/assimp/LWOBLoader.cpp @ 0:b2f14e535253

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 01 Feb 2014 19:58:19 +0200
parents
children
line source
1 /*
2 ---------------------------------------------------------------------------
3 Open Asset Import Library (assimp)
4 ---------------------------------------------------------------------------
6 Copyright (c) 2006-2012, assimp team
8 All rights reserved.
10 Redistribution and use of this software in source and binary forms,
11 with or without modification, are permitted provided that the following
12 conditions are met:
14 * Redistributions of source code must retain the above
15 copyright notice, this list of conditions and the
16 following disclaimer.
18 * Redistributions in binary form must reproduce the above
19 copyright notice, this list of conditions and the
20 following disclaimer in the documentation and/or other
21 materials provided with the distribution.
23 * Neither the name of the assimp team, nor the names of its
24 contributors may be used to endorse or promote products
25 derived from this software without specific prior
26 written permission of the assimp team.
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 ---------------------------------------------------------------------------
40 */
42 /** @file Implementation of the LWO importer class for the older LWOB
43 file formats, including materials */
45 #include "AssimpPCH.h"
46 #ifndef ASSIMP_BUILD_NO_LWO_IMPORTER
48 // Internal headers
49 #include "LWOLoader.h"
50 using namespace Assimp;
53 // ------------------------------------------------------------------------------------------------
54 void LWOImporter::LoadLWOBFile()
55 {
56 LE_NCONST uint8_t* const end = mFileBuffer + fileSize;
57 bool running = true;
58 while (running)
59 {
60 if (mFileBuffer + sizeof(IFF::ChunkHeader) > end)break;
61 LE_NCONST IFF::ChunkHeader* const head = IFF::LoadChunk(mFileBuffer);
63 if (mFileBuffer + head->length > end)
64 {
65 throw DeadlyImportError("LWOB: Invalid chunk length");
66 break;
67 }
68 uint8_t* const next = mFileBuffer+head->length;
69 switch (head->type)
70 {
71 // vertex list
72 case AI_LWO_PNTS:
73 {
74 if (!mCurLayer->mTempPoints.empty())
75 DefaultLogger::get()->warn("LWO: PNTS chunk encountered twice");
76 else LoadLWOPoints(head->length);
77 break;
78 }
79 // face list
80 case AI_LWO_POLS:
81 {
82 if (!mCurLayer->mFaces.empty())
83 DefaultLogger::get()->warn("LWO: POLS chunk encountered twice");
84 else LoadLWOBPolygons(head->length);
85 break;
86 }
87 // list of tags
88 case AI_LWO_SRFS:
89 {
90 if (!mTags->empty())
91 DefaultLogger::get()->warn("LWO: SRFS chunk encountered twice");
92 else LoadLWOTags(head->length);
93 break;
94 }
96 // surface chunk
97 case AI_LWO_SURF:
98 {
99 LoadLWOBSurface(head->length);
100 break;
101 }
102 }
103 mFileBuffer = next;
104 }
105 }
107 // ------------------------------------------------------------------------------------------------
108 void LWOImporter::LoadLWOBPolygons(unsigned int length)
109 {
110 // first find out how many faces and vertices we'll finally need
111 LE_NCONST uint16_t* const end = (LE_NCONST uint16_t*)(mFileBuffer+length);
112 LE_NCONST uint16_t* cursor = (LE_NCONST uint16_t*)mFileBuffer;
114 // perform endianess conversions
115 #ifndef AI_BUILD_BIG_ENDIAN
116 while (cursor < end)ByteSwap::Swap2(cursor++);
117 cursor = (LE_NCONST uint16_t*)mFileBuffer;
118 #endif
120 unsigned int iNumFaces = 0,iNumVertices = 0;
121 CountVertsAndFacesLWOB(iNumVertices,iNumFaces,cursor,end);
123 // allocate the output array and copy face indices
124 if (iNumFaces)
125 {
126 cursor = (LE_NCONST uint16_t*)mFileBuffer;
128 mCurLayer->mFaces.resize(iNumFaces);
129 FaceList::iterator it = mCurLayer->mFaces.begin();
130 CopyFaceIndicesLWOB(it,cursor,end);
131 }
132 }
134 // ------------------------------------------------------------------------------------------------
135 void LWOImporter::CountVertsAndFacesLWOB(unsigned int& verts, unsigned int& faces,
136 LE_NCONST uint16_t*& cursor, const uint16_t* const end, unsigned int max)
137 {
138 while (cursor < end && max--)
139 {
140 uint16_t numIndices = *cursor++;
141 verts += numIndices;faces++;
142 cursor += numIndices;
143 int16_t surface = *cursor++;
144 if (surface < 0)
145 {
146 // there are detail polygons
147 numIndices = *cursor++;
148 CountVertsAndFacesLWOB(verts,faces,cursor,end,numIndices);
149 }
150 }
151 }
153 // ------------------------------------------------------------------------------------------------
154 void LWOImporter::CopyFaceIndicesLWOB(FaceList::iterator& it,
155 LE_NCONST uint16_t*& cursor,
156 const uint16_t* const end,
157 unsigned int max)
158 {
159 while (cursor < end && max--)
160 {
161 LWO::Face& face = *it;++it;
162 if((face.mNumIndices = *cursor++))
163 {
164 if (cursor + face.mNumIndices >= end)break;
165 face.mIndices = new unsigned int[face.mNumIndices];
166 for (unsigned int i = 0; i < face.mNumIndices;++i)
167 {
168 unsigned int & mi = face.mIndices[i] = *cursor++;
169 if (mi > mCurLayer->mTempPoints.size())
170 {
171 DefaultLogger::get()->warn("LWOB: face index is out of range");
172 mi = (unsigned int)mCurLayer->mTempPoints.size()-1;
173 }
174 }
175 }
176 else DefaultLogger::get()->warn("LWOB: Face has 0 indices");
177 int16_t surface = *cursor++;
178 if (surface < 0)
179 {
180 surface = -surface;
182 // there are detail polygons.
183 const uint16_t numPolygons = *cursor++;
184 if (cursor < end)CopyFaceIndicesLWOB(it,cursor,end,numPolygons);
185 }
186 face.surfaceIndex = surface-1;
187 }
188 }
190 // ------------------------------------------------------------------------------------------------
191 LWO::Texture* LWOImporter::SetupNewTextureLWOB(LWO::TextureList& list,unsigned int size)
192 {
193 list.push_back(LWO::Texture());
194 LWO::Texture* tex = &list.back();
196 std::string type;
197 GetS0(type,size);
198 const char* s = type.c_str();
200 if(strstr(s, "Image Map"))
201 {
202 // Determine mapping type
203 if(strstr(s, "Planar"))
204 tex->mapMode = LWO::Texture::Planar;
205 else if(strstr(s, "Cylindrical"))
206 tex->mapMode = LWO::Texture::Cylindrical;
207 else if(strstr(s, "Spherical"))
208 tex->mapMode = LWO::Texture::Spherical;
209 else if(strstr(s, "Cubic"))
210 tex->mapMode = LWO::Texture::Cubic;
211 else if(strstr(s, "Front"))
212 tex->mapMode = LWO::Texture::FrontProjection;
213 }
214 else
215 {
216 // procedural or gradient, not supported
217 DefaultLogger::get()->error("LWOB: Unsupported legacy texture: " + type);
218 }
220 return tex;
221 }
223 // ------------------------------------------------------------------------------------------------
224 void LWOImporter::LoadLWOBSurface(unsigned int size)
225 {
226 LE_NCONST uint8_t* const end = mFileBuffer + size;
228 mSurfaces->push_back( LWO::Surface () );
229 LWO::Surface& surf = mSurfaces->back();
230 LWO::Texture* pTex = NULL;
232 GetS0(surf.mName,size);
233 bool runnning = true;
234 while (runnning) {
235 if (mFileBuffer + 6 >= end)
236 break;
238 IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
240 /* A single test file (sonycam.lwo) seems to have invalid surface chunks.
241 * I'm assuming it's the fault of a single, unknown exporter so there are
242 * probably THOUSANDS of them. Here's a dirty workaround:
243 *
244 * We don't break if the chunk limit is exceeded. Instead, we're computing
245 * how much storage is actually left and work with this value from now on.
246 */
247 if (mFileBuffer + head->length > end) {
248 DefaultLogger::get()->error("LWOB: Invalid surface chunk length. Trying to continue.");
249 head->length = (uint16_t) (end - mFileBuffer);
250 }
252 uint8_t* const next = mFileBuffer+head->length;
253 switch (head->type)
254 {
255 // diffuse color
256 case AI_LWO_COLR:
257 {
258 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,COLR,3);
259 surf.mColor.r = GetU1() / 255.0f;
260 surf.mColor.g = GetU1() / 255.0f;
261 surf.mColor.b = GetU1() / 255.0f;
262 break;
263 }
264 // diffuse strength ...
265 case AI_LWO_DIFF:
266 {
267 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,DIFF,2);
268 surf.mDiffuseValue = GetU2() / 255.0f;
269 break;
270 }
271 // specular strength ...
272 case AI_LWO_SPEC:
273 {
274 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SPEC,2);
275 surf.mSpecularValue = GetU2() / 255.0f;
276 break;
277 }
278 // luminosity ...
279 case AI_LWO_LUMI:
280 {
281 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,LUMI,2);
282 surf.mLuminosity = GetU2() / 255.0f;
283 break;
284 }
285 // transparency
286 case AI_LWO_TRAN:
287 {
288 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TRAN,2);
289 surf.mTransparency = GetU2() / 255.0f;
290 break;
291 }
292 // surface flags
293 case AI_LWO_FLAG:
294 {
295 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,FLAG,2);
296 uint16_t flag = GetU2();
297 if (flag & 0x4 ) surf.mMaximumSmoothAngle = 1.56207f;
298 if (flag & 0x8 ) surf.mColorHighlights = 1.f;
299 if (flag & 0x100) surf.bDoubleSided = true;
300 break;
301 }
302 // maximum smoothing angle
303 case AI_LWO_SMAN:
304 {
305 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SMAN,4);
306 surf.mMaximumSmoothAngle = fabs( GetF4() );
307 break;
308 }
309 // glossiness
310 case AI_LWO_GLOS:
311 {
312 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,GLOS,2);
313 surf.mGlossiness = (float)GetU2();
314 break;
315 }
316 // color texture
317 case AI_LWO_CTEX:
318 {
319 pTex = SetupNewTextureLWOB(surf.mColorTextures,
320 head->length);
321 break;
322 }
323 // diffuse texture
324 case AI_LWO_DTEX:
325 {
326 pTex = SetupNewTextureLWOB(surf.mDiffuseTextures,
327 head->length);
328 break;
329 }
330 // specular texture
331 case AI_LWO_STEX:
332 {
333 pTex = SetupNewTextureLWOB(surf.mSpecularTextures,
334 head->length);
335 break;
336 }
337 // bump texture
338 case AI_LWO_BTEX:
339 {
340 pTex = SetupNewTextureLWOB(surf.mBumpTextures,
341 head->length);
342 break;
343 }
344 // transparency texture
345 case AI_LWO_TTEX:
346 {
347 pTex = SetupNewTextureLWOB(surf.mOpacityTextures,
348 head->length);
349 break;
350 }
351 // texture path
352 case AI_LWO_TIMG:
353 {
354 if (pTex) {
355 GetS0(pTex->mFileName,head->length);
356 }
357 else DefaultLogger::get()->warn("LWOB: Unexpected TIMG chunk");
358 break;
359 }
360 // texture strength
361 case AI_LWO_TVAL:
362 {
363 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TVAL,1);
364 if (pTex) {
365 pTex->mStrength = (float)GetU1()/ 255.f;
366 }
367 else DefaultLogger::get()->warn("LWOB: Unexpected TVAL chunk");
368 break;
369 }
370 // texture flags
371 case AI_LWO_TFLG:
372 {
373 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TFLG,2);
375 if (pTex)
376 {
377 const uint16_t s = GetU2();
378 if (s & 1)
379 pTex->majorAxis = LWO::Texture::AXIS_X;
380 else if (s & 2)
381 pTex->majorAxis = LWO::Texture::AXIS_Y;
382 else if (s & 4)
383 pTex->majorAxis = LWO::Texture::AXIS_Z;
385 if (s & 16)
386 DefaultLogger::get()->warn("LWOB: Ignoring \'negate\' flag on texture");
387 }
388 else DefaultLogger::get()->warn("LWOB: Unexpected TFLG chunk");
389 break;
390 }
391 }
392 mFileBuffer = next;
393 }
394 }
396 #endif // !! ASSIMP_BUILD_NO_LWO_IMPORTER