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
3
Question by IgorAherne · Jan 08, 2014 at 05:56 PM · meshpositiondetectionvolumeinside

Am I inside a volume? (without colliders)

Hey guys!

Interesting, can one tell if a point in space is inside a given mesh without any kind of colliders? It get's harder once it's not a cube, but for example a pyramid, especially if we are using the x-y-z coordinate-bound approach, comparing all 3 coordinate components of vertexes against ours.

Can I use c# to actually see that my position is inside a specified volume using some function?

Many thanks!

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 OP_toss · Jan 08, 2014 at 06:03 PM 0
Share

For a pyramid? Yes, totally doable. For ANY $$anonymous$$ESH? No, you'd essentially be rebuilding a collision system by that point, so you might as well use the optimized collision system already there.

Out of curiousity, why don't you want to use colliders?

avatar image robertbu · Jan 08, 2014 at 06:13 PM 0
Share

Here is an untested hack that might be useful depending on your situation. Produce a mesh collider based on your object with the normals reversed. Then Raycast in two opposite directions from your test point. If both Raycasts hit, you know you are inside.

http://wiki.unity3d.com/index.php?title=ReverseNormals

avatar image IgorAherne · Jan 08, 2014 at 07:09 PM 0
Share

Op_toss, I want to thread this process out, and can't use API of Unity. :/

People, the thing is - I cannot use ray cast since I need to do this at the same time about 200 times every frame from 200 different points on the map. :<

I was thinking if I ray cast every 10 degrees, so I get 36 ray casts (All done in editor before the game starts). I then detect points of intersection, plant a vertex there, and come out with a mesh. Standing inside it I know that I will be able to see towards that emission point.

But I need to find out if I am in between those vertexes during gameplay. Raycast is very heavy on resources.

thanks for helping! alt text

check.png (80.6 kB)
avatar image IgorAherne · Jan 08, 2014 at 07:40 PM 0
Share

Here is the solution http://wiki.unity3d.com/index.php?title=PolyContainsPoint I am wondering if c# can for example take an array of vertexes and solve for 3D in a similar way

3 Replies

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

Answer by Bunny83 · Jan 08, 2014 at 07:48 PM

It's quite simple but you have to iterate over all triangles of course. Also it the volume isn't closed you might get wrong results since the volume doesn't have a clear boundary.

All you have to do is check if the point is behind all plane which are defined by all triangles.

You can use Unity's Plane class for this:

 //C#
 public static class MeshExtension
 {
     public static bool IsPointInside(this Mesh aMesh, Vector3 aLocalPoint)
     {
         var verts = aMesh.vertices;
         var tris = aMesh.triangles;
         int triangleCount = tris.Length / 3;
         for (int i = 0; i < triangleCount; i++)
         {
             var V1 = verts[ tris[ i*3     ] ];
             var V2 = verts[ tris[ i*3 + 1 ] ];
             var V3 = verts[ tris[ i*3 + 2 ] ];
             var P = new Plane(V1,V2,V3);
             if (P.GetSide(aLocalPoint))
                 return false;
         }
         return true;
     }
 }

The documentation of GetSide is not very clear, so you might have to invert the result ( if (!P.GetSide(aLocalPoint)) )

To use this extension method, just put this class somewhere in your project and use it like this:

 if (someMesh.IsPointInside(meshTransform.InverseTransformPoint(yourPoint)))
     // "yourPoint" is inside "someMesh".

edit
important: This method only works for convex meshes! Concave meshes aren't that easy.

Comment
Add comment · Show 2 · 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 IgorAherne · Jan 08, 2014 at 09:23 PM 0
Share

damn, I need convex ones as well ! :<

avatar image Bunny83 · Jan 08, 2014 at 09:39 PM 0
Share

I guess you mean concave, right?

In that case i would suggest to implement your own raycasting solution which checks the intersection with each triangle manually and implement the raycasting algorithm. This works the same for 3d. This is basically what the above mentioned algorithm does optimised for 2d, however it's way more complicated for 3d.

avatar image
2
Wiki

Answer by intrepidis · Nov 16, 2014 at 02:33 PM

Here is a fast method to find whether a point is within the bounding sphere of a mesh. I have made this as an extension method to the Mesh class.

 using System;
 using UnityEngine;
 
 public static class MeshExtension
 {
     public static bool PointIsWithinBoundingSphere(this Mesh mesh, Vector3 point)
     {
         if (!mesh.bounds.Contains(point))
             return false;
         
         // Get the point relative to the mesh center.
         var p = point - mesh.bounds.center;
         Func<float, float> getSide = vector => vector < 0f ? -1f : 1f;
         var sideFlip = new Vector3(getSide(p.x), getSide(p.y), getSide(p.z));
         float pointDist = p.sqrMagnitude;
         foreach (var vert in mesh.vertices)
         {
             // Get the vertice relative to the mesh center.
             var v = vert - mesh.bounds.center;
             // Is vertice on other side of mesh center than the target point?
             if (v.x * sideFlip.x < 0f || v.y * sideFlip.y < 0f || v.z * sideFlip.z < 0f)
                 continue;
             float vectorDist = v.sqrMagnitude;
             if (vectorDist > pointDist)
                 return true;
         }
         return false;
     }
 }

