3D vers 2D avec perspective

Partagez votre expérience de PureBasic avec les autres utilisateurs.
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: 3D vers 2D avec perspective

Message par Ollivier »

@LSI

Je doute sur la crédibilité de tes calculs de rotation. Et je trouve étrange que personne n'en ai encore fait la remarque avant que tu commences l'optimisation.

Peut-être devrions-nous préparer un ensemble de conventions sur les rotations dans l'espace dans la section Info&Tuto ?

Ollivier
Warkering
Messages : 808
Inscription : ven. 08/janv./2010 1:14
Localisation : Québec, Canada

Re: 3D vers 2D avec perspective

Message par Warkering »

Moi, je me fous des calculs, tant que ça me dise que mon portable est une bombe! :mrgreen:
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: 3D vers 2D avec perspective

Message par Le Soldat Inconnu »

Mes calcul sont basé sur les équations de changement de repère de mes cours de mécaniques. et je n'ai jamais de problèmes avec. Je vais faire quelques test pour voir.
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)]
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: 3D vers 2D avec perspective

Message par Le Soldat Inconnu »

Après test, j'avais une erreur d'affichage car l'écran affiche les Y de haut en bas, donc j'ai inversé l'affichage des Y en les mettant en négatif.

Sinon, pour le calcul, il est OK. Le sens de rotation de chaque axe est bon (sens trigo). Et le sens mon repère XYZ est correct (vérifier par la règle des 3 doigts, pouce et index à angle droit, majeur perpendiculaire à la pause de la main. Pouce = axe X, Index = axe Y, majeur = axe Z)

J'ai ajouter un mode manuel pour pouvoir jouer manuellement avec les angles. Regarde le premier sujet. L'entête du programme décrit les touches.
Si il y a qlqchose qui te choques, dis moi. parce que pour moi, tous est OK.
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)]
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: 3D vers 2D avec perspective

Message par Ollivier »

Bonjour LSI,

Je te prie de m'excuser de t'avoir snobé: c'est involontaire. J'ai ommis quelque peu certaines choses ces derniers temps... :mrgreen:

Je viens de vérifier ton programme. Il possède la même erreur qu'à l'origine. Dès que j'ai du temps, je me concentre sur ce problème...
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: 3D vers 2D avec perspective

Message par Ollivier »

Voilà...

* J'ai, d'abord été page 1 de ce sujet récupérer le tout premier code du post n°1. Je précise au cas où une étourderie m'eusse contraint à copier un autre code que celui décrit et normalement concerné! Si l'erreur est là, j'en suis confus. :roll:

* Une fois collé chez moi, chaque modification dans ton code a été clairement balisé. Ne sont balisés que mes ajouts de code m'appartenant et mes suppressions effectuées sur le code t'appartenant. Ainsi, tu vois parfaitement ce que j'ai modifié, quelqu'en soit la modification volontaire!

* J'ai totalisé 6 modifications commentées, numérotées et ordonnées de 1 à 6. Ainsi, tu peux manuellement effectuer l'annulation de mes modifications MAIS en prenant soin de respecter l'ordre décroissant de la modification numéro 6 qui est la première annulation jusqu'à la modification numéro 1 qui est, elle, la dernière annulation. Ainsi, en comparant avec l'originale, tu as la possibilité de voir parfaitement ce que j'ai modifié par mégarde, quelqu'en soit la modification involontaire!

* L'exécution du diptique obtenu, tu peux aisément tester les 3 rotations offertes par ton procédé calculatoire : cela fonctionne impeccablement.
Les touches HAUT et BAS exécutent la rotation absolue sur l'axe des x (de couleur verte);
Les touches TAB et A exécutent la rotation absolue sur l'axe des y (de couleur rouge);
Les touches GAUCHE et DROITE exécutent la rotation relative sur l'axe des z (de couleur bleue);

(Rem 1 : J'ai donné des définitions de ce que je nomme la « rotation absolue » et la « rotation relative ». Ce sont des définitions personnelles et je ne suis pas académicien donc tu as éventuellement un jargon à m'apprendre à ce sujet.
Rem 2 : Le fait que ton procédé exécute 2 rotations absolues selon 2 premiers axes et une rotation relative selon le 3ème axe restant n'est pas un défaut invalidant. Cependant, le procédé d'exécution de 3 rotations absolues, comme son procédé complémentaire d'exécution de 3 rotations relatives approche d'une conception plus « conventionnelle », de par leur simplicité d'utilisation - L'utilisateur est respectivement soit le décor qui contraint l'objet par une rotation, soit l'objet lui-même qui se contraint par une rotation - Dans ton code, ce dicernement de repérage reste ambigü selon les axes concernés)

* Durant l'exécution, l'appui sur la touche ESPACE, provoque le démarrage d'une DEMO. Cette démonstration opère en 4 temps:
1) Les 3 axes sont mis à zéro
2) Une rotation de pi/3 est exécutée sur l'axe des x
3) Une rotation de pi/3 est exécutée sur l'axe des y
4) Une rotation de pi/3 est exécutée sur l'axe des z
On obtient une orientation particulière du trièdre.

* Au départ d'une exécution, en respectant quelques gestes simples de contrôle, tu peux procéder comme suit:
1) Fais des va-et-vients avec les touches HAUT et BAS pour contrôler la rotation sur l'axe des x (axe vert)
2) Appuie sur ESPACE pour déclencher la démo.
3) Fais à nouveau des va-et-vients selon l'axe des x, c'est-à-dire de manière similaire à l'étape 1

Question : la rotation de l'étape 3 selon l'axe des x est-elle désormais crédible?

Mon avis est de dire non car ni une rotation absolue, ni une rotation relative au trièdre ne se caractèrise en cette rotation. Cette rotation s'effectue désormais (après la démo) selon un axe intermédiaire actuellement invisible. S'il y a une rotation selon un axe « fantôme », le choix de remettre en cause ton procédé sur le plan de la crédibilité me semble conforme.

Code : Tout sélectionner

; Auteur : Le Soldat Inconnu
; Version de PB :  4.5
;
; Explication du programme :
; Exemple qui montre comment dessiner un repère XYZ en 3D
; Touche d'utilisation :
; Enter : Passage de la rotation automatique à manuelle
; X : En mode de rotation manuelle, change l'angle sur l'axe X
; Y : En mode de rotation manuelle, change l'angle sur l'axe Y
; Z : En mode de rotation manuelle, change l'angle sur l'axe Z


Structure Point3D
   x.d
   y.d
   z.d
EndStructure
Structure Point3DP
   x.d
   y.d
   z.d
   p.d
EndStructure

#Angle_Resolution = 100
Global Dim Calculation_Cos.d(360 * #Angle_Resolution * 2)
Global Dim Calculation_Sin.d(360 * #Angle_Resolution * 2)
For i = -360 * #Angle_Resolution To 360 * #Angle_Resolution
   Calculation_Cos(i + 360 * #Angle_Resolution) = Cos(i * #PI / (180 * #Angle_Resolution))
   Calculation_Sin(i + 360 * #Angle_Resolution) = Sin(i * #PI / (180 * #Angle_Resolution))
Next

Procedure XYZ_Rotate(*Origine.Point3D, Angle_X_Axis.d, Angle_Y_Axis.d, Angle_Z_Axis.d, *Final.Point3D)
  ; Angle_X_Axis, ay, Angle_Z_Axis : angle de rotation du point sur l'Angle_X_Axise x, y et z, pour avoir un repère 3D décalé par rapport au repère de l'écran
  
  Protected Calcul.Point3D, Sin.d, Cos.d
  
   ; Rotation sur l'axe Z
   If Angle_Z_Axis
      ; Cos = Cos(Angle_Z_Axis)
      ; Sin = Sin(Angle_Z_Axis)
      Angle.i = Angle_Z_Axis * #Angle_Resolution * 180 / #PI + 360 * #Angle_Resolution
      Cos = Calculation_Cos(Angle)
      Sin = Calculation_Sin(Angle)
      Calcul\x = *Origine\x * Cos - *Origine\y * Sin
      Calcul\y = *Origine\x * Sin + *Origine\y * Cos
   Else
      Calcul\x = *Origine\x
      Calcul\y = *Origine\y
   EndIf
  ; Debug StrD(Calcul\x) + " , " + StrD(Calcul\y) + " , " + StrD(*Origine\z)
  
  ; Rotation sur l'axe X
   If Angle_X_Axis
      ; Cos = Cos(Angle_X_Axis)
      ; Sin = Sin(Angle_X_Axis)
      Angle.i = Angle_X_Axis * #Angle_Resolution * 180 / #PI + 360 * #Angle_Resolution
      Cos = Calculation_Cos(Angle)
      Sin = Calculation_Sin(Angle)
      *Final\y = Calcul\y * Cos - *Origine\z * Sin
      Calcul\z = Calcul\y * Sin + *Origine\z * Cos
   Else
      *Final\y = Calcul\y
      Calcul\z = *Origine\z
   EndIf
  ; Debug StrD(Calcul\x) + " , " + StrD(*Final\y) + " , " + StrD(Calcul\z)
  
  ; Rotation sur l'axe Y
   If Angle_Y_Axis
      ; Cos = Cos(Angle_Y_Axis)
      ; Sin = Sin(Angle_Y_Axis)
      Angle.i = Angle_Y_Axis * #Angle_Resolution * 180 / #PI + 360 * #Angle_Resolution
      Cos = Calculation_Cos(Angle)
      Sin = Calculation_Sin(Angle)
      *Final\z = Calcul\z * Cos - Calcul\x * Sin
      *Final\x = Calcul\z * Sin + Calcul\x * Cos
   Else
      *Final\z = Calcul\z
      *Final\x = Calcul\x
   EndIf
  ; Debug StrD(*Final\x) + " , " + StrD(*Final\y) + " , " + StrD(*Final\z)
EndProcedure

Procedure XYFrom3D(*Origine.Point3D, Angle_X_Axis.d, Angle_Y_Axis.d, Angle_Z_Axis.d, Perspective.q, *Final.Point3DP)
  ; Angle_X_Axis, ay, Angle_Z_Axis : angle de rotation du point sur l'Angle_X_Axise x, y et z, pour avoir un repère 3D décalé par rapport au repère de l'écran
  
  XYZ_Rotate(*Origine.Point3D, Angle_X_Axis.d, Angle_Y_Axis.d, Angle_Z_Axis.d, *Final.Point3DP)
   
   *Final\p = 1 + Abs(*Final\z) / Perspective
  If *Final\z < 0
    *Final\p = 1 / *Final\p
   EndIf
   *Final\x * *Final\p
   *Final\y * *Final\p
   
EndProcedure


If InitSprite() = 0
  End
EndIf

If OpenWindow(0, 0, 0, 500, 500, "Le Soldat Inconnu", #PB_Window_ScreenCentered | #PB_Window_SystemMenu) = 0
  End
EndIf

If OpenWindowedScreen(WindowID(0), 0, 0, 500, 500, 1, 0, 0) = 0
  End
EndIf

AngleX.d = 0
AngleY.d = 0
AngleZ.d = 0

Rotation_Auto = 1

FontID = LoadFont(0, "Verdana", 8, #PB_Font_HighQuality)

;- 4) INITIALISATION CLAVIER AJOUTE *************v
If InitKeyboard() = 0: MessageRequester("Erreur", "Clavier ingérable!"): End: Else: KeyboardMode(#PB_Keyboard_International): EndIf
; FIN INIT CLAVIER AJOUTE **********************^

Repeat
  
  ;- 3) ATTENTE AJOUTEE **************************v (comme d'hab)
  Delay(1)
  ; FIN ATTENTE AJOUTEE **************************^
  
  ClearScreen($FFFFFF)
  
  ; On change l'angle d'inclinaison du texte (en fait, on change les angles entre le repère écran et le repère du texte)
  ; Vous pouver mettre les paramètres que vous voulez pour changer la rotation du repère 3D
  
  ;- 5) INTERFACE CLAVIER AJOUTE ****************************v
  ExamineKeyboard()
  If KeyboardPushed(#PB_Key_Escape): End          : EndIf ; Redondance de la fin de boucle
  If KeyboardPushed(#PB_Key_Up):     AngleX - 0.05: EndIf
  If KeyboardPushed(#PB_Key_Down):   AngleX + 0.05: EndIf
  If KeyboardPushed(#PB_Key_Left):   AngleZ - 0.05: EndIf
  If KeyboardPushed(#PB_Key_Right):  AngleZ + 0.05: EndIf
  If KeyboardPushed(#PB_Key_Tab):    AngleY - 0.05: EndIf
  If KeyboardPushed(#PB_Key_A):      AngleY + 0.05: EndIf
  If KeyboardPushed(#PB_Key_Space):  Demo | 1     : EndIf
  ; FIN GESTION CLAVIER AJOUTE ******************************^
  
  ;- 6) DEMO AJOUT ****************************************v
  If Demo & 3
    Demo | 2
    If Demo & 1
      Demo & ~$1
      AngleX = 0.
      AngleY = 0.
      AngleZ = 0.
      Phase = 0
    EndIf
    Select Phase
        Case 0
          AngleX + 0.05
          If AngleX => #PI / 3.
            Phase = 1
          EndIf
        Case 1
          AngleZ + 0.05
          If AngleZ => #PI / 3.
            Phase = 2
          EndIf
        Case 2
          AngleY + 0.05
          If AngleY => #PI / 3.
            Phase = 15
          EndIf
        Case 15
          Demo & ~$2
    EndSelect
  EndIf  
  ; FIN DEMO AJOUT ****************************************^
  
   ;- 2) MOUVEMENT AUTOMATIQUE COMMENTE *********v
   ;If Rotation_Auto
   ;   AngleX + 0.005
   ;   AngleY + 0.003
   ;   AngleZ + 0.002
   ;EndIf
   ; FIN MVT AUTO COMMENTE *********************^
   
   If AngleX > 2 * #PI
      AngleX - 2 * #PI
   ElseIf AngleX < 0
      AngleX + 2 * #PI
   EndIf
   
   If AngleY > 2 * #PI
      AngleY - 2 * #PI
   ElseIf AngleY < 0
      AngleY + 2 * #PI
   EndIf
   
   If AngleZ > 2 * #PI
      AngleZ - 2 * #PI
   ElseIf AngleZ < 0
      AngleZ + 2 * #PI
   EndIf
   
   X_Origine.Point3D
   X_Origine\x = 200
   Y_Origine.Point3D
   Y_Origine\y = 200
   Z_Origine.Point3D
   Z_Origine\z = 200
  
  StartDrawing(ScreenOutput())
    DrawingFont(FontID)
    DrawingMode(#PB_2DDrawing_Transparent)
      
    ; On affiche le repère
    ; la ligne représentant l'axe X en vert
    XYFrom3D(@X_Origine, AngleX, AngleY, AngleZ, 400, @Coord.Point3DP) ; on calcul les coordonnées de l'extrémité de la ligne pour l'affichage sur l'écran
    LineXY(250, 250, 250 + Coord\x, 250 - Coord\y, RGB(0, 255, 0)) ; on trace une ligne verte à partir du centre de l'image vers les coordonnées calculées
    Circle(250 + Coord\x, 250 - Coord\y, 5 * Coord\p, RGB(0, 255, 0)) ; on trace un cerle sur le bout de la ligne. La variable Coord\p permet de prendre en compte la perspective sur une forme de taille définie, ici un cercle mais également une image par exemple.
    DrawText(255 + Coord\x, 255 - Coord\y, "X", 0) ;On affiche le label de l'axe
    
    ; la ligne représentant l'axe Y en rouge
    XYFrom3D(@Y_Origine, AngleX, AngleY, AngleZ, 400, @Coord.Point3DP) ; on calcul les coordonnées de l'extrémité de la ligne pour l'affichage sur l'écran
    LineXY(250, 250, 250 + Coord\x, 250 - Coord\y, RGB(255, 0, 0))
    Circle(250 + Coord\x, 250 - Coord\y, 5 * Coord\p, RGB(255, 0, 0))
    DrawText(255 + Coord\x, 255 - Coord\y, "Y", 0)
    
    ; la ligne représentant l'axe Z en bleu
    XYFrom3D(@Z_Origine, AngleX, AngleY, AngleZ, 400, @Coord.Point3DP) ; on calcul les coordonnées de l'extrémité de la ligne pour l'affichage sur l'écran
    LineXY(250, 250, 250 + Coord\x, 250 - Coord\y, RGB(0, 0, 255))
    Circle(250 + Coord\x, 250 - Coord\y, 5 * Coord\p, RGB(0, 0, 255))
    DrawText(255 + Coord\x, 255 - Coord\y, "Z", 0)
    
  StopDrawing()
  
  FlipBuffers()

  Repeat
      Event = WindowEvent()
      
      ;- 1) INTERFACE COMMENTEE *********v
      ;If Event = #WM_KEYUP
      ;   Select EventwParam()
      ;      Case 'X'
      ;         AngleX + #PI/6
      ;      Case 'Y'
      ;         AngleY + #PI/6
      ;      Case 'Z'
      ;         AngleZ + #PI/6
      ;      Case 13
      ;         Rotation_Auto = 1 - Rotation_Auto
      ;         AngleX = 0
      ;         AngleY = 0
      ;         AngleZ = 0
      ;  EndSelect
      ;EndIf
      ; FIN INTERFACE COMMENTEE ********^
      
      If Event = #PB_Event_CloseWindow
         End
      EndIf
      
   Until Event = 0
   
ForEver
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: 3D vers 2D avec perspective

Message par Le Soldat Inconnu »

Alors, reprenons le procédé, je fais d'abord tourner sur l'axe Z, puis sur l'axe X et enfin sur l'axe Y. Car il faut bien choisir un ordre, n'est ce pas ?

Donc le seul axe dont la rotation te semblera crédible est l'axe Z, le premier.
En terme de rotation par rapport à un axe, cela te choque ? C'est normal, je parle de changement de repère, c'est un repère que je tourne sur 3 axes pour obtenir un nouveau repère.
Il faut toujours penser que la rotation du repère (et non de l'axe) se fait par rapport à l'origine et non par rapport au dernier résultat. Et en fonction de l'ordre définie de rotation soit Z puis X puis Y

Si tu veux une rotation crédible par rapport à un axe, c'est bien plus compliqué qu'un simple changement de repère et je dois dire que je sèche.

En mettant l'axe que l'on souhaite tourner en premier le rendu visuel est mieux sauf que l'orientation du repère n'est pas la même en fonction de l'ordre de rotation X Y Z (ce qui est normal). Donc ça ne va pas.

Si tu as une solution pour cela, je suis preneur.

voici mon essai

Code : Tout sélectionner

; Auteur : Le Soldat Inconnu
; Version de PB :  4.5
;
; Explication du programme :
; Exemple qui montre comment dessiner un repère XYZ en 3D
; Touche d'utilisation :
; Enter : Passage de la rotation automatique à manuelle
; X : En mode de rotation manuelle, change l'angle sur l'axe X
; Y : En mode de rotation manuelle, change l'angle sur l'axe Y
; Z : En mode de rotation manuelle, change l'angle sur l'axe Z


Structure Point3D
	x.d
	y.d
	z.d
EndStructure
Structure Point3DP
	x.d
	y.d
	z.d
	p.d
EndStructure

#Angle_Resolution = 100
Global Dim Calculation_Cos.d(360 * #Angle_Resolution)
Global Dim Calculation_Sin.d(360 * #Angle_Resolution)
For i = 0 To 360 * #Angle_Resolution
	Calculation_Cos(i) = Cos(i * #PI / (180 * #Angle_Resolution))
	Calculation_Sin(i) = Sin(i * #PI / (180 * #Angle_Resolution))
Next

Procedure XYZ_Rotate(*Origine.Point3D, Angle_X_Axis.d, Angle_Y_Axis.d, Angle_Z_Axis.d, Order.i, *Final.Point3D)
  ; Angle_X_Axis, ay, Angle_Z_Axis : angle de rotation du point sur l'Angle_X_Axise x, y et z, pour avoir un repère 3D décalé par rapport au repère de l'écran
  
  Protected Calcul.Point3D, Sin.d, Cos.d
  
	Select Order
		Case 2 ;- Axe Y en premier
			; Rotation sur l'axe Y
			Angle.i = Angle_Y_Axis * #Angle_Resolution * 180 / #PI
			Cos = Calculation_Cos(Angle)
			Sin = Calculation_Sin(Angle)
			Calcul\z = *Origine\z * Cos - *Origine\x * Sin
			Calcul\x = *Origine\z * Sin + *Origine\x * Cos
			; Rotation sur l'axe Z
			Angle.i = Angle_Z_Axis * #Angle_Resolution * 180 / #PI
			Cos = Calculation_Cos(Angle)
			Sin = Calculation_Sin(Angle)
			*Final\x = Calcul\x * Cos - *Origine\y * Sin
			Calcul\y = Calcul\x * Sin + *Origine\y * Cos
			; Rotation sur l'axe X
			Angle.i = Angle_X_Axis * #Angle_Resolution * 180 / #PI
			Cos = Calculation_Cos(Angle)
			Sin = Calculation_Sin(Angle)
			*Final\y = Calcul\y * Cos - Calcul\z * Sin
			*Final\z = Calcul\y * Sin + Calcul\z * Cos
		Case 3 ;- Axe Z en premier
			; Rotation sur l'axe Z
			Angle.i = Angle_Z_Axis * #Angle_Resolution * 180 / #PI
			Cos = Calculation_Cos(Angle)
			Sin = Calculation_Sin(Angle)
			Calcul\x = *Origine\x * Cos - *Origine\y * Sin
			Calcul\y = *Origine\x * Sin + *Origine\y * Cos
			; Rotation sur l'axe X
			Angle.i = Angle_X_Axis * #Angle_Resolution * 180 / #PI
			Cos = Calculation_Cos(Angle)
			Sin = Calculation_Sin(Angle)
			*Final\y = Calcul\y * Cos - *Origine\z * Sin
			Calcul\z = Calcul\y * Sin + *Origine\z * Cos
			; Rotation sur l'axe Y
			Angle.i = Angle_Y_Axis * #Angle_Resolution * 180 / #PI
			Cos = Calculation_Cos(Angle)
			Sin = Calculation_Sin(Angle)
			*Final\z = Calcul\z * Cos - Calcul\x * Sin
			*Final\x = Calcul\z * Sin + Calcul\x * Cos
		Default ;- Axe X en premier
			; Rotation sur l'axe X
			Angle.i = Angle_X_Axis * #Angle_Resolution * 180 / #PI
			Cos = Calculation_Cos(Angle)
			Sin = Calculation_Sin(Angle)
			Calcul\y = *Origine\y * Cos - *Origine\z * Sin
			Calcul\z = *Origine\y * Sin + *Origine\z * Cos
			; Rotation sur l'axe Y
			Angle.i = Angle_Y_Axis * #Angle_Resolution * 180 / #PI
			Cos = Calculation_Cos(Angle)
			Sin = Calculation_Sin(Angle)
			*Final\z = Calcul\z * Cos - *Origine\x * Sin
			Calcul\x = Calcul\z * Sin + *Origine\x * Cos
			; Rotation sur l'axe Z
			Angle.i = Angle_Z_Axis * #Angle_Resolution * 180 / #PI
			Cos = Calculation_Cos(Angle)
			Sin = Calculation_Sin(Angle)
			*Final\x = Calcul\x * Cos - Calcul\y * Sin
			*Final\y = Calcul\x * Sin + Calcul\y * Cos
			
	EndSelect

EndProcedure

Procedure XYFrom3D(*Origine.Point3D, Angle_X_Axis.d, Angle_Y_Axis.d, Angle_Z_Axis.d, Order.i, Perspective.q, *Final.Point3DP)
  ; Angle_X_Axis, ay, Angle_Z_Axis : angle de rotation du point sur l'Angle_X_Axise x, y et z, pour avoir un repère 3D décalé par rapport au repère de l'écran
  
  XYZ_Rotate(*Origine.Point3D, Angle_X_Axis.d, Angle_Y_Axis.d, Angle_Z_Axis.d, Order.i, *Final.Point3DP)
	
	*Final\p = 1 + Abs(*Final\z) / Perspective
  If *Final\z < 0
    *Final\p = 1 / *Final\p
	EndIf
	*Final\x * *Final\p
	*Final\y * *Final\p
	
EndProcedure


If InitSprite() = 0
  End
EndIf

If OpenWindow(0, 0, 0, 500, 500, "Le Soldat Inconnu", #PB_Window_ScreenCentered | #PB_Window_SystemMenu) = 0
  End
EndIf

If OpenWindowedScreen(WindowID(0), 0, 0, 500, 500, 1, 0, 0) = 0
  End
EndIf

AngleX.d = 0
AngleY.d = 0
AngleZ.d = 0
AngleX2.d = AngleX
AngleY2.d = AngleY
AngleZ2.d = AngleZ

Rotation_Auto = 1

X_Origine.Point3D
X_Origine\x = 200
Y_Origine.Point3D
Y_Origine\y = 200
Z_Origine.Point3D
Z_Origine\z = 200

FontID = LoadFont(0, "Verdana", 8, #PB_Font_HighQuality)

Repeat

  ClearScreen($FFFFFF)
  
  ; On change l'angle d'inclinaison du texte (en fait, on change les angles entre le repère écran et le repère du texte)
  ; Vous pouvez mettre les paramètres que vous voulez pour changer la rotation du repère 3D
	If Rotation_Auto
		AngleX + 0.005
		AngleY + 0.003
		AngleZ + 0.002
	EndIf
	
	If AngleX > 2 * #PI
		AngleX - 2 * #PI
	ElseIf AngleX < 0
		AngleX + 2 * #PI
	EndIf
	If AngleY > 2 * #PI
		AngleY - 2 * #PI
	ElseIf AngleY < 0
		AngleY + 2 * #PI
	EndIf
	If AngleZ > 2 * #PI
		AngleZ - 2 * #PI
	ElseIf AngleZ < 0
		AngleZ + 2 * #PI
	EndIf
	
	; Recherche de l'axe qui bouge pour ordonner les rotations
	If AngleX <> AngleX2
		Ordre = 1
	ElseIf AngleY <> AngleY2
		Ordre = 2
	ElseIf AngleZ <> AngleZ2
		Ordre = 3
	EndIf
	AngleX2.d = AngleX
	AngleY2.d = AngleY
	AngleZ2.d = AngleZ
  
  StartDrawing(ScreenOutput())
    DrawingFont(FontID)
    DrawingMode(#PB_2DDrawing_Transparent)
		
    ; On affiche le repère
    ; la ligne représentant l'axe X en vert
    XYFrom3D(@X_Origine, AngleX, AngleY, AngleZ, Ordre, 400, @Coord.Point3DP) ; on calcul les coordonnées de l'extrémité de la ligne pour l'affichage sur l'écran
    LineXY(250, 250, 250 + Coord\x, 250 - Coord\y, RGB(0, 255, 0)) ; on trace une ligne verte à partir du centre de l'image vers les coordonnées calculées
    Circle(250 + Coord\x, 250 - Coord\y, 5 * Coord\p, RGB(0, 255, 0)) ; on trace un cerle sur le bout de la ligne. La variable Coord\p permet de prendre en compte la perspective sur une forme de taille définie, ici un cercle mais également une image par exemple.
    DrawText(255 + Coord\x, 255 - Coord\y, "X", 0) ;On affiche le label de l'axe
    
    ; la ligne représentant l'axe Y en rouge
    XYFrom3D(@Y_Origine, AngleX, AngleY, AngleZ, Ordre, 400, @Coord.Point3DP) ; on calcul les coordonnées de l'extrémité de la ligne pour l'affichage sur l'écran
    LineXY(250, 250, 250 + Coord\x, 250 - Coord\y, RGB(255, 0, 0))
    Circle(250 + Coord\x, 250 - Coord\y, 5 * Coord\p, RGB(255, 0, 0))
    DrawText(255 + Coord\x, 255 - Coord\y, "Y", 0)
    
    ; la ligne représentant l'axe Z en bleu
    XYFrom3D(@Z_Origine, AngleX, AngleY, AngleZ, Ordre, 400, @Coord.Point3DP) ; on calcul les coordonnées de l'extrémité de la ligne pour l'affichage sur l'écran
    LineXY(250, 250, 250 + Coord\x, 250 - Coord\y, RGB(0, 0, 255))
    Circle(250 + Coord\x, 250 - Coord\y, 5 * Coord\p, RGB(0, 0, 255))
    DrawText(255 + Coord\x, 255 - Coord\y, "Z", 0)
    
  StopDrawing()
  
  FlipBuffers()

  Repeat
		Event = WindowEvent()
		
		If Event = #WM_KEYUP
			Select EventwParam()
				Case 'X'
					AngleX + #PI/6
				Case 'Y'
					AngleY + #PI/6
				Case 'Z'
					AngleZ + #PI/6
				Case 13
					Rotation_Auto = 1 - Rotation_Auto
					AngleX = 0
					AngleY = 0
					AngleZ = 0
		EndSelect
		EndIf
		
		If Event = #PB_Event_CloseWindow
			End
		EndIf
		
	Until Event = 0
	
ForEver
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)]
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: 3D vers 2D avec perspective

Message par Ollivier »

Bonjour LSI,

Une rotation sans axe, c'est comme un oiseau sans aile...
Le Soldat Inconnu a écrit :Si tu as une solution pour cela, je suis preneur.
Ce n'est pas ma nature de critiquer sans offrir de solutions. On va dire que la roue tourne! C'est toi maintenant qui va juger si mon petit bout de code est « crédible » ou pas. :wink:

Dans ce code, tu disposes de 12 rotations (rien que ça...) contrôlées par 12 touches. Elles doivent être toutes testées, et bourrinement s'il le faut!

2 touches par rotation (sens positif et sens négatif)
2 types de rotation (absolue et relative)
3 axes par rotations (x, y et z)

2 * 2 * 3 = 12 ; Le compte y est.

Rotations absolues:
Flèche HAUT/Flèche BAS Selon Axe X
Flèche GAUCHE/Flèche DROITE Selon Axe Z
Touche TABULATION/Touche A Selon Axe Y

Rotations relatives:
Pavé numérique TOUCHE 4/TOUCHE 6 Selon Axe i
Pavé numérique TOUCHE 8/TOUCHE 2 Selon Axe j
Pavé numérique TOUCHE 9/TOUCHE 3 Selon Axe k

Parmi ces 12 rotations qui te font tourner le trièdre dans tous les sens possibles et inimaginables, aucune rotation ne s'exécute autrement qu'autour d'un axe bien défini, calculable, clairement affiché à l'écran, et tout, et tout...

Code : Tout sélectionner

;_______________________________________________________
;  Titre : ROTATIONS 3D ABSOLUES ET RELATIVES (PIVOT)
;  Auteur :                                  OLLIVIER
;  Date :                                  08/01/2011
;  Outil numérique utilisé :              MATRICE 2x2
;  Sens de la base :                         INDIRECT
;  Perspective                            ISOMETRIQUE
;  Interface                                  CLAVIER
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
      Structure IJK
            Ix.D: Iy.D: Iz.D
            Jx.D: Jy.D: Jz.D
            Kx.D: Ky.D: Kz.D
      EndStructure

      Base .IJK: Base \Ix = 1. : Base \Jy = 1. : Base \Kz = 1.
      Base0.IJK: Base0\Ix = 1.5: Base0\Jy = 1.5: Base0\Kz = 1.5

      Global.I DskW, DskH, DskD, DskF
      Global.D OnX, OnY

Procedure DrawLine(x.D, y.D, z.D, Name.S, Color.I)
      x1 = DskW / 4
      y1 = DskH / 4
      OnX = x * 100.0
      OnY = y * 100.0
      x2 = x1 + OnX
      y2 = y1 - OnY ; Soustraction dûe à l'opposition du sens de l'axe Y de l'écran par rapport à l'axe Y conventionnel en géométrie
      LineXY(x1, y1, x2, y2, Color)
      DrawText(x2 + 4, y2 + 4, Name, Color, RGB(254, 254, 254) )
      x2 = x1 - OnX
      y2 = y1 + OnY
      LineXY(x1, y1, x2, y2, Color)
EndProcedure

Procedure RotationOrtho(*r.DOUBLE, *i.DOUBLE, w.D)
      Protected.D x, y, Cos, Sin
      x = *r\D
      y = *i\D
      Cos = Cos(w)
      Sin = Sin(w)
      *r\D = x * Cos - y * Sin
      *i\D = y * Cos + x * Sin 
EndProcedure

Macro Rotation(a, b, c)
      RotationOrtho(@Base\I#a, @Base\I#b, c)
      RotationOrtho(@Base\J#a, @Base\J#b, c)
      RotationOrtho(@Base\K#a, @Base\K#b, c)
EndMacro

Macro Pivot(a, b, c)
      Cos = Cos(c)
      Sin = Sin(c)
      x = Base\a#x
      y = Base\a#y
      z = Base\a#z
      Base\a#x = x * Cos - Base\b#x * Sin
      Base\a#y = y * Cos - Base\b#y * Sin
      Base\a#z = z * Cos - Base\b#z * Sin
      Base\b#x = x * Sin + Base\b#x * Cos
      Base\b#y = y * Sin + Base\b#y * Cos
      Base\b#z = z * Sin + Base\b#z * Cos
EndMacro

      Define.D x, y, z, Cos, Sin, v = 0.05
      InitSprite()
      InitSprite3D()
      InitKeyboard()
      ExamineDesktops()
      DskW = DesktopWidth(0)
      DskH = DesktopHeight(0)
      DskD = DesktopDepth(0)
      DskF = DesktopFrequency(0)
      WinN = OpenWindow(#PB_Any, 0, 0, DskW / 2, DskH / 2, "Rotations 3D", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
      OpenWindowedScreen(WindowID(WinN), 0, 0, DskW / 2, DskH / 2, 0, 0, 0)
      KeyboardMode(#PB_Keyboard_International)
      Repeat
            Delay(1)
            ExamineKeyboard()
            If KeyboardPushed(#PB_Key_Up)   : Rotation(y, z, v) : EndIf
            If KeyboardPushed(#PB_Key_Down) : Rotation(y, z, -v): EndIf
            If KeyboardPushed(#PB_Key_Tab)  : Rotation(x, z, v) : EndIf
            If KeyboardPushed(#PB_Key_A)    : Rotation(x, z, -v): EndIf
            If KeyboardPushed(#PB_Key_Left) : Rotation(x, y, v) : EndIf
            If KeyboardPushed(#PB_Key_Right): Rotation(x, y, -v): EndIf
            If KeyboardPushed(#PB_Key_Pad8) : Pivot(J, K, v): EndIf
            If KeyboardPushed(#PB_Key_Pad2) : Pivot(J, K, -v): EndIf
            If KeyboardPushed(#PB_Key_Pad4) : Pivot(I, J, v): EndIf
            If KeyboardPushed(#PB_Key_Pad6) : Pivot(I, J, -v): EndIf
            If KeyboardPushed(#PB_Key_Pad9) : Pivot(K, I, v): EndIf
            If KeyboardPushed(#PB_Key_Pad3) : Pivot(K, I, -v): EndIf
            ClearScreen(RGB(254, 254, 254) )
            StartDrawing(ScreenOutput() )
                  DrawLine(Base0\Ix, Base0\Iy, Base0\Iz, "X", RGB(1, 128, 1) )
                  DrawLine(Base0\Jx, Base0\Jy, Base0\Jz, "Y", RGB(1, 1, 128) )
                  DrawLine(Base0\Kx, Base0\Ky, Base0\Kz, "Z", RGB(128, 1, 1) )
                  DrawLine(Base \Ix, Base \Iy, Base \Iz, "i", RGB(1, 254, 1) )
                  DrawLine(Base \Jx, Base \Jy, Base \Jz, "j", RGB(1, 1, 254) )
                  DrawLine(Base \Kx, Base \Ky, Base \Kz, "k", RGB(254, 1, 1) )
            StopDrawing()
            FlipBuffers()
      Until WindowEvent() = #PB_Event_CloseWindow Or KeyboardPushed(#PB_Key_Escape)
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: 3D vers 2D avec perspective

Message par Le Soldat Inconnu »

en fait, tu utilises 2 repères. un ortho et un orienté. C'est bien vu :)

Question ?
Pour ajouter un point de coordonné x=3, y=2, z=1 et l'afficher, je dois rentrer quelle coordonnée dans ce repère "double" ? (Repère IJK)
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)]
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: 3D vers 2D avec perspective

Message par Ollivier »

Il y a plus ou moins deux sortes de possibilités d'ajouter un point.
La première consiste à créer autant de base que de points.
La seconde consiste à créer des points relatifs à une base.

J'ai déjà posté la première possibilité sur ce forum (« Vol libre dans un champ d'étoiles » dans la section 3D).
Voici donc la seconde possibilité dans le code qui suit.

Code : Tout sélectionner

;_______________________________________________________
;  Titre : ROTATIONS 3D ABSOLUES ET RELATIVES (PIVOT)
;  Auteur :                                  OLLIVIER
;  Date :                                  08/01/2011
;  Outil numérique utilisé :              MATRICE 2x2
;  Sens de la base :                         INDIRECT
;  Perspective                            ISOMETRIQUE
;  Interface                                  CLAVIER
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
;  Ajout d'un nuage de points relatif à IJK (MAJ#1)
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
      Structure IJK
            Ix.D: Iy.D: Iz.D
            Jx.D: Jy.D: Jz.D
            Kx.D: Ky.D: Kz.D
      EndStructure

      Base .IJK: Base \Ix = 1. : Base \Jy = 1. : Base \Kz = 1.
      Base0.IJK: Base0\Ix = 1.5: Base0\Jy = 1.5: Base0\Kz = 1.5

      Global.I DskW, DskH, DskD, DskF
      Global.D OnX, OnY

;{ MAJ#1 }
      #PQty = 1024
      Structure V3
            x.D: y.D: z.D
      EndStructure

      Global Dim Cloud.V3(#PQty)

      For I = 0 To #PQty
            Cloud(I)\x = Random(200) / 200. - 0.5
            Cloud(I)\y = Random(200) / 200. - 0.5
            Cloud(I)\z = Random(200) / 200. - 0.5
      Next

Procedure DrawPoint(x.D, y.D, z.D)
      x1 = DskW / 4
      y1 = DskH / 4
      OnX = x * 100.0
      OnY = y * 100.0
      x2 = x1 + OnX
      y2 = y1 - OnY ; Soustraction dûe à l'opposition du sens de l'axe Y de l'écran par rapport à l'axe Y conventionnel en géométrie
      Circle(x2, y2, 2, RGB(1, 1, 1) )
EndProcedure

Procedure DrawCloud(*Base.IJK)
      Protected.D x, y, z
      For I = 0 To #PQty
            With Cloud(I)
                  x = \x * *Base\Ix + \y * *Base\Jx + \z * *Base\Kx
                  y = \x * *Base\Iy + \y * *Base\Jy + \z * *Base\Ky
                  z = \x * *Base\Iz + \y * *Base\Jz + \z * *Base\Kz
                  DrawPoint(x, y, z)
            EndWith 
      Next
EndProcedure
;}

Procedure DrawLine(x.D, y.D, z.D, Name.S, Color.I)
      x1 = DskW / 4
      y1 = DskH / 4
      OnX = x * 100.0
      OnY = y * 100.0
      x2 = x1 + OnX
      y2 = y1 - OnY ; Soustraction dûe à l'opposition du sens de l'axe Y de l'écran par rapport à l'axe Y conventionnel en géométrie
      LineXY(x1, y1, x2, y2, Color)
      DrawText(x2 + 4, y2 + 4, Name, Color, RGB(254, 254, 254) )
      x2 = x1 - OnX
      y2 = y1 + OnY
      LineXY(x1, y1, x2, y2, Color)
EndProcedure

Procedure RotationOrtho(*r.DOUBLE, *i.DOUBLE, w.D)
      Protected.D x, y, Cos, Sin
      x = *r\D
      y = *i\D
      Cos = Cos(w)
      Sin = Sin(w)
      *r\D = x * Cos - y * Sin
      *i\D = y * Cos + x * Sin 
EndProcedure

Macro Rotation(a, b, c)
      RotationOrtho(@Base\I#a, @Base\I#b, c)
      RotationOrtho(@Base\J#a, @Base\J#b, c)
      RotationOrtho(@Base\K#a, @Base\K#b, c)
EndMacro

Macro Pivot(a, b, c)
      Cos = Cos(c)
      Sin = Sin(c)
      x = Base\a#x
      y = Base\a#y
      z = Base\a#z
      Base\a#x = x * Cos - Base\b#x * Sin
      Base\a#y = y * Cos - Base\b#y * Sin
      Base\a#z = z * Cos - Base\b#z * Sin
      Base\b#x = x * Sin + Base\b#x * Cos
      Base\b#y = y * Sin + Base\b#y * Cos
      Base\b#z = z * Sin + Base\b#z * Cos
EndMacro

      Define.D x, y, z, Cos, Sin, v = 0.05
      InitSprite()
      InitSprite3D()
      InitKeyboard()
      ExamineDesktops()
      DskW = DesktopWidth(0)
      DskH = DesktopHeight(0)
      DskD = DesktopDepth(0)
      DskF = DesktopFrequency(0)
      WinN = OpenWindow(#PB_Any, 0, 0, DskW / 2, DskH / 2, "Rotations 3D", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
      OpenWindowedScreen(WindowID(WinN), 0, 0, DskW / 2, DskH / 2, 0, 0, 0)
      KeyboardMode(#PB_Keyboard_International)
      Repeat
            Delay(1)
            ExamineKeyboard()
            If KeyboardPushed(#PB_Key_Up)   : Rotation(y, z, v) : EndIf
            If KeyboardPushed(#PB_Key_Down) : Rotation(y, z, -v): EndIf
            If KeyboardPushed(#PB_Key_Tab)  : Rotation(x, z, v) : EndIf
            If KeyboardPushed(#PB_Key_A)    : Rotation(x, z, -v): EndIf
            If KeyboardPushed(#PB_Key_Left) : Rotation(x, y, v) : EndIf
            If KeyboardPushed(#PB_Key_Right): Rotation(x, y, -v): EndIf
            If KeyboardPushed(#PB_Key_Pad8) : Pivot(J, K, v): EndIf
            If KeyboardPushed(#PB_Key_Pad2) : Pivot(J, K, -v): EndIf
            If KeyboardPushed(#PB_Key_Pad4) : Pivot(I, J, v): EndIf
            If KeyboardPushed(#PB_Key_Pad6) : Pivot(I, J, -v): EndIf
            If KeyboardPushed(#PB_Key_Pad9) : Pivot(K, I, v): EndIf
            If KeyboardPushed(#PB_Key_Pad3) : Pivot(K, I, -v): EndIf
            ClearScreen(RGB(254, 254, 254) )
            StartDrawing(ScreenOutput() )
                  DrawLine(Base0\Ix, Base0\Iy, Base0\Iz, "X", RGB(1, 128, 1) )
                  DrawLine(Base0\Jx, Base0\Jy, Base0\Jz, "Y", RGB(1, 1, 128) )
                  DrawLine(Base0\Kx, Base0\Ky, Base0\Kz, "Z", RGB(128, 1, 1) )
                  DrawLine(Base \Ix, Base \Iy, Base \Iz, "i", RGB(1, 254, 1) )
                  DrawLine(Base \Jx, Base \Jy, Base \Jz, "j", RGB(1, 1, 254) )
                  DrawLine(Base \Kx, Base \Ky, Base \Kz, "k", RGB(254, 1, 1) )
                  DrawCloud(Base) ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< MAJ#1
            StopDrawing()
            FlipBuffers()
      Until WindowEvent() = #PB_Event_CloseWindow Or KeyboardPushed(#PB_Key_Escape)
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Re: 3D vers 2D avec perspective

Message par Le Soldat Inconnu »

Ah oui, super simple, je n'avais pas pris le problème dans le bon sens :)
Merci
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)]
Warkering
Messages : 808
Inscription : ven. 08/janv./2010 1:14
Localisation : Québec, Canada

Re: 3D vers 2D avec perspective

Message par Warkering »

Dans ton entête, tu dis utiliser une matrice. Elle est où dans le code? C'est la structure? Car je ne connais pas de façon réservée d'en faire en PB.
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: 3D vers 2D avec perspective

Message par Ollivier »

Bonjour Warkering,

J'ai isolé toutes les opérations sur les matrices 2x2 dans la macro Rotation() avec des commentaires lignes 39 et 40 pour imaginer comment chacune de ces matrices se compose. Du point de vue de l'utilisateur, il y a 6 utilisations de la macro donc 6 matrices 2x2. Mais l'interface clavier étant, le sens de rotation de chacune d'entre elle est propre à la touche concernée. Donc, du point de vue du programmeur, il y a 12 utilisations, donc 12 matrices 2x2.

Code : Tout sélectionner

;_______________________________________________________
;  Titre : ROTATIONS 3D ABSOLUES ET RELATIVES (PIVOT)
;  Auteur :                                  OLLIVIER
;  Date :                                  08/01/2011
;  Outil numérique utilisé :              MATRICE 2x2
;  Sens de la base :                         INDIRECT
;  Perspective                            ISOMETRIQUE
;  Interface                                  CLAVIER
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
      Structure IJK
            Ix.D: Iy.D: Iz.D
            Jx.D: Jy.D: Jz.D
            Kx.D: Ky.D: Kz.D
      EndStructure

      Base .IJK: Base \Ix = 1. : Base \Jy = 1. : Base \Kz = 1.
      Base0.IJK: Base0\Ix = 1.5: Base0\Jy = 1.5: Base0\Kz = 1.5

      Global.I DskW, DskH, DskD, DskF, AffW, AffH
      Global.D OnX, OnY

Procedure DrawLine(x.D, y.D, z.D, Name.S, Color.I)
      x1 = AffW / 2
      y1 = AffH / 2
      OnX = x * 100.0
      OnY = y * 100.0
      x2 = x1 + OnX
      y2 = y1 - OnY ; Soustraction dûe à l'opposition du sens de l'axe Y de l'écran par rapport à l'axe Y conventionnel en géométrie
      LineXY(x1, y1, x2, y2, Color)
      DrawText(x2 + 4, y2 + 4, Name, Color, RGB(254, 254, 254) )
      x2 = x1 - OnX
      y2 = y1 + OnY
      LineXY(x1, y1, x2, y2, Color)
EndProcedure

Macro Rotation(a, b, Cos, Sin)
      x = a
      y = b
      a = x * Cos - y * Sin ; Matrice 2x2 : | a    Cos |
      b = x * Sin + y * Cos ;               | b   -Sin |
EndMacro

Macro RotationAbsolue(a, b, c)
      Cos = Cos(c)
      Sin = Sin(c)
      Rotation(Base\I#a, Base\I#b, Cos, Sin)
      Rotation(Base\J#a, Base\J#b, Cos, Sin)
      Rotation(Base\K#a, Base\K#b, Cos, Sin)
EndMacro

Macro RotationRelative(a, b, c)
      Cos = Cos(c)
      Sin = Sin(c)
      Rotation(Base\a#x, Base\b#x, Cos, Sin)
      Rotation(Base\a#y, Base\b#y, Cos, Sin)
      Rotation(Base\a#z, Base\b#z, Cos, Sin)
EndMacro

      Define.D x, y, z, Cos, Sin, v = 0.05
      InitSprite()
      InitSprite3D()
      InitKeyboard()
      ExamineDesktops()
      DskW = DesktopWidth(0)
      DskH = DesktopHeight(0)
      DskD = DesktopDepth(0)
      DskF = DesktopFrequency(0)
      AffW = DskW / 4 * 3
      AffH = DskH / 4 * 3
      WinN = OpenWindow(#PB_Any, 0, 0, AffW, AffH, "Rotations 3D", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
      OpenWindowedScreen(WindowID(WinN), 0, 0, AffW, AffH, 0, 0, 0)
      KeyboardMode(#PB_Keyboard_International)
      Repeat
            Delay(1)
            ExamineKeyboard()
            If KeyboardPushed(#PB_Key_Up)   : RotationAbsolue(y, z, v) : EndIf
            If KeyboardPushed(#PB_Key_Down) : RotationAbsolue(y, z, -v): EndIf
            If KeyboardPushed(#PB_Key_Tab)  : RotationAbsolue(x, z, v) : EndIf
            If KeyboardPushed(#PB_Key_A)    : RotationAbsolue(x, z, -v): EndIf
            If KeyboardPushed(#PB_Key_Left) : RotationAbsolue(x, y, v) : EndIf
            If KeyboardPushed(#PB_Key_Right): RotationAbsolue(x, y, -v): EndIf
            If KeyboardPushed(#PB_Key_Pad8) : RotationRelative(J, K, v): EndIf
            If KeyboardPushed(#PB_Key_Pad2) : RotationRelative(J, K, -v): EndIf
            If KeyboardPushed(#PB_Key_Pad4) : RotationRelative(I, J, v): EndIf
            If KeyboardPushed(#PB_Key_Pad6) : RotationRelative(I, J, -v): EndIf
            If KeyboardPushed(#PB_Key_Pad9) : RotationRelative(K, I, v): EndIf
            If KeyboardPushed(#PB_Key_Pad3) : RotationRelative(K, I, -v): EndIf
            ClearScreen(RGB(254, 254, 254) )
            StartDrawing(ScreenOutput() )
                  DrawLine(Base0\Ix, Base0\Iy, Base0\Iz, "X", RGB(1, 128, 1) )
                  DrawLine(Base0\Jx, Base0\Jy, Base0\Jz, "Y", RGB(1, 1, 128) )
                  DrawLine(Base0\Kx, Base0\Ky, Base0\Kz, "Z", RGB(128, 1, 1) )
                  DrawLine(Base \Ix, Base \Iy, Base \Iz, "i", RGB(1, 254, 1) )
                  DrawLine(Base \Jx, Base \Jy, Base \Jz, "j", RGB(1, 1, 254) )
                  DrawLine(Base \Kx, Base \Ky, Base \Kz, "k", RGB(254, 1, 1) )
            StopDrawing()
            FlipBuffers()
      Until WindowEvent() = #PB_Event_CloseWindow Or KeyboardPushed(#PB_Key_Escape)
Avatar de l’utilisateur
kernadec
Messages : 1606
Inscription : ven. 25/avr./2008 11:14

Re: 3D vers 2D avec perspective

Message par kernadec »

bonjour
Merci LSI et pour Ollivier de sa lumière.

Au début de notre ère l'olivier servait à produire l'huile des lampes
c'est pour cela que le rameau d'olivier représente symboliquement la lumière.
Quand Noé voit la colombe blanche revenir avec un rameau d'olivier,
il reçoit le signe qu'il a atteint la Lumière Divine.
il faut aussi remarquer qu'Ollivier porte deux ailes :wink: ce qui donne pour titre " Vol libre dans un champ d'étoiles "
Cordialement
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Re: 3D vers 2D avec perspective

Message par Backup »

kernadec a écrit : il faut aussi remarquer qu'Ollivier porte deux ailes :wink: ce qui donne pour titre " Vol libre dans un champ d'étoiles "
Cordialement
tiens "qu'Ollivier" contient aussi 2 L O Q hum !! :lol: ; désolé, la perche etait tendue.. :lol:
Répondre