V-ART
meshobject.cpp
Go to the documentation of this file.
1 
5 #include "vart/meshobject.h"
6 #include "vart/file.h"
7 #include <sstream>
8 #include <cassert>
9 #include <fstream>
10 #include <cstdlib>
11 #include <algorithm> // transform
12 #include <cctype> // tolower
13 
14 using namespace std;
15 
17 
18 // === Auxiliary functions ===
19 unsigned int CountOccurrences(char c, string s)
20 {
21  unsigned int occurrences = 0;
22  string::size_type pos = s.find(c);
23  while (pos != string::npos)
24  {
25  ++occurrences;
26  pos = s.find(c, pos+1);
27  }
28  return occurrences;
29 }
30 
31 // === Member funcitions ===
33 {
34  howToShow = FILLED;
35 }
36 
38 {
39  this->operator=(obj);
40 }
41 
43 {
44  this->GraphicObj::operator =(obj);
45  vertVec = obj.vertVec;
46  vertCoordVec = obj.vertCoordVec;
47  normVec = obj.normVec;
48  normCoordVec = obj.normCoordVec;
49  textCoordVec = obj.textCoordVec;
50  meshList = obj.meshList;
51  return *this;
52 }
53 
55 {
56  return new VART::MeshObject(*this);
57 }
58 
60 {
61  vertVec.clear();
62  vertCoordVec.clear();
63  normVec.clear();
64  normCoordVec.clear();
65  textCoordVec.clear();
66  meshList.clear();
67 }
68 
70 {
71  list<VART::Mesh>::iterator iter;
72  for (iter = meshList.begin(); iter != meshList.end(); ++iter)
73  iter->material = mat;
74 }
75 
76 void VART::MeshObject::SetVertices(const std::vector<VART::Point4D>& vertexVec)
77 {
78  vertCoordVec.clear();
79  unsigned int numberOfVertex = vertexVec.size();
80  vertCoordVec.reserve(numberOfVertex * 3);
81  for (unsigned int i = 0; i < numberOfVertex; ++i) {
82  vertCoordVec.push_back(vertexVec[i].GetX());
83  vertCoordVec.push_back(vertexVec[i].GetY());
84  vertCoordVec.push_back(vertexVec[i].GetZ());
85  }
86  meshList.clear();
87  ComputeBoundingBox();
88  ComputeRecursiveBoundingBox();
89 }
90 
91 void VART::MeshObject::SetNormals(const vector<Point4D>& normalVec)
92 {
93  normVec = normalVec;
94  meshList.clear(); // FixMe: Why clear the meshlist?
95  ComputeBoundingBox(); // FixMe: Why recompute the bounding box?
96  ComputeRecursiveBoundingBox();
97 }
98 
99 void VART::MeshObject::SetVertices(const char* vertexStr)
100 {
101  string valStr = vertexStr;
102  istringstream iss(valStr);
103  double x,y,z,w;
104  bool notFinished = true;
105  VART::Point4D point;
106 
107  vertVec.clear();
108  do {
109  if (!(iss >> x >> y >> z)) // Try to read 3 values
110  notFinished = false; // signal end of parsing
111  else
112  {
113  if (!(iss >> w)) // try to read 4th value
114  {
115  w = 1.0; // use default value
116  iss.clear(); // erase error flags
117  }
118  point.SetXYZW(x,y,z,w);
119  vertVec.push_back(point);
120  iss >> ws; // skip possible white space before comma
121  iss.get(); // skip the comma
122  }
123  } while (notFinished);
124  meshList.clear();
125  ComputeBoundingBox();
126  ComputeRecursiveBoundingBox();
127 }
128 
129 void VART::MeshObject::SetVertex(unsigned int index, const VART::Point4D& newValue)
130 {
131  if (vertVec.empty())
132  {
133  unsigned int newIndex = index*3;
134  vertCoordVec[newIndex] = newValue.GetX();
135  vertCoordVec[newIndex+1] = newValue.GetY();
136  vertCoordVec[newIndex+2] = newValue.GetZ();
137  }
138  else
139  { // vertVec is not empty
140  vertVec[index] = newValue;
141  }
142 }
143 
145 {
146  if (vertVec.empty())
147  {
148  unsigned int newPos = pos*3;
149  return VART::Point4D(vertCoordVec[newPos],vertCoordVec[newPos+1],vertCoordVec[newPos+2]);
150  }
151  else
152  { // vertVec is not empty
153  return vertVec[pos];
154 
155  }
156 }
157 
158 void VART::MeshObject::AddNormal(unsigned int idx, const Point4D& vec)
159 {
160  unsigned int coordIdx = idx*3;
161  normCoordVec[coordIdx] += vec.GetX();
162  ++coordIdx;
163  normCoordVec[coordIdx] += vec.GetY();
164  ++coordIdx;
165  normCoordVec[coordIdx] += vec.GetZ();
166 }
167 
169 {
170  unsigned int result = 0;
171  list<Mesh>::iterator iter = meshList.begin();
172  // for each mesh
173  for (; iter != meshList.end(); ++iter)
174  {
175  switch (iter->type)
176  {
177  case Mesh::QUADS:
178  result += iter->indexVec.size() / 4;
179  break;
180  case Mesh::TRIANGLES:
181  result += iter->indexVec.size() / 3;
182  break;
183  default:
184  cerr << "Error: MeshObject::NumFaces not implementes for meshes of type "
185  << static_cast<int>(iter->type) << "\n";
186  exit(1);
187  }
188  }
189  return result;
190 }
191 
193 {
194  if (vertVec.empty())
195  { // optimized representation
196  Point4D smaller(vertCoordVec[0],vertCoordVec[1],vertCoordVec[2]);
197  Point4D temp;
198  unsigned int size = vertCoordVec.size();
199  for (unsigned int i=3; i < size; i += 3)
200  {
201  // We want to use Point4D's flexible comparison, so we put coordinates inside a Point4D.
202  temp.SetXYZ(vertCoordVec[i],vertCoordVec[i+1],vertCoordVec[i+2]);
203  if (temp < smaller)
204  smaller = temp;
205  }
206  *resultPtr = smaller;
207  }
208  else
209  { // unoptimized representation
210  Point4D smaller = vertVec[0];
211  unsigned int size = vertVec.size();
212  for (unsigned int i=1; i < size; ++i)
213  {
214  if (vertVec[i] < smaller)
215  smaller = vertVec[i];
216  }
217  *resultPtr = smaller;
218  }
219 }
220 
222 // deprecated
223 // FixMe: Should be useful, probably as void ComputeCentroid(Point4D* resultPtr).
224 {
225  cerr << "\aWarning: MeshObject::GetVertexMedia() is deprecated.\n";
226  VART::Point4D mean = VART::Point4D(0,0,0,1);
227  double size = 0;
228 
229  size = vertCoordVec.size();
230 
231  for( int i=0; i < size ; i+=3)
232  { // FixMe: inefficient, use separate sums
233  mean += VART::Point4D( vertCoordVec[i], vertCoordVec[i+1], vertCoordVec[i+2]);
234  }
235 
236  if( size == 0 )
237  return VART::Point4D(0,0,0,1);
238  else
239  mean = mean / (size/3);
240 
241  return mean;
242 }
243 
244 void VART::MeshObject::AddFace(const char* indexStr)
245 {
246  string valStr = indexStr;
247  istringstream iss(valStr);
248  unsigned int value;
249  unsigned int thisFacesNormalIndex = normVec.size();
250  VART::Mesh mesh;
251 
252  mesh.type = VART::Mesh::POLYGON;
253  while (iss >> value)
254  {
255  mesh.indexVec.push_back(value);
256  mesh.normIndVec.push_back(thisFacesNormalIndex);
257  }
258  meshList.push_back(mesh);
259 
260  // Auto computation of face normal
261  // FixMe: It should be possible to disable auto computation
262  VART::Point4D v1 = vertVec[mesh.indexVec[1]] - vertVec[mesh.indexVec[0]];
263  VART::Point4D v2 = vertVec[mesh.indexVec[2]] - vertVec[mesh.indexVec[1]];
264  v1.Normalize();
265  v2.Normalize();
266  VART::Point4D normal = v1.CrossProduct(v2);
267  normVec.push_back(normal);
268 }
269 
271 {
272  meshList.push_back(m);
273 }
274 
275 void VART::MeshObject::MakeBox(double minX, double maxX, double minY, double maxY, double minZ, double maxZ)
276 {
277  cerr << "MeshObject::MakeBox is deprecated. Use VART::Box.\n";
278  assert((minX <= maxX) && (minY <= maxY) && (minZ <= maxZ));
279  // each vertex must repeat 3 times because there must be a vertex/normal correspondence
280  // of 1:1
281  double coordinateArray[] = { minX,minY,minZ, //0
282  minX,maxY,minZ, //1
283  maxX,maxY,minZ, //2
284  maxX,minY,minZ, //3
285  minX,minY,maxZ, //4
286  minX,maxY,maxZ, //5
287  maxX,maxY,maxZ, //6
288  maxX,minY,maxZ, //7
289  minX,minY,minZ,
290  minX,maxY,minZ,
291  maxX,maxY,minZ,
292  maxX,minY,minZ,
293  minX,minY,maxZ,
294  minX,maxY,maxZ,
295  maxX,maxY,maxZ,
296  maxX,minY,maxZ,
297  minX,minY,minZ,
298  minX,maxY,minZ,
299  maxX,maxY,minZ,
300  maxX,minY,minZ,
301  minX,minY,maxZ,
302  minX,maxY,maxZ,
303  maxX,maxY,maxZ,
304  maxX,minY,maxZ };
305  double* endOfCoordinateArray = coordinateArray + sizeof(coordinateArray)/sizeof(double);
306  unsigned int indexArray[] = { 0,1,2,3, // back face
307  4,7,6,5, // front face
308  11,10,14,15, // right face
309  13,9,8,12, // left face
310  22,18,17,21, // top face
311  23,20,16,19 }; // bottom face
312  unsigned int* endOfIndexArray = indexArray + sizeof(indexArray)/sizeof(int);
313  double normalArray[] = { 0,0,-1, 0,0,-1, 0,0,-1, 0,0,-1,
314  0,0,1, 0,0,1, 0,0,1, 0,0,1,
315  -1,0,0, -1,0,0, 1,0,0, 1,0,0,
316  -1,0,0, -1,0,0, 1,0,0, 1,0,0,
317  0,-1,0, 0,1,0, 0,1,0, 0,-1,0,
318  0,-1,0, 0,1,0, 0,1,0, 0,-1,0 };
319  double* endOfNormalArray = normalArray + sizeof(normalArray)/sizeof(double);
320  float textArray[] = { 0,0,0, 0,1,0, 1,1,0, 1,0,0,
321  0,0,0, 0,1,0, 1,1,0, 1,0,0,
322  0,0,0, 0,1,0, 1,1,0, 1,0,0,
323  0,0,0, 0,1,0, 1,1,0, 1,0,0,
324  0,0,0, 0,1,0, 1,1,0, 1,0,0,
325  0,0,0, 0,1,0, 1,1,0, 1,0,0 };
326  float* endOfTextArray = textArray + sizeof(textArray)/sizeof(float);
327 
328  VART::Mesh mesh;
329  vertCoordVec.clear();
330  normCoordVec.clear();
331  textCoordVec.clear();
332  meshList.clear();
333  vertCoordVec.assign(coordinateArray,endOfCoordinateArray);
334  normCoordVec.assign(normalArray,endOfNormalArray);
335  textCoordVec.assign(textArray,endOfTextArray);
336  mesh.type = VART::Mesh::QUADS;
337  mesh.indexVec.assign(indexArray,endOfIndexArray);
338  mesh.material = VART::Material::DARK_PLASTIC_GRAY(); // default material
339  meshList.push_back(mesh);
340  ComputeBoundingBox();
341  ComputeRecursiveBoundingBox();
342 }
343 
344 void VART::MeshObject::GetYProjection(std::list<VART::Point4D>* resultPtr, double height) const
345 // height defaults to 0 (see headers).
346 {
347  VART::Point4D point;
348  resultPtr->clear();
349  if (vertCoordVec.size() > 6)
350  { // Found optimized data - use it
351  unsigned int vertexVetEnd = vertCoordVec.size();
352  for (unsigned int i=0; i < vertexVetEnd; i+=3)
353  {
354  point.SetXYZW(vertCoordVec[i],height,vertCoordVec[i+2],1);
355  resultPtr->push_back(point);
356  }
357  }
358  else
359  { // Use unoptimized data
360  unsigned int vertexVetEnd = vertVec.size();
361  for (unsigned int i=0; i < vertexVetEnd; ++i)
362  {
363  point.SetXYZW(vertVec[i].GetX(), height, vertVec[i].GetZ(), 1);
364  resultPtr->push_back(point);
365  }
366  }
367 }
368 
370 {
371  // Create optmized structures from unoptimized ones
372  // Erase unoptimized data
373 }
374 
376  if (vertCoordVec.size() > 0)
377  { // Optimized structure found - use it!
378  // Initialize
379  bBox.SetBoundingBox(vertCoordVec[0], vertCoordVec[1], vertCoordVec[2],
380  vertCoordVec[0], vertCoordVec[1], vertCoordVec[2]);
381  // Check against the others
382  for (unsigned int i=3; i < vertCoordVec.size(); i+=3)
383  bBox.ConditionalUpdate(vertCoordVec[i], vertCoordVec[i+1], vertCoordVec[i+2]);
384  }
385  else
386  { // No optmized structure found - use vertVec
387  // Initialize
388  bBox.SetBoundingBox(vertVec[0].GetX(), vertVec[0].GetY(), vertVec[0].GetZ(),
389  vertVec[0].GetX(), vertVec[0].GetY(), vertVec[0].GetZ());
390  // Check against the others
391  for (unsigned int i=1; i < vertVec.size(); ++i)
392  bBox.ConditionalUpdate(vertVec[i]);
393  }
394  bBox.ProcessCenter();
395 }
396 
398 
399  VART::Point4D p;
400 
401  if (vertCoordVec.size() > 0)
402  { // Optimized structure found - use it!
403  // Initialize
404  p.SetXYZW( vertCoordVec[0], vertCoordVec[1], vertCoordVec[2], 1 );
405  p = trans * p;
406  bbPtr->SetBoundingBox(p.GetX(), p.GetY(), p.GetZ() , p.GetX(), p.GetY(), p.GetZ());
407  // Check against the others
408  for (unsigned int i=3; i < vertCoordVec.size(); i+=3)
409  {
410  p.SetXYZW( vertCoordVec[i], vertCoordVec[i+1], vertCoordVec[i+2], 1 );
411  p = trans * p;
412  bbPtr->ConditionalUpdate( p );
413  }
414  }
415  else
416  { // No optmized structure found - use vertVec
417  // Initialize
418  p = vertVec[0];
419  p = trans * p;
420  bbPtr->SetBoundingBox(p.GetX(), p.GetY(), p.GetZ() , p.GetX(), p.GetY(), p.GetZ());
421  // Check against the others
422  for (unsigned int i=1; i < vertVec.size(); ++i)
423  {
424  p = vertVec[i];
425  p = trans * p;
426  bbPtr->ConditionalUpdate( p );
427  }
428  }
429 }
430 
431 void VART::MeshObject::ComputeSubBBoxes( const Transform& trans, int subdivisions )
432 {
433  VART::Point4D p;
434  VART::BoundingBox globalBBox;
435  std::vector<VART::Point4D> pointList;
436 
437 
438  if (vertCoordVec.size() <= 0)
439  return;
440 
441  pointList.reserve( (int) (vertCoordVec.size() / 3) );
442 
443  // Initialize
444  p.SetXYZW( vertCoordVec[0], vertCoordVec[1], vertCoordVec[2], 1 );
445  p = trans * p;
446  pointList.push_back( p );
447  globalBBox.SetBoundingBox(p.GetX(), p.GetY(), p.GetZ() , p.GetX(), p.GetY(), p.GetZ());
448 
449  // Check against the others
450  for (unsigned int i=3; i < vertCoordVec.size(); i+=3)
451  {
452  p.SetXYZW( vertCoordVec[i], vertCoordVec[i+1], vertCoordVec[i+2], 1 );
453  p = trans * p;
454  pointList.push_back( p );
455  globalBBox.ConditionalUpdate( p );
456  }
457 
458  if( subdivisions <= 0)
459  {
460  subBBoxes.push_back( globalBBox );
461  return;
462  }
463  subBBoxes.clear();
464  subBBoxes.reserve( (int)pow(8.0f, subdivisions) );
465 
466  subDivideBBox( globalBBox, subdivisions-1, pointList);
467 }
468 
469 //~ void VART::MeshObject::ComputeFaceNormal(unsigned int faceIdx)
470 //~ {
471  //~ unsigned int vertexIdx;
472  //~ Point4D p1(vertCoordVec
473 //~ }
474 
476 {
477  // The normal for each vertex will be the average for each face
478  // initialize every normal to (0,0,0), to acumulate a vector sum at each normal
479  normCoordVec.assign(vertCoordVec.size(), 0);
480 
481  // for each mesh
482  list<Mesh>::iterator iter = meshList.begin();
483  for (; iter != meshList.end(); ++iter)
484  {
485  unsigned int p1Idx = 0;
486  unsigned int p2Idx = 1;
487  unsigned int p3Idx = 2;
488  unsigned int end = iter->indexVec.size();
489  // for each face
490  while (p3Idx < end)
491  {
492  // compute face normal
493  Point4D normal;
494  ComputeTriangleNormal(Vertex(iter->indexVec[p1Idx]),
495  Vertex(iter->indexVec[p2Idx]),
496  Vertex(iter->indexVec[p3Idx]), &normal);
497  // Add face normal to vertex normal (3 vertices)
498  AddNormal(iter->indexVec[p1Idx], normal); // Add face normal to vertex normal
499  AddNormal(iter->indexVec[p2Idx], normal); // Add face normal to vertex normal
500  AddNormal(iter->indexVec[p3Idx], normal); // Add face normal to vertex normal
501  // Add face normal to other vertices
502  switch (iter->type)
503  {
504  case Mesh::TRIANGLES:
505  p1Idx += 3;
506  p2Idx += 3;
507  p3Idx += 3;
508  break;
509  case Mesh::TRIANGLE_STRIP:
510  p1Idx += 1;
511  p2Idx += 1;
512  p3Idx += 1;
513  break;
514  case Mesh::TRIANGLE_FAN:
515  p3Idx += 1;
516  break;
517  case Mesh::QUADS:
518  AddNormal(iter->indexVec[p3Idx+1], normal);
519  p1Idx += 4;
520  p2Idx += 4;
521  p3Idx += 4;
522  break;
523  case Mesh::QUAD_STRIP:
524  AddNormal(iter->indexVec[p3Idx+1], normal);
525  p1Idx += 2;
526  p2Idx += 2;
527  p3Idx += 2;
528  break;
529  case Mesh::POLYGON:
530  ++p3Idx;
531  for (; p3Idx < end; ++p3Idx)
532  AddNormal(iter->indexVec[p3Idx], normal);
533  break;
534  default:
535  cerr << "Error: MeshObject::ComputeVertexNormals not implemented for mesh type "
536  << static_cast<int>(iter->type) << endl;
537  exit (1);
538  }
539  }
540  // now, each normal holds the sum of face normals that share it
541  }
542  NormalizeAllNormals();
543 }
544 
545 void VART::MeshObject::subDivideBBox( VART::BoundingBox motherBox, int subdivisions, std::vector<VART::Point4D> pointList )
546 {
547  VART::Point4D center;
548  VART::BoundingBox newBBox;
549 
550  motherBox.ProcessCenter();
551  center = motherBox.GetCenter();
552 
553  // Here we test the points for each original bbox octet;
554 
555  // octet 1 (max, max, max)
556  newBBox.SetBoundingBox(center.GetX(), center.GetY(), center.GetZ(),
557  motherBox.GetGreaterX(), motherBox.GetGreaterY(), motherBox.GetGreaterZ());
558  computeNewSubBBox( newBBox, subdivisions, pointList );
559 
560  // octet 2 (min, max, max)
561  newBBox.SetBoundingBox(motherBox.GetSmallerX(), center.GetY(), center.GetZ(),
562  center.GetX(), motherBox.GetGreaterY(), motherBox.GetGreaterZ());
563  computeNewSubBBox( newBBox, subdivisions, pointList );
564 
565  // octet 3 (max, min, max)
566  newBBox.SetBoundingBox(center.GetX(), motherBox.GetSmallerY(), center.GetZ(),
567  motherBox.GetGreaterX(), center.GetY(), motherBox.GetGreaterZ());
568  computeNewSubBBox( newBBox, subdivisions, pointList );
569 
570  // octet 4 (min, min, max)
571  newBBox.SetBoundingBox(motherBox.GetSmallerX(), motherBox.GetSmallerY(), center.GetZ(),
572  center.GetX(), center.GetY() , motherBox.GetGreaterZ());
573  computeNewSubBBox( newBBox, subdivisions, pointList );
574 
575  // octet 5 (max, max, min)
576  newBBox.SetBoundingBox(center.GetX(), center.GetY(), motherBox.GetSmallerZ(),
577  motherBox.GetGreaterX(), motherBox.GetGreaterY(),center.GetZ() );
578  computeNewSubBBox( newBBox, subdivisions, pointList );
579 
580  // octet 6 (min, max, min)
581  newBBox.SetBoundingBox(motherBox.GetSmallerX(), center.GetY(), motherBox.GetSmallerZ(),
582  center.GetX(), motherBox.GetGreaterY(), center.GetZ() );
583  computeNewSubBBox( newBBox, subdivisions, pointList );
584 
585  // octet 7 (max, min, min)
586  newBBox.SetBoundingBox(center.GetX(), motherBox.GetSmallerY(), motherBox.GetSmallerZ(),
587  motherBox.GetGreaterX(), center.GetY(), center.GetZ() );
588  computeNewSubBBox( newBBox, subdivisions, pointList );
589 
590  // octet 8 (min, min, min)
591  newBBox.SetBoundingBox(motherBox.GetSmallerX(), motherBox.GetSmallerY(), motherBox.GetSmallerZ(),
592  center.GetX(), center.GetY(), center.GetZ() );
593  computeNewSubBBox( newBBox, subdivisions, pointList );
594 }
595 
596 void VART::MeshObject::computeNewSubBBox( VART::BoundingBox oldBox, int subdivisions, std::vector<VART::Point4D> pointList)
597 {
598  std::vector<Point4D> newPointList;
599  VART::BoundingBox newBBox;
600  bool initialized = false;
601 
602  for( unsigned int i=0; (i < pointList.size()) && (!initialized); i++ )
603  if( oldBox.testPoint( pointList[i] ))
604  {
605  newBBox.SetBoundingBox( pointList[i].GetX(), pointList[i].GetY(), pointList[i].GetZ(),
606  pointList[i].GetX(), pointList[i].GetY(), pointList[i].GetZ());
607  initialized = true;
608  }
609 
610  if( !initialized )
611  return;
612 
613  newBBox.SetColor( VART::Color::GREEN() );
614 
615  for( unsigned int i=0; i < pointList.size(); i+=3 )
616  if( oldBox.testPoint( pointList[i] ) ||
617  oldBox.testPoint( pointList[i+1] ) ||
618  oldBox.testPoint( pointList[i+2] ) )
619  {
620  newBBox.ConditionalUpdate( pointList[i] );
621  newBBox.ConditionalUpdate( pointList[i+1] );
622  newBBox.ConditionalUpdate( pointList[i+2] );
623  }
624 
625  newBBox.CutBBox( oldBox );
626 
627  if(subdivisions == 0)
628  subBBoxes.push_back( newBBox );
629  else
630  subDivideBBox( newBBox, subdivisions-1, pointList);
631 }
632 
634 // both meshObjects must be optimized or the both must be unoptimized
635  bool bothOptimized = vertVec.empty() && obj.vertVec.empty();
636  list<VART::Mesh>::const_iterator iter = obj.meshList.begin();
637  VART::Mesh mesh;
638  unsigned int prevNumVertices;
639  assert (bothOptimized || (vertCoordVec.empty() && obj.vertCoordVec.empty()));
640 
641  prevNumVertices = (bothOptimized? (vertCoordVec.size()/3) : vertVec.size());
642  for (; iter != obj.meshList.end(); ++iter)
643  {
644  mesh = *iter;
645  mesh.IncrementIndices(prevNumVertices);
646  meshList.push_back(mesh);
647  }
648 
649  vertVec.insert(vertVec.end(), obj.vertVec.begin(), obj.vertVec.end());
650  vertCoordVec.insert(vertCoordVec.end(), obj.vertCoordVec.begin(), obj.vertCoordVec.end());
651  normVec.insert(normVec.end(), obj.normVec.begin(), obj.normVec.end());
652  normCoordVec.insert(normCoordVec.end(), obj.normCoordVec.begin(), obj.normCoordVec.end());
653  textCoordVec.insert(textCoordVec.end(), obj.textCoordVec.begin(), obj.textCoordVec.end());
654  ComputeBoundingBox();
655  ComputeRecursiveBoundingBox();
656 }
657 
659  unsigned int i = 0;
660  unsigned int size;
661 
662  if (vertCoordVec.empty())
663  {
664  for (size = vertVec.size(); i < size; ++i)
665  {
666  trans.ApplyTo(&(vertVec[i]));
667  }
668  }
669  else
670  {
671  VART::Point4D vertex;
672  for (size = vertCoordVec.size(); i < size; i+=3)
673  {
674  vertex.SetXYZW(vertCoordVec[i],vertCoordVec[i+1],vertCoordVec[i+2],1);
675  trans.ApplyTo(&vertex);
676  vertCoordVec[i] = vertex.GetX();
677  vertCoordVec[i+1] = vertex.GetY();
678  vertCoordVec[i+2] = vertex.GetZ();
679  }
680  }
681  ComputeBoundingBox();
682  ComputeRecursiveBoundingBox();
683 }
684 
686  const VART::Point4D& v3, VART::Point4D* resultPtr) {
687  VART::Point4D edge1 = v2 - v1;
688  VART::Point4D edge2 = v3 - v2;
689  *resultPtr = edge1.CrossProduct(edge2);
690  resultPtr->Normalize();
691 }
692 
694 #ifdef VART_OGL
695  bool result = true;
696  list<VART::Mesh>::const_iterator iter;
697  if (show) // if visible...
698  { // FixMe: no need to keep this old name; rename "show" to "visible".
699  switch (howToShow)
700  {
701  case LINES:
702  case LINES_AND_NORMALS:
703  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
704  break;
705  case POINTS:
706  case POINTS_AND_NORMALS:
707  glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
708  break;
709  default:
710  glPolygonMode(GL_FRONT, GL_FILL);
711  break;
712  }
713  if (vertCoordVec.size() > 0)
714  { // Optimized structure found - draw it!
715  // Note that vertex arrays must be enabled to allow drawing of optimized meshes. See
716  // VART::ViewerGlutOGL.
717  glVertexPointer(3, GL_DOUBLE, 0, &vertCoordVec[0]);
718  glNormalPointer(GL_DOUBLE, 0, &normCoordVec[0]);
719  if (!textCoordVec.empty())
720  glTexCoordPointer(3, GL_FLOAT, 0, &textCoordVec[0]);
721  if ((howToShow == LINES_AND_NORMALS) || (howToShow == POINTS_AND_NORMALS))
722  { // Draw normals
723  unsigned int numVertices = vertCoordVec.size() / 3;
724  unsigned int index = 0;
725  Material::PLASTIC_WHITE().DrawOGL(); //FixMe: make more generic.
726  glBegin(GL_LINES);
727  for (unsigned int i=0; i < numVertices; ++i)
728  {
729  glVertex3dv(&vertCoordVec[index]);
730  glVertex3d(vertCoordVec[index] + sizeOfNormals*normCoordVec[index],
731  vertCoordVec[index+1]+sizeOfNormals*normCoordVec[index+1],
732  vertCoordVec[index+2]+sizeOfNormals*normCoordVec[index+2]);
733  index += 3;
734  }
735  glEnd();
736  }
737  for (iter = meshList.begin(); iter != meshList.end(); ++iter)
738  { // for each mesh:
739  //if (iter->material.GetTexture().HasTextureLoad() ) {
740  //glTexCoordPointer(3,GL_FLOAT,0,&textCoordVec[0]);
741  //}
742  result &= iter->DrawInstanceOGL();
743  }
744  }
745  else
746  { // No optmized structure found - draw vertices from vertVec
747  unsigned int meshSize;
748  unsigned int i;
749  for (iter = meshList.begin(); iter != meshList.end(); ++iter)
750  { // for each mesh:
751  iter->material.DrawOGL();
752  glBegin(iter->GetOglType());
753  meshSize = iter->indexVec.size();
754  assert(meshSize == iter->normIndVec.size());
755  for (i = 0; i < meshSize; ++i)
756  {
757  // FixMe: need to draw texture vertices for unoptimized mesh
758  glNormal3dv(normVec[iter->normIndVec[i]].VetXYZW());
759  glVertex4dv(vertVec[iter->indexVec[i]].VetXYZW());
760  }
761  glEnd();
762  }
763  }
764  }
765  if(bBox.visible)
766  bBox.DrawInstanceOGL();
767  if(recBBox.visible)
768  recBBox.DrawInstanceOGL();
769  return result;
770 #else
771  return false;
772 #endif
773 }
774 
775 bool VART::MeshObject::ReadFromOBJ(const string& filename, list<VART::MeshObject*>* resultPtr)
776 // passing garbage on *resultPtr makes the method crash. Remember to clean it before calling.
777 
778 // Note: Blender saves obj files with multiple objects, reusing normal coordinates (and
779 // probably other stuff) between objects. V-ART has to repeat those coordinates because
780 // each object in the file turns into a mesh object with its own coordinates vector.
781 {
782  ifstream file(filename.c_str());
783  if(file.is_open())
784  cout << "Loading " << filename << "...\n" << flush;
785  else {
786  cerr << "MeshObject::ReadFromOBJ failed to open '" << filename << "'.\n";
787  throw 1;
788  }
789 
790  VART::MeshObject* meshObjectPtr = new VART::MeshObject();
791  meshObjectPtr->SetDescription(filename);
792  resultPtr->push_back(meshObjectPtr);
793 
794  istringstream iss;
795  string line;
796  string lineID;
797  string name;
798  //char trash;
799  double x,y,z;
800  map<string,VART::Material> materialMap;
801  map<string,VART::Texture> textureMap;
802  // vertIndexesMap maps vi/ni/ti triplets to unique array indices
803  map<VertexTriplet, unsigned int> vertIndexesMap;
804  vector<float> vertCoordTempVec; // cache of previous vertices described in a file
805  vector<float> vertNormTempVec; // cache of previous normals described in a file
806  vector<float> textCoordTempVec; // cache of previous textures described in a file
807  VART::Mesh mesh;
808 // unsigned int vi, ti, ni; // vertex, texture and normal indices
809  unsigned int faceCounter = 0; // counts the number of faces in the file
810  unsigned int objCounter = 0; // counts the number of objects in the file
811  unsigned int lineNumber = 0;
812 
813  while (getline(file, line)) {
814  iss.clear(); // reset error status
815  iss.str(line); // iss <- line
816  if(iss.peek() != -1) {
817  iss >> lineID;
818  ++lineNumber;
819  static unsigned int index = 0;
820  if (lineID == "v") { // vertex
821  iss >> x >> y >> z;
822  // store coordinates in the mesh object
823  // meshObjectPtr->vertCoordVec.push_back(x);
824  // meshObjectPtr->vertCoordVec.push_back(y);
825  // meshObjectPtr->vertCoordVec.push_back(z);
826  // keep a local copy to deal with index beetween objects in the file
827  vertCoordTempVec.push_back(x);
828  vertCoordTempVec.push_back(y);
829  vertCoordTempVec.push_back(z);
830  }
831  else if (lineID == "vn") { // vertex normal
832  iss >> x >> y >> z;
833  // store coordinates in the mesh object
834  // meshObjectPtr->normCoordVec.push_back(x);
835  // meshObjectPtr->normCoordVec.push_back(y);
836  // meshObjectPtr->normCoordVec.push_back(z);
837  // keep a local copy to deal with index beetween objects in the file
838  vertNormTempVec.push_back(x);
839  vertNormTempVec.push_back(y);
840  vertNormTempVec.push_back(z);
841  }
842  else if (lineID == "vt") { // texture coordinates
843  // Texture coordinates could be 2 or 3 values,
844  // only the first 2 are read.
845  iss >> x >> y;
846  textCoordTempVec.push_back(x);
847  textCoordTempVec.push_back(y);
848  textCoordTempVec.push_back(0.0f);
849  }
850  else if (lineID == "f") { // face
851  list<VertexTriplet> vertices;
852  ReadVerticesLine(iss, &vertices);
853  VART::Mesh::MeshType tempType;
854  switch(vertices.size()) {
855  case 1: cerr << "ReadFromObj found a face with 1 vertex!\n";
856  throw 2;
857  case 2: cerr << "ReadFromObj found a face with 2 vertices!\n";
858  throw 3;
859  case 3: tempType = VART::Mesh::TRIANGLES;
860  break;
861  case 4: tempType = VART::Mesh::QUADS;
862  break;
863  default:
864  tempType = VART::Mesh::POLYGON;
865  }
866  // V-Art will create a new mesh every time the number
867  // of vertices in a face is different than in the previous ones.
868  if (mesh.type != Mesh::NONE) {
869  if (tempType != mesh.type) {
870  // start new mesh
871  // add old mesh to meshObject
872  meshObjectPtr->meshList.push_back(mesh);
873  mesh.indexVec.clear();
874  mesh.normIndVec.clear();
875  mesh.type = tempType;
876  }
877  }
878  else { // this is the first face in the mesh
879  mesh.type = tempType;
880  }
881 
882  // A file has many objects, but each object gets separated on a MeshObject
883  // with its on vertex coordinates vector. Need to subtract from last.
884  // However, the file may refer to vertices or normals that were put with
885  // previous mesh objects.
886  for (auto& vTriple : vertices) {
887  map<VertexTriplet, unsigned int>::iterator pos =
888  vertIndexesMap.find(vTriple);
889  if (pos != vertIndexesMap.end()) {
890  // index has been used before
891  mesh.indexVec.push_back(pos->second);
892  }
893  else { // index triple hasn't been used before
894  vertIndexesMap.insert(make_pair(vTriple, index));
895  mesh.indexVec.push_back(index);
896  ++index;
897 
898  // copy vertex, texture and normal coordinates to this mesh object
899  unsigned int i = (vTriple.vertexIndex-1)*3; // x coordinate in vertCoordTempVec
900  meshObjectPtr->vertCoordVec.push_back(vertCoordTempVec[i]);
901  meshObjectPtr->vertCoordVec.push_back(vertCoordTempVec[++i]);
902  meshObjectPtr->vertCoordVec.push_back(vertCoordTempVec[++i]);
903 
904  if (vTriple.textIndex != 0) {
905  i = (vTriple.textIndex-1)*3; // x coordinate in textCoordTempVec
906  meshObjectPtr->textCoordVec.push_back(textCoordTempVec[i]);
907  meshObjectPtr->textCoordVec.push_back(textCoordTempVec[++i]);
908  meshObjectPtr->textCoordVec.push_back(textCoordTempVec[++i]);
909  }
910 
911  i = (vTriple.normIndex-1)*3; // x coordinate in normCoordTempVec
912  meshObjectPtr->normCoordVec.push_back(vertNormTempVec[i]);
913  meshObjectPtr->normCoordVec.push_back(vertNormTempVec[++i]);
914  meshObjectPtr->normCoordVec.push_back(vertNormTempVec[++i]);
915  }
916  }
917  ++faceCounter;
918  } // end of face line
919  else if (lineID == "usemtl") // material assignment
920  { // start new mesh
921  // add old mesh to meshObject
922  if (mesh.indexVec.size() > 0)
923  {
924  meshObjectPtr->meshList.push_back(mesh);
925  mesh.indexVec.clear();
926  mesh.normIndVec.clear();
927  }
928 
929  iss >> ws >> name;
930  mesh.material = materialMap[name];
931  }
932  else if (lineID == "usemap") // texture of current mesh
933  {
934  iss >> name;
935  // make sure the name is in lower case
936  transform(name.begin(), name.end(), name.begin(), ::tolower);
937  VART::Texture texture = textureMap[name];
938  if(!texture.HasData()) //Read a texture file not read yet
939  {
940  name = VART::File::GetPathFromString(filename)+name;
941  if(! texture.LoadFromFile(name) )
942  cerr << "Error reading usemap in '" << VART::File::GetPathFromString(filename) << filename << "', line " << lineNumber <<
943  ": could not read texture file '" << name << "'" << endl;
944  textureMap[name] = texture;
945  }
946  mesh.material.SetTexture( texture );
947  }
948  else if (lineID == "mtllib") // material library
949  {
950  iss >> ws >> name;
951  ReadMaterialTable(VART::File::GetPathFromString(filename)+name, &materialMap);
952  }
953  else if (lineID == "maplib") //texture mapping library
954  {//ignore this line, no maplib implemented yet in V-Art
955  }
956  else if (lineID == "o") // object delimiter
957  {
958  ++objCounter;
959  iss >> ws >> name;
960  // Add last mesh to last meshObject
961  if (mesh.indexVec.size() > 0)
962  {
963  meshObjectPtr->meshList.push_back(mesh);
964  mesh.indexVec.clear();
965  mesh.type = VART::Mesh::NONE;
966  }
967 
968  if (meshObjectPtr->IsEmpty())
969  {
970  resultPtr->remove(meshObjectPtr);
971  delete meshObjectPtr;
972  }
973 
974  meshObjectPtr = new VART::MeshObject;
975  meshObjectPtr->autoDelete = true;
976  meshObjectPtr->SetDescription(name);
977  resultPtr->push_back(meshObjectPtr);
978  index = 0;
979  }
980  else if (lineID[0] == '#')
981  { // ignore this line (comment)
982  }
983  else if (lineID == "g") // group names
984  { // ignore this line (no groups in V-ART yet!)
985  }
986  else if (lineID == "s") // smoothing group
987  { // ignore this line (no smoothing groups in V-ART yet!)
988  }
989  else
990  cerr << "Error in '" << filename << "', line " << lineNumber << ": unknown ID '"
991  << lineID << "'" << endl;
992  }
993  }
994  // Finished. Add last mesh to last meshObject
995  if (mesh.indexVec.size() > 0)
996  {
997  meshObjectPtr->meshList.push_back(mesh);
998  }
999  // Compute bounding boxes
1000  list<VART::MeshObject*>::iterator iter;
1001  for (iter = resultPtr->begin(); iter != resultPtr->end(); ++iter)
1002  {
1003  (*iter)->ComputeBoundingBox();
1004  (*iter)->ComputeRecursiveBoundingBox();
1005  }
1006  clog << "File " << filename << " finished loading ("
1007  << objCounter << " objects, "
1008  << faceCounter << " polygons).\n";
1009 
1010  return true;
1011 }
1012 
1014 {
1015  unsigned int i0 = 0;
1016  unsigned int i1 = 1;
1017  unsigned int i2 = 2;
1018  double size;
1019  while (i2 < normCoordVec.size())
1020  {
1021  size = sqrt(normCoordVec[i0]*normCoordVec[i0] +
1022  normCoordVec[i1]*normCoordVec[i1] +
1023  normCoordVec[i2]*normCoordVec[i2]);
1024  normCoordVec[i0] /= size;
1025  normCoordVec[i1] /= size;
1026  normCoordVec[i2] /= size;
1027  i0 += 3;
1028  i1 += 3;
1029  i2 += 3;
1030  }
1031 }
1032 
1033 void VART::MeshObject::ReadMaterialTable(const string& filename, map<string,VART::Material>* matMapPtr)
1034 // Reads a Wavefront material table (.mtl file)
1035 {
1036  ifstream file(filename.c_str());
1037  istringstream iss;
1038  string line;
1039  string lineID;
1040  string materialName;
1041  string textureName;
1042  VART::Material material;
1043  VART::Texture texture;
1044  std::map<std::string,VART::Texture> textureMap;
1045  float r,g,b;
1046  float value;
1047  unsigned int type;
1048  unsigned int lineNumber = 0;
1049 
1051  if( !file.is_open() )
1052  {
1053  cerr << "Error in '" << filename << "': could not read material table file." << endl;
1054  return;
1055  }
1056  while (getline(file,line))
1057  {
1058  iss.str(line); // iss <- line
1059  iss >> lineID;
1060  ++lineNumber;
1061  if (lineID == "newmtl")
1062  {
1063  // if not the first material, add the last material to the material table
1064  if (materialName.size() > 0)
1065  matMapPtr->insert(make_pair(materialName,material));
1066  // read name for current material
1067  iss >> ws >> materialName;
1068  }
1069  else if (lineID == "Ns")
1070  {
1071  iss >> value;
1072  // shininess values appear to be in the range 0..1000, so they should be
1073  // multiplied by 0.128
1074  material.SetShininess(value*0.128);
1075  }
1076  else if (lineID == "Kd")
1077  {
1078  iss >> r >> g >> b;
1079  material.SetDiffuseColor(VART::Color(static_cast<unsigned char>(r*255),
1080  static_cast<unsigned char>(g*255),
1081  static_cast<unsigned char>(b*255)));
1082  }
1083  else if (lineID == "Ka")
1084  {
1085  iss >> r >> g >> b;
1086  material.SetAmbientColor(VART::Color(static_cast<unsigned char>(r*255),
1087  static_cast<unsigned char>(g*255),
1088  static_cast<unsigned char>(b*255)));
1089  }
1090  else if (lineID == "Ks")
1091  {
1092  iss >> r >> g >> b;
1093  material.SetSpecularColor(VART::Color(static_cast<unsigned char>(r*255),
1094  static_cast<unsigned char>(g*255),
1095  static_cast<unsigned char>(b*255)));
1096  }
1097  else if (lineID == "Ke")
1098  {
1099  iss >> r >> g >> b;
1100  material.SetEmissiveColor(VART::Color(static_cast<unsigned char>(r*255),
1101  static_cast<unsigned char>(g*255),
1102  static_cast<unsigned char>(b*255)));
1103  }
1104  else if ((lineID == "d") || (lineID == "Tr"))
1105  {
1106  iss >> value; // transparency value
1107  // FixMe: use the value
1108  }
1109  else if (lineID == "illum")
1110  {
1111  iss >> type;
1112  if (type == 1) // no specular color for this material
1114  //~ material.SetSpecularColor(material.GetDiffuseColor());
1115  }
1116  else if (lineID == "map_Kd")
1117  {
1118  iss >> textureName;
1119  texture = textureMap[textureName];
1120  if(!texture.HasData())
1121  {
1122  string path = VART::File::GetPathFromString(filename);
1123  if( !texture.LoadFromFile( path+textureName ) )
1124  {
1125  cerr << "Error reading map_Kd in '" << filename << "', line "
1126  << lineNumber << ": could not read texture file '"
1127  << path << textureName << "'" << endl;
1128  }
1129  textureMap[textureName] = texture;
1130  }
1131  material.SetTexture( texture );
1132  }
1133  else if (lineID == "Ni")
1134  { // "Ni" Specifies the optical density for the surface. This is also
1135  // known as index of refraction. The values can range from 0.001 to
1136  // 10. A value of 1.0 means that light does not bend as it passes
1137  // through an object. Increasing the optical_density increases the
1138  // amount of bending. Glass has an index of refraction of about 1.5.
1139  // Values of less than 1.0 produce bizarre results and are not
1140  // recommended.
1141  float opticalDensity;
1142  iss >> opticalDensity; // Currently there is no use for it.
1143  }
1144  else if (lineID == "#")
1145  { // comment, ignore this line
1146  }
1147  else
1148  {
1149  cerr << "Error in '" << filename << "', line " << lineNumber << ": unknown ID '"
1150  << lineID << "'" << endl;
1151  }
1152  iss.clear();
1153  }
1154  // Add last material to material table
1155  if (materialName.size() > 0)
1156  matMapPtr->insert(make_pair(materialName,material));
1157 }
1158 
1159 // static protected
1160 void VART::MeshObject::ReadVertex(std::istringstream& iss,
1161  unsigned int* viPtr, unsigned int* tiPtr, unsigned int* niPtr)
1162 // Reads a triple vi/ti/ni (vertex index, texture index, normal index).
1163 // An OBJ file could also have the formats: vi/ti or vi//ni
1164 // Indexes in the file should start on "1", this methods uses the value 0 to indicate that
1165 // there was no value in the file.
1166 {
1167  unsigned int& vi = *viPtr;
1168  unsigned int& ti = *tiPtr;
1169  unsigned int& ni = *niPtr;
1170  ti = ni = 0;
1171  string vertexString;
1172  iss >> vertexString; // iss is the whole line, vertexString is the triplet part
1173  if (vertexString.empty())
1174  throw "Input Finished";
1175  unsigned int slashOccurrences = CountOccurrences('/', vertexString);
1176  istringstream vStream(vertexString);
1177  try {
1178  char slash;
1179  vStream >> vi >> slash;
1180  if (slashOccurrences == 2) {
1181  if(vStream.peek() != '/')
1182  vStream >> ti;
1183  else {
1184  static bool notWarned = true;
1185  if (notWarned) {
1186  clog << "Warning: OBJ file is missing texture indices.\n";
1187  notWarned = false;
1188  }
1189  }
1190  vStream >> slash;
1191  }
1192  else {
1193  static bool notWarned = true;
1194  if (notWarned) {
1195  cerr << "Error: OBJ file is missing normal indices.\n";
1196  notWarned = false;
1197  }
1198  }
1199  vStream >> ni;
1200  }
1201  catch (...) {
1202  cerr << "Error while reading. See MeshObject::ReadVertex.\n";
1203  throw 4;
1204  }
1205 }
1206 // static, protected
1207 void VART::MeshObject::ReadVerticesLine(std::istringstream& input,
1208  std::list<VertexTriplet>* resultPtr)
1209 // Reads all vertex triplets from a "face" line in a LightWaveOBJ file.
1210 {
1211  resultPtr->clear();
1212  unsigned int vi, ni, ti;
1213  try {
1214  while(true) { // Read every vertex triplet
1215  ReadVertex(input, &vi, &ni, &ti);
1216  resultPtr->push_back(VertexTriplet(vi, ni, ti));
1217  }
1218  }
1219  catch (char const* error) {
1220  }
1221 }
1222 
1223 namespace VART
1224 {
1225  ostream& operator<<(ostream& output, const MeshObject& m)
1226  {
1227  unsigned int size = m.vertCoordVec.size();
1228  output << "[ MeshObject '" << m.description << "'\n" << flush
1229  << " " << size/3 << " vertices: (";
1230  for (unsigned int i = 0; i < size; ++i) {
1231  output << m.vertCoordVec[i] << ",";
1232  output << m.vertCoordVec[++i] << ",";
1233  output << m.vertCoordVec[++i] << "; ";
1234  }
1235  if (not m.textCoordVec.empty()) {
1236  output << ")\n " << size/3 << " texture coordinates: ( ";
1237  for (unsigned int i = 0; i < size; ++i) {
1238  output << m.textCoordVec[i] << ",";
1239  output << m.textCoordVec[++i] << ",";
1240  output << m.textCoordVec[++i] << "; ";
1241  }
1242  }
1243  output << ")\n " << m.meshList.size() << " meshes: ";
1244  list<Mesh>::const_iterator iter = m.meshList.begin();
1245  for (; iter != m.meshList.end(); ++iter)
1246  output << "(" << *iter << ")\n";
1247  output << "]";
1248  return output;
1249  }
1250 }
unsigned int CountOccurrences(char c, string s)
Definition: meshobject.cpp:19
Base class for objects that compose a scene graph.
Definition: scenenode.h:25
Point4D GetVertex(unsigned int pos)
Returns a copy of a vertex.
Definition: meshobject.cpp:144
static void ReadMaterialTable(const std::string &filename, std::map< std::string, Material > *matMapPtr)
Points and vectors using homogeneous coordinates.
Definition: point4d.h:22
std::vector< unsigned int > normIndVec
indexes of the normals (for unoptimized meshes)
Definition: mesh.h:64
void AddNormal(unsigned int idx, const Point4D &vec)
Adds a vector to a vertex normal.
Definition: meshobject.cpp:158
void SetEmissiveColor(const Color &c)
Sets the emissive color of the material.
Definition: material.h:61
void ApplyTo(Point4D *ptPoint) const
Applies tranformation to a point.
Definition: transform.cpp:149
static void ComputeTriangleNormal(const Point4D &v1, const Point4D &v2, const Point4D &v3, Point4D *resultPtr)
Computes the normal of a triangle.
Definition: meshobject.cpp:685
void CutBBox(const BoundingBox &box)
Test against other bounding box and update itself if its outside the given bbox.
void SetBoundingBox(double minX, double minY, double minZ, double maxX, double maxY, double maxZ)
void AddFace(const char *indexStr)
Adds a face (a mesh of a single polygon) based on previously set vertices.
Definition: meshobject.cpp:244
MeshType type
Definition: mesh.h:66
static const Color & GREEN()
Green opaque color.
Definition: color.cpp:80
void SetShininess(float newValue)
Set the shininess of the material.
Definition: material.h:79
std::list< Mesh > meshList
List of Meshes.
Definition: meshobject.h:283
static const Material & DARK_PLASTIC_GRAY()
Definition: material.cpp:70
void Normalize()
Normalizes the point/vector.
Definition: point4d.cpp:88
void ConditionalUpdate(double x, double y, double z)
Updates the bounding box if any given coordinate is outside it.
double GetZ() const
Definition: point4d.h:80
bool HasData() const
Indicates if a texture object contains data.
Definition: texture.h:92
std::string description
Textual identification.
Definition: scenenode.h:162
void GetYProjection(std::list< Point4D > *resultPtr, double height=0) const
Computes the projection of all vertices along the Y axis.
Definition: meshobject.cpp:344
void SetAmbientColor(const Color &c)
Sets the ambient color of the material.
Definition: material.h:55
RGBA color representation.
Definition: color.h:24
double GetY() const
Definition: point4d.h:79
Axis aligned bounding box.
Definition: boundingbox.h:23
Header file for V-ART class "File".
void SetVertices(const std::vector< Point4D > &vertexVec)
Sets the vector of vertices.
void SetColor(const Color &value)
Sets the bounding box color.
Definition: boundingbox.h:93
double GetGreaterZ() const
Definition: boundingbox.cpp:93
A mesh is part of an graphical object, in which faces are made of vertices according to some rule of ...
Definition: mesh.h:30
double GetSmallerX() const
bool testPoint(VART::Point4D p)
Test if a point is included in the bbox.
void IncrementIndices(unsigned int increment)
Returns the mesh type as OpenGL enum.
Definition: mesh.cpp:27
Point4D GetVertexMedia()
Return the Aritmethic mean of vertexes values.
Definition: meshobject.cpp:221
bool IsEmpty()
Checks whether the object contains geometry data.
Definition: meshobject.h:160
std::vector< double > normCoordVec
Vector of all vertex normals (their coordinates in sequence).
Definition: meshobject.h:274
void NormalizeAllNormals()
Normalizes all vertex normals.
Geometric transformations.
Definition: transform.h:24
void SetTexture(const Texture &t)
Sets the texture of material.
Definition: material.cpp:106
Point4D CrossProduct(const Point4D &p) const
Computes the cross product between "this" and "p".
Definition: point4d.cpp:121
void SetXYZ(double x, double y, double z)
Definition: point4d.cpp:73
static std::string GetPathFromString(const std::string &fileName)
Definition: file.cpp:9
void SetSpecularColor(const Color &c)
Sets the specular color (highlight color) of the material.
Definition: material.h:49
void SmallerVertex(Point4D *resultPtr)
Computes and returns the smaller vertex.
Definition: meshobject.cpp:192
2D image to use as texture.
Definition: texture.h:48
void SetDiffuseColor(const Color &c)
Sets the diffuse color (main color) of the material.
Definition: material.h:43
virtual void ComputeBoundingBox()
Computes the bounding box.
Definition: meshobject.cpp:375
void Clear()
Erases internal structures.
Definition: meshobject.cpp:59
double GetSmallerY() const
MeshType
Definition: mesh.h:34
void SetDescription(const std::string &desc)
Changes the object's description.
Definition: scenenode.h:53
Material properties for graphical objects.
Definition: material.h:16
static const Color & BLACK()
Black opaque color.
Definition: color.cpp:70
std::vector< float > textCoordVec
Vector of all texture coordinates.
Definition: meshobject.h:280
double GetGreaterY() const
Definition: boundingbox.cpp:89
void SetMaterial(const Material &mat)
Assigns a material to all meshes of the mesh object.
Definition: meshobject.cpp:69
ostream & operator<<(ostream &output, const MeshObject &m)
virtual bool DrawInstanceOGL() const
Non-recursive drawing - should be overriden by every derived class.
Definition: meshobject.cpp:693
void ComputeSubBBoxes(const Transform &trans, int subdivisions)
Computes de SubBBoxes and stores them.
Definition: meshobject.cpp:431
void AddMesh(const Mesh &m)
Adds a copy of the mesh to the object.
Definition: meshobject.cpp:270
std::vector< unsigned int > indexVec
indexes of the vertices (start at 0) defining faces
Definition: mesh.h:62
unsigned int NumFaces()
Computes the number of faces.
Definition: meshobject.cpp:168
void ApplyTransform(const Transform &trans)
Apply Transformation to all vertices.
Definition: meshobject.cpp:658
static float sizeOfNormals
Size of normals for rendering (in world coordinates).
Definition: meshobject.h:212
void SetVertex(unsigned int index, const Point4D &newValue)
Changes one vertex.
Definition: meshobject.cpp:129
void SetNormals(const std::vector< Point4D > &normalVec)
Sets the vector of normals.
Definition: meshobject.cpp:91
const Point4D & GetCenter() const
static void ReadVertex(std::istringstream &iss, unsigned int *vi, unsigned int *ti, unsigned int *ni)
Reads a vertex description from a face on a OBJ file.
std::vector< double > vertCoordVec
Vector of all vertex coordinates (their coordinates in sequence).
Definition: meshobject.h:262
std::vector< Point4D > normVec
Vector of all normals.
Definition: meshobject.h:268
static void ReadVerticesLine(std::istringstream &input, std::list< VertexTriplet > *resultPtr)
void SetXYZW(double x, double y, double z, double w)
Definition: point4d.cpp:80
Header file for V-ART class "MeshObject".
void Optimize()
Optimize object for display.
Definition: meshobject.cpp:369
std::vector< Point4D > vertVec
Vector of all vertices.
Definition: meshobject.h:255
static bool ReadFromOBJ(const std::string &filename, std::list< MeshObject * > *resultPtr)
Read MeshObjects from a Wavefront OBJ file.
Definition: meshobject.cpp:775
void MakeBox(double minX, double maxX, double minY, double maxY, double minZ, double maxZ)
Creates a box aligned with the 3 reference planes (XY, XZ and YZ).
Definition: meshobject.cpp:275
void MergeWith(const MeshObject &obj)
Merges one mesh object with another.
Definition: meshobject.cpp:633
virtual VART::SceneNode * Copy()
Returns a copy of an MeshObject. Every derived class must reimplements this method, to avoid errors with VART::SceneNode::RecursiveCopy.
Definition: meshobject.cpp:54
void ComputeVertexNormals()
Computes the normal of every vertex.
Definition: meshobject.cpp:475
double GetX() const
Definition: point4d.h:78
double GetGreaterX() const
Definition: boundingbox.cpp:85
double GetSmallerZ() const
Graphical object made of polygon meshes.
Definition: meshobject.h:25
MeshObject & operator=(const MeshObject &obj)
Definition: meshobject.cpp:42
bool LoadFromFile(const std::string &fileName)
Loads a texture from a file.
Definition: texture.cpp:50
Material material
Definition: mesh.h:65