Visualization Library

A lightweight C++ OpenGL middleware for 2D/3D graphics
[Home] [Tutorials] [All Classes] [Grouped Classes]

X:/dropbox/visualizationlibrary/src/vlGraphics/plugins/io3DS.cpp

Go to the documentation of this file.
00001 /**************************************************************************************/
00002 /*                                                                                    */
00003 /*  Visualization Library                                                             */
00004 /*  http://www.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 //-----------------------------------------------------------------------------

Visualization Library 2011.09.1160 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu May 2 2013 13:40:39.
Permission is granted to use this page to write and publish articles regarding Visualization Library.