Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
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
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
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
00316 line_reader->readLineLF(str);
00317 if (str.trim() != "ply")
00318 return false;
00319
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
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
00420 ref<Effect> effect = new Effect;
00421
00422
00423 effect->shader()->enable(EN_DEPTH_TEST);
00424
00425
00426 if( mNormals )
00427 effect->shader()->enable(EN_LIGHTING);
00428
00429
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