Visualization Library 2.0.0

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
io3DS.cpp
Go to the documentation of this file.
1 /**************************************************************************************/
2 /* */
3 /* Visualization Library */
4 /* http://visualizationlibrary.org */
5 /* */
6 /* Copyright (c) 2005-2020, Michele Bosi */
7 /* All rights reserved. */
8 /* */
9 /* Redistribution and use in source and binary forms, with or without modification, */
10 /* are permitted provided that the following conditions are met: */
11 /* */
12 /* - Redistributions of source code must retain the above copyright notice, this */
13 /* list of conditions and the following disclaimer. */
14 /* */
15 /* - Redistributions in binary form must reproduce the above copyright notice, this */
16 /* list of conditions and the following disclaimer in the documentation and/or */
17 /* other materials provided with the distribution. */
18 /* */
19 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */
20 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
21 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
22 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */
23 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
24 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
25 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
26 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
27 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
28 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
29 /* */
30 /**************************************************************************************/
31 
32 #include "io3DS.hpp"
33 #include <vlGraphics/Effect.hpp>
34 #include <vlGraphics/Geometry.hpp>
35 #include <vlGraphics/Actor.hpp>
36 #include <vlGraphics/Texture.hpp>
37 #include <vlCore/Image.hpp>
38 #include <vlGraphics/Camera.hpp>
39 #include <vlCore/Time.hpp>
40 #include <vlCore/Log.hpp>
41 #include <vlCore/Say.hpp>
44 #include <vlCore/FileSystem.hpp>
45 #include <set>
46 
47 using namespace vl;
48 
49 #define ID_3D_EDITOR_CHUNK 0x3D3D
50 #define ID_MAIN_CHUNK 0x4D4D
51 #define ID_3DS_VERSION 0x0002
52 #define ID_OBJECT_BLOCK 0x4000
53 #define ID_MATERIAL_BLOCK 0xAFFF
54 #define ID_COLOR_F 0x0010
55 #define ID_COLOR_24 0x0011
56 #define ID_LIN_COLOR_24 0x0012
57 #define ID_LIN_COLOR_F 0x0013
58 #define ID_INT_PERCENTAGE 0x0030
59 #define ID_FLOAT_PERCENTAGE 0x0031
60 #define ID_MATERIAL_NAME 0xA000
61 #define ID_MAT_AMBIENT 0xA010
62 #define ID_MAT_DIFFUSE 0xA020
63 #define ID_MAT_SPECULAR 0xA030
64 #define ID_MAT_SHININESS_PERCENT 0xA040
65 #define ID_MAT_SHININESS_STRENGTH_PERCENT 0xA041
66 #define ID_MAT_TRANSPARENCY 0xA050
67 #define ID_MAT_TWO_SIDE 0xA081
68 #define ID_MAT_TEXMAP 0xA200
69 #define ID_MAT_TEXMAP2 0xA33A
70 #define ID_MAT_MAPNAME 0xA300
71 #define ID_MAT_MAP_TILING 0xA351
72 #define ID_MAT_USCALE 0xA354
73 #define ID_MAT_VSCALE 0xA356
74 #define ID_MAT_UOFFSET 0xA358
75 #define ID_MAT_VOFFSET 0xA35A
76 #define ID_MAT_MAP_ROTATION 0xA35C
77 #define ID_TRIANGULAR_MESH 0x4100
78 #define ID_LOCAL_COORDS_SYSTEM 0x4160
79 #define ID_MAPPING_COORDS 0x4140
80 #define ID_SMOOTHING_GROUP_LIST 0x4150
81 #define ID_FACE_MATERIAL_LIST 0x4130
82 #define ID_FACE_LIST 0x4120
83 #define ID_VERTEX_LIST 0x4110
84 #define ID_HIERARCHY 0x4F00
85 #define ID_PARENT_OBJECT 0x4F10
86 #define ID_PIVOT_OBJECT 0x4F20
87 #define ID_PIVOT_LIMITS 0x4F30
88 #define ID_PIVOT_ORDER 0x4F40
89 #define ID_XLATE_RANGE 0x4F50
90 
91 #define ID_KEYFRAMER_CHUNK 0xB000
92  #define ID_KEYF_OBJDES 0xB002 // Mesh Information Block
93  #define ID_KEYF_OBJHIERARCH 0xB010 // Object Name And Hierarchy
94  #define ID_KEYF_OBJPIVOT 0xB013 // Object Pivot Point
95  #define ID_KEYF_POSITION_TRACK 0xB020 // Position Track + Pivot
96  #define ID_KEYF_ROTATION_TRACK 0xB021 // Rotation Track
97  #define ID_KEYF_SCALE_TRACK 0xB022 // Scale Track
98  #define ID_KEYF_NODE_ID 0xB030 // Node ID
99  #define ID_KEY_SPOTLIGHT_NODE_TAG 0xB007 // Spot Light Information Block
100  #define ID_KEY_FRAMES_START_END 0xB008 // Frames (Start and End)
101 
102 //-----------------------------------------------------------------------------
103 // A3DSLoader
104 //-----------------------------------------------------------------------------
106 {
107 }
108 //-----------------------------------------------------------------------------
110 {
111  fvec3 v;
112  v.x() = mInputFile->readFloat();
113  v.y() = mInputFile->readFloat();
114  v.z() = mInputFile->readFloat();
115  return v;
116 }
117 //-----------------------------------------------------------------------------
119 {
120  fvec3 c;
121  c.r() = mInputFile->readUInt8() / 255.0f;
122  c.g() = mInputFile->readUInt8() / 255.0f;
123  c.b() = mInputFile->readUInt8() / 255.0f;
124  return c;
125 }
126 //-----------------------------------------------------------------------------
128 {
129  fvec3 c;
130  c.r() = mInputFile->readFloat();
131  c.g() = mInputFile->readFloat();
132  c.b() = mInputFile->readFloat();
133  return c;
134 }
135 //-----------------------------------------------------------------------------
137 {
138  std::vector<unsigned char> str;
139  unsigned char b;
140  do {
141  b= mInputFile->readUInt8();
142  str.push_back(b);
143  } while(b);
144 
145  return (char*)&str[0];
146 }
147 //-----------------------------------------------------------------------------
149 {
150  return mInputFile->readUInt16() / 100.0f;
151 }
152 //-----------------------------------------------------------------------------
154 {
155  return mInputFile->readFloat() / 100.0f;
156 }
157 //-----------------------------------------------------------------------------
159 {
162 }
163 //-----------------------------------------------------------------------------
165 {
167  if (mCorrupted)
168  {
169  Log::error("3ds file is corrupted.\n");
170  mObjects.clear();
171  mMaterials.clear();
172  }
173 
174  return !mCorrupted;
175 }
176 //-----------------------------------------------------------------------------
178 {
179  long long chunk_end = (int)mInputFile->position() + mChunkLen - 6;
180  if ( chunk_end > mInputFile->size() )
181  {
182  Log::error("3ds file is corrupted.\n");
183  mCorrupted = true;
184  mObjects.clear();
185  mMaterials.clear();
186  chunk_end = mInputFile->size();
187  }
188 
189  while(mInputFile->position() < chunk_end && !mCorrupted)
190  {
191  readChunk();
192 
193  switch(mChunkId)
194  {
195  case ID_OBJECT_BLOCK:
197  break;
198 
199  case ID_MATERIAL_BLOCK:
201  break;
202 
203  default:
204  skipChunk();
205  }
206  }
207 }
208 //-----------------------------------------------------------------------------
210 {
211  long long chunk_end = (int)mInputFile->position() + mChunkLen - 6;
212  if ( chunk_end > mInputFile->size() )
213  {
214  Log::error("3ds file is corrupted.\n");
215  mCorrupted = true;
216  mObjects.clear();
217  mMaterials.clear();
218  chunk_end = mInputFile->size();
219  }
220 
221  fvec3 color;
222  while( mInputFile->position() < chunk_end && !mCorrupted )
223  {
224  readChunk();
225  switch(mChunkId)
226  {
227  case ID_COLOR_F:
228  color = readColFloat3();
229  break;
230  case ID_COLOR_24:
231  color = readColByte3();
232  break;
233  // skip gamma byte
234  case ID_LIN_COLOR_24:
235  readColByte3();
236  break;
237  // skip gamma float
238  case ID_LIN_COLOR_F:
239  readColFloat3();
240  break;
241  }
242  }
243  return color;
244 }
245 //-----------------------------------------------------------------------------
247 {
248  readChunk();
249  float perc=0;
250  switch(mChunkId)
251  {
252  case ID_INT_PERCENTAGE:
253  perc = readWordPercent();
254  break;
255  case ID_FLOAT_PERCENTAGE:
256  perc = readFloatPercent();
257  break;
258  }
259  return perc;
260 }
261 //-----------------------------------------------------------------------------
262 // materials
264 {
265  long long chunk_end = (int)mInputFile->position() + mChunkLen - 6;
266  if ( chunk_end > mInputFile->size() )
267  {
268  Log::error("3ds file is corrupted.\n");
269  mCorrupted = true;
270  mObjects.clear();
271  mMaterials.clear();
272  chunk_end = mInputFile->size();
273  }
274 
275  // unsigned int id = mChunkId;
276 
277  A3DSMaterial mat;
278 
279  while(mInputFile->position() < chunk_end && !mCorrupted)
280  {
281  readChunk();
282 
283  switch(mChunkId)
284  {
285  // Material name
286  case ID_MATERIAL_NAME:
287  {
288  mat.mMaterialName = readLine();
289  }
290  break;
291  // Ambient color
292  case ID_MAT_AMBIENT:
293  {
294  mat.mAmbient = readColChunk();
295  }
296  break;
297  // Diffuse color
298  case ID_MAT_DIFFUSE:
299  {
300  mat.mDiffuse = readColChunk();
301  }
302  break;
303  // Specular color
304  case ID_MAT_SPECULAR:
305  {
306  mat.mSpecular = readColChunk();
307  }
308  break;
309  // Shininess percent
311  {
313  }
314  break;
315  // Shininess strength percent
317  {
319  }
320  break;
321  // Transparency percent
322  case ID_MAT_TRANSPARENCY:
323  {
325  }
326  break;
327  // Double sided material
328  case ID_MAT_TWO_SIDE:
329  {
330  mat.mDoubleSided = true;
331  }
332  // Texture map 1
333  case ID_MAT_TEXMAP:
334  {
335  mat.mTexture1 = readMapChunk();
336  }
337  break;
338  // Texture map 2
339  case ID_MAT_TEXMAP2:
340  {
341  mat.mTexture2 = readMapChunk();
342  }
343  break;
344 
345  default:
346  skipChunk();
347  }
348  }
349  mMaterials.push_back(mat);
350 }
351 //-----------------------------------------------------------------------------
352 // A3DSObject Block
354 {
355  long long chunk_end = (int)mInputFile->position() + mChunkLen - 6;
356  if ( chunk_end > mInputFile->size() )
357  {
358  Log::error("3ds file is corrupted.\n");
359  mCorrupted = true;
360  mObjects.clear();
361  mMaterials.clear();
362  chunk_end = mInputFile->size();
363  }
364 
365  // unsigned int id = mChunkId;
366 
367  A3DSTexture tex;
368 
369  while(mInputFile->position() < chunk_end && !mCorrupted)
370  {
371  readChunk();
372 
373  switch(mChunkId)
374  {
375  // Map filename
376  case ID_MAT_MAPNAME:
377  {
378  tex.mFileName = readLine();
379  // locate the actual file
381  if (file)
382  tex.mFileName = file->path();
383 
384  }
385  break;
386  // Map options
387  case ID_MAT_MAP_TILING:
388  {
389  unsigned short flags = mInputFile->readUInt16();
390  int bit[10] = { flags&(1<<0), flags&(1<<1), flags&(1<<2), flags&(1<<3),
391  flags&(1<<4), flags&(1<<5), flags&(1<<6), flags&(1<<7),
392  flags&(1<<8), flags&(1<<9) };
393  tex.mOpt_tile = (!bit[4] && !bit[0]) || (!bit[4] && bit[1]);
394  tex.mOpt_decal = (bit[4] && bit[0]) || (!bit[4] && bit[1]);
395  tex.mOpt_mirror = bit[1]?true:false; // vc issues warnings otherwise
396  tex.mOpt_negative = bit[3]?true:false;
397  tex.mOpt_summed_area = bit[5]?true:false;
398  tex.mOpt_use_alpha = bit[6]?true:false;
399  tex.mOpt_one_channel_tint = bit[7]?true:false;
400  tex.mOpt_ignore_alpha = bit[8]?true:false;
401  tex.mOpt_rgb_tint = bit[9]?true:false;
402  }
403  break;
404  // U scale
405  case ID_MAT_USCALE:
406  {
407  tex.mUScale = mInputFile->readFloat();
408  }
409  break;
410  // V scale
411  case ID_MAT_VSCALE:
412  {
413  tex.mVScale = mInputFile->readFloat();
414  }
415  break;
416  // U offset
417  case ID_MAT_UOFFSET:
418  {
419  tex.mUOffset = mInputFile->readFloat();
420  }
421  break;
422  // V offset
423  case ID_MAT_VOFFSET:
424  {
425  tex.mVOffset = mInputFile->readFloat();
426  }
427  break;
428  // rotation
429  case ID_MAT_MAP_ROTATION:
430  {
431  tex.mRotation = mInputFile->readFloat();
432  }
433  break;
434  default:
435  skipChunk();
436  }
437  }
438  return tex;
439 }
440 //-----------------------------------------------------------------------------
441 // Object Block
443 {
444  long long chunk_end = (int)mInputFile->position() + mChunkLen - 6;
445  if ( chunk_end > mInputFile->size() )
446  {
447  Log::error("3ds file is corrupted.\n");
448  mCorrupted = true;
449  mObjects.clear();
450  mMaterials.clear();
451  chunk_end = mInputFile->size();
452  }
453 
454  // unsigned int id = mChunkId;
455 
456  mObjects.push_back( A3DSObject() );
457  mObjects.back().mObjName = readLine();
458 
459  while(mInputFile->position() < chunk_end && !mCorrupted)
460  {
461  readChunk();
462 
463  switch(mChunkId)
464  {
465  case ID_TRIANGULAR_MESH:
467  break;
468 
469  default:
470  // Reject lights and cameras
471  mObjects.pop_back();
472  skipChunk();
473  }
474  }
475 }
476 //-----------------------------------------------------------------------------
477 // Triangular mesh
479 {
480  long long chunk_end = (int)mInputFile->position() + mChunkLen - 6;
481  if ( chunk_end > mInputFile->size() )
482  {
483  Log::error("3ds file is corrupted.\n");
484  mCorrupted = true;
485  mObjects.clear();
486  mMaterials.clear();
487  chunk_end = mInputFile->size();
488  }
489 
490  // unsigned int id = mChunkId;
491 
492  while(mInputFile->position() < chunk_end && !mCorrupted)
493  {
494  readChunk();
495 
496  switch(mChunkId)
497  {
498  // Vertices list
499  case ID_VERTEX_LIST:
500  {
501  unsigned short vertc = mInputFile->readUInt16();
502  if (!vertc)
503  break;
504  mObjects.back().mVertices.resize(vertc);
505  #if 1
506  std::vector<fvec3> verts;
507  verts.resize(vertc);
508  mInputFile->read(&verts[0], 3*vertc*sizeof(float));
509  for(unsigned short i=0; i<vertc; ++i)
510  mObjects.back().mVertices[i].mPos = verts[i];
511  #else
512  for(unsigned short i=0; i<vertc; ++i)
513  mObjects.back().mVertices[i].mPos = readVec3();
514  #endif
515  }
516  break;
517  // Faces description
518  case ID_FACE_LIST:
519  {
520  unsigned short facec= mInputFile->readUInt16();
521  if (!facec)
522  break;
523  mObjects.back().mFaceList.resize(facec);
524  #if 1
525  std::vector<unsigned short> faces;
526  faces.resize(facec*4);
527  mInputFile->readUInt16(&faces[0], faces.size());
528  for(unsigned short i=0; i<facec; ++i)
529  {
530  mObjects.back().mFaceList[i].mA = faces[i*4+0];
531  mObjects.back().mFaceList[i].mB = faces[i*4+1];
532  mObjects.back().mFaceList[i].mC = faces[i*4+2];
533  mObjects.back().mFaceList[i].mFlags = faces[i*4+3];
534  }
535  #else
536  for(unsigned short i=0; i<facec; ++i)
537  {
538  mObjects.back().mFaceList[i].a = mInputFile->readUInt16();
539  mObjects.back().mFaceList[i].b = mInputFile->readUInt16();
540  mObjects.back().mFaceList[i].c = mInputFile->readUInt16();
541  mObjects.back().mFaceList[i].flags = mInputFile->readUInt16();
542  }
543  #endif
544  }
545  break;
546  // Face material list
548  {
549  String name = readLine();
550  unsigned short facec = mInputFile->readUInt16();
551  if (!facec)
552  break;
553  mObjects.back().mMatFaceMap.push_back(A3DSMaterialFaceMapping());
554  mObjects.back().mMatFaceMap.back().mMaterialName = name;
555  mObjects.back().mMatFaceMap.back().mMappedFace.resize(facec);
556  #if 1
557  mInputFile->readUInt16(&mObjects.back().mMatFaceMap.back().mMappedFace[0], facec);
558  #else
559  for(unsigned short i=0; i<facec; ++i)
560  {
561  unsigned short face = mInputFile->readUInt16();
562  mObjects.back().mMatFaceMap.back().mMappedFace[i] = face;
563  }
564  #endif
565  }
566  break;
567  // Smoothing group list
569  {
570  #if 1
571  if (mObjects.back().mFaceList.empty())
572  break;
573  std::vector<unsigned int> group;
574  group.resize(mObjects.back().mFaceList.size());
575  mInputFile->readUInt32(&group[0], group.size());
576  for(unsigned short i=0; i<mObjects.back().mFaceList.size(); ++i)
577  mObjects.back().mFaceList[i].mSmoothingGroup = group[i];
578  #else
579  for(unsigned short i=0; i<mObjects.back().mFaceList.size(); ++i)
580  mObjects.back().mFaceList[i].mSmoothingGroup = mInputFile->readUInt32();
581  #endif
582  }
583  break;
584  // Mapping coordinates
585  case ID_MAPPING_COORDS:
586  {
587  unsigned short vertc = mInputFile->readUInt16();
588  if(!vertc)
589  break;
590  mObjects.back().mVertices.resize(vertc);
591  #if 1
592  std::vector<fvec2> tuvs;
593  tuvs.resize(vertc);
594  mInputFile->read(&tuvs[0], 2*vertc*sizeof(float));
595  for(unsigned short i=0; i<vertc; ++i)
596  mObjects.back().mVertices[i].mUV = tuvs[i];
597  #else
598  for(unsigned short i=0; i<vertc; ++i)
599  {
600  fvec2 uv;
601  uv.s() = mInputFile->readFloat();
602  uv.t() = mInputFile->readFloat(); // 1 - mInputFile->readFloat(); ? see also mapping flags
603  mObjects.back().mVertices[i].mUV = uv;
604  }
605  #endif
606  }
607  break;
608  // Local coordinates
610  {
611  fmat4 m;
612 
613  fvec3 x,y,z,t;
614  x = readVec3();
615  y = readVec3();
616  z = readVec3();
617  t = readVec3();
618  m.setX( x );
619  m.setY( y );
620  m.setZ( z );
621  m.setT( t );
622 
623  mObjects.back().mCoordSystem = m;
624  }
625  break;
626 
627  default:
628  skipChunk();
629  }
630  }
631 }
632 //-----------------------------------------------------------------------------
634 {
635  mCorrupted = false;
636  mInputFile = file;
637  if ( !mInputFile->open(OM_ReadOnly) )
638  {
639  Log::print(Say("Could not open '%s'. \n") << mInputFile->path() );
640  return false;
641  }
642 
643  // Main 3DS Chunk
644  readChunk();
645  if (mChunkId == ID_MAIN_CHUNK)
646  readChunk();
647  else
648  {
649  Log::error( Say("'%s' is not a valid 3DS file.\n") << mInputFile->path() );
650  // will try to use the chunk we just read
651  }
652 
653  do
654  {
655  // Inside main
656  switch(mChunkId)
657  {
658  case ID_3DS_VERSION: // 3DS Version
659  {
660  /*unsigned int version =*/ mInputFile->readUInt32();
661  }
662  break;
663 
664  // 3D Editor
665  case ID_3D_EDITOR_CHUNK:
666  {
668  }
669  break;
670 
671  default:
672  skipChunk();
673  }
674  readChunk();
675  }
676  while( !mInputFile->endOfFile() && !mCorrupted );
677 
678  mInputFile->close();
679  return !mCorrupted;
680 }
681 //-----------------------------------------------------------------------------
683 {
684  ref<VirtualFile> file = defFileSystem()->locateFile(path);
685 
686  if (file)
687  return load3DS( file.get() );
688  else
689  {
690  Log::error( Say("Could not locate '%s'.\n") << path );
691  return NULL;
692  }
693 }
695 {
696  if (!file)
697  return NULL;
698 
700 
701  A3DSLoader loader;
702  /*bool force_double_face = false;*/
703  if (!loader.parse3DS(file))
704  return NULL;
705 
706  ref<Effect> default_effect = new Effect;
707  res_db->resources().push_back(default_effect.get());
708 
709  default_effect->setObjectName("3ds default effect");
710  default_effect->shader()->enable(EN_DEPTH_TEST);
711  /*default_effect->shader()->gocLightModel()->setTwoSide(true);*/
712  /* default_effect->shader()->disable(EN_CULL_FACE); */
713 
714  std::map< String, ref<Effect> > mat_map;
715 
716  for(unsigned int iobj=0; iobj<loader.mObjects.size(); ++iobj)
717  {
718  if (loader.mObjects[iobj].mVertices.empty())
719  continue;
720 
721  if (loader.mObjects[iobj].mFaceList.empty())
722  continue;
723 
724  // create a Geometry for each material group
725  for(unsigned imat_map=0; imat_map<loader.mObjects[iobj].mMatFaceMap.size() || (imat_map==0&&loader.mObjects[iobj].mMatFaceMap.empty()); ++imat_map)
726  {
727  int mat_index = -1;
728 
729  if (!loader.mObjects[iobj].mMatFaceMap.empty())
730  {
731  for(unsigned imat=0; imat<loader.mMaterials.size(); ++imat)
732  {
733  if (loader.mObjects[iobj].mMatFaceMap[imat_map].mMaterialName == loader.mMaterials[imat].mMaterialName)
734  {
735  mat_index = imat;
736  break;
737  }
738  }
739  }
740 
741  if (mat_index != -1)
742  {
743  // assign material to mObjects
744  for(unsigned int iface=0; iface<loader.mObjects[iobj].mMatFaceMap[imat_map].mMappedFace.size(); iface++)
745  {
746  int face_index = loader.mObjects[iobj].mMatFaceMap[imat_map].mMappedFace[iface];
747  loader.mObjects[iobj].mFaceList[face_index].mMaterialIndex = mat_index;
748  }
749  }
750 
751  ref<Geometry> geom = new Geometry;
752  ref<Actor> act = new Actor(geom.get());
753  geom->setObjectName( loader.mObjects[iobj].mObjName.toStdString().c_str() );
754  act ->setObjectName( loader.mObjects[iobj].mObjName.toStdString().c_str() );
755 
756  // builds the vertex sets: a vertex belongs to a single group
757 
758  std::set<A3DSVertex> vertex_set;
759  std::vector<unsigned int> index_buffer;
760  index_buffer.resize( 3 * loader.mObjects[iobj].mFaceList.size() );
761  int index_counter = 0;
762  for(unsigned int iface=0; iface<loader.mObjects[iobj].mFaceList.size(); iface++)
763  {
764  if ( loader.mObjects[iobj].mFaceList[iface].mMaterialIndex != mat_index )
765  continue;
766 
767  unsigned int vertidx[] =
768  {
769  loader.mObjects[iobj].mFaceList[iface].mA,
770  loader.mObjects[iobj].mFaceList[iface].mB,
771  loader.mObjects[iobj].mFaceList[iface].mC
772  };
773 
774  for(int iv=0; iv<3; ++iv)
775  {
776  A3DSVertex v;
777  if (vertidx[iv]>=loader.mObjects[iobj].mVertices.size())
778  {
779  Log::error("index out of range, 3ds file is corrupted.\n");
780  return NULL;
781  }
782  v = loader.mObjects[iobj].mVertices[ vertidx[iv] ];
783  v.mSmoothingGroup = loader.mObjects[iobj].mFaceList[iface].mSmoothingGroup;
784  std::set<A3DSVertex>::iterator it = vertex_set.find(v);
785  if (it == vertex_set.end())
786  {
787  v.mIndex = index_counter;
788  vertex_set.insert(v);
789  index_counter ++;
790  }
791  else
792  v = *it;
793  index_buffer[iface*3+iv] = v.mIndex;
794  }
795  }
796 
797  if (index_counter == 0)
798  continue;
799 
800  // add after we are sure the geometry has content
801 
802  res_db->resources().push_back(geom.get());
803  res_db->resources().push_back( act.get() );
804 
805  // dump vertices and uv
806 
807  ref<ArrayFloat3> vert_interf = new ArrayFloat3;
808  ref<ArrayFloat2> tuvs_interf = new ArrayFloat2;
809  geom->setVertexArray(vert_interf.get());
810  geom->setTexCoordArray(0, tuvs_interf.get());
811  vert_interf->resize( index_counter );
812  tuvs_interf->resize( index_counter );
813  for(std::set<A3DSVertex>::iterator ivert=vertex_set.begin(); ivert!=vertex_set.end(); ++ivert)
814  {
815  vert_interf->at(ivert->mIndex).x() = ivert->mPos.x();
816  vert_interf->at(ivert->mIndex).y() = ivert->mPos.z();
817  vert_interf->at(ivert->mIndex).z() =-ivert->mPos.y();
818  tuvs_interf->at(ivert->mIndex) = ivert->mUV;
819  }
820 
821  // dump indices
822 
824  geom->drawCalls().push_back( polys.get() );
825  polys->indexBuffer()->resize( index_buffer.size() );
826  VL_CHECK( polys->indexBuffer()->bytesUsed() == sizeof(index_buffer[0]) * index_buffer.size() )
827  memcpy(polys->indexBuffer()->ptr(), &index_buffer[0], polys->indexBuffer()->bytesUsed());
828 
829  // matrix
830 
831  // we still have problems when the pivots are not centered on the object
832 
833  // dump materials
834 
835  if ( mat_index != -1 )
836  {
837  const String& mat_name = loader.mMaterials[mat_index].mMaterialName;
838  if (mat_map[mat_name].get() == NULL)
839  {
840  mat_map[mat_name] = new Effect;
841  res_db->resources().push_back(mat_map[mat_name].get());
842 
843  mat_map[mat_name]->setObjectName(mat_name.toStdString().c_str());
844 
845  float alpha = 1.0f - loader.mMaterials[mat_index].mTransparency;
846  fvec4 ambient( loader.mMaterials[mat_index].mAmbient.r(), loader.mMaterials[mat_index].mAmbient.g(), loader.mMaterials[mat_index].mAmbient.b(), alpha );
847  fvec4 diffuse( loader.mMaterials[mat_index].mDiffuse.r(), loader.mMaterials[mat_index].mDiffuse.g(), loader.mMaterials[mat_index].mDiffuse.b(), alpha );
848  fvec4 specular( loader.mMaterials[mat_index].mSpecular.r(), loader.mMaterials[mat_index].mSpecular.g(), loader.mMaterials[mat_index].mSpecular.b(), alpha );
849  specular *= loader.mMaterials[mat_index].mShininessStrength;
850  mat_map[mat_name]->shader()->gocMaterial()->setAmbient( ambient );
851  mat_map[mat_name]->shader()->gocMaterial()->setDiffuse( diffuse );
852  mat_map[mat_name]->shader()->gocMaterial()->setSpecular( specular );
853  mat_map[mat_name]->shader()->gocMaterial()->setShininess( loader.mMaterials[mat_index].mShininess * 128.0f );
854 
855  mat_map[mat_name]->shader()->enable(EN_DEPTH_TEST);
856  /* mat_map[mat_name]->shader()->disable(EN_CULL_FACE); */
857 
858  if (alpha<1.0f || loader.mMaterials[mat_index].mTexture1.mOpt_use_alpha)
859  {
860  mat_map[mat_name]->shader()->enable(EN_BLEND);
861  mat_map[mat_name]->shader()->gocBlendFunc()->set(BF_SRC_ALPHA, BF_ONE_MINUS_SRC_ALPHA);
862  }
863  /*if ( loader.mMaterials[mat_index].mDoubleSided || force_double_face )
864  {
865  mat_map[mat_name]->shader()->gocLightModel()->setTwoSide(true);
866  }*/
867  if ( !loader.mMaterials[mat_index].mTexture1.mFileName.empty() )
868  {
869  ref<Texture> texture = new Texture;
870  texture->prepareTexture2D(loader.mMaterials[mat_index].mTexture1.mFileName, TF_RGBA);
871  if (loader.mMaterials[mat_index].mTexture1.mOpt_tile)
872  {
873  texture->getTexParameter()->setWrapS(TPW_REPEAT);
874  texture->getTexParameter()->setWrapT(TPW_REPEAT);
875  texture->getTexParameter()->setWrapR(TPW_REPEAT);
876  }
877  else
878  {
879  texture->getTexParameter()->setWrapS(TPW_CLAMP);
880  texture->getTexParameter()->setWrapT(TPW_CLAMP);
881  texture->getTexParameter()->setWrapR(TPW_CLAMP);
882  }
883  mat_map[mat_name]->shader()->gocTextureSampler(0)->setTexture( texture.get() );
884  }
885  }
886 
887  act->setEffect( mat_map[mat_name].get() );
888  }
889  else
890  act->setEffect( default_effect.get() );
891 
892  /* now managed by GeometryLoadCallback */
893  /*// this will already take into consideration the smoothing groups
894  geom->computeNormals();*/
895  }
896  }
897 
898  return res_db;
899 }
900 //-----------------------------------------------------------------------------
long long read(void *buffer, long long byte_count)
Reads byte_count bytes from a file. Returns the number of bytes actually read.
Definition: VirtualFile.cpp:82
Associates a Renderable object to an Effect and Transform.
Definition: Actor.hpp:130
String readLine()
Definition: io3DS.cpp:136
#define ID_MAT_TEXMAP2
Definition: io3DS.cpp:69
#define ID_MAT_UOFFSET
Definition: io3DS.cpp:74
bool parse3DS(VirtualFile *file)
Definition: io3DS.cpp:633
bool mOpt_rgb_tint
Definition: io3DS.hpp:110
void setEffect(Effect *effect)
Binds an Effect to an Actor.
Definition: Actor.hpp:196
VLCORE_EXPORT FileSystem * defFileSystem()
Returns the default FileSystem used by VisualizationLibrary.
Definition: pimpl.cpp:97
TexParameter * getTexParameter()
The TexParameter object associated to a Texture.
Definition: Texture.hpp:246
std::vector< A3DSMaterial > mMaterials
Definition: io3DS.hpp:227
const T_Scalar & t() const
Definition: Vector2.hpp:145
void prepareTexture2D(int width, int height, ETextureFormat format, bool border=false)
Prepares for creation an empty 2D texture.
Definition: Texture.hpp:329
bool mCorrupted
Definition: io3DS.hpp:233
#define ID_MAT_AMBIENT
Definition: io3DS.cpp:61
fvec3 readColByte3()
Definition: io3DS.cpp:118
const T_Scalar & b() const
Definition: Vector3.hpp:99
The A3DSMaterialFaceMapping class represents the material/face mapping in a 3DS file.
Definition: io3DS.hpp:146
const T * get() const
Definition: Object.hpp:128
float mVScale
Definition: io3DS.hpp:101
An abstract class representing a file.
Definition: VirtualFile.hpp:60
If enabled, do depth comparisons and update the depth buffer; Note that even if the depth buffer exis...
Matrix4 & setT(const Vector3< T_Scalar > &v)
Definition: Matrix4.hpp:160
Matrix4 & setX(const Vector3< T_Scalar > &v)
Definition: Matrix4.hpp:136
bool mOpt_tile
Definition: io3DS.hpp:102
A simple String formatting class.
Definition: Say.hpp:124
void setObjectName(const char *name)
The name of the object, by default set to the object&#39;s class name in debug builds.
Definition: Object.hpp:220
float mUScale
Definition: io3DS.hpp:101
const T_Scalar & s() const
Definition: Vector2.hpp:144
#define ID_MAT_MAP_ROTATION
Definition: io3DS.cpp:76
#define ID_MAIN_CHUNK
Definition: io3DS.cpp:50
float readFloatPercent()
Definition: io3DS.cpp:153
float mTransparency
Definition: io3DS.hpp:124
The String class implements an advanced UTF16 (Unicode BMP) string manipulation engine.
Definition: String.hpp:62
const T_Scalar & z() const
Definition: Vector3.hpp:91
bool mDoubleSided
Definition: io3DS.hpp:125
bool mOpt_summed_area
Definition: io3DS.hpp:106
#define ID_LIN_COLOR_24
Definition: io3DS.cpp:56
If enabled, blend the incoming RGBA color values with the values in the color buffers, see also BlendFunc for more information.
bool seekCur(long long offset)
Changes the current read/write position of a file.
fvec3 mAmbient
Definition: io3DS.hpp:122
fvec3 mSpecular
Definition: io3DS.hpp:122
#define ID_3DS_VERSION
Definition: io3DS.cpp:51
The A3DSLoader class loads an Autodesk 3DS file and generates a vector of A3DSObject and A3DSMaterial...
Definition: io3DS.hpp:202
static void error(const String &message)
Use this function to provide information about run-time errors: file not found, out of memory...
Definition: Log.cpp:165
void setWrapT(ETexParamWrap texturewrap)
Definition: Texture.hpp:88
void setVertexArray(ArrayAbstract *data)
Conventional vertex array.
Definition: Geometry.cpp:155
unsigned short mChunkId
Definition: io3DS.hpp:231
#define ID_MAT_SPECULAR
Definition: io3DS.cpp:63
#define ID_OBJECT_BLOCK
Definition: io3DS.cpp:52
String extractPath() const
If the String contains a file path the function returns the path with trailing slash, without the file name.
Definition: String.cpp:830
#define ID_MATERIAL_NAME
Definition: io3DS.cpp:60
#define ID_MAT_TWO_SIDE
Definition: io3DS.cpp:67
Wraps an OpenGL texture object representing and managing all the supported texture types...
Definition: Texture.hpp:143
virtual ref< VirtualFile > locateFile(const String &full_path, const String &alternate_path=String()) const
Looks for a VirtualFile on the disk and in the currently active FileSystem.
Definition: FileSystem.cpp:61
void read_TRIANGULAR_MESH()
Definition: io3DS.cpp:478
void setWrapS(ETexParamWrap texturewrap)
Definition: Texture.hpp:87
void resize(size_t dim)
Definition: Array.hpp:233
#define ID_MAT_VOFFSET
Definition: io3DS.cpp:75
bool endOfFile() const
Returns true if position() >= size()
float readPercentChunk()
Definition: io3DS.cpp:246
void readChunk()
Definition: io3DS.cpp:158
float readFloat(bool little_endian_data=true)
Reads single entry.
virtual void close()=0
Closes the file.
#define ID_LIN_COLOR_F
Definition: io3DS.cpp:57
float mVOffset
Definition: io3DS.hpp:101
bool skipChunk()
Definition: io3DS.cpp:164
const T_Scalar & r() const
Definition: Vector3.hpp:97
#define ID_FLOAT_PERCENTAGE
Definition: io3DS.cpp:59
const String & path() const
Returns the path of the file.
Definition: VirtualFile.hpp:98
A3DSTexture readMapChunk()
Definition: io3DS.cpp:353
The Geometry class is a Renderable that implements a polygonal mesh made of polygons, lines and points.
Definition: Geometry.hpp:66
The A3DSMaterial class represents a material in a 3DS file.
Definition: io3DS.hpp:116
Visualization Library main namespace.
VirtualFile * mInputFile
Definition: io3DS.hpp:230
#define ID_FACE_LIST
Definition: io3DS.cpp:82
unsigned int mChunkLen
Definition: io3DS.hpp:232
const unsigned char * ptr() const
Returns the pointer to the first element of the local buffer. Equivalent to bufferObject()->ptr() ...
Definition: Array.hpp:103
float readWordPercent()
Definition: io3DS.cpp:148
#define ID_COLOR_F
Definition: io3DS.cpp:54
float mRotation
Definition: io3DS.hpp:101
#define ID_MAT_USCALE
Definition: io3DS.cpp:72
Matrix4 & setZ(const Vector3< T_Scalar > &v)
Definition: Matrix4.hpp:152
The A3DSObject class represents an object in a 3DS file.
Definition: io3DS.hpp:189
unsigned int mSmoothingGroup
Definition: io3DS.hpp:182
#define ID_MAT_SHININESS_STRENGTH_PERCENT
Definition: io3DS.cpp:65
float mShininessStrength
Definition: io3DS.hpp:123
const std::vector< ref< Object > > & resources() const
void read_MATERIAL_BLOCK()
Definition: io3DS.cpp:263
See DrawElements.
bool mOpt_one_channel_tint
Definition: io3DS.hpp:108
static void print(const String &message)
Application message for the user.
Definition: Log.cpp:136
void read_OBJECT_BLOCK()
Definition: io3DS.cpp:442
fvec3 readColFloat3()
Definition: io3DS.cpp:127
unsigned char readUInt8()
Reads single entry.
#define ID_COLOR_24
Definition: io3DS.cpp:55
#define ID_TRIANGULAR_MESH
Definition: io3DS.cpp:77
const T_Scalar & y() const
Definition: Vector3.hpp:90
virtual bool open(EOpenMode mode)=0
Opens the file in the specified mode.
bool mOpt_mirror
Definition: io3DS.hpp:104
A3DSTexture mTexture1
Definition: io3DS.hpp:126
#define ID_MAT_TRANSPARENCY
Definition: io3DS.cpp:66
void setTexCoordArray(int tex_unit, ArrayAbstract *data)
Conventional texture coords arrays.
Definition: Geometry.cpp:222
std::vector< A3DSObject > mObjects
Definition: io3DS.hpp:226
#define ID_MAT_VSCALE
Definition: io3DS.cpp:73
bool mOpt_negative
Definition: io3DS.hpp:105
#define NULL
Definition: OpenGLDefs.hpp:81
Matrix4 & setY(const Vector3< T_Scalar > &v)
Definition: Matrix4.hpp:144
arr_type * indexBuffer()
The BufferObject containing the indices used to render.
Shader * shader(int lodi=0, int pass=0)
Utility function, same as &#39;lod(lodi)->at(pass);&#39;.
Definition: Effect.hpp:178
Defines the sequence of Shader objects used to render an Actor.
Definition: Effect.hpp:91
virtual long long size() const =0
Returns the size of the file in bytes.
#define ID_SMOOTHING_GROUP_LIST
Definition: io3DS.cpp:80
#define ID_INT_PERCENTAGE
Definition: io3DS.cpp:58
T_VectorType & at(size_t i)
Definition: Array.hpp:255
#define ID_MAT_DIFFUSE
Definition: io3DS.cpp:62
#define ID_MATERIAL_BLOCK
Definition: io3DS.cpp:53
bool mOpt_decal
Definition: io3DS.hpp:103
#define ID_MAPPING_COORDS
Definition: io3DS.cpp:79
#define ID_VERTEX_LIST
Definition: io3DS.cpp:83
unsigned short readUInt16(bool little_endian_data=true)
Reads single entry.
String mFileName
Definition: io3DS.hpp:100
bool mOpt_use_alpha
Definition: io3DS.hpp:107
void setWrapR(ETexParamWrap texturewrap)
Definition: Texture.hpp:89
const T_Scalar & x() const
Definition: Vector3.hpp:89
fvec3 mDiffuse
Definition: io3DS.hpp:122
unsigned int readUInt32(bool little_endian_data=true)
Reads single entry.
bool mOpt_ignore_alpha
Definition: io3DS.hpp:109
The ref<> class is used to reference-count an Object.
Definition: Object.hpp:55
An array of vl::fvec3.
Definition: Array.hpp:414
#define ID_3D_EDITOR_CHUNK
Definition: io3DS.cpp:49
std::string toStdString() const
Returns a UTF8 encoded std::string.
Definition: String.cpp:1156
#define ID_LOCAL_COORDS_SYSTEM
Definition: io3DS.cpp:78
#define ID_MAT_MAPNAME
Definition: io3DS.cpp:70
#define ID_FACE_MATERIAL_LIST
Definition: io3DS.cpp:81
fvec3 readColChunk()
Definition: io3DS.cpp:209
#define ID_MAT_MAP_TILING
Definition: io3DS.cpp:71
The A3DSTexture class represents a texture in a 3DS file.
Definition: io3DS.hpp:92
long long position() const
Returns the current position in the file.
Definition: VirtualFile.cpp:98
void read_3D_EDITOR_CHUNK()
Definition: io3DS.cpp:177
#define ID_MAT_TEXMAP
Definition: io3DS.cpp:68
virtual size_t bytesUsed() const
Returns the amount of memory in bytes used by an array. Equivalent to bufferObject()->bytesUsed().
Definition: Array.hpp:109
An array of vl::fvec2.
Definition: Array.hpp:412
The A3DSVertex class represents a vertex in a 3DS file.
Definition: io3DS.hpp:156
const T_Scalar & g() const
Definition: Vector3.hpp:98
#define VL_CHECK(expr)
Definition: checks.hpp:73
VLGRAPHICS_EXPORT ref< ResourceDatabase > load3DS(VirtualFile *file)
Definition: io3DS.cpp:694
void enable(EEnable capability)
Definition: Shader.hpp:2158
#define ID_MAT_SHININESS_PERCENT
Definition: io3DS.cpp:64
A3DSTexture mTexture2
Definition: io3DS.hpp:127
fvec3 readVec3()
Definition: io3DS.cpp:109
float mShininess
Definition: io3DS.hpp:123
The ResourceDatabase class contains and manipulates a set of resources.
Collection< DrawCall > & drawCalls()
Returns the list of DrawCall objects bound to a Geometry.
Definition: Geometry.hpp:102
float mUOffset
Definition: io3DS.hpp:101
String mMaterialName
Definition: io3DS.hpp:121