Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
8
Question by Egons · Mar 16, 2011 at 07:13 PM · meshvolume

How would one calculate a 3d Mesh volume in Unity?

Basicly, how could I calculate the volume of a 3d Mesh in Unity?

I have found this, pseudocode, I guess (not sure if it's pseudocode, just a guess):

public float SignedVolumeOfTriangle(Vector p1, Vector p2, Vector p3) {
    var v321 = p3.X*p2.Y*p1.Z;
    var v231 = p2.X*p3.Y*p1.Z;
    var v312 = p3.X*p1.Y*p2.Z;
    var v132 = p1.X*p3.Y*p2.Z;
    var v213 = p2.X*p1.Y*p3.Z;
    var v123 = p1.X*p2.Y*p3.Z;
    return (1.0f/6.0f)*(-v321 + v231 + v312 - v132 - v213 + v123);
}

P.S. SignedVolumeOfTriangle(); calculates volume of Tetrahedron, calculated from those triangles. followed by this:

public float VolumeOfMesh(Mesh mesh) {
    var vols = from t in mesh.Triangles
               select SignedVolumeOfTriangle(t.P1, t.P2, t.P3);
    return Math.Abs(vols.Sum());
}

But I have no idea how to translate it to JavaScript or C# for use in Unity... Could someone point me into the right direction on how to do this?

Thanks in advance!

Comment
Add comment · Show 4
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image flaviusxvii · Mar 16, 2011 at 07:55 PM 0
Share

Triangles have area, not volume. Are you looking for surface area?

avatar image Egons · Mar 16, 2011 at 08:03 PM 0
Share

@flaviusxvii, no I am looking for volume, and that function there is a copy paste from StackOverflow question, about, how to calculate volume. I have no idea how to do that kind of calculation, therefore, I don't actually know what that function is doing... that's why I'm asking here.

avatar image yoyo · Mar 16, 2011 at 08:40 PM 0
Share

This tetrahedron-based computation assumes the origin is within the object and that all triangles can "see" the origin without looking outside the volume. (I was going to say the object had to be convex, but that's not quite true.)

avatar image Statement · Mar 17, 2011 at 12:50 AM 0
Share

I think it has to be convex and it has to have its center (0, 0, 0) inside the volume.

4 Replies

· Add your reply
  • Sort: 
avatar image
10
Best Answer

Answer by Statement · Mar 17, 2011 at 12:34 AM

Given your code works as intended, here's how you'd typically use it.

 using UnityEngine;
 
 public class MeshVolume : MonoBehaviour
 {
     void Start()
     {
         Mesh mesh = GetComponent<MeshFilter>().sharedMesh;
         float volume = VolumeOfMesh(mesh);
         string msg = "The volume of the mesh is " + volume + " cube units.";
         Debug.Log(msg);
     }
 
     public float SignedVolumeOfTriangle(Vector3 p1, Vector3 p2, Vector3 p3)
     {
         float v321 = p3.x * p2.y * p1.z;
         float v231 = p2.x * p3.y * p1.z;
         float v312 = p3.x * p1.y * p2.z;
         float v132 = p1.x * p3.y * p2.z;
         float v213 = p2.x * p1.y * p3.z;
         float v123 = p1.x * p2.y * p3.z;
 
         return (1.0f / 6.0f) * (-v321 + v231 + v312 - v132 - v213 + v123);
     }
 
     public float VolumeOfMesh(Mesh mesh)
     {
         float volume = 0;
 
         Vector3[] vertices = mesh.vertices;
         int[] triangles = mesh.triangles;
 
         for (int i = 0; i < triangles.Length; i += 3)
         {
             Vector3 p1 = vertices[triangles[i + 0]];
             Vector3 p2 = vertices[triangles[i + 1]];
             Vector3 p3 = vertices[triangles[i + 2]];
             volume += SignedVolumeOfTriangle(p1, p2, p3);
         }
         return Mathf.Abs(volume);
     }
 }
Comment
Add comment · Show 9 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Egons · Mar 17, 2011 at 12:52 AM 0
Share

Flawless, perfect, epic, fantastic, you-name-it! Thanks!

avatar image CoalCzar · Sep 11, 2013 at 08:22 PM 0
Share

This worked for me except that at line 39 I added:

 volume *= this.transform.localScale.x * this.transform.localScale.y * this.transform.localScale.z;
 

so that scaling of the objects was taken into account.

avatar image Nanako · Dec 02, 2014 at 01:27 PM 0
Share

that's not very good code, CoalCzar. doesn't "this" refer to the script itself? how can a script have a transform. In any case your addition assumes the code will be run from within an object, which is very limited. This is the sort of thing that should be put in a static helper class.

I think what's really needed is to pass the $$anonymous$$eshFilter, rather than the mesh. extract the mesh within the volume finding function, and also use this

 volume *= meshFilter.gameObject.transform.localScale.x * meshFilter.gameObject.transform.localScale.y * meshFilter.gameObject.transform.localScale.z;



and this goes on line 27

avatar image m_atef · Oct 19, 2017 at 02:00 PM 0
Share

I'm sorry how the code shall work? just by attaching it to the mesh in the inspector? Because no calculation is done if it is attached.

avatar image unit_nick · Oct 19, 2017 at 02:19 PM 1
Share

This equation always gets me thinking. A tri is a surface element. There is no way of knowing the depth of the triangle. I believe this equation makes assumptions about the the triangle, that the forth point would be relative to the other 3. But there is no way of knowing the real forth point with only 3 points. On a convex mesh you could create the forth point but if the mesh isn't convex then you simply cannot work it out from surface tris even if you had a central point. Perhaps I'm wrong but that's how it appears to me.

So how do you calculate the volume? If you add a RigidBody to the mesh then as long as the density is 1 the mass will equal the volume.

Show more comments
avatar image
2

Answer by Statement · Mar 16, 2011 at 07:25 PM

Actually, that looks to me as valid C# code. By the looks of it, it should work (Given you have such a Mesh class). You might have to resolve namespaces System and System.Linq though.

I am not quite sure what you are looking to do, this seems to calculate the volume of a mesh (cubic units), was that just what you had in mind? Take a look at the Unity3d Mesh reference to see how you could get the triangles.

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Egons · Mar 16, 2011 at 07:36 PM 0
Share

Uhm, well, but how can I get the coordinates of points from those triangles? $$anonymous$$esh.triangles; returned only one integer, ie: 42.

avatar image Egons · Mar 16, 2011 at 07:43 PM 0
Share

You said "I am not quite sure what you are looking to do", as simple as "calculate the volume of 3D mesh".

avatar image yoyo · Mar 16, 2011 at 08:33 PM 2
Share

Get point i for triangle j with p = mesh.vertices[mesh.triangles[i + 3 * j]] -- i is 0, 1, 2 for the three corners of the triangle, and j goes from 0 to mesh.triangles.length/3 - 1.

avatar image Statement · Mar 16, 2011 at 08:44 PM 0
Share

Yeah Egons, the thing I asked this is because I've seen people find a script and try to use it when they think they will solve another problem than it was intended for :)

avatar image
2

Answer by yoyo · Mar 16, 2011 at 08:16 PM

For a rough (over-)estimate, you can use the bounding volume ...

float volume = mesh.bounds.size.x * mesh.bounds.size.y * mesh.bounds.size.z;

This won't work for all purposes, but could be useful, depending what you need to do.

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Egons · Mar 16, 2011 at 08:21 PM 0
Share

Nah, I'm looking for a function to calculate real mesh volume, not boundary box.

avatar image yoyo · Mar 16, 2011 at 08:28 PM 0
Share

Oh well, I tried. ;) $$anonymous$$aybe it'll help someone else looking at this later.

avatar image Grespon · Aug 05, 2012 at 08:08 PM 0
Share

I think this would help me. Thanks.

avatar image ahsen35813 · Apr 11, 2021 at 10:48 PM 0
Share

Seems to be what I need. I just need an approximation of the size of the mesh, so this is great, thanks!

avatar image
2

Answer by matteo1000g · Sep 25, 2018 at 08:59 AM

To me, it sounds like there is a bit of explanation needed about how and why this formula works since we do have some assumptions. Basically, it is using the vectorial equation for the computation of the volume of a tetrahedron, explained and illustrated here: https://math.stackexchange.com/questions/1603651/volume-of-tetrahedron-using-cross-and-dot-product This assumes that the vectors a, b and c define the edges of the tetrahedron and not the point coordinates of its vertices. Note: If you assume that the 4th point of the tetrahedron is on the origin, then you can use a, b and c as the coordinates of the vertices. Otherwise, if you have 4 vertices coordinates (let's call them d,e,f,g), you can use the same equation but you should use: a = e-d; b = f-d; c=g-d.

Also, please be aware that this equation works only with convex volume. You should envision to use the volume computation through voxelization (explained here: http://blog.wolfire.com/2009/11/Triangle-mesh-voxelization) if you want something more robust to complex shapes (but be aware that it is much slower to compute). However, I did not found an easy to use implementation, all those I found were giving compile errors in complex codes and I did not have time to figure it out.

Note2: @HoverX : Using Unity's RigidBody SetDensity method computes, to my understanding the volume of the Collider's box of your mesh (generally a Capsule). So it is a very coarse approximation.

So, implementing the same volume computation using the 4 vertices of the tetrahedron and defining the fourth vertex of every tetrahedron as the center of mass of the later, one gets the following implementation:

     using UnityEngine;
 
     public float SignedVolumeOfTriangle(Vector3 p1, Vector3 p2, Vector3 p3, Vector3 o)
     {
         Vector3 v1 = p1 - o;
         Vector3 v2 = p2 - o;
         Vector3 v3 = p3 - o;
 
         return Vector3.Dot(Vector3.Cross(v1, v2), v3) / 6f; ;
     }
 
     public float VolumeOfMesh(Mesh mesh)
     {
         float volume = 0;
         Vector3[] vertices = mesh.vertices;
         int[] triangles = mesh.triangles;
 
         Vector3 o = new Vector3(0f, 0f, 0f);
         // Computing the center mass of the polyhedron as the fourth element of each mesh
         for (int i = 0; i < triangles.Length; i++)
         {
             o += vertices[triangles[i]];
         }
         o = o / mesh.triangles.Length;
 
         // Computing the sum of the volumes of all the sub-polyhedrons
         for (int i = 0; i < triangles.Length; i += 3)
         {
             Vector3 p1 = vertices[triangles[i + 0]];
             Vector3 p2 = vertices[triangles[i + 1]];
             Vector3 p3 = vertices[triangles[i + 2]];
             volume += SignedVolumeOfTriangle(p1, p2, p3, o);
         }
         return Mathf.Abs(volume);
     }
Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Bunny83 · Sep 25, 2018 at 01:22 PM 1
Share

Note that this is actually called the tripple product which calculates the volume of a "parallelepiped". This is made up of 6 equal tetrahedra hence we divide by 6. It can be easily envisioned if one remembers that the length of the vector you get from a cross product is equal to the area of the parallelogram the two vectors describe. The volume of a parallelepiped is just the base times it's height. So we need to project the diagonal length onto the normal of the base surface. That's implicitly done by the dot product since the area vector we get from the cross product is the scaled normal of the base.


To understand why it actually works regardless of the reference point you may have a look at the 2d equivalent which works the same way. I've posted two comments over here with a gif animation. The second comment shows why the 2d version doesn't work for polygons which intersect itself.


Note that I think it should actually work for non convex meshes. Of course it only works for meshes which are actually closed and also don't have self intersecting surfaces. Though it's hard to imagine or visualize the 3d case.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

8 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Am I inside a volume? (Without ray cast and default colliders?) 0 Answers

Finding volume of two 3D meshes intersection. 2 Answers

Get the triangles of a convex mesh collider 1 Answer

Find all triangles inside given bounds 1 Answer

Understanding mesh volume 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges