Visualization Library v1.0.3A lightweight C++ OpenGL middleware for 2D/3D graphics |
[Download] [Tutorials] [All Classes] [Grouped Classes] |
00001 /**************************************************************************************/ 00002 /* */ 00003 /* Visualization Library */ 00004 /* http://visualizationlibrary.org */ 00005 /* */ 00006 /* Copyright (c) 2005-2010, Michele Bosi */ 00007 /* All rights reserved. */ 00008 /* */ 00009 /* Redistribution and use in source and binary forms, with or without modification, */ 00010 /* are permitted provided that the following conditions are met: */ 00011 /* */ 00012 /* - Redistributions of source code must retain the above copyright notice, this */ 00013 /* list of conditions and the following disclaimer. */ 00014 /* */ 00015 /* - Redistributions in binary form must reproduce the above copyright notice, this */ 00016 /* list of conditions and the following disclaimer in the documentation and/or */ 00017 /* other materials provided with the distribution. */ 00018 /* */ 00019 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ 00020 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ 00021 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ 00022 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */ 00023 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ 00024 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ 00025 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ 00026 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ 00027 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ 00028 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 00029 /* */ 00030 /**************************************************************************************/ 00031 00032 #include "io3DS.hpp" 00033 #include <vlGraphics/Effect.hpp> 00034 #include <vlGraphics/Geometry.hpp> 00035 #include <vlGraphics/Actor.hpp> 00036 #include <vlGraphics/Texture.hpp> 00037 #include <vlCore/Image.hpp> 00038 #include <vlGraphics/Camera.hpp> 00039 #include <vlCore/Time.hpp> 00040 #include <vlCore/Log.hpp> 00041 #include <vlCore/Say.hpp> 00042 #include <vlCore/LoadWriterManager.hpp> 00043 #include <vlCore/VisualizationLibrary.hpp> 00044 #include <vlCore/FileSystem.hpp> 00045 #include <set> 00046 00047 using namespace vl; 00048 00049 #define ID_3D_EDITOR_CHUNK 0x3D3D 00050 #define ID_MAIN_CHUNK 0x4D4D 00051 #define ID_3DS_VERSION 0x0002 00052 #define ID_OBJECT_BLOCK 0x4000 00053 #define ID_MATERIAL_BLOCK 0xAFFF 00054 #define ID_COLOR_F 0x0010 00055 #define ID_COLOR_24 0x0011 00056 #define ID_LIN_COLOR_24 0x0012 00057 #define ID_LIN_COLOR_F 0x0013 00058 #define ID_INT_PERCENTAGE 0x0030 00059 #define ID_FLOAT_PERCENTAGE 0x0031 00060 #define ID_MATERIAL_NAME 0xA000 00061 #define ID_MAT_AMBIENT 0xA010 00062 #define ID_MAT_DIFFUSE 0xA020 00063 #define ID_MAT_SPECULAR 0xA030 00064 #define ID_MAT_SHININESS_PERCENT 0xA040 00065 #define ID_MAT_SHININESS_STRENGTH_PERCENT 0xA041 00066 #define ID_MAT_TRANSPARENCY 0xA050 00067 #define ID_MAT_TWO_SIDE 0xA081 00068 #define ID_MAT_TEXMAP 0xA200 00069 #define ID_MAT_TEXMAP2 0xA33A 00070 #define ID_MAT_MAPNAME 0xA300 00071 #define ID_MAT_MAP_TILING 0xA351 00072 #define ID_MAT_USCALE 0xA354 00073 #define ID_MAT_VSCALE 0xA356 00074 #define ID_MAT_UOFFSET 0xA358 00075 #define ID_MAT_VOFFSET 0xA35A 00076 #define ID_MAT_MAP_ROTATION 0xA35C 00077 #define ID_TRIANGULAR_MESH 0x4100 00078 #define ID_LOCAL_COORDS_SYSTEM 0x4160 00079 #define ID_MAPPING_COORDS 0x4140 00080 #define ID_SMOOTHING_GROUP_LIST 0x4150 00081 #define ID_FACE_MATERIAL_LIST 0x4130 00082 #define ID_FACE_LIST 0x4120 00083 #define ID_VERTEX_LIST 0x4110 00084 #define ID_HIERARCHY 0x4F00 00085 #define ID_PARENT_OBJECT 0x4F10 00086 #define ID_PIVOT_OBJECT 0x4F20 00087 #define ID_PIVOT_LIMITS 0x4F30 00088 #define ID_PIVOT_ORDER 0x4F40 00089 #define ID_XLATE_RANGE 0x4F50 00090 00091 #define ID_KEYFRAMER_CHUNK 0xB000 00092 #define ID_KEYF_OBJDES 0xB002 // Mesh Information Block 00093 #define ID_KEYF_OBJHIERARCH 0xB010 // Object Name And Hierarchy 00094 #define ID_KEYF_OBJPIVOT 0xB013 // Object Pivot Point 00095 #define ID_KEYF_POSITION_TRACK 0xB020 // Position Track + Pivot 00096 #define ID_KEYF_ROTATION_TRACK 0xB021 // Rotation Track 00097 #define ID_KEYF_SCALE_TRACK 0xB022 // Scale Track 00098 #define ID_KEYF_NODE_ID 0xB030 // Node ID 00099 #define ID_KEY_SPOTLIGHT_NODE_TAG 0xB007 // Spot Light Information Block 00100 #define ID_KEY_FRAMES_START_END 0xB008 // Frames (Start and End) 00101 00102 //----------------------------------------------------------------------------- 00103 // A3DSLoader 00104 //----------------------------------------------------------------------------- 00105 A3DSLoader::A3DSLoader() 00106 { 00107 } 00108 //----------------------------------------------------------------------------- 00109 fvec3 A3DSLoader::readVec3() 00110 { 00111 fvec3 v; 00112 v.x() = mInputFile->readFloat(); 00113 v.y() = mInputFile->readFloat(); 00114 v.z() = mInputFile->readFloat(); 00115 return v; 00116 } 00117 //----------------------------------------------------------------------------- 00118 fvec3 A3DSLoader::readColByte3() 00119 { 00120 fvec3 c; 00121 c.r() = mInputFile->readUInt8() / 255.0f; 00122 c.g() = mInputFile->readUInt8() / 255.0f; 00123 c.b() = mInputFile->readUInt8() / 255.0f; 00124 return c; 00125 } 00126 //----------------------------------------------------------------------------- 00127 fvec3 A3DSLoader::readColFloat3() 00128 { 00129 fvec3 c; 00130 c.r() = mInputFile->readFloat(); 00131 c.g() = mInputFile->readFloat(); 00132 c.b() = mInputFile->readFloat(); 00133 return c; 00134 } 00135 //----------------------------------------------------------------------------- 00136 String A3DSLoader::readLine() 00137 { 00138 std::vector<unsigned char> str; 00139 unsigned char b; 00140 do { 00141 b= mInputFile->readUInt8(); 00142 str.push_back(b); 00143 } while(b); 00144 00145 return (char*)&str[0]; 00146 } 00147 //----------------------------------------------------------------------------- 00148 float A3DSLoader::readWordPercent() 00149 { 00150 return mInputFile->readUInt16() / 100.0f; 00151 } 00152 //----------------------------------------------------------------------------- 00153 float A3DSLoader::readFloatPercent() 00154 { 00155 return mInputFile->readFloat() / 100.0f; 00156 } 00157 //----------------------------------------------------------------------------- 00158 void A3DSLoader::readChunk() 00159 { 00160 mChunkId = mInputFile->readUInt16(); 00161 mChunkLen = mInputFile->readUInt32(); 00162 } 00163 //----------------------------------------------------------------------------- 00164 bool A3DSLoader::skipChunk() 00165 { 00166 mCorrupted |= !mInputFile->seekCur( mChunkLen - 6 ); 00167 if (mCorrupted) 00168 { 00169 Log::error("3ds file is corrupted.\n"); 00170 mObjects.clear(); 00171 mMaterials.clear(); 00172 } 00173 00174 return !mCorrupted; 00175 } 00176 //----------------------------------------------------------------------------- 00177 void A3DSLoader::read_3D_EDITOR_CHUNK() 00178 { 00179 long long chunk_end = (int)mInputFile->position() + mChunkLen - 6; 00180 if ( chunk_end > mInputFile->size() ) 00181 { 00182 Log::error("3ds file is corrupted.\n"); 00183 mCorrupted = true; 00184 mObjects.clear(); 00185 mMaterials.clear(); 00186 chunk_end = mInputFile->size(); 00187 } 00188 00189 while(mInputFile->position() < chunk_end && !mCorrupted) 00190 { 00191 readChunk(); 00192 00193 switch(mChunkId) 00194 { 00195 case ID_OBJECT_BLOCK: 00196 read_OBJECT_BLOCK(); 00197 break; 00198 00199 case ID_MATERIAL_BLOCK: 00200 read_MATERIAL_BLOCK(); 00201 break; 00202 00203 default: 00204 skipChunk(); 00205 } 00206 } 00207 } 00208 //----------------------------------------------------------------------------- 00209 fvec3 A3DSLoader::readColChunk() 00210 { 00211 long long chunk_end = (int)mInputFile->position() + mChunkLen - 6; 00212 if ( chunk_end > mInputFile->size() ) 00213 { 00214 Log::error("3ds file is corrupted.\n"); 00215 mCorrupted = true; 00216 mObjects.clear(); 00217 mMaterials.clear(); 00218 chunk_end = mInputFile->size(); 00219 } 00220 00221 fvec3 color; 00222 while( mInputFile->position() < chunk_end && !mCorrupted ) 00223 { 00224 readChunk(); 00225 switch(mChunkId) 00226 { 00227 case ID_COLOR_F: 00228 color = readColFloat3(); 00229 break; 00230 case ID_COLOR_24: 00231 color = readColByte3(); 00232 break; 00233 // skip gamma byte 00234 case ID_LIN_COLOR_24: 00235 readColByte3(); 00236 break; 00237 // skip gamma float 00238 case ID_LIN_COLOR_F: 00239 readColFloat3(); 00240 break; 00241 } 00242 } 00243 return color; 00244 } 00245 //----------------------------------------------------------------------------- 00246 float A3DSLoader::readPercentChunk() 00247 { 00248 readChunk(); 00249 float perc=0; 00250 switch(mChunkId) 00251 { 00252 case ID_INT_PERCENTAGE: 00253 perc = readWordPercent(); 00254 break; 00255 case ID_FLOAT_PERCENTAGE: 00256 perc = readFloatPercent(); 00257 break; 00258 } 00259 return perc; 00260 } 00261 //----------------------------------------------------------------------------- 00262 // materials 00263 void A3DSLoader::read_MATERIAL_BLOCK() 00264 { 00265 long long chunk_end = (int)mInputFile->position() + mChunkLen - 6; 00266 if ( chunk_end > mInputFile->size() ) 00267 { 00268 Log::error("3ds file is corrupted.\n"); 00269 mCorrupted = true; 00270 mObjects.clear(); 00271 mMaterials.clear(); 00272 chunk_end = mInputFile->size(); 00273 } 00274 00275 // unsigned int id = mChunkId; 00276 00277 A3DSMaterial mat; 00278 00279 while(mInputFile->position() < chunk_end && !mCorrupted) 00280 { 00281 readChunk(); 00282 00283 switch(mChunkId) 00284 { 00285 // Material name 00286 case ID_MATERIAL_NAME: 00287 { 00288 mat.mMaterialName = readLine(); 00289 } 00290 break; 00291 // Ambient color 00292 case ID_MAT_AMBIENT: 00293 { 00294 mat.mAmbient = readColChunk(); 00295 } 00296 break; 00297 // Diffuse color 00298 case ID_MAT_DIFFUSE: 00299 { 00300 mat.mDiffuse = readColChunk(); 00301 } 00302 break; 00303 // Specular color 00304 case ID_MAT_SPECULAR: 00305 { 00306 mat.mSpecular = readColChunk(); 00307 } 00308 break; 00309 // Shininess percent 00310 case ID_MAT_SHININESS_PERCENT: 00311 { 00312 mat.mShininess = readPercentChunk(); 00313 } 00314 break; 00315 // Shininess strength percent 00316 case ID_MAT_SHININESS_STRENGTH_PERCENT: 00317 { 00318 mat.mShininessStrength = readPercentChunk(); 00319 } 00320 break; 00321 // Transparency percent 00322 case ID_MAT_TRANSPARENCY: 00323 { 00324 mat.mTransparency = readPercentChunk(); 00325 } 00326 break; 00327 // Double sided material 00328 case ID_MAT_TWO_SIDE: 00329 { 00330 mat.mDoubleSided = true; 00331 } 00332 // Texture map 1 00333 case ID_MAT_TEXMAP: 00334 { 00335 mat.mTexture1 = readMapChunk(); 00336 } 00337 break; 00338 // Texture map 2 00339 case ID_MAT_TEXMAP2: 00340 { 00341 mat.mTexture2 = readMapChunk(); 00342 } 00343 break; 00344 00345 default: 00346 skipChunk(); 00347 } 00348 } 00349 mMaterials.push_back(mat); 00350 } 00351 //----------------------------------------------------------------------------- 00352 // A3DSObject Block 00353 A3DSTexture A3DSLoader::readMapChunk() 00354 { 00355 long long chunk_end = (int)mInputFile->position() + mChunkLen - 6; 00356 if ( chunk_end > mInputFile->size() ) 00357 { 00358 Log::error("3ds file is corrupted.\n"); 00359 mCorrupted = true; 00360 mObjects.clear(); 00361 mMaterials.clear(); 00362 chunk_end = mInputFile->size(); 00363 } 00364 00365 // unsigned int id = mChunkId; 00366 00367 A3DSTexture tex; 00368 00369 while(mInputFile->position() < chunk_end && !mCorrupted) 00370 { 00371 readChunk(); 00372 00373 switch(mChunkId) 00374 { 00375 // Map filename 00376 case ID_MAT_MAPNAME: 00377 { 00378 tex.mFileName = readLine(); 00379 // locate the actual file 00380 ref<VirtualFile> file = vl::defFileSystem()->locateFile(tex.mFileName, mInputFile->path().extractPath()); 00381 if (file) 00382 tex.mFileName = file->path(); 00383 00384 } 00385 break; 00386 // Map options 00387 case ID_MAT_MAP_TILING: 00388 { 00389 unsigned short flags = mInputFile->readUInt16(); 00390 int bit[10] = { flags&(1<<0), flags&(1<<1), flags&(1<<2), flags&(1<<3), 00391 flags&(1<<4), flags&(1<<5), flags&(1<<6), flags&(1<<7), 00392 flags&(1<<8), flags&(1<<9) }; 00393 tex.mOpt_tile = (!bit[4] && !bit[0]) || (!bit[4] && bit[1]); 00394 tex.mOpt_decal = (bit[4] && bit[0]) || (!bit[4] && bit[1]); 00395 tex.mOpt_mirror = bit[1]?true:false; // vc issues warnings otherwise 00396 tex.mOpt_negative = bit[3]?true:false; 00397 tex.mOpt_summed_area = bit[5]?true:false; 00398 tex.mOpt_use_alpha = bit[6]?true:false; 00399 tex.mOpt_one_channel_tint = bit[7]?true:false; 00400 tex.mOpt_ignore_alpha = bit[8]?true:false; 00401 tex.mOpt_rgb_tint = bit[9]?true:false; 00402 } 00403 break; 00404 // U scale 00405 case ID_MAT_USCALE: 00406 { 00407 tex.mUScale = mInputFile->readFloat(); 00408 } 00409 break; 00410 // V scale 00411 case ID_MAT_VSCALE: 00412 { 00413 tex.mVScale = mInputFile->readFloat(); 00414 } 00415 break; 00416 // U offset 00417 case ID_MAT_UOFFSET: 00418 { 00419 tex.mUOffset = mInputFile->readFloat(); 00420 } 00421 break; 00422 // V offset 00423 case ID_MAT_VOFFSET: 00424 { 00425 tex.mVOffset = mInputFile->readFloat(); 00426 } 00427 break; 00428 // rotation 00429 case ID_MAT_MAP_ROTATION: 00430 { 00431 tex.mRotation = mInputFile->readFloat(); 00432 } 00433 break; 00434 default: 00435 skipChunk(); 00436 } 00437 } 00438 return tex; 00439 } 00440 //----------------------------------------------------------------------------- 00441 // Object Block 00442 void A3DSLoader::read_OBJECT_BLOCK() 00443 { 00444 long long chunk_end = (int)mInputFile->position() + mChunkLen - 6; 00445 if ( chunk_end > mInputFile->size() ) 00446 { 00447 Log::error("3ds file is corrupted.\n"); 00448 mCorrupted = true; 00449 mObjects.clear(); 00450 mMaterials.clear(); 00451 chunk_end = mInputFile->size(); 00452 } 00453 00454 // unsigned int id = mChunkId; 00455 00456 mObjects.push_back( A3DSObject() ); 00457 mObjects.back().mObjName = readLine(); 00458 00459 while(mInputFile->position() < chunk_end && !mCorrupted) 00460 { 00461 readChunk(); 00462 00463 switch(mChunkId) 00464 { 00465 case ID_TRIANGULAR_MESH: 00466 read_TRIANGULAR_MESH(); 00467 break; 00468 00469 default: 00470 // Reject lights and cameras 00471 mObjects.pop_back(); 00472 skipChunk(); 00473 } 00474 } 00475 } 00476 //----------------------------------------------------------------------------- 00477 // Triangular mesh 00478 void A3DSLoader::read_TRIANGULAR_MESH() 00479 { 00480 long long chunk_end = (int)mInputFile->position() + mChunkLen - 6; 00481 if ( chunk_end > mInputFile->size() ) 00482 { 00483 Log::error("3ds file is corrupted.\n"); 00484 mCorrupted = true; 00485 mObjects.clear(); 00486 mMaterials.clear(); 00487 chunk_end = mInputFile->size(); 00488 } 00489 00490 // unsigned int id = mChunkId; 00491 00492 while(mInputFile->position() < chunk_end && !mCorrupted) 00493 { 00494 readChunk(); 00495 00496 switch(mChunkId) 00497 { 00498 // Vertices list 00499 case ID_VERTEX_LIST: 00500 { 00501 unsigned short vertc = mInputFile->readUInt16(); 00502 if (!vertc) 00503 break; 00504 mObjects.back().mVertices.resize(vertc); 00505 #if 1 00506 std::vector<fvec3> verts; 00507 verts.resize(vertc); 00508 mInputFile->read(&verts[0], 3*vertc*sizeof(float)); 00509 for(unsigned short i=0; i<vertc; ++i) 00510 mObjects.back().mVertices[i].mPos = verts[i]; 00511 #else 00512 for(unsigned short i=0; i<vertc; ++i) 00513 mObjects.back().mVertices[i].mPos = readVec3(); 00514 #endif 00515 } 00516 break; 00517 // Faces description 00518 case ID_FACE_LIST: 00519 { 00520 unsigned short facec= mInputFile->readUInt16(); 00521 if (!facec) 00522 break; 00523 mObjects.back().mFaceList.resize(facec); 00524 #if 1 00525 std::vector<unsigned short> faces; 00526 faces.resize(facec*4); 00527 mInputFile->readUInt16(&faces[0], faces.size()); 00528 for(unsigned short i=0; i<facec; ++i) 00529 { 00530 mObjects.back().mFaceList[i].mA = faces[i*4+0]; 00531 mObjects.back().mFaceList[i].mB = faces[i*4+1]; 00532 mObjects.back().mFaceList[i].mC = faces[i*4+2]; 00533 mObjects.back().mFaceList[i].mFlags = faces[i*4+3]; 00534 } 00535 #else 00536 for(unsigned short i=0; i<facec; ++i) 00537 { 00538 mObjects.back().mFaceList[i].a = mInputFile->readUInt16(); 00539 mObjects.back().mFaceList[i].b = mInputFile->readUInt16(); 00540 mObjects.back().mFaceList[i].c = mInputFile->readUInt16(); 00541 mObjects.back().mFaceList[i].flags = mInputFile->readUInt16(); 00542 } 00543 #endif 00544 } 00545 break; 00546 // Face material list 00547 case ID_FACE_MATERIAL_LIST: 00548 { 00549 String name = readLine(); 00550 unsigned short facec = mInputFile->readUInt16(); 00551 if (!facec) 00552 break; 00553 mObjects.back().mMatFaceMap.push_back(A3DSMaterialFaceMapping()); 00554 mObjects.back().mMatFaceMap.back().mMaterialName = name; 00555 mObjects.back().mMatFaceMap.back().mMappedFace.resize(facec); 00556 #if 1 00557 mInputFile->readUInt16(&mObjects.back().mMatFaceMap.back().mMappedFace[0], facec); 00558 #else 00559 for(unsigned short i=0; i<facec; ++i) 00560 { 00561 unsigned short face = mInputFile->readUInt16(); 00562 mObjects.back().mMatFaceMap.back().mMappedFace[i] = face; 00563 } 00564 #endif 00565 } 00566 break; 00567 // Smoothing group list 00568 case ID_SMOOTHING_GROUP_LIST: 00569 { 00570 #if 1 00571 if (mObjects.back().mFaceList.empty()) 00572 break; 00573 std::vector<unsigned int> group; 00574 group.resize(mObjects.back().mFaceList.size()); 00575 mInputFile->readUInt32(&group[0], group.size()); 00576 for(unsigned short i=0; i<mObjects.back().mFaceList.size(); ++i) 00577 mObjects.back().mFaceList[i].mSmoothingGroup = group[i]; 00578 #else 00579 for(unsigned short i=0; i<mObjects.back().mFaceList.size(); ++i) 00580 mObjects.back().mFaceList[i].mSmoothingGroup = mInputFile->readUInt32(); 00581 #endif 00582 } 00583 break; 00584 // Mapping coordinates 00585 case ID_MAPPING_COORDS: 00586 { 00587 unsigned short vertc = mInputFile->readUInt16(); 00588 if(!vertc) 00589 break; 00590 mObjects.back().mVertices.resize(vertc); 00591 #if 1 00592 std::vector<fvec2> tuvs; 00593 tuvs.resize(vertc); 00594 mInputFile->read(&tuvs[0], 2*vertc*sizeof(float)); 00595 for(unsigned short i=0; i<vertc; ++i) 00596 mObjects.back().mVertices[i].mUV = tuvs[i]; 00597 #else 00598 for(unsigned short i=0; i<vertc; ++i) 00599 { 00600 fvec2 uv; 00601 uv.s() = mInputFile->readFloat(); 00602 uv.t() = mInputFile->readFloat(); // 1 - mInputFile->readFloat(); ? see also mapping flags 00603 mObjects.back().mVertices[i].mUV = uv; 00604 } 00605 #endif 00606 } 00607 break; 00608 // Local coordinates 00609 case ID_LOCAL_COORDS_SYSTEM: 00610 { 00611 fmat4 m; 00612 00613 fvec3 x,y,z,t; 00614 x = readVec3(); 00615 y = readVec3(); 00616 z = readVec3(); 00617 t = readVec3(); 00618 m.setX( x ); 00619 m.setY( y ); 00620 m.setZ( z ); 00621 m.setT( t ); 00622 00623 mObjects.back().mCoordSystem = m; 00624 } 00625 break; 00626 00627 default: 00628 skipChunk(); 00629 } 00630 } 00631 } 00632 //----------------------------------------------------------------------------- 00633 bool A3DSLoader::parse3DS( VirtualFile* file ) 00634 { 00635 mCorrupted = false; 00636 mInputFile = file; 00637 if ( !mInputFile->open(OM_ReadOnly) ) 00638 { 00639 Log::print(Say("Could not open '%s'. \n") << mInputFile->path() ); 00640 return false; 00641 } 00642 00643 // Main 3DS Chunk 00644 readChunk(); 00645 if (mChunkId == ID_MAIN_CHUNK) 00646 readChunk(); 00647 else 00648 { 00649 Log::error( Say("'%s' is not a valid 3DS file.\n") << mInputFile->path() ); 00650 // will try to use the chunk we just read 00651 } 00652 00653 do 00654 { 00655 // Inside main 00656 switch(mChunkId) 00657 { 00658 case ID_3DS_VERSION: // 3DS Version 00659 { 00660 /*unsigned int version =*/ mInputFile->readUInt32(); 00661 } 00662 break; 00663 00664 // 3D Editor 00665 case ID_3D_EDITOR_CHUNK: 00666 { 00667 read_3D_EDITOR_CHUNK(); 00668 } 00669 break; 00670 00671 default: 00672 skipChunk(); 00673 } 00674 readChunk(); 00675 } 00676 while( !mInputFile->endOfFile() && !mCorrupted ); 00677 00678 mInputFile->close(); 00679 return !mCorrupted; 00680 } 00681 //----------------------------------------------------------------------------- 00682 ref<ResourceDatabase> vl::load3DS(const String& path) 00683 { 00684 ref<VirtualFile> file = defFileSystem()->locateFile(path); 00685 00686 if (file) 00687 return load3DS( file.get() ); 00688 else 00689 { 00690 Log::error( Say("Could not locate '%s'.\n") << path ); 00691 return NULL; 00692 } 00693 } 00694 ref<ResourceDatabase> vl::load3DS(VirtualFile* file) 00695 { 00696 if (!file) 00697 return NULL; 00698 00699 ref<ResourceDatabase> res_db = new ResourceDatabase; 00700 00701 A3DSLoader loader; 00702 /*bool force_double_face = false;*/ 00703 if (!loader.parse3DS(file)) 00704 return NULL; 00705 00706 ref<Effect> default_effect = new Effect; 00707 res_db->resources().push_back(default_effect.get()); 00708 00709 default_effect->setObjectName("3ds default effect"); 00710 default_effect->shader()->enable(EN_DEPTH_TEST); 00711 /*default_effect->shader()->gocLightModel()->setTwoSide(true);*/ 00712 /* default_effect->shader()->disable(EN_CULL_FACE); */ 00713 00714 std::map< String, ref<Effect> > mat_map; 00715 00716 for(unsigned int iobj=0; iobj<loader.mObjects.size(); ++iobj) 00717 { 00718 if (loader.mObjects[iobj].mVertices.empty()) 00719 continue; 00720 00721 if (loader.mObjects[iobj].mFaceList.empty()) 00722 continue; 00723 00724 // create a Geometry for each material group 00725 for(unsigned imat_map=0; imat_map<loader.mObjects[iobj].mMatFaceMap.size() || (imat_map==0&&loader.mObjects[iobj].mMatFaceMap.empty()); ++imat_map) 00726 { 00727 int mat_index = -1; 00728 00729 if (!loader.mObjects[iobj].mMatFaceMap.empty()) 00730 { 00731 for(unsigned imat=0; imat<loader.mMaterials.size(); ++imat) 00732 { 00733 if (loader.mObjects[iobj].mMatFaceMap[imat_map].mMaterialName == loader.mMaterials[imat].mMaterialName) 00734 { 00735 mat_index = imat; 00736 break; 00737 } 00738 } 00739 } 00740 00741 if (mat_index != -1) 00742 { 00743 // assign material to mObjects 00744 for(unsigned int iface=0; iface<loader.mObjects[iobj].mMatFaceMap[imat_map].mMappedFace.size(); iface++) 00745 { 00746 int face_index = loader.mObjects[iobj].mMatFaceMap[imat_map].mMappedFace[iface]; 00747 loader.mObjects[iobj].mFaceList[face_index].mMaterialIndex = mat_index; 00748 } 00749 } 00750 00751 ref<Geometry> geom = new Geometry; 00752 ref<Actor> act = new Actor(geom.get()); 00753 geom->setObjectName( loader.mObjects[iobj].mObjName.toStdString().c_str() ); 00754 act ->setObjectName( loader.mObjects[iobj].mObjName.toStdString().c_str() ); 00755 00756 // builds the vertex sets: a vertex belongs to a single group 00757 00758 std::set<A3DSVertex> vertex_set; 00759 std::vector<unsigned int> index_buffer; 00760 index_buffer.resize( 3 * loader.mObjects[iobj].mFaceList.size() ); 00761 int index_counter = 0; 00762 for(unsigned int iface=0; iface<loader.mObjects[iobj].mFaceList.size(); iface++) 00763 { 00764 if ( loader.mObjects[iobj].mFaceList[iface].mMaterialIndex != mat_index ) 00765 continue; 00766 00767 unsigned int vertidx[] = 00768 { 00769 loader.mObjects[iobj].mFaceList[iface].mA, 00770 loader.mObjects[iobj].mFaceList[iface].mB, 00771 loader.mObjects[iobj].mFaceList[iface].mC 00772 }; 00773 00774 for(int iv=0; iv<3; ++iv) 00775 { 00776 A3DSVertex v; 00777 if (vertidx[iv]>=loader.mObjects[iobj].mVertices.size()) 00778 { 00779 Log::error("index out of range, 3ds file is corrupted.\n"); 00780 return NULL; 00781 } 00782 v = loader.mObjects[iobj].mVertices[ vertidx[iv] ]; 00783 v.mSmoothingGroup = loader.mObjects[iobj].mFaceList[iface].mSmoothingGroup; 00784 std::set<A3DSVertex>::iterator it = vertex_set.find(v); 00785 if (it == vertex_set.end()) 00786 { 00787 v.mIndex = index_counter; 00788 vertex_set.insert(v); 00789 index_counter ++; 00790 } 00791 else 00792 v = *it; 00793 index_buffer[iface*3+iv] = v.mIndex; 00794 } 00795 } 00796 00797 if (index_counter == 0) 00798 continue; 00799 00800 // add after we are sure the geometry has content 00801 00802 res_db->resources().push_back(geom.get()); 00803 res_db->resources().push_back( act.get() ); 00804 00805 // dump vertices and uv 00806 00807 ref<ArrayFloat3> vert_interf = new ArrayFloat3; 00808 ref<ArrayFloat2> tuvs_interf = new ArrayFloat2; 00809 geom->setVertexArray(vert_interf.get()); 00810 geom->setTexCoordArray(0, tuvs_interf.get()); 00811 vert_interf->resize( index_counter ); 00812 tuvs_interf->resize( index_counter ); 00813 for(std::set<A3DSVertex>::iterator ivert=vertex_set.begin(); ivert!=vertex_set.end(); ++ivert) 00814 { 00815 vert_interf->at(ivert->mIndex).x() = ivert->mPos.x(); 00816 vert_interf->at(ivert->mIndex).y() = ivert->mPos.z(); 00817 vert_interf->at(ivert->mIndex).z() =-ivert->mPos.y(); 00818 tuvs_interf->at(ivert->mIndex) = ivert->mUV; 00819 } 00820 00821 // dump indices 00822 00823 ref<DrawElementsUInt> polys = new DrawElementsUInt; 00824 geom->drawCalls()->push_back( polys.get() ); 00825 polys->indexBuffer()->resize( index_buffer.size() ); 00826 VL_CHECK( polys->indexBuffer()->bytesUsed() == sizeof(index_buffer[0]) * index_buffer.size() ) 00827 memcpy(polys->indexBuffer()->ptr(), &index_buffer[0], polys->indexBuffer()->bytesUsed()); 00828 00829 // matrix 00830 00831 // we still have problems when the pivots are not centered on the object 00832 00833 // dump materials 00834 00835 if ( mat_index != -1 ) 00836 { 00837 const String& mat_name = loader.mMaterials[mat_index].mMaterialName; 00838 if (mat_map[mat_name].get() == NULL) 00839 { 00840 mat_map[mat_name] = new Effect; 00841 res_db->resources().push_back(mat_map[mat_name].get()); 00842 00843 mat_map[mat_name]->setObjectName(mat_name.toStdString().c_str()); 00844 00845 float alpha = 1.0f - loader.mMaterials[mat_index].mTransparency; 00846 fvec4 ambient( loader.mMaterials[mat_index].mAmbient.r(), loader.mMaterials[mat_index].mAmbient.g(), loader.mMaterials[mat_index].mAmbient.b(), alpha ); 00847 fvec4 diffuse( loader.mMaterials[mat_index].mDiffuse.r(), loader.mMaterials[mat_index].mDiffuse.g(), loader.mMaterials[mat_index].mDiffuse.b(), alpha ); 00848 fvec4 specular( loader.mMaterials[mat_index].mSpecular.r(), loader.mMaterials[mat_index].mSpecular.g(), loader.mMaterials[mat_index].mSpecular.b(), alpha ); 00849 specular *= loader.mMaterials[mat_index].mShininessStrength; 00850 mat_map[mat_name]->shader()->gocMaterial()->setAmbient( ambient ); 00851 mat_map[mat_name]->shader()->gocMaterial()->setDiffuse( diffuse ); 00852 mat_map[mat_name]->shader()->gocMaterial()->setSpecular( specular ); 00853 mat_map[mat_name]->shader()->gocMaterial()->setShininess( loader.mMaterials[mat_index].mShininess * 128.0f ); 00854 00855 mat_map[mat_name]->shader()->enable(EN_DEPTH_TEST); 00856 /* mat_map[mat_name]->shader()->disable(EN_CULL_FACE); */ 00857 00858 if (alpha<1.0f || loader.mMaterials[mat_index].mTexture1.mOpt_use_alpha) 00859 { 00860 mat_map[mat_name]->shader()->enable(EN_BLEND); 00861 mat_map[mat_name]->shader()->gocBlendFunc()->set(BF_SRC_ALPHA, BF_ONE_MINUS_SRC_ALPHA); 00862 } 00863 /*if ( loader.mMaterials[mat_index].mDoubleSided || force_double_face ) 00864 { 00865 mat_map[mat_name]->shader()->gocLightModel()->setTwoSide(true); 00866 }*/ 00867 if ( !loader.mMaterials[mat_index].mTexture1.mFileName.empty() ) 00868 { 00869 ref<Texture> texture = new Texture; 00870 texture->prepareTexture2D(loader.mMaterials[mat_index].mTexture1.mFileName, TF_RGBA); 00871 if (loader.mMaterials[mat_index].mTexture1.mOpt_tile) 00872 { 00873 texture->getTexParameter()->setWrapS(TPW_REPEAT); 00874 texture->getTexParameter()->setWrapT(TPW_REPEAT); 00875 texture->getTexParameter()->setWrapR(TPW_REPEAT); 00876 } 00877 else 00878 { 00879 texture->getTexParameter()->setWrapS(TPW_CLAMP); 00880 texture->getTexParameter()->setWrapT(TPW_CLAMP); 00881 texture->getTexParameter()->setWrapR(TPW_CLAMP); 00882 } 00883 mat_map[mat_name]->shader()->gocTextureSampler(0)->setTexture( texture.get() ); 00884 } 00885 } 00886 00887 act->setEffect( mat_map[mat_name].get() ); 00888 } 00889 else 00890 act->setEffect( default_effect.get() ); 00891 00892 /* now managed by GeometryLoadCallback */ 00893 /*// this will already take into consideration the smoothing groups 00894 geom->computeNormals();*/ 00895 } 00896 } 00897 00898 return res_db; 00899 } 00900 //-----------------------------------------------------------------------------