How could I polygonise a bool[,,] How could I polygonise a bool[,,] wpf wpf

How could I polygonise a bool[,,]


One of the assumptions of Marching Cube algorithm is that every cube geometry is a separate entity and doesn't depend on other cubes (which is not completely true but let's stick to this for now).

Given that, you can split entire mesh into cubes and solve each one separately. You may also notice, that although the final mesh depends on exact values of your 3D scalar field, the topology of the mesh depends only on fact if some given cube corner is inside of a mesh or outside.

For example: Let's say your isolevel is set to 0 and your 3D field has positive and negative numbers. If you now change some value from 0.1 to 1.0 then you'll change only proportions of some triangles but not their number and/or topology. On the other hand, if you change some value from 0.1 to -0.1 then your triangles may switch to another arrangement and their number may change.

Thanks to this we can use some clever optimization - for each of 8 corners you check if the corner is inside or outside of a mesh, you use those 8 bits to build a number - which becomes an index to your precomputed table of possible cube solutions, let's call them Variants.

Each Cube Variant is a list of triangles for this specific configuration of corners. Triangles in Marching Cubes always span between cube edges, so we use edge indices to describe it. Those indices are the exact data you see in those 'magic' tables in Paul Bourke code :).

But this is not the final mesh yet. The triangles you get here are based just on a fact if some corner is inside or outside of a mesh, but how far is it from the surface? Does it have any influence on the result? Here comes your grid values once again - when you've selected your Variant, got the list of triangles and 3 edges for each of those triangles, then you get the values on ends of the edge and interpolate them to find 0 value (we've set it as isolevel, remember?). Those final, interpolated vertices should be used for your mesh.

That became quite a long introduction, I hope you understand what I wrote.

My suggestion:The simplest change is with corners, instead of doing this:

if (grid.val[0] < isolevel) cubeindex |= 1;

Try to change it this way:

if (grid.val[0] > isolevelMin && grid.val[0] < isolevelMax) cubeindex |= 1;// And the same for other lines...

Final interpolation is a bit trickier and I have no way to test it but let's try:

  • Modify your VertexInterp to pass two isolevels - min and max
  • Inside VertexInterp check which isolevel is between valp1 and valp2 values
  • Interpolate as in the current code, but using selected isolevel (min or max)

And let me know if it worked :) or if you have any questions.


disclaimer: it won't be a full answer, as I don't have the time to put one right now, I'm not rushing for the bounty.

I'll start an idea for a way to do ray-tracing, that should produce a list of points visible on the outside of your shape.

basically for raytracing, you trace a ray from each point of each face (and maybe diagonal), this won't be the best way, but that should output something.

the ray is a vector, in this case if you go from the x,y plane on one side to the other it'll be something like this [pseudocode]

bool[,,] points = getpoints();bool[,,] outsidepoints = new bool[width,height,depth];//this is traceray from x,y,0 to x,y,depthfor(int x=0;x<width;x++){  for(int y=0;y<height;y++){    for(int z=0;z<depth;z++){      if (points[x,y,z]==true){        outsidepoints[x,y,z]=true        z=depth;//we break the last for      }    }  } }

do the same for all 6 combinations in the last loop (x=0..width, x=width..0, y=0..height etc...)

that should work well enough if you have no overhangs (e.g. a single convex shape), if you do they might get cut off.

once you have your external points you just need an algorithm to make them into triangles (something like making slices of connections in each plane along an axis, then sewing for the last 2 connections.)

ps: if what you want is just display, you can use raytracing by taking the value of first point that connects with the ray for each point of your display (expect an image every couple of seconds depending on your hardware and picture size.) for this you can use the Line drawing algorithm (check wikipedia, there's a sample, in 2d though) best thing about it is that you can directly get the color from your picture (just set a threshold at which the pixel is void (the ray passes through))

another edit: if you need any precision, pm me, or comment down here

using pass through rays:

bool lastwasempty=true;for(int x=0;x<width;x++){  for(int y=0;y<height;y++){    for(int z=0;z<depth;z++){      if (points[x,y,z]==true){        if(lastwasempty){           outsidepoints[x,y,z]=true        }        lastwasempty=false;      }else{        lastwasempty=true;      }    }  } }