Coordonnées barycentriques
Les coordonnées barycentriques d'un triengle permettent d'exprimer un point intérieur comme une combinaison linéaire des sommets, avec des poids alpha, bêta et gamma dont la somme est égale à 1. Cette méthode facilite l'interpolation de positions au sein d'une surface triangulaire, que ce soit pour obtenir les coefficients d'un point donné ou pour calculer un point à partir de coefficients spécifiés.
[Range(0f, 1f)] public float poidsAlpha;
[Range(0f, 1f)] public float poidsBeta;
[Range(0f, 1f)] public float poidsGamma;
private void OnDrawGizmos()
{
float total = poidsAlpha + poidsBeta + poidsGamma;
poidsAlpha /= total;
poidsBeta /= total;
poidsGamma /= total;
Gizmos.DrawLine(sommetA.position, sommetB.position);
Gizmos.DrawLine(sommetB.position, sommetC.position);
Gizmos.DrawLine(sommetC.position, sommetA.position);
Vector3 pointCible = poidsAlpha * sommetA.position + poidsBeta * sommetB.position + poidsGamma * sommetC.position;
Gizmos.DrawWireSphere(pointCible, 0.1f);
}
}
</div>Génération de points sur un maillage
------------------------------------
Pour générer un point aléatoire à l'intérieur d'un mailllage, il convient d'abord de sélectionner un triangle proportionnellement à son aire, en utilisant une méthode de tirage pondéré. Une fois le triangle choisi, les coordonnées barycantriques sont appliquées avec des poids aléatoires pour déterminer un point final.
<div>```
using System.Collections.Generic;
using UnityEngine;
public class GenerateurPointsMaillage : MonoBehaviour
{
public struct ElementPondere
{
public float poids;
public int indice;
}
private int SelectionAleatoirePonderee(ElementPondere[] elements)
{
const float epsilon = 0.00001f;
float sommePoids = 0f;
for (int i = 0; i < elements.Length; i++)
sommePoids += elements[i].poids;
float valeurAleatoire = Random.Range(0f, sommePoids);
float cumul = 0f;
for (int i = 0; i < elements.Length; i++)
{
float borneInferieure = cumul;
cumul += elements[i].poids;
float borneSuperieure = cumul;
if (valeurAleatoire > borneInferieure && valeurAleatoire < borneSuperieure + epsilon)
return elements[i].indice;
}
throw new System.InvalidOperationException("Aucun élément sélectionné");
}
public MeshFilter filtreMaillage;
private Vector3 CalculerPointAleatoire()
{
float CalculerAire(Vector3 v1, Vector3 v2, Vector3 v3)
{
return Vector3.Cross(v2 - v1, v3 - v1).magnitude * 0.5f;
}
Mesh maillage = filtreMaillage.sharedMesh;
int[] triangles = maillage.triangles;
Vector3[] sommets = maillage.vertices;
List<elementpondere> listePoids = new List<elementpondere>(triangles.Length / 3);
for (int i = 0; i < triangles.Length; i += 3)
{
Vector3 sommet1 = sommets[triangles[i]];
Vector3 sommet2 = sommets[triangles[i + 1]];
Vector3 sommet3 = sommets[triangles[i + 2]];
float aire = CalculerAire(sommet1, sommet2, sommet3);
listePoids.Add(new ElementPondere { poids = aire, indice = i });
}
int indiceTriangle = SelectionAleatoirePonderee(listePoids.ToArray());
Vector3 pointA = transform.TransformPoint(sommets[triangles[indiceTriangle]]);
Vector3 pointB = transform.TransformPoint(sommets[triangles[indiceTriangle + 1]]);
Vector3 pointC = transform.TransformPoint(sommets[triangles[indiceTriangle + 2]]);
float a = Random.Range(0f, 1f);
float b = Random.Range(0f, 1f);
float c = Random.Range(0f, 1f);
float sommeCoeffs = a + b + c;
a /= sommeCoeffs;
b /= sommeCoeffs;
c /= sommeCoeffs;
return a * pointA + b * pointB + c * pointC;
}
private void OnDrawGizmos()
{
Gizmos.color = Color.red;
for (int i = 0; i < 500; i++)
{
Vector3 point = CalculerPointAleatoire();
Gizmos.DrawWireSphere(point, 0.02f);
}
}
}</elementpondere></elementpondere>