Je tiens à vous remercier pour vos avis encourageants, que ce soit Flaith (très imaginatif, bonjour au passage, car on cause rarement), Djes (désolé pour le Purepunch...), Cpl.Bator, Venom, Mdsv(les délais ne sont pas retardés) et Ar-S.
@Cpl.Bator
En étant sérieux deux minutes, tu as entièrement raison: la perspective est archi-non réaliste. Mais ce que je souhaite c'est partager mon point de vue 3D. Et même si je semble m'étioler sur des jolies âneries, je suis un protocole strict d'explicatifs.
Si on apprends dans le désordre, on oublie facilement ou c'est agaçant, etc... Là, le 1er code évoque les 3 rotations orthonormales dans l'espace. C'est court et les calculs maths sont directs. Ensuite, une fois que les 3 rotations Oxyz sont comprises avec des calculs "humains" (la macro Ro() ), on peut passer à l'utilisation des "matrices spatiales" et puis au changement de référentiel. Je n'ai pas encore le code correct aussi impeccable que le premier, mais j'ai son tutoriel inachevé. Comme je vais lâcher un peu le language quelques jours, je poste de suite ce code-tuto, même s'il est à l'arrache et qu'il "casse" un peu le côté ludique du sujet.
Toutes les commandes de rotations (les 6 touches tab+A+4flèches) restent exactement les mêmes. Il n'y a plus de vitesse. Il n'y a que le changement d'échelle de référence [Entrée] et [Backspace]. En rouge, c'est tout ce qui se rapporte au décor (comme les étoiles, etc...) et en bleu, c'est tout ce qui se rapport à la caméra (qui symbolise n'importe quel objet 3D à venir).
La routine importante c'est la procédure Tr() qui décompose de manière ordonnée le mélange de 3 angles (d'où la possibilité ensuite de gérer correctement la perspective avec cette routine).
Vous noterez que l'objet bleu (considérée comme étant la caméra) ne subit ainsi aucun blocage de cardan.
Code : Tout sélectionner
;{ /!\ }
;{ Directives du compilateur }
DisableDebugger
;}
;{ Structures }
;{ Ecran }
Structure DeskInfo
Width.I
Height.I
Depth.I
EndStructure
;}
;{ 3D }
Structure V3
X.F
Y.F
Z.F
EndStructure
Structure RefInfo
O.V3
X.V3
Y.V3
Z.V3
EndStructure
;}
;}
;{ Variables globales }
Global Desk.DeskInfo
;}
;{ Procédures }
Procedure InitScreen()
InitSprite()
InitSprite3D()
InitKeyboard()
InitMouse()
ExamineDesktops()
Desk\Width = DesktopWidth(0)
Desk\Height = DesktopHeight(0)
Desk\Depth = DesktopDepth(0)
OpenScreen(Desk\Width, Desk\Height, Desk\Depth, "")
EndProcedure
Procedure.F Dist(X.F, Y.F, Z.F = 0.0)
Protected Result.F
Result = Sqr(X * X + Y * Y + Z * Z)
ProcedureReturn Result
EndProcedure
Procedure Poke(*Adr, Length.I, Char.I)
Protected I.I
For I = 0 To Length - 1
PokeB(*Adr + I, Char)
Next
EndProcedure
;}
;{ Reste-à-choux }
Structure AB
A.I
B.I
EndStructure
Structure Zone
Dep.I
Fin.I
EndStructure
Nb = 4999
Global Option.I
Global Dim V.V3(Nb)
Global.F H, R, A
Global Dim Fil.AB(99)
Global Dim Corps.Zone(9)
Macro Local(Co)
Co = Co#(i)
EndMacro
Macro Ro(CoA, CoB, CoC): Procedure R#CoA(i, Angle.F)
Protected.F X, Y, Z
X = V(i)\X
Y = V(i)\Y
Z = V(i)\Z
H = CoA
R = Sqr((CoB * CoB) + (CoC * CoC) )
If R > 0.0
A = ACos(CoC / R): If CoB < 0.0: A = 0.0 - A: EndIf
Else
A = 0.0
EndIf
V(i)\CoA = H
V(i)\CoB = Sin(A + Angle) * R
V(i)\CoC = Cos(A + Angle) * R
EndProcedure: EndMacro
Macro For2Nb(SubMacro)
For I = 0 To Nb
SubMacro
Next
EndMacro
Ro(x,y,z):Ro(y,z,x):Ro(z,x,y)
Procedure RefReset(*Adr)
Poke(*Adr, 48, 0)
PokeF(*Adr + 12, 1.0)
PokeF(*Adr + 28, 1.0)
PokeF(*Adr + 44, 1.0)
EndProcedure
Procedure Tr(AA, B)
;Protected.F X, Y, Z
Protected Sauvegarde.RefInfo
RefReset(@V(B)\X)
CopyMemory(@V(AA)\X, @Sauvegarde, SizeOf(RefInfo) )
; On couche l'axe X sur le plan XZ par rotation sur l'axe Z
AngleZ.F = ACos(V(AA + 1)\X / Dist(V(AA + 1)\X, V(AA + 1)\Y) )
If V(AA + 1)\Y < 0.0
AngleZ = 0.0 - AngleZ
EndIf
For I = 0 To 7
Rz(I, AngleZ)
Next I
; On couche l'axe X sur le plan YZ par rotation sur l'axe Y
AngleY.F = ACos(V(AA + 1)\X / Dist(V(AA + 1)\X, V(AA + 1)\Z) )
If V(AA + 1)\Z > 0.0
AngleY = 0.0 - AngleY
EndIf
For I = 0 To 7
Ry(I, AngleY)
Next I
; On couche l'axe Y sur le plan XY par rotation sur l'axe X
AngleX.F = ACos(V(AA + 2)\Z / Dist(V(AA + 2)\Y, V(AA + 2)\Z) )
If V(AA + 2)\Y < 0.0
AngleX = 0.0 - AngleX
EndIf
AngleX = #PI / 2.0 - AngleX
For I = 0 To 7
Rx(I, AngleX)
Next I
CopyMemory(@Sauvegarde, @V(AA)\X, SizeOf(RefInfo) )
EndProcedure
Macro AffFil(Cor, Coul, CXR, CYR)
For J = Corps(Cor)\Dep To Corps(Cor)\Fin
I = Fil(J)\A
ZCoef.F = 10.0 / Sqr(110.0 + V(I)\Z * 100.0)
X1.F = CXR + V(I)\X * 100.0 * ZCoef
Y1.F = CYR - V(I)\Y * 100.0 * ZCoef
I = Fil(J)\B
ZCoef.F = 10.0 / Sqr(110.0 + V(I)\Z * 100.0)
X2.F = CXR + V(I)\X * 100.0 * ZCoef
Y2.F = CYR - V(I)\Y * 100.0 * ZCoef
LineXY(X1, Y1, X2, Y2, Coul)
;DrawingMode(#PB_2DDrawing_Transparent)
X3.F = CXR + V(I)\X * 100.0 * ZCoef * 1.1
Y3.F = CYR - V(I)\Y * 100.0 * ZCoef * 1.1
If Option & (1 << (J - Corps(Cor)\Dep) )
Fond = RGB(255, 255, 255)
Else
Fond = 0
EndIf
DrawText(X3 - 8, Y3 - 8, Chr(Asc("X") + (J - Corps(Cor)\Dep) ), Coul, Fond)
Next
EndMacro
InitScreen()
CX0.F = Desk\Width / 2.0
CY0.F = Desk\Height / 2.0
CX1.F = Desk\Width / 3.0
CY1.F = Desk\Height / 3.0
CX2.F = 2 * Desk\Width / 3.0
CY2.F = 2 * Desk\Height / 3.0
CX3.F = Desk\Width / 4.0
CY3.F = Desk\Height / 4.0
Count.I = Pow(Nb, 1.0 / 3.0) - 2
Stepp.F = 120 / Count
XX.F = 0
L = 0
For I = 0 To Count
YY.F = 0
For J = 0 To Count
ZZ.F = 0
For K = 0 To Count
V(L)\X = (XX - 60.0)
V(L)\Y = (YY - 60.0)
V(L)\Z = (ZZ - 60.0)
L + 1
ZZ + Stepp
Next
YY + Stepp
Next
XX + Stepp
Next
RefReset(@V(0)\X)
Fil(0)\A = 0
Fil(0)\B = 1
Fil(1)\A = 0
Fil(1)\B = 2
Fil(2)\A = 0
Fil(2)\B = 3
RefReset(@V(4)\X)
Fil(3)\A = 4
Fil(3)\B = 5
Fil(4)\A = 4
Fil(4)\B = 6
Fil(5)\A = 4
Fil(5)\B = 7
RefReset(@V(8)\X)
Fil(6)\A = 8
Fil(6)\B = 9
Fil(7)\A = 8
Fil(7)\B = 10
Fil(8)\A = 8
Fil(8)\B = 11
Corps(0)\Dep = 0
Corps(0)\Fin = 2
Corps(1)\Dep = 3
Corps(1)\Fin = 5
Corps(3)\Dep = 6
Corps(3)\Fin = 8
Corps(2)\Dep = 12
Corps(2)\Fin = Nb
RSpeed.F = 0.04
KeyboardMode(#PB_Keyboard_International)
If CreateSprite(0, 16, 16)
StartDrawing(SpriteOutput(0) )
Box(0, 0, 16, 16, RGB(255, 255, 255) )
StopDrawing()
Else
End
EndIf
e.F = 1.0
Repeat
Delay(1)
ExamineKeyboard()
ClearScreen(0)
StartDrawing(ScreenOutput() )
Corps = 2
CorpsRef = 1
Ref = 4
RXX.F = V(Ref + 1)\X
RXY.F = V(Ref + 2)\X
RXZ.F = V(Ref + 3)\X
RYX.F = V(Ref + 1)\Y
RYY.F = V(Ref + 2)\Y
RYZ.F = V(Ref + 3)\Y
RZX.F = V(Ref + 1)\Z
RZY.F = V(Ref + 2)\Z
RZZ.F = V(Ref + 3)\Z
For I = Corps(Corps)\Dep To Corps(Corps)\Fin
u.F = V(I)\X
v.F = V(I)\Y
w.F = V(I)\Z
VX.F = (u * RXX + v * RXY + w * RXZ) * e
VY.F = (u * RYX + v * RYY + w * RYZ) * e
VZ.F = (u * RZX + v * RZY + w * RZZ) * e
ZCoef.F = 300.0 / (300.0 + VZ)
X.F = CX2 + VX * ZCoef
Y.F = CY0 - VY * ZCoef
Box(X, Y, 1, 1, RGB(0, 0, 255) )
Next
Ref = 0
RXX.F = V(Ref + 1)\X
RXY.F = V(Ref + 2)\X
RXZ.F = V(Ref + 3)\X
RYX.F = V(Ref + 1)\Y
RYY.F = V(Ref + 2)\Y
RYZ.F = V(Ref + 3)\Y
RZX.F = V(Ref + 1)\Z
RZY.F = V(Ref + 2)\Z
RZZ.F = V(Ref + 3)\Z
For I = Corps(Corps)\Dep To Corps(Corps)\Fin
u.F = V(I)\X
v.F = V(I)\Y
w.F = V(I)\Z
VX.F = (u * RXX + v * RXY + w * RXZ) * (4.0 - e)
VY.F = (u * RYX + v * RYY + w * RYZ) * (4.0 - e)
VZ.F = (u * RZX + v * RZY + w * RZZ) * (4.0 - e)
ZCoef.F = 300.0 / (300.0 + VZ)
X.F = CX3 + VX * ZCoef
Y.F = CY0 - VY * ZCoef
Box(X, Y, 1, 1, RGB(255, 0, 0) )
Next
;DisplaySprite(0, 0, 0)
Option = 0: AffFil(0, RGB(255, 0, 0), CX3, CY0)
Option = Modif: AffFil(3, RGB(0, 0, 255), CX3, CY0)
Option = Modif: AffFil(1, RGB(0, 0, 255), CX2, CY0)
Option = 0: AffFil(3, RGB(255, 0, 0), CX2, CY0)
Dep = 1
Fin = 3
Modif = 0
If KeyboardPushed(#PB_Key_Return)
If e < 3.5
e + 0.1
EndIf
EndIf
If KeyboardPushed(#PB_Key_Back)
If e > 0.5
e - 0.1
EndIf
EndIf
If KeyboardPushed(#PB_Key_Up)
Modif | 1
For I = Dep To Fin
Rx(I, RSpeed)
Next
EndIf
If KeyboardPushed(#PB_Key_Down)
Modif | 1
For I = Dep To Fin
Rx(I, -RSpeed)
Next
EndIf
If KeyboardPushed(#PB_Key_Left)
Modif | 4
For I = Dep To Fin
Rz(I, RSpeed)
Next
EndIf
If KeyboardPushed(#PB_Key_Right)
Modif | 4
For I = Dep To Fin
Rz(I, -RSpeed)
Next
EndIf
If KeyboardPushed(#PB_Key_Tab)
Modif | 2
For I = Dep To Fin
Ry(I, RSpeed)
Next
EndIf
If KeyboardPushed(#PB_Key_A)
Modif | 2
For I = Dep To Fin
Ry(I, -RSpeed)
Next
EndIf
Tr(0, 4)
DrawText(0, 0, "ROTATIONS : X = Haut/Bas Y = Tab/A Z = Gauche/Droite REFERENTIEL : Entrée/Backspace")
StopDrawing()
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)
;}
;}