valkaari
18/09/2012, 15h27
Bonjour,
Je cherchais ces derniers jours comment générer une/des positions aléatoires à l'intérieur d'un objet.
Donc j'ai trouvé qu'en triangulant l'objet puis en calculant sur un polygon pris au hasard des coordonnées barycentriques au hasard (x+y+z = 1)
(ça fait beaucoup de hasard tout ça)
Puis en envoyant un rayon dans le sens de la normal pour aller toucher la surface de l'autre coté, et prendre un point aléatoire sur cette ligne, ça donnait un résultat relativement convenable.
Par contre j'ai encore des points qui restent en dehors. Le problème vient certainement des collisions du rayon.
SI vous avez des idées pour optimiser je suis preneur
Code commenté :
import c4d
import random
from c4d import utils
import time
#Welcome to the world of Python
def main():
#lancement du chrono
start = time.time()
#creation d'un null parent pour récolter toutes les positions
NullParent = c4d.BaseObject(c4d.Onull)
#Récupération de l'objet enfant
#trianguler l'objet également après l'avoir cloné.
original = op.GetDown()
if not original:return
child = original.GetClone()
if not child:return
ret = c4d.utils.SendModelingCommand(command = c4d.MCOMMAND_TRIANGULATE,
list = [child])
if ret == False:
return
#initialisation du collider
Collide = c4d.utils.GeRayCollider()
Collide.Init(child)
# NombreObj -> Nombre d'objets crée , TotalPos -> Nombre de position à générer
NombreObj = 0
TotalPos = 10000
#récupération du nombre de polygons dans l'objet et de sa plus longue distance pour
#être certain que le rayon traverse tout l'objet.
pcnt =child.GetPolygonCount()
childDim = child.GetRad()
RayLenght = childDim.x
if childDim.y > RayLenght:
RayLenght = childDim.y
if childDim.z > RayLenght:
RayLenght = childDim.z
RayLenght *= 2
#boucle sur le nombre total de position à trouver
for cpt in xrange(TotalPos):
#on prend un poly au hasard
polyNb = random.randint(0,pcnt-1)
polygon = child.GetPolygon(polyNb)
#on récupère la position des 3 premiers points
A = child.GetPoint(polygon.a)
B = child.GetPoint(polygon.b)
C = child.GetPoint(polygon.c)
#calcul des vecteurs
AB = c4d.Vector(B.x - A.x, B.y - A.y , B.z - A.z)
AC = c4d.Vector(C.x - A.x, C.y - A.y , C.z - A.z)
#calcul de la normal du poly avec un CrossProduct
normal = AB.Cross(AC)
normal.Normalize()
#on inverse la normal pour aller vers l'intérieur
normal = -normal
#création de coordonées barycentrique aléatoire
#pa + pb + pc = 1
pa = random.random()
pb = random.uniform(0,1.0-pa)
pc = 1.0 - pa - pb
#création du point et ajout de 1/10 de la normal pour ne pas être collé au poly
SPoint = c4d.Vector( A*pa + B*pb + C*pc )
SPoint+=normal/10.0
#lancement d'un rayon à partir de cette position en direction de la normal pour
#trouver le point oposé
Collide.Intersect (SPoint, normal, RayLenght)
if Collide.GetIntersectionCount() == 0:
continue
Intersect = Collide.GetNearestIntersection(0)
OutPoint = Intersect['hitpos']
#calcul d'un point aléatoire entre les deux points
pa = random.random()
InsidePoint = SPoint*pa + OutPoint* (1-pa)
#création de l'objet neutre à la position généré.
Null = c4d.BaseObject(c4d.Onull)
Null[c4d.NULLOBJECT_DISPLAY] = 0
Null[c4d.NULLOBJECT_RADIUS] = 4
Null[c4d.NULLOBJECT_ORIENTATION] =1
Null.SetMg(c4d.utils.HPBToMatrix(c4d.utils.VectorT oHPB (normal)))
Null.SetAbsPos(InsidePoint)
Null.InsertUnder(NullParent)
#ajouter 1 au nombre d'objet crée
NombreObj+=1
#fin du chornomètre et affichage d'information dans la console
end = time.time() - start
print "temps d'execution ", end , " Nombre de position : " , NombreObj , " sur ", TotalPos
#retourner le Nullparent
return NullParent
Je cherchais ces derniers jours comment générer une/des positions aléatoires à l'intérieur d'un objet.
Donc j'ai trouvé qu'en triangulant l'objet puis en calculant sur un polygon pris au hasard des coordonnées barycentriques au hasard (x+y+z = 1)
(ça fait beaucoup de hasard tout ça)
Puis en envoyant un rayon dans le sens de la normal pour aller toucher la surface de l'autre coté, et prendre un point aléatoire sur cette ligne, ça donnait un résultat relativement convenable.
Par contre j'ai encore des points qui restent en dehors. Le problème vient certainement des collisions du rayon.
SI vous avez des idées pour optimiser je suis preneur
Code commenté :
import c4d
import random
from c4d import utils
import time
#Welcome to the world of Python
def main():
#lancement du chrono
start = time.time()
#creation d'un null parent pour récolter toutes les positions
NullParent = c4d.BaseObject(c4d.Onull)
#Récupération de l'objet enfant
#trianguler l'objet également après l'avoir cloné.
original = op.GetDown()
if not original:return
child = original.GetClone()
if not child:return
ret = c4d.utils.SendModelingCommand(command = c4d.MCOMMAND_TRIANGULATE,
list = [child])
if ret == False:
return
#initialisation du collider
Collide = c4d.utils.GeRayCollider()
Collide.Init(child)
# NombreObj -> Nombre d'objets crée , TotalPos -> Nombre de position à générer
NombreObj = 0
TotalPos = 10000
#récupération du nombre de polygons dans l'objet et de sa plus longue distance pour
#être certain que le rayon traverse tout l'objet.
pcnt =child.GetPolygonCount()
childDim = child.GetRad()
RayLenght = childDim.x
if childDim.y > RayLenght:
RayLenght = childDim.y
if childDim.z > RayLenght:
RayLenght = childDim.z
RayLenght *= 2
#boucle sur le nombre total de position à trouver
for cpt in xrange(TotalPos):
#on prend un poly au hasard
polyNb = random.randint(0,pcnt-1)
polygon = child.GetPolygon(polyNb)
#on récupère la position des 3 premiers points
A = child.GetPoint(polygon.a)
B = child.GetPoint(polygon.b)
C = child.GetPoint(polygon.c)
#calcul des vecteurs
AB = c4d.Vector(B.x - A.x, B.y - A.y , B.z - A.z)
AC = c4d.Vector(C.x - A.x, C.y - A.y , C.z - A.z)
#calcul de la normal du poly avec un CrossProduct
normal = AB.Cross(AC)
normal.Normalize()
#on inverse la normal pour aller vers l'intérieur
normal = -normal
#création de coordonées barycentrique aléatoire
#pa + pb + pc = 1
pa = random.random()
pb = random.uniform(0,1.0-pa)
pc = 1.0 - pa - pb
#création du point et ajout de 1/10 de la normal pour ne pas être collé au poly
SPoint = c4d.Vector( A*pa + B*pb + C*pc )
SPoint+=normal/10.0
#lancement d'un rayon à partir de cette position en direction de la normal pour
#trouver le point oposé
Collide.Intersect (SPoint, normal, RayLenght)
if Collide.GetIntersectionCount() == 0:
continue
Intersect = Collide.GetNearestIntersection(0)
OutPoint = Intersect['hitpos']
#calcul d'un point aléatoire entre les deux points
pa = random.random()
InsidePoint = SPoint*pa + OutPoint* (1-pa)
#création de l'objet neutre à la position généré.
Null = c4d.BaseObject(c4d.Onull)
Null[c4d.NULLOBJECT_DISPLAY] = 0
Null[c4d.NULLOBJECT_RADIUS] = 4
Null[c4d.NULLOBJECT_ORIENTATION] =1
Null.SetMg(c4d.utils.HPBToMatrix(c4d.utils.VectorT oHPB (normal)))
Null.SetAbsPos(InsidePoint)
Null.InsertUnder(NullParent)
#ajouter 1 au nombre d'objet crée
NombreObj+=1
#fin du chornomètre et affichage d'information dans la console
end = time.time() - start
print "temps d'execution ", end , " Nombre de position : " , NombreObj , " sur ", TotalPos
#retourner le Nullparent
return NullParent