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 "io3DS.hpp"
00033 #include <vlGraphics/Effect.hpp>
00034 #include <vlGraphics/Geometry.hpp>
00035 #include <vlGraphics/Actor.hpp>
00036 #include <vlGraphics/Texture.hpp>
00037 #include <vlCore/Image.hpp>
00038 #include <vlGraphics/Camera.hpp>
00039 #include <vlCore/Time.hpp>
00040 #include <vlCore/Log.hpp>
00041 #include <vlCore/Say.hpp>
00042 #include <vlCore/LoadWriterManager.hpp>
00043 #include <vlCore/VisualizationLibrary.hpp>
00044 #include <vlCore/FileSystem.hpp>
00045 #include <set>
00046
00047 using namespace vl;
00048
00049 #define ID_3D_EDITOR_CHUNK 0x3D3D
00050 #define ID_MAIN_CHUNK 0x4D4D
00051 #define ID_3DS_VERSION 0x0002
00052 #define ID_OBJECT_BLOCK 0x4000
00053 #define ID_MATERIAL_BLOCK 0xAFFF
00054 #define ID_COLOR_F 0x0010
00055 #define ID_COLOR_24 0x0011
00056 #define ID_LIN_COLOR_24 0x0012
00057 #define ID_LIN_COLOR_F 0x0013
00058 #define ID_INT_PERCENTAGE 0x0030
00059 #define ID_FLOAT_PERCENTAGE 0x0031
00060 #define ID_MATERIAL_NAME 0xA000
00061 #define ID_MAT_AMBIENT 0xA010
00062 #define ID_MAT_DIFFUSE 0xA020
00063 #define ID_MAT_SPECULAR 0xA030
00064 #define ID_MAT_SHININESS_PERCENT 0xA040
00065 #define ID_MAT_SHININESS_STRENGTH_PERCENT 0xA041
00066 #define ID_MAT_TRANSPARENCY 0xA050
00067 #define ID_MAT_TWO_SIDE 0xA081
00068 #define ID_MAT_TEXMAP 0xA200
00069 #define ID_MAT_TEXMAP2 0xA33A
00070 #define ID_MAT_MAPNAME 0xA300
00071 #define ID_MAT_MAP_TILING 0xA351
00072 #define ID_MAT_USCALE 0xA354
00073 #define ID_MAT_VSCALE 0xA356
00074 #define ID_MAT_UOFFSET 0xA358
00075 #define ID_MAT_VOFFSET 0xA35A
00076 #define ID_MAT_MAP_ROTATION 0xA35C
00077 #define ID_TRIANGULAR_MESH 0x4100
00078 #define ID_LOCAL_COORDS_SYSTEM 0x4160
00079 #define ID_MAPPING_COORDS 0x4140
00080 #define ID_SMOOTHING_GROUP_LIST 0x4150
00081 #define ID_FACE_MATERIAL_LIST 0x4130
00082 #define ID_FACE_LIST 0x4120
00083 #define ID_VERTEX_LIST 0x4110
00084 #define ID_HIERARCHY 0x4F00
00085 #define ID_PARENT_OBJECT 0x4F10
00086 #define ID_PIVOT_OBJECT 0x4F20
00087 #define ID_PIVOT_LIMITS 0x4F30
00088 #define ID_PIVOT_ORDER 0x4F40
00089 #define ID_XLATE_RANGE 0x4F50
00090
00091 #define ID_KEYFRAMER_CHUNK 0xB000
00092 #define ID_KEYF_OBJDES 0xB002 // Mesh Information Block
00093 #define ID_KEYF_OBJHIERARCH 0xB010 // Object Name And Hierarchy
00094 #define ID_KEYF_OBJPIVOT 0xB013 // Object Pivot Point
00095 #define ID_KEYF_POSITION_TRACK 0xB020 // Position Track + Pivot
00096 #define ID_KEYF_ROTATION_TRACK 0xB021 // Rotation Track
00097 #define ID_KEYF_SCALE_TRACK 0xB022 // Scale Track
00098 #define ID_KEYF_NODE_ID 0xB030 // Node ID
00099 #define ID_KEY_SPOTLIGHT_NODE_TAG 0xB007 // Spot Light Information Block
00100 #define ID_KEY_FRAMES_START_END 0xB008 // Frames (Start and End)
00101
00102
00103
00104
00105 A3DSLoader::A3DSLoader()
00106 {
00107 }
00108
00109 fvec3 A3DSLoader::readVec3()
00110 {
00111 fvec3 v;
00112 v.x() = mInputFile->readFloat();
00113 v.y() = mInputFile->readFloat();
00114 v.z() = mInputFile->readFloat();
00115 return v;
00116 }
00117
00118 fvec3 A3DSLoader::readColByte3()
00119 {
00120 fvec3 c;
00121 c.r() = mInputFile->readUInt8() / 255.0f;
00122 c.g() = mInputFile->readUInt8() / 255.0f;
00123 c.b() = mInputFile->readUInt8() / 255.0f;
00124 return c;
00125 }
00126
00127 fvec3 A3DSLoader::readColFloat3()
00128 {
00129 fvec3 c;
00130 c.r() = mInputFile->readFloat();
00131 c.g() = mInputFile->readFloat();
00132 c.b() = mInputFile->readFloat();
00133 return c;
00134 }
00135
00136 String A3DSLoader::readLine()
00137 {
00138 std::vector<unsigned char> str;
00139 unsigned char b;
00140 do {
00141 b= mInputFile->readUInt8();
00142 str.push_back(b);
00143 } while(b);
00144
00145 return (char*)&str[0];
00146 }
00147
00148 float A3DSLoader::readWordPercent()
00149 {
00150 return mInputFile->readUInt16() / 100.0f;
00151 }
00152
00153 float A3DSLoader::readFloatPercent()
00154 {
00155 return mInputFile->readFloat() / 100.0f;
00156 }
00157
00158 void A3DSLoader::readChunk()
00159 {
00160 mChunkId = mInputFile->readUInt16();
00161 mChunkLen = mInputFile->readUInt32();
00162 }
00163
00164 bool A3DSLoader::skipChunk()
00165 {
00166 mCorrupted |= !mInputFile->seekCur( mChunkLen - 6 );
00167 if (mCorrupted)
00168 {
00169 Log::error("3ds file is corrupted.\n");
00170 mObjects.clear();
00171 mMaterials.clear();
00172 }
00173
00174 return !mCorrupted;
00175 }
00176
00177 void A3DSLoader::read_3D_EDITOR_CHUNK()
00178 {
00179 long long chunk_end = (int)mInputFile->position() + mChunkLen - 6;
00180 if ( chunk_end > mInputFile->size() )
00181 {
00182 Log::error("3ds file is corrupted.\n");
00183 mCorrupted = true;
00184 mObjects.clear();
00185 mMaterials.clear();
00186 chunk_end = mInputFile->size();
00187 }
00188
00189 while(mInputFile->position() < chunk_end && !mCorrupted)
00190 {
00191 readChunk();
00192
00193 switch(mChunkId)
00194 {
00195 case ID_OBJECT_BLOCK:
00196 read_OBJECT_BLOCK();
00197 break;
00198
00199 case ID_MATERIAL_BLOCK:
00200 read_MATERIAL_BLOCK();
00201 break;
00202
00203 default:
00204 skipChunk();
00205 }
00206 }
00207 }
00208
00209 fvec3 A3DSLoader::readColChunk()
00210 {
00211 long long chunk_end = (int)mInputFile->position() + mChunkLen - 6;
00212 if ( chunk_end > mInputFile->size() )
00213 {
00214 Log::error("3ds file is corrupted.\n");
00215 mCorrupted = true;
00216 mObjects.clear();
00217 mMaterials.clear();
00218 chunk_end = mInputFile->size();
00219 }
00220
00221 fvec3 color;
00222 while( mInputFile->position() < chunk_end && !mCorrupted )
00223 {
00224 readChunk();
00225 switch(mChunkId)
00226 {
00227 case ID_COLOR_F:
00228 color = readColFloat3();
00229 break;
00230 case ID_COLOR_24:
00231 color = readColByte3();
00232 break;
00233
00234 case ID_LIN_COLOR_24:
00235 readColByte3();
00236 break;
00237
00238 case ID_LIN_COLOR_F:
00239 readColFloat3();
00240 break;
00241 }
00242 }
00243 return color;
00244 }
00245
00246 float A3DSLoader::readPercentChunk()
00247 {
00248 readChunk();
00249 float perc=0;
00250 switch(mChunkId)
00251 {
00252 case ID_INT_PERCENTAGE:
00253 perc = readWordPercent();
00254 break;
00255 case ID_FLOAT_PERCENTAGE:
00256 perc = readFloatPercent();
00257 break;
00258 }
00259 return perc;
00260 }
00261
00262
00263 void A3DSLoader::read_MATERIAL_BLOCK()
00264 {
00265 long long chunk_end = (int)mInputFile->position() + mChunkLen - 6;
00266 if ( chunk_end > mInputFile->size() )
00267 {
00268 Log::error("3ds file is corrupted.\n");
00269 mCorrupted = true;
00270 mObjects.clear();
00271 mMaterials.clear();
00272 chunk_end = mInputFile->size();
00273 }
00274
00275
00276
00277 A3DSMaterial mat;
00278
00279 while(mInputFile->position() < chunk_end && !mCorrupted)
00280 {
00281 readChunk();
00282
00283 switch(mChunkId)
00284 {
00285
00286 case ID_MATERIAL_NAME:
00287 {
00288 mat.mMaterialName = readLine();
00289 }
00290 break;
00291
00292 case ID_MAT_AMBIENT:
00293 {
00294 mat.mAmbient = readColChunk();
00295 }
00296 break;
00297
00298 case ID_MAT_DIFFUSE:
00299 {
00300 mat.mDiffuse = readColChunk();
00301 }
00302 break;
00303
00304 case ID_MAT_SPECULAR:
00305 {
00306 mat.mSpecular = readColChunk();
00307 }
00308 break;
00309
00310 case ID_MAT_SHININESS_PERCENT:
00311 {
00312 mat.mShininess = readPercentChunk();
00313 }
00314 break;
00315
00316 case ID_MAT_SHININESS_STRENGTH_PERCENT:
00317 {
00318 mat.mShininessStrength = readPercentChunk();
00319 }
00320 break;
00321
00322 case ID_MAT_TRANSPARENCY:
00323 {
00324 mat.mTransparency = readPercentChunk();
00325 }
00326 break;
00327
00328 case ID_MAT_TWO_SIDE:
00329 {
00330 mat.mDoubleSided = true;
00331 }
00332
00333 case ID_MAT_TEXMAP:
00334 {
00335 mat.mTexture1 = readMapChunk();
00336 }
00337 break;
00338
00339 case ID_MAT_TEXMAP2:
00340 {
00341 mat.mTexture2 = readMapChunk();
00342 }
00343 break;
00344
00345 default:
00346 skipChunk();
00347 }
00348 }
00349 mMaterials.push_back(mat);
00350 }
00351
00352
00353 A3DSTexture A3DSLoader::readMapChunk()
00354 {
00355 long long chunk_end = (int)mInputFile->position() + mChunkLen - 6;
00356 if ( chunk_end > mInputFile->size() )
00357 {
00358 Log::error("3ds file is corrupted.\n");
00359 mCorrupted = true;
00360 mObjects.clear();
00361 mMaterials.clear();
00362 chunk_end = mInputFile->size();
00363 }
00364
00365
00366
00367 A3DSTexture tex;
00368
00369 while(mInputFile->position() < chunk_end && !mCorrupted)
00370 {
00371 readChunk();
00372
00373 switch(mChunkId)
00374 {
00375
00376 case ID_MAT_MAPNAME:
00377 {
00378 tex.mFileName = readLine();
00379
00380 ref<VirtualFile> file = vl::defFileSystem()->locateFile(tex.mFileName, mInputFile->path().extractPath());
00381 if (file)
00382 tex.mFileName = file->path();
00383
00384 }
00385 break;
00386
00387 case ID_MAT_MAP_TILING:
00388 {
00389 unsigned short flags = mInputFile->readUInt16();
00390 int bit[10] = { flags&(1<<0), flags&(1<<1), flags&(1<<2), flags&(1<<3),
00391 flags&(1<<4), flags&(1<<5), flags&(1<<6), flags&(1<<7),
00392 flags&(1<<8), flags&(1<<9) };
00393 tex.mOpt_tile = (!bit[4] && !bit[0]) || (!bit[4] && bit[1]);
00394 tex.mOpt_decal = (bit[4] && bit[0]) || (!bit[4] && bit[1]);
00395 tex.mOpt_mirror = bit[1]?true:false;
00396 tex.mOpt_negative = bit[3]?true:false;
00397 tex.mOpt_summed_area = bit[5]?true:false;
00398 tex.mOpt_use_alpha = bit[6]?true:false;
00399 tex.mOpt_one_channel_tint = bit[7]?true:false;
00400 tex.mOpt_ignore_alpha = bit[8]?true:false;
00401 tex.mOpt_rgb_tint = bit[9]?true:false;
00402 }
00403 break;
00404
00405 case ID_MAT_USCALE:
00406 {
00407 tex.mUScale = mInputFile->readFloat();
00408 }
00409 break;
00410
00411 case ID_MAT_VSCALE:
00412 {
00413 tex.mVScale = mInputFile->readFloat();
00414 }
00415 break;
00416
00417 case ID_MAT_UOFFSET:
00418 {
00419 tex.mUOffset = mInputFile->readFloat();
00420 }
00421 break;
00422
00423 case ID_MAT_VOFFSET:
00424 {
00425 tex.mVOffset = mInputFile->readFloat();
00426 }
00427 break;
00428
00429 case ID_MAT_MAP_ROTATION:
00430 {
00431 tex.mRotation = mInputFile->readFloat();
00432 }
00433 break;
00434 default:
00435 skipChunk();
00436 }
00437 }
00438 return tex;
00439 }
00440
00441
00442 void A3DSLoader::read_OBJECT_BLOCK()
00443 {
00444 long long chunk_end = (int)mInputFile->position() + mChunkLen - 6;
00445 if ( chunk_end > mInputFile->size() )
00446 {
00447 Log::error("3ds file is corrupted.\n");
00448 mCorrupted = true;
00449 mObjects.clear();
00450 mMaterials.clear();
00451 chunk_end = mInputFile->size();
00452 }
00453
00454
00455
00456 mObjects.push_back( A3DSObject() );
00457 mObjects.back().mObjName = readLine();
00458
00459 while(mInputFile->position() < chunk_end && !mCorrupted)
00460 {
00461 readChunk();
00462
00463 switch(mChunkId)
00464 {
00465 case ID_TRIANGULAR_MESH:
00466 read_TRIANGULAR_MESH();
00467 break;
00468
00469 default:
00470
00471 mObjects.pop_back();
00472 skipChunk();
00473 }
00474 }
00475 }
00476
00477
00478 void A3DSLoader::read_TRIANGULAR_MESH()
00479 {
00480 long long chunk_end = (int)mInputFile->position() + mChunkLen - 6;
00481 if ( chunk_end > mInputFile->size() )
00482 {
00483 Log::error("3ds file is corrupted.\n");
00484 mCorrupted = true;
00485 mObjects.clear();
00486 mMaterials.clear();
00487 chunk_end = mInputFile->size();
00488 }
00489
00490
00491
00492 while(mInputFile->position() < chunk_end && !mCorrupted)
00493 {
00494 readChunk();
00495
00496 switch(mChunkId)
00497 {
00498
00499 case ID_VERTEX_LIST:
00500 {
00501 unsigned short vertc = mInputFile->readUInt16();
00502 if (!vertc)
00503 break;
00504 mObjects.back().mVertices.resize(vertc);
00505 #if 1
00506 std::vector<fvec3> verts;
00507 verts.resize(vertc);
00508 mInputFile->read(&verts[0], 3*vertc*sizeof(float));
00509 for(unsigned short i=0; i<vertc; ++i)
00510 mObjects.back().mVertices[i].mPos = verts[i];
00511 #else
00512 for(unsigned short i=0; i<vertc; ++i)
00513 mObjects.back().mVertices[i].mPos = readVec3();
00514 #endif
00515 }
00516 break;
00517
00518 case ID_FACE_LIST:
00519 {
00520 unsigned short facec= mInputFile->readUInt16();
00521 if (!facec)
00522 break;
00523 mObjects.back().mFaceList.resize(facec);
00524 #if 1
00525 std::vector<unsigned short> faces;
00526 faces.resize(facec*4);
00527 mInputFile->readUInt16(&faces[0], faces.size());
00528 for(unsigned short i=0; i<facec; ++i)
00529 {
00530 mObjects.back().mFaceList[i].mA = faces[i*4+0];
00531 mObjects.back().mFaceList[i].mB = faces[i*4+1];
00532 mObjects.back().mFaceList[i].mC = faces[i*4+2];
00533 mObjects.back().mFaceList[i].mFlags = faces[i*4+3];
00534 }
00535 #else
00536 for(unsigned short i=0; i<facec; ++i)
00537 {
00538 mObjects.back().mFaceList[i].a = mInputFile->readUInt16();
00539 mObjects.back().mFaceList[i].b = mInputFile->readUInt16();
00540 mObjects.back().mFaceList[i].c = mInputFile->readUInt16();
00541 mObjects.back().mFaceList[i].flags = mInputFile->readUInt16();
00542 }
00543 #endif
00544 }
00545 break;
00546
00547 case ID_FACE_MATERIAL_LIST:
00548 {
00549 String name = readLine();
00550 unsigned short facec = mInputFile->readUInt16();
00551 if (!facec)
00552 break;
00553 mObjects.back().mMatFaceMap.push_back(A3DSMaterialFaceMapping());
00554 mObjects.back().mMatFaceMap.back().mMaterialName = name;
00555 mObjects.back().mMatFaceMap.back().mMappedFace.resize(facec);
00556 #if 1
00557 mInputFile->readUInt16(&mObjects.back().mMatFaceMap.back().mMappedFace[0], facec);
00558 #else
00559 for(unsigned short i=0; i<facec; ++i)
00560 {
00561 unsigned short face = mInputFile->readUInt16();
00562 mObjects.back().mMatFaceMap.back().mMappedFace[i] = face;
00563 }
00564 #endif
00565 }
00566 break;
00567
00568 case ID_SMOOTHING_GROUP_LIST:
00569 {
00570 #if 1
00571 if (mObjects.back().mFaceList.empty())
00572 break;
00573 std::vector<unsigned int> group;
00574 group.resize(mObjects.back().mFaceList.size());
00575 mInputFile->readUInt32(&group[0], group.size());
00576 for(unsigned short i=0; i<mObjects.back().mFaceList.size(); ++i)
00577 mObjects.back().mFaceList[i].mSmoothingGroup = group[i];
00578 #else
00579 for(unsigned short i=0; i<mObjects.back().mFaceList.size(); ++i)
00580 mObjects.back().mFaceList[i].mSmoothingGroup = mInputFile->readUInt32();
00581 #endif
00582 }
00583 break;
00584
00585 case ID_MAPPING_COORDS:
00586 {
00587 unsigned short vertc = mInputFile->readUInt16();
00588 if(!vertc)
00589 break;
00590 mObjects.back().mVertices.resize(vertc);
00591 #if 1
00592 std::vector<fvec2> tuvs;
00593 tuvs.resize(vertc);
00594 mInputFile->read(&tuvs[0], 2*vertc*sizeof(float));
00595 for(unsigned short i=0; i<vertc; ++i)
00596 mObjects.back().mVertices[i].mUV = tuvs[i];
00597 #else
00598 for(unsigned short i=0; i<vertc; ++i)
00599 {
00600 fvec2 uv;
00601 uv.s() = mInputFile->readFloat();
00602 uv.t() = mInputFile->readFloat();
00603 mObjects.back().mVertices[i].mUV = uv;
00604 }
00605 #endif
00606 }
00607 break;
00608
00609 case ID_LOCAL_COORDS_SYSTEM:
00610 {
00611 fmat4 m;
00612
00613 fvec3 x,y,z,t;
00614 x = readVec3();
00615 y = readVec3();
00616 z = readVec3();
00617 t = readVec3();
00618 m.setX( x );
00619 m.setY( y );
00620 m.setZ( z );
00621 m.setT( t );
00622
00623 mObjects.back().mCoordSystem = m;
00624 }
00625 break;
00626
00627 default:
00628 skipChunk();
00629 }
00630 }
00631 }
00632
00633 bool A3DSLoader::parse3DS( VirtualFile* file )
00634 {
00635 mCorrupted = false;
00636 mInputFile = file;
00637 if ( !mInputFile->open(OM_ReadOnly) )
00638 {
00639 Log::print(Say("Could not open '%s'. \n") << mInputFile->path() );
00640 return false;
00641 }
00642
00643
00644 readChunk();
00645 if (mChunkId == ID_MAIN_CHUNK)
00646 readChunk();
00647 else
00648 {
00649 Log::error( Say("'%s' is not a valid 3DS file.\n") << mInputFile->path() );
00650
00651 }
00652
00653 do
00654 {
00655
00656 switch(mChunkId)
00657 {
00658 case ID_3DS_VERSION:
00659 {
00660 mInputFile->readUInt32();
00661 }
00662 break;
00663
00664
00665 case ID_3D_EDITOR_CHUNK:
00666 {
00667 read_3D_EDITOR_CHUNK();
00668 }
00669 break;
00670
00671 default:
00672 skipChunk();
00673 }
00674 readChunk();
00675 }
00676 while( !mInputFile->endOfFile() && !mCorrupted );
00677
00678 mInputFile->close();
00679 return !mCorrupted;
00680 }
00681
00682 ref<ResourceDatabase> vl::load3DS(const String& path)
00683 {
00684 ref<VirtualFile> file = defFileSystem()->locateFile(path);
00685
00686 if (file)
00687 return load3DS( file.get() );
00688 else
00689 {
00690 Log::error( Say("Could not locate '%s'.\n") << path );
00691 return NULL;
00692 }
00693 }
00694 ref<ResourceDatabase> vl::load3DS(VirtualFile* file)
00695 {
00696 if (!file)
00697 return NULL;
00698
00699 ref<ResourceDatabase> res_db = new ResourceDatabase;
00700
00701 A3DSLoader loader;
00702
00703 if (!loader.parse3DS(file))
00704 return NULL;
00705
00706 ref<Effect> default_effect = new Effect;
00707 res_db->resources().push_back(default_effect.get());
00708
00709 default_effect->setObjectName("3ds default effect");
00710 default_effect->shader()->enable(EN_DEPTH_TEST);
00711
00712
00713
00714 std::map< String, ref<Effect> > mat_map;
00715
00716 for(unsigned int iobj=0; iobj<loader.mObjects.size(); ++iobj)
00717 {
00718 if (loader.mObjects[iobj].mVertices.empty())
00719 continue;
00720
00721 if (loader.mObjects[iobj].mFaceList.empty())
00722 continue;
00723
00724
00725 for(unsigned imat_map=0; imat_map<loader.mObjects[iobj].mMatFaceMap.size() || (imat_map==0&&loader.mObjects[iobj].mMatFaceMap.empty()); ++imat_map)
00726 {
00727 int mat_index = -1;
00728
00729 if (!loader.mObjects[iobj].mMatFaceMap.empty())
00730 {
00731 for(unsigned imat=0; imat<loader.mMaterials.size(); ++imat)
00732 {
00733 if (loader.mObjects[iobj].mMatFaceMap[imat_map].mMaterialName == loader.mMaterials[imat].mMaterialName)
00734 {
00735 mat_index = imat;
00736 break;
00737 }
00738 }
00739 }
00740
00741 if (mat_index != -1)
00742 {
00743
00744 for(unsigned int iface=0; iface<loader.mObjects[iobj].mMatFaceMap[imat_map].mMappedFace.size(); iface++)
00745 {
00746 int face_index = loader.mObjects[iobj].mMatFaceMap[imat_map].mMappedFace[iface];
00747 loader.mObjects[iobj].mFaceList[face_index].mMaterialIndex = mat_index;
00748 }
00749 }
00750
00751 ref<Geometry> geom = new Geometry;
00752 ref<Actor> act = new Actor(geom.get());
00753 geom->setObjectName( loader.mObjects[iobj].mObjName.toStdString().c_str() );
00754 act ->setObjectName( loader.mObjects[iobj].mObjName.toStdString().c_str() );
00755
00756
00757
00758 std::set<A3DSVertex> vertex_set;
00759 std::vector<unsigned int> index_buffer;
00760 index_buffer.resize( 3 * loader.mObjects[iobj].mFaceList.size() );
00761 int index_counter = 0;
00762 for(unsigned int iface=0; iface<loader.mObjects[iobj].mFaceList.size(); iface++)
00763 {
00764 if ( loader.mObjects[iobj].mFaceList[iface].mMaterialIndex != mat_index )
00765 continue;
00766
00767 unsigned int vertidx[] =
00768 {
00769 loader.mObjects[iobj].mFaceList[iface].mA,
00770 loader.mObjects[iobj].mFaceList[iface].mB,
00771 loader.mObjects[iobj].mFaceList[iface].mC
00772 };
00773
00774 for(int iv=0; iv<3; ++iv)
00775 {
00776 A3DSVertex v;
00777 if (vertidx[iv]>=loader.mObjects[iobj].mVertices.size())
00778 {
00779 Log::error("index out of range, 3ds file is corrupted.\n");
00780 return NULL;
00781 }
00782 v = loader.mObjects[iobj].mVertices[ vertidx[iv] ];
00783 v.mSmoothingGroup = loader.mObjects[iobj].mFaceList[iface].mSmoothingGroup;
00784 std::set<A3DSVertex>::iterator it = vertex_set.find(v);
00785 if (it == vertex_set.end())
00786 {
00787 v.mIndex = index_counter;
00788 vertex_set.insert(v);
00789 index_counter ++;
00790 }
00791 else
00792 v = *it;
00793 index_buffer[iface*3+iv] = v.mIndex;
00794 }
00795 }
00796
00797 if (index_counter == 0)
00798 continue;
00799
00800
00801
00802 res_db->resources().push_back(geom.get());
00803 res_db->resources().push_back( act.get() );
00804
00805
00806
00807 ref<ArrayFloat3> vert_interf = new ArrayFloat3;
00808 ref<ArrayFloat2> tuvs_interf = new ArrayFloat2;
00809 geom->setVertexArray(vert_interf.get());
00810 geom->setTexCoordArray(0, tuvs_interf.get());
00811 vert_interf->resize( index_counter );
00812 tuvs_interf->resize( index_counter );
00813 for(std::set<A3DSVertex>::iterator ivert=vertex_set.begin(); ivert!=vertex_set.end(); ++ivert)
00814 {
00815 vert_interf->at(ivert->mIndex).x() = ivert->mPos.x();
00816 vert_interf->at(ivert->mIndex).y() = ivert->mPos.z();
00817 vert_interf->at(ivert->mIndex).z() =-ivert->mPos.y();
00818 tuvs_interf->at(ivert->mIndex) = ivert->mUV;
00819 }
00820
00821
00822
00823 ref<DrawElementsUInt> polys = new DrawElementsUInt;
00824 geom->drawCalls()->push_back( polys.get() );
00825 polys->indexBuffer()->resize( index_buffer.size() );
00826 VL_CHECK( polys->indexBuffer()->bytesUsed() == sizeof(index_buffer[0]) * index_buffer.size() )
00827 memcpy(polys->indexBuffer()->ptr(), &index_buffer[0], polys->indexBuffer()->bytesUsed());
00828
00829
00830
00831
00832
00833
00834
00835 if ( mat_index != -1 )
00836 {
00837 const String& mat_name = loader.mMaterials[mat_index].mMaterialName;
00838 if (mat_map[mat_name].get() == NULL)
00839 {
00840 mat_map[mat_name] = new Effect;
00841 res_db->resources().push_back(mat_map[mat_name].get());
00842
00843 mat_map[mat_name]->setObjectName(mat_name.toStdString().c_str());
00844
00845 float alpha = 1.0f - loader.mMaterials[mat_index].mTransparency;
00846 fvec4 ambient( loader.mMaterials[mat_index].mAmbient.r(), loader.mMaterials[mat_index].mAmbient.g(), loader.mMaterials[mat_index].mAmbient.b(), alpha );
00847 fvec4 diffuse( loader.mMaterials[mat_index].mDiffuse.r(), loader.mMaterials[mat_index].mDiffuse.g(), loader.mMaterials[mat_index].mDiffuse.b(), alpha );
00848 fvec4 specular( loader.mMaterials[mat_index].mSpecular.r(), loader.mMaterials[mat_index].mSpecular.g(), loader.mMaterials[mat_index].mSpecular.b(), alpha );
00849 specular *= loader.mMaterials[mat_index].mShininessStrength;
00850 mat_map[mat_name]->shader()->gocMaterial()->setAmbient( ambient );
00851 mat_map[mat_name]->shader()->gocMaterial()->setDiffuse( diffuse );
00852 mat_map[mat_name]->shader()->gocMaterial()->setSpecular( specular );
00853 mat_map[mat_name]->shader()->gocMaterial()->setShininess( loader.mMaterials[mat_index].mShininess * 128.0f );
00854
00855 mat_map[mat_name]->shader()->enable(EN_DEPTH_TEST);
00856
00857
00858 if (alpha<1.0f || loader.mMaterials[mat_index].mTexture1.mOpt_use_alpha)
00859 {
00860 mat_map[mat_name]->shader()->enable(EN_BLEND);
00861 mat_map[mat_name]->shader()->gocBlendFunc()->set(BF_SRC_ALPHA, BF_ONE_MINUS_SRC_ALPHA);
00862 }
00863
00864
00865
00866
00867 if ( !loader.mMaterials[mat_index].mTexture1.mFileName.empty() )
00868 {
00869 ref<Texture> texture = new Texture;
00870 texture->prepareTexture2D(loader.mMaterials[mat_index].mTexture1.mFileName, TF_RGBA);
00871 if (loader.mMaterials[mat_index].mTexture1.mOpt_tile)
00872 {
00873 texture->getTexParameter()->setWrapS(TPW_REPEAT);
00874 texture->getTexParameter()->setWrapT(TPW_REPEAT);
00875 texture->getTexParameter()->setWrapR(TPW_REPEAT);
00876 }
00877 else
00878 {
00879 texture->getTexParameter()->setWrapS(TPW_CLAMP);
00880 texture->getTexParameter()->setWrapT(TPW_CLAMP);
00881 texture->getTexParameter()->setWrapR(TPW_CLAMP);
00882 }
00883 mat_map[mat_name]->shader()->gocTextureSampler(0)->setTexture( texture.get() );
00884 }
00885 }
00886
00887 act->setEffect( mat_map[mat_name].get() );
00888 }
00889 else
00890 act->setEffect( default_effect.get() );
00891
00892
00893
00894
00895 }
00896 }
00897
00898 return res_db;
00899 }
00900