0
\$\begingroup\$

I was trying to implement the marching cubes and combine every little cube this way:

  • I get a cube of vertices depending on their surfaceLevel
  • I look for the ones that are below the surfaceLevel and get the edges that relates to them
  • get a vertice out of the edge using the formula on: http://paulbourke.net/geometry/polygonise/
  • I put every vertex i created based on the edges on mesh.vertices
  • I make the order on mesh.triangles based of the edge number on triTable
  • i combine everything but i get this: problemCombining

Here's my code: https://pastebin.com/jqetCk8r. My guess was that the combine order of every marched little cube is not good. I've got no idea know how to solve this.

ps: the triTable doesn't show in the pastebin, i copied it from the same link above.

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Here is how to convert the raw triangles into welded vertices, face normals and vertex normals. It is a small code, and it works well:

void get_vertices_and_normals_from_triangles(vector<triangle> &t, vector<vertex_3> &fn, vector<vertex_3> &v, vector<vertex_3> &vn)
{
    fn.clear();
    v.clear();
    vn.clear();
    
    if(0 == t.size())
        return;

    cout << "Triangles: " << t.size() << endl;
    
    cout << "Welding vertices" << endl;
 
    // Insert unique vertices into set.
    set<vertex_3> vertex_set;
 
    for(vector<triangle>::const_iterator i = t.begin(); i != t.end(); i++)
    {
        vertex_set.insert(i->vertex[0]);
        vertex_set.insert(i->vertex[1]);
        vertex_set.insert(i->vertex[2]);
    }
 
    cout << "Vertices: " << vertex_set.size() << endl;

    cout << "Generating vertex indices" << endl;
 
    // Add indices to the vertices.
    for(set<vertex_3>::const_iterator i = vertex_set.begin(); i != vertex_set.end(); i++)
    {
        size_t index = v.size();
        v.push_back(*i);
        v[index].index = index;
    }
 
    vertex_set.clear();

    // Re-insert modifies vertices into set.
    for(vector<vertex_3>::const_iterator i = v.begin(); i != v.end(); i++)
        vertex_set.insert(*i);
 
    cout << "Assigning vertex indices to triangles" << endl;
   
    // Find the three vertices for each triangle, by index.
    set<vertex_3>::iterator find_iter;
 
    for(vector<triangle>::iterator i = t.begin(); i != t.end(); i++)
    {
        find_iter = vertex_set.find(i->vertex[0]);
        i->vertex[0].index = find_iter->index;
 
        find_iter = vertex_set.find(i->vertex[1]);
        i->vertex[1].index = find_iter->index;
 
        find_iter = vertex_set.find(i->vertex[2]);
        i->vertex[2].index = find_iter->index;
    }

    vertex_set.clear();

    cout << "Calculating normals" << endl;
    fn.resize(t.size());
    vn.resize(v.size());

    for(size_t i = 0; i < t.size(); i++)
    {
        vertex_3 v0 = t[i].vertex[1] - t[i].vertex[0];
        vertex_3 v1 = t[i].vertex[2] - t[i].vertex[0];
        fn[i] = v0.cross(v1);
        fn[i].normalize();

        vn[t[i].vertex[0].index] = vn[t[i].vertex[0].index] + fn[i];
        vn[t[i].vertex[1].index] = vn[t[i].vertex[1].index] + fn[i];
        vn[t[i].vertex[2].index] = vn[t[i].vertex[2].index] + fn[i];
    }

    for(size_t i = 0; i < vn.size(); i++)
        vn[i].normalize();
}

Where the less-than operator is implemented as:

inline bool operator<(const vertex_3 &right) const
{
    if(right.x > x)
        return true;
    else if(right.x < x)
        return false;

    if(right.y > y)
        return true;
    else if(right.y < y)
        return false;

    if(right.z > z)
        return true;
    else if(right.z < z)
        return false;

    return false;
}

Also, make sure that you sort the vertices before interpolation, if you're using floats instead of doubles. This is because cracks can form in the mesh if the vertices aren't sorted.

vertex_3 marching_cubes::vertex_interp(const float isovalue, vertex_3 p1, vertex_3 p2, float valp1, float valp2)
{
    // Sort the vertices so that cracks don't mess up the water-tightness of the mesh.
    // Note: the cracks don't appear if you use doubles instead of floats.
    if (p2 < p1)
    {
        vertex_3 tempv = p2;
        p2 = p1;
        p1 = tempv;

        float tempf = valp2;
        valp2 = valp1;
        valp1 = tempf;
    }

    const float epsilon = 1e-10f;

    if(fabs(isovalue - valp1) < epsilon)
        return(p1);

    if(fabs(isovalue - valp2) < epsilon)
        return(p2);

    if(fabs(valp1 - valp2) < epsilon)
        return(p1);

    float mu = (isovalue - valp1) / (valp2 - valp1);

    return p1 + (p2 - p1)*mu;
}

The full codes are at:

https://github.com/sjhalayka/marching_cubes

https://github.com/sjhalayka/opengl1_stlview

\$\endgroup\$
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .