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.
* 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