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 "ioAC3D.hpp"
00033 #include <vlCore/checks.hpp>
00034 #include <vlGraphics/Effect.hpp>
00035 #include <vlGraphics/Geometry.hpp>
00036 #include <vlCore/Image.hpp>
00037 #include <vlGraphics/Texture.hpp>
00038 #include <vlCore/Log.hpp>
00039 #include <vlCore/Say.hpp>
00040 #include <vlCore/VisualizationLibrary.hpp>
00041 #include <vlCore/FileSystem.hpp>
00042 #include <vlCore/TextStream.hpp>
00043 #include <vlCore/VirtualFile.hpp>
00044 #include <vlGraphics/DoubleVertexRemover.hpp>
00045 #include <map>
00046 #include <vlCore/LoadWriterManager.hpp>
00047
00048 using namespace vl;
00049
00050 namespace
00051 {
00052 class LoaderAC3D
00053 {
00054 public:
00055
00056 class vert_info
00057 {
00058 public:
00059 int Vert;
00060 float U;
00061 float V;
00062 };
00063
00064 class material_info
00065 {
00066 public:
00067 String Name;
00068 fvec3 Diffuse;
00069 fvec3 Ambient;
00070 fvec3 Emission;
00071 fvec3 Specular;
00072 float Shininess;
00073 float Trans;
00074 };
00075
00076 class surface_info
00077 {
00078 public:
00079 int Flags;
00080 int materials;
00081 int VertCount;
00082 std::vector<vert_info> Vertex;
00083 };
00084
00085 class mesh_info
00086 {
00087 public:
00088 mesh_info();
00089
00090 String Name;
00091 String Data;
00092 String Texture;
00093 float TexRep[2];
00094 dmat4 Matrix;
00095 String Url;
00096 int NumVert;
00097 std::vector<fvec3> Vert;
00098 int NumSurf;
00099 std::vector<surface_info> Surface;
00100 int NumKids;
00101 };
00102
00103 LoaderAC3D();
00104 bool parseAC3D(VirtualFile* file);
00105
00106 fvec3 readColor();
00107 fvec3 readVector();
00108 float readFloat();
00109 int readInt();
00110 int readHex();
00111 String readLine();
00112 String readWord();
00113 String readName();
00114 void readMaterial();
00115 void readObject();
00116
00117 std::vector<material_info> materials;
00118 std::vector<mesh_info> meshes;
00119 bool verbose;
00120
00121 protected:
00122 ref<TextStream> mTokenizer;
00123 String mTmpStr;
00124 bool mEOF;
00125 };
00126 }
00127
00128
00129
00130 LoaderAC3D::mesh_info::mesh_info()
00131 {
00132 TexRep[0] = 1;
00133 TexRep[1] = 1;
00134 NumVert = 0;
00135 NumSurf = 0;
00136 NumKids = 0;
00137 }
00138
00139
00140
00141 LoaderAC3D::LoaderAC3D()
00142 {
00143 verbose = true;
00144 }
00145
00146 bool LoaderAC3D::parseAC3D(VirtualFile* file)
00147 {
00148 mEOF = false;
00149
00150 mTokenizer = new TextStream;
00151 mTokenizer->setInputFile( file );
00152 String token;
00153
00154 mTokenizer->readString(token);
00155
00156 if (token != "AC3Db")
00157 {
00158 Log::error("Not an AC3Db file!\n");
00159 file->close();
00160 return false;
00161 }
00162
00163 while( mTokenizer->readString(token) )
00164 {
00165 if (token == "MATERIAL")
00166 readMaterial();
00167 else
00168 if (token == "OBJECT")
00169 readObject();
00170 else
00171 {
00172 Log::error("AC3D parse error.\n");
00173 file->close();
00174 return false;
00175 }
00176 }
00177
00178 file->close();
00179 return true;
00180 }
00181
00182 fvec3 LoaderAC3D::readColor()
00183 {
00184 bool ok = true;
00185 ok &= mTokenizer->readString(mTmpStr); float r = mTmpStr.toFloat();
00186 ok &= mTokenizer->readString(mTmpStr); float g = mTmpStr.toFloat();
00187 ok &= mTokenizer->readString(mTmpStr); float b = mTmpStr.toFloat();
00188 mEOF = !ok;
00189 if ( !ok )
00190 Log::error("LoaderAC3D::readColor() IO error.\n");
00191 return fvec3(r,g,b);
00192 }
00193
00194 fvec3 LoaderAC3D::readVector()
00195 {
00196 bool ok = true;
00197 ok &= mTokenizer->readString(mTmpStr); float x = mTmpStr.toFloat();
00198 ok &= mTokenizer->readString(mTmpStr); float y = mTmpStr.toFloat();
00199 ok &= mTokenizer->readString(mTmpStr); float z = mTmpStr.toFloat();
00200 mEOF = !ok;
00201 if ( !ok )
00202 Log::error("LoaderAC3D::readVector() IO error.\n");
00203 return fvec3(x,y,z);
00204 }
00205
00206 float LoaderAC3D::readFloat()
00207 {
00208 bool ok = true;
00209 ok &= mTokenizer->readString(mTmpStr); float f = mTmpStr.toFloat();
00210 mEOF = !ok;
00211 if ( !ok )
00212 Log::error("LoaderAC3D::readFloat() IO error.\n");
00213 return f;
00214 }
00215
00216 int LoaderAC3D::readInt()
00217 {
00218 bool ok = true;
00219 ok &= mTokenizer->readString(mTmpStr); int i = mTmpStr.toInt();
00220 mEOF = !ok;
00221 if ( !ok )
00222 Log::error("LoaderAC3D::readInt() IO error.\n");
00223 return i;
00224 }
00225
00226 int LoaderAC3D::readHex()
00227 {
00228 bool ok = true;
00229 ok &= mTokenizer->readString(mTmpStr);
00230 mEOF = !ok;
00231 if ( !ok )
00232 {
00233 Log::error("I/O error reading hex.\n");
00234 return 0;
00235 }
00236 else
00237 {
00238 mTmpStr[0] = ' ';
00239 mTmpStr[1] = ' ';
00240 return mTmpStr.toInt(true);
00241 }
00242 }
00243
00244 String LoaderAC3D::readWord()
00245 {
00246 bool ok = true;
00247 ok &= mTokenizer->readString( mTmpStr );
00248 mEOF = !ok;
00249 if ( !ok )
00250 {
00251 Log::error("I/O error reading word.\n");
00252 return "";
00253 }
00254 else
00255 {
00256 if ( mTmpStr.count('"') == 1 )
00257 {
00258 Log::error( Say("The string '%s' contains a single '\"'.\n") << mTmpStr );
00259 }
00260
00261 mTmpStr.remove('"');
00262 return mTmpStr;
00263 }
00264 }
00265
00266 String LoaderAC3D::readName()
00267 {
00268 bool ok = true;
00269 ok &= mTokenizer->readQuotedString( mTmpStr );
00270 mEOF = !ok;
00271 if ( !ok )
00272 {
00273 Log::error("I/O error reading word.\n");
00274 return "";
00275 }
00276 else
00277 {
00278 if ( mTmpStr.count('"') == 1 )
00279 {
00280 Log::error( Say("The string '%s' contains a single '\"'.\n") << mTmpStr );
00281 }
00282
00283 mTmpStr.remove('"');
00284 return mTmpStr;
00285 }
00286 }
00287
00288 String LoaderAC3D::readLine()
00289 {
00290 bool ok = true;
00291 ok &= mTokenizer->readLine( mTmpStr );
00292 if ( !ok )
00293 {
00294 Log::error("I/O error reading line.\n");
00295 return "";
00296 }
00297 else
00298 {
00299 return mTmpStr;
00300 }
00301 }
00302
00303 void LoaderAC3D::readMaterial()
00304 {
00305
00306 material_info material;
00307
00308 material.Name = readName();
00309 readWord();
00310 material.Diffuse = readColor();
00311 readWord();
00312 material.Ambient = readColor();
00313 readWord();
00314 material.Emission = readColor();
00315 readWord();
00316 material.Specular = readColor();
00317 readWord();
00318 material.Shininess = readFloat();
00319 readWord();
00320 material.Trans = 1 - readFloat();
00321
00322 materials.push_back(material);
00323 }
00324
00325 void LoaderAC3D::readObject()
00326 {
00327 mesh_info mesh;
00328 String block;
00329
00330 block = readWord();
00331
00332 do
00333 {
00334 block = readWord();
00335
00336 if (mEOF)
00337 break;
00338
00339 if (block == "name")
00340 {
00341 mesh.Name = readName();
00342 } else
00343 if (block == "data")
00344 {
00345
00346 int data_size=0;
00347 mTokenizer->readLine(mTmpStr);
00348 data_size = mTmpStr.toInt();
00349
00350
00351 unsigned char ch = 0;
00352 for (int i=0; i<data_size; i++ )
00353 mTokenizer->readToken(&ch);
00354 }
00355 else
00356 if (block == "texture")
00357 {
00358 mesh.Texture = readName();
00359 } else
00360 if (block == "texrep")
00361 {
00362 mesh.TexRep[0] = readFloat();
00363 mesh.TexRep[1] = readFloat();
00364 } else
00365 if (block == "rot")
00366 {
00367 mesh.Matrix.setX( (dvec3)readVector() );
00368 mesh.Matrix.setY( (dvec3)readVector() );
00369 mesh.Matrix.setZ( (dvec3)readVector() );
00370 } else
00371 if (block == "loc")
00372 {
00373 mesh.Matrix.setT( (dvec3)readVector() );
00374 } else
00375 if (block == "url")
00376 {
00377 mesh.Url = readName();
00378 } else
00379 if (block == "numvert")
00380 {
00381 mesh.NumVert = readInt();
00382 for(int i=0; i<mesh.NumVert; ++i)
00383 {
00384 mesh.Vert.push_back( readVector() );
00385 }
00386 } else
00387 if (block == "numsurf")
00388 {
00389 mesh.NumSurf = readInt();
00390 for(int i=0; i<mesh.NumSurf; ++i)
00391 {
00392 surface_info surf;
00393 String tmp;
00394 do
00395 {
00396 tmp = readWord();
00397
00398 if (tmp == "SURF")
00399 {
00400 surf.Flags = readHex();
00401 }
00402 if (tmp == "mat")
00403 {
00404 surf.materials = readInt();
00405 }
00406 if (tmp == "refs")
00407 {
00408 surf.VertCount = readInt();
00409 for(int j=0; j<surf.VertCount; ++j)
00410 {
00411 vert_info vert;
00412 vert.Vert = readInt();
00413 vert.U = readFloat();
00414 vert.V = readFloat();
00415 surf.Vertex.push_back( vert );
00416 }
00417 }
00418 }
00419 while (tmp != "refs");
00420 mesh.Surface.push_back(surf);
00421 }
00422 }
00423 else
00424 if (block == "kids")
00425 {
00426 mesh.NumKids = readInt();
00427 meshes.push_back(mesh);
00428 }
00429 else
00430 {
00431 if (verbose)
00432 Log::warning( Say("unknown block '%s'\n") << block );
00433
00434 mTokenizer->readLine(mTmpStr);
00435 }
00436 }
00437 while(block != "kids");
00438 }
00439
00440 ref<ResourceDatabase> vl::loadAC3D(const String& path)
00441 {
00442 ref<VirtualFile> file = defFileSystem()->locateFile(path);
00443 if ( !file )
00444 {
00445 Log::error( Say("Could not locate '%s'.\n") << path );
00446 return NULL;
00447 }
00448 else
00449 {
00450 return loadAC3D(file.get() );
00451 }
00452 }
00453
00454 ref<ResourceDatabase> vl::loadAC3D( VirtualFile* file)
00455 {
00456 ref<ResourceDatabase> res_db = new ResourceDatabase;
00457
00458 LoaderAC3D loader;
00459 if ( !loader.parseAC3D(file) )
00460 return NULL;
00461
00462
00463 std::vector< ref<Effect> > mat_map;
00464 for(unsigned imat=0; imat<loader.materials.size(); imat++)
00465 {
00466 ref<Effect> effect = new Effect;
00467 mat_map.push_back(effect.get());
00468
00469
00470 effect->shader()->enable(EN_DEPTH_TEST);
00471
00472 effect->shader()->gocMaterial()->setAmbient( fvec4(loader.materials[ imat ].Ambient, 1.0f) );
00473 effect->shader()->gocMaterial()->setDiffuse( fvec4(loader.materials[ imat ].Diffuse, 1.0f) );
00474 effect->shader()->gocMaterial()->setEmission( fvec4(loader.materials[ imat ].Emission, 1.0f) );
00475 effect->shader()->gocMaterial()->setSpecular( fvec4(loader.materials[ imat ].Specular, 1.0f) );
00476 effect->shader()->gocMaterial()->setShininess( loader.materials[ imat ].Shininess );
00477 effect->shader()->gocMaterial()->setTransparency( loader.materials[ imat ].Trans );
00478
00479 if ( loader.materials[ imat ].Trans < 1.0f )
00480 {
00481 effect->shader()->enable(EN_CULL_FACE);
00482 effect->shader()->enable(EN_BLEND);
00483 effect->shader()->gocBlendFunc()->set(BF_SRC_ALPHA, BF_ONE_MINUS_SRC_ALPHA);
00484 }
00485 }
00486
00487
00488 for(unsigned imesh=0; imesh<loader.meshes.size(); imesh++)
00489 {
00490 if ( loader.meshes[imesh].Surface.empty() )
00491 continue;
00492
00493 ref<Actor> act = new Actor;
00494 act->setObjectName( loader.meshes[imesh].Name.toStdString().c_str() );
00495
00496 ref<Geometry> geom = new Geometry;
00497 geom->setObjectName( loader.meshes[imesh].Name.toStdString().c_str() );
00498
00499 ref<ArrayFloat3> verts = new ArrayFloat3;
00500 ref<ArrayFloat2> uv = new ArrayFloat2;
00501 ref<DrawElementsUInt> polys = new DrawElementsUInt;
00502 geom->drawCalls()->push_back( polys.get() );
00503 geom->setVertexArray( verts.get() );
00504 geom->setTexCoordArray(0, uv.get());
00505 act->setLod(0, geom.get());
00506
00507
00508 int mat_index = loader.meshes[imesh].Surface[0].materials;
00509
00510 act->setEffect( mat_map[ mat_index ].get() );
00511
00512
00513 int vert_count = 0;
00514 for(unsigned isurf=0; isurf<loader.meshes[imesh].Surface.size(); isurf++)
00515 {
00516 if ( (loader.meshes[imesh].Surface[isurf].Flags & 0xF) != 0 )
00517 continue;
00518 for( int ivert=1; ivert<loader.meshes[imesh].Surface[isurf].VertCount-1; ivert++)
00519 for(int i=0; i<3; ++i)
00520 ++vert_count;
00521 }
00522
00523 verts->resize( vert_count );
00524 uv->resize( vert_count );
00525
00526 if (!vert_count)
00527 continue;
00528
00529
00530
00531 res_db->resources().push_back( act.get() );
00532 res_db->resources().push_back( geom.get() );
00533
00534
00535
00536
00537 polys->indexBuffer()->resize( vert_count );
00538
00539 int idx = 0;
00540 for(unsigned isurf=0; isurf<loader.meshes[imesh].Surface.size(); isurf++)
00541 {
00542 if ( (loader.meshes[imesh].Surface[isurf].Flags & 0xF) != 0 )
00543 continue;
00544 VL_CHECK( loader.meshes[imesh].Surface[isurf].VertCount >= 3 )
00545 for( int ivert=1; ivert<loader.meshes[imesh].Surface[isurf].VertCount-1; ivert++)
00546 {
00547 int vert_idx[] = { 0, ivert, ivert+1 };
00548 for(int i=0; i<3; ++i, idx++)
00549 {
00550
00551 polys->indexBuffer()->at( idx ) = idx;
00552 int iv = loader.meshes[imesh].Surface[isurf].Vertex[ vert_idx[i] ].Vert;
00553 verts->at( idx ) = loader.meshes[imesh].Vert[ iv ];
00554 uv->at( idx ) = fvec2(loader.meshes[imesh].Surface[isurf].Vertex[ vert_idx[i] ].U, loader.meshes[imesh].Surface[isurf].Vertex[ vert_idx[i] ].V);
00555 }
00556 }
00557 }
00558
00559
00560
00561
00562 geom->transform( (mat4)loader.meshes[imesh].Matrix );
00563
00564
00565
00566
00567
00568
00569 if ( loader.meshes[imesh].Texture.length() )
00570 {
00571 ref<Texture> texture = new Texture;
00572
00573 String tex_path = loader.meshes[imesh].Texture;
00574 ref<VirtualFile> tex_file = defFileSystem()->locateFile(tex_path,file->path().extractPath());
00575 if (tex_file)
00576 tex_path = tex_file->path();
00577 texture->prepareTexture2D(tex_path, TF_RGBA);
00578 act->effect()->shader()->gocTextureSampler(0)->setTexture( texture.get() );
00579 }
00580
00581
00582 if ( (loader.meshes[imesh].Surface[0].Flags & 0x20) )
00583 {
00584 act->effect()->shader()->gocLightModel()->setTwoSide(true);
00585
00586 }
00587
00588 }
00589
00590 return res_db;
00591 }
00592