Visualization Library v1.0.3A lightweight C++ OpenGL middleware for 2D/3D graphics |
[Download] [Tutorials] [All Classes] [Grouped Classes] |
00001 /**************************************************************************************/ 00002 /* */ 00003 /* Visualization Library */ 00004 /* http://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 //-----------------------------------------------------------------------------