Un petit code d'animation 3D, je dessine un texte qui tourne avec des points de couleur
Code : Tout sélectionner
#Pi = 3.14159274
#ImageFondX = 500
#ImageFondY = 200
#ImageTexteX = 500
#ImageTexteY = 70
#DepartZ = 0
#Espacement = 10
#Duree = 100
#AngleDepartX.f = #Pi / 2
#AngleDepartY.f = #Pi
#AngleDepartZ.f = 0 ; #Pi / 2
Structure Point3D
x.f
y.f
z.f
EndStructure
Global Coord.Point3D
Structure TInfo
Couleur.l
z.l
EndStructure
Dim Texte.TInfo(#ImageTexteX, #ImageTexteY)
Procedure XYFrom3D(x.f, y.f, z.f, ax.f, ay.f, az.f)
; x, y, z : position de l'objet
; ax, ay, az : angle de rotation du point sur l'axe x, y et z, pour avoir un repère 3D décalé par rapport au repère de l'écran
Protected x2.f, y2.f, z3.f
; Rotation sur l'axe Z
x2 = x * Cos(az) - y * Sin(az)
y2 = x * Sin(az) + y * Cos(az)
; z2 = z
; Debug StrF(x2) + " , " + StrF(y2) + " , " + StrF(z)
; Rotation sur l'axe X
; x3 = x2
Coord\y = y2 * Cos(ax) - z * Sin(ax)
z3 = y2 * Sin(ax) + z * Cos(ax)
; Debug StrF(x2) + " , " + StrF(Coord\y) + " , " + StrF(z3)
; Rotation sur l'axe Y
Coord\z = z3 * Cos(ay) - x3 * Sin(ay)
Coord\x = z3 * Sin(ay) + x2 * Cos(ay)
; y4 = y3
; Debug StrF(Coord\x) + " , " + StrF(Coord\y) + " , " + StrF(z3)
EndProcedure
If InitSprite() = 0
End
EndIf
If OpenWindow(0, 0, 0, #ImageFondX, #ImageFondY, #PB_Window_BorderLess | #PB_Window_ScreenCentered, "Le Soldat Inconnu") = 0
End
EndIf
If OpenWindowedScreen(WindowID(), 0, 0, #ImageFondX, #ImageFondY, 1, 0, 0) = 0
End
EndIf
UsePNGImageDecoder()
LoadSprite(0, "Fond.png")
DisplaySprite(0, 0, 0)
FlipBuffers()
LoadSprite(1, "Texte.png")
StartDrawing(SpriteOutput(1))
For n = 0 To #ImageTexteX - 1
For nn = 0 To #ImageTexteY - 1
Texte(n, nn)\Couleur = Point(n, nn) ; On charge la couleur de l'image dans un tableau
Texte(n, nn)\z = #DepartZ + Random(#Espacement) - #Espacement / 2 ; on crée une position en z aléatoire
Next
Next
StopDrawing()
AngleX.f = #AngleDepartX
AngleY.f = #AngleDepartY
AngleZ.f = #AngleDepartZ
Duree = 0
Repeat
DisplaySprite(0, 0, 0)
; 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)
Duree + 1
AngleX - #AngleDepartX / #Duree
AngleY - #AngleDepartY / #Duree
AngleZ - #AngleDepartZ / #Duree
; On affiche les points
StartDrawing(ScreenOutput())
For n = 0 To #ImageTexteX - 1
For nn = 0 To #ImageTexteY - 1
XYFrom3D(n - #ImageTexteX / 2, nn - #ImageTexteY / 2, Texte(n, nn)\z, AngleX, AngleY, AngleZ) ; Calcul de la position des points du texte sur le repère de l'écran
If Coord\x + #ImageTexteX / 2 >= 0 And Coord\x + #ImageTexteX / 2 < #ImageFondX And Coord\y + #ImageTexteY / 2 >= 0 And Coord\y + #ImageTexteY / 2 < #ImageFondY And Texte(n, nn)\Couleur <> $3C0000 ; si le point est sur la zone de dessin et si la couleur est différente de la couleur de fond de l'image représentant le texte
Plot(Coord\x + #ImageTexteX / 2, Coord\y + #ImageTexteY / 2, Texte(n, nn)\Couleur) ; on affiche le point
EndIf
Next
Next
StopDrawing()
FlipBuffers()
Until Duree = #Duree
Delay(3000)
http://perso.wanadoo.fr/lesoldatinconnu ... etoile.zip (138 ko)
la partie du code intéressante est celle-ci
Code : Tout sélectionner
Structure Point3D
x.f
y.f
z.f
EndStructure
Global Coord.Point3D
Procedure XYFrom3D(x.f, y.f, z.f, ax.f, ay.f, az.f)
; x, y, z : position de l'objet
; ax, ay, az : angle de rotation du point sur l'axe x, y et z, pour avoir un repère 3D décalé par rapport au repère de l'écran
Protected x2.f, y2.f, z3.f
; Rotation sur l'axe Z
x2 = x * Cos(az) - y * Sin(az)
y2 = x * Sin(az) + y * Cos(az)
; z2 = z
; Debug StrF(x2) + " , " + StrF(y2) + " , " + StrF(z)
; Rotation sur l'axe X
; x3 = x2
Coord\y = y2 * Cos(ax) - z * Sin(ax)
z3 = y2 * Sin(ax) + z * Cos(ax)
; Debug StrF(x2) + " , " + StrF(Coord\y) + " , " + StrF(z3)
; Rotation sur l'axe Y
Coord\z = z3 * Cos(ay) - x3 * Sin(ay)
Coord\x = z3 * Sin(ay) + x2 * Cos(ay)
; y4 = y3
; Debug StrF(Coord\x) + " , " + StrF(Coord\y) + " , " + StrF(z3)
EndProcedure
donc si les coordonnée d'un point sont x, y, z
que le repère dans lequel vous l'affiché en orienté d'un angle de #Pi/4 radians sur l'axe des x par exemple, on obtient les coordonnées du point sur l'écran comme suit :
Code : Tout sélectionner
XYFrom3D(x, y, z, #Pi/2, 0, 0)
donc pour faire tourner un sprite dans l'espace, il suffit de jouer sur les angles entre le repère 3D et celui de l'écran.
pour afficher les repères des 2 plans (écran et 3D) et bien comprendre le phénomène, lancer le code suivant :
Code : Tout sélectionner
Structure Point3D
x.f
y.f
z.f
EndStructure
Global Coord.Point3D
Procedure XYFrom3D(x.f, y.f, z.f, ax.f, ay.f, az.f)
; x, y, z : position de l'objet
; ax, ay, az : angle de rotation du point sur l'axe x, y et z, pour avoir un repère 3D décalé par rapport au repère de l'écran
Protected x2.f, y2.f, z3.f
; Rotation sur l'axe Z
x2 = x * Cos(az) - y * Sin(az)
y2 = x * Sin(az) + y * Cos(az)
; z2 = z
; Debug StrF(x2) + " , " + StrF(y2) + " , " + StrF(z)
; Rotation sur l'axe X
; x3 = x2
Coord\y = y2 * Cos(ax) - z * Sin(ax)
z3 = y2 * Sin(ax) + z * Cos(ax)
; Debug StrF(x2) + " , " + StrF(Coord\y) + " , " + StrF(z3)
; Rotation sur l'axe Y
Coord\z = z3 * Cos(ay) - x3 * Sin(ay)
Coord\x = z3 * Sin(ay) + x2 * Cos(ay)
; y4 = y3
; Debug StrF(Coord\x) + " , " + StrF(Coord\y) + " , " + StrF(z3)
EndProcedure
If InitSprite() = 0 Or InitKeyboard() = 0
End
EndIf
If OpenWindow(0, 0, 0, 500, 500, #PB_Window_BorderLess | #PB_Window_ScreenCentered, "Le Soldat Inconnu") = 0
End
EndIf
If OpenWindowedScreen(WindowID(), 0, 0, 500, 500, 1, 0, 0) = 0
End
EndIf
AngleX.f = 0
AngleY.f = 0
AngleZ.f = 0
FontID = LoadFont(0, "tahoma", 8, #PB_Font_HighQuality)
Repeat
ClearScreen(255, 255, 255)
; 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
AngleX + 0.01
AngleY + 0.005
AngleZ + 0.02
StartDrawing(ScreenOutput())
DrawingFont(FontID)
; On affiche le repère
; la ligne représentant l'axe X en vert
XYFrom3D(200, 0, 0, AngleX, AngleY, AngleZ) ; on calcul les coordonnées de l'extrémité de la ligne pour l'affichage sur l'écran
Line(250, 250, Coord\x, 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, RGB(0, 255, 0)) ; on trace un cerle sur le bout de la ligne
Locate(255 + Coord\x, 255 + Coord\y)
DrawText("X") ;On affiche le label de l'axe
; la ligne représentant l'axe Y en rouge
XYFrom3D(0, 200, 0, AngleX, AngleY, AngleZ) ; on calcul les coordonnées de l'extrémité de la ligne pour l'affichage sur l'écran
Line(250, 250, Coord\x, Coord\y, RGB(255, 0, 0))
Circle(250 + Coord\x, 250 + Coord\y, 5, RGB(255, 0, 0))
Locate(255 + Coord\x, 255 + Coord\y)
DrawText("Y")
; la ligne représentant l'axe Z en bleu
XYFrom3D(0, 0, 200, AngleX, AngleY, AngleZ) ; on calcul les coordonnées de l'extrémité de la ligne pour l'affichage sur l'écran
Line(250, 250, Coord\x, Coord\y, RGB(0, 0, 255))
Circle(250 + Coord\x, 250 + Coord\y, 5, RGB(0, 0, 255))
Locate(255 + Coord\x, 255 + Coord\y)
DrawText("Z")
StopDrawing()
FlipBuffers()
ExamineKeyboard()
Until KeyboardPushed(#PB_Key_Escape)
et si vous souhaiter avoir des objets en mouvement, il suffit de modifier les coordonnées de ces points ou sprites pendant la rotation du repère 3D comme si vous étiez en 2D, la procedure de calcul pour passer d'un plan à l'autre fera le reste
