Visualization Library

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

X:/dropbox/visualizationlibrary/src/vlGraphics/plugins/ioOBJ.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 "ioOBJ.hpp"
00033 #include <vlCore/TextStream.hpp>
00034 #include <vlCore/VirtualFile.hpp>
00035 #include <vlCore/VirtualDirectory.hpp>
00036 #include <vlCore/VisualizationLibrary.hpp>
00037 #include <vlCore/FileSystem.hpp>
00038 #include <vlGraphics/DoubleVertexRemover.hpp>
00039 #include <vlCore/LoadWriterManager.hpp>
00040 #include <vlGraphics/Effect.hpp>
00041 #include <vlGraphics/Actor.hpp>
00042 #include <string>
00043 #include <vector>
00044 #include <stdio.h>
00045 
00046 using namespace vl;
00047 
00048 namespace 
00049 {
00050   /*
00051    * Utility function
00052    */
00053   template <class T>
00054   void append(std::vector<T>& vec, const T& data, const int& alloc_step = 1024*10)
00055   {
00056     if (vec.size() == vec.capacity())
00057       vec.reserve( vec.size() + alloc_step );
00058     vec.push_back(data);
00059   }
00060 }
00061 //-----------------------------------------------------------------------------
00062 // ObjTexture
00063 //-----------------------------------------------------------------------------
00064 ObjTexture::ObjTexture()
00065 {
00066   mBlendU   = false;
00067   mBlendV   = false;
00068   mCC       = false;
00069   mClamp    = false;
00070   mMM_Base  = 0.0f;
00071   mMM_Gain  = 0.0f;
00072   mO_UVW[0] = 0.0f; mO_UVW[1] = 0.0f; mO_UVW[2] = 0.0f;
00073   mS_UVW[0] = 0.0f; mS_UVW[1] = 0.0f; mS_UVW[2] = 0.0f;
00074   mT_UVW[0] = 0.0f; mT_UVW[1] = 0.0f; mT_UVW[2] = 0.0f;
00075   mTexres_Value = 0.0f;
00076   mImfchan  = 0;
00077   mBM       = 0.0f;
00078 }
00079 //-----------------------------------------------------------------------------
00080 const ObjTexture& ObjTexture::parseLine(const String& line, const String& file)
00081 {
00082   std::vector<String> tokens;
00083   line.split(" \t",tokens,true);
00084 
00085   if (!tokens.empty())
00086   {
00087     tokens.erase(tokens.begin());
00088     mFileName = tokens.back();
00089   }
00090   for(int i=0; i<(int)tokens.size(); ++i)
00091   {
00092     if (tokens[i] == "-blendu")
00093     {
00094       mBlendU = tokens[i+1] == "on";
00095       ++i;
00096     }
00097     else
00098     if (tokens[i] == "-blendv")
00099     {
00100       mBlendV = tokens[i+1] == "on";
00101       ++i;
00102     }
00103     else
00104     if (tokens[i] == "-cc")
00105     {
00106       mCC = tokens[i+1] == "on";
00107       ++i;
00108     }
00109     else
00110     if (tokens[i] == "-clamp")
00111     {
00112       mClamp = tokens[i+1] == "on";
00113       ++i;
00114     }
00115     else
00116     if (tokens[i] == "-mm")
00117     {
00118       mMM_Base = (float)tokens[i+1].toDouble();
00119       mMM_Gain = (float)tokens[i+2].toDouble();
00120       i+=2;
00121     }
00122     else
00123     if (tokens[i] == "-o")
00124     {
00125       mO_UVW[0] = (float)tokens[i+1].toDouble();
00126       mO_UVW[1] = (float)tokens[i+2].toDouble();
00127       mO_UVW[2] = (float)tokens[i+3].toDouble();
00128       i+=3;
00129     }
00130     else
00131     if (tokens[i] == "-s")
00132     {
00133       mS_UVW[0] = (float)tokens[i+1].toDouble();
00134       mS_UVW[1] = (float)tokens[i+2].toDouble();
00135       mS_UVW[2] = (float)tokens[i+3].toDouble();
00136       i+=3;
00137     }
00138     else
00139     if (tokens[i] == "-t")
00140     {
00141       mT_UVW[0] = (float)tokens[i+1].toDouble();
00142       mT_UVW[1] = (float)tokens[i+2].toDouble();
00143       mT_UVW[2] = (float)tokens[i+3].toDouble();
00144       i+=3;
00145     }
00146     else
00147     if (tokens[i] == "-texres")
00148     {
00149       mTexres_Value = (float)tokens[i+1].toDouble();
00150       ++i;
00151     }
00152     else
00153     if (tokens[i] == "-imfchan")
00154     {
00155       mImfchan = (unsigned char)tokens[i+1][0];
00156       ++i;
00157     }
00158     else
00159     if (tokens[i] == "-bm")
00160     {
00161       mBM = (float)tokens[i+1].toDouble();
00162       ++i;
00163     }
00164     else
00165     {
00166       if ( i != (int)tokens.size()-1 )
00167         Log::error( Say("Unknown map option '%s' in file '%s'.\n") << tokens[i] << file );
00168     }
00169   }
00170   return *this;
00171 }
00172 //-----------------------------------------------------------------------------
00173 void ObjTexture::print()
00174 {
00175   Log::print(
00176     Say("-blendu %s -blendv %s -cc %s -clamp %s -mm %n %n -o %n %n %n -s %n %n %n -t %n %n %n -texres %n -imfchan '%c' -bm %n %s\n")
00177     << (mBlendU ? "on" : "off")
00178     << (mBlendV ? "on" : "off")
00179     << (mCC     ? "on" : "off")
00180     << (mClamp  ? "on" : "off")
00181     << mMM_Base << mMM_Gain
00182     << mO_UVW[0] << mO_UVW[1] << mO_UVW[2]
00183     << mS_UVW[0] << mS_UVW[1] << mS_UVW[2]
00184     << mT_UVW[0] << mT_UVW[1] << mT_UVW[2]
00185     << mTexres_Value
00186     << mImfchan
00187     << mBM
00188     << mFileName.toStdString().c_str()
00189     );
00190 }
00191 //-----------------------------------------------------------------------------
00192 // loadObjMaterials
00193 //-----------------------------------------------------------------------------
00194 void ObjLoader::loadObjMaterials(VirtualFile* input, std::vector<ObjMaterial>& materials )
00195 {
00196   ref<TextStream> line_reader = new TextStream(input);
00197 
00198   String line;
00199   String file = input->path();
00200   while(line_reader->readLine(line))
00201   {
00202     line = line.trim();
00203     if (line.empty() || line[0] == '#')
00204       continue;
00205     else
00206     {
00207       if (line.startsWith("newmtl"))
00208       {
00209         materials.push_back(ObjMaterial());
00210         materials.back().setObjectName( line.field(' ', 1).toStdString().c_str() );
00211       }
00212       else
00213       if (line.startsWith("Ns"))
00214       {
00215         materials.back().setNs (line.field(' ', 1).toFloat());
00216       }
00217       else
00218       if (line.startsWith("Ka"))
00219       {
00220         fvec3 col;
00221         col.r() = (float)line.field(' ', 1).toDouble();
00222         col.g() = (float)line.field(' ', 2).toDouble();
00223         col.b() = (float)line.field(' ', 3).toDouble();
00224         materials.back().setKa(col);
00225       }
00226       else
00227       if (line.startsWith("Kd"))
00228       {
00229         fvec3 col;
00230         col.r() = (float)line.field(' ', 1).toDouble();
00231         col.g() = (float)line.field(' ', 2).toDouble();
00232         col.b() = (float)line.field(' ', 3).toDouble();
00233         materials.back().setKd(col);
00234       }
00235       else
00236       if (line.startsWith("Ks"))
00237       {
00238         fvec3 col;
00239         col.r() = (float)line.field(' ', 1).toDouble();
00240         col.g() = (float)line.field(' ', 2).toDouble();
00241         col.b() = (float)line.field(' ', 3).toDouble();
00242         materials.back().setKs(col);
00243       }
00244       else
00245       if (line.startsWith("Ke"))
00246       {
00247         fvec3 col;
00248         col.r() = (float)line.field(' ', 1).toDouble();
00249         col.g() = (float)line.field(' ', 2).toDouble();
00250         col.b() = (float)line.field(' ', 3).toDouble();
00251         materials.back().setKe(col);
00252       }
00253       else
00254       if (line.startsWith("Tf"))
00255       {
00256         // skip transmission filter
00257       }
00258       else
00259       if (line.startsWith("Ni"))
00260       {
00261         materials.back().setNi(line.field(' ', 1).toFloat());
00262       }
00263       else
00264       if (line.startsWith("d") || line.startsWith("Tr"))
00265       {
00266         materials.back().setTr(line.field(' ', 1).toFloat());
00267       }
00268       else
00269       if (line.startsWith("illum"))
00270       {
00271         materials.back().setIllum(line.field(' ', 1).toInt());
00272       }
00273       else
00274       if (line.startsWith("map_Kd"))
00275         materials.back().setMap_Kd(ObjTexture().parseLine(line,file));
00276       else
00277       if (line.startsWith("map_Ks"))
00278         materials.back().setMap_Ks(ObjTexture().parseLine(line,file));
00279       else
00280       if (line.startsWith("map_Ka"))
00281         materials.back().setMap_Ka(ObjTexture().parseLine(line,file));
00282       else
00283       if (line.startsWith("map_Ns"))
00284         materials.back().setMap_Ns(ObjTexture().parseLine(line,file));
00285       else
00286       if (line.startsWith("map_d"))
00287         materials.back().setMap_d(ObjTexture().parseLine(line,file));
00288       else
00289       if (line.startsWith("decal"))
00290         materials.back().setMap_Decal(ObjTexture().parseLine(line,file));
00291       else
00292       if (line.startsWith("disp"))
00293         materials.back().setMap_Disp(ObjTexture().parseLine(line,file));
00294       else
00295       if (line.startsWith("bump") || line.startsWith("map_bump"))
00296         materials.back().setMap_Bump(ObjTexture().parseLine(line,file));
00297       else
00298         Log::error( Say("Unknown field '%s' in file %s'.\n") << line << file );
00299     }
00300   }
00301 }
00302 //-----------------------------------------------------------------------------
00303 ref<ResourceDatabase> ObjLoader::loadOBJ( VirtualFile* file )
00304 {
00305   if (!file)
00306   {
00307     Log::error("loadOBJ() called with NULL argument.\n");
00308     return NULL;
00309   }
00310   ref<TextStream> stream = new TextStream(file);
00311   if ( !stream->inputFile()->open(OM_ReadOnly) )
00312   {
00313     Log::error( Say("loadOBJ(): could not open source file.\n") );
00314     return NULL;
00315   }
00316 
00317   mCoords.clear();
00318   // std::vector<float> mNormals;
00319   // std::vector<float> mTexCoords;
00320   std::map< std::string, ref<ObjMaterial> > mMaterials;
00321   std::vector< ref<ObjMesh> > mMeshes;
00322 
00323   ref<ObjMaterial> cur_material;
00324   ref<ObjMesh> cur_mesh;
00325 
00326   const int BUF_SIZE = 1024;
00327   char cmd[BUF_SIZE];
00328 
00329   int line_count = 0;
00330   int f_format_type = 0;
00331   std::string object_name;
00332   bool starts_new_geom = true;
00333   #if 0
00334     bool smoothing_group = false;
00335   #endif
00336 
00337   std::string stdstr_line;
00338   while( stream->readLine(stdstr_line) )
00339   {
00340     ++line_count;
00341     std::string line = String::trimStdString(stdstr_line);
00342     if (line.empty() || line[0] == '#')
00343       continue;
00344 
00345     // note: comments cannot be multiline
00346     while( line[line.length()-1] == '\\' && stream->readLine(stdstr_line) )
00347     {
00348       ++line_count;
00349       // remove "\"
00350       line[line.length()-1] = ' ';
00351       // remove spaces before \ and insert a single ' ' space
00352       line = String::trimStdString(line) + ' ';
00353       // appends new line
00354       line += String::trimStdString(stdstr_line);
00355     }
00356 
00357     cmd[0] = 0;
00358     sscanf(line.c_str(), "%s ", cmd);
00359     if ( !cmd[0] )
00360       continue;
00361 // ----------------------------------------------------------------------------
00362     // Vertex data:
00363     if (strcmp(cmd,"v") == 0) // Geometric vertices
00364     {
00365       float x=0,y=0,z=0,w=1.0f;
00366       sscanf(line.c_str()+2,"%f %f %f", &x, &y, &z);
00367       append(mCoords,fvec4(x,y,z,w));
00368       /*append(mCoords,x);
00369       append(mCoords,y);
00370       append(mCoords,z);
00371       append(mCoords,w);*/
00372     }
00373     else
00374     if (strcmp(cmd,"vt") == 0) // Texture vertices
00375     {
00376       // note, this might have less than 3 mCoords
00377       float x=0,y=0,z=0;
00378       sscanf(line.c_str()+3,"%f %f %f", &x, &y, &z);
00379       append(mTexCoords,fvec3(x,y,z));
00380       /*append(mTexCoords,x);
00381       append(mTexCoords,y);
00382       append(mTexCoords,z);*/
00383     }
00384     else
00385     if (strcmp(cmd,"vn") == 0) // Vertex mNormals
00386     {
00387       float x=0,y=0,z=0;
00388       sscanf(line.c_str()+3,"%f %f %f", &x, &y, &z);
00389       append(mNormals,fvec3(x,y,z));
00390       /*append(mNormals,x);
00391       append(mNormals,y);
00392       append(mNormals,z);*/
00393     }
00394     else
00395     /*if (strcmp(cmd,"vp") == 0) // Parameter space vertices
00396     {
00397     }
00398     else*/
00399 // ----------------------------------------------------------------------------
00400     // Elements:
00401     if (strcmp(cmd,"f") == 0) // Face
00402     {
00403       // starts new geometry if necessary
00404       if (starts_new_geom)
00405       {
00406         cur_mesh = new ObjMesh;
00407         cur_mesh->setObjectName(object_name.c_str());
00408         mMeshes.push_back( cur_mesh );
00409         starts_new_geom = false;
00410         cur_mesh->setMaterial(cur_material.get());
00411 
00412         // detect vertex format
00413 
00414         int i=1;
00415         while( line[i] == ' ' || line[i] == '\t' ) ++i;
00416         int slash1 = 0;
00417         int slash2 = 0;
00418         while( i < (int)line.size() && line[i] != ' ' && line[i] != '\t' ) 
00419         {
00420           if (line[i] == '/')
00421           {
00422             if (!slash1)
00423               slash1 = i;
00424             else
00425             if (!slash2)
00426             {
00427               slash2 = i;
00428               break;
00429             }
00430           }
00431           ++i;
00432         }
00433         if (!slash1 && !slash2)
00434           f_format_type = 0;
00435         else
00436         if (slash1 && !slash2)
00437           f_format_type = 1;
00438         else
00439         {
00440           VL_CHECK(slash1)
00441           VL_CHECK(slash2)
00442           if (slash2 == slash1+1)
00443             f_format_type = 2;
00444           else
00445             f_format_type = 3;
00446         }
00447       }
00448 
00449       int face_type = 0;
00450       // divide into tokens
00451       for(size_t i=0; i < line.size(); ++i)
00452       {
00453         if (line[i] == ' ')
00454         {
00455           ++face_type;
00456 
00457           // eat all the spaces
00458           while( line[i] == ' ' ) 
00459             ++i;
00460 
00461           if (line[i] == 0)
00462             break;
00463 
00464           int iv=-1,ivt=-1,ivn=-1;
00465           // 0 = f v       v       v
00466           // 1 = f v/vt    v/vt    v/vt
00467           // 2 = f v//vn   v//vn   v//vn
00468           // 3 = f v/vt/vn v/vt/vn v/vt/vn
00469           switch(f_format_type)
00470           {
00471           case 0:
00472             sscanf(line.c_str()+i, "%d", &iv); 
00473             if (iv>0)  --iv; else  iv  = (int)mCoords.size()    - iv;
00474             append(cur_mesh->facePositionIndex(), iv);
00475             break;
00476           case 1:
00477             sscanf(line.c_str()+i, "%d/%d", &iv,&ivt); 
00478             if (iv>0)  --iv; else  iv  = (int)mCoords.size()    - iv;
00479             if (ivt>0) --ivt; else ivt = (int)mTexCoords.size() - ivt;
00480             append(cur_mesh->facePositionIndex(), iv);
00481             append(cur_mesh->faceTexCoordIndex(), ivt);
00482             break;
00483           case 2:
00484             sscanf(line.c_str()+i, "%d//%d", &iv,&ivn); 
00485             if (iv>0)  --iv; else  iv  = (int)mCoords.size()    - iv;
00486             if (ivn>0) --ivn; else ivn = (int)mNormals.size()   - ivn;
00487             append(cur_mesh->facePositionIndex(), iv);
00488             append(cur_mesh->faceNormalIndex(), ivn);
00489             break;
00490           case 3:
00491             sscanf(line.c_str()+i, "%d/%d/%d", &iv,&ivt,&ivn); 
00492             if (iv>0)  --iv; else  iv  = (int)mCoords.size()    - iv;
00493             if (ivt>0) --ivt; else ivt = (int)mTexCoords.size() - ivt;
00494             if (ivn>0) --ivn; else ivn = (int)mNormals.size()   - ivn;
00495             append(cur_mesh->facePositionIndex(), iv);
00496             append(cur_mesh->faceTexCoordIndex(), ivt);
00497             append(cur_mesh->faceNormalIndex(), ivn);
00498             break;
00499           default:
00500             break;
00501           }
00502         }
00503       }
00504       VL_CHECK(face_type > 2)
00505       // track the face type in order to triangulate it later
00506       append(cur_mesh->face_type(), face_type);
00507     }
00508     else
00509     /*if (strcmp(cmd,"p") == 0) // Point 
00510     {
00511     }
00512     else
00513     if (strcmp(cmd,"l") == 0) // Line
00514     {
00515     }
00516     else
00517     if (strcmp(cmd,"curv") == 0) // Curve
00518     {
00519     }
00520     else
00521     if (strcmp(cmd,"curv2") == 0) // 2D Curve
00522     {
00523     }
00524     else
00525     if (strcmp(cmd,"surf") == 0) // Surface
00526     {
00527     }
00528     else
00529 // ----------------------------------------------------------------------------
00530     // Free-form curve/surface attributes:
00531     if (strcmp(cmd,"deg") == 0) // Degree
00532     {
00533     }
00534     else
00535     if (strcmp(cmd,"bmat") == 0) // Basis matrix
00536     {
00537     }
00538     else
00539     if (strcmp(cmd,"step") == 0) // Step size
00540     {
00541     }
00542     else
00543     if (strcmp(cmd,"cstype") == 0) // Curve or surface type
00544     {
00545     }
00546     else
00547 // ----------------------------------------------------------------------------
00548     // Free-form curve/surface body statements:
00549     if (strcmp(cmd,"parm") == 0) // Parameter values
00550     {
00551     }
00552     else
00553     if (strcmp(cmd,"trim") == 0) // Outer trimming loop
00554     {
00555     }
00556     else
00557     if (strcmp(cmd,"hole") == 0) // Inner trimming loop
00558     {
00559     }
00560     else
00561     if (strcmp(cmd,"scrv") == 0) // Special curve
00562     {
00563     }
00564     else
00565     if (strcmp(cmd,"sp") == 0) // Special point
00566     {
00567     }
00568     else
00569     if (strcmp(cmd,"end") == 0) // End statement
00570     {
00571     }
00572     else
00573 // ----------------------------------------------------------------------------
00574     // Connectivity between free-form surfaces:
00575     if (strcmp(cmd,"con") == 0) // Connect
00576     {
00577     }
00578     else
00579     // Grouping:
00580     if (strcmp(cmd,"g") == 0) // Group name
00581     {
00582     }
00583     else*/
00584     if (strcmp(cmd,"s") == 0) // Smoothing group
00585     {
00586       // not used
00587       #if 0
00588         if(String::trim(line+1) == "off" || String::trim(line+1) == "0")
00589           smoothing_group = false;
00590         else
00591           smoothing_group = true;
00592       #endif
00593     }
00594     else
00595     /*if (strcmp(cmd,"mg") == 0) // Merging group
00596     {
00597     }
00598     else*/
00599     if (strcmp(cmd,"o") == 0) // Object name
00600     {
00601       starts_new_geom = true;
00602       object_name = String::trimStdString(line.c_str()+1);
00603     }
00604     else
00605 // ----------------------------------------------------------------------------
00606     // Display/render attributes:
00607     /*if (strcmp(cmd,"bevel") == 0) // Bevel interpolation
00608     {
00609     }
00610     else
00611     if (strcmp(cmd,"c_interp") == 0) // Color interpolation
00612     {
00613     }
00614     else
00615     if (strcmp(cmd,"d_interp") == 0) // Dissolve interpolation
00616     {
00617     }
00618     else
00619     if (strcmp(cmd,"lod") == 0) // Level of detail
00620     {
00621     }
00622     else*/
00623     if (strcmp(cmd,"usemtl") == 0) // Material name
00624     {
00625       starts_new_geom = true;
00626       std::string mat_name = String(line.c_str()+6).trim().toStdString();
00627       // can also become NULL
00628       cur_material = mMaterials[mat_name];
00629     }
00630     else
00631     if (strcmp(cmd,"mtllib") == 0) // Material library
00632     {
00633       // creates the path for the mtl
00634       String path = file->path().extractPath() + String(line.c_str()+7).trim();
00635       ref<VirtualFile> vfile = defFileSystem()->locateFile(path, file->path().extractPath());
00636       std::string str_file = file->path().toStdString();
00637       std::string str_path = path.toStdString();
00638       if (vfile)
00639       {
00640         // reads the material
00641         std::vector<ObjMaterial> mats;
00642         loadObjMaterials(vfile.get(), mats);
00643         // updates the material library
00644         for(size_t i=0; i < mats.size(); ++i)
00645           mMaterials[mats[i].objectName()] = new ObjMaterial(mats[i]);
00646       }
00647       else
00648       {
00649         Log::error( Say("Could not find OBJ material file '%s'.\n") << path );
00650       }
00651     }
00652     /*else
00653     if (strcmp(cmd,"shadow_obj") == 0) // Shadow casting
00654     {
00655     }
00656     else
00657     if (strcmp(cmd,"trace_obj") == 0) // Ray tracing
00658     {
00659     }
00660     else
00661     if (strcmp(cmd,"ctech") == 0) // Curve approximation technique
00662     {
00663     }
00664     else
00665     if (strcmp(cmd,"stech") == 0) // Surface approximation technique
00666     {
00667     }*/
00668   }
00669 
00670   ref<ResourceDatabase> res_db = new ResourceDatabase;
00671 
00672   // compile the material/effect library
00673 
00674   std::map< ObjMaterial*, ref<Effect> > material_map;
00675   for (std::map< std::string, ref<ObjMaterial> >::iterator it = mMaterials.begin();
00676       it != mMaterials.end();
00677       ++it)
00678   {
00679     ref<Effect> effect = new Effect;
00680     res_db->resources().push_back(effect.get());
00681 
00682     ref<ObjMaterial> obj_mat = it->second;
00683     material_map[it->second.get()] = effect;
00684     res_db->resources().push_back(effect);
00685 
00686     effect->shader()->enable(EN_DEPTH_TEST);
00687     effect->shader()->disable(EN_CULL_FACE);
00688     effect->shader()->enable(EN_LIGHTING);
00689     effect->shader()->gocLightModel()->setTwoSide(true);
00690 
00691     if (obj_mat)
00692     {
00693       // sets the name
00694       effect->shader()->gocMaterial()->setObjectName(obj_mat->objectName().c_str());
00695       // add the Material to the ResourceDatabase
00696       res_db->resources().push_back(effect->shader()->gocMaterial());
00697       // setup the material
00698       fvec4 diffuse  = fvec4( obj_mat->kd(), 1.0f - obj_mat->tr() );
00699       fvec4 ambient  = fvec4( obj_mat->ka(), 1.0f - obj_mat->tr() );
00700       fvec4 specular = fvec4( obj_mat->ks(), 1.0f - obj_mat->tr() );
00701       fvec4 emission = fvec4( obj_mat->ke(), 1.0f - obj_mat->tr() );
00702       effect->shader()->gocMaterial()->setDiffuse( diffuse );
00703       effect->shader()->gocMaterial()->setAmbient( ambient );
00704       effect->shader()->gocMaterial()->setSpecular( specular );
00705       effect->shader()->gocMaterial()->setEmission( emission );
00706       effect->shader()->gocMaterial()->setShininess( obj_mat->ns());
00707 
00708       // setup transparency
00709       if (obj_mat->tr() > 0 || obj_mat->map_d().valid())
00710       {
00711         effect->shader()->enable(EN_BLEND);
00712 
00713         // if it has a mask map use alpha testing (typically for vegetation).
00714         if ( obj_mat->map_d().valid() )
00715         {
00716           effect->shader()->gocAlphaFunc()->set(FU_GEQUAL, 0.5);
00717           effect->shader()->enable(EN_ALPHA_TEST);
00718           // disable cull face
00719           // enable two side
00720         }
00721         else
00722         {
00723           effect->shader()->enable(EN_CULL_FACE);
00724           effect->shader()->gocLightModel()->setTwoSide(false);
00725         }
00726       }
00727 
00728       // setup texture
00729       if (obj_mat->map_Kd().valid())
00730       {
00731         // diffuse
00732         ref<VirtualFile> diff_file = defFileSystem()->locateFile(obj_mat->map_Kd().path(), file->path().extractPath());
00733         ref<Image> diff_img;
00734         if (diff_file)
00735           diff_img = loadImage( diff_file.get() );
00736 
00737         // mask
00738         if (obj_mat->map_d().valid())
00739         {
00740           ref<VirtualFile> mask_file = defFileSystem()->locateFile(obj_mat->map_d().path(), file->path().extractPath());
00741           ref<Image> mask_img;
00742           if (mask_file)
00743             mask_img = loadImage( mask_file.get() );
00744           if (mask_img)
00745           {
00746             if (mask_img->width() == diff_img->width() && mask_img->height() == diff_img->height())
00747             {
00748               diff_img = diff_img->convertFormat(IF_RGBA); VL_CHECK(diff_img)
00749               diff_img = diff_img->convertType(IT_UNSIGNED_BYTE); VL_CHECK(diff_img)
00750               mask_img = mask_img->convertType(IT_UNSIGNED_BYTE);
00751               int bpp = mask_img->bitsPerPixel() / 8;
00752               unsigned char* mask_px  = mask_img->pixels();
00753               unsigned char* mask_end = mask_img->pixels() + mask_img->requiredMemory();
00754               unsigned char* diff_px  = diff_img->pixels() + 3;
00755               while( mask_px != mask_end )
00756               {
00757                 diff_px[0] = mask_px[0];
00758                 mask_px += bpp;
00759                 diff_px += 4;
00760               }
00761             }
00762           }
00763         }
00764 
00765         if ( diff_img )
00766         {
00767           ref<Texture> texture = new Texture;
00768           texture->getTexParameter()->setMinFilter(TPF_LINEAR_MIPMAP_LINEAR);
00769           texture->getTexParameter()->setMagFilter(TPF_LINEAR);
00770           texture->prepareTexture2D( diff_img.get(), TF_RGBA, true );
00771           effect->shader()->gocTextureSampler(0)->setTexture( texture.get() );
00772         }
00773       }
00774     }
00775   }
00776 
00777   for(int imesh=0; imesh<(int)mMeshes.size(); ++imesh)
00778   {
00779     if ( mMeshes[imesh]->facePositionIndex().empty() )
00780     {
00781       Log::warning("OBJ mesh empty.\n");
00782       VL_TRAP()
00783       continue;
00784     }
00785 
00786     #ifndef NDEBUG
00787       int sum = 0;
00788       for(int k=0; k<(int)mMeshes[imesh]->face_type().size(); ++k)
00789         sum += mMeshes[imesh]->face_type()[k];
00790       VL_CHECK( sum == (int)mMeshes[imesh]->facePositionIndex().size() )
00791     #endif
00792 
00793     ref< ArrayFloat3 >   v_coords  = new ArrayFloat3;
00794     ref< ArrayFloat3 >   n_coords  = new ArrayFloat3;
00795     // we support only 2d textures
00796     ref< ArrayFloat2 >   t_coords2 = new ArrayFloat2;
00797 
00798     if ( !mMeshes[imesh]->faceNormalIndex().empty() && mMeshes[imesh]->faceNormalIndex().size() != mMeshes[imesh]->facePositionIndex().size() )
00799     {
00800       Log::print("OBJ mesh corrupted.\n");
00801       continue;
00802     }
00803 
00804     if ( !mMeshes[imesh]->faceTexCoordIndex().empty() && mMeshes[imesh]->faceTexCoordIndex().size() != mMeshes[imesh]->facePositionIndex().size() )
00805     {
00806       Log::print("OBJ mesh corrupted.\n");
00807       continue;
00808     }
00809 
00810     // allocate vertex buffer
00811 
00812     int tri_verts_count = 0;
00813     for(int k=0; k<(int)mMeshes[imesh]->face_type().size(); ++k)
00814       tri_verts_count += (mMeshes[imesh]->face_type()[k] - 2) * 3;
00815 
00816     v_coords->resize( tri_verts_count );
00817     if ( !mMeshes[imesh]->faceNormalIndex().empty() )
00818       n_coords->resize( tri_verts_count );
00819     if ( !mMeshes[imesh]->faceTexCoordIndex().empty() )
00820       t_coords2->resize( tri_verts_count );
00821 
00822     // fill geometry
00823 
00824     int src_base_idx = 0;
00825     int dst_base_idx = 0;
00826     for(int iface=0; iface<(int)mMeshes[imesh]->face_type().size(); ++iface)
00827     {
00828       int type = mMeshes[imesh]->face_type()[iface];
00829       for( int ivert=2; ivert < type; ++ivert )
00830       {
00831         int a = mMeshes[imesh]->facePositionIndex()[src_base_idx+0];
00832         int b = mMeshes[imesh]->facePositionIndex()[src_base_idx+ivert-1];
00833         int c = mMeshes[imesh]->facePositionIndex()[src_base_idx+ivert];
00834 
00835         VL_CHECK( a>= 0)
00836         VL_CHECK( b>= 0)
00837         VL_CHECK( c>= 0)
00838         VL_CHECK( a<(int)mCoords.size() )
00839         VL_CHECK( b<(int)mCoords.size() )
00840         VL_CHECK( c<(int)mCoords.size() )
00841 
00842         v_coords->at(dst_base_idx+0) = mCoords[a].xyz();
00843         v_coords->at(dst_base_idx+1) = mCoords[b].xyz();
00844         v_coords->at(dst_base_idx+2) = mCoords[c].xyz();
00845 
00846         if (!mMeshes[imesh]->faceNormalIndex().empty())
00847         {
00848           int na = mMeshes[imesh]->faceNormalIndex()[src_base_idx+0];
00849           int nb = mMeshes[imesh]->faceNormalIndex()[src_base_idx+ivert-1];
00850           int nc = mMeshes[imesh]->faceNormalIndex()[src_base_idx+ivert];
00851 
00852           VL_CHECK( na>= 0)
00853           VL_CHECK( nb>= 0)
00854           VL_CHECK( nc>= 0)
00855           VL_CHECK( na<(int)mNormals.size() )
00856           VL_CHECK( nb<(int)mNormals.size() )
00857           VL_CHECK( nc<(int)mNormals.size() )
00858 
00859           n_coords->at(dst_base_idx+0) = mNormals[na];
00860           n_coords->at(dst_base_idx+1) = mNormals[nb];
00861           n_coords->at(dst_base_idx+2) = mNormals[nc];
00862         }
00863 
00864         // we consider all the texture coords as 2d
00865         if (!mMeshes[imesh]->faceTexCoordIndex().empty())
00866         {
00867           int na = mMeshes[imesh]->faceTexCoordIndex()[src_base_idx+0];
00868           int nb = mMeshes[imesh]->faceTexCoordIndex()[src_base_idx+ivert-1];
00869           int nc = mMeshes[imesh]->faceTexCoordIndex()[src_base_idx+ivert];
00870 
00871           VL_CHECK( na>= 0)
00872           VL_CHECK( nb>= 0)
00873           VL_CHECK( nc>= 0)
00874           VL_CHECK( na<(int)mTexCoords.size() )
00875           VL_CHECK( nb<(int)mTexCoords.size() )
00876           VL_CHECK( nc<(int)mTexCoords.size() )
00877 
00878           t_coords2->at(dst_base_idx+0) = mTexCoords[na].st();
00879           t_coords2->at(dst_base_idx+1) = mTexCoords[nb].st();
00880           t_coords2->at(dst_base_idx+2) = mTexCoords[nc].st();
00881         }
00882 
00883         dst_base_idx+=3;
00884       }
00885       src_base_idx += type;
00886     }
00887 
00888     // Geometry
00889 
00890     ref<Geometry> geom = new Geometry;
00891     geom->setObjectName(mMeshes[imesh]->objectName().c_str());
00892     geom->setVertexArray( v_coords.get() );
00893     if ( mMeshes[imesh]->faceNormalIndex().size() )
00894       geom->setNormalArray( n_coords.get() );
00895     if ( mMeshes[imesh]->faceTexCoordIndex().size() )
00896       geom->setTexCoordArray(0, t_coords2.get() );
00897     geom->drawCalls()->push_back( new DrawArrays(PT_TRIANGLES, 0, tri_verts_count) );
00898 
00899     // Material/Effect
00900 
00901     ref<Effect> effect = material_map[ mMeshes[imesh]->material() ];
00902     if (!effect)
00903     {
00904       effect = material_map[ mMeshes[imesh]->material() ] = new Effect;
00905       res_db->resources().push_back(effect.get());
00906 
00907       effect->shader()->enable(EN_DEPTH_TEST);
00908       effect->shader()->disable(EN_CULL_FACE);
00909       effect->shader()->enable(EN_LIGHTING);
00910       effect->shader()->gocLightModel()->setTwoSide(true);
00911     }
00912     VL_CHECK(effect)
00913 
00914     // Actor
00915     ref<Actor> actor = new Actor(geom.get(), NULL);
00916     res_db->resources().push_back(actor);
00917     actor->setObjectName(mMeshes[imesh]->objectName().c_str());
00918     actor->setEffect(effect.get());
00919   }
00920 
00921   stream->inputFile()->close();
00922 
00923   return res_db;
00924 }
00925 //-----------------------------------------------------------------------------
00926 ref<ResourceDatabase> vl::loadOBJ( const String& path )
00927 {
00928   ref<VirtualFile> file = defFileSystem()->locateFile( path );
00929   if (file)
00930     return loadOBJ( file.get() );
00931   else
00932   {
00933     Log::error( Say("Could not locate '%s'.\n") << path );
00934     return NULL;
00935   }
00936 }
00937 //-----------------------------------------------------------------------------
00938 ref<ResourceDatabase> vl::loadOBJ( VirtualFile* file )
00939 {
00940   return ObjLoader().loadOBJ(file);
00941 }
00942 //-----------------------------------------------------------------------------

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.