voxelTerrain
 All Classes Functions Variables Typedefs Enumerations Pages
surface.hpp
1 #ifndef PROCEDURAL_VOXEL_TILE_SURFACE_HPP
2 #define PROCEDURAL_VOXEL_TILE_SURFACE_HPP
3 
4 #include "blub/core/array.hpp"
5 #include "blub/core/sharedPointer.hpp"
6 #include "blub/core/vector.hpp"
7 #include "blub/math/vector2int.hpp"
8 #include "blub/math/vector3.hpp"
9 #include "blub/math/vector3int.hpp"
10 #include "blub/procedural/voxel/tile/base.hpp"
11 #include "blub/procedural/voxel/tile/internal/transvoxelTables.hpp"
12 
13 
14 namespace blub
15 {
16 namespace procedural
17 {
18 namespace voxel
19 {
20 namespace tile
21 {
22 
23 
32 template <class configType>
33 class surface : public base<surface<configType> >
34 {
35 public:
36  typedef configType t_config;
37  typedef base<surface<t_config> > t_base;
38  typedef typename t_config::t_surface::t_tile* t_thiz;
39  typedef typename t_config::t_accessor::t_tile t_voxelAccessor;
40  typedef sharedPointer<t_voxelAccessor> t_voxelAccessorPtr;
41  typedef vector<typename t_config::t_vertex> t_vertices;
42  typedef vector<typename t_config::t_index> t_indices;
43  typedef typename t_config::t_data t_voxel;
44  typedef typename t_config::t_vertex t_vertex;
45 
46  typedef array<t_voxel, 2*2*2> t_calcVoxel;
47  typedef array<t_voxel, 3*3*3+2*2> t_calcVoxelLod;
48 
53  static typename t_base::pointer create()
54  {
55  return new surface();
56  }
57 
63  static typename t_base::pointer createCopy(typename t_base::pointer toCopy)
64  {
65  typename t_base::pointer result(new surface(*toCopy.get()));
66  return result;
67  }
72  {
73 #ifdef BLUB_LOG_VOXEL_SURFACE
74  blub::BOUT("surface::~surface()");
75 #endif
76  }
77 
85  void calculateSurface(const t_voxelAccessorPtr voxel,
86  const real &voxelSize = 1.,
87  const bool& calculateNormalCorrection = true,
88  const int32 &lod = 0)
89  {
90 #ifdef BLUB_LOG_VOXEL_SURFACE
91  blub::BOUT("surface::calculateSurface(..) lod:" + blub::string::number(lod));
92 #endif
93 
94 
95  static_cast<t_thiz>(this)->clear();
96 
97  m_voxel = voxel;
98  m_lod = lod;
99 
100  m_vertices.reserve(1000);
101  m_indices.reserve(2000);
102 
103  const vector3int32 voxelStart(-1);
104  const vector3int32 voxelEnd(t_voxelAccessor::voxelLength+2);
105 
106  const int32 vertexIndicesReuseSize(((voxelEnd.x-voxelStart.x)*3)*((voxelEnd.y-voxelStart.y)*3)*((voxelEnd.z-voxelStart.z)*3));
107  // the indexer for the vertices. *3 because gets saved with edge-id
108  int32 *vertexIndicesReuse = new int32[vertexIndicesReuseSize];
109  for (int32 index = 0; index < vertexIndicesReuseSize; ++index)
110  {
111  vertexIndicesReuse[index] = -1;
112  }
113 
114  // isLevel describes at which interpolation-level a surface is generated around the voxel
115  const int8 isoLevel(0);
116  for (int32 x = voxelStart.x; x < voxelEnd.x-1; ++x)
117  {
118  for (int32 y = voxelStart.y; y < voxelEnd.y-1; ++y)
119  {
120  for (int32 z = voxelStart.z; z < voxelEnd.z-1; ++z)
121  {
122  // depending on the voxel-neighbour- the count and look, of the triangles gets calculated.
123  uint8 tableIndex(0);
124  const vector3int32 posVoxel(x, y, z);
125  t_calcVoxel voxelCalc;
126  const vector3int32 toCheck[] = {
127  vector3int32(0, 0, 0),
128  vector3int32(1, 0, 0),
129  vector3int32(0, 0, 1),
130  vector3int32(1, 0, 1),
131  vector3int32(0, 1, 0),
132  vector3int32(1, 1, 0),
133  vector3int32(0, 1, 1),
134  vector3int32(1, 1, 1)
135  };
136  uint16 toAddToTableIndex(1);
137  for (uint16 indCheck = 0; indCheck < 8; ++indCheck)
138  {
139  voxelCalc[indCheck] = getVoxel(posVoxel + toCheck[indCheck]); // <-- acc to valgrind getVoxel is the most expensivec call;
140  if (voxelCalc[indCheck].getInterpolation() < isoLevel) // OPTIMISE reuse "voxelCalc", instead of calling getVoxel 2 times later!
141  {
142  tableIndex |= toAddToTableIndex;
143  }
144  toAddToTableIndex*=2;
145  }
146 
147  // Now create a triangulation of the isosurface in this
148  // cell.
149  if (tableIndex == 0 || tableIndex == 255)
150  {
151  continue;
152  }
153  bool calculateFaces(true);
154  if (calculateNormalCorrection)
155  {
156  calculateFaces = (posVoxel >= vector3int32(0) && posVoxel < voxelEnd - vector3int32(2));
157  }
158  // OPTIMISE: too many vertices get calculated because of normalcorrection; optimise!
159  const RegularCellData *data = &regularCellData[regularCellClass[tableIndex]];
160  int32 ids[12];
161  for (int32 ind = 0; ind < data->GetVertexCount(); ++ind)
162  {
163  int32 data2 = regularVertexData[tableIndex][ind];
164  int32 corner0 = data2 & 0x0F;
165  int32 corner1 = (data2 & 0xF0) >> 4;
166  int32 id = calculateEdgeId(posVoxel, data2 >> 8); // for reuse
167  BASSERT(id >= 0);
168  BASSERT(id < vertexIndicesReuseSize);
169 
170  if (vertexIndicesReuse[id] == -1)
171  {
172  vector3 point = calculateIntersectionPosition(posVoxel, corner0, corner1); // OPTIMISE so dirty - use voxelCalc inside the method!
173  // we calucluate here everything in positive values; but normal correction starts @ -1
174  point *= voxelSize;
175  t_voxel voxel0 = getVoxel(posVoxel + calculateCorner(corner0)); // OPTIMISE so dirty - use voxelCalc!
176  t_voxel voxel1 = getVoxel(posVoxel + calculateCorner(corner1));
177  const t_vertex vertex(static_cast<t_thiz>(this)->createVertex(posVoxel, voxel0, voxel1, point, vector3()));
178  m_vertices.push_back(vertex);
179  ids[ind] = vertexIndicesReuse[id] = m_vertices.size()-1;
180  }
181  else
182  {
183  ids[ind] = vertexIndicesReuse[id];
184  }
185  }
186  for (int32 ind = 0; ind < data->GetTriangleCount()*3; ind+=3)
187  {
188  // calc triangle and normal
189  const int32 vertexIndex0(ids[data->vertexIndex[ind+0]]);
190  const int32 vertexIndex1(ids[data->vertexIndex[ind+1]]);
191  const int32 vertexIndex2(ids[data->vertexIndex[ind+2]]);
192  const vector3 vertex0(m_vertices.at(vertexIndex0).position);
193  const vector3 vertex1(m_vertices.at(vertexIndex1).position);
194  const vector3 vertex2(m_vertices.at(vertexIndex2).position);
195  if (vertex0 == vertex1 || vertex0 == vertex2 || vertex1 == vertex2)
196  {
197  continue; // triangle with zero space
198  }
199  const vector3 addNormal = (vertex1 - vertex0).crossProduct(vertex2 - vertex0);//.normalisedCopy();
200  // if (calculateFaces) // for normal-correction-test
201  {
202  m_vertices.at(vertexIndex0).normal += addNormal;
203  m_vertices.at(vertexIndex1).normal += addNormal;
204  m_vertices.at(vertexIndex2).normal += addNormal;
205  }
206  if (calculateFaces)
207  {
208  // insert new triangle
209  m_indices.push_back(vertexIndex0);
210  m_indices.push_back(vertexIndex1);
211  m_indices.push_back(vertexIndex2);
212  }
213  }
214  }
215  }
216  }
217 
218  // transvoxel
219  if (m_lod > 0)// && false)
220  {
221  typedef vector3int32 v3i;
222  const vector3int32 voxelLookups[][9] = {
223  {v3i(0, 0, 0),v3i(0, 1, 0),v3i(0, 2, 0),v3i(0, 2, 1),v3i(0, 2, 2),v3i(0, 1, 2),v3i(0, 0, 2),v3i(0, 0, 1),v3i(0, 1, 1)},
224  {v3i(0, 0, 0),v3i(1, 0, 0),v3i(2, 0, 0),v3i(2, 0, 1),v3i(2, 0, 2),v3i(1, 0, 2),v3i(0, 0, 2),v3i(0, 0, 1),v3i(1, 0, 1)},
225  {v3i(0, 0, 0),v3i(1, 0, 0),v3i(2, 0, 0),v3i(2, 1, 0),v3i(2, 2, 0),v3i(1, 2, 0),v3i(0, 2, 0),v3i(0, 1, 0),v3i(1, 1, 0)},
226  };
227  const int32 voxelLengthLodStart(t_voxelAccessor::voxelLengthLod-2);
228  const int32 voxelLengthLodEnd(t_voxelAccessor::voxelLengthLod-1);
229  const vector3int32 toIterate[][2] = {
230  {v3i(0, 0, 0), v3i(1, voxelLengthLodStart, voxelLengthLodStart)},
231  {v3i(voxelLengthLodStart, 0, 0), v3i(voxelLengthLodEnd, voxelLengthLodStart, voxelLengthLodStart)},
232  {v3i(0, 0, 0), v3i(voxelLengthLodStart, 1, voxelLengthLodStart)},
233  {v3i(0, voxelLengthLodStart, 0), v3i(voxelLengthLodStart, voxelLengthLodEnd, voxelLengthLodStart)},
234  {v3i(0, 0, 0), v3i(voxelLengthLodStart, voxelLengthLodStart, 1)},
235  {v3i(0, 0, voxelLengthLodStart), v3i(voxelLengthLodStart, voxelLengthLodStart, voxelLengthLodEnd)}
236  };
237  const vector3int32 reuseCorrection[] = {
238  v3i(1, 0, 0),
239  v3i(1, 0, 0),
240  v3i(0, 1, 0),
241  v3i(0, 1, 0),
242  v3i(0, 0, 1),
243  v3i(0, 0, 1)
244  };
245 
246  const bool toInvertTriangles[] = {
247  false, true,
248  true, false, // data from Eric Lengyel seems to have different axis-desc
249  false, true
250  };
251 
252  for (int32 lod = 0; lod < 6; ++lod)
253  {
254  const int32 coord(lod/2);
255  const vector3int32& start(toIterate[lod][0]);
256  const vector3int32& end (toIterate[lod][1]);
257  const bool invertTriangles(toInvertTriangles[lod]);
258 
259  // the indexer for the vertices. *3 because gets saved with edge-id
260  const int32 vertexIndicesReuseLodSize(((t_voxelAccessor::voxelLength+1)*4)*
261  ((t_voxelAccessor::voxelLength+1)*4));
262  vector<int32> vertexIndicesReuseLod(vertexIndicesReuseLodSize, -1);
263 
264  for (uint32 x = start.x; x < (unsigned)end.x; x+=2)
265  {
266  for (uint32 y = start.y; y < (unsigned)end.y; y+=2)
267  {
268  for (uint32 z = start.z; z < (unsigned)end.z; z+=2)
269  {
270  const vector3int32 voxelPos(x, y, z);
271  {
272  uint32 tableIndex(0);
273  uint32 add(1);
274  t_calcVoxelLod voxelCalc;
275  for (uint16 ind = 0; ind < 9; ++ind)
276  {
277  const vector3int32 lookUp((voxelPos-start)+voxelLookups[coord][ind]);
278  voxelCalc[ind] = getVoxelLod(lookUp, lod);
279  if (voxelCalc[ind].getInterpolation() < isoLevel)
280  {
281  tableIndex |= add;
282  }
283  add*=2;
284  }
285  if (tableIndex == 0 || tableIndex == 511) // no triangles
286  {
287  continue;
288  }
289 
290  uint32 classIndex = transitionCellClass[tableIndex];
291  const TransitionCellData *data = &transitionCellData[classIndex & 0x7F]; // only the last 7 bit count
292  uint32 ids[12];
293 
294  vector3 normalsForTransvoxel[4];
295 
296  for (uint16 ind = 0; ind < data->GetVertexCount(); ++ind)
297  {
298  const uint16 data2 = transitionVertexData[tableIndex][ind];
299  const uint16 edge = data2 >> 8;
300  const uint16 edgeId = edge & 0x0F;
301  const uint16 edgeBetween(data2 & 0xFF);
302 
303  if (edgeId == 0x9 || edgeId == 0x8)
304  {
305  BASSERT(edge == 0x88 || edge == 0x28 || edge == 0x89 || edge == 0x19);
306 
307  const uint16 owner((edge & 0xF0) >> 4);
308  BASSERT(owner == 1 || owner == 2 || owner == 8);
309 
310  uint16 newEdgeId(0);
311  uint16 newOwner(0);
312 
313  if (coord == 0)
314  {
315  if (edgeId == 0x8)
316  {
317  newEdgeId = 0x3;
318  }
319  else
320  {
321  newEdgeId = 0x1;
322  }
323  if (owner == 0x1)
324  {
325  newOwner = 0x4;
326  }
327  if (owner == 0x2)
328  {
329  newOwner = 0x2;
330  }
331  }
332  if (coord == 1)
333  {
334  if (edgeId == 0x8)
335  {
336  newEdgeId = 0x2;
337  }
338  else
339  {
340  newEdgeId = 0x1;
341  }
342  newOwner = owner;
343  }
344  if (coord == 2)
345  {
346  newEdgeId = edgeId - 6;
347  if (owner == 0x1)
348  {
349  newOwner = 0x1;
350  }
351  if (owner == 0x2)
352  {
353  newOwner = 0x4;
354  }
355  }
356 
357 
358  uint16 newEdge((newOwner << 4) | newEdgeId);
359  const int32 id = calculateEdgeId((voxelPos / 2) - reuseCorrection[lod], newEdge);
360 
361  BASSERT(vertexIndicesReuse[id] != -1);
362 
363  ids[ind]=vertexIndicesReuse[id];
364 
365  const vector3& normal(m_vertices.at(ids[ind]).normal);
366  switch (edgeBetween)
367  {
368  case 0x9A:
369  normalsForTransvoxel[0] = normal;
370  break;
371  case 0xAC:
372  normalsForTransvoxel[1] = normal;
373  break;
374  case 0xBC:
375  normalsForTransvoxel[2] = normal;
376  break;
377  case 0x9B:
378  normalsForTransvoxel[3] = normal;
379  break;
380  default:
381  BASSERT(false);
382  }
383  }
384  }
385  for (uint16 ind = 0; ind < data->GetVertexCount(); ++ind)
386  {
387  const uint16 data2 = transitionVertexData[tableIndex][ind];
388  const uint16 edge = data2 >> 8;
389  const uint16 edgeId = edge & 0x0F;
390  const uint16 edgeBetween(data2 & 0xFF);
391 
392  if (edgeId != 0x9 && edgeId != 0x8)
393  {
394  const uint16 corner0 = data2 & 0x0F;
395  const uint16 corner1 = (data2 & 0xF0) >> 4;
396 
397 
398  const int32 id = calculateEdgeIdTransvoxel(voxelPos/2, edge, coord);
399 
400  //blub::BOUT("edge:" + blub::string::number(edge, 16) + " id:" + blub::string::number(id));
401 
402  bool calculateVertexPosition(id == -1);
403  if (!calculateVertexPosition)
404  {
405  calculateVertexPosition = vertexIndicesReuseLod[id] == -1;
406  }
407 
408  if (calculateVertexPosition)
409  {
410  vector3 point = calculateIntersectionPositionTransvoxel(voxelPos-start, corner0, corner1, voxelLookups[coord], lod);
411  point+=vector3(start)/2.;
412 
413  point *= voxelSize;
414 
415  vector3 normal;
416 
417  switch (edgeBetween)
418  {
419  case 0x01:
420  case 0x12:
421  normal = normalsForTransvoxel[0];
422  break;
423  case 0x03:
424  case 0x36:
425  normal = normalsForTransvoxel[3];
426  break;
427  case 0x25:
428  case 0x58:
429  normal = normalsForTransvoxel[1];
430  break;
431  case 0x67:
432  case 0x78:
433  normal = normalsForTransvoxel[2];
434  break;
435  case 0x34:
436  case 0x14:
437  case 0x45:
438  case 0x47:
439  normal = normalsForTransvoxel[0] + normalsForTransvoxel[1] + normalsForTransvoxel[2] + normalsForTransvoxel[3];
440  break;
441  default:
442  BASSERT(false);
443  }
444 
445  t_voxel voxel0 = getVoxelLod(voxelPos-start + calculateCornerTransvoxel(corner0, voxelLookups[coord]), lod); // OPTIMISE so dirty - use voxelCalc!
446  t_voxel voxel1 = getVoxelLod(voxelPos-start + calculateCornerTransvoxel(corner1, voxelLookups[coord]), lod);
447  const t_vertex vertex(static_cast<t_thiz>(this)->createVertexLod(voxelPos, voxel0, voxel1, point, normal));
448  m_vertices.push_back(vertex);
449 
450  if (id == -1)
451  {
452  ids[ind] = m_vertices.size()-1;
453  }
454  else
455  {
456  ids[ind] = vertexIndicesReuseLod[id] = m_vertices.size()-1;
457  }
458  }
459  else
460  {
461  ids[ind] = vertexIndicesReuseLod[id];
462  }
463  }
464  }
465  for (uint16 ind = 0; ind < data->GetTriangleCount()*3; ind+=3)
466  {
467  // calc triangle
468  const int32 vertexIndex0(ids[data->vertexIndex[ind+0]]);
469  const int32 vertexIndex1(ids[data->vertexIndex[ind+1]]);
470  const int32 vertexIndex2(ids[data->vertexIndex[ind+2]]);
471  const vector3 vertex0(m_vertices.at(vertexIndex0).position);
472  const vector3 vertex1(m_vertices.at(vertexIndex1).position);
473  const vector3 vertex2(m_vertices.at(vertexIndex2).position);
474  if (vertex0 == vertex1 || vertex1 == vertex2 || vertex0 == vertex2)
475  {
476  continue; // triangle with zero space
477  }
478  // insert new triangle
479  uint16 invert(1);
480  if (invertTriangles)
481  {
482  invert = 0;
483  }
484  m_indicesLod[lod].push_back(vertexIndex0);
485  if ((classIndex >> 7) % 2 == invert)
486  {
487  m_indicesLod[lod].push_back(vertexIndex1);
488  m_indicesLod[lod].push_back(vertexIndex2);
489  }
490  else
491  {
492  m_indicesLod[lod].push_back(vertexIndex2);
493  m_indicesLod[lod].push_back(vertexIndex1);
494  }
495  }
496  }
497  }
498  }
499  }
500  }
501  }
502 
503  delete [] vertexIndicesReuse;
504 
505  // normalise normals
506  for (t_vertex& workVertex : m_vertices)
507  {
508  workVertex.normal.normalise();
509  }
510 
511 #ifdef BLUB_LOG_VOXEL_SURFACE
512  blub::BOUT("surface::calculateSurface(..) end");
513 #endif
514  }
515 
519  void clear()
520  {
521  m_vertices.clear();
522  m_indices.clear();
523  for (int32 lod = 0; lod < 6; ++lod)
524  {
525  m_indicesLod[lod].clear();
526  }
527  }
528 
534  {
535  return m_lod > 0;
536  }
537 
542  bool getCaluculateLod() const
543  {
544  return getCaluculateTransvoxel();
545  }
546 
551  const t_vertices& getVertices() const
552  {
553  return m_vertices;
554  }
559  const t_indices& getIndices() const
560  {
561  return m_indices;
562  }
567  const t_indices& getIndicesLod(const uint16& lod) const
568  {
569  BASSERT(lod < 6);
570  return m_indicesLod[lod];
571  }
572 
573 protected:
578  {
579  }
580 
584  t_vertex createVertex(const vector3int32& /*voxelPos*/, const t_voxel &/*voxel0*/, const t_voxel &/*voxel1*/, const vector3 &position, const vector3 &normal)
585  {
586  t_vertex result;
587  result.position = position;
588  result.normal = normal;
589  return result;
590  }
591 
595  t_vertex createVertexLod(const vector3int32& /*voxelPos*/, const t_voxel &/*voxel0*/, const t_voxel &/*voxel1*/, const vector3 &position, const vector3 &normal)
596  {
597  t_vertex result;
598  result.position = position;
599  result.normal = normal;
600  return result;
601  }
602 
603 private:
604  const t_voxel &getVoxel(const vector3int32& pos) const
605  {
606  return m_voxel->getVoxel(pos);
607  }
608  const int8 &getVoxelInterpolation(const vector3int32& pos) const
609  {
610  return getVoxel(pos).getInterpolation();
611  }
612  const t_voxel &getVoxelLod(const vector3int32& pos, const uint16 &lod) const
613  {
614  return m_voxel->getVoxelLod(pos, lod);
615  }
616  const int8 &getVoxelInterpolationLod(const vector3int32& pos, const uint16 &lod) const
617  {
618  return getVoxelLod(pos, lod).getInterpolation();
619  }
620  int32 calculateEdgeId(const vector3int32& pos, const int32& edgeInformation) const
621  {
622  const int32 edge(edgeInformation & 0x0F);
623  const int32 owner((edgeInformation & 0xF0) >> 4);
624  const int32 diffX(owner % 2);
625  const int32 diffY((owner >> 2) % 2); // !!! order
626  const int32 diffZ((owner >> 1) % 2);
627 
628  BASSERT((diffX == 0) || (diffX == 1));
629  BASSERT((diffY == 0) || (diffY == 1));
630  BASSERT((diffZ == 0) || (diffZ == 1));
631 
632  return calculateVertexId(pos - vector3int32(diffX, diffY, diffZ)) + (edge-1);
633  }
634  int32 calculateEdgeIdTransvoxel(const vector3int32& pos, const int32& edgeInformation, const int32& coord) const
635  {
636  const int32 edge(edgeInformation & 0x0F);
637  const int32 owner((edgeInformation & 0xF0) >> 4);
638  const int32 diffFst(owner % 2);
639  const int32 diffSnd((owner >> 1) % 2);
640 
641  BASSERT(edge >= 3);
642  BASSERT(edge <= 6);
643  BASSERT(owner == 1 || owner == 2 || owner == 4 || owner == 8);
644  BASSERT((diffFst == 0) || (diffFst == 1));
645  BASSERT((diffSnd == 0) || (diffSnd == 1));
646 
647  if (owner == 4) // no reuse
648  {
649  return -1;
650  }
651  switch (coord) {
652  case 0:
653  return calculateVertexIdTransvoxel(vector2int32(pos.y - diffFst, pos.z - diffSnd)) + (edge-3);
654  case 1:
655  return calculateVertexIdTransvoxel(vector2int32(pos.x - diffFst, pos.z - diffSnd)) + (edge-3);
656  case 2:
657  return calculateVertexIdTransvoxel(vector2int32(pos.x - diffFst, pos.y - diffSnd)) + (edge-3);
658  default:
659  break;
660  }
661 
662  BASSERT(false);
663  return -1;
664  }
665  int32 calculateVertexId(const vector3int32& pos) const
666  {
667  return (
668  ((pos.x+2)*3) * ((t_voxelAccessor::voxelLengthWithNormalCorrection)*3)*((t_voxelAccessor::voxelLengthWithNormalCorrection)*3) +
669  ((pos.y+2)*3) * ((t_voxelAccessor::voxelLengthWithNormalCorrection)*3) +
670  ((pos.z+2)*3)
671  );
672  }
673  int32 calculateVertexIdTransvoxel(const vector2int32& pos) const
674  {
675  return (pos.x+1)*4*(t_voxelAccessor::voxelLength+1) +
676  (pos.y+1)*4;
677  }
678  vector3 calculateIntersectionPosition(const vector3int32& pos, const int32& corner0, const int32& corner1)
679  {
680  const vector3int32 corn0(calculateCorner(corner0));
681  const vector3int32 corn1(calculateCorner(corner1));
682 
683  const int8 interpolation0 = getVoxelInterpolation(corn0+pos);
684  const int8 interpolation1 = getVoxelInterpolation(corn1+pos);
685 
686  const vector3 result = getInterpolatedPosition(vector3(corn0), vector3(corn1), interpolation0, interpolation1);
687 
688  return vector3(pos) + result;
689  }
690  vector3 calculateIntersectionPositionTransvoxel(const vector3int32& pos, const int32& corner0, const int32& corner1, const vector3int32 voxel[], const uint16 &lod)
691  {
692  const vector3int32 corn0(calculateCornerTransvoxel(corner0, voxel));
693  const vector3int32 corn1(calculateCornerTransvoxel(corner1, voxel));
694 
695  const int8 interpolation0 = getVoxelInterpolationLod(corn0+pos, lod);
696  const int8 interpolation1 = getVoxelInterpolationLod(corn1+pos, lod);
697 
698  const vector3 result = getInterpolatedPosition(vector3(corn0), vector3(corn1), interpolation0, interpolation1);
699 
700  return (vector3(pos) + result)/2.;
701  }
702  static vector3int32 calculateCorner(const int32& corner)
703  {
704  switch (corner)
705  {
706  case 0:
707  return vector3int32(0, 0, 0);
708  case 1:
709  return vector3int32(1, 0, 0);
710  case 2:
711  return vector3int32(0, 0, 1);
712  case 3:
713  return vector3int32(1, 0, 1);
714  case 4:
715  return vector3int32(0, 1, 0);
716  case 5:
717  return vector3int32(1, 1, 0);
718  case 6:
719  return vector3int32(0, 1, 1);
720  case 7:
721  return vector3int32(1, 1, 1);
722  default:
723  // fatal
724  break;
725  }
726  // never reach!
727  BASSERT(false);
728 
729  return vector3int32(0, 0, 0); // to remove the compile warning
730  }
731  static vector3int32 calculateCornerTransvoxel(const int32& corner, const vector3int32 voxel[])
732  {
733  switch (corner)
734  {
735  case 0x0:
736  return vector3int32(0, 0, 0);
737  case 0x1:
738  return voxel[1];
739  case 0x2:
740  return voxel[2];
741  case 0x3:
742  return voxel[7];
743  case 0x4:
744  return voxel[8];
745  case 0x5:
746  return voxel[3];
747  case 0x6:
748  return voxel[6];
749  case 0x7:
750  return voxel[5];
751  case 0x8:
752  return voxel[4];
753  case 0x9:
754  case 0xA:
755  case 0xB:
756  case 0xC:
757  default:
758  break;
759  }
760  BASSERT(false);
761  return vector3(0.);
762  }
763  static vector3 getInterpolatedPosition(const vector3& positionFrom, const vector3& positionTo, const int8& interpolationFrom, const int8& interpolationTo)
764  {
765  BASSERT(interpolationTo != interpolationFrom);
766 
767  const real mu((0.0 - ((real)interpolationFrom)) / ((real)(interpolationTo - interpolationFrom)));
768  const vector3 result = positionFrom + mu*(positionTo-positionFrom);
769 
770  return result;
771  }
772 
773 protected:
774  t_voxelAccessorPtr m_voxel;
775  int32 m_lod;
776 
777  t_vertices m_vertices;
778  t_indices m_indices;
779  t_indices m_indicesLod[6];
780 };
781 
782 
783 }
784 }
785 }
786 }
787 
788 
789 #endif // PROCEDURAL_VOXEL_TILE_SURFACE_HPP
Definition: transvoxelTables.hpp:36
Definition: customVertexInformation.cpp:186
Definition: customVertexInformation.cpp:193
Definition: vector.hpp:19
void calculateSurface(const t_voxelAccessorPtr voxel, const real &voxelSize=1., const bool &calculateNormalCorrection=true, const int32 &lod=0)
calculateSurface calculates the iso surface.
Definition: surface.hpp:85
const t_indices & getIndices() const
getIndices returns resulting index-list.
Definition: surface.hpp:559
t_vertex createVertex(const vector3int32 &, const t_voxel &, const t_voxel &, const vector3 &position, const vector3 &normal)
Creates a vertex.
Definition: surface.hpp:584
Definition: sharedPointer.hpp:12
t_vertex createVertexLod(const vector3int32 &, const t_voxel &, const t_voxel &, const vector3 &position, const vector3 &normal)
Creates a vertex for lod.
Definition: surface.hpp:595
const t_vertices & getVertices() const
getPositions returns resulting position-list.
Definition: surface.hpp:551
void clear()
clear erases all buffer/results.
Definition: surface.hpp:519
static t_base::pointer create()
create creates an instance.
Definition: surface.hpp:53
Definition: vector3.hpp:26
const t_indices & getIndicesLod(const uint16 &lod) const
getPositions returns resulting transvoxel-list. Vertices for these indices are in getPositions() and ...
Definition: surface.hpp:567
surface()
surface constructor
Definition: surface.hpp:577
The data class is the default voxel. Contains an 8-bit interpolation value. Replace/derive it and set...
Definition: data.hpp:27
bool getCaluculateLod() const
same as getCaluculateTransvoxel()
Definition: surface.hpp:542
bool getCaluculateTransvoxel() const
does the transvoxel algo get applied.
Definition: surface.hpp:533
int8 & getInterpolation()
getInterpolation returns reference to interpolation.
Definition: data.hpp:70
Definition: deadlineTimer.hpp:10
The accessor class contains a custom amount of level of details of type simple::accessor.
Definition: predecl.hpp:60
~surface()
~surface desctructor
Definition: surface.hpp:71
Definition: customVertexInformation.cpp:177
static t_base::pointer createCopy(typename t_base::pointer toCopy)
createCopy copies an instance.
Definition: surface.hpp:63
Definition: vertex.hpp:15
Definition: transvoxelTables.hpp:57