courbes catmull-rom et bezier Le retour :

Programmation avancée de jeux en PureBasic
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

courbes catmull-rom et bezier Le retour :

Message par Thyphoon »

il y a quelques années déjà j'avais cherché sans succès a intégré une interpolation de type catmull rom pour le déplacement dans mes jeux
(la différence entre catmull-rom et les courbes de Béziers, c'est qu'avec catmull-rom on passe obligatoirement part les points données)
voici le résultat aujourd'hui ! :P
si quelqu'un a une idée pour améliorer la fonction ou la lisibilité de se code qu'il n’hésitez pas !

Code : Tout sélectionner

Structure game
  screenPixelWidth.l
  screenPixelHeight.l
 
EndStructure

Global game.game
game\screenPixelWidth=800
game\screenPixelheight=600


If InitSprite() And InitSprite3D() And InitSound() And InitNetwork()
  If InitKeyboard() And InitMouse()
    winMain = OpenWindow(#PB_Any,0,0,game\screenPixelWidth,game\screenPixelHeight,"Press [Esc] to close",#PB_Window_ScreenCentered | #PB_Window_SystemMenu)
    OpenWindowedScreen(WindowID(winMain), 0, 0,game\screenPixelWidth,game\screenPixelHeight, 1, 0, 0)
    UsePNGImageDecoder()
    UseJPEGImageDecoder()
    SetFrameRate(60)
  EndIf
Else
  MessageRequester("","Unable to initsprite") :
EndIf

Define p.point,p0.Point,p1.Point,p2.point,p3.point

;les 4 points part le quel je dois passer
p0\x=Random(100)+50:p0\y=Random(500)+50
p1\x=Random(100)+250:p1\y=Random(500)+50
p2\x=Random(100)+350:p2\y=Random(500)+50
p3\x=Random(100)+450:p3\y=Random(500)+50

; t doit varier de 0 a 1 (0 étant le point de départ et 1 le point d'arrivé)
;CATMULL ROM FUNCTIONALITY
Procedure CatmullRomSpline(t.f,*result.POINT,*p0.Point,*p1.Point,*p2.point,*p3.point)
    t2.f = t * t
    t3.f = t2 * t
    *result\x= 0.5 * ( ( 2.0 * *p1\x ) + ( -*p0\x + *p2\x ) * t + ( 2.0 * *p0\x - 5.0 * *p1\x + 4 * *p2\x - *p3\x ) * t2 + ( -*p0\x + 3.0 * *p1\x - 3.0 * *p2\x + *p3\x ) * t3 )
    *result\y= 0.5 * ( ( 2.0 * *p1\y ) + ( -*p0\y + *p2\y ) * t + ( 2.0 * *p0\y - 5.0 * *p1\y + 4 * *p2\y - *p3\y ) * t2 + ( -*p0\y + 3.0 * *p1\y - 3.0 * *p2\y + *p3\y ) * t3 )
EndProcedure

;première version
Procedure old_beziersSpline(t.f,*result.POINT,*p0.Point,*p1.Point,*p2.point,*p3.point)
    *result\x = *p0\x*Pow((1-t),3) + 3* *p1\x*Pow((1-t),2)*t + 3* *p2\x*(1-t)*Pow(t,2) + *p3\x*Pow(t,3)
    *result\y = *p0\y*Pow((1-t),3) + 3* *p1\y*Pow((1-t),2)*t + 3* *p2\y*(1-t)*Pow(t,2) + *p3\y*Pow(t,3)
EndProcedure

;une version optimizé ! :o)
Procedure beziersSpline(t.f,*result.POINT,*p0.Point,*p1.Point,*p2.point,*p3.point)
  a.f=(1-t)
  b.f=a*a
  c.f=a*a*a
  d.f=t*t
  e.f=d*t
  *result\x = *p0\x*c + 3* *p1\x*b*t + 3* *p2\x*a*d + *p3\x*e
  *result\y = *p0\y*c + 3* *p1\y*b*t + 3* *p2\y*a*d + *p3\y*e
EndProcedure


Repeat
  Delay(1)
  EventID = WindowEvent()
  ExamineKeyboard()
  ClearScreen(0)
  
  StartDrawing(ScreenOutput())



  div=50 ;nombre de division entre les 2 points
  For z=0 To div 
    ;-CatmullRom
    ;premier segment
    CatmullRomSpline(z/div,p,p0,p0,p1,p2)
    Circle(p\x,p\y,2,#Blue)
    ;second segment
    CatmullRomSpline(z/div,p,p0,p1,p2,p3)
    Circle(p\x,p\y,2,#Blue)
    ;troisième segment
    CatmullRomSpline(z/div,p,p1,p2,p3,p3)
    Circle(p\x,p\y,2,#Blue)
    
    ;-Bezier
    beziersSpline(z/div,p,p0,p1,p2,p3)
    Circle(p\x,p\y,2,#Green)
  Next
  
  ;Je trace les points de passage !
  Circle(p0\x,p0\y,10,#Red):DrawText(p0\x+15,p0\y,"(0)")
  Circle(p1\x,p1\y,10,#Red):DrawText(p1\x+15,p1\y,"(1)")
  Circle(p2\x,p2\y,10,#Red):DrawText(p2\x+15,p2\y,"(2)")
  Circle(p3\x,p3\y,10,#Red):DrawText(p3\x+15,p3\y,"(3)")
  
  StopDrawing()
  
   FlipBuffers()
 Until KeyboardReleased(#PB_Key_Escape) Or EventID = #PB_Event_CloseWindow
 
   
  
 
   
  
Dernière modification par Thyphoon le dim. 12/juin/2011 9:24, modifié 2 fois.
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Re: courbe catmull rom Le retour :

Message par Thyphoon »

j'ai rajouter la courbe de Béziers pour les mêmes points en vert !
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: courbe catmull rom Le retour :

Message par djes »

Simple et pratique :)
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Re: courbe catmull rom Le retour :

Message par Thyphoon »

djes a écrit :Simple et pratique :)
Merci ! :D
je pense que la courbe de beziers peut être optimiser (surtout a cause du pow)
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Re: courbe catmull rom Le retour :

Message par Thyphoon »

petit test d'optimisation pour la courbe de Béziers
16ms pour la optimisé
265ms pour la non optimisé !
:mrgreen:

Code : Tout sélectionner

DisableDebugger
Define p.point,p0.Point,p1.Point,p2.point,p3.point

;les 4 points part le quel je dois passer
p0\x=Random(100)+50:p0\y=Random(500)+50
p1\x=Random(100)+250:p1\y=Random(500)+50
p2\x=Random(100)+350:p2\y=Random(500)+50
p3\x=Random(100)+450:p3\y=Random(500)+50

; t doit varier de 0 a 1 (0 étant le point de départ et 1 le point d'arrivé)
Procedure beziersSpline(t.f,*result.POINT,*p0.Point,*p1.Point,*p2.point,*p3.point)
    *result\x = *p0\x*Pow((1-t),3) + 3* *p1\x*Pow((1-t),2)*t + 3* *p2\x*(1-t)*Pow(t,2) + *p3\x*Pow(t,3)
    *result\y = *p0\y*Pow((1-t),3) + 3* *p1\y*Pow((1-t),2)*t + 3* *p2\y*(1-t)*Pow(t,2) + *p3\y*Pow(t,3)
EndProcedure

Procedure ObeziersSpline(t.f,*result.POINT,*p0.Point,*p1.Point,*p2.point,*p3.point)
  a.f=(1-t)
  b.f=a*a
  c.f=a*a*a
  d.f=t*t
  e.f=d*t
  *result\x = *p0\x*c + 3* *p1\x*b*t + 3* *p2\x*a*d + *p3\x*e
  *result\y = *p0\y*c + 3* *p1\y*b*t + 3* *p2\y*a*d + *p3\y*e
EndProcedure

div=1000 ;nombre de division entre les 2 points
time=ElapsedMilliseconds()
For n=1 To 400
  For z=0 To div 
  ObeziersSpline(z/div,p,p0,p1,p2,p3)
  Next
Next
t1=ElapsedMilliseconds()-time

time=ElapsedMilliseconds()
For n=1 To 400
  For z=0 To div 
  beziersSpline(z/div,p,p0,p1,p2,p3)
  Next
Next
t2=ElapsedMilliseconds()-time

MessageRequester("", "optimizé:"+Str(t1)+"ms normal:"+Str(t2)+"ms")
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: courbes catmull-rom et bezier Le retour :

Message par Le Soldat Inconnu »

C'est à cause de la fonction Pow qui est très lente.

En tous cas, c'est chouette, encore plus en mettant les points en bordel

Code : Tout sélectionner

Structure game
	screenPixelWidth.l
	screenPixelHeight.l
	
EndStructure

Global game.game
game\screenPixelWidth = 800
game\screenPixelHeight = 600


If InitSprite() And InitSprite3D() And InitSound() And InitNetwork()
	If InitKeyboard() And InitMouse()
		winMain = OpenWindow(#PB_Any, 0, 0, game\screenPixelWidth, game\screenPixelHeight, "Press [Esc] to close", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
		OpenWindowedScreen(WindowID(winMain), 0, 0, game\screenPixelWidth, game\screenPixelHeight, 1, 0, 0)
		SetFrameRate(60)
	EndIf
Else
	MessageRequester("", "Unable to initsprite"):
EndIf

Define p.point, p0.point, p1.point, p2.point, p3.point

; les 4 points part le quel je dois passer
p0\x = Random(700) + 50 : p0\y = Random(500) + 50
p1\x = Random(700) + 50 : p1\y = Random(500) + 50
p2\x = Random(700) + 50 : p2\y = Random(500) + 50
p3\x = Random(700) + 50 : p3\y = Random(500) + 50

; t doit varier de 0 a 1 (0 étant le point de départ et 1 le point d'arrivé)
; CATMULL ROM FUNCTIONALITY
Procedure CatmullRomSpline(t.f, *result.point, *p0.point, *p1.point, *p2.point, *p3.point)
	t2.f = t * t
	t3.f = t2 * t
	*result\x = 0.5 *(( 2.0 * *p1\x) +(- *p0\x + *p2\x) * t +(2.0 * *p0\x - 5.0 * *p1\x + 4 * *p2\x - *p3\x) * t2 +(- *p0\x + 3.0 * *p1\x - 3.0 * *p2\x + *p3\x) * t3)
	*result\y = 0.5 *(( 2.0 * *p1\y) +(- *p0\y + *p2\y) * t +(2.0 * *p0\y - 5.0 * *p1\y + 4 * *p2\y - *p3\y) * t2 +(- *p0\y + 3.0 * *p1\y - 3.0 * *p2\y + *p3\y) * t3)
EndProcedure

; première version
Procedure old_beziersSpline(t.f, *result.point, *p0.point, *p1.point, *p2.point, *p3.point)
	*result\x = *p0\x * Pow((1 - t), 3) + 3 * *p1\x * Pow((1 - t), 2) * t + 3 * *p2\x *(1 - t) * Pow(t, 2) + *p3\x * Pow(t, 3)
	*result\y = *p0\y * Pow((1 - t), 3) + 3 * *p1\y * Pow((1 - t), 2) * t + 3 * *p2\y *(1 - t) * Pow(t, 2) + *p3\y * Pow(t, 3)
EndProcedure

; une version optimizé ! :o)
Procedure beziersSpline(t.f, *result.point, *p0.point, *p1.point, *p2.point, *p3.point)
	a.f = (1 - t)
	b.f = a * a
	c.f = a * a * a
	d.f = t * t
	e.f = d * t
	*result\x = *p0\x * c + 3 * *p1\x * b * t + 3 * *p2\x * a * d + *p3\x * e
	*result\y = *p0\y * c + 3 * *p1\y * b * t + 3 * *p2\y * a * d + *p3\y * e
EndProcedure


Repeat
	Delay(1)
	Repeat
		EventID = WindowEvent()
		Select EventID
			Case #PB_Event_CloseWindow
				Quitter = 1
		EndSelect
	Until EventID = 0
	ExamineKeyboard()
	ClearScreen(0)
	
	StartDrawing(ScreenOutput())
		
		div = 25 ; nombre de division entre les 2 points
		For z = 0 To div
			;- CatmullRom
			; premier segment
			CatmullRomSpline(z / div, p, p0, p0, p1, p2)
			Circle(p\x, p\y, 2, #Blue)
			; second segment
			CatmullRomSpline(z / div, p, p0, p1, p2, p3)
			Circle(p\x, p\y, 2, #Blue)
			; troisième segment
			CatmullRomSpline(z / div, p, p1, p2, p3, p3)
			Circle(p\x, p\y, 2, #Blue)
			
			;- Bezier
			beziersSpline(z / div, p, p0, p1, p2, p3)
			Circle(p\x, p\y, 2, #Green)
		Next
		
		; Je trace les points de passage !
		Circle(p0\x, p0\y, 10, #Red) : DrawText(p0\x + 15, p0\y, "(0)")
		Circle(p1\x, p1\y, 10, #Red) : DrawText(p1\x + 15, p1\y, "(1)")
		Circle(p2\x, p2\y, 10, #Red) : DrawText(p2\x + 15, p2\y, "(2)")
		Circle(p3\x, p3\y, 10, #Red) : DrawText(p3\x + 15, p3\y, "(3)")
		
	StopDrawing()
	
	FlipBuffers()
Until KeyboardReleased(#PB_Key_Escape) Or Quitter
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
G-Rom
Messages : 3641
Inscription : dim. 10/janv./2010 5:29

Re: courbes catmull-rom et bezier Le retour :

Message par G-Rom »

@Thyphoon

Merci Thyphoon , le traçage est un peu foireux , mais l'idée est là , catmull room peut être très utile lors d'une animation
ou d'un déplacement , mieux que beziers dans certain cas en tout cas.
Merci encore du partage ! ;)
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Re: courbes catmull-rom et bezier Le retour :

Message par graph100 »

Et hop dans un tiroir :P
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Re: courbes catmull-rom et bezier Le retour :

Message par Thyphoon »

tout ce que j'arrive a faire, c'est grâce a d'autre qui on partager avant, normal que je partage ! :D
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: courbes catmull-rom et bezier Le retour :

Message par Le Soldat Inconnu »

Moi, j'y vois des applications industrielles, du calcul de trajectoire pour un robot par exemple :mrgreen: , Bordel, c'est le week-end et je pense au boulot !
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Re: courbes catmull-rom et bezier Le retour :

Message par Thyphoon »

Le Soldat Inconnu a écrit :Moi, j'y vois des applications industrielles, du calcul de trajectoire pour un robot par exemple :mrgreen: , Bordel, c'est le week-end et je pense au boulot !
:mrgreen: déformation professionnel ou bien grand passionné part son boulot ?
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: courbes catmull-rom et bezier Le retour :

Message par djes »

En passant (sans vraiment réfléchir), tu n'aurais pas le code pour avoir la longueur?
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Re: courbes catmull-rom et bezier Le retour :

Message par Thyphoon »

djes a écrit :En passant (sans vraiment réfléchir), tu n'aurais pas le code pour avoir la longueur?
figure toi que c'est ce que je cherche depuis une heure ... pour l'instant j'ai pas réussi !
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Re: courbes catmull-rom et bezier Le retour :

Message par Thyphoon »

pour la longueur de la courbe de beziers j'ai trouvé ça
http://forums.futura-sciences.com/mathe ... ligne.html
mais pas encore reussi a mettre en application, et restera alors a trouver la même chose pour une cattmumm-rom
Répondre