3D minimaliste
coccinelle18-Mar-2011/21:50:41+1:00
Pour mon Quetzal, j'ai quand même envie d'afficher les planeurs en 3D de manière minimaliste.

Comme je n'y comprenais rien aux algorithmes que j'ai trouvé, j'ai pondu un truc minimaliste. Mon problème, c'est que la plupart emploient la position d'un observateur pour calculer les choses. Moi, je m'y retrouve mieux lorsque l'on indique les angles de rotation, c'est plus facile.

Si vous avez des idées pour améliorer ou simplifier la chose, vous me dites...

C'est basique, mais ça me parait suffisant, enfin j'espère.
REBOL []

matrice-product: func [
	{Produit matriciel ordinaire de deux matrices.
	Retourne une matrice (m,p) (block! de m block! de p éléments}
	matrice-1 [block!] {Matrice (m,n) (block! de m block! de n élément)}
	matrice-2 [block!] {Matrice (n,p) (block! de n block! de p élément)}
	/local l1 c1 l2 c2 result
][
	l1: length? matrice-1
	c1: length? matrice-1/1
	l2: length? matrice-2
	c2: length? matrice-2/1
	result: array/initial reduce [l1 c2] 0
	for i 1 l1 1 [
		for j 1 c2 1 [
			for k 1 c1 1 [
				result/(i)/(j): result/(i)/(j) + (matrice-1/(i)/(k) * matrice-2/(k)/(j))
			]
		]
	]
	result
]

matrice-rotation: func [
	{Calcul la matrice de rotation en fonction d'un axe et d'un angle de rotation}
	axe [object!] {Axe de rotation}
	alpha [number!] {Angle de rotation}
	/local c s C1 xs ys zs xC yC zC xyC yzC zxC
][
	C1: 1 - c: cosine(alpha) s: sine(alpha)
	xs: axe/x * s   ys: axe/y * s   zs: axe/z * s
	xC: axe/x * C1   yC: axe/y * C1   zC: axe/z * C1
	xyC: axe/x * yC  yzC: axe/y * zC zxC: axe/z * xC
	reduce [	
		reduce [ axe/x * xC + c   xyC - zs   zxC + ys ]
		reduce [ xyC + zs   axe/y * yC + c   yzC - xs ]
		reduce [ zxC - ys   yzC + xs   axe/z * zC + c ]
	]
]

point: context [x: y: z: 0]

rotate-point: func [
	{Applique une matrice de rotation sur un point}
	point [object!]
	matrice [block!]
	/local x y z
][
	x: point/x y: point/y z: point/z
	point/x: (x * matrice/1/1) + (y * matrice/1/2) + (z * matrice/1/3)
	point/y: (x * matrice/2/1) + (y * matrice/2/2) + (z * matrice/2/3)
	point/z: (x * matrice/3/1) + (y * matrice/3/2) + (z * matrice/3/3)
]

surface: context [
	draw: [pen ivory fill-pen snow polygon (pairs)]
	refs: []                 ; Pointeurs sur les points
]

object: context [
	axes: reduce [ ; Current axes
		make point [x: 1 y: 0 z: 0] ; Axe des x
		make point [x: 0 y: 1 z: 0] ; Axe des y
		make point [x: 0 y: 0 z: 1] ; Axe des z
	]
	points: []		; Liste des points
	surfaces: []	; Liste des surfaces
]

rotate-object: func [
	{Calcul les nouvelles coordonnées d'une point en appliquant une rotation}
	roll [number!]  {Rotation autour de l'axe des x = aileron - positif vers la droite}
	pitch [number!] {Rotation autour de l'axe des y = profondeur - positif vers le haut}
	yaw [number!]   {Rotation autour de l'axe des z = direction - positif vers la droite}
	object [object!] {L'objet à faire tourner}
	/local matrice-x matrice-y matrice-z matrice
][
; Calcul les matrices selon les trois axes
	matrice-x: matrice-rotation object/axes/1 roll  ; Matrice de rotation autour de x
	matrice-y: matrice-rotation object/axes/2 pitch ; Matrice de rotation autour de y
	matrice-z: matrice-rotation object/axes/3 yaw   ; Matrice de rotation autour de z

; Multiplie les trois matrices	
	matrice: matrice-product matrice-product matrice-x matrice-y matrice-z

; Applique la rotation aux trois axes
	foreach axe object/axes [
		rotate-point axe matrice
	]

; Applique la rotation à tous les points
	foreach point object/points [
		rotate-point point matrice
	]

; Retourne l'objet
	object
]

draw-object: func [
	elevation [number!]
	azimuth [number!]
	distance [number!]
	object [object!]
	/local
		matrice-x matrice-z matrice
		points surfaces draws pairs len result
][
	matrice-x: matrice-rotation make point [x: 1 y: 0 z: 0] elevation ; Axe des x
	matrice-z: matrice-rotation make point [x: 0 y: 0 z: 1] azimuth ; Axe des z
	matrice: matrice-product matrice-x matrice-z

; Crée le nouvel ensemble de point :
; - applique la matrice de rotation
; - et effectue la projection (x -> x et z -> y)
	points: make block! length? object/points
	foreach point object/points [
		append points new-point: make point [pair: 0x0] ; Ajoute la pair! projetée au point.
		rotate-point new-point matrice
		ratio: distance / either zero? ratio: distance - new-point/y [1][ratio]
		new-point/pair/x: round new-point/x * ratio		
		new-point/pair/y: negate round new-point/z * ratio		
	]

; Construit les éléments graphiques
; et les trie du plus éloigné au moins éloigné
	draws: make block! 2 * length? object/surfaces
	foreach surface object/surfaces [
		len: 0
	 	pairs: make block! length? surface/refs
		foreach ref surface/refs [
			len: len + points/(ref)/y
			append pairs points/(ref)/pair 
		]
		bind surface/draw 'pairs
		append draws reduce [len / length? surface/refs compose surface/draw]
	]
	sort/skip draws 2

; Produit le résultat à partir des éléments graphiques triés
	result: copy []
	foreach [len draw] draws [
		append result draw
	]

; Retourne le block! draw
	result
]


azimuth: 235
elevation: 20
distance: 600

drw: []

lay: layout [
	across
	b: box 800x600 edge [size: 1x1] effect [draw [line-width 3 translate 400x300 push drw]]
	return
	panel edge [size: 1x1][
		across origin 2x2
		H1 "View" return
		btn 60 "Left" [azimuth: azimuth - 5 build-drw] 
		btn 60 "Right" [azimuth: azimuth + 5 build-drw]
		return
		btn 60 "Up" [elevation: elevation + 5 build-drw]
		btn 60 "Down" [elevation: elevation - 5 build-drw]
		return
; 		btn 60 "Approcher" [distance: distance - 100 build-drw] 
; 		btn 60 "Eloigner" [distance: distance + 100 build-drw]
	]
	tab
	panel edge [size: 1x1][
		across origin 2x2
		H1 "Object" return
		btn 60 "Roll left" [rotate-object -5 0 0 cube build-drw]
		btn 60 "Roll right" [rotate-object 5 0 0 cube build-drw]
		return
		btn 60 "Pitch down" [rotate-object 0 -5 0 cube build-drw]
		btn 60 "Pitch up" [rotate-object 0 5 0 cube build-drw]
		return
		btn 60 "Yaw left" [rotate-object 0 0 -5 cube build-drw]
		btn 60 "Yaw right" [rotate-object 0 0 5 cube build-drw]
	]
]

cube: make object [
	points: reduce [
		make point [x: -100 y: -100 z: -100]
		make point [x: -100 y: -100 z:  100]
		make point [x: -100 y:  100 z:  100]
		make point [x: -100 y:  100 z: -100]

		make point [x:  100 y: -100 z: -100]
		make point [x:  100 y: -100 z:  100]
		make point [x:  100 y:  100 z:  100]
		make point [x:  100 y:  100 z: -100]

		make point [x:    0 y:    0 z:    0]
		
		make point [x:    0 y:    0 z:    0]
		make point [x: -100 y:    0 z: -100]
		make point [x: -100 y:    0 z:  100]
	]
	surfaces: reduce [
; 		make surface [draw: [pen snow fill-pen ivory polygon (pairs)] refs: [1 2 3 4 1]]
		make surface [draw: [pen snow fill-pen red polygon (pairs)] refs: [1 5 6 2]]
		make surface [draw: [pen snow fill-pen green polygon (pairs)] refs: [2 6 7 3]]
		make surface [draw: [pen snow fill-pen blue polygon (pairs)] refs: [3 7 8 4]]
		make surface [draw: [pen snow fill-pen magenta polygon (pairs)] refs: [4 8 5 1]]
 		make surface [draw: [pen snow fill-pen pink polygon (pairs)] refs: [5 6 7 8]]
 		make surface [draw: [pen snow fill-pen black polygon (pairs)] refs: [10 11 12]]
 		
 		make surface [draw: [pen gold fill-pen yellow circle (pairs) 15] refs: [9]]
	]
]


do build-drw: does [
	azimuth: remainder azimuth 360
	elevation: remainder elevation 360
	distance: maximum 200 round distance
	drw: draw-object elevation azimuth distance cube
	show b
]

view lay
ldci18-Mar-2011/23:10:43+1:00
Salut
Efficace, mais regarde la library r3d-matrix.r ( matrix and vector library) qui n'est pas mal du tout
none19-Mar-2011/0:21:48+1:00
r3d-Matrix.r and r3d-engine.r sont absoument géniaux mais c'est trop compliqué pour moi et je ne saurais pas les utiliser.

Mon truc minimaliste est une sorte d'extension 3d de draw et on peut quand même faire des choses assez sympa qui intègre par exemple un spline et un texte vectoriel (dernière surface):
REBOL []

matrice-product: func [
	{Produit matriciel ordinaire de deux matrices.
	Retourne une matrice (m,p) (block! de m block! de p éléments}
	matrice-1 [block!] {Matrice (m,n) (block! de m block! de n élément)}
	matrice-2 [block!] {Matrice (n,p) (block! de n block! de p élément)}
	/local l1 c1 l2 c2 result
][
	l1: length? matrice-1
	c1: length? matrice-1/1
	l2: length? matrice-2
	c2: length? matrice-2/1
	result: array/initial reduce [l1 c2] 0
	for i 1 l1 1 [
		for j 1 c2 1 [
			for k 1 c1 1 [
				result/(i)/(j): result/(i)/(j) + (matrice-1/(i)/(k) * matrice-2/(k)/(j))
			]
		]
	]
	result
]

matrice-rotation: func [
	{Calcul la matrice de rotation en fonction d'un axe et d'un angle de rotation}
	axe [object!] {Axe de rotation}
	alpha [number!] {Angle de rotation}
	/local c s C1 xs ys zs xC yC zC xyC yzC zxC
][
	C1: 1 - c: cosine(alpha) s: sine(alpha)
	xs: axe/x * s   ys: axe/y * s   zs: axe/z * s
	xC: axe/x * C1   yC: axe/y * C1   zC: axe/z * C1
	xyC: axe/x * yC  yzC: axe/y * zC zxC: axe/z * xC
	reduce [	
		reduce [ axe/x * xC + c   xyC - zs   zxC + ys ]
		reduce [ xyC + zs   axe/y * yC + c   yzC - xs ]
		reduce [ zxC - ys   yzC + xs   axe/z * zC + c ]
	]
]

point: context [x: y: z: 0]

rotate-point: func [
	{Applique une matrice de rotation sur un point}
	point [object!]
	matrice [block!]
	/local x y z
][
	x: point/x y: point/y z: point/z
	point/x: (x * matrice/1/1) + (y * matrice/1/2) + (z * matrice/1/3)
	point/y: (x * matrice/2/1) + (y * matrice/2/2) + (z * matrice/2/3)
	point/z: (x * matrice/3/1) + (y * matrice/3/2) + (z * matrice/3/3)
]

surface: context [
	draw: [pen ivory fill-pen snow polygon (pairs)]
	refs: []                 ; Pointeurs sur les points
]

object: context [
	axes: reduce [ ; Current axes
		make point [x: 1 y: 0 z: 0] ; Axe des x
		make point [x: 0 y: 1 z: 0] ; Axe des y
		make point [x: 0 y: 0 z: 1] ; Axe des z
	]
	points: []		; Liste des points
	surfaces: []	; Liste des surfaces
]

rotate-object: func [
	{Calcul les nouvelles coordonnées d'un point en appliquant une rotation}
	roll [number!]  {Rotation autour de l'axe des x = aileron - positif vers la droite}
	pitch [number!] {Rotation autour de l'axe des y = profondeur - positif vers le haut}
	yaw [number!]   {Rotation autour de l'axe des z = direction - positif vers la droite}
	object [object!] {L'objet à faire tourner}
	/local matrice-x matrice-y matrice-z matrice
][
; Calcul les matrices selon les trois axes
	matrice-x: matrice-rotation object/axes/1 roll  ; Matrice de rotation autour de x
	matrice-y: matrice-rotation object/axes/2 pitch ; Matrice de rotation autour de y
	matrice-z: matrice-rotation object/axes/3 yaw   ; Matrice de rotation autour de z

; Multiplie les trois matrices	
	matrice: matrice-product matrice-product matrice-x matrice-y matrice-z

; Applique la rotation aux trois axes
	foreach axe object/axes [
		rotate-point axe matrice
	]

; Applique la rotation à tous les points
	foreach point object/points [
		rotate-point point matrice
	]

; Retourne l'objet
	object
]

draw-object: func [
	elevation [number!]
	azimuth [number!]
	distance [number!]
	object [object!]
	/local
		matrice-x matrice-z matrice
		points surfaces draws pairs len result
][
	matrice-x: matrice-rotation make point [x: 1 y: 0 z: 0] elevation ; Axe des x
	matrice-z: matrice-rotation make point [x: 0 y: 0 z: 1] azimuth ; Axe des z
	matrice: matrice-product matrice-x matrice-z

; Crée le nouvel ensemble de point :
; - applique la matrice de rotation
; - et effectue la projection (x -> x et z -> y)
	points: make block! length? object/points
	foreach point object/points [
		append points new-point: make point [pair: 0x0] ; Ajoute la pair! projetée au point.
		rotate-point new-point matrice
		ratio: distance / either zero? ratio: distance - new-point/y [1][ratio]
		new-point/pair/x: round new-point/x * ratio		
		new-point/pair/y: negate round new-point/z * ratio		
	]

; Construit les éléments graphiques
; et les trie du plus éloigné au moins éloigné
	draws: make block! 2 * length? object/surfaces
	foreach surface object/surfaces [
		len: 0
	 	pairs: make block! length? surface/refs
		foreach ref surface/refs [
			len: len + points/(ref)/y
			append pairs points/(ref)/pair 
		]
		bind surface/draw 'pairs
		append draws reduce [len / length? surface/refs compose surface/draw]
	]
	sort/skip draws 2

; Produit le résultat à partir des éléments graphiques triés
	result: copy []
	foreach [len draw] draws [
		append result draw
	]

; Retourne le block! draw
	result
]


azimuth: 270
elevation: 0
distance: 600

drw: []

lay: layout [
	across
	b: box 800x600 edge [size: 1x1] effect [draw [line-width 3 translate 400x300 push drw]]
	return
	panel edge [size: 1x1][
		across origin 2x2
		H1 "View" return
		btn 60 "Left" [azimuth: azimuth - 5 build-drw] 
		btn 60 "Right" [azimuth: azimuth + 5 build-drw]
		return
		btn 60 "Up" [elevation: elevation + 5 build-drw]
		btn 60 "Down" [elevation: elevation - 5 build-drw]
		return
; 		btn 60 "Approcher" [distance: distance - 100 build-drw] 
; 		btn 60 "Eloigner" [distance: distance + 100 build-drw]
	]
	tab
	panel edge [size: 1x1][
		across origin 2x2
		H1 "Object" return
		btn 60 "Roll left" [rotate-object -5 0 0 cube build-drw]
		btn 60 "Roll right" [rotate-object 5 0 0 cube build-drw]
		return
		btn 60 "Pitch down" [rotate-object 0 -5 0 cube build-drw]
		btn 60 "Pitch up" [rotate-object 0 5 0 cube build-drw]
		return
		btn 60 "Yaw left" [rotate-object 0 0 -5 cube build-drw]
		btn 60 "Yaw right" [rotate-object 0 0 5 cube build-drw]
	]
]
my-font: make face/font [style: [bold italic] size: 32]

cube: make object [
	points: reduce [
		make point [x: -100 y: -100 z: -100]
		make point [x: -100 y: -100 z:  100]
		make point [x: -100 y:  100 z:  100]
		make point [x: -100 y:  100 z: -100]

		make point [x:  100 y: -100 z: -100]
		make point [x:  100 y: -100 z:  100]
		make point [x:  100 y:  100 z:  100]
		make point [x:  100 y:  100 z: -100]

		make point [x:    0 y:    0 z:    0]
		
		make point [x:    0 y:    0 z:    0]
		make point [x: -100 y:    0 z: -100]
		make point [x: -100 y:    0 z:  100]
	]
	surfaces: reduce [
		make surface [draw: [pen snow fill-pen none polygon (pairs)] refs: [1 5 6 2]]
		make surface [draw: [pen snow fill-pen none polygon (pairs)] refs: [2 6 7 3]]
		make surface [draw: [pen snow fill-pen none polygon (pairs)] refs: [3 7 8 4]]
		make surface [draw: [pen snow fill-pen none polygon (pairs)] refs: [4 8 5 1]]
 		make surface [draw: [pen snow fill-pen pink polygon (pairs)] refs: [5 6 7 8]]
 		make surface [draw: [pen snow fill-pen black polygon (pairs)] refs: [10 11 12]]
 		
 		make surface [draw: [pen gold fill-pen yellow circle (pairs) 15] refs: [9]]
 		
 		make surface [draw: [
 			pen cyan fill-pen none spline 10 (pairs) closed
 			font my-font pen navy fill-pen red text vectorial (pairs) "3D curved text rendered by DRAW!" 600 closed
 			] refs: [1 2 3 4 5 6 7 8]]
	]
]


do build-drw: does [
	azimuth: remainder azimuth 360
	elevation: remainder elevation 360
	distance: maximum 200 round distance
	drw: draw-object elevation azimuth distance cube
	show b
]

view lay
ldci19-Mar-2011/12:22:16+1:00
@coccinelle
C'est super car effectivement plus simple que la lib r3d
Bonne illustration de l'utilisation de rebol pour un besoin spécifique.
On pourrait pas commander ton Quetzal à partir de rebol?
coccinelle19-Mar-2011/16:53:59+1:00
Si quand tu dis "commander ton Quetzal à partir de rebol", tu penses à un simulateur de vol, la réponse est clairement NON.

Par contre, l'idée du Quetzal est de pouvoir générer facilement des modèles pour le simulateur CRRCSim qui est probablement l'un des plus réaliste au niveau du vol mais pas le plus beau graphiquement, quoique...

Voici une nouvelle mouture avec la notion de front et de back qui permet de dessiner les choses différemment selon que la série de point fait "face" ou au contraire "dos" à l'observateur.

La convention est que lorsque les points tournent dans le sens inverse des aiguilles d'une montre, on considère que la série fait "face" à l'observateur.

Dans le cadre du cube, cela permet par exemple de bien distinguer l'interieur de l'extérieur.

REBOL []

point: context [x: y: z: 0]

surface: context [
	front-draw: [pen ivory fill-pen snow polygon (pairs)]
	back-draw: []
	refs: []                 ; Pointeurs sur les points
]

object: context [
	axes: reduce [ ; Current axes
		make point [x: 1 y: 0 z: 0] ; Axe des x
		make point [x: 0 y: 1 z: 0] ; Axe des y
		make point [x: 0 y: 0 z: 1] ; Axe des z
	]
	points: []		; Liste des points
	surfaces: []	; Liste des surfaces
]
draw-object: none
rotate-object: none

ctx-3d: context [
	
	set 'draw-object func [
		elevation [number!]
		azimuth [number!]
		distance [number!]
		object [object!]
		/local
			matrice-x matrice-z matrice
			points surfaces draws draw pairs side len result
	][
		matrice-x: matrice-rotation make point [x: 1 y: 0 z: 0] elevation ; Axe des x
		matrice-z: matrice-rotation make point [x: 0 y: 0 z: 1] azimuth ; Axe des z
		matrice: matrice-product matrice-x matrice-z
	
; Crée le nouvel ensemble de point :
; - applique la matrice de rotation
; - et effectue la projection (x -> x et z -> y)
		points: make block! length? object/points
		foreach point object/points [
			append points new-point: make point [pair: 0x0] ; Ajoute la pair! projetée au point.
			rotate-point new-point matrice
			ratio: distance / either zero? ratio: distance - new-point/y [1][ratio]
			new-point/pair/x: round new-point/x * ratio		
			new-point/pair/y: negate round new-point/z * ratio		
		]
	
; Construit les éléments graphiques
; - détermne le sens de rotation des points pour savoir 
;   si l'on affiche le front-face ou le back-face
; - et les trie du plus éloigné au moins éloigné
		draws: make block! 2 * length? object/surfaces
		foreach surface object/surfaces [
			len: 0 side: 0
			prev-pair: points/(last surface/refs)/pair
			prev-angle: alpha-xy prev-pair - points/(first back back tail surface/refs)/pair
		 	pairs: make block! length? surface/refs
			foreach ref surface/refs [
				len: len + points/(ref)/y
				wrk: 0 - prev-angle + prev-angle: alpha-xy 0x0 - prev-pair + prev-pair: points/(ref)/pair
				if 180 <  wrk [wrk: wrk - 360]
				if -180 > wrk [wrk: wrk + 360]
				side: side + wrk
				append pairs points/(ref)/pair 
			]
			draw: bind either negative? side [surface/back-draw][surface/front-draw] 'pairs
			append draws reduce [len / length? surface/refs compose/deep draw]
		]
		sort/skip draws 2
	
; Produit le résultat à partir des éléments graphiques triés
		result: copy []
		foreach [len draw] draws [
			append result draw
		]
	
; Retourne le block! draw
		result
	]
	
	set 'rotate-object func [
		{Calcule les nouvelles coordonnées d'un point en appliquant une rotation}
		roll [number!]  {Rotation autour de l'axe des x = aileron - positif vers la droite}
		pitch [number!] {Rotation autour de l'axe des y = profondeur - positif vers le haut}
		yaw [number!]   {Rotation autour de l'axe des z = direction - positif vers la droite}
		object [object!] {L'objet à faire tourner}
		/local matrice-x matrice-y matrice-z matrice
	][
; Calcul les matrices selon les trois axes
		matrice-x: matrice-rotation object/axes/1 roll  ; Matrice de rotation autour de x
		matrice-y: matrice-rotation object/axes/2 pitch ; Matrice de rotation autour de y
		matrice-z: matrice-rotation object/axes/3 yaw   ; Matrice de rotation autour de z
	
; Multiplie les trois matrices	
		matrice: matrice-product matrice-product matrice-x matrice-y matrice-z
	
; Applique la rotation aux trois axes
		foreach axe object/axes [
			rotate-point axe matrice
		]
	
; Applique la rotation à tous les points
		foreach point object/points [
			rotate-point point matrice
		]
	
; Retourne l'objet
		object
	]
	
	rotate-point: func [
		{Applique une matrice de rotation sur un point}
		point [object!]
		matrice [block!]
		/local x y z
	][
		x: point/x y: point/y z: point/z
		point/x: (x * matrice/1/1) + (y * matrice/1/2) + (z * matrice/1/3)
		point/y: (x * matrice/2/1) + (y * matrice/2/2) + (z * matrice/2/3)
		point/z: (x * matrice/3/1) + (y * matrice/3/2) + (z * matrice/3/3)
	]
	
	matrice-product: func [
		{Produit matriciel ordinaire de deux matrices.
		Retourne une matrice (m,p) (block! de m block! de p éléments}
		matrice-1 [block!] {Matrice (m,n) (block! de m block! de n élément)}
		matrice-2 [block!] {Matrice (n,p) (block! de n block! de p élément)}
		/local l1 c1 l2 c2 result
	][
		l1: length? matrice-1
		c1: length? matrice-1/1
		l2: length? matrice-2
		c2: length? matrice-2/1
		result: array/initial reduce [l1 c2] 0
		for i 1 l1 1 [
			for j 1 c2 1 [
				for k 1 c1 1 [
					result/(i)/(j): result/(i)/(j) + (matrice-1/(i)/(k) * matrice-2/(k)/(j))
				]
			]
		]
		result
	]
	
	matrice-rotation: func [
		{Calcul la matrice de rotation en fonction d'un axe et d'un angle de rotation}
		axe [object!] {Axe de rotation}
		alpha [number!] {Angle de rotation}
		/local c s C1 xs ys zs xC yC zC xyC yzC zxC
	][
		C1: 1 - c: cosine(alpha) s: sine(alpha)
		xs: axe/x * s   ys: axe/y * s   zs: axe/z * s
		xC: axe/x * C1   yC: axe/y * C1   zC: axe/z * C1
		xyC: axe/x * yC  yzC: axe/y * zC zxC: axe/z * xC
		reduce [	
			reduce [ axe/x * xC + c   xyC - zs   zxC + ys ]
			reduce [ xyC + zs   axe/y * yC + c   yzC - xs ]
			reduce [ zxC - ys   yzC + xs   axe/z * zC + c ]
		]
	]

	alpha-xy: func [
		{Calcul l'angle d'un point dans le repère de view (y pointe vers en bas)}
		pair [pair!] {Un point dans le repère de view}
		/local x y
	][

; L'algorithme doit pouvoir être largement amélioré mais ça marche :-)
		x: pair/x y: negate pair/y
		do select [
			 0  0 [0]
			 1  0 [0]
			 1  1 [arctangent y / x]
			 0  1 [90]
			-1  1 [180 + arctangent y / x]
			-1  0 [180]
			-1 -1 [180 + arctangent y / x]
			 0 -1 [270]
			 1 -1 [360 + arctangent y / x]
		] reduce [sign? x sign? y]
	]
	
]

font-16: make face/font [size: 16]

cube: make object [
	points: reduce [
		make point [x: -100 y:  100 z: -100]
		make point [x:  100 y:  100 z: -100]
		make point [x:  100 y:  100 z:  100]
		make point [x: -100 y:  100 z:  100]

		make point [x: -100 y: -100 z: -100]
		make point [x:  100 y: -100 z: -100]
		make point [x:  100 y: -100 z:  100]
		make point [x: -100 y: -100 z:  100]

		make point [x:    0 y:    0 z:    0]
		make point [x: -100 y:    0 z: -100]
		make point [x: -100 y:    0 z:  100]
	]
	surfaces: reduce [
 		make surface [front-draw: back-draw: [font font-16 pen black text vectorial (pairs/1 * 1.1) "1"] refs: [1]]
 		make surface [front-draw: back-draw: [font font-16 pen black text vectorial (pairs/1 * 1.1) "2"] refs: [2]]
 		make surface [front-draw: back-draw: [font font-16 pen black text vectorial (pairs/1 * 1.1) "3"] refs: [3]]
 		make surface [front-draw: back-draw: [font font-16 pen black text vectorial (pairs/1 * 1.1) "4"] refs: [4]]
 		make surface [front-draw: back-draw: [font font-16 pen black text vectorial (pairs/1 * 1.1) "5"] refs: [5]]
 		make surface [front-draw: back-draw: [font font-16 pen black text vectorial (pairs/1 * 1.1) "6"] refs: [6]]
 		make surface [front-draw: back-draw: [font font-16 pen black text vectorial (pairs/1 * 1.1) "7"] refs: [7]]
 		make surface [front-draw: back-draw: [font font-16 pen black text vectorial (pairs/1 * 1.1) "8"] refs: [8]]

 		make surface [
 			front-draw: [pen coal fill-pen red polygon (pairs)]
 			back-draw: [pen snow fill-pen orange polygon (pairs)]
  			refs: [5 8 7 6]
 		]
 		make surface [
 			front-draw: [pen coal fill-pen green polygon (pairs)]
 			back-draw: [pen snow fill-pen leaf polygon (pairs)]
 			refs: [1 5 6 2]
 		]
 		make surface [
 			front-draw: [pen coal fill-pen blue polygon (pairs)]
 			back-draw: [pen snow fill-pen navy polygon (pairs)]
 			refs: [2 6 7 3]
 		]
 		make surface [
 			front-draw: [pen coal fill-pen magenta polygon (pairs)]
 			back-draw: [pen snow fill-pen pink polygon (pairs)]
 			refs: [3 7 8 4]
 		]
 		make surface [
 			front-draw: [pen coal fill-pen yellow polygon (pairs)]
 			back-draw: [pen snow fill-pen gold polygon (pairs)]
 			refs: [1 2 3 4]
 		]

  		make surface [front-draw: back-draw: [pen none fill-pen mint circle (pairs) 15] refs: [9]]
  		
  		make surface [
  			front-draw: back-draw: [pen snow fill-pen coal polygon (pairs)]
  			refs: [9 10 11]
  		]
	]
]

lay: layout [
	across
	b: box 800x600 edge [size: 1x1] effect [draw [line-width 2 translate 400x300 push drw]]
	return
	panel edge [size: 1x1][
		across origin 2x2
		H1 "View" return
		btn 60 "Left" [azimuth: azimuth - 5 build-drw] 
		btn 60 "Right" [azimuth: azimuth + 5 build-drw]
		return
		btn 60 "Down" [elevation: elevation - 5 build-drw]
		btn 60 "Up" [elevation: elevation + 5 build-drw]
	]
	tab
	panel edge [size: 1x1][
		across origin 2x2
		H1 "Object" return
		btn 60 "Roll left" [rotate-object -5 0 0 cube build-drw]
		btn 60 "Roll right" [rotate-object 5 0 0 cube build-drw]
		return
		btn 60 "Pitch down" [rotate-object 0 -5 0 cube build-drw]
		btn 60 "Pitch up" [rotate-object 0 5 0 cube build-drw]
		return
		btn 60 "Yaw left" [rotate-object 0 0 -5 cube build-drw]
		btn 60 "Yaw right" [rotate-object 0 0 5 cube build-drw]
	]
]

azimuth: -90 - 25
elevation: 25
distance: 600

do build-drw: does [
	azimuth: remainder azimuth 360
	elevation: remainder elevation 360
	distance: maximum 200 round distance
	drw: draw-object elevation azimuth distance cube
	show b
]

view lay
Didec21-Mar-2011/10:41:47+1:00
Là encore, très sympa ce résultat.
Toujours aussi fortiche Marco !
coccinelle21-Mar-2011/13:42:49+1:00
Merci Didec,

Fortiche, je ne sais pas, mais comme toujours avec Rebol, si l'on ne cherche pas imiter ce qui se fait avec d'autres langages mais que l'on cherche au mieux avec Rebol à résoudre son problème, Rebol est généralement plutôt efficace.

Je me réjouis d'intégrer ça dans le Quetzal pour pouvoir visualiser le planeur en entier en 3D.

@+ Marco.

Login required to Post.


Powered by RebelBB and REBOL 2.7.8.4.2