Visualization Library

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

X:/dropbox/visualizationlibrary/src/vlGraphics/plugins/ioPLY.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 "ioPLY.hpp"
00033 #include <vlCore/Log.hpp>
00034 #include <vlCore/Say.hpp>
00035 #include <vlCore/VisualizationLibrary.hpp>
00036 #include <vlCore/FileSystem.hpp>
00037 #include <vlCore/TextStream.hpp>
00038 #include <vlCore/VirtualFile.hpp>
00039 #include <vlGraphics/Effect.hpp>
00040 #include <vlGraphics/Actor.hpp>
00041 #include <vlCore/LoadWriterManager.hpp>
00042 
00043 using namespace vl;
00044 //-----------------------------------------------------------------------------
00045 ref<ResourceDatabase> vl::loadPLY(const String& path)
00046 {
00047   ref<VirtualFile> file = defFileSystem()->locateFile(path);
00048 
00049   if (file)
00050     return loadPLY( file.get() );
00051   else
00052   {
00053     Log::error( Say("Could not locate '%s'.\n") << path );
00054     return NULL;
00055   }
00056 }
00057 //-----------------------------------------------------------------------------
00058 ref<ResourceDatabase> vl::loadPLY(VirtualFile* file)
00059 {
00060   PlyLoader ply;
00061   ref<ResourceDatabase> res_db = ply.loadPly(file);
00062   return res_db;
00063 }
00064 //-----------------------------------------------------------------------------
00065 void PlyLoader::PlyScalar::read(VirtualFile* file, bool le)
00066 {
00067   switch(scalarType()) 
00068   {
00069     case PlyChar:   mData.mChar   = file->readSInt8(); break;
00070     case PlyUChar:  mData.mUChar  = file->readUInt8(); break;
00071     case PlyShort:  mData.mShort  = file->readSInt16(le); break;
00072     case PlyUShort: mData.mUShort = file->readUInt16(le); break;
00073     case PlyInt:    mData.mInt    = file->readSInt32(le); break;
00074     case PlyUInt:   mData.mUInt   = file->readUInt32(le); break;
00075     case PlyFloat:  mData.mFloat  = file->readFloat(le); break;
00076     case PlyDouble: mData.mDouble = file->readDouble(le); break;
00077     default:
00078       Log::error("PlyLoader: scalar read error.\n");
00079   }
00080 }
00081 void PlyLoader::PlyScalar::read(TextStream* text)
00082 {
00083   int idata;
00084   double ddata;
00085   switch(scalarType())
00086   {
00087     case PlyChar:   text->readInt(idata); mData.mChar   = (char)idata; break;
00088     case PlyUChar:  text->readInt(idata); mData.mUChar  = (unsigned char)idata; break;
00089     case PlyShort:  text->readInt(idata); mData.mShort  = (short)idata; break;
00090     case PlyUShort: text->readInt(idata); mData.mUShort = (unsigned short)idata; break;
00091     case PlyInt:    text->readInt(idata); mData.mInt    = (int)idata; break;
00092     case PlyUInt:   text->readInt(idata); mData.mUInt   = (unsigned int)idata; break;
00093     case PlyFloat:  text->readDouble(ddata); mData.mFloat  = (float)ddata; break;
00094     case PlyDouble: text->readDouble(ddata); mData.mDouble = (double)ddata; break;
00095     default:
00096       Log::error("PlyLoader: scalar read error.\n");
00097   }
00098 }
00099 float PlyLoader::PlyScalar::getAsFloat() const
00100 {
00101   switch(scalarType())
00102   {
00103     case PlyChar:   return (float)mData.mChar;
00104     case PlyUChar:  return (float)mData.mUChar;
00105     case PlyShort:  return (float)mData.mShort;
00106     case PlyUShort: return (float)mData.mUShort;
00107     case PlyInt:    return (float)mData.mInt;
00108     case PlyUInt:   return (float)mData.mUInt;
00109     case PlyFloat:  return mData.mFloat;
00110     case PlyDouble: return (float)mData.mDouble;
00111     default:
00112       Log::error("PlyLoader: getAsFloat() error.\n");
00113       return 0.0f;
00114   }
00115 }
00116 int PlyLoader::PlyScalar::getAsInt() const
00117 {
00118   switch(scalarType())
00119   {
00120     case PlyChar:   return (int)mData.mChar;
00121     case PlyUChar:  return (int)mData.mUChar;
00122     case PlyShort:  return (int)mData.mShort;
00123     case PlyUShort: return (int)mData.mUShort;
00124     case PlyInt:    return (int)mData.mInt;
00125     case PlyUInt:   return (int)mData.mUInt;
00126     case PlyFloat:  return (int)mData.mFloat;
00127     case PlyDouble: return (int)mData.mDouble;
00128     default:
00129       Log::error("PlyLoader: getAsFloat() error.\n");
00130       return 0;
00131   }
00132 }
00133 void PlyLoader::PlyElement::analyze()
00134 {
00135   mVertex.resize(3);
00136   mNormal.resize(3);
00137   mColor.resize(4);
00138   if (name() == "vertex")
00139   {
00140     for(unsigned int j=0; j<properties().size(); ++j)
00141     {
00142       PlyScalar* scalar = cast<PlyScalar>(properties()[j].get()); VL_CHECK(scalar)
00143       if (scalar)
00144       {
00145         if (scalar->name() == "x")
00146           mVertex[0] = scalar;
00147         else
00148         if (scalar->name() == "y")
00149           mVertex[1] = scalar;
00150         else
00151         if (scalar->name() == "z")
00152           mVertex[2] = scalar;
00153         else
00154         if (scalar->name() == "nx")
00155           mNormal[0] = scalar;
00156         else
00157         if (scalar->name() == "ny")
00158           mNormal[1] = scalar;
00159         else
00160         if (scalar->name() == "nz")
00161           mNormal[2] = scalar;
00162         else
00163         if (scalar->name() == "red")
00164           mColor[0] = scalar;
00165         else
00166         if (scalar->name() == "green")
00167           mColor[1] = scalar;
00168         else
00169         if (scalar->name() == "blue")
00170           mColor[2] = scalar;
00171         else
00172         if (scalar->name() == "alpha")
00173           mColor[3] = scalar;
00174       }
00175     }
00176   }
00177 }
00178 void PlyLoader::readElements(VirtualFile* file)
00179 {
00180   // reposition to the correct location
00181   file->seekSet(0);
00182   std::string str;
00183   do
00184   {
00185     unsigned char ch = file->readUInt8();
00186     if (ch == '\n' && str == "end_header")
00187       break;
00188     if (ch == '\n')
00189     {
00190       str.clear();
00191       continue;
00192     }
00193     str.push_back( ch );
00194   } while(true);
00195 
00196   for(unsigned i=0; i<mElements.size(); ++i)
00197     for(int j=0; j<mElements[i]->elemCount(); ++j)
00198     {
00199       mElements[i]->read(file, littleEndian());
00200       newElement(mElements[i].get());
00201     }
00202 }
00203 void PlyLoader::readElements(TextStream* text)
00204 {
00205   for(unsigned i=0; i<mElements.size(); ++i)
00206     for(int j=0; j<mElements[i]->elemCount(); ++j)
00207     {
00208       mElements[i]->read(text);
00209       newElement(mElements[i].get());
00210     }
00211 }
00212 void PlyLoader::newElement(PlyElement*el)
00213 {
00214   if (el->name() == "vertex")
00215   {
00216     for(unsigned int j=0; j<el->properties().size(); ++j)
00217     {
00218       if (mVerts)
00219         mVerts->at(mVertexIndex)   = el->getVertex();
00220       if (mNormals)
00221         mNormals->at(mVertexIndex) = el->getNormal();
00222       if (mColors)
00223         mColors->at(mVertexIndex)  = el->getColor();
00224     }
00225 
00226     ++mVertexIndex;
00227   }
00228   else
00229   if (el->name() == "face")
00230   {
00231     for(unsigned int j=0; j<el->properties().size(); ++j)
00232     {
00233       PlyScalarList* list = cast<PlyScalarList>(el->properties()[j].get()); VL_CHECK(list)
00234       if (list && list->name() == "vertex_indices")
00235       {
00236         for(int i=1; i<(int)list->scalars().size()-1; ++i)
00237         {
00238           if (mIndices.capacity() - mIndices.size() == 0)
00239             mIndices.reserve( mIndices.capacity() * 2 );
00240           mIndices.push_back( list->scalars()[0].getAsInt());
00241           mIndices.push_back( list->scalars()[i].getAsInt());
00242           mIndices.push_back( list->scalars()[i+1].getAsInt());
00243         }
00244       }
00245     }
00246   }
00247 }
00248 PlyLoader::EType PlyLoader::translateType(const String& type)
00249 {
00250   if (type == "int8")   return PlyChar; else
00251   if (type == "char")   return PlyChar; else
00252   if (type == "uint8")   return PlyChar; else
00253   if (type == "uchar")  return PlyUChar; else
00254   if (type == "ushort") return PlyUShort; else
00255   if (type == "uint16") return PlyUShort; else
00256   if (type == "short")  return PlyShort; else
00257   if (type == "int16")  return PlyShort; else
00258   if (type == "int")    return PlyInt; else
00259   if (type == "int32")    return PlyInt; else
00260   if (type == "uint")   return PlyUInt; else
00261   if (type == "uint32")   return PlyUInt; else
00262   if (type == "float")  return PlyFloat; else
00263   if (type == "float32")  return PlyFloat; else
00264   if (type == "float64")  return PlyDouble; else
00265   if (type == "double") return PlyDouble; 
00266   else
00267   {
00268     Log::error("PlyLoader: type parse error.\n");
00269     return PlyError;
00270   }
00271 }
00272 void PlyLoader::analyzeHeader()
00273 {
00274   // allocate space for vertices, normals and colors.
00275   for(unsigned int i=0; i<elements().size(); ++i)
00276   {
00277     if (elements()[i]->name() == "vertex")
00278     {
00279       for(unsigned int j=0; j<elements()[i]->properties().size(); ++j)
00280       {
00281         if (elements()[i]->properties()[j]->name() == "x")
00282         {
00283           mVerts = new ArrayFloat3;
00284           mVerts->resize( elements()[i]->elemCount() );
00285         }
00286         if (elements()[i]->properties()[j]->name() == "nx")
00287         {
00288           mNormals = new ArrayFloat3;
00289           mNormals->resize( elements()[i]->elemCount() );
00290         }
00291         if (elements()[i]->properties()[j]->name() == "red")
00292         {
00293           mColors = new ArrayUByte4;
00294           mColors->resize( elements()[i]->elemCount() );
00295           memset(mColors->ptr(), 0xFF, sizeof(mColors->at(0))*mColors->size());
00296         }
00297       }
00298       elements()[i]->analyze();
00299     }
00300   }
00301   if (mVerts->size() == 0)
00302   {
00303     Log::error("PlyLoader: no vertices found.\n");
00304   }
00305 }
00306 bool PlyLoader::readHeader(TextStream* line_reader)
00307 {
00308   mVerts   = NULL;
00309   mNormals = NULL;
00310   mColors  = NULL;
00311   mIndices.reserve(100);
00312   bool ok = true;
00313   elements().clear();
00314   String str;
00315   // ply loader
00316   line_reader->readLineLF(str);
00317   if (str.trim() != "ply")
00318     return false;
00319   // format
00320   line_reader->readLineLF(str);
00321   if (str.trim() == "format ascii 1.0")
00322   {
00323     mBinary = false;
00324   }
00325   else
00326   if (str.trim() == "format binary_little_endian 1.0")
00327   {
00328     mBinary = true;
00329     mLittleEndian = true;
00330   }
00331   else
00332   if (str.trim() == "format binary_big_endian 1.0")
00333   {
00334     mBinary = true;
00335     mLittleEndian = false;
00336   }
00337   else
00338     return false;
00339   // read elements
00340   while ( (line_reader->readLineLF(str)) && str.trim() != "end_header")
00341   {
00342     if (str.startsWith("comment"))
00343       continue;
00344     else
00345     if (str.startsWith("element"))
00346     {
00347       elements().push_back(new PlyElement);
00348       elements().back()->setName( str.field(' ',1) );
00349       elements().back()->setElemCount( str.field(' ',2).toInt() );
00350     }
00351     else
00352     if (str.startsWith("property"))
00353     {
00354       String prop_type = str.field(' ',1);
00355       ref<PlyScalar> prop;
00356       ref<PlyScalarList> scalar_list;
00357       if (prop_type == "list")
00358       {
00359         String num_type = str.field(' ',2);
00360         String idx_type = str.field(' ',3);
00361         String name     = str.field(' ',4);
00362         if (name.empty())
00363         {
00364           Log::error("PLY parse error #5.\n");
00365           return false;
00366         }
00367 
00368         scalar_list = new PlyScalarList;
00369         elements().back()->properties().push_back(scalar_list);
00370 
00371         scalar_list->setCountType(translateType(num_type));
00372         scalar_list->setScalarType(translateType(idx_type));
00373         scalar_list->setName(name);
00374       }
00375       else
00376       {
00377         prop = new PlyScalar;
00378         elements().back()->properties().push_back(prop);
00379         prop->setName( str.field(' ',2) );
00380         prop->setScalarType(translateType(prop_type));
00381       }
00382     }
00383     else
00384     {
00385       Log::error("PLY parse error #2.\n");
00386       return false;
00387     }
00388   }
00389   analyzeHeader();
00390   mVertexIndex = 0;
00391   return ok;
00392 }
00393 ref<ResourceDatabase> PlyLoader::loadPly(VirtualFile* file)
00394 {
00395   ref<TextStream> line_reader = new TextStream;
00396 
00397   line_reader->setInputFile(file);
00398 
00399   readHeader(line_reader.get());
00400 
00401   if (binary())
00402     readElements(file);
00403   else
00404     readElements(line_reader.get());
00405   file->close();
00406 
00407   if (mIndices.empty() || !mVerts)
00408     return NULL;
00409 
00410   ref<Geometry> geom = new Geometry;
00411   geom->setVertexArray(mVerts.get());
00412   geom->setNormalArray(mNormals.get());
00413   geom->setColorArray(mColors.get());
00414   ref<DrawElementsUInt> de = new DrawElementsUInt(PT_TRIANGLES);
00415   geom->drawCalls()->push_back(de.get());
00416   de->indexBuffer()->resize(mIndices.size());
00417   memcpy(de->indexBuffer()->ptr(), &mIndices[0], sizeof(unsigned int)*mIndices.size());
00418 
00419   // Effect
00420   ref<Effect> effect = new Effect;
00421 
00422   // Detph test
00423   effect->shader()->enable(EN_DEPTH_TEST);
00424 
00425   // Lighting
00426   if( mNormals )
00427     effect->shader()->enable(EN_LIGHTING);
00428 
00429   // note: we don't insert any light
00430   if (mColors)
00431     effect->shader()->gocMaterial()->setColorMaterialEnabled(true);
00432 
00433   ref<ResourceDatabase> res_db = new ResourceDatabase;
00434   res_db->resources().push_back( new Actor(geom.get(), effect.get(), NULL ) );
00435   return res_db;
00436 }
00437 //-----------------------------------------------------------------------------

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.