How to generate points inside mesh

Hi

I am working on small program which will generate random points inside a mesh. But I am stuck

Here is what I have so far. I am working in C#.

private void generate_points( int number_of_points, GameObject mesh, GameObject size)
	{
		// the mesh can be any geometry but it will be created in 3d program so when I bring it in I will generate mesh collider

		Vector3 [] Result = new Vector3[number_of_points];

		Vector3 position_of_mesh = mesh.transform.position; 
		// in the x and z plane
		Vector2 position = new Vector2(position_of_mesh.x, position_of_mesh.z);
		Vector2 local_position = new Vector2(0,0);

		Collider mesh_collider = mesh.GetComponent<MeshCollider>();

		//float cen = mesh_collider ;
		SphereCollider j = size.GetComponent<SphereCollider>();

		float width = j.radius;
		float lenght = j.radius;
		


		int i = 0;
	
		while ( i < number_of_points)
		{

			//not sure if I need two loops
			// this is the point I am stuck at

			// Genrate random point within mesh

			Vector2 inside_pos =  new Vector2(0,0);
			//Check if the point is inside mesh

			bool yes = false; // code to check point 
		 // GameObject J = Instantiate(size,
				if (yes)
			{
				Result *= new Vector3(inside_pos.x,position_of_mesh.y,inside_pos.y) ;*
  •  		i++;*
    
  •  	}*
    
  •  	else {*
    
  •  		//gen_point()*
    
  •  	}*
    
  •  }*
    
  • }*

This is actually pretty hard to do. Meshes are extremely complex topologically. They are not guaranteed to be solid, which means that they don’t even have a good definition of inside and outside. If you can guarantee that your meshes are water tight, then that helps, but they still may be concave, which makes this tricky. Probably what you will want is some sort of raycasting solution, where you fire a ray from the point, outwards some amount beyond the extent of the mesh bounds. Then you’ll need to count the number of faces this intersects wtih, where odd numbers mean inside, and even numbers (or 0) mean outside. Or something like that. As I said, it’s complex because meshes can be extremely complex. You may not be able to use Unity raycasting for this, either, as it’s built more around collision and such.

If you want a simpler hack, try this - randomly pick a vertex, then generate a position a small distance in the opposite direction of the vertex normal. This will generate positions just inside the “skin” of the mesh, which hopefully is nearly as good as them being anywhere inside it.

Generate a random point inside the bounding box. Then check if the point is inside the mesh.
Repeat about 100x.

One way is to use Physics.CheckSphere() with a very small sphere radius.

That should do the trick!

As many others have said already, this is surprisingly complex to solve. A possible way to make it easier to solve is to break the mesh into its core components, triangles.

  1. Create a class that will old 3 points on a triangle in vector3.

  2. Get all the triangles within the mesh. They are pairs of 3 integers that represent index of the vertex they connect to.

  3. Get the vertexes that the triangles point to and put it in the class.

  4. You should now have a list of classes that represents triangles. Pick a random one.

  5. Pick a random point within that triangle.

  6. Profit.?

Edit: Have a look at this answer, it should help out too Am I inside a volume? (without colliders) - Unity Answers

Here is an example. Please note that this doesn’t actually give a point on the triangle, but should give a rough idea on what to do.

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class PointInTriangle : MonoBehaviour {

	public Vector3 GetRandomPoint(Mesh m)
    {
        //Prepare a list of all triangles
        List<Triangle> triangles = new List<Triangle>();

        //Iterate over each triangle
        for(int i = 0; i < m.triangles.Length; i += 3)
        {
            //Get the index of the vertices
            int a = m.triangles*;*

int b = m.triangles[i + 1];
int c = m.triangles[i + 2];

//Create the triangle class
Triangle t = new Triangle();

//Get the actual vertecies
t.vertexA = m.vertices[a];
t.vertexB = m.vertices**;**
t.vertexC = m.vertices
```c
**;

            //Add the triangle to the list
            triangles.Add(t);
        }

        //Make sure we have actually found triangles
        if (triangles.Count == 0)
            return Vector3.zero;

        //Pick a random triangle
        Triangle t = triangles[Random.Range(0, triangles.Count)];

        //Get a random point within the triangle
        return t.GetRandomPoint();
    }
}

public class Triangle
{
    public Vector3 vertexA, vertexB, vertexC;


    public Vector3 GetRandomPoint()
    {
        //This happens to be the easiest to calculate
        Vector3 min = GetMinPoint();
        Vector3 max = GetMaxPoint();

        //Give a random point.
        //NOTE! This will not return a point on the triangle, but instead just a random point within the area the triangle makes up.
        //You will have to find more complicated algorythms to detect a random point on 3D triangles.
        return new Vector3(Random.Range(min.x, max.x), Random.Range(min.y, max.y), Random.Range(min.z, max.z));
    }

    Vector3 GetMinPoint()
    {
        Vector3 point = new Vector3();
        point.x = Mathf.Min(vertexA.x, vertexB.x, vertexC.x);
        point.y = Mathf.Min(vertexA.y, vertexB.y, vertexC.y);
        point.z = Mathf.Min(vertexA.z, vertexB.z, vertexC.z);
        return point;
    }
    Vector3 GetMaxPoint()
    {
        Vector3 point = new Vector3();
        point.x = Mathf.Max(vertexA.x, vertexB.x, vertexC.x);
        point.y = Mathf.Max(vertexA.y, vertexB.y, vertexC.y);
        point.z = Mathf.Max(vertexA.z, vertexB.z, vertexC.z);
        return point;
    }
}**</em>

```