Visualization Library

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

X:/dropbox/visualizationlibrary/src/vlGraphics/plugins/ioAC3D.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 "ioAC3D.hpp"
00033 #include <vlCore/checks.hpp>
00034 #include <vlGraphics/Effect.hpp>
00035 #include <vlGraphics/Geometry.hpp>
00036 #include <vlCore/Image.hpp>
00037 #include <vlGraphics/Texture.hpp>
00038 #include <vlCore/Log.hpp>
00039 #include <vlCore/Say.hpp>
00040 #include <vlCore/VisualizationLibrary.hpp>
00041 #include <vlCore/FileSystem.hpp>
00042 #include <vlCore/TextStream.hpp>
00043 #include <vlCore/VirtualFile.hpp>
00044 #include <vlGraphics/DoubleVertexRemover.hpp>
00045 #include <map>
00046 #include <vlCore/LoadWriterManager.hpp>
00047 
00048 using namespace vl;
00049 
00050 namespace
00051 {
00052   class LoaderAC3D 
00053   {
00054   public:
00055 
00056     class vert_info 
00057     {
00058     public:
00059       int Vert;
00060       float U;
00061       float V;
00062     };
00063     
00064     class material_info 
00065     {
00066     public:
00067       String Name;
00068       fvec3 Diffuse;
00069       fvec3 Ambient;
00070       fvec3 Emission;
00071       fvec3 Specular;
00072       float Shininess;
00073       float Trans;
00074     };
00075 
00076     class surface_info 
00077     {
00078     public:
00079       int Flags;
00080       int materials;
00081       int VertCount;
00082       std::vector<vert_info> Vertex;
00083     };
00084 
00085     class mesh_info 
00086     {
00087     public:
00088       mesh_info();
00089     
00090       String Name;
00091       String Data;
00092       String Texture;
00093       float TexRep[2];
00094       dmat4 Matrix;
00095       String Url;
00096       int NumVert;
00097       std::vector<fvec3> Vert;
00098       int NumSurf;
00099       std::vector<surface_info> Surface;    
00100       int NumKids;
00101     };
00102     
00103     LoaderAC3D();  
00104     bool parseAC3D(VirtualFile* file);  
00105 
00106     fvec3 readColor();  
00107     fvec3 readVector();
00108     float readFloat();
00109     int readInt();
00110     int readHex();
00111     String readLine();
00112     String readWord();
00113     String readName();
00114     void readMaterial();
00115     void readObject();
00116     
00117     std::vector<material_info> materials;
00118     std::vector<mesh_info> meshes;
00119     bool verbose;
00120     
00121   protected:
00122     ref<TextStream> mTokenizer;
00123     String mTmpStr;
00124     bool mEOF;
00125   };
00126 }
00127 //-----------------------------------------------------------------------------
00128 // mesh_info
00129 //-----------------------------------------------------------------------------
00130 LoaderAC3D::mesh_info::mesh_info()
00131 {
00132   TexRep[0] = 1;
00133   TexRep[1] = 1;
00134   NumVert = 0;
00135   NumSurf = 0;
00136   NumKids = 0;
00137 }
00138 //-----------------------------------------------------------------------------
00139 // LoaderAC3D
00140 //-----------------------------------------------------------------------------
00141 LoaderAC3D::LoaderAC3D()
00142 {
00143   verbose = true;
00144 }
00145 //-----------------------------------------------------------------------------
00146 bool LoaderAC3D::parseAC3D(VirtualFile* file)
00147 {
00148   mEOF = false;
00149 
00150   mTokenizer = new TextStream;
00151   mTokenizer->setInputFile( file );
00152   String token;
00153 
00154   mTokenizer->readString(token);
00155 
00156   if (token != "AC3Db")
00157   {
00158     Log::error("Not an AC3Db file!\n");
00159     file->close();
00160     return false;
00161   }
00162 
00163   while( mTokenizer->readString(token) )
00164   {
00165     if (token == "MATERIAL")
00166       readMaterial();
00167     else
00168     if (token == "OBJECT")
00169       readObject();
00170     else
00171     {
00172       Log::error("AC3D parse error.\n");
00173       file->close();
00174       return false;
00175     }
00176   }
00177 
00178   file->close();
00179   return true;
00180 }
00181 //-----------------------------------------------------------------------------
00182 fvec3 LoaderAC3D::readColor()
00183 {
00184   bool ok = true;
00185   ok &= mTokenizer->readString(mTmpStr); float r = mTmpStr.toFloat();
00186   ok &= mTokenizer->readString(mTmpStr); float g = mTmpStr.toFloat();
00187   ok &= mTokenizer->readString(mTmpStr); float b = mTmpStr.toFloat();
00188   mEOF = !ok;
00189   if ( !ok )
00190     Log::error("LoaderAC3D::readColor() IO error.\n");
00191   return fvec3(r,g,b);
00192 }
00193 //-----------------------------------------------------------------------------
00194 fvec3 LoaderAC3D::readVector()
00195 {
00196   bool ok = true;
00197   ok &= mTokenizer->readString(mTmpStr); float x = mTmpStr.toFloat();
00198   ok &= mTokenizer->readString(mTmpStr); float y = mTmpStr.toFloat();
00199   ok &= mTokenizer->readString(mTmpStr); float z = mTmpStr.toFloat();
00200   mEOF = !ok;
00201   if ( !ok )
00202     Log::error("LoaderAC3D::readVector() IO error.\n");
00203   return fvec3(x,y,z);
00204 }
00205 //-----------------------------------------------------------------------------
00206 float LoaderAC3D::readFloat()
00207 {
00208   bool ok = true;
00209   ok &= mTokenizer->readString(mTmpStr); float f = mTmpStr.toFloat();
00210   mEOF = !ok;
00211   if ( !ok )
00212     Log::error("LoaderAC3D::readFloat() IO error.\n");
00213   return f;
00214 }
00215 //-----------------------------------------------------------------------------
00216 int LoaderAC3D::readInt()
00217 {
00218   bool ok = true;
00219   ok &= mTokenizer->readString(mTmpStr); int i = mTmpStr.toInt();
00220   mEOF = !ok;
00221   if ( !ok )
00222     Log::error("LoaderAC3D::readInt() IO error.\n");
00223   return i;
00224 }
00225 //-----------------------------------------------------------------------------
00226 int LoaderAC3D::readHex()
00227 {
00228   bool ok = true;
00229   ok &= mTokenizer->readString(mTmpStr);
00230   mEOF = !ok;
00231   if ( !ok )
00232   {
00233     Log::error("I/O error reading hex.\n");
00234     return 0;
00235   }
00236   else
00237   {
00238     mTmpStr[0] = ' ';
00239     mTmpStr[1] = ' ';
00240     return mTmpStr.toInt(true);
00241   }
00242 }
00243 //-----------------------------------------------------------------------------
00244 String LoaderAC3D::readWord()
00245 {
00246   bool ok = true;
00247   ok &= mTokenizer->readString( mTmpStr );
00248   mEOF = !ok;
00249   if ( !ok )
00250   {
00251     Log::error("I/O error reading word.\n");
00252     return "";
00253   }
00254   else
00255   {
00256     if ( mTmpStr.count('"') == 1 )
00257     {
00258       Log::error( Say("The string '%s' contains a single '\"'.\n") << mTmpStr );
00259     }
00260 
00261     mTmpStr.remove('"');
00262     return mTmpStr;
00263   }
00264 }
00265 //-----------------------------------------------------------------------------
00266 String LoaderAC3D::readName()
00267 {
00268   bool ok = true;
00269   ok &= mTokenizer->readQuotedString( mTmpStr );
00270   mEOF = !ok;
00271   if ( !ok )
00272   {
00273     Log::error("I/O error reading word.\n");
00274     return "";
00275   }
00276   else
00277   {
00278     if ( mTmpStr.count('"') == 1 )
00279     {
00280       Log::error( Say("The string '%s' contains a single '\"'.\n") << mTmpStr );
00281     }
00282 
00283     mTmpStr.remove('"');
00284     return mTmpStr;
00285   }
00286 }
00287 //-----------------------------------------------------------------------------
00288 String LoaderAC3D::readLine()
00289 {
00290   bool ok = true;
00291   ok &= mTokenizer->readLine( mTmpStr );
00292   if ( !ok )
00293   {
00294     Log::error("I/O error reading line.\n");
00295     return "";
00296   }
00297   else
00298   {
00299     return mTmpStr;
00300   }
00301 }
00302 //-----------------------------------------------------------------------------
00303 void LoaderAC3D::readMaterial()
00304 {
00305   // MATERIAL %s rgb %f %f %f  amb %f %f %f  emis %f %f %f  spec %f %f %f  shi %d  trans %f
00306   material_info material;
00307 
00308   material.Name = readName();
00309   readWord(); // rgb
00310   material.Diffuse = readColor();
00311   readWord(); // amb
00312   material.Ambient = readColor();
00313   readWord(); // emis
00314   material.Emission = readColor();
00315   readWord(); // spec
00316   material.Specular = readColor();
00317   readWord(); // shi
00318   material.Shininess = readFloat();
00319   readWord(); // trans
00320   material.Trans = 1 - readFloat();
00321 
00322   materials.push_back(material);
00323 }
00324 //-----------------------------------------------------------------------------
00325 void LoaderAC3D::readObject()
00326 {
00327   mesh_info mesh;
00328   String block;
00329 
00330   block = readWord();
00331 
00332   do
00333   {
00334     block = readWord();
00335 
00336     if (mEOF)
00337       break;
00338 
00339     if (block == "name")
00340     {
00341       mesh.Name = readName();
00342     } else
00343     if (block == "data")
00344     {
00345       // needed to safely skip to the next line
00346       int data_size=0;
00347       mTokenizer->readLine(mTmpStr);
00348       data_size = mTmpStr.toInt();
00349 
00350       // skip data_size bytes
00351       unsigned char ch = 0;
00352       for (int i=0; i<data_size; i++ )
00353         mTokenizer->readToken(&ch);
00354     }
00355     else
00356     if (block == "texture")
00357     {
00358       mesh.Texture = readName();
00359     } else
00360     if (block == "texrep")
00361     {
00362       mesh.TexRep[0] = readFloat();
00363       mesh.TexRep[1] = readFloat();
00364     } else
00365     if (block == "rot")
00366     {
00367       mesh.Matrix.setX( (dvec3)readVector() );
00368       mesh.Matrix.setY( (dvec3)readVector() );
00369       mesh.Matrix.setZ( (dvec3)readVector() );
00370     } else
00371     if (block == "loc")
00372     {
00373       mesh.Matrix.setT( (dvec3)readVector() );
00374     } else
00375     if (block == "url")
00376     {
00377       mesh.Url = readName();
00378     } else
00379     if (block == "numvert")
00380     {
00381       mesh.NumVert = readInt();
00382       for(int i=0; i<mesh.NumVert; ++i)
00383       {
00384         mesh.Vert.push_back( readVector() );
00385       }
00386     } else
00387     if (block == "numsurf")
00388     {
00389       mesh.NumSurf = readInt();
00390       for(int i=0; i<mesh.NumSurf; ++i)
00391       {
00392         surface_info surf;
00393         String tmp;
00394         do
00395         {
00396           tmp = readWord();
00397 
00398           if (tmp == "SURF")
00399           {
00400             surf.Flags = readHex();
00401           }
00402           if (tmp == "mat")
00403           {
00404             surf.materials = readInt();
00405           }
00406           if (tmp == "refs")
00407           {
00408             surf.VertCount = readInt();
00409             for(int j=0; j<surf.VertCount; ++j)
00410             {
00411               vert_info vert;
00412               vert.Vert = readInt();
00413               vert.U = readFloat();
00414               vert.V = readFloat();
00415               surf.Vertex.push_back( vert );
00416             }
00417           }
00418         }
00419         while (tmp != "refs");
00420         mesh.Surface.push_back(surf);
00421       }
00422     }
00423     else
00424     if (block == "kids")
00425     {
00426       mesh.NumKids = readInt();
00427       meshes.push_back(mesh);
00428     }
00429     else
00430     {
00431       if (verbose)
00432         Log::warning( Say("unknown block '%s'\n") << block );
00433       // skip line
00434       mTokenizer->readLine(mTmpStr);
00435     }
00436   }
00437   while(block != "kids");
00438 }
00439 //-----------------------------------------------------------------------------
00440 ref<ResourceDatabase> vl::loadAC3D(const String& path)
00441 {
00442   ref<VirtualFile> file = defFileSystem()->locateFile(path);
00443   if ( !file )
00444   {
00445     Log::error( Say("Could not locate '%s'.\n") << path );
00446     return NULL;
00447   }
00448   else
00449   {
00450     return loadAC3D(file.get() );
00451   }  
00452 }
00453 //-----------------------------------------------------------------------------
00454 ref<ResourceDatabase> vl::loadAC3D( VirtualFile* file)
00455 {
00456   ref<ResourceDatabase> res_db = new ResourceDatabase;
00457 
00458   LoaderAC3D loader;
00459   if ( !loader.parseAC3D(file) )
00460     return NULL;
00461 
00462   // compile the material map
00463   std::vector< ref<Effect> > mat_map;
00464   for(unsigned imat=0; imat<loader.materials.size(); imat++)
00465   {
00466     ref<Effect> effect = new Effect;
00467     mat_map.push_back(effect.get());
00468 
00469     // apply material
00470     effect->shader()->enable(EN_DEPTH_TEST);
00471 
00472     effect->shader()->gocMaterial()->setAmbient( fvec4(loader.materials[ imat ].Ambient, 1.0f) );
00473     effect->shader()->gocMaterial()->setDiffuse( fvec4(loader.materials[ imat ].Diffuse, 1.0f) );
00474     effect->shader()->gocMaterial()->setEmission( fvec4(loader.materials[ imat ].Emission, 1.0f) );
00475     effect->shader()->gocMaterial()->setSpecular( fvec4(loader.materials[ imat ].Specular, 1.0f) );
00476     effect->shader()->gocMaterial()->setShininess( loader.materials[ imat ].Shininess );
00477     effect->shader()->gocMaterial()->setTransparency( loader.materials[ imat ].Trans );
00478 
00479     if ( loader.materials[ imat ].Trans < 1.0f )
00480     {
00481       effect->shader()->enable(EN_CULL_FACE);
00482       effect->shader()->enable(EN_BLEND);
00483       effect->shader()->gocBlendFunc()->set(BF_SRC_ALPHA, BF_ONE_MINUS_SRC_ALPHA);
00484     }
00485   }
00486 
00487   // dumps the objects
00488   for(unsigned imesh=0; imesh<loader.meshes.size(); imesh++)
00489   {
00490     if ( loader.meshes[imesh].Surface.empty() )
00491       continue;
00492 
00493     ref<Actor> act = new Actor;
00494     act->setObjectName( loader.meshes[imesh].Name.toStdString().c_str() );
00495 
00496     ref<Geometry> geom = new Geometry;
00497     geom->setObjectName( loader.meshes[imesh].Name.toStdString().c_str() );
00498 
00499     ref<ArrayFloat3> verts = new ArrayFloat3;
00500     ref<ArrayFloat2> uv    = new ArrayFloat2;
00501     ref<DrawElementsUInt> polys = new DrawElementsUInt;
00502     geom->drawCalls()->push_back( polys.get() );
00503     geom->setVertexArray( verts.get() );
00504     geom->setTexCoordArray(0, uv.get());
00505     act->setLod(0, geom.get());
00506 
00507     // we handle only one material per surface
00508     int mat_index = loader.meshes[imesh].Surface[0].materials;
00509 
00510     act->setEffect( mat_map[ mat_index ].get() );
00511 
00512     // polygons + vertices
00513     int vert_count = 0;
00514     for(unsigned isurf=0; isurf<loader.meshes[imesh].Surface.size(); isurf++)
00515     {
00516       if ( (loader.meshes[imesh].Surface[isurf].Flags & 0xF) != 0 )
00517         continue;
00518       for( int ivert=1; ivert<loader.meshes[imesh].Surface[isurf].VertCount-1; ivert++)
00519         for(int i=0; i<3; ++i)
00520           ++vert_count;
00521     }
00522 
00523     verts->resize( vert_count );
00524     uv->resize( vert_count );
00525 
00526     if (!vert_count)
00527       continue;
00528 
00529     // add when we are sure we have some content
00530 
00531     res_db->resources().push_back( act.get() );
00532     res_db->resources().push_back( geom.get() );
00533 
00534     // warning: this is a quite experimental importer.
00535 
00536     // !!! FIX !!! i vertici dovrebbero essere < degli indici in generale, vedi sotto
00537     polys->indexBuffer()->resize( vert_count );
00538 
00539     int idx = 0;
00540     for(unsigned isurf=0; isurf<loader.meshes[imesh].Surface.size(); isurf++)
00541     {
00542       if ( (loader.meshes[imesh].Surface[isurf].Flags & 0xF) != 0 ) // not a poly
00543         continue;
00544       VL_CHECK( loader.meshes[imesh].Surface[isurf].VertCount >= 3 )
00545       for( int ivert=1; ivert<loader.meshes[imesh].Surface[isurf].VertCount-1; ivert++)
00546       {
00547         int vert_idx[] = { 0, ivert, ivert+1 };
00548         for(int i=0; i<3; ++i, idx++)
00549         {
00550           // FIXME: a quanto pare i vertici non sono condivisi, ma lo dovrebbero essere
00551           polys->indexBuffer()->at( idx ) = idx;
00552           int iv = loader.meshes[imesh].Surface[isurf].Vertex[ vert_idx[i] ].Vert;
00553           verts->at( idx ) = loader.meshes[imesh].Vert[ iv ];
00554           uv->at( idx )    = fvec2(loader.meshes[imesh].Surface[isurf].Vertex[ vert_idx[i] ].U, loader.meshes[imesh].Surface[isurf].Vertex[ vert_idx[i] ].V);
00555         }
00556       }
00557     }
00558 
00559     // FIXME
00560     /*DoubleVertexRemover dvr;
00561     dvr.removeDoubles(geom.get());*/
00562     geom->transform( (mat4)loader.meshes[imesh].Matrix );
00563     // geom->computeNormals();
00564 
00565     // !!! FIX !!! texture e double-side sono specificati per mesh e non per materiale, VL dovrebbe creare
00566     // combinazioni uniche di materiali/texture/double-side
00567 
00568     // !!! FIX !!! texture - ci dovrebbe essere un unico materiale per ogni combinazione di double-side/texture
00569     if ( loader.meshes[imesh].Texture.length() )
00570     {
00571       ref<Texture> texture = new Texture;
00572       // locate texture
00573       String tex_path = loader.meshes[imesh].Texture;
00574       ref<VirtualFile> tex_file = defFileSystem()->locateFile(tex_path,file->path().extractPath());
00575       if (tex_file)
00576         tex_path = tex_file->path();
00577       texture->prepareTexture2D(tex_path, TF_RGBA);
00578       act->effect()->shader()->gocTextureSampler(0)->setTexture( texture.get() );
00579     }
00580 
00581     // !!! FIX !!! double-side - ci dovrebbe essere un unico materiale per ogni combinazione di double-side/texture
00582     if ( (loader.meshes[imesh].Surface[0].Flags & 0x20) )
00583     {
00584       act->effect()->shader()->gocLightModel()->setTwoSide(true);
00585       /* effect->shader()->disable(EN_CULL_FACE); */
00586     }
00587 
00588   }
00589 
00590   return res_db;
00591 }
00592 //-----------------------------------------------------------------------------

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.