# Visualization Library

A lightweight C++ OpenGL middleware for 2D/3D graphics

[Home] [Tutorials] [All Classes] [Grouped Classes]

- Main Page
- Related Pages
- Namespaces
- Classes
- Files

- File List
- File Members

# D:/VL/BuildSystem/VL_DISTRO/Visualization_Library_SDK/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 v2011.09.1162 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu Jan 26 2012 00:43:41.
Permission is granted to use this page to write and publish articles regarding Visualization Library.