# 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/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 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.