vrshoot

annotate 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
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 LWO importer class for the older LWOB
nuclear@0 43 file formats, including materials */
nuclear@0 44
nuclear@0 45 #include "AssimpPCH.h"
nuclear@0 46 #ifndef ASSIMP_BUILD_NO_LWO_IMPORTER
nuclear@0 47
nuclear@0 48 // Internal headers
nuclear@0 49 #include "LWOLoader.h"
nuclear@0 50 using namespace Assimp;
nuclear@0 51
nuclear@0 52
nuclear@0 53 // ------------------------------------------------------------------------------------------------
nuclear@0 54 void LWOImporter::LoadLWOBFile()
nuclear@0 55 {
nuclear@0 56 LE_NCONST uint8_t* const end = mFileBuffer + fileSize;
nuclear@0 57 bool running = true;
nuclear@0 58 while (running)
nuclear@0 59 {
nuclear@0 60 if (mFileBuffer + sizeof(IFF::ChunkHeader) > end)break;
nuclear@0 61 LE_NCONST IFF::ChunkHeader* const head = IFF::LoadChunk(mFileBuffer);
nuclear@0 62
nuclear@0 63 if (mFileBuffer + head->length > end)
nuclear@0 64 {
nuclear@0 65 throw DeadlyImportError("LWOB: Invalid chunk length");
nuclear@0 66 break;
nuclear@0 67 }
nuclear@0 68 uint8_t* const next = mFileBuffer+head->length;
nuclear@0 69 switch (head->type)
nuclear@0 70 {
nuclear@0 71 // vertex list
nuclear@0 72 case AI_LWO_PNTS:
nuclear@0 73 {
nuclear@0 74 if (!mCurLayer->mTempPoints.empty())
nuclear@0 75 DefaultLogger::get()->warn("LWO: PNTS chunk encountered twice");
nuclear@0 76 else LoadLWOPoints(head->length);
nuclear@0 77 break;
nuclear@0 78 }
nuclear@0 79 // face list
nuclear@0 80 case AI_LWO_POLS:
nuclear@0 81 {
nuclear@0 82 if (!mCurLayer->mFaces.empty())
nuclear@0 83 DefaultLogger::get()->warn("LWO: POLS chunk encountered twice");
nuclear@0 84 else LoadLWOBPolygons(head->length);
nuclear@0 85 break;
nuclear@0 86 }
nuclear@0 87 // list of tags
nuclear@0 88 case AI_LWO_SRFS:
nuclear@0 89 {
nuclear@0 90 if (!mTags->empty())
nuclear@0 91 DefaultLogger::get()->warn("LWO: SRFS chunk encountered twice");
nuclear@0 92 else LoadLWOTags(head->length);
nuclear@0 93 break;
nuclear@0 94 }
nuclear@0 95
nuclear@0 96 // surface chunk
nuclear@0 97 case AI_LWO_SURF:
nuclear@0 98 {
nuclear@0 99 LoadLWOBSurface(head->length);
nuclear@0 100 break;
nuclear@0 101 }
nuclear@0 102 }
nuclear@0 103 mFileBuffer = next;
nuclear@0 104 }
nuclear@0 105 }
nuclear@0 106
nuclear@0 107 // ------------------------------------------------------------------------------------------------
nuclear@0 108 void LWOImporter::LoadLWOBPolygons(unsigned int length)
nuclear@0 109 {
nuclear@0 110 // first find out how many faces and vertices we'll finally need
nuclear@0 111 LE_NCONST uint16_t* const end = (LE_NCONST uint16_t*)(mFileBuffer+length);
nuclear@0 112 LE_NCONST uint16_t* cursor = (LE_NCONST uint16_t*)mFileBuffer;
nuclear@0 113
nuclear@0 114 // perform endianess conversions
nuclear@0 115 #ifndef AI_BUILD_BIG_ENDIAN
nuclear@0 116 while (cursor < end)ByteSwap::Swap2(cursor++);
nuclear@0 117 cursor = (LE_NCONST uint16_t*)mFileBuffer;
nuclear@0 118 #endif
nuclear@0 119
nuclear@0 120 unsigned int iNumFaces = 0,iNumVertices = 0;
nuclear@0 121 CountVertsAndFacesLWOB(iNumVertices,iNumFaces,cursor,end);
nuclear@0 122
nuclear@0 123 // allocate the output array and copy face indices
nuclear@0 124 if (iNumFaces)
nuclear@0 125 {
nuclear@0 126 cursor = (LE_NCONST uint16_t*)mFileBuffer;
nuclear@0 127
nuclear@0 128 mCurLayer->mFaces.resize(iNumFaces);
nuclear@0 129 FaceList::iterator it = mCurLayer->mFaces.begin();
nuclear@0 130 CopyFaceIndicesLWOB(it,cursor,end);
nuclear@0 131 }
nuclear@0 132 }
nuclear@0 133
nuclear@0 134 // ------------------------------------------------------------------------------------------------
nuclear@0 135 void LWOImporter::CountVertsAndFacesLWOB(unsigned int& verts, unsigned int& faces,
nuclear@0 136 LE_NCONST uint16_t*& cursor, const uint16_t* const end, unsigned int max)
nuclear@0 137 {
nuclear@0 138 while (cursor < end && max--)
nuclear@0 139 {
nuclear@0 140 uint16_t numIndices = *cursor++;
nuclear@0 141 verts += numIndices;faces++;
nuclear@0 142 cursor += numIndices;
nuclear@0 143 int16_t surface = *cursor++;
nuclear@0 144 if (surface < 0)
nuclear@0 145 {
nuclear@0 146 // there are detail polygons
nuclear@0 147 numIndices = *cursor++;
nuclear@0 148 CountVertsAndFacesLWOB(verts,faces,cursor,end,numIndices);
nuclear@0 149 }
nuclear@0 150 }
nuclear@0 151 }
nuclear@0 152
nuclear@0 153 // ------------------------------------------------------------------------------------------------
nuclear@0 154 void LWOImporter::CopyFaceIndicesLWOB(FaceList::iterator& it,
nuclear@0 155 LE_NCONST uint16_t*& cursor,
nuclear@0 156 const uint16_t* const end,
nuclear@0 157 unsigned int max)
nuclear@0 158 {
nuclear@0 159 while (cursor < end && max--)
nuclear@0 160 {
nuclear@0 161 LWO::Face& face = *it;++it;
nuclear@0 162 if((face.mNumIndices = *cursor++))
nuclear@0 163 {
nuclear@0 164 if (cursor + face.mNumIndices >= end)break;
nuclear@0 165 face.mIndices = new unsigned int[face.mNumIndices];
nuclear@0 166 for (unsigned int i = 0; i < face.mNumIndices;++i)
nuclear@0 167 {
nuclear@0 168 unsigned int & mi = face.mIndices[i] = *cursor++;
nuclear@0 169 if (mi > mCurLayer->mTempPoints.size())
nuclear@0 170 {
nuclear@0 171 DefaultLogger::get()->warn("LWOB: face index is out of range");
nuclear@0 172 mi = (unsigned int)mCurLayer->mTempPoints.size()-1;
nuclear@0 173 }
nuclear@0 174 }
nuclear@0 175 }
nuclear@0 176 else DefaultLogger::get()->warn("LWOB: Face has 0 indices");
nuclear@0 177 int16_t surface = *cursor++;
nuclear@0 178 if (surface < 0)
nuclear@0 179 {
nuclear@0 180 surface = -surface;
nuclear@0 181
nuclear@0 182 // there are detail polygons.
nuclear@0 183 const uint16_t numPolygons = *cursor++;
nuclear@0 184 if (cursor < end)CopyFaceIndicesLWOB(it,cursor,end,numPolygons);
nuclear@0 185 }
nuclear@0 186 face.surfaceIndex = surface-1;
nuclear@0 187 }
nuclear@0 188 }
nuclear@0 189
nuclear@0 190 // ------------------------------------------------------------------------------------------------
nuclear@0 191 LWO::Texture* LWOImporter::SetupNewTextureLWOB(LWO::TextureList& list,unsigned int size)
nuclear@0 192 {
nuclear@0 193 list.push_back(LWO::Texture());
nuclear@0 194 LWO::Texture* tex = &list.back();
nuclear@0 195
nuclear@0 196 std::string type;
nuclear@0 197 GetS0(type,size);
nuclear@0 198 const char* s = type.c_str();
nuclear@0 199
nuclear@0 200 if(strstr(s, "Image Map"))
nuclear@0 201 {
nuclear@0 202 // Determine mapping type
nuclear@0 203 if(strstr(s, "Planar"))
nuclear@0 204 tex->mapMode = LWO::Texture::Planar;
nuclear@0 205 else if(strstr(s, "Cylindrical"))
nuclear@0 206 tex->mapMode = LWO::Texture::Cylindrical;
nuclear@0 207 else if(strstr(s, "Spherical"))
nuclear@0 208 tex->mapMode = LWO::Texture::Spherical;
nuclear@0 209 else if(strstr(s, "Cubic"))
nuclear@0 210 tex->mapMode = LWO::Texture::Cubic;
nuclear@0 211 else if(strstr(s, "Front"))
nuclear@0 212 tex->mapMode = LWO::Texture::FrontProjection;
nuclear@0 213 }
nuclear@0 214 else
nuclear@0 215 {
nuclear@0 216 // procedural or gradient, not supported
nuclear@0 217 DefaultLogger::get()->error("LWOB: Unsupported legacy texture: " + type);
nuclear@0 218 }
nuclear@0 219
nuclear@0 220 return tex;
nuclear@0 221 }
nuclear@0 222
nuclear@0 223 // ------------------------------------------------------------------------------------------------
nuclear@0 224 void LWOImporter::LoadLWOBSurface(unsigned int size)
nuclear@0 225 {
nuclear@0 226 LE_NCONST uint8_t* const end = mFileBuffer + size;
nuclear@0 227
nuclear@0 228 mSurfaces->push_back( LWO::Surface () );
nuclear@0 229 LWO::Surface& surf = mSurfaces->back();
nuclear@0 230 LWO::Texture* pTex = NULL;
nuclear@0 231
nuclear@0 232 GetS0(surf.mName,size);
nuclear@0 233 bool runnning = true;
nuclear@0 234 while (runnning) {
nuclear@0 235 if (mFileBuffer + 6 >= end)
nuclear@0 236 break;
nuclear@0 237
nuclear@0 238 IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
nuclear@0 239
nuclear@0 240 /* A single test file (sonycam.lwo) seems to have invalid surface chunks.
nuclear@0 241 * I'm assuming it's the fault of a single, unknown exporter so there are
nuclear@0 242 * probably THOUSANDS of them. Here's a dirty workaround:
nuclear@0 243 *
nuclear@0 244 * We don't break if the chunk limit is exceeded. Instead, we're computing
nuclear@0 245 * how much storage is actually left and work with this value from now on.
nuclear@0 246 */
nuclear@0 247 if (mFileBuffer + head->length > end) {
nuclear@0 248 DefaultLogger::get()->error("LWOB: Invalid surface chunk length. Trying to continue.");
nuclear@0 249 head->length = (uint16_t) (end - mFileBuffer);
nuclear@0 250 }
nuclear@0 251
nuclear@0 252 uint8_t* const next = mFileBuffer+head->length;
nuclear@0 253 switch (head->type)
nuclear@0 254 {
nuclear@0 255 // diffuse color
nuclear@0 256 case AI_LWO_COLR:
nuclear@0 257 {
nuclear@0 258 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,COLR,3);
nuclear@0 259 surf.mColor.r = GetU1() / 255.0f;
nuclear@0 260 surf.mColor.g = GetU1() / 255.0f;
nuclear@0 261 surf.mColor.b = GetU1() / 255.0f;
nuclear@0 262 break;
nuclear@0 263 }
nuclear@0 264 // diffuse strength ...
nuclear@0 265 case AI_LWO_DIFF:
nuclear@0 266 {
nuclear@0 267 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,DIFF,2);
nuclear@0 268 surf.mDiffuseValue = GetU2() / 255.0f;
nuclear@0 269 break;
nuclear@0 270 }
nuclear@0 271 // specular strength ...
nuclear@0 272 case AI_LWO_SPEC:
nuclear@0 273 {
nuclear@0 274 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SPEC,2);
nuclear@0 275 surf.mSpecularValue = GetU2() / 255.0f;
nuclear@0 276 break;
nuclear@0 277 }
nuclear@0 278 // luminosity ...
nuclear@0 279 case AI_LWO_LUMI:
nuclear@0 280 {
nuclear@0 281 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,LUMI,2);
nuclear@0 282 surf.mLuminosity = GetU2() / 255.0f;
nuclear@0 283 break;
nuclear@0 284 }
nuclear@0 285 // transparency
nuclear@0 286 case AI_LWO_TRAN:
nuclear@0 287 {
nuclear@0 288 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TRAN,2);
nuclear@0 289 surf.mTransparency = GetU2() / 255.0f;
nuclear@0 290 break;
nuclear@0 291 }
nuclear@0 292 // surface flags
nuclear@0 293 case AI_LWO_FLAG:
nuclear@0 294 {
nuclear@0 295 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,FLAG,2);
nuclear@0 296 uint16_t flag = GetU2();
nuclear@0 297 if (flag & 0x4 ) surf.mMaximumSmoothAngle = 1.56207f;
nuclear@0 298 if (flag & 0x8 ) surf.mColorHighlights = 1.f;
nuclear@0 299 if (flag & 0x100) surf.bDoubleSided = true;
nuclear@0 300 break;
nuclear@0 301 }
nuclear@0 302 // maximum smoothing angle
nuclear@0 303 case AI_LWO_SMAN:
nuclear@0 304 {
nuclear@0 305 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SMAN,4);
nuclear@0 306 surf.mMaximumSmoothAngle = fabs( GetF4() );
nuclear@0 307 break;
nuclear@0 308 }
nuclear@0 309 // glossiness
nuclear@0 310 case AI_LWO_GLOS:
nuclear@0 311 {
nuclear@0 312 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,GLOS,2);
nuclear@0 313 surf.mGlossiness = (float)GetU2();
nuclear@0 314 break;
nuclear@0 315 }
nuclear@0 316 // color texture
nuclear@0 317 case AI_LWO_CTEX:
nuclear@0 318 {
nuclear@0 319 pTex = SetupNewTextureLWOB(surf.mColorTextures,
nuclear@0 320 head->length);
nuclear@0 321 break;
nuclear@0 322 }
nuclear@0 323 // diffuse texture
nuclear@0 324 case AI_LWO_DTEX:
nuclear@0 325 {
nuclear@0 326 pTex = SetupNewTextureLWOB(surf.mDiffuseTextures,
nuclear@0 327 head->length);
nuclear@0 328 break;
nuclear@0 329 }
nuclear@0 330 // specular texture
nuclear@0 331 case AI_LWO_STEX:
nuclear@0 332 {
nuclear@0 333 pTex = SetupNewTextureLWOB(surf.mSpecularTextures,
nuclear@0 334 head->length);
nuclear@0 335 break;
nuclear@0 336 }
nuclear@0 337 // bump texture
nuclear@0 338 case AI_LWO_BTEX:
nuclear@0 339 {
nuclear@0 340 pTex = SetupNewTextureLWOB(surf.mBumpTextures,
nuclear@0 341 head->length);
nuclear@0 342 break;
nuclear@0 343 }
nuclear@0 344 // transparency texture
nuclear@0 345 case AI_LWO_TTEX:
nuclear@0 346 {
nuclear@0 347 pTex = SetupNewTextureLWOB(surf.mOpacityTextures,
nuclear@0 348 head->length);
nuclear@0 349 break;
nuclear@0 350 }
nuclear@0 351 // texture path
nuclear@0 352 case AI_LWO_TIMG:
nuclear@0 353 {
nuclear@0 354 if (pTex) {
nuclear@0 355 GetS0(pTex->mFileName,head->length);
nuclear@0 356 }
nuclear@0 357 else DefaultLogger::get()->warn("LWOB: Unexpected TIMG chunk");
nuclear@0 358 break;
nuclear@0 359 }
nuclear@0 360 // texture strength
nuclear@0 361 case AI_LWO_TVAL:
nuclear@0 362 {
nuclear@0 363 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TVAL,1);
nuclear@0 364 if (pTex) {
nuclear@0 365 pTex->mStrength = (float)GetU1()/ 255.f;
nuclear@0 366 }
nuclear@0 367 else DefaultLogger::get()->warn("LWOB: Unexpected TVAL chunk");
nuclear@0 368 break;
nuclear@0 369 }
nuclear@0 370 // texture flags
nuclear@0 371 case AI_LWO_TFLG:
nuclear@0 372 {
nuclear@0 373 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TFLG,2);
nuclear@0 374
nuclear@0 375 if (pTex)
nuclear@0 376 {
nuclear@0 377 const uint16_t s = GetU2();
nuclear@0 378 if (s & 1)
nuclear@0 379 pTex->majorAxis = LWO::Texture::AXIS_X;
nuclear@0 380 else if (s & 2)
nuclear@0 381 pTex->majorAxis = LWO::Texture::AXIS_Y;
nuclear@0 382 else if (s & 4)
nuclear@0 383 pTex->majorAxis = LWO::Texture::AXIS_Z;
nuclear@0 384
nuclear@0 385 if (s & 16)
nuclear@0 386 DefaultLogger::get()->warn("LWOB: Ignoring \'negate\' flag on texture");
nuclear@0 387 }
nuclear@0 388 else DefaultLogger::get()->warn("LWOB: Unexpected TFLG chunk");
nuclear@0 389 break;
nuclear@0 390 }
nuclear@0 391 }
nuclear@0 392 mFileBuffer = next;
nuclear@0 393 }
nuclear@0 394 }
nuclear@0 395
nuclear@0 396 #endif // !! ASSIMP_BUILD_NO_LWO_IMPORTER