vrshoot
diff libs/assimp/ASEParser.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/ASEParser.cpp Sat Feb 01 19:58:19 2014 +0200 1.3 @@ -0,0 +1,2153 @@ 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 ASEParser.cpp 1.46 + * @brief Implementation of the ASE parser class 1.47 + */ 1.48 + 1.49 +#include "AssimpPCH.h" 1.50 +#ifndef ASSIMP_BUILD_NO_ASE_IMPORTER 1.51 + 1.52 +// internal headers 1.53 +#include "TextureTransform.h" 1.54 +#include "ASELoader.h" 1.55 +#include "MaterialSystem.h" 1.56 +#include "fast_atof.h" 1.57 + 1.58 +using namespace Assimp; 1.59 +using namespace Assimp::ASE; 1.60 + 1.61 + 1.62 +// ------------------------------------------------------------------------------------------------ 1.63 +// Begin an ASE parsing function 1.64 + 1.65 +#define AI_ASE_PARSER_INIT() \ 1.66 + int iDepth = 0; 1.67 + 1.68 +// ------------------------------------------------------------------------------------------------ 1.69 +// Handle a "top-level" section in the file. EOF is no error in this case. 1.70 + 1.71 +#define AI_ASE_HANDLE_TOP_LEVEL_SECTION() \ 1.72 + else if ('{' == *filePtr)iDepth++; \ 1.73 + else if ('}' == *filePtr) \ 1.74 + { \ 1.75 + if (0 == --iDepth) \ 1.76 + { \ 1.77 + ++filePtr; \ 1.78 + SkipToNextToken(); \ 1.79 + return; \ 1.80 + } \ 1.81 + } \ 1.82 + else if ('\0' == *filePtr) \ 1.83 + { \ 1.84 + return; \ 1.85 + } \ 1.86 + if(IsLineEnd(*filePtr) && !bLastWasEndLine) \ 1.87 + { \ 1.88 + ++iLineNumber; \ 1.89 + bLastWasEndLine = true; \ 1.90 + } else bLastWasEndLine = false; \ 1.91 + ++filePtr; 1.92 + 1.93 +// ------------------------------------------------------------------------------------------------ 1.94 +// Handle a nested section in the file. EOF is an error in this case 1.95 +// @param level "Depth" of the section 1.96 +// @param msg Full name of the section (including the asterisk) 1.97 + 1.98 +#define AI_ASE_HANDLE_SECTION(level, msg) \ 1.99 + if ('{' == *filePtr)iDepth++; \ 1.100 + else if ('}' == *filePtr) \ 1.101 + { \ 1.102 + if (0 == --iDepth) \ 1.103 + { \ 1.104 + ++filePtr; \ 1.105 + SkipToNextToken(); \ 1.106 + return; \ 1.107 + } \ 1.108 + } \ 1.109 + else if ('\0' == *filePtr) \ 1.110 + { \ 1.111 + LogError("Encountered unexpected EOL while parsing a " msg \ 1.112 + " chunk (Level " level ")"); \ 1.113 + } \ 1.114 + if(IsLineEnd(*filePtr) && !bLastWasEndLine) \ 1.115 + { \ 1.116 + ++iLineNumber; \ 1.117 + bLastWasEndLine = true; \ 1.118 + } else bLastWasEndLine = false; \ 1.119 + ++filePtr; 1.120 + 1.121 +// ------------------------------------------------------------------------------------------------ 1.122 +Parser::Parser (const char* szFile, unsigned int fileFormatDefault) 1.123 +{ 1.124 + ai_assert(NULL != szFile); 1.125 + filePtr = szFile; 1.126 + iFileFormat = fileFormatDefault; 1.127 + 1.128 + // make sure that the color values are invalid 1.129 + m_clrBackground.r = get_qnan(); 1.130 + m_clrAmbient.r = get_qnan(); 1.131 + 1.132 + // setup some default values 1.133 + iLineNumber = 0; 1.134 + iFirstFrame = 0; 1.135 + iLastFrame = 0; 1.136 + iFrameSpeed = 30; // use 30 as default value for this property 1.137 + iTicksPerFrame = 1; // use 1 as default value for this property 1.138 + bLastWasEndLine = false; // need to handle \r\n seqs due to binary file mapping 1.139 +} 1.140 + 1.141 +// ------------------------------------------------------------------------------------------------ 1.142 +void Parser::LogWarning(const char* szWarn) 1.143 +{ 1.144 + ai_assert(NULL != szWarn); 1.145 + 1.146 + char szTemp[1024]; 1.147 +#if _MSC_VER >= 1400 1.148 + sprintf_s(szTemp,"Line %i: %s",iLineNumber,szWarn); 1.149 +#else 1.150 + snprintf(szTemp,1024,"Line %i: %s",iLineNumber,szWarn); 1.151 +#endif 1.152 + 1.153 + // output the warning to the logger ... 1.154 + DefaultLogger::get()->warn(szTemp); 1.155 +} 1.156 + 1.157 +// ------------------------------------------------------------------------------------------------ 1.158 +void Parser::LogInfo(const char* szWarn) 1.159 +{ 1.160 + ai_assert(NULL != szWarn); 1.161 + 1.162 + char szTemp[1024]; 1.163 +#if _MSC_VER >= 1400 1.164 + sprintf_s(szTemp,"Line %i: %s",iLineNumber,szWarn); 1.165 +#else 1.166 + snprintf(szTemp,1024,"Line %i: %s",iLineNumber,szWarn); 1.167 +#endif 1.168 + 1.169 + // output the information to the logger ... 1.170 + DefaultLogger::get()->info(szTemp); 1.171 +} 1.172 + 1.173 +// ------------------------------------------------------------------------------------------------ 1.174 +void Parser::LogError(const char* szWarn) 1.175 +{ 1.176 + ai_assert(NULL != szWarn); 1.177 + 1.178 + char szTemp[1024]; 1.179 +#if _MSC_VER >= 1400 1.180 + sprintf_s(szTemp,"Line %i: %s",iLineNumber,szWarn); 1.181 +#else 1.182 + snprintf(szTemp,1024,"Line %i: %s",iLineNumber,szWarn); 1.183 +#endif 1.184 + 1.185 + // throw an exception 1.186 + throw DeadlyImportError(szTemp); 1.187 +} 1.188 + 1.189 +// ------------------------------------------------------------------------------------------------ 1.190 +bool Parser::SkipToNextToken() 1.191 +{ 1.192 + while (true) 1.193 + { 1.194 + char me = *filePtr; 1.195 + 1.196 + // increase the line number counter if necessary 1.197 + if (IsLineEnd(me) && !bLastWasEndLine) 1.198 + { 1.199 + ++iLineNumber; 1.200 + bLastWasEndLine = true; 1.201 + } 1.202 + else bLastWasEndLine = false; 1.203 + if ('*' == me || '}' == me || '{' == me)return true; 1.204 + if ('\0' == me)return false; 1.205 + 1.206 + ++filePtr; 1.207 + } 1.208 +} 1.209 + 1.210 +// ------------------------------------------------------------------------------------------------ 1.211 +bool Parser::SkipSection() 1.212 +{ 1.213 + // must handle subsections ... 1.214 + int iCnt = 0; 1.215 + while (true) 1.216 + { 1.217 + if ('}' == *filePtr) 1.218 + { 1.219 + --iCnt; 1.220 + if (0 == iCnt) 1.221 + { 1.222 + // go to the next valid token ... 1.223 + ++filePtr; 1.224 + SkipToNextToken(); 1.225 + return true; 1.226 + } 1.227 + } 1.228 + else if ('{' == *filePtr) 1.229 + { 1.230 + ++iCnt; 1.231 + } 1.232 + else if ('\0' == *filePtr) 1.233 + { 1.234 + LogWarning("Unable to parse block: Unexpected EOF, closing bracket \'}\' was expected [#1]"); 1.235 + return false; 1.236 + } 1.237 + else if(IsLineEnd(*filePtr))++iLineNumber; 1.238 + ++filePtr; 1.239 + } 1.240 +} 1.241 + 1.242 +// ------------------------------------------------------------------------------------------------ 1.243 +void Parser::Parse() 1.244 +{ 1.245 + AI_ASE_PARSER_INIT(); 1.246 + while (true) 1.247 + { 1.248 + if ('*' == *filePtr) 1.249 + { 1.250 + ++filePtr; 1.251 + 1.252 + // Version should be 200. Validate this ... 1.253 + if (TokenMatch(filePtr,"3DSMAX_ASCIIEXPORT",18)) 1.254 + { 1.255 + unsigned int fmt; 1.256 + ParseLV4MeshLong(fmt); 1.257 + 1.258 + if (fmt > 200) 1.259 + { 1.260 + LogWarning("Unknown file format version: *3DSMAX_ASCIIEXPORT should \ 1.261 + be <= 200"); 1.262 + } 1.263 + // ************************************************************* 1.264 + // - fmt will be 0 if we're unable to read the version number 1.265 + // there are some faulty files without a version number ... 1.266 + // in this case we'll guess the exact file format by looking 1.267 + // at the file extension (ASE, ASK, ASC) 1.268 + // ************************************************************* 1.269 + 1.270 + if (fmt)iFileFormat = fmt; 1.271 + continue; 1.272 + } 1.273 + // main scene information 1.274 + if (TokenMatch(filePtr,"SCENE",5)) 1.275 + { 1.276 + ParseLV1SceneBlock(); 1.277 + continue; 1.278 + } 1.279 + // "group" - no implementation yet, in facte 1.280 + // we're just ignoring them for the moment 1.281 + if (TokenMatch(filePtr,"GROUP",5)) 1.282 + { 1.283 + Parse(); 1.284 + continue; 1.285 + } 1.286 + // material list 1.287 + if (TokenMatch(filePtr,"MATERIAL_LIST",13)) 1.288 + { 1.289 + ParseLV1MaterialListBlock(); 1.290 + continue; 1.291 + } 1.292 + // geometric object (mesh) 1.293 + if (TokenMatch(filePtr,"GEOMOBJECT",10)) 1.294 + 1.295 + { 1.296 + m_vMeshes.push_back(Mesh()); 1.297 + ParseLV1ObjectBlock(m_vMeshes.back()); 1.298 + continue; 1.299 + } 1.300 + // helper object = dummy in the hierarchy 1.301 + if (TokenMatch(filePtr,"HELPEROBJECT",12)) 1.302 + 1.303 + { 1.304 + m_vDummies.push_back(Dummy()); 1.305 + ParseLV1ObjectBlock(m_vDummies.back()); 1.306 + continue; 1.307 + } 1.308 + // light object 1.309 + if (TokenMatch(filePtr,"LIGHTOBJECT",11)) 1.310 + 1.311 + { 1.312 + m_vLights.push_back(Light()); 1.313 + ParseLV1ObjectBlock(m_vLights.back()); 1.314 + continue; 1.315 + } 1.316 + // camera object 1.317 + if (TokenMatch(filePtr,"CAMERAOBJECT",12)) 1.318 + { 1.319 + m_vCameras.push_back(Camera()); 1.320 + ParseLV1ObjectBlock(m_vCameras.back()); 1.321 + continue; 1.322 + } 1.323 + // comment - print it on the console 1.324 + if (TokenMatch(filePtr,"COMMENT",7)) 1.325 + { 1.326 + std::string out = "<unknown>"; 1.327 + ParseString(out,"*COMMENT"); 1.328 + LogInfo(("Comment: " + out).c_str()); 1.329 + continue; 1.330 + } 1.331 + // ASC bone weights 1.332 + if (AI_ASE_IS_OLD_FILE_FORMAT() && TokenMatch(filePtr,"MESH_SOFTSKINVERTS",18)) 1.333 + { 1.334 + ParseLV1SoftSkinBlock(); 1.335 + } 1.336 + } 1.337 + AI_ASE_HANDLE_TOP_LEVEL_SECTION(); 1.338 + } 1.339 + return; 1.340 +} 1.341 + 1.342 +// ------------------------------------------------------------------------------------------------ 1.343 +void Parser::ParseLV1SoftSkinBlock() 1.344 +{ 1.345 + // TODO: fix line counting here 1.346 + 1.347 + // ************************************************************** 1.348 + // The soft skin block is formatted differently. There are no 1.349 + // nested sections supported and the single elements aren't 1.350 + // marked by keywords starting with an asterisk. 1.351 + 1.352 + /** 1.353 + FORMAT BEGIN 1.354 + 1.355 + *MESH_SOFTSKINVERTS { 1.356 + <nodename> 1.357 + <number of vertices> 1.358 + 1.359 + [for <number of vertices> times:] 1.360 + <number of weights> [for <number of weights> times:] <bone name> <weight> 1.361 + } 1.362 + 1.363 + FORMAT END 1.364 + */ 1.365 + // ************************************************************** 1.366 + while (true) 1.367 + { 1.368 + if (*filePtr == '}' ) {++filePtr;return;} 1.369 + else if (*filePtr == '\0') return; 1.370 + else if (*filePtr == '{' ) ++filePtr; 1.371 + 1.372 + else // if (!IsSpace(*filePtr) && !IsLineEnd(*filePtr)) 1.373 + { 1.374 + ASE::Mesh* curMesh = NULL; 1.375 + unsigned int numVerts = 0; 1.376 + 1.377 + const char* sz = filePtr; 1.378 + while (!IsSpaceOrNewLine(*filePtr))++filePtr; 1.379 + 1.380 + const unsigned int diff = (unsigned int)(filePtr-sz); 1.381 + if (diff) 1.382 + { 1.383 + std::string name = std::string(sz,diff); 1.384 + for (std::vector<ASE::Mesh>::iterator it = m_vMeshes.begin(); 1.385 + it != m_vMeshes.end(); ++it) 1.386 + { 1.387 + if ((*it).mName == name) 1.388 + { 1.389 + curMesh = & (*it); 1.390 + break; 1.391 + } 1.392 + } 1.393 + if (!curMesh) 1.394 + { 1.395 + LogWarning("Encountered unknown mesh in *MESH_SOFTSKINVERTS section"); 1.396 + 1.397 + // Skip the mesh data - until we find a new mesh 1.398 + // or the end of the *MESH_SOFTSKINVERTS section 1.399 + while (true) 1.400 + { 1.401 + SkipSpacesAndLineEnd(&filePtr); 1.402 + if (*filePtr == '}') 1.403 + {++filePtr;return;} 1.404 + else if (!IsNumeric(*filePtr)) 1.405 + break; 1.406 + 1.407 + SkipLine(&filePtr); 1.408 + } 1.409 + } 1.410 + else 1.411 + { 1.412 + SkipSpacesAndLineEnd(&filePtr); 1.413 + ParseLV4MeshLong(numVerts); 1.414 + 1.415 + // Reserve enough storage 1.416 + curMesh->mBoneVertices.reserve(numVerts); 1.417 + 1.418 + for (unsigned int i = 0; i < numVerts;++i) 1.419 + { 1.420 + SkipSpacesAndLineEnd(&filePtr); 1.421 + unsigned int numWeights; 1.422 + ParseLV4MeshLong(numWeights); 1.423 + 1.424 + curMesh->mBoneVertices.push_back(ASE::BoneVertex()); 1.425 + ASE::BoneVertex& vert = curMesh->mBoneVertices.back(); 1.426 + 1.427 + // Reserve enough storage 1.428 + vert.mBoneWeights.reserve(numWeights); 1.429 + 1.430 + for (unsigned int w = 0; w < numWeights;++w) 1.431 + { 1.432 + std::string bone; 1.433 + ParseString(bone,"*MESH_SOFTSKINVERTS.Bone"); 1.434 + 1.435 + // Find the bone in the mesh's list 1.436 + std::pair<int,float> me; 1.437 + me.first = -1; 1.438 + 1.439 + for (unsigned int n = 0; n < curMesh->mBones.size();++n) 1.440 + { 1.441 + if (curMesh->mBones[n].mName == bone) 1.442 + { 1.443 + me.first = n; 1.444 + break; 1.445 + } 1.446 + } 1.447 + if (-1 == me.first) 1.448 + { 1.449 + // We don't have this bone yet, so add it to the list 1.450 + me.first = (int)curMesh->mBones.size(); 1.451 + curMesh->mBones.push_back(ASE::Bone(bone)); 1.452 + } 1.453 + ParseLV4MeshFloat( me.second ); 1.454 + 1.455 + // Add the new bone weight to list 1.456 + vert.mBoneWeights.push_back(me); 1.457 + } 1.458 + } 1.459 + } 1.460 + } 1.461 + } 1.462 + ++filePtr; 1.463 + SkipSpacesAndLineEnd(&filePtr); 1.464 + } 1.465 +} 1.466 + 1.467 +// ------------------------------------------------------------------------------------------------ 1.468 +void Parser::ParseLV1SceneBlock() 1.469 +{ 1.470 + AI_ASE_PARSER_INIT(); 1.471 + while (true) 1.472 + { 1.473 + if ('*' == *filePtr) 1.474 + { 1.475 + ++filePtr; 1.476 + if (TokenMatch(filePtr,"SCENE_BACKGROUND_STATIC",23)) 1.477 + 1.478 + { 1.479 + // parse a color triple and assume it is really the bg color 1.480 + ParseLV4MeshFloatTriple( &m_clrBackground.r ); 1.481 + continue; 1.482 + } 1.483 + if (TokenMatch(filePtr,"SCENE_AMBIENT_STATIC",20)) 1.484 + 1.485 + { 1.486 + // parse a color triple and assume it is really the bg color 1.487 + ParseLV4MeshFloatTriple( &m_clrAmbient.r ); 1.488 + continue; 1.489 + } 1.490 + if (TokenMatch(filePtr,"SCENE_FIRSTFRAME",16)) 1.491 + { 1.492 + ParseLV4MeshLong(iFirstFrame); 1.493 + continue; 1.494 + } 1.495 + if (TokenMatch(filePtr,"SCENE_LASTFRAME",15)) 1.496 + { 1.497 + ParseLV4MeshLong(iLastFrame); 1.498 + continue; 1.499 + } 1.500 + if (TokenMatch(filePtr,"SCENE_FRAMESPEED",16)) 1.501 + { 1.502 + ParseLV4MeshLong(iFrameSpeed); 1.503 + continue; 1.504 + } 1.505 + if (TokenMatch(filePtr,"SCENE_TICKSPERFRAME",19)) 1.506 + { 1.507 + ParseLV4MeshLong(iTicksPerFrame); 1.508 + continue; 1.509 + } 1.510 + } 1.511 + AI_ASE_HANDLE_TOP_LEVEL_SECTION(); 1.512 + } 1.513 +} 1.514 + 1.515 +// ------------------------------------------------------------------------------------------------ 1.516 +void Parser::ParseLV1MaterialListBlock() 1.517 +{ 1.518 + AI_ASE_PARSER_INIT(); 1.519 + 1.520 + unsigned int iMaterialCount = 0; 1.521 + unsigned int iOldMaterialCount = (unsigned int)m_vMaterials.size(); 1.522 + while (true) 1.523 + { 1.524 + if ('*' == *filePtr) 1.525 + { 1.526 + ++filePtr; 1.527 + if (TokenMatch(filePtr,"MATERIAL_COUNT",14)) 1.528 + { 1.529 + ParseLV4MeshLong(iMaterialCount); 1.530 + 1.531 + // now allocate enough storage to hold all materials 1.532 + m_vMaterials.resize(iOldMaterialCount+iMaterialCount); 1.533 + continue; 1.534 + } 1.535 + if (TokenMatch(filePtr,"MATERIAL",8)) 1.536 + { 1.537 + unsigned int iIndex = 0; 1.538 + ParseLV4MeshLong(iIndex); 1.539 + 1.540 + if (iIndex >= iMaterialCount) 1.541 + { 1.542 + LogWarning("Out of range: material index is too large"); 1.543 + iIndex = iMaterialCount-1; 1.544 + } 1.545 + 1.546 + // get a reference to the material 1.547 + Material& sMat = m_vMaterials[iIndex+iOldMaterialCount]; 1.548 + // parse the material block 1.549 + ParseLV2MaterialBlock(sMat); 1.550 + continue; 1.551 + } 1.552 + } 1.553 + AI_ASE_HANDLE_TOP_LEVEL_SECTION(); 1.554 + } 1.555 +} 1.556 + 1.557 +// ------------------------------------------------------------------------------------------------ 1.558 +void Parser::ParseLV2MaterialBlock(ASE::Material& mat) 1.559 +{ 1.560 + AI_ASE_PARSER_INIT(); 1.561 + 1.562 + unsigned int iNumSubMaterials = 0; 1.563 + while (true) 1.564 + { 1.565 + if ('*' == *filePtr) 1.566 + { 1.567 + ++filePtr; 1.568 + if (TokenMatch(filePtr,"MATERIAL_NAME",13)) 1.569 + { 1.570 + if (!ParseString(mat.mName,"*MATERIAL_NAME")) 1.571 + SkipToNextToken(); 1.572 + continue; 1.573 + } 1.574 + // ambient material color 1.575 + if (TokenMatch(filePtr,"MATERIAL_AMBIENT",16)) 1.576 + { 1.577 + ParseLV4MeshFloatTriple(&mat.mAmbient.r); 1.578 + continue; 1.579 + } 1.580 + // diffuse material color 1.581 + if (TokenMatch(filePtr,"MATERIAL_DIFFUSE",16) ) 1.582 + { 1.583 + ParseLV4MeshFloatTriple(&mat.mDiffuse.r); 1.584 + continue; 1.585 + } 1.586 + // specular material color 1.587 + if (TokenMatch(filePtr,"MATERIAL_SPECULAR",17)) 1.588 + { 1.589 + ParseLV4MeshFloatTriple(&mat.mSpecular.r); 1.590 + continue; 1.591 + } 1.592 + // material shading type 1.593 + if (TokenMatch(filePtr,"MATERIAL_SHADING",16)) 1.594 + { 1.595 + if (TokenMatch(filePtr,"Blinn",5)) 1.596 + { 1.597 + mat.mShading = Discreet3DS::Blinn; 1.598 + } 1.599 + else if (TokenMatch(filePtr,"Phong",5)) 1.600 + { 1.601 + mat.mShading = Discreet3DS::Phong; 1.602 + } 1.603 + else if (TokenMatch(filePtr,"Flat",4)) 1.604 + { 1.605 + mat.mShading = Discreet3DS::Flat; 1.606 + } 1.607 + else if (TokenMatch(filePtr,"Wire",4)) 1.608 + { 1.609 + mat.mShading = Discreet3DS::Wire; 1.610 + } 1.611 + else 1.612 + { 1.613 + // assume gouraud shading 1.614 + mat.mShading = Discreet3DS::Gouraud; 1.615 + SkipToNextToken(); 1.616 + } 1.617 + continue; 1.618 + } 1.619 + // material transparency 1.620 + if (TokenMatch(filePtr,"MATERIAL_TRANSPARENCY",21)) 1.621 + { 1.622 + ParseLV4MeshFloat(mat.mTransparency); 1.623 + mat.mTransparency = 1.0f - mat.mTransparency;continue; 1.624 + } 1.625 + // material self illumination 1.626 + if (TokenMatch(filePtr,"MATERIAL_SELFILLUM",18)) 1.627 + { 1.628 + float f = 0.0f; 1.629 + ParseLV4MeshFloat(f); 1.630 + 1.631 + mat.mEmissive.r = f; 1.632 + mat.mEmissive.g = f; 1.633 + mat.mEmissive.b = f; 1.634 + continue; 1.635 + } 1.636 + // material shininess 1.637 + if (TokenMatch(filePtr,"MATERIAL_SHINE",14) ) 1.638 + { 1.639 + ParseLV4MeshFloat(mat.mSpecularExponent); 1.640 + mat.mSpecularExponent *= 15; 1.641 + continue; 1.642 + } 1.643 + // two-sided material 1.644 + if (TokenMatch(filePtr,"MATERIAL_TWOSIDED",17) ) 1.645 + { 1.646 + mat.mTwoSided = true; 1.647 + continue; 1.648 + } 1.649 + // material shininess strength 1.650 + if (TokenMatch(filePtr,"MATERIAL_SHINESTRENGTH",22)) 1.651 + { 1.652 + ParseLV4MeshFloat(mat.mShininessStrength); 1.653 + continue; 1.654 + } 1.655 + // diffuse color map 1.656 + if (TokenMatch(filePtr,"MAP_DIFFUSE",11)) 1.657 + { 1.658 + // parse the texture block 1.659 + ParseLV3MapBlock(mat.sTexDiffuse); 1.660 + continue; 1.661 + } 1.662 + // ambient color map 1.663 + if (TokenMatch(filePtr,"MAP_AMBIENT",11)) 1.664 + { 1.665 + // parse the texture block 1.666 + ParseLV3MapBlock(mat.sTexAmbient); 1.667 + continue; 1.668 + } 1.669 + // specular color map 1.670 + if (TokenMatch(filePtr,"MAP_SPECULAR",12)) 1.671 + { 1.672 + // parse the texture block 1.673 + ParseLV3MapBlock(mat.sTexSpecular); 1.674 + continue; 1.675 + } 1.676 + // opacity map 1.677 + if (TokenMatch(filePtr,"MAP_OPACITY",11)) 1.678 + { 1.679 + // parse the texture block 1.680 + ParseLV3MapBlock(mat.sTexOpacity); 1.681 + continue; 1.682 + } 1.683 + // emissive map 1.684 + if (TokenMatch(filePtr,"MAP_SELFILLUM",13)) 1.685 + { 1.686 + // parse the texture block 1.687 + ParseLV3MapBlock(mat.sTexEmissive); 1.688 + continue; 1.689 + } 1.690 + // bump map 1.691 + if (TokenMatch(filePtr,"MAP_BUMP",8)) 1.692 + { 1.693 + // parse the texture block 1.694 + ParseLV3MapBlock(mat.sTexBump); 1.695 + } 1.696 + // specular/shininess map 1.697 + if (TokenMatch(filePtr,"MAP_SHINESTRENGTH",17)) 1.698 + { 1.699 + // parse the texture block 1.700 + ParseLV3MapBlock(mat.sTexShininess); 1.701 + continue; 1.702 + } 1.703 + // number of submaterials 1.704 + if (TokenMatch(filePtr,"NUMSUBMTLS",10)) 1.705 + { 1.706 + ParseLV4MeshLong(iNumSubMaterials); 1.707 + 1.708 + // allocate enough storage 1.709 + mat.avSubMaterials.resize(iNumSubMaterials); 1.710 + } 1.711 + // submaterial chunks 1.712 + if (TokenMatch(filePtr,"SUBMATERIAL",11)) 1.713 + { 1.714 + 1.715 + unsigned int iIndex = 0; 1.716 + ParseLV4MeshLong(iIndex); 1.717 + 1.718 + if (iIndex >= iNumSubMaterials) 1.719 + { 1.720 + LogWarning("Out of range: submaterial index is too large"); 1.721 + iIndex = iNumSubMaterials-1; 1.722 + } 1.723 + 1.724 + // get a reference to the material 1.725 + Material& sMat = mat.avSubMaterials[iIndex]; 1.726 + 1.727 + // parse the material block 1.728 + ParseLV2MaterialBlock(sMat); 1.729 + continue; 1.730 + } 1.731 + } 1.732 + AI_ASE_HANDLE_SECTION("2","*MATERIAL"); 1.733 + } 1.734 +} 1.735 + 1.736 +// ------------------------------------------------------------------------------------------------ 1.737 +void Parser::ParseLV3MapBlock(Texture& map) 1.738 +{ 1.739 + AI_ASE_PARSER_INIT(); 1.740 + 1.741 + // *********************************************************** 1.742 + // *BITMAP should not be there if *MAP_CLASS is not BITMAP, 1.743 + // but we need to expect that case ... if the path is 1.744 + // empty the texture won't be used later. 1.745 + // *********************************************************** 1.746 + bool parsePath = true; 1.747 + while (true) 1.748 + { 1.749 + if ('*' == *filePtr) 1.750 + { 1.751 + ++filePtr; 1.752 + // type of map 1.753 + if (TokenMatch(filePtr,"MAP_CLASS" ,9)) 1.754 + { 1.755 + std::string temp; 1.756 + if(!ParseString(temp,"*MAP_CLASS")) 1.757 + SkipToNextToken(); 1.758 + if (temp != "Bitmap" && temp != "Normal Bump") 1.759 + { 1.760 + DefaultLogger::get()->warn("ASE: Skipping unknown map type: " + temp); 1.761 + parsePath = false; 1.762 + } 1.763 + continue; 1.764 + } 1.765 + // path to the texture 1.766 + if (parsePath && TokenMatch(filePtr,"BITMAP" ,6)) 1.767 + { 1.768 + if(!ParseString(map.mMapName,"*BITMAP")) 1.769 + SkipToNextToken(); 1.770 + 1.771 + if (map.mMapName == "None") 1.772 + { 1.773 + // Files with 'None' as map name are produced by 1.774 + // an Maja to ASE exporter which name I forgot .. 1.775 + DefaultLogger::get()->warn("ASE: Skipping invalid map entry"); 1.776 + map.mMapName = ""; 1.777 + } 1.778 + 1.779 + continue; 1.780 + } 1.781 + // offset on the u axis 1.782 + if (TokenMatch(filePtr,"UVW_U_OFFSET" ,12)) 1.783 + { 1.784 + ParseLV4MeshFloat(map.mOffsetU); 1.785 + continue; 1.786 + } 1.787 + // offset on the v axis 1.788 + if (TokenMatch(filePtr,"UVW_V_OFFSET" ,12)) 1.789 + { 1.790 + ParseLV4MeshFloat(map.mOffsetV); 1.791 + continue; 1.792 + } 1.793 + // tiling on the u axis 1.794 + if (TokenMatch(filePtr,"UVW_U_TILING" ,12)) 1.795 + { 1.796 + ParseLV4MeshFloat(map.mScaleU); 1.797 + continue; 1.798 + } 1.799 + // tiling on the v axis 1.800 + if (TokenMatch(filePtr,"UVW_V_TILING" ,12)) 1.801 + { 1.802 + ParseLV4MeshFloat(map.mScaleV); 1.803 + continue; 1.804 + } 1.805 + // rotation around the z-axis 1.806 + if (TokenMatch(filePtr,"UVW_ANGLE" ,9)) 1.807 + { 1.808 + ParseLV4MeshFloat(map.mRotation); 1.809 + continue; 1.810 + } 1.811 + // map blending factor 1.812 + if (TokenMatch(filePtr,"MAP_AMOUNT" ,10)) 1.813 + { 1.814 + ParseLV4MeshFloat(map.mTextureBlend); 1.815 + continue; 1.816 + } 1.817 + } 1.818 + AI_ASE_HANDLE_SECTION("3","*MAP_XXXXXX"); 1.819 + } 1.820 + return; 1.821 +} 1.822 + 1.823 +// ------------------------------------------------------------------------------------------------ 1.824 +bool Parser::ParseString(std::string& out,const char* szName) 1.825 +{ 1.826 + char szBuffer[1024]; 1.827 + if (!SkipSpaces(&filePtr)) 1.828 + { 1.829 + 1.830 + sprintf(szBuffer,"Unable to parse %s block: Unexpected EOL",szName); 1.831 + LogWarning(szBuffer); 1.832 + return false; 1.833 + } 1.834 + // there must be '"' 1.835 + if ('\"' != *filePtr) 1.836 + { 1.837 + 1.838 + sprintf(szBuffer,"Unable to parse %s block: Strings are expected " 1.839 + "to be enclosed in double quotation marks",szName); 1.840 + LogWarning(szBuffer); 1.841 + return false; 1.842 + } 1.843 + ++filePtr; 1.844 + const char* sz = filePtr; 1.845 + while (true) 1.846 + { 1.847 + if ('\"' == *sz)break; 1.848 + else if ('\0' == *sz) 1.849 + { 1.850 + sprintf(szBuffer,"Unable to parse %s block: Strings are expected to " 1.851 + "be enclosed in double quotation marks but EOF was reached before " 1.852 + "a closing quotation mark was encountered",szName); 1.853 + LogWarning(szBuffer); 1.854 + return false; 1.855 + } 1.856 + sz++; 1.857 + } 1.858 + out = std::string(filePtr,(uintptr_t)sz-(uintptr_t)filePtr); 1.859 + filePtr = sz+1; 1.860 + return true; 1.861 +} 1.862 + 1.863 +// ------------------------------------------------------------------------------------------------ 1.864 +void Parser::ParseLV1ObjectBlock(ASE::BaseNode& node) 1.865 +{ 1.866 + AI_ASE_PARSER_INIT(); 1.867 + while (true) 1.868 + { 1.869 + if ('*' == *filePtr) 1.870 + { 1.871 + ++filePtr; 1.872 + 1.873 + // first process common tokens such as node name and transform 1.874 + // name of the mesh/node 1.875 + if (TokenMatch(filePtr,"NODE_NAME" ,9)) 1.876 + { 1.877 + if(!ParseString(node.mName,"*NODE_NAME")) 1.878 + SkipToNextToken(); 1.879 + continue; 1.880 + } 1.881 + // name of the parent of the node 1.882 + if (TokenMatch(filePtr,"NODE_PARENT" ,11) ) 1.883 + { 1.884 + if(!ParseString(node.mParent,"*NODE_PARENT")) 1.885 + SkipToNextToken(); 1.886 + continue; 1.887 + } 1.888 + // transformation matrix of the node 1.889 + if (TokenMatch(filePtr,"NODE_TM" ,7)) 1.890 + { 1.891 + ParseLV2NodeTransformBlock(node); 1.892 + continue; 1.893 + } 1.894 + // animation data of the node 1.895 + if (TokenMatch(filePtr,"TM_ANIMATION" ,12)) 1.896 + { 1.897 + ParseLV2AnimationBlock(node); 1.898 + continue; 1.899 + } 1.900 + 1.901 + if (node.mType == BaseNode::Light) 1.902 + { 1.903 + // light settings 1.904 + if (TokenMatch(filePtr,"LIGHT_SETTINGS" ,14)) 1.905 + { 1.906 + ParseLV2LightSettingsBlock((ASE::Light&)node); 1.907 + continue; 1.908 + } 1.909 + // type of the light source 1.910 + if (TokenMatch(filePtr,"LIGHT_TYPE" ,10)) 1.911 + { 1.912 + if (!ASSIMP_strincmp("omni",filePtr,4)) 1.913 + { 1.914 + ((ASE::Light&)node).mLightType = ASE::Light::OMNI; 1.915 + } 1.916 + else if (!ASSIMP_strincmp("target",filePtr,6)) 1.917 + { 1.918 + ((ASE::Light&)node).mLightType = ASE::Light::TARGET; 1.919 + } 1.920 + else if (!ASSIMP_strincmp("free",filePtr,4)) 1.921 + { 1.922 + ((ASE::Light&)node).mLightType = ASE::Light::FREE; 1.923 + } 1.924 + else if (!ASSIMP_strincmp("directional",filePtr,11)) 1.925 + { 1.926 + ((ASE::Light&)node).mLightType = ASE::Light::DIRECTIONAL; 1.927 + } 1.928 + else 1.929 + { 1.930 + LogWarning("Unknown kind of light source"); 1.931 + } 1.932 + continue; 1.933 + } 1.934 + } 1.935 + else if (node.mType == BaseNode::Camera) 1.936 + { 1.937 + // Camera settings 1.938 + if (TokenMatch(filePtr,"CAMERA_SETTINGS" ,15)) 1.939 + { 1.940 + ParseLV2CameraSettingsBlock((ASE::Camera&)node); 1.941 + continue; 1.942 + } 1.943 + else if (TokenMatch(filePtr,"CAMERA_TYPE" ,11)) 1.944 + { 1.945 + if (!ASSIMP_strincmp("target",filePtr,6)) 1.946 + { 1.947 + ((ASE::Camera&)node).mCameraType = ASE::Camera::TARGET; 1.948 + } 1.949 + else if (!ASSIMP_strincmp("free",filePtr,4)) 1.950 + { 1.951 + ((ASE::Camera&)node).mCameraType = ASE::Camera::FREE; 1.952 + } 1.953 + else 1.954 + { 1.955 + LogWarning("Unknown kind of camera"); 1.956 + } 1.957 + continue; 1.958 + } 1.959 + } 1.960 + else if (node.mType == BaseNode::Mesh) 1.961 + { 1.962 + // mesh data 1.963 + // FIX: Older files use MESH_SOFTSKIN 1.964 + if (TokenMatch(filePtr,"MESH" ,4) || 1.965 + TokenMatch(filePtr,"MESH_SOFTSKIN",13)) 1.966 + { 1.967 + ParseLV2MeshBlock((ASE::Mesh&)node); 1.968 + continue; 1.969 + } 1.970 + // mesh material index 1.971 + if (TokenMatch(filePtr,"MATERIAL_REF" ,12)) 1.972 + { 1.973 + ParseLV4MeshLong(((ASE::Mesh&)node).iMaterialIndex); 1.974 + continue; 1.975 + } 1.976 + } 1.977 + } 1.978 + AI_ASE_HANDLE_TOP_LEVEL_SECTION(); 1.979 + } 1.980 + return; 1.981 +} 1.982 + 1.983 +// ------------------------------------------------------------------------------------------------ 1.984 +void Parser::ParseLV2CameraSettingsBlock(ASE::Camera& camera) 1.985 +{ 1.986 + AI_ASE_PARSER_INIT(); 1.987 + while (true) 1.988 + { 1.989 + if ('*' == *filePtr) 1.990 + { 1.991 + ++filePtr; 1.992 + if (TokenMatch(filePtr,"CAMERA_NEAR" ,11)) 1.993 + { 1.994 + ParseLV4MeshFloat(camera.mNear); 1.995 + continue; 1.996 + } 1.997 + if (TokenMatch(filePtr,"CAMERA_FAR" ,10)) 1.998 + { 1.999 + ParseLV4MeshFloat(camera.mFar); 1.1000 + continue; 1.1001 + } 1.1002 + if (TokenMatch(filePtr,"CAMERA_FOV" ,10)) 1.1003 + { 1.1004 + ParseLV4MeshFloat(camera.mFOV); 1.1005 + continue; 1.1006 + } 1.1007 + } 1.1008 + AI_ASE_HANDLE_SECTION("2","CAMERA_SETTINGS"); 1.1009 + } 1.1010 + return; 1.1011 +} 1.1012 + 1.1013 +// ------------------------------------------------------------------------------------------------ 1.1014 +void Parser::ParseLV2LightSettingsBlock(ASE::Light& light) 1.1015 +{ 1.1016 + AI_ASE_PARSER_INIT(); 1.1017 + while (true) 1.1018 + { 1.1019 + if ('*' == *filePtr) 1.1020 + { 1.1021 + ++filePtr; 1.1022 + if (TokenMatch(filePtr,"LIGHT_COLOR" ,11)) 1.1023 + { 1.1024 + ParseLV4MeshFloatTriple(&light.mColor.r); 1.1025 + continue; 1.1026 + } 1.1027 + if (TokenMatch(filePtr,"LIGHT_INTENS" ,12)) 1.1028 + { 1.1029 + ParseLV4MeshFloat(light.mIntensity); 1.1030 + continue; 1.1031 + } 1.1032 + if (TokenMatch(filePtr,"LIGHT_HOTSPOT" ,13)) 1.1033 + { 1.1034 + ParseLV4MeshFloat(light.mAngle); 1.1035 + continue; 1.1036 + } 1.1037 + if (TokenMatch(filePtr,"LIGHT_FALLOFF" ,13)) 1.1038 + { 1.1039 + ParseLV4MeshFloat(light.mFalloff); 1.1040 + continue; 1.1041 + } 1.1042 + } 1.1043 + AI_ASE_HANDLE_SECTION("2","LIGHT_SETTINGS"); 1.1044 + } 1.1045 + return; 1.1046 +} 1.1047 + 1.1048 +// ------------------------------------------------------------------------------------------------ 1.1049 +void Parser::ParseLV2AnimationBlock(ASE::BaseNode& mesh) 1.1050 +{ 1.1051 + AI_ASE_PARSER_INIT(); 1.1052 + 1.1053 + ASE::Animation* anim = &mesh.mAnim; 1.1054 + while (true) 1.1055 + { 1.1056 + if ('*' == *filePtr) 1.1057 + { 1.1058 + ++filePtr; 1.1059 + if (TokenMatch(filePtr,"NODE_NAME" ,9)) 1.1060 + { 1.1061 + std::string temp; 1.1062 + if(!ParseString(temp,"*NODE_NAME")) 1.1063 + SkipToNextToken(); 1.1064 + 1.1065 + // If the name of the node contains .target it 1.1066 + // represents an animated camera or spot light 1.1067 + // target. 1.1068 + if (std::string::npos != temp.find(".Target")) 1.1069 + { 1.1070 + if ((mesh.mType != BaseNode::Camera || ((ASE::Camera&)mesh).mCameraType != ASE::Camera::TARGET) && 1.1071 + ( mesh.mType != BaseNode::Light || ((ASE::Light&)mesh).mLightType != ASE::Light::TARGET)) 1.1072 + { 1.1073 + 1.1074 + DefaultLogger::get()->error("ASE: Found target animation channel " 1.1075 + "but the node is neither a camera nor a spot light"); 1.1076 + anim = NULL; 1.1077 + } 1.1078 + else anim = &mesh.mTargetAnim; 1.1079 + } 1.1080 + continue; 1.1081 + } 1.1082 + 1.1083 + // position keyframes 1.1084 + if (TokenMatch(filePtr,"CONTROL_POS_TRACK" ,17) || 1.1085 + TokenMatch(filePtr,"CONTROL_POS_BEZIER" ,18) || 1.1086 + TokenMatch(filePtr,"CONTROL_POS_TCB" ,15)) 1.1087 + { 1.1088 + if (!anim)SkipSection(); 1.1089 + else ParseLV3PosAnimationBlock(*anim); 1.1090 + continue; 1.1091 + } 1.1092 + // scaling keyframes 1.1093 + if (TokenMatch(filePtr,"CONTROL_SCALE_TRACK" ,19) || 1.1094 + TokenMatch(filePtr,"CONTROL_SCALE_BEZIER" ,20) || 1.1095 + TokenMatch(filePtr,"CONTROL_SCALE_TCB" ,17)) 1.1096 + { 1.1097 + if (!anim || anim == &mesh.mTargetAnim) 1.1098 + { 1.1099 + // Target animation channels may have no rotation channels 1.1100 + DefaultLogger::get()->error("ASE: Ignoring scaling channel in target animation"); 1.1101 + SkipSection(); 1.1102 + } 1.1103 + else ParseLV3ScaleAnimationBlock(*anim); 1.1104 + continue; 1.1105 + } 1.1106 + // rotation keyframes 1.1107 + if (TokenMatch(filePtr,"CONTROL_ROT_TRACK" ,17) || 1.1108 + TokenMatch(filePtr,"CONTROL_ROT_BEZIER" ,18) || 1.1109 + TokenMatch(filePtr,"CONTROL_ROT_TCB" ,15)) 1.1110 + { 1.1111 + if (!anim || anim == &mesh.mTargetAnim) 1.1112 + { 1.1113 + // Target animation channels may have no rotation channels 1.1114 + DefaultLogger::get()->error("ASE: Ignoring rotation channel in target animation"); 1.1115 + SkipSection(); 1.1116 + } 1.1117 + else ParseLV3RotAnimationBlock(*anim); 1.1118 + continue; 1.1119 + } 1.1120 + } 1.1121 + AI_ASE_HANDLE_SECTION("2","TM_ANIMATION"); 1.1122 + } 1.1123 +} 1.1124 +// ------------------------------------------------------------------------------------------------ 1.1125 +void Parser::ParseLV3ScaleAnimationBlock(ASE::Animation& anim) 1.1126 +{ 1.1127 + AI_ASE_PARSER_INIT(); 1.1128 + unsigned int iIndex; 1.1129 + 1.1130 + while (true) 1.1131 + { 1.1132 + if ('*' == *filePtr) 1.1133 + { 1.1134 + ++filePtr; 1.1135 + 1.1136 + bool b = false; 1.1137 + 1.1138 + // For the moment we're just reading the three floats - 1.1139 + // we ignore the ádditional information for bezier's and TCBs 1.1140 + 1.1141 + // simple scaling keyframe 1.1142 + if (TokenMatch(filePtr,"CONTROL_SCALE_SAMPLE" ,20)) 1.1143 + { 1.1144 + b = true; 1.1145 + anim.mScalingType = ASE::Animation::TRACK; 1.1146 + } 1.1147 + 1.1148 + // Bezier scaling keyframe 1.1149 + if (TokenMatch(filePtr,"CONTROL_BEZIER_SCALE_KEY" ,24)) 1.1150 + { 1.1151 + b = true; 1.1152 + anim.mScalingType = ASE::Animation::BEZIER; 1.1153 + } 1.1154 + // TCB scaling keyframe 1.1155 + if (TokenMatch(filePtr,"CONTROL_TCB_SCALE_KEY" ,21)) 1.1156 + { 1.1157 + b = true; 1.1158 + anim.mScalingType = ASE::Animation::TCB; 1.1159 + } 1.1160 + if (b) 1.1161 + { 1.1162 + anim.akeyScaling.push_back(aiVectorKey()); 1.1163 + aiVectorKey& key = anim.akeyScaling.back(); 1.1164 + ParseLV4MeshFloatTriple(&key.mValue.x,iIndex); 1.1165 + key.mTime = (double)iIndex; 1.1166 + } 1.1167 + } 1.1168 + AI_ASE_HANDLE_SECTION("3","*CONTROL_POS_TRACK"); 1.1169 + } 1.1170 +} 1.1171 +// ------------------------------------------------------------------------------------------------ 1.1172 +void Parser::ParseLV3PosAnimationBlock(ASE::Animation& anim) 1.1173 +{ 1.1174 + AI_ASE_PARSER_INIT(); 1.1175 + unsigned int iIndex; 1.1176 + while (true) 1.1177 + { 1.1178 + if ('*' == *filePtr) 1.1179 + { 1.1180 + ++filePtr; 1.1181 + 1.1182 + bool b = false; 1.1183 + 1.1184 + // For the moment we're just reading the three floats - 1.1185 + // we ignore the ádditional information for bezier's and TCBs 1.1186 + 1.1187 + // simple scaling keyframe 1.1188 + if (TokenMatch(filePtr,"CONTROL_POS_SAMPLE" ,18)) 1.1189 + { 1.1190 + b = true; 1.1191 + anim.mPositionType = ASE::Animation::TRACK; 1.1192 + } 1.1193 + 1.1194 + // Bezier scaling keyframe 1.1195 + if (TokenMatch(filePtr,"CONTROL_BEZIER_POS_KEY" ,22)) 1.1196 + { 1.1197 + b = true; 1.1198 + anim.mPositionType = ASE::Animation::BEZIER; 1.1199 + } 1.1200 + // TCB scaling keyframe 1.1201 + if (TokenMatch(filePtr,"CONTROL_TCB_POS_KEY" ,19)) 1.1202 + { 1.1203 + b = true; 1.1204 + anim.mPositionType = ASE::Animation::TCB; 1.1205 + } 1.1206 + if (b) 1.1207 + { 1.1208 + anim.akeyPositions.push_back(aiVectorKey()); 1.1209 + aiVectorKey& key = anim.akeyPositions.back(); 1.1210 + ParseLV4MeshFloatTriple(&key.mValue.x,iIndex); 1.1211 + key.mTime = (double)iIndex; 1.1212 + } 1.1213 + } 1.1214 + AI_ASE_HANDLE_SECTION("3","*CONTROL_POS_TRACK"); 1.1215 + } 1.1216 +} 1.1217 +// ------------------------------------------------------------------------------------------------ 1.1218 +void Parser::ParseLV3RotAnimationBlock(ASE::Animation& anim) 1.1219 +{ 1.1220 + AI_ASE_PARSER_INIT(); 1.1221 + unsigned int iIndex; 1.1222 + while (true) 1.1223 + { 1.1224 + if ('*' == *filePtr) 1.1225 + { 1.1226 + ++filePtr; 1.1227 + 1.1228 + bool b = false; 1.1229 + 1.1230 + // For the moment we're just reading the floats - 1.1231 + // we ignore the ádditional information for bezier's and TCBs 1.1232 + 1.1233 + // simple scaling keyframe 1.1234 + if (TokenMatch(filePtr,"CONTROL_ROT_SAMPLE" ,18)) 1.1235 + { 1.1236 + b = true; 1.1237 + anim.mRotationType = ASE::Animation::TRACK; 1.1238 + } 1.1239 + 1.1240 + // Bezier scaling keyframe 1.1241 + if (TokenMatch(filePtr,"CONTROL_BEZIER_ROT_KEY" ,22)) 1.1242 + { 1.1243 + b = true; 1.1244 + anim.mRotationType = ASE::Animation::BEZIER; 1.1245 + } 1.1246 + // TCB scaling keyframe 1.1247 + if (TokenMatch(filePtr,"CONTROL_TCB_ROT_KEY" ,19)) 1.1248 + { 1.1249 + b = true; 1.1250 + anim.mRotationType = ASE::Animation::TCB; 1.1251 + } 1.1252 + if (b) 1.1253 + { 1.1254 + anim.akeyRotations.push_back(aiQuatKey()); 1.1255 + aiQuatKey& key = anim.akeyRotations.back(); 1.1256 + aiVector3D v;float f; 1.1257 + ParseLV4MeshFloatTriple(&v.x,iIndex); 1.1258 + ParseLV4MeshFloat(f); 1.1259 + key.mTime = (double)iIndex; 1.1260 + key.mValue = aiQuaternion(v,f); 1.1261 + } 1.1262 + } 1.1263 + AI_ASE_HANDLE_SECTION("3","*CONTROL_ROT_TRACK"); 1.1264 + } 1.1265 +} 1.1266 +// ------------------------------------------------------------------------------------------------ 1.1267 +void Parser::ParseLV2NodeTransformBlock(ASE::BaseNode& mesh) 1.1268 +{ 1.1269 + AI_ASE_PARSER_INIT(); 1.1270 + int mode = 0; 1.1271 + while (true) 1.1272 + { 1.1273 + if ('*' == *filePtr) 1.1274 + { 1.1275 + ++filePtr; 1.1276 + // name of the node 1.1277 + if (TokenMatch(filePtr,"NODE_NAME" ,9)) 1.1278 + { 1.1279 + std::string temp; 1.1280 + if(!ParseString(temp,"*NODE_NAME")) 1.1281 + SkipToNextToken(); 1.1282 + 1.1283 + std::string::size_type s; 1.1284 + if (temp == mesh.mName) 1.1285 + { 1.1286 + mode = 1; 1.1287 + } 1.1288 + else if (std::string::npos != (s = temp.find(".Target")) && 1.1289 + mesh.mName == temp.substr(0,s)) 1.1290 + { 1.1291 + // This should be either a target light or a target camera 1.1292 + if ( (mesh.mType == BaseNode::Light && ((ASE::Light&)mesh) .mLightType == ASE::Light::TARGET) || 1.1293 + (mesh.mType == BaseNode::Camera && ((ASE::Camera&)mesh).mCameraType == ASE::Camera::TARGET)) 1.1294 + { 1.1295 + mode = 2; 1.1296 + } 1.1297 + else DefaultLogger::get()->error("ASE: Ignoring target transform, " 1.1298 + "this is no spot light or target camera"); 1.1299 + } 1.1300 + else 1.1301 + { 1.1302 + DefaultLogger::get()->error("ASE: Unknown node transformation: " + temp); 1.1303 + // mode = 0 1.1304 + } 1.1305 + continue; 1.1306 + } 1.1307 + if (mode) 1.1308 + { 1.1309 + // fourth row of the transformation matrix - and also the 1.1310 + // only information here that is interesting for targets 1.1311 + if (TokenMatch(filePtr,"TM_ROW3" ,7)) 1.1312 + { 1.1313 + ParseLV4MeshFloatTriple((mode == 1 ? mesh.mTransform[3] : &mesh.mTargetPosition.x)); 1.1314 + continue; 1.1315 + } 1.1316 + if (mode == 1) 1.1317 + { 1.1318 + // first row of the transformation matrix 1.1319 + if (TokenMatch(filePtr,"TM_ROW0" ,7)) 1.1320 + { 1.1321 + ParseLV4MeshFloatTriple(mesh.mTransform[0]); 1.1322 + continue; 1.1323 + } 1.1324 + // second row of the transformation matrix 1.1325 + if (TokenMatch(filePtr,"TM_ROW1" ,7)) 1.1326 + { 1.1327 + ParseLV4MeshFloatTriple(mesh.mTransform[1]); 1.1328 + continue; 1.1329 + } 1.1330 + // third row of the transformation matrix 1.1331 + if (TokenMatch(filePtr,"TM_ROW2" ,7)) 1.1332 + { 1.1333 + ParseLV4MeshFloatTriple(mesh.mTransform[2]); 1.1334 + continue; 1.1335 + } 1.1336 + // inherited position axes 1.1337 + if (TokenMatch(filePtr,"INHERIT_POS" ,11)) 1.1338 + { 1.1339 + unsigned int aiVal[3]; 1.1340 + ParseLV4MeshLongTriple(aiVal); 1.1341 + 1.1342 + for (unsigned int i = 0; i < 3;++i) 1.1343 + mesh.inherit.abInheritPosition[i] = aiVal[i] != 0; 1.1344 + continue; 1.1345 + } 1.1346 + // inherited rotation axes 1.1347 + if (TokenMatch(filePtr,"INHERIT_ROT" ,11)) 1.1348 + { 1.1349 + unsigned int aiVal[3]; 1.1350 + ParseLV4MeshLongTriple(aiVal); 1.1351 + 1.1352 + for (unsigned int i = 0; i < 3;++i) 1.1353 + mesh.inherit.abInheritRotation[i] = aiVal[i] != 0; 1.1354 + continue; 1.1355 + } 1.1356 + // inherited scaling axes 1.1357 + if (TokenMatch(filePtr,"INHERIT_SCL" ,11)) 1.1358 + { 1.1359 + unsigned int aiVal[3]; 1.1360 + ParseLV4MeshLongTriple(aiVal); 1.1361 + 1.1362 + for (unsigned int i = 0; i < 3;++i) 1.1363 + mesh.inherit.abInheritScaling[i] = aiVal[i] != 0; 1.1364 + continue; 1.1365 + } 1.1366 + } 1.1367 + } 1.1368 + } 1.1369 + AI_ASE_HANDLE_SECTION("2","*NODE_TM"); 1.1370 + } 1.1371 + return; 1.1372 +} 1.1373 +// ------------------------------------------------------------------------------------------------ 1.1374 +void Parser::ParseLV2MeshBlock(ASE::Mesh& mesh) 1.1375 +{ 1.1376 + AI_ASE_PARSER_INIT(); 1.1377 + 1.1378 + unsigned int iNumVertices = 0; 1.1379 + unsigned int iNumFaces = 0; 1.1380 + unsigned int iNumTVertices = 0; 1.1381 + unsigned int iNumTFaces = 0; 1.1382 + unsigned int iNumCVertices = 0; 1.1383 + unsigned int iNumCFaces = 0; 1.1384 + while (true) 1.1385 + { 1.1386 + if ('*' == *filePtr) 1.1387 + { 1.1388 + ++filePtr; 1.1389 + // Number of vertices in the mesh 1.1390 + if (TokenMatch(filePtr,"MESH_NUMVERTEX" ,14)) 1.1391 + { 1.1392 + ParseLV4MeshLong(iNumVertices); 1.1393 + continue; 1.1394 + } 1.1395 + // Number of texture coordinates in the mesh 1.1396 + if (TokenMatch(filePtr,"MESH_NUMTVERTEX" ,15)) 1.1397 + { 1.1398 + ParseLV4MeshLong(iNumTVertices); 1.1399 + continue; 1.1400 + } 1.1401 + // Number of vertex colors in the mesh 1.1402 + if (TokenMatch(filePtr,"MESH_NUMCVERTEX" ,15)) 1.1403 + { 1.1404 + ParseLV4MeshLong(iNumCVertices); 1.1405 + continue; 1.1406 + } 1.1407 + // Number of regular faces in the mesh 1.1408 + if (TokenMatch(filePtr,"MESH_NUMFACES" ,13)) 1.1409 + { 1.1410 + ParseLV4MeshLong(iNumFaces); 1.1411 + continue; 1.1412 + } 1.1413 + // Number of UVWed faces in the mesh 1.1414 + if (TokenMatch(filePtr,"MESH_NUMTVFACES" ,15)) 1.1415 + { 1.1416 + ParseLV4MeshLong(iNumTFaces); 1.1417 + continue; 1.1418 + } 1.1419 + // Number of colored faces in the mesh 1.1420 + if (TokenMatch(filePtr,"MESH_NUMCVFACES" ,15)) 1.1421 + { 1.1422 + ParseLV4MeshLong(iNumCFaces); 1.1423 + continue; 1.1424 + } 1.1425 + // mesh vertex list block 1.1426 + if (TokenMatch(filePtr,"MESH_VERTEX_LIST" ,16)) 1.1427 + { 1.1428 + ParseLV3MeshVertexListBlock(iNumVertices,mesh); 1.1429 + continue; 1.1430 + } 1.1431 + // mesh face list block 1.1432 + if (TokenMatch(filePtr,"MESH_FACE_LIST" ,14)) 1.1433 + { 1.1434 + ParseLV3MeshFaceListBlock(iNumFaces,mesh); 1.1435 + continue; 1.1436 + } 1.1437 + // mesh texture vertex list block 1.1438 + if (TokenMatch(filePtr,"MESH_TVERTLIST" ,14)) 1.1439 + { 1.1440 + ParseLV3MeshTListBlock(iNumTVertices,mesh); 1.1441 + continue; 1.1442 + } 1.1443 + // mesh texture face block 1.1444 + if (TokenMatch(filePtr,"MESH_TFACELIST" ,14)) 1.1445 + { 1.1446 + ParseLV3MeshTFaceListBlock(iNumTFaces,mesh); 1.1447 + continue; 1.1448 + } 1.1449 + // mesh color vertex list block 1.1450 + if (TokenMatch(filePtr,"MESH_CVERTLIST" ,14)) 1.1451 + { 1.1452 + ParseLV3MeshCListBlock(iNumCVertices,mesh); 1.1453 + continue; 1.1454 + } 1.1455 + // mesh color face block 1.1456 + if (TokenMatch(filePtr,"MESH_CFACELIST" ,14)) 1.1457 + { 1.1458 + ParseLV3MeshCFaceListBlock(iNumCFaces,mesh); 1.1459 + continue; 1.1460 + } 1.1461 + // mesh normals 1.1462 + if (TokenMatch(filePtr,"MESH_NORMALS" ,12)) 1.1463 + { 1.1464 + ParseLV3MeshNormalListBlock(mesh); 1.1465 + continue; 1.1466 + } 1.1467 + // another mesh UV channel ... 1.1468 + if (TokenMatch(filePtr,"MESH_MAPPINGCHANNEL" ,19)) 1.1469 + { 1.1470 + 1.1471 + unsigned int iIndex = 0; 1.1472 + ParseLV4MeshLong(iIndex); 1.1473 + 1.1474 + if (iIndex < 2) 1.1475 + { 1.1476 + LogWarning("Mapping channel has an invalid index. Skipping UV channel"); 1.1477 + // skip it ... 1.1478 + SkipSection(); 1.1479 + } 1.1480 + if (iIndex > AI_MAX_NUMBER_OF_TEXTURECOORDS) 1.1481 + { 1.1482 + LogWarning("Too many UV channels specified. Skipping channel .."); 1.1483 + // skip it ... 1.1484 + SkipSection(); 1.1485 + } 1.1486 + else 1.1487 + { 1.1488 + // parse the mapping channel 1.1489 + ParseLV3MappingChannel(iIndex-1,mesh); 1.1490 + } 1.1491 + continue; 1.1492 + } 1.1493 + // mesh animation keyframe. Not supported 1.1494 + if (TokenMatch(filePtr,"MESH_ANIMATION" ,14)) 1.1495 + { 1.1496 + 1.1497 + LogWarning("Found *MESH_ANIMATION element in ASE/ASK file. " 1.1498 + "Keyframe animation is not supported by Assimp, this element " 1.1499 + "will be ignored"); 1.1500 + //SkipSection(); 1.1501 + continue; 1.1502 + } 1.1503 + if (TokenMatch(filePtr,"MESH_WEIGHTS" ,12)) 1.1504 + { 1.1505 + ParseLV3MeshWeightsBlock(mesh);continue; 1.1506 + } 1.1507 + } 1.1508 + AI_ASE_HANDLE_SECTION("2","*MESH"); 1.1509 + } 1.1510 + return; 1.1511 +} 1.1512 +// ------------------------------------------------------------------------------------------------ 1.1513 +void Parser::ParseLV3MeshWeightsBlock(ASE::Mesh& mesh) 1.1514 +{ 1.1515 + AI_ASE_PARSER_INIT(); 1.1516 + 1.1517 + unsigned int iNumVertices = 0, iNumBones = 0; 1.1518 + while (true) 1.1519 + { 1.1520 + if ('*' == *filePtr) 1.1521 + { 1.1522 + ++filePtr; 1.1523 + 1.1524 + // Number of bone vertices ... 1.1525 + if (TokenMatch(filePtr,"MESH_NUMVERTEX" ,14)) 1.1526 + { 1.1527 + ParseLV4MeshLong(iNumVertices); 1.1528 + continue; 1.1529 + } 1.1530 + // Number of bones 1.1531 + if (TokenMatch(filePtr,"MESH_NUMBONE" ,11)) 1.1532 + { 1.1533 + ParseLV4MeshLong(iNumBones); 1.1534 + continue; 1.1535 + } 1.1536 + // parse the list of bones 1.1537 + if (TokenMatch(filePtr,"MESH_BONE_LIST" ,14)) 1.1538 + { 1.1539 + ParseLV4MeshBones(iNumBones,mesh); 1.1540 + continue; 1.1541 + } 1.1542 + // parse the list of bones vertices 1.1543 + if (TokenMatch(filePtr,"MESH_BONE_VERTEX_LIST" ,21) ) 1.1544 + { 1.1545 + ParseLV4MeshBonesVertices(iNumVertices,mesh); 1.1546 + continue; 1.1547 + } 1.1548 + } 1.1549 + AI_ASE_HANDLE_SECTION("3","*MESH_WEIGHTS"); 1.1550 + } 1.1551 + return; 1.1552 +} 1.1553 +// ------------------------------------------------------------------------------------------------ 1.1554 +void Parser::ParseLV4MeshBones(unsigned int iNumBones,ASE::Mesh& mesh) 1.1555 +{ 1.1556 + AI_ASE_PARSER_INIT(); 1.1557 + mesh.mBones.resize(iNumBones); 1.1558 + while (true) 1.1559 + { 1.1560 + if ('*' == *filePtr) 1.1561 + { 1.1562 + ++filePtr; 1.1563 + 1.1564 + // Mesh bone with name ... 1.1565 + if (TokenMatch(filePtr,"MESH_BONE_NAME" ,16)) 1.1566 + { 1.1567 + // parse an index ... 1.1568 + if(SkipSpaces(&filePtr)) 1.1569 + { 1.1570 + unsigned int iIndex = strtoul10(filePtr,&filePtr); 1.1571 + if (iIndex >= iNumBones) 1.1572 + { 1.1573 + LogWarning("Bone index is out of bounds"); 1.1574 + continue; 1.1575 + } 1.1576 + if (!ParseString(mesh.mBones[iIndex].mName,"*MESH_BONE_NAME")) 1.1577 + SkipToNextToken(); 1.1578 + continue; 1.1579 + } 1.1580 + } 1.1581 + } 1.1582 + AI_ASE_HANDLE_SECTION("3","*MESH_BONE_LIST"); 1.1583 + } 1.1584 +} 1.1585 +// ------------------------------------------------------------------------------------------------ 1.1586 +void Parser::ParseLV4MeshBonesVertices(unsigned int iNumVertices,ASE::Mesh& mesh) 1.1587 +{ 1.1588 + AI_ASE_PARSER_INIT(); 1.1589 + mesh.mBoneVertices.resize(iNumVertices); 1.1590 + while (true) 1.1591 + { 1.1592 + if ('*' == *filePtr) 1.1593 + { 1.1594 + ++filePtr; 1.1595 + 1.1596 + // Mesh bone vertex 1.1597 + if (TokenMatch(filePtr,"MESH_BONE_VERTEX" ,16)) 1.1598 + { 1.1599 + // read the vertex index 1.1600 + unsigned int iIndex = strtoul10(filePtr,&filePtr); 1.1601 + if (iIndex >= mesh.mPositions.size()) 1.1602 + { 1.1603 + iIndex = (unsigned int)mesh.mPositions.size()-1; 1.1604 + LogWarning("Bone vertex index is out of bounds. Using the largest valid " 1.1605 + "bone vertex index instead"); 1.1606 + } 1.1607 + 1.1608 + // --- ignored 1.1609 + float afVert[3]; 1.1610 + ParseLV4MeshFloatTriple(afVert); 1.1611 + 1.1612 + std::pair<int,float> pairOut; 1.1613 + while (true) 1.1614 + { 1.1615 + // first parse the bone index ... 1.1616 + if (!SkipSpaces(&filePtr))break; 1.1617 + pairOut.first = strtoul10(filePtr,&filePtr); 1.1618 + 1.1619 + // then parse the vertex weight 1.1620 + if (!SkipSpaces(&filePtr))break; 1.1621 + filePtr = fast_atoreal_move<float>(filePtr,pairOut.second); 1.1622 + 1.1623 + // -1 marks unused entries 1.1624 + if (-1 != pairOut.first) 1.1625 + { 1.1626 + mesh.mBoneVertices[iIndex].mBoneWeights.push_back(pairOut); 1.1627 + } 1.1628 + } 1.1629 + continue; 1.1630 + } 1.1631 + } 1.1632 + AI_ASE_HANDLE_SECTION("4","*MESH_BONE_VERTEX"); 1.1633 + } 1.1634 + return; 1.1635 +} 1.1636 +// ------------------------------------------------------------------------------------------------ 1.1637 +void Parser::ParseLV3MeshVertexListBlock( 1.1638 + unsigned int iNumVertices, ASE::Mesh& mesh) 1.1639 +{ 1.1640 + AI_ASE_PARSER_INIT(); 1.1641 + 1.1642 + // allocate enough storage in the array 1.1643 + mesh.mPositions.resize(iNumVertices); 1.1644 + while (true) 1.1645 + { 1.1646 + if ('*' == *filePtr) 1.1647 + { 1.1648 + ++filePtr; 1.1649 + 1.1650 + // Vertex entry 1.1651 + if (TokenMatch(filePtr,"MESH_VERTEX" ,11)) 1.1652 + { 1.1653 + 1.1654 + aiVector3D vTemp; 1.1655 + unsigned int iIndex; 1.1656 + ParseLV4MeshFloatTriple(&vTemp.x,iIndex); 1.1657 + 1.1658 + if (iIndex >= iNumVertices) 1.1659 + { 1.1660 + LogWarning("Invalid vertex index. It will be ignored"); 1.1661 + } 1.1662 + else mesh.mPositions[iIndex] = vTemp; 1.1663 + continue; 1.1664 + } 1.1665 + } 1.1666 + AI_ASE_HANDLE_SECTION("3","*MESH_VERTEX_LIST"); 1.1667 + } 1.1668 + return; 1.1669 +} 1.1670 +// ------------------------------------------------------------------------------------------------ 1.1671 +void Parser::ParseLV3MeshFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh) 1.1672 +{ 1.1673 + AI_ASE_PARSER_INIT(); 1.1674 + 1.1675 + // allocate enough storage in the face array 1.1676 + mesh.mFaces.resize(iNumFaces); 1.1677 + while (true) 1.1678 + { 1.1679 + if ('*' == *filePtr) 1.1680 + { 1.1681 + ++filePtr; 1.1682 + 1.1683 + // Face entry 1.1684 + if (TokenMatch(filePtr,"MESH_FACE" ,9)) 1.1685 + { 1.1686 + 1.1687 + ASE::Face mFace; 1.1688 + ParseLV4MeshFace(mFace); 1.1689 + 1.1690 + if (mFace.iFace >= iNumFaces) 1.1691 + { 1.1692 + LogWarning("Face has an invalid index. It will be ignored"); 1.1693 + } 1.1694 + else mesh.mFaces[mFace.iFace] = mFace; 1.1695 + continue; 1.1696 + } 1.1697 + } 1.1698 + AI_ASE_HANDLE_SECTION("3","*MESH_FACE_LIST"); 1.1699 + } 1.1700 + return; 1.1701 +} 1.1702 +// ------------------------------------------------------------------------------------------------ 1.1703 +void Parser::ParseLV3MeshTListBlock(unsigned int iNumVertices, 1.1704 + ASE::Mesh& mesh, unsigned int iChannel) 1.1705 +{ 1.1706 + AI_ASE_PARSER_INIT(); 1.1707 + 1.1708 + // allocate enough storage in the array 1.1709 + mesh.amTexCoords[iChannel].resize(iNumVertices); 1.1710 + while (true) 1.1711 + { 1.1712 + if ('*' == *filePtr) 1.1713 + { 1.1714 + ++filePtr; 1.1715 + 1.1716 + // Vertex entry 1.1717 + if (TokenMatch(filePtr,"MESH_TVERT" ,10)) 1.1718 + { 1.1719 + aiVector3D vTemp; 1.1720 + unsigned int iIndex; 1.1721 + ParseLV4MeshFloatTriple(&vTemp.x,iIndex); 1.1722 + 1.1723 + if (iIndex >= iNumVertices) 1.1724 + { 1.1725 + LogWarning("Tvertex has an invalid index. It will be ignored"); 1.1726 + } 1.1727 + else mesh.amTexCoords[iChannel][iIndex] = vTemp; 1.1728 + 1.1729 + if (0.0f != vTemp.z) 1.1730 + { 1.1731 + // we need 3 coordinate channels 1.1732 + mesh.mNumUVComponents[iChannel] = 3; 1.1733 + } 1.1734 + continue; 1.1735 + } 1.1736 + } 1.1737 + AI_ASE_HANDLE_SECTION("3","*MESH_TVERT_LIST"); 1.1738 + } 1.1739 + return; 1.1740 +} 1.1741 +// ------------------------------------------------------------------------------------------------ 1.1742 +void Parser::ParseLV3MeshTFaceListBlock(unsigned int iNumFaces, 1.1743 + ASE::Mesh& mesh, unsigned int iChannel) 1.1744 +{ 1.1745 + AI_ASE_PARSER_INIT(); 1.1746 + while (true) 1.1747 + { 1.1748 + if ('*' == *filePtr) 1.1749 + { 1.1750 + ++filePtr; 1.1751 + 1.1752 + // Face entry 1.1753 + if (TokenMatch(filePtr,"MESH_TFACE" ,10)) 1.1754 + { 1.1755 + unsigned int aiValues[3]; 1.1756 + unsigned int iIndex = 0; 1.1757 + 1.1758 + ParseLV4MeshLongTriple(aiValues,iIndex); 1.1759 + if (iIndex >= iNumFaces || iIndex >= mesh.mFaces.size()) 1.1760 + { 1.1761 + LogWarning("UV-Face has an invalid index. It will be ignored"); 1.1762 + } 1.1763 + else 1.1764 + { 1.1765 + // copy UV indices 1.1766 + mesh.mFaces[iIndex].amUVIndices[iChannel][0] = aiValues[0]; 1.1767 + mesh.mFaces[iIndex].amUVIndices[iChannel][1] = aiValues[1]; 1.1768 + mesh.mFaces[iIndex].amUVIndices[iChannel][2] = aiValues[2]; 1.1769 + } 1.1770 + continue; 1.1771 + } 1.1772 + } 1.1773 + AI_ASE_HANDLE_SECTION("3","*MESH_TFACE_LIST"); 1.1774 + } 1.1775 + return; 1.1776 +} 1.1777 +// ------------------------------------------------------------------------------------------------ 1.1778 +void Parser::ParseLV3MappingChannel(unsigned int iChannel, ASE::Mesh& mesh) 1.1779 +{ 1.1780 + AI_ASE_PARSER_INIT(); 1.1781 + 1.1782 + unsigned int iNumTVertices = 0; 1.1783 + unsigned int iNumTFaces = 0; 1.1784 + while (true) 1.1785 + { 1.1786 + if ('*' == *filePtr) 1.1787 + { 1.1788 + ++filePtr; 1.1789 + 1.1790 + // Number of texture coordinates in the mesh 1.1791 + if (TokenMatch(filePtr,"MESH_NUMTVERTEX" ,15)) 1.1792 + { 1.1793 + ParseLV4MeshLong(iNumTVertices); 1.1794 + continue; 1.1795 + } 1.1796 + // Number of UVWed faces in the mesh 1.1797 + if (TokenMatch(filePtr,"MESH_NUMTVFACES" ,15)) 1.1798 + { 1.1799 + ParseLV4MeshLong(iNumTFaces); 1.1800 + continue; 1.1801 + } 1.1802 + // mesh texture vertex list block 1.1803 + if (TokenMatch(filePtr,"MESH_TVERTLIST" ,14)) 1.1804 + { 1.1805 + ParseLV3MeshTListBlock(iNumTVertices,mesh,iChannel); 1.1806 + continue; 1.1807 + } 1.1808 + // mesh texture face block 1.1809 + if (TokenMatch(filePtr,"MESH_TFACELIST" ,14)) 1.1810 + { 1.1811 + ParseLV3MeshTFaceListBlock(iNumTFaces,mesh, iChannel); 1.1812 + continue; 1.1813 + } 1.1814 + } 1.1815 + AI_ASE_HANDLE_SECTION("3","*MESH_MAPPING_CHANNEL"); 1.1816 + } 1.1817 + return; 1.1818 +} 1.1819 +// ------------------------------------------------------------------------------------------------ 1.1820 +void Parser::ParseLV3MeshCListBlock(unsigned int iNumVertices, ASE::Mesh& mesh) 1.1821 +{ 1.1822 + AI_ASE_PARSER_INIT(); 1.1823 + 1.1824 + // allocate enough storage in the array 1.1825 + mesh.mVertexColors.resize(iNumVertices); 1.1826 + while (true) 1.1827 + { 1.1828 + if ('*' == *filePtr) 1.1829 + { 1.1830 + ++filePtr; 1.1831 + 1.1832 + // Vertex entry 1.1833 + if (TokenMatch(filePtr,"MESH_VERTCOL" ,12)) 1.1834 + { 1.1835 + aiColor4D vTemp; 1.1836 + vTemp.a = 1.0f; 1.1837 + unsigned int iIndex; 1.1838 + ParseLV4MeshFloatTriple(&vTemp.r,iIndex); 1.1839 + 1.1840 + if (iIndex >= iNumVertices) 1.1841 + { 1.1842 + LogWarning("Vertex color has an invalid index. It will be ignored"); 1.1843 + } 1.1844 + else mesh.mVertexColors[iIndex] = vTemp; 1.1845 + continue; 1.1846 + } 1.1847 + } 1.1848 + AI_ASE_HANDLE_SECTION("3","*MESH_CVERTEX_LIST"); 1.1849 + } 1.1850 + return; 1.1851 +} 1.1852 +// ------------------------------------------------------------------------------------------------ 1.1853 +void Parser::ParseLV3MeshCFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh) 1.1854 +{ 1.1855 + AI_ASE_PARSER_INIT(); 1.1856 + while (true) 1.1857 + { 1.1858 + if ('*' == *filePtr) 1.1859 + { 1.1860 + ++filePtr; 1.1861 + 1.1862 + // Face entry 1.1863 + if (TokenMatch(filePtr,"MESH_CFACE" ,11)) 1.1864 + { 1.1865 + unsigned int aiValues[3]; 1.1866 + unsigned int iIndex = 0; 1.1867 + 1.1868 + ParseLV4MeshLongTriple(aiValues,iIndex); 1.1869 + if (iIndex >= iNumFaces || iIndex >= mesh.mFaces.size()) 1.1870 + { 1.1871 + LogWarning("UV-Face has an invalid index. It will be ignored"); 1.1872 + } 1.1873 + else 1.1874 + { 1.1875 + // copy color indices 1.1876 + mesh.mFaces[iIndex].mColorIndices[0] = aiValues[0]; 1.1877 + mesh.mFaces[iIndex].mColorIndices[1] = aiValues[1]; 1.1878 + mesh.mFaces[iIndex].mColorIndices[2] = aiValues[2]; 1.1879 + } 1.1880 + continue; 1.1881 + } 1.1882 + } 1.1883 + AI_ASE_HANDLE_SECTION("3","*MESH_CFACE_LIST"); 1.1884 + } 1.1885 + return; 1.1886 +} 1.1887 +// ------------------------------------------------------------------------------------------------ 1.1888 +void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh) 1.1889 +{ 1.1890 + AI_ASE_PARSER_INIT(); 1.1891 + 1.1892 + // Allocate enough storage for the normals 1.1893 + sMesh.mNormals.resize(sMesh.mFaces.size()*3,aiVector3D( 0.f, 0.f, 0.f )); 1.1894 + unsigned int index, faceIdx = UINT_MAX; 1.1895 + 1.1896 + // FIXME: rewrite this and find out how to interpret the normals 1.1897 + // correctly. This is crap. 1.1898 + 1.1899 + // Smooth the vertex and face normals together. The result 1.1900 + // will be edgy then, but otherwise everything would be soft ... 1.1901 + while (true) { 1.1902 + if ('*' == *filePtr) { 1.1903 + ++filePtr; 1.1904 + if (faceIdx != UINT_MAX && TokenMatch(filePtr,"MESH_VERTEXNORMAL",17)) { 1.1905 + aiVector3D vNormal; 1.1906 + ParseLV4MeshFloatTriple(&vNormal.x,index); 1.1907 + if (faceIdx >= sMesh.mFaces.size()) 1.1908 + continue; 1.1909 + 1.1910 + // Make sure we assign it to the correct face 1.1911 + const ASE::Face& face = sMesh.mFaces[faceIdx]; 1.1912 + if (index == face.mIndices[0]) 1.1913 + index = 0; 1.1914 + else if (index == face.mIndices[1]) 1.1915 + index = 1; 1.1916 + else if (index == face.mIndices[2]) 1.1917 + index = 2; 1.1918 + else { 1.1919 + DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_VERTEXNORMAL section"); 1.1920 + continue; 1.1921 + } 1.1922 + // We'll renormalize later 1.1923 + sMesh.mNormals[faceIdx*3+index] += vNormal; 1.1924 + continue; 1.1925 + } 1.1926 + if (TokenMatch(filePtr,"MESH_FACENORMAL",15)) { 1.1927 + aiVector3D vNormal; 1.1928 + ParseLV4MeshFloatTriple(&vNormal.x,faceIdx); 1.1929 + 1.1930 + if (faceIdx >= sMesh.mFaces.size()) { 1.1931 + DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_FACENORMAL section"); 1.1932 + continue; 1.1933 + } 1.1934 + 1.1935 + // We'll renormalize later 1.1936 + sMesh.mNormals[faceIdx*3] += vNormal; 1.1937 + sMesh.mNormals[faceIdx*3+1] += vNormal; 1.1938 + sMesh.mNormals[faceIdx*3+2] += vNormal; 1.1939 + continue; 1.1940 + } 1.1941 + } 1.1942 + AI_ASE_HANDLE_SECTION("3","*MESH_NORMALS"); 1.1943 + } 1.1944 + return; 1.1945 +} 1.1946 +// ------------------------------------------------------------------------------------------------ 1.1947 +void Parser::ParseLV4MeshFace(ASE::Face& out) 1.1948 +{ 1.1949 + // skip spaces and tabs 1.1950 + if(!SkipSpaces(&filePtr)) 1.1951 + { 1.1952 + LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL [#1]"); 1.1953 + SkipToNextToken(); 1.1954 + return; 1.1955 + } 1.1956 + 1.1957 + // parse the face index 1.1958 + out.iFace = strtoul10(filePtr,&filePtr); 1.1959 + 1.1960 + // next character should be ':' 1.1961 + if(!SkipSpaces(&filePtr)) 1.1962 + { 1.1963 + // FIX: there are some ASE files which haven't got : here .... 1.1964 + LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. \':\' expected [#2]"); 1.1965 + SkipToNextToken(); 1.1966 + return; 1.1967 + } 1.1968 + // FIX: There are some ASE files which haven't got ':' here 1.1969 + if(':' == *filePtr)++filePtr; 1.1970 + 1.1971 + // Parse all mesh indices 1.1972 + for (unsigned int i = 0; i < 3;++i) 1.1973 + { 1.1974 + unsigned int iIndex = 0; 1.1975 + if(!SkipSpaces(&filePtr)) 1.1976 + { 1.1977 + LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL"); 1.1978 + SkipToNextToken(); 1.1979 + return; 1.1980 + } 1.1981 + switch (*filePtr) 1.1982 + { 1.1983 + case 'A': 1.1984 + case 'a': 1.1985 + break; 1.1986 + case 'B': 1.1987 + case 'b': 1.1988 + iIndex = 1; 1.1989 + break; 1.1990 + case 'C': 1.1991 + case 'c': 1.1992 + iIndex = 2; 1.1993 + break; 1.1994 + default: 1.1995 + LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. " 1.1996 + "A,B or C expected [#3]"); 1.1997 + SkipToNextToken(); 1.1998 + return; 1.1999 + }; 1.2000 + ++filePtr; 1.2001 + 1.2002 + // next character should be ':' 1.2003 + if(!SkipSpaces(&filePtr) || ':' != *filePtr) 1.2004 + { 1.2005 + LogWarning("Unable to parse *MESH_FACE Element: " 1.2006 + "Unexpected EOL. \':\' expected [#2]"); 1.2007 + SkipToNextToken(); 1.2008 + return; 1.2009 + } 1.2010 + 1.2011 + ++filePtr; 1.2012 + if(!SkipSpaces(&filePtr)) 1.2013 + { 1.2014 + LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. " 1.2015 + "Vertex index ecpected [#4]"); 1.2016 + SkipToNextToken(); 1.2017 + return; 1.2018 + } 1.2019 + out.mIndices[iIndex] = strtoul10(filePtr,&filePtr); 1.2020 + } 1.2021 + 1.2022 + // now we need to skip the AB, BC, CA blocks. 1.2023 + while (true) 1.2024 + { 1.2025 + if ('*' == *filePtr)break; 1.2026 + if (IsLineEnd(*filePtr)) 1.2027 + { 1.2028 + //iLineNumber++; 1.2029 + return; 1.2030 + } 1.2031 + filePtr++; 1.2032 + } 1.2033 + 1.2034 + // parse the smoothing group of the face 1.2035 + if (TokenMatch(filePtr,"*MESH_SMOOTHING",15)) 1.2036 + { 1.2037 + if(!SkipSpaces(&filePtr)) 1.2038 + { 1.2039 + LogWarning("Unable to parse *MESH_SMOOTHING Element: " 1.2040 + "Unexpected EOL. Smoothing group(s) expected [#5]"); 1.2041 + SkipToNextToken(); 1.2042 + return; 1.2043 + } 1.2044 + 1.2045 + // Parse smoothing groups until we don't anymore see commas 1.2046 + // FIX: There needn't always be a value, sad but true 1.2047 + while (true) 1.2048 + { 1.2049 + if (*filePtr < '9' && *filePtr >= '0') 1.2050 + { 1.2051 + out.iSmoothGroup |= (1 << strtoul10(filePtr,&filePtr)); 1.2052 + } 1.2053 + SkipSpaces(&filePtr); 1.2054 + if (',' != *filePtr) 1.2055 + { 1.2056 + break; 1.2057 + } 1.2058 + ++filePtr; 1.2059 + SkipSpaces(&filePtr); 1.2060 + } 1.2061 + } 1.2062 + 1.2063 + // *MESH_MTLID is optional, too 1.2064 + while (true) 1.2065 + { 1.2066 + if ('*' == *filePtr)break; 1.2067 + if (IsLineEnd(*filePtr)) 1.2068 + { 1.2069 + return; 1.2070 + } 1.2071 + filePtr++; 1.2072 + } 1.2073 + 1.2074 + if (TokenMatch(filePtr,"*MESH_MTLID",11)) 1.2075 + { 1.2076 + if(!SkipSpaces(&filePtr)) 1.2077 + { 1.2078 + LogWarning("Unable to parse *MESH_MTLID Element: Unexpected EOL. " 1.2079 + "Material index expected [#6]"); 1.2080 + SkipToNextToken(); 1.2081 + return; 1.2082 + } 1.2083 + out.iMaterial = strtoul10(filePtr,&filePtr); 1.2084 + } 1.2085 + return; 1.2086 +} 1.2087 +// ------------------------------------------------------------------------------------------------ 1.2088 +void Parser::ParseLV4MeshLongTriple(unsigned int* apOut) 1.2089 +{ 1.2090 + ai_assert(NULL != apOut); 1.2091 + 1.2092 + for (unsigned int i = 0; i < 3;++i) 1.2093 + ParseLV4MeshLong(apOut[i]); 1.2094 +} 1.2095 +// ------------------------------------------------------------------------------------------------ 1.2096 +void Parser::ParseLV4MeshLongTriple(unsigned int* apOut, unsigned int& rIndexOut) 1.2097 +{ 1.2098 + ai_assert(NULL != apOut); 1.2099 + 1.2100 + // parse the index 1.2101 + ParseLV4MeshLong(rIndexOut); 1.2102 + 1.2103 + // parse the three others 1.2104 + ParseLV4MeshLongTriple(apOut); 1.2105 +} 1.2106 +// ------------------------------------------------------------------------------------------------ 1.2107 +void Parser::ParseLV4MeshFloatTriple(float* apOut, unsigned int& rIndexOut) 1.2108 +{ 1.2109 + ai_assert(NULL != apOut); 1.2110 + 1.2111 + // parse the index 1.2112 + ParseLV4MeshLong(rIndexOut); 1.2113 + 1.2114 + // parse the three others 1.2115 + ParseLV4MeshFloatTriple(apOut); 1.2116 +} 1.2117 +// ------------------------------------------------------------------------------------------------ 1.2118 +void Parser::ParseLV4MeshFloatTriple(float* apOut) 1.2119 +{ 1.2120 + ai_assert(NULL != apOut); 1.2121 + 1.2122 + for (unsigned int i = 0; i < 3;++i) 1.2123 + ParseLV4MeshFloat(apOut[i]); 1.2124 +} 1.2125 +// ------------------------------------------------------------------------------------------------ 1.2126 +void Parser::ParseLV4MeshFloat(float& fOut) 1.2127 +{ 1.2128 + // skip spaces and tabs 1.2129 + if(!SkipSpaces(&filePtr)) 1.2130 + { 1.2131 + // LOG 1.2132 + LogWarning("Unable to parse float: unexpected EOL [#1]"); 1.2133 + fOut = 0.0f; 1.2134 + ++iLineNumber; 1.2135 + return; 1.2136 + } 1.2137 + // parse the first float 1.2138 + filePtr = fast_atoreal_move<float>(filePtr,fOut); 1.2139 +} 1.2140 +// ------------------------------------------------------------------------------------------------ 1.2141 +void Parser::ParseLV4MeshLong(unsigned int& iOut) 1.2142 +{ 1.2143 + // Skip spaces and tabs 1.2144 + if(!SkipSpaces(&filePtr)) 1.2145 + { 1.2146 + // LOG 1.2147 + LogWarning("Unable to parse long: unexpected EOL [#1]"); 1.2148 + iOut = 0; 1.2149 + ++iLineNumber; 1.2150 + return; 1.2151 + } 1.2152 + // parse the value 1.2153 + iOut = strtoul10(filePtr,&filePtr); 1.2154 +} 1.2155 + 1.2156 +#endif // !! ASSIMP_BUILD_NO_BASE_IMPORTER