vrshoot
diff 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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libs/assimp/LWOBLoader.cpp Sat Feb 01 19:58:19 2014 +0200 1.3 @@ -0,0 +1,396 @@ 1.4 +/* 1.5 +--------------------------------------------------------------------------- 1.6 +Open Asset Import Library (assimp) 1.7 +--------------------------------------------------------------------------- 1.8 + 1.9 +Copyright (c) 2006-2012, assimp team 1.10 + 1.11 +All rights reserved. 1.12 + 1.13 +Redistribution and use of this software in source and binary forms, 1.14 +with or without modification, are permitted provided that the following 1.15 +conditions are met: 1.16 + 1.17 +* Redistributions of source code must retain the above 1.18 + copyright notice, this list of conditions and the 1.19 + following disclaimer. 1.20 + 1.21 +* Redistributions in binary form must reproduce the above 1.22 + copyright notice, this list of conditions and the 1.23 + following disclaimer in the documentation and/or other 1.24 + materials provided with the distribution. 1.25 + 1.26 +* Neither the name of the assimp team, nor the names of its 1.27 + contributors may be used to endorse or promote products 1.28 + derived from this software without specific prior 1.29 + written permission of the assimp team. 1.30 + 1.31 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.32 +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.33 +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.34 +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.35 +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.36 +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.37 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.38 +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.39 +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.40 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.41 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.42 +--------------------------------------------------------------------------- 1.43 +*/ 1.44 + 1.45 +/** @file Implementation of the LWO importer class for the older LWOB 1.46 + file formats, including materials */ 1.47 + 1.48 +#include "AssimpPCH.h" 1.49 +#ifndef ASSIMP_BUILD_NO_LWO_IMPORTER 1.50 + 1.51 +// Internal headers 1.52 +#include "LWOLoader.h" 1.53 +using namespace Assimp; 1.54 + 1.55 + 1.56 +// ------------------------------------------------------------------------------------------------ 1.57 +void LWOImporter::LoadLWOBFile() 1.58 +{ 1.59 + LE_NCONST uint8_t* const end = mFileBuffer + fileSize; 1.60 + bool running = true; 1.61 + while (running) 1.62 + { 1.63 + if (mFileBuffer + sizeof(IFF::ChunkHeader) > end)break; 1.64 + LE_NCONST IFF::ChunkHeader* const head = IFF::LoadChunk(mFileBuffer); 1.65 + 1.66 + if (mFileBuffer + head->length > end) 1.67 + { 1.68 + throw DeadlyImportError("LWOB: Invalid chunk length"); 1.69 + break; 1.70 + } 1.71 + uint8_t* const next = mFileBuffer+head->length; 1.72 + switch (head->type) 1.73 + { 1.74 + // vertex list 1.75 + case AI_LWO_PNTS: 1.76 + { 1.77 + if (!mCurLayer->mTempPoints.empty()) 1.78 + DefaultLogger::get()->warn("LWO: PNTS chunk encountered twice"); 1.79 + else LoadLWOPoints(head->length); 1.80 + break; 1.81 + } 1.82 + // face list 1.83 + case AI_LWO_POLS: 1.84 + { 1.85 + if (!mCurLayer->mFaces.empty()) 1.86 + DefaultLogger::get()->warn("LWO: POLS chunk encountered twice"); 1.87 + else LoadLWOBPolygons(head->length); 1.88 + break; 1.89 + } 1.90 + // list of tags 1.91 + case AI_LWO_SRFS: 1.92 + { 1.93 + if (!mTags->empty()) 1.94 + DefaultLogger::get()->warn("LWO: SRFS chunk encountered twice"); 1.95 + else LoadLWOTags(head->length); 1.96 + break; 1.97 + } 1.98 + 1.99 + // surface chunk 1.100 + case AI_LWO_SURF: 1.101 + { 1.102 + LoadLWOBSurface(head->length); 1.103 + break; 1.104 + } 1.105 + } 1.106 + mFileBuffer = next; 1.107 + } 1.108 +} 1.109 + 1.110 +// ------------------------------------------------------------------------------------------------ 1.111 +void LWOImporter::LoadLWOBPolygons(unsigned int length) 1.112 +{ 1.113 + // first find out how many faces and vertices we'll finally need 1.114 + LE_NCONST uint16_t* const end = (LE_NCONST uint16_t*)(mFileBuffer+length); 1.115 + LE_NCONST uint16_t* cursor = (LE_NCONST uint16_t*)mFileBuffer; 1.116 + 1.117 + // perform endianess conversions 1.118 +#ifndef AI_BUILD_BIG_ENDIAN 1.119 + while (cursor < end)ByteSwap::Swap2(cursor++); 1.120 + cursor = (LE_NCONST uint16_t*)mFileBuffer; 1.121 +#endif 1.122 + 1.123 + unsigned int iNumFaces = 0,iNumVertices = 0; 1.124 + CountVertsAndFacesLWOB(iNumVertices,iNumFaces,cursor,end); 1.125 + 1.126 + // allocate the output array and copy face indices 1.127 + if (iNumFaces) 1.128 + { 1.129 + cursor = (LE_NCONST uint16_t*)mFileBuffer; 1.130 + 1.131 + mCurLayer->mFaces.resize(iNumFaces); 1.132 + FaceList::iterator it = mCurLayer->mFaces.begin(); 1.133 + CopyFaceIndicesLWOB(it,cursor,end); 1.134 + } 1.135 +} 1.136 + 1.137 +// ------------------------------------------------------------------------------------------------ 1.138 +void LWOImporter::CountVertsAndFacesLWOB(unsigned int& verts, unsigned int& faces, 1.139 + LE_NCONST uint16_t*& cursor, const uint16_t* const end, unsigned int max) 1.140 +{ 1.141 + while (cursor < end && max--) 1.142 + { 1.143 + uint16_t numIndices = *cursor++; 1.144 + verts += numIndices;faces++; 1.145 + cursor += numIndices; 1.146 + int16_t surface = *cursor++; 1.147 + if (surface < 0) 1.148 + { 1.149 + // there are detail polygons 1.150 + numIndices = *cursor++; 1.151 + CountVertsAndFacesLWOB(verts,faces,cursor,end,numIndices); 1.152 + } 1.153 + } 1.154 +} 1.155 + 1.156 +// ------------------------------------------------------------------------------------------------ 1.157 +void LWOImporter::CopyFaceIndicesLWOB(FaceList::iterator& it, 1.158 + LE_NCONST uint16_t*& cursor, 1.159 + const uint16_t* const end, 1.160 + unsigned int max) 1.161 +{ 1.162 + while (cursor < end && max--) 1.163 + { 1.164 + LWO::Face& face = *it;++it; 1.165 + if((face.mNumIndices = *cursor++)) 1.166 + { 1.167 + if (cursor + face.mNumIndices >= end)break; 1.168 + face.mIndices = new unsigned int[face.mNumIndices]; 1.169 + for (unsigned int i = 0; i < face.mNumIndices;++i) 1.170 + { 1.171 + unsigned int & mi = face.mIndices[i] = *cursor++; 1.172 + if (mi > mCurLayer->mTempPoints.size()) 1.173 + { 1.174 + DefaultLogger::get()->warn("LWOB: face index is out of range"); 1.175 + mi = (unsigned int)mCurLayer->mTempPoints.size()-1; 1.176 + } 1.177 + } 1.178 + } 1.179 + else DefaultLogger::get()->warn("LWOB: Face has 0 indices"); 1.180 + int16_t surface = *cursor++; 1.181 + if (surface < 0) 1.182 + { 1.183 + surface = -surface; 1.184 + 1.185 + // there are detail polygons. 1.186 + const uint16_t numPolygons = *cursor++; 1.187 + if (cursor < end)CopyFaceIndicesLWOB(it,cursor,end,numPolygons); 1.188 + } 1.189 + face.surfaceIndex = surface-1; 1.190 + } 1.191 +} 1.192 + 1.193 +// ------------------------------------------------------------------------------------------------ 1.194 +LWO::Texture* LWOImporter::SetupNewTextureLWOB(LWO::TextureList& list,unsigned int size) 1.195 +{ 1.196 + list.push_back(LWO::Texture()); 1.197 + LWO::Texture* tex = &list.back(); 1.198 + 1.199 + std::string type; 1.200 + GetS0(type,size); 1.201 + const char* s = type.c_str(); 1.202 + 1.203 + if(strstr(s, "Image Map")) 1.204 + { 1.205 + // Determine mapping type 1.206 + if(strstr(s, "Planar")) 1.207 + tex->mapMode = LWO::Texture::Planar; 1.208 + else if(strstr(s, "Cylindrical")) 1.209 + tex->mapMode = LWO::Texture::Cylindrical; 1.210 + else if(strstr(s, "Spherical")) 1.211 + tex->mapMode = LWO::Texture::Spherical; 1.212 + else if(strstr(s, "Cubic")) 1.213 + tex->mapMode = LWO::Texture::Cubic; 1.214 + else if(strstr(s, "Front")) 1.215 + tex->mapMode = LWO::Texture::FrontProjection; 1.216 + } 1.217 + else 1.218 + { 1.219 + // procedural or gradient, not supported 1.220 + DefaultLogger::get()->error("LWOB: Unsupported legacy texture: " + type); 1.221 + } 1.222 + 1.223 + return tex; 1.224 +} 1.225 + 1.226 +// ------------------------------------------------------------------------------------------------ 1.227 +void LWOImporter::LoadLWOBSurface(unsigned int size) 1.228 +{ 1.229 + LE_NCONST uint8_t* const end = mFileBuffer + size; 1.230 + 1.231 + mSurfaces->push_back( LWO::Surface () ); 1.232 + LWO::Surface& surf = mSurfaces->back(); 1.233 + LWO::Texture* pTex = NULL; 1.234 + 1.235 + GetS0(surf.mName,size); 1.236 + bool runnning = true; 1.237 + while (runnning) { 1.238 + if (mFileBuffer + 6 >= end) 1.239 + break; 1.240 + 1.241 + IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer); 1.242 + 1.243 + /* A single test file (sonycam.lwo) seems to have invalid surface chunks. 1.244 + * I'm assuming it's the fault of a single, unknown exporter so there are 1.245 + * probably THOUSANDS of them. Here's a dirty workaround: 1.246 + * 1.247 + * We don't break if the chunk limit is exceeded. Instead, we're computing 1.248 + * how much storage is actually left and work with this value from now on. 1.249 + */ 1.250 + if (mFileBuffer + head->length > end) { 1.251 + DefaultLogger::get()->error("LWOB: Invalid surface chunk length. Trying to continue."); 1.252 + head->length = (uint16_t) (end - mFileBuffer); 1.253 + } 1.254 + 1.255 + uint8_t* const next = mFileBuffer+head->length; 1.256 + switch (head->type) 1.257 + { 1.258 + // diffuse color 1.259 + case AI_LWO_COLR: 1.260 + { 1.261 + AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,COLR,3); 1.262 + surf.mColor.r = GetU1() / 255.0f; 1.263 + surf.mColor.g = GetU1() / 255.0f; 1.264 + surf.mColor.b = GetU1() / 255.0f; 1.265 + break; 1.266 + } 1.267 + // diffuse strength ... 1.268 + case AI_LWO_DIFF: 1.269 + { 1.270 + AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,DIFF,2); 1.271 + surf.mDiffuseValue = GetU2() / 255.0f; 1.272 + break; 1.273 + } 1.274 + // specular strength ... 1.275 + case AI_LWO_SPEC: 1.276 + { 1.277 + AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SPEC,2); 1.278 + surf.mSpecularValue = GetU2() / 255.0f; 1.279 + break; 1.280 + } 1.281 + // luminosity ... 1.282 + case AI_LWO_LUMI: 1.283 + { 1.284 + AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,LUMI,2); 1.285 + surf.mLuminosity = GetU2() / 255.0f; 1.286 + break; 1.287 + } 1.288 + // transparency 1.289 + case AI_LWO_TRAN: 1.290 + { 1.291 + AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TRAN,2); 1.292 + surf.mTransparency = GetU2() / 255.0f; 1.293 + break; 1.294 + } 1.295 + // surface flags 1.296 + case AI_LWO_FLAG: 1.297 + { 1.298 + AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,FLAG,2); 1.299 + uint16_t flag = GetU2(); 1.300 + if (flag & 0x4 ) surf.mMaximumSmoothAngle = 1.56207f; 1.301 + if (flag & 0x8 ) surf.mColorHighlights = 1.f; 1.302 + if (flag & 0x100) surf.bDoubleSided = true; 1.303 + break; 1.304 + } 1.305 + // maximum smoothing angle 1.306 + case AI_LWO_SMAN: 1.307 + { 1.308 + AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SMAN,4); 1.309 + surf.mMaximumSmoothAngle = fabs( GetF4() ); 1.310 + break; 1.311 + } 1.312 + // glossiness 1.313 + case AI_LWO_GLOS: 1.314 + { 1.315 + AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,GLOS,2); 1.316 + surf.mGlossiness = (float)GetU2(); 1.317 + break; 1.318 + } 1.319 + // color texture 1.320 + case AI_LWO_CTEX: 1.321 + { 1.322 + pTex = SetupNewTextureLWOB(surf.mColorTextures, 1.323 + head->length); 1.324 + break; 1.325 + } 1.326 + // diffuse texture 1.327 + case AI_LWO_DTEX: 1.328 + { 1.329 + pTex = SetupNewTextureLWOB(surf.mDiffuseTextures, 1.330 + head->length); 1.331 + break; 1.332 + } 1.333 + // specular texture 1.334 + case AI_LWO_STEX: 1.335 + { 1.336 + pTex = SetupNewTextureLWOB(surf.mSpecularTextures, 1.337 + head->length); 1.338 + break; 1.339 + } 1.340 + // bump texture 1.341 + case AI_LWO_BTEX: 1.342 + { 1.343 + pTex = SetupNewTextureLWOB(surf.mBumpTextures, 1.344 + head->length); 1.345 + break; 1.346 + } 1.347 + // transparency texture 1.348 + case AI_LWO_TTEX: 1.349 + { 1.350 + pTex = SetupNewTextureLWOB(surf.mOpacityTextures, 1.351 + head->length); 1.352 + break; 1.353 + } 1.354 + // texture path 1.355 + case AI_LWO_TIMG: 1.356 + { 1.357 + if (pTex) { 1.358 + GetS0(pTex->mFileName,head->length); 1.359 + } 1.360 + else DefaultLogger::get()->warn("LWOB: Unexpected TIMG chunk"); 1.361 + break; 1.362 + } 1.363 + // texture strength 1.364 + case AI_LWO_TVAL: 1.365 + { 1.366 + AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TVAL,1); 1.367 + if (pTex) { 1.368 + pTex->mStrength = (float)GetU1()/ 255.f; 1.369 + } 1.370 + else DefaultLogger::get()->warn("LWOB: Unexpected TVAL chunk"); 1.371 + break; 1.372 + } 1.373 + // texture flags 1.374 + case AI_LWO_TFLG: 1.375 + { 1.376 + AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TFLG,2); 1.377 + 1.378 + if (pTex) 1.379 + { 1.380 + const uint16_t s = GetU2(); 1.381 + if (s & 1) 1.382 + pTex->majorAxis = LWO::Texture::AXIS_X; 1.383 + else if (s & 2) 1.384 + pTex->majorAxis = LWO::Texture::AXIS_Y; 1.385 + else if (s & 4) 1.386 + pTex->majorAxis = LWO::Texture::AXIS_Z; 1.387 + 1.388 + if (s & 16) 1.389 + DefaultLogger::get()->warn("LWOB: Ignoring \'negate\' flag on texture"); 1.390 + } 1.391 + else DefaultLogger::get()->warn("LWOB: Unexpected TFLG chunk"); 1.392 + break; 1.393 + } 1.394 + } 1.395 + mFileBuffer = next; 1.396 + } 1.397 +} 1.398 + 1.399 +#endif // !! ASSIMP_BUILD_NO_LWO_IMPORTER