1 #ifndef PROCEDURAL_VOXEL_TILE_SURFACE_HPP
2 #define PROCEDURAL_VOXEL_TILE_SURFACE_HPP
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"
32 template <
class configType>
33 class surface :
public base<surface<configType> >
37 typedef base<surface<t_config> > t_base;
38 typedef typename t_config::t_surface::t_tile* t_thiz;
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;
46 typedef array<t_voxel, 2*2*2> t_calcVoxel;
47 typedef array<t_voxel, 3*3*3+2*2> t_calcVoxelLod;
73 #ifdef BLUB_LOG_VOXEL_SURFACE
74 blub::BOUT(
"surface::~surface()");
86 const real &voxelSize = 1.,
87 const bool& calculateNormalCorrection =
true,
90 #ifdef BLUB_LOG_VOXEL_SURFACE
91 blub::BOUT(
"surface::calculateSurface(..) lod:" + blub::string::number(lod));
95 static_cast<t_thiz
>(
this)->
clear();
100 m_vertices.reserve(1000);
101 m_indices.reserve(2000);
104 const vector3int32 voxelEnd(t_voxelAccessor::voxelLength+2);
106 const int32 vertexIndicesReuseSize(((voxelEnd.x-voxelStart.x)*3)*((voxelEnd.y-voxelStart.y)*3)*((voxelEnd.z-voxelStart.z)*3));
108 int32 *vertexIndicesReuse =
new int32[vertexIndicesReuseSize];
109 for (int32 index = 0; index < vertexIndicesReuseSize; ++index)
111 vertexIndicesReuse[index] = -1;
115 const int8 isoLevel(0);
116 for (int32 x = voxelStart.x; x < voxelEnd.x-1; ++x)
118 for (int32 y = voxelStart.y; y < voxelEnd.y-1; ++y)
120 for (int32 z = voxelStart.z; z < voxelEnd.z-1; ++z)
125 t_calcVoxel voxelCalc;
136 uint16 toAddToTableIndex(1);
137 for (uint16 indCheck = 0; indCheck < 8; ++indCheck)
139 voxelCalc[indCheck] = getVoxel(posVoxel + toCheck[indCheck]);
140 if (voxelCalc[indCheck].getInterpolation() < isoLevel)
142 tableIndex |= toAddToTableIndex;
144 toAddToTableIndex*=2;
149 if (tableIndex == 0 || tableIndex == 255)
153 bool calculateFaces(
true);
154 if (calculateNormalCorrection)
161 for (int32 ind = 0; ind < data->GetVertexCount(); ++ind)
163 int32 data2 = regularVertexData[tableIndex][ind];
164 int32 corner0 = data2 & 0x0F;
165 int32 corner1 = (data2 & 0xF0) >> 4;
166 int32
id = calculateEdgeId(posVoxel, data2 >> 8);
168 BASSERT(
id < vertexIndicesReuseSize);
170 if (vertexIndicesReuse[
id] == -1)
172 vector3 point = calculateIntersectionPosition(posVoxel, corner0, corner1);
175 t_voxel voxel0 = getVoxel(posVoxel + calculateCorner(corner0));
176 t_voxel voxel1 = getVoxel(posVoxel + calculateCorner(corner1));
178 m_vertices.push_back(vertex);
179 ids[ind] = vertexIndicesReuse[id] = m_vertices.size()-1;
183 ids[ind] = vertexIndicesReuse[id];
186 for (int32 ind = 0; ind < data->GetTriangleCount()*3; ind+=3)
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)
199 const vector3 addNormal = (vertex1 - vertex0).crossProduct(vertex2 - vertex0);
202 m_vertices.at(vertexIndex0).normal += addNormal;
203 m_vertices.at(vertexIndex1).normal += addNormal;
204 m_vertices.at(vertexIndex2).normal += addNormal;
209 m_indices.push_back(vertexIndex0);
210 m_indices.push_back(vertexIndex1);
211 m_indices.push_back(vertexIndex2);
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)},
227 const int32 voxelLengthLodStart(t_voxelAccessor::voxelLengthLod-2);
228 const int32 voxelLengthLodEnd(t_voxelAccessor::voxelLengthLod-1);
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)}
246 const bool toInvertTriangles[] = {
252 for (int32 lod = 0; lod < 6; ++lod)
254 const int32 coord(lod/2);
257 const bool invertTriangles(toInvertTriangles[lod]);
260 const int32 vertexIndicesReuseLodSize(((t_voxelAccessor::voxelLength+1)*4)*
261 ((t_voxelAccessor::voxelLength+1)*4));
262 vector<int32> vertexIndicesReuseLod(vertexIndicesReuseLodSize, -1);
264 for (uint32 x = start.x; x < (
unsigned)end.x; x+=2)
266 for (uint32 y = start.y; y < (
unsigned)end.y; y+=2)
268 for (uint32 z = start.z; z < (
unsigned)end.z; z+=2)
272 uint32 tableIndex(0);
274 t_calcVoxelLod voxelCalc;
275 for (uint16 ind = 0; ind < 9; ++ind)
277 const vector3int32 lookUp((voxelPos-start)+voxelLookups[coord][ind]);
278 voxelCalc[ind] = getVoxelLod(lookUp, lod);
279 if (voxelCalc[ind].getInterpolation() < isoLevel)
285 if (tableIndex == 0 || tableIndex == 511)
290 uint32 classIndex = transitionCellClass[tableIndex];
294 vector3 normalsForTransvoxel[4];
296 for (uint16 ind = 0; ind < data->GetVertexCount(); ++ind)
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);
303 if (edgeId == 0x9 || edgeId == 0x8)
305 BASSERT(edge == 0x88 || edge == 0x28 || edge == 0x89 || edge == 0x19);
307 const uint16 owner((edge & 0xF0) >> 4);
308 BASSERT(owner == 1 || owner == 2 || owner == 8);
346 newEdgeId = edgeId - 6;
358 uint16 newEdge((newOwner << 4) | newEdgeId);
359 const int32
id = calculateEdgeId((voxelPos / 2) - reuseCorrection[lod], newEdge);
361 BASSERT(vertexIndicesReuse[
id] != -1);
363 ids[ind]=vertexIndicesReuse[id];
365 const vector3& normal(m_vertices.at(ids[ind]).normal);
369 normalsForTransvoxel[0] = normal;
372 normalsForTransvoxel[1] = normal;
375 normalsForTransvoxel[2] = normal;
378 normalsForTransvoxel[3] = normal;
385 for (uint16 ind = 0; ind < data->GetVertexCount(); ++ind)
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);
392 if (edgeId != 0x9 && edgeId != 0x8)
394 const uint16 corner0 = data2 & 0x0F;
395 const uint16 corner1 = (data2 & 0xF0) >> 4;
398 const int32
id = calculateEdgeIdTransvoxel(voxelPos/2, edge, coord);
402 bool calculateVertexPosition(
id == -1);
403 if (!calculateVertexPosition)
405 calculateVertexPosition = vertexIndicesReuseLod[id] == -1;
408 if (calculateVertexPosition)
410 vector3 point = calculateIntersectionPositionTransvoxel(voxelPos-start, corner0, corner1, voxelLookups[coord], lod);
421 normal = normalsForTransvoxel[0];
425 normal = normalsForTransvoxel[3];
429 normal = normalsForTransvoxel[1];
433 normal = normalsForTransvoxel[2];
439 normal = normalsForTransvoxel[0] + normalsForTransvoxel[1] + normalsForTransvoxel[2] + normalsForTransvoxel[3];
445 t_voxel voxel0 = getVoxelLod(voxelPos-start + calculateCornerTransvoxel(corner0, voxelLookups[coord]), lod);
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);
452 ids[ind] = m_vertices.size()-1;
456 ids[ind] = vertexIndicesReuseLod[id] = m_vertices.size()-1;
461 ids[ind] = vertexIndicesReuseLod[id];
465 for (uint16 ind = 0; ind < data->GetTriangleCount()*3; ind+=3)
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)
484 m_indicesLod[lod].push_back(vertexIndex0);
485 if ((classIndex >> 7) % 2 == invert)
487 m_indicesLod[lod].push_back(vertexIndex1);
488 m_indicesLod[lod].push_back(vertexIndex2);
492 m_indicesLod[lod].push_back(vertexIndex2);
493 m_indicesLod[lod].push_back(vertexIndex1);
503 delete [] vertexIndicesReuse;
506 for (t_vertex& workVertex : m_vertices)
508 workVertex.normal.normalise();
511 #ifdef BLUB_LOG_VOXEL_SURFACE
512 blub::BOUT(
"surface::calculateSurface(..) end");
523 for (int32 lod = 0; lod < 6; ++lod)
525 m_indicesLod[lod].clear();
570 return m_indicesLod[lod];
587 result.position = position;
588 result.normal = normal;
598 result.position = position;
599 result.normal = normal;
606 return m_voxel->getVoxel(pos);
608 const int8 &getVoxelInterpolation(
const vector3int32& pos)
const
612 const t_voxel &getVoxelLod(
const vector3int32& pos,
const uint16 &lod)
const
614 return m_voxel->getVoxelLod(pos, lod);
616 const int8 &getVoxelInterpolationLod(
const vector3int32& pos,
const uint16 &lod)
const
620 int32 calculateEdgeId(
const vector3int32& pos,
const int32& edgeInformation)
const
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);
626 const int32 diffZ((owner >> 1) % 2);
628 BASSERT((diffX == 0) || (diffX == 1));
629 BASSERT((diffY == 0) || (diffY == 1));
630 BASSERT((diffZ == 0) || (diffZ == 1));
632 return calculateVertexId(pos - vector3int32(diffX, diffY, diffZ)) + (edge-1);
634 int32 calculateEdgeIdTransvoxel(
const vector3int32& pos,
const int32& edgeInformation,
const int32& coord)
const
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);
643 BASSERT(owner == 1 || owner == 2 || owner == 4 || owner == 8);
644 BASSERT((diffFst == 0) || (diffFst == 1));
645 BASSERT((diffSnd == 0) || (diffSnd == 1));
653 return calculateVertexIdTransvoxel(vector2int32(pos.y - diffFst, pos.z - diffSnd)) + (edge-3);
655 return calculateVertexIdTransvoxel(vector2int32(pos.x - diffFst, pos.z - diffSnd)) + (edge-3);
657 return calculateVertexIdTransvoxel(vector2int32(pos.x - diffFst, pos.y - diffSnd)) + (edge-3);
665 int32 calculateVertexId(
const vector3int32& pos)
const
668 ((pos.x+2)*3) * ((t_voxelAccessor::voxelLengthWithNormalCorrection)*3)*((t_voxelAccessor::voxelLengthWithNormalCorrection)*3) +
669 ((pos.y+2)*3) * ((t_voxelAccessor::voxelLengthWithNormalCorrection)*3) +
673 int32 calculateVertexIdTransvoxel(
const vector2int32& pos)
const
675 return (pos.x+1)*4*(t_voxelAccessor::voxelLength+1) +
678 vector3 calculateIntersectionPosition(
const vector3int32& pos,
const int32& corner0,
const int32& corner1)
680 const vector3int32 corn0(calculateCorner(corner0));
681 const vector3int32 corn1(calculateCorner(corner1));
683 const int8 interpolation0 = getVoxelInterpolation(corn0+pos);
684 const int8 interpolation1 = getVoxelInterpolation(corn1+pos);
686 const vector3 result = getInterpolatedPosition(vector3(corn0), vector3(corn1), interpolation0, interpolation1);
688 return vector3(pos) + result;
690 vector3 calculateIntersectionPositionTransvoxel(
const vector3int32& pos,
const int32& corner0,
const int32& corner1,
const vector3int32 voxel[],
const uint16 &lod)
692 const vector3int32 corn0(calculateCornerTransvoxel(corner0, voxel));
693 const vector3int32 corn1(calculateCornerTransvoxel(corner1, voxel));
695 const int8 interpolation0 = getVoxelInterpolationLod(corn0+pos, lod);
696 const int8 interpolation1 = getVoxelInterpolationLod(corn1+pos, lod);
698 const vector3 result = getInterpolatedPosition(vector3(corn0), vector3(corn1), interpolation0, interpolation1);
700 return (vector3(pos) + result)/2.;
702 static vector3int32 calculateCorner(
const int32& corner)
707 return vector3int32(0, 0, 0);
709 return vector3int32(1, 0, 0);
711 return vector3int32(0, 0, 1);
713 return vector3int32(1, 0, 1);
715 return vector3int32(0, 1, 0);
717 return vector3int32(1, 1, 0);
719 return vector3int32(0, 1, 1);
721 return vector3int32(1, 1, 1);
729 return vector3int32(0, 0, 0);
731 static vector3int32 calculateCornerTransvoxel(
const int32& corner,
const vector3int32 voxel[])
736 return vector3int32(0, 0, 0);
763 static vector3 getInterpolatedPosition(
const vector3& positionFrom,
const vector3& positionTo,
const int8& interpolationFrom,
const int8& interpolationTo)
765 BASSERT(interpolationTo != interpolationFrom);
767 const real mu((0.0 - ((real)interpolationFrom)) / ((real)(interpolationTo - interpolationFrom)));
768 const vector3 result = positionFrom + mu*(positionTo-positionFrom);
774 t_voxelAccessorPtr m_voxel;
777 t_vertices m_vertices;
779 t_indices m_indicesLod[6];
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