Hi everybody,
I have implemented a marching tetrahedra algorithm for the isosurface extraction. For the normals, I was only able to compute them per triangle as per vertes I need information about all neighbouring triangle. However, in neighboring cells I have no information about which triangles are adjacent to the cell so I cannot compute the normals per vertex. How is this normally done? Ma marching tetrahedra code is as follows :
void marching_tetras::MarchingCubesSplitter(Vec3f verts[8], float interpol[8],int parity, bool wireframe, bool raytracer,vector<triangle> &triangleList) {
//! Split each cube into 5 tetrahedra
//! need to alternate orientation of central tetrahedron to ensure the diagonals line up
if (parity) {
MarchingTetras(verts[0],verts[5],verts[3],verts[6],interpol[0],interpol[5],interpol[3],interpol[6],wireframe,raytracer,triangleList);
MarchingTetras(verts[0],verts[1],verts[3],verts[5],interpol[0],interpol[1],interpol[3],interpol[5],wireframe,raytracer,triangleList);
MarchingTetras(verts[0],verts[4],verts[5],verts[6],interpol[0],interpol[4],interpol[5],interpol[6],wireframe,raytracer,triangleList);
MarchingTetras(verts[0],verts[2],verts[6],verts[3],interpol[0],interpol[2],interpol[6],interpol[3],wireframe,raytracer,triangleList);
MarchingTetras(verts[3],verts[7],verts[6],verts[5],interpol[3],interpol[7],interpol[6],interpol[5],wireframe,raytracer,triangleList);
} else {
MarchingTetras(verts[2],verts[4],verts[1],verts[7],interpol[2],interpol[4],interpol[1],interpol[7],wireframe,raytracer,triangleList);
MarchingTetras(verts[5],verts[4],verts[7],verts[1],interpol[5],interpol[4],interpol[7],interpol[1],wireframe,raytracer,triangleList);
MarchingTetras(verts[2],verts[3],verts[7],verts[1],interpol[2],interpol[3],interpol[7],interpol[1],wireframe,raytracer,triangleList);
MarchingTetras(verts[4],verts[2],verts[1],verts[0],interpol[4],interpol[2],interpol[1],interpol[0],wireframe,raytracer,triangleList);
MarchingTetras(verts[2],verts[7],verts[6],verts[4],interpol[2],interpol[7],interpol[6],interpol[4],wireframe,raytracer,triangleList);
}
}
void marching_tetras::MarchingTetras(Vec3f a, Vec3f b, Vec3f c, Vec3f d,float val_a, float val_b, float val_c, float val_d, bool wireframe, bool raytracer,vector<triangle> &triangleList) {
//! figure out how masimulationGrid->getYSize() of the vertices are on each side of the isosurface
//! If value is smaller than 0 -> not part of fluid. Count is the number of vertices inside the volume
int count =
(val_a > m_isosurface) +
(val_b > m_isosurface) +
(val_c > m_isosurface) +
(val_d > m_isosurface);
//! handle each case
//! All vertices are inside the volume or outside the volume (This time of the tetrahedra, not the cube!)
if(count==0 || count==4) return;
//! Three vertices are inside the volume
else if (count == 3) {
//! Make sure that fourth value lies outside
if (val_d <= m_isosurface) MarchingTetrasHelper3(a,b,c,d,val_a,val_b,val_c,val_d,wireframe,raytracer,triangleList);
else if (val_c <= m_isosurface) MarchingTetrasHelper3(a,d,b,c,val_a,val_d,val_b,val_c,wireframe,raytracer,triangleList);
else if (val_b <= m_isosurface) MarchingTetrasHelper3(a,c,d,b,val_a,val_c,val_d,val_b,wireframe,raytracer,triangleList);
else MarchingTetrasHelper3(b,d,c,a,val_b,val_d,val_c,val_a,wireframe,raytracer,triangleList);
}
//! Two vertices are inside the volume
else if (count == 2) {
//! Make sure that the last two points lie outside
if (val_a > m_isosurface && val_b > m_isosurface) MarchingTetrasHelper2(a,b,c,d,val_a,val_b,val_c,val_d,wireframe,raytracer,triangleList);
else if (val_a > m_isosurface && val_c > m_isosurface) MarchingTetrasHelper2(a,c,d,b,val_a,val_c,val_d,val_b,wireframe,raytracer,triangleList);
else if (val_a > m_isosurface && val_d > m_isosurface) MarchingTetrasHelper2(a,d,b,c,val_a,val_d,val_b,val_c,wireframe,raytracer,triangleList);
else if (val_b > m_isosurface && val_c > m_isosurface) MarchingTetrasHelper2(b,c,a,d,val_b,val_c,val_a,val_d,wireframe,raytracer,triangleList);
else if (val_b > m_isosurface && val_d > m_isosurface) MarchingTetrasHelper2(b,d,c,a,val_b,val_d,val_c,val_a,wireframe,raytracer,triangleList);
else MarchingTetrasHelper2(c,d,a,b,val_c,val_d,val_a,val_b,wireframe,raytracer,triangleList);
}
//! One vertex is inside the volume
else if (count == 1) {
//! Make sure that the last three points lie outside
if (val_a > m_isosurface) MarchingTetrasHelper1(a,b,c,d,val_a,val_b,val_c,val_d,wireframe,raytracer,triangleList);
else if (val_b > m_isosurface) MarchingTetrasHelper1(b,c,a,d,val_b,val_c,val_a,val_d,wireframe,raytracer,triangleList);
else if (val_c > m_isosurface) MarchingTetrasHelper1(c,a,b,d,val_c,val_a,val_b,val_d,wireframe,raytracer,triangleList);
else MarchingTetrasHelper1(d,c,b,a,val_d,val_c,val_b,val_a,wireframe,raytracer,triangleList);
}
}
//! when 3 vertices are within the volume
void marching_tetras::MarchingTetrasHelper3(Vec3f a, Vec3f b, Vec3f c, Vec3f d, float val_a, float val_b, float val_c, float val_d,bool wireframe, bool raytracer,vector<triangle> &triangleList) {
//! Compute intersection points of isosurface with tetrahedron
float ad_frac = (m_isosurface - val_d) / (val_a - val_d);
float bd_frac = (m_isosurface - val_d) / (val_b - val_d);
float cd_frac = (m_isosurface - val_d) / (val_c - val_d);
//! Compute the vertices of the intersections of the isosurface with the tetrahedron
Vec3f ad = ad_frac*a + (1-ad_frac)*d;
Vec3f bd = bd_frac*b + (1-bd_frac)*d;
Vec3f cd = cd_frac*c + (1-cd_frac)*d;
//! Render the triangle
storeTriangle(ad,cd,bd);
}
//! when 2 vertices are within the volume
void marching_tetras::MarchingTetrasHelper2(Vec3f a, Vec3f b, Vec3f c, Vec3f d,float val_a,float val_b,float val_c,float val_d,bool wireframe,bool raytracer,vector<triangle> &triangleList) {
//! Compute the intersection points of isosurface with tetrahedron
float ac_frac = (m_isosurface - val_c) / (val_a - val_c);
float ad_frac = (m_isosurface - val_d) / (val_a - val_d);
float bc_frac = (m_isosurface - val_c) / (val_b - val_c);
float bd_frac = (m_isosurface - val_d) / (val_b - val_d);
//! Compute the vertices of the TWO triangles which mark the intersection of the isosurface with the tetrahedron
Vec3f ac = ac_frac*a + (1-ac_frac)*c;
Vec3f ad = ad_frac*a + (1-ad_frac)*d;
Vec3f bc = bc_frac*b + (1-bc_frac)*c;
Vec3f bd = bd_frac*b + (1-bd_frac)*d;
//! Render the two triangles
storeTriangle(ac,bc,ad);
storeTriangle(bc,bd,ad);
}
//! when 1 vertex is within the volume
void marching_tetras::MarchingTetrasHelper1(Vec3f a, Vec3f b, Vec3f c, Vec3f d,float val_a,float val_b,float val_c,float val_d, bool wireframe, bool raytracer,vector<triangle> &triangleList) {
//! Compute the intersection points of isosurface with tetrahedron
float ab_frac = (m_isosurface - val_b) / (val_a - val_b);
float ac_frac = (m_isosurface - val_c) / (val_a - val_c);
float ad_frac = (m_isosurface - val_d) / (val_a - val_d);
//! Compute the vertices of the intersections of the isosurface with the tetrahedron
Vec3f ab = ab_frac*a + (1-ab_frac)*b;
Vec3f ac = ac_frac*a + (1-ac_frac)*c;
Vec3f ad = ad_frac*a + (1-ad_frac)*d;
//! Render the triangle
storeTriangle(ab,ad,ac);
}