Mesh surface area calculation errors after subdividing

Started by
6 comments, last by Sollum 6 years, 2 months ago

Hello!

I have this strange issue with mesh surface area calculation. Surface area increases, if i "subdivide" mesh to be more detailed and add more polygons, even tho the relative size remains the same.
Code is rather simple and the formula itself doesn't matter as much as differentiating results based on polygon count.


float total_area = 0;
int indice_count = finalMeshIndices.length;
for (int i = 0; i < indice_count; i += 3)
{
  float area = 0;

  Vector3 p1 = new Vector3(finalMeshVertexFloatArray[i + 0], finalMeshVertexFloatArray[i + 1], finalMeshVertexFloatArray[i + 2]);
  Vector3 p2 = new Vector3(finalMeshVertexFloatArray[i + 10], finalMeshVertexFloatArray[i + 11], finalMeshVertexFloatArray[i + 12]);
  Vector3 p3 = new Vector3(finalMeshVertexFloatArray[i + 20], finalMeshVertexFloatArray[i + 21], finalMeshVertexFloatArray[i + 22]);

  Vector3 e1 = p2.sub(p1);
  Vector3 e2 = p3.sub(p1);
  Vector3 e3 = e1.crs(e2);

  area = (float) (0.5 * Math.sqrt(e3.x * e3.x + e3.y * e3.y + e3.z * e3.z));

  if (Float.isNaN(area)) System.out.println("NaN... The fuck?");

  total_area += area;
}

I think the issue is with float precision, because i have the same issue if i take a model and flip it.

Here is visual representation
image.png.e7526cf68e7f6b037046b2f9524db25a.png

image.png.eeb1e102509c1c7e29027fa8e7bb194b.png

If i take a cube 1,1,1 its area is ~5
If i upscale it 3 times, its area becomes ~19

So it seems that float precision is a culprit here. At least i guess so.

Advertisement

For your sphere this is not surprising. You aren't just dividing the triangles, you are also moving the vertices outwards to lie on the sphere surface (otherwise subdividing wouldn't make the shape any rounder). And when you move those vertices outwards, you are increasing the volume of the shape (and hence the surface area).

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

Sorry for the late reply.

Yes, i though the same, but difference is way way way way way way to big in my opinion.
~5 times bigger surface area from subdividing 2 or 3 times.  And the volume itself becomes ~3 times bigger.

Different example: 
image.png.e2a8f69a2e565f7bcb0448642431d97f.pngimage.png.801b6ab9bf7d53779ddcd69e6efac434.png
 

Same model, only flipped in 3d modeling tool and loaded as a separate model.
Its area and volume differs.

Ok, this has to be an issue with how you are calculating the area. Looking at the function in your original post, one thing looks strange to me. The code references an index array, but then it doesn't use the index array to lookup the vertices. Is this an indexed mesh or not?

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

On 7.2.2018 at 8:38 PM, Sollum said:

Vector3 p2 = new Vector3(finalMeshVertexFloatArray[i + 10], finalMeshVertexFloatArray[i + 11], finalMeshVertexFloatArray[i + 12]);

Agree, looks like an indexing bug. Your vertices have 10 floats? Increasing i by 3 makes little sense, probably forgot to read the index?


for (int i = 0; i < indice_count; i += 3)

But why do you allocate the vertices with new? (even if that's intended, you forgot to delete it.) 

:)

2 minutes ago, JoeJ said:

But why do you allocate the vertices with new? (even if that's intended, you forgot to delete it.)

He's programming in Java, not C++ (note the System.out.println near the end).

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

Thanks lads!

Crap, what a lame mistake that was. Fixing it was fast and easy.
 


int i_indiceMod = 10 * i;
Vector3 p1 = new Vector3(finalMeshVertexFloatArray[i_indiceMod + 0], finalMeshVertexFloatArray[i_indiceMod + 1], finalMeshVertexFloatArray[i_indiceMod + 2]);
Vector3 p2 = new Vector3(finalMeshVertexFloatArray[i_indiceMod + 10], finalMeshVertexFloatArray[i_indiceMod + 11], finalMeshVertexFloatArray[i_indiceMod + 12]);
Vector3 p3 = new Vector3(finalMeshVertexFloatArray[i_indiceMod + 20], finalMeshVertexFloatArray[i_indiceMod + 21], finalMeshVertexFloatArray[i_indiceMod + 22]);

 

Everything now seems normal, and both spheres seem to have only marginal difference in surface area. Tho the first one seems to have bigger surface area, but somehow it makes sens to me.
image.png.df5e6cbc8915724c0fd3cfc483749898.pngimage.png.a48574bc84f6842a88ebcf1fa1fdb2dd.png

 

Flipped models are also fixed, but there is small 0.000001 error :D
image.png.3f01332e492048b004336cf5f678474c.pngimage.png.2123132769013595be0d98d520ac32c1.png

For now I am using "new" operator, since calculations are done only once, whilst loading the models. Latter on ill simply use raw vertice data for calclulations.
 

This topic is closed to new replies.

Advertisement