If the point is found to be within the bounding sphere, you can then use this much more accurate but vastly slower method to find if the point is within the mesh.

 using System;
 using UnityEngine;
 
 public static class MeshExtension
 {
     /// <summary>
     /// Decide whether a point is within a mesh, in a good yet simplistic way.
     /// It works best with convex meshes, whereas a concave mesh is simply
     /// treated as a convex mesh and so it will not be totally exact.
     /// (For a torus/donut mesh it will be like it didn't have a hole.)
     /// </summary>
     public static bool PointIsWithin(this Mesh mesh, Vector3 point)
     {
         Vector3 p = point - mesh.bounds.center;
         
         for (int i = 0; i < mesh.vertices.Length; i += 3)
         {
             Vector3 a = mesh.vertices[i] - mesh.bounds.center;
             Vector3 b = mesh.vertices[i + 1] - mesh.bounds.center;
             Vector3 c = mesh.vertices[i + 2] - mesh.bounds.center;
             if (RayWithinTriangle(p, a, b, c))
                 return true;
         }
         return false;
     }

     /// <summary>
     /// Radiate out from the origin through the given point to see whether
     /// the ray would hit the triangle and the point is closer to the origin than the triangle.
     /// The triangle is specified by v0, v1 and v2.
     /// </summary>
     private static bool RayWithinTriangle(Vector3 point, Vector3 v0, Vector3 v1, Vector3 v2)
     {
         Vector3 intersectionPoint;
         if (RayIntersectsTriangle(point, v0, v1, v2, out intersectionPoint))
         {
             float pointDist = point.sqrMagnitude;
             float intersectionDist = intersectionPoint.sqrMagnitude;
             return (pointDist < intersectionDist);
         }
         return false;
     }
     
     /// <summary>
     /// Radiate out from the origin through the given point to see whether
     /// the ray would hit the triangle.
     /// The triangle is specified by v0, v1 and v2.
     /// </summary>
     private static bool RayIntersectsTriangle(Vector3 direction, Vector3 v0, Vector3 v1, Vector3 v2, out Vector3 intersectionPoint)
     {
         intersectionPoint = new Vector3();
         
         Vector3 e1 = v1 - v0;
         Vector3 e2 = v2 - v0;
         
         Vector3 h = Vector3.Cross(direction, e2);
         float a = Vector3.Dot(e1, h);
         
         if (a > -0.00001 && a < 0.00001)
             return false;
         
         float f = 1 / a;
         Vector3 s = Vector3.zero - v0;
         float u = f * Vector3.Dot(s, h);
         
         if (u < 0.0 || u > 1.0)
             return false;
         
         Vector3 q = Vector3.Cross(s, e1);
         float v = f * Vector3.Dot(direction, q);
         
         if (v < 0.0 || u + v > 1.0)
             return false;
         
         // At this stage we can compute t to find out where
         // the intersection point is on the line.
         float t = f * Vector3.Dot(e2, q);
         
         if (t > 0.00001) // ray intersection
         {
             intersectionPoint[0] = direction[0] * t;
             intersectionPoint[1] = direction[1] * t;
             intersectionPoint[2] = direction[2] * t;
             return true;
         }
         
         // At this point there is a line intersection
         // but not a ray intersection.
         return false;
     }
 }

The RayIntersectsTriangle method was taken from this site:

http://www.lighthouse3d.com/tutorials/maths/ray-triangle-intersection/

Comment
Add comment · Show 3 · 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 · Nov 16, 2014 at 05:33 PM 0
Share

Sorry, but that simply doesn't work. Just because the point you want to test is in the same quadrant (cell) and has a smaller distance from the center than an arbitrary vertex doesn't mean the point is inside the mesh. That wouldn't even work reliably for convex meshes.

avatar image intrepidis · Nov 17, 2014 at 04:00 AM 1
Share

Too true, I've updated to specify that it only checks the bounding sphere of a mesh. Thanks.

avatar image intrepidis · Nov 17, 2014 at 07:21 AM 0
Share

I have now added the much more accurate but slower method.

avatar image
0

Answer by yoonitee · Jun 12, 2016 at 04:38 AM

Actually its not too hard. Here's the pseudo code:

Set N=0; For each triangle form tetrahedron with one point at the origin. If point is in this tetrahedron N++;

If at the end N%2==1 then the point is inside the mesh.

Now, to test if a point is inside a tetrahedron requires testing if it is within 4 planes.

Comment
Add comment · 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

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

21 People are following this question.

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

Related Questions

Find all triangles inside given bounds 1 Answer

Editing vertices 1 Answer

get terrain vertices? 2 Answers

Detect exactly where other objects around player are 3 Answers

Can a shader render darkness inside a mesh? 2 Answers


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