using System.Collections.Generic;
public class PointDistributor : MonoBehaviour
private Mesh mesh; // Reference to the mesh
private GameObject prefab; // Prefab to instantiate at points
private Transform container; // Parent container for prefabs
private int numberOfPoints = 1000; // Total points to distribute
private KeyCode generateKey = KeyCode.G; // Key to trigger point generation
private List<GameObject> instantiatedPrefabs = new List<GameObject>();
mesh = GetComponent<MeshFilter>()?.mesh;
Debug.LogError("No mesh assigned or found on the object.");
// Create a default container if not set
GameObject containerObj = new GameObject("PrefabContainer");
container = containerObj.transform;
// Check for key press to generate points and instantiate prefabs
if (Input.GetKeyDown(generateKey))
GeneratePointsAndPrefabs();
private void GeneratePointsAndPrefabs()
// Clear existing prefabs
ClearInstantiatedPrefabs();
List<Vector3> points = DistributePointsAcrossMesh();
// Instantiate prefabs at generated points
foreach (var point in points)
GameObject instance = Instantiate(prefab, point, Quaternion.identity, container);
instantiatedPrefabs.Add(instance);
Debug.Log($"Generated {points.Count} points and instantiated {instantiatedPrefabs.Count} prefabs.");
private void ClearInstantiatedPrefabs()
foreach (var obj in instantiatedPrefabs)
instantiatedPrefabs.Clear();
private List<Vector3> DistributePointsAcrossMesh()
List<Vector3> distributedPoints = new List<Vector3>();
Debug.LogError("Mesh is null. Cannot distribute points.");
return distributedPoints;
Vector3[] vertices = mesh.vertices;
int[] triangles = mesh.triangles;
Color[] vertexColors = mesh.colors;
if (vertexColors.Length == 0)
Debug.LogError("Mesh does not have vertex colours.");
return distributedPoints;
// Create a list of triangle weights based on grayscale values
List<float> triangleWeights = new List<float>();
for (int i = 0; i < triangles.Length; i += 3)
// Get the vertex indices of the triangle
int index0 = triangles[i];
int index1 = triangles[i + 1];
int index2 = triangles[i + 2];
// Get the grayscale values of the vertices
float grayscale0 = vertexColors[index0].r;
float grayscale1 = vertexColors[index1].r;
float grayscale2 = vertexColors[index2].r;
// Average grayscale for the triangle
float averageGrayscale = (grayscale0 + grayscale1 + grayscale2) / 3f;
// Calculate the area of the triangle
float area = CalculateTriangleArea(vertices[index0], vertices[index1], vertices[index2]);
// Weight is proportional to area * average grayscale
float weight = area * averageGrayscale;
triangleWeights.Add(weight);
for (int i = 0; i < triangleWeights.Count; i++)
triangleWeights[i] /= totalWeight;
// Distribute points based on triangle weights
for (int i = 0; i < numberOfPoints; i++)
// Choose a triangle based on its weight
int chosenTriangle = ChooseTriangleByWeight(triangleWeights);
// Get the vertex indices of the chosen triangle
int index0 = triangles[chosenTriangle * 3];
int index1 = triangles[chosenTriangle * 3 + 1];
int index2 = triangles[chosenTriangle * 3 + 2];
// Generate a random point within the triangle
Vector3 randomPoint = GetRandomPointInTriangle(
// Convert the point to world space and add to the list
distributedPoints.Add(transform.TransformPoint(randomPoint));
return distributedPoints;
private float CalculateTriangleArea(Vector3 v0, Vector3 v1, Vector3 v2)
// Area of the triangle using cross product
return Vector3.Cross(v1 - v0, v2 - v0).magnitude / 2f;
private int ChooseTriangleByWeight(List<float> weights)
float randomValue = Random.value; // Between 0 and 1
float cumulativeWeight = 0;
for (int i = 0; i < weights.Count; i++)
cumulativeWeight += weights[i];
if (randomValue <= cumulativeWeight)
return weights.Count - 1; // Fallback to the last triangle
private Vector3 GetRandomPointInTriangle(Vector3 v0, Vector3 v1, Vector3 v2)
// Generate random barycentric coordinates
return v0 + u * (v1 - v0) + v * (v2 - v0);