# Visualization Library

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

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

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

# D:/VL/BuildSystem/VL_DISTRO/Visualization_Library_SDK/src/vlGraphics/plugins/vlAC3D.cpp

Go to the documentation of this file.

    00001 /**************************************************************************************/
    00002 /*                                                                                    */
    00003 /*  Visualization Library                                                             */
    00004 /*  http://www.visualizationlibrary.com                                               */
    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 "vlAC3D.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() );
    00495
    00496     ref<Geometry> geom = new Geometry;
    00497     geom->setObjectName( loader.meshes[imesh].Name.toStdString() );
    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->indices()->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->indices()->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()->gocTextureUnit(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 v2011.05.1142 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu May 26 2011 22:51:24.
Permission is granted to use this page to write and publish articles regarding Visualization Library.