

Cordialement
Code : Tout sélectionner
; Auteur : Le Soldat Inconnu
; Version de PB : 4.5
; Explication du programme :
; Exemple qui montre comment dessiner un repère IJK en 3D dans le XYZ (l'écran)
; Repère XYZ (l'écran)
; X : Ligne horizontal, sens + vers la droite
; Y : Ligne vertical, sens + vers le haut
; Z : Perpendiculaire à la surface de l'écran, sens + vers soi
; Repère IJK
; Votre objet 3D est représenté avec des coordonnées dans le repère IJK qui ensuite affiché dans le repère XYZ (l'écran) en fonction des angles de rotation entre le repère IJK et le repère XYZ
; Angle
; En radian, le sens de rotation est le sens trigonométrique (une rotation d'un angle positif fait tourner l'objet dans le sens trigonométrique, quand vous avez l'axe qui vient vers votre regard (sens + vers vous))
; Touche d'utilisation :
; Enter : Retour à l'origine (Initialise le repère IJK sur le repère XYZ)
; P : Mode perspective
; X : Change l'angle sur l'axe X
; Y : Change l'angle sur l'axe Y
; Z : Change l'angle sur l'axe Z
; I : Change l'angle sur l'axe I
; J : Change l'angle sur l'axe J
; K : Change l'angle sur l'axe K
#Optimisation = 1
Structure Repere3D
ix.d
iy.d
iz.d
jx.d
jy.d
jz.d
kx.d
ky.d
kz.d
EndStructure
Global Repere.Repere3D
Structure Point3D
x.d
y.d
z.d
EndStructure
Structure Point3DP
x.d
y.d
z.d
p.d
EndStructure
CompilerIf #Optimisation
#Angle_Resolution = 500
Global Dim PreCalcul_Cos.d(360 * #Angle_Resolution * 2)
Global Dim PreCalcul_Sin.d(360 * #Angle_Resolution * 2)
For I = -360 * #Angle_Resolution To 360 * #Angle_Resolution
PreCalcul_Cos(I + 360 * #Angle_Resolution) = Cos(I * #PI / (180 * #Angle_Resolution))
PreCalcul_Sin(I + 360 * #Angle_Resolution) = Sin(I * #PI / (180 * #Angle_Resolution))
Next
CompilerEndIf
Procedure Rotation_Origine(*Repere.Repere3D)
Repere\ix = 1
Repere\iy = 0
Repere\iz = 0
Repere\jx = 0
Repere\jy = 1
Repere\jz = 0
Repere\kx = 0
Repere\ky = 0
Repere\kz = 1
EndProcedure
Macro Rotation_Axe_Angle()
CompilerIf #Optimisation
Protected a.i
a = Angle * #Angle_Resolution * 180 / #PI + 360 * #Angle_Resolution
Cos = PreCalcul_Cos(a)
Sin = PreCalcul_Sin(a)
CompilerElse
Cos = Cos(Angle)
Sin = Sin(Angle)
CompilerEndIf
EndMacro
Macro Rotation_Axe_Calcul(Axe1, Axe2, Cos, Sin)
x = Axe1
Axe1 = x * Cos - Axe2 * Sin
Axe2 = Axe2 * Cos + x * Sin
EndMacro
Procedure Rotation_Axe_X(*Repere.Repere3D, Angle.d)
Protected Cos.d, Sin.d, x.d
Rotation_Axe_Angle()
Rotation_Axe_Calcul(*Repere\iy, *Repere\iz, Cos, Sin)
Rotation_Axe_Calcul(*Repere\jy, *Repere\jz, Cos, Sin)
Rotation_Axe_Calcul(*Repere\ky, *Repere\kz, Cos, Sin)
EndProcedure
Procedure Rotation_Axe_Y(*Repere.Repere3D, Angle.d)
Protected Cos.d, Sin.d, x.d
Rotation_Axe_Angle()
Rotation_Axe_Calcul(*Repere\iz, *Repere\ix, Cos, Sin)
Rotation_Axe_Calcul(*Repere\jz, *Repere\jx, Cos, Sin)
Rotation_Axe_Calcul(*Repere\kz, *Repere\kx, Cos, Sin)
EndProcedure
Procedure Rotation_Axe_Z(*Repere.Repere3D, Angle.d)
Protected Cos.d, Sin.d, x.d
Rotation_Axe_Angle()
Rotation_Axe_Calcul(*Repere\ix, *Repere\iy, Cos, Sin)
Rotation_Axe_Calcul(*Repere\jx, *Repere\jy, Cos, Sin)
Rotation_Axe_Calcul(*Repere\kx, *Repere\ky, Cos, Sin)
EndProcedure
Procedure Rotation_Axe_I(*Repere.Repere3D, Angle.d)
Protected Cos.d, Sin.d, x.d
Rotation_Axe_Angle()
Rotation_Axe_Calcul(*Repere\kx, *Repere\jx, Cos, Sin)
Rotation_Axe_Calcul(*Repere\ky, *Repere\jy, Cos, Sin)
Rotation_Axe_Calcul(*Repere\kz, *Repere\jz, Cos, Sin)
EndProcedure
Procedure Rotation_Axe_J(*Repere.Repere3D, Angle.d)
Protected Cos.d, Sin.d, x.d
Rotation_Axe_Angle()
Rotation_Axe_Calcul(*Repere\ix, *Repere\kx, Cos, Sin)
Rotation_Axe_Calcul(*Repere\iy, *Repere\ky, Cos, Sin)
Rotation_Axe_Calcul(*Repere\iz, *Repere\kz, Cos, Sin)
EndProcedure
Procedure Rotation_Axe_K(*Repere.Repere3D, Angle.d)
Protected Cos.d, Sin.d, x.d
Rotation_Axe_Angle()
Rotation_Axe_Calcul(*Repere\jx, *Repere\ix, Cos, Sin)
Rotation_Axe_Calcul(*Repere\jy, *Repere\iy, Cos, Sin)
Rotation_Axe_Calcul(*Repere\jz, *Repere\iz, Cos, Sin)
EndProcedure
Procedure XYZ(*Repere.Repere3D, *PointIJK.Point3D, *PointXYZ.Point3D)
*PointXYZ\x = *PointIJK\x * *Repere\ix + *PointIJK\y * *Repere\jx + *PointIJK\z * *Repere\kx
*PointXYZ\y = *PointIJK\x * *Repere\iy + *PointIJK\y * *Repere\jy + *PointIJK\z * *Repere\ky
*PointXYZ\z = *PointIJK\x * *Repere\iz + *PointIJK\y * *Repere\jz + *PointIJK\z * *Repere\kz
EndProcedure
Procedure XYZ_P(*Repere.Repere3D, *PointIJK.Point3D, *PointXYZ.Point3DP, Perspective.q)
*PointXYZ\x = *PointIJK\x * *Repere\ix + *PointIJK\y * *Repere\jx + *PointIJK\z * *Repere\kx
*PointXYZ\y = *PointIJK\x * *Repere\iy + *PointIJK\y * *Repere\jy + *PointIJK\z * *Repere\ky
*PointXYZ\z = *PointIJK\x * *Repere\iz + *PointIJK\y * *Repere\jz + *PointIJK\z * *Repere\kz
*PointXYZ\p = 1 + Abs(*PointXYZ\z) / Perspective
If *PointXYZ\z < 0
*PointXYZ\p = 1 / *PointXYZ\p
EndIf
*PointXYZ\x * *PointXYZ\p
*PointXYZ\y * *PointXYZ\p
EndProcedure
If InitSprite() = 0
End
EndIf
If OpenWindow(0, 0, 0, 500, 500, "Repère 3D", #PB_Window_ScreenCentered | #PB_Window_SystemMenu) = 0
End
EndIf
If OpenWindowedScreen(WindowID(0), 0, 0, 500, 500, 1, 0, 0) = 0
End
EndIf
Rotation_Origine(@Repere)
Axe_I.Point3D
Axe_I\x = 200
Axe_J.Point3D
Axe_J\y = 200
Axe_K.Point3D
Axe_K\z = 200
FontID = LoadFont(0, "Verdana", 8, #PB_Font_HighQuality)
Repeat
ClearScreen($FFFFFF)
StartDrawing(ScreenOutput())
DrawingFont(FontID)
DrawingMode(#PB_2DDrawing_Transparent)
; On affiche le repère
; la ligne représentant l'axe I en vert
If Perspective
XYZ_P(@Repere, @Axe_I, @Coord.Point3DP, 400) ; on calcul les coordonnées de l'extrémité de la ligne pour l'affichage sur l'écran
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.
Else
XYZ(@Repere, @Axe_I, @Coord.Point3DP)
Circle(250 + Coord\x, 250 - Coord\y, 5, 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.
EndIf
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
DrawText(255 + Coord\x, 255 - Coord\y, "I", 0) ; On affiche le label de l'axe
; la ligne représentant l'axe J en rouge
If Perspective
XYZ_P(@Repere, @Axe_J, @Coord.Point3DP, 400) ; on calcul les coordonnées de l'extrémité de la ligne pour l'affichage sur l'écran
Circle(250 + Coord\x, 250 - Coord\y, 5 * Coord\p, RGB(255, 0, 0))
Else
XYZ(@Repere, @Axe_J, @Coord.Point3DP)
Circle(250 + Coord\x, 250 - Coord\y, 5, RGB(255, 0, 0))
EndIf
LineXY(250, 250, 250 + Coord\x, 250 - Coord\y, RGB(255, 0, 0))
DrawText(255 + Coord\x, 255 - Coord\y, "J", 0)
; la ligne représentant l'axe K en bleu
If Perspective
XYZ_P(@Repere, @Axe_K, @Coord.Point3DP, 400) ; on calcul les coordonnées de l'extrémité de la ligne pour l'affichage sur l'écran
Circle(250 + Coord\x, 250 - Coord\y, 5 * Coord\p, RGB(0, 0, 255))
Else
XYZ(@Repere, @Axe_K, @Coord.Point3DP)
Circle(250 + Coord\x, 250 - Coord\y, 5, RGB(0, 0, 255))
EndIf
LineXY(250, 250, 250 + Coord\x, 250 - Coord\y, RGB(0, 0, 255))
DrawText(255 + Coord\x, 255 - Coord\y, "K", 0)
StopDrawing()
FlipBuffers()
Repeat
Event = WindowEvent()
If Event = #WM_KEYDOWN
Select EventwParam()
Case 'P'
Perspective = 1 - Perspective
Case 'X'
Rotation_Axe_X(@Repere, #PI / 6)
Case 'Y'
Rotation_Axe_Y(@Repere, #PI / 6)
Case 'Z'
Rotation_Axe_Z(@Repere, #PI / 6)
Case 'I'
Rotation_Axe_I(@Repere, #PI / 6)
Case 'J'
Rotation_Axe_J(@Repere, #PI / 6)
Case 'K'
Rotation_Axe_K(@Repere, #PI / 6)
Case 13
Rotation_Origine(@Repere)
EndSelect
EndIf
If Event = #PB_Event_CloseWindow
End
EndIf
Until Event = 0
ForEver
Je n'ai pas été une flèche non plus à l'école , j'ai même pas le brevet des collèges , j'ai redoublé 2x...voila en tout cas ce qui représente pour moi une limite infranchissable
(de ma compréhension ) , n’étant pas allé assez loin dans les études ...
(pensez donc.. la 6em redoublée en plus.. )
Code : Tout sélectionner
If KeyboardPushed(#PB_Key_Pad7) : rot_x - vit : EndIf
If KeyboardPushed(#PB_Key_Pad8) : rot_x + vit : EndIf
If KeyboardPushed(#PB_Key_Pad4) : rot_y - vit : EndIf
If KeyboardPushed(#PB_Key_Pad5) : rot_y + vit : EndIf
If KeyboardPushed(#PB_Key_Pad1) : rot_z - vit : EndIf
If KeyboardPushed(#PB_Key_Pad2) : rot_z + vit : EndIf
If KeyboardPushed(#PB_Key_Pad9) : zoom * 1.5 : EndIf
If KeyboardPushed(#PB_Key_Pad3) : zoom / 1.5 : EndIf
If KeyboardPushed(#PB_Key_PageUp) : fact + 0.002 : EndIf
If KeyboardPushed(#PB_Key_PageDown) : fact - 0.002 : EndIf
If KeyboardPushed(#PB_Key_F1) : mode = 0 : EndIf
If KeyboardPushed(#PB_Key_F2) : mode = 1 : EndIf
If KeyboardPushed(#PB_Key_F3) : mode = 2 : EndIf
Code : Tout sélectionner
; tr = 40
; mo = 20
tr = 10
mo = 10
l = 50
dimension = tr * mo - 1
dimension_t = mo - 1
Procedure.d Convert1(degre.d, radian.d) ; Convertti un nombre en degré en radian ou si degre = 0, le contraire
If degre = 0
ProcedureReturn ((180 * radian) / #PI)
EndIf
ProcedureReturn ((#PI * degre) / 180)
EndProcedure
Procedure FillTriangle(x1, y1, x2, y2, x3, y3, color)
For boucle = 0 To 1
If x1 > x2 : x = x2 : x2 = x1 : x1 = x : y = y2 : y2 = y1 : y1 = y : EndIf
If x2 > x3 : x = x3 : x3 = x2 : x2 = x : y = y3 : y3 = y2 : y2 = y : EndIf
Next
If x1 = x2
Else
a.d = (y2 - y1) / (x2 - x1)
b.d = y2 - a * x2
a1.d = (y1 - y3) / (x1 - x3)
b1.d = y3 - a1 * x3
For x = x1 To x2
LineXY(x, a * x + b, x, a1 * x + b1, color)
Next
EndIf
If x2 = x3
Else
a.d = (y2 - y3) / (x2 - x3)
b.d = y2 - a * x2
a1.d = (y1 - y3) / (x1 - x3)
b1.d = y1 - a1 * x1
For x = x2 To x3
LineXY(x, a * x + b, x, a1 * x + b1, color)
Next
EndIf
EndProcedure
Structure FACE
x1.d
y1.d
z1.d
x2.d
y2.d
z2.d
x3.d
y3.d
z3.d
x4.d
y4.d
z4.d
z_min.d
color.l
EndStructure
Structure List
dimension.l
adresse.l
x.d
y.d
z.d
EndStructure
Procedure Cube(*objet.FACE, centre_x, centre_y, centre_z, cote); le tableau objet devrait faire 5 en taille, pour ne pas generer des erreurs
Dim obj_cube.FACE(5)
cote / 2
;{ calcul des faces
obj_cube(0)\x1 = centre_x - cote
obj_cube(0)\x2 = centre_x - cote
obj_cube(0)\x3 = centre_x + cote
obj_cube(0)\x4 = centre_x + cote
obj_cube(0)\y1 = centre_y + cote
obj_cube(0)\y2 = centre_y - cote
obj_cube(0)\y3 = centre_y - cote
obj_cube(0)\y4 = centre_y + cote
obj_cube(0)\z1 = centre_z + cote
obj_cube(0)\z2 = centre_z + cote
obj_cube(0)\z3 = centre_z + cote
obj_cube(0)\z4 = centre_z + cote
obj_cube(0)\z_min = centre_z + cote
obj_cube(0)\color = RGB(255, 0, 0)
obj_cube(1)\x1 = centre_x - cote
obj_cube(1)\x2 = centre_x - cote
obj_cube(1)\x3 = centre_x + cote
obj_cube(1)\x4 = centre_x + cote
obj_cube(1)\y1 = centre_y + cote
obj_cube(1)\y2 = centre_y + cote
obj_cube(1)\y3 = centre_y + cote
obj_cube(1)\y4 = centre_y + cote
obj_cube(1)\z1 = centre_z + cote
obj_cube(1)\z2 = centre_z - cote
obj_cube(1)\z3 = centre_z - cote
obj_cube(1)\z4 = centre_z + cote
obj_cube(1)\z_min = centre_z - cote
obj_cube(1)\color = RGB(255, 255, 0)
obj_cube(2)\x1 = centre_x - cote
obj_cube(2)\x2 = centre_x - cote
obj_cube(2)\x3 = centre_x + cote
obj_cube(2)\x4 = centre_x + cote
obj_cube(2)\y1 = centre_y + cote
obj_cube(2)\y2 = centre_y - cote
obj_cube(2)\y3 = centre_y - cote
obj_cube(2)\y4 = centre_y + cote
obj_cube(2)\z1 = centre_z - cote
obj_cube(2)\z2 = centre_z - cote
obj_cube(2)\z3 = centre_z - cote
obj_cube(2)\z4 = centre_z - cote
obj_cube(2)\z_min = centre_z - cote
obj_cube(2)\color = RGB(255, 0, 255)
obj_cube(3)\x1 = centre_x - cote
obj_cube(3)\x2 = centre_x - cote
obj_cube(3)\x3 = centre_x + cote
obj_cube(3)\x4 = centre_x + cote
obj_cube(3)\y1 = centre_y - cote
obj_cube(3)\y2 = centre_y - cote
obj_cube(3)\y3 = centre_y - cote
obj_cube(3)\y4 = centre_y - cote
obj_cube(3)\z1 = centre_z + cote
obj_cube(3)\z2 = centre_z - cote
obj_cube(3)\z3 = centre_z - cote
obj_cube(3)\z4 = centre_z + cote
obj_cube(3)\z_min = centre_z - cote
obj_cube(3)\color = RGB(0, 255, 255)
obj_cube(4)\x1 = centre_x - cote
obj_cube(4)\x2 = centre_x - cote
obj_cube(4)\x3 = centre_x - cote
obj_cube(4)\x4 = centre_x - cote
obj_cube(4)\y1 = centre_y + cote
obj_cube(4)\y2 = centre_y + cote
obj_cube(4)\y3 = centre_y - cote
obj_cube(4)\y4 = centre_y - cote
obj_cube(4)\z1 = centre_z + cote
obj_cube(4)\z2 = centre_z - cote
obj_cube(4)\z3 = centre_z - cote
obj_cube(4)\z4 = centre_z + cote
obj_cube(4)\z_min = centre_z - cote
obj_cube(4)\color = RGB(0, 255, 0)
obj_cube(5)\x1 = centre_x + cote
obj_cube(5)\x2 = centre_x + cote
obj_cube(5)\x3 = centre_x + cote
obj_cube(5)\x4 = centre_x + cote
obj_cube(5)\y1 = centre_y + cote
obj_cube(5)\y2 = centre_y + cote
obj_cube(5)\y3 = centre_y - cote
obj_cube(5)\y4 = centre_y - cote
obj_cube(5)\z1 = centre_z + cote
obj_cube(5)\z2 = centre_z - cote
obj_cube(5)\z3 = centre_z - cote
obj_cube(5)\z4 = centre_z + cote
obj_cube(5)\z_min = centre_z - cote
obj_cube(5)\color = RGB(0, 0, 255)
;}
; copie du tableau passer en parametre
CopyMemory(obj_cube(), *objet, SizeOf(FACE) * 6)
EndProcedure
Procedure Sphere(*objet.FACE, centre_x.d, centre_y.d, centre_z.d, rayon.d, tranche, morceau, color)
Dim Obj_S.FACE(tranche * morceau - 1)
epais.d = rayon * 2 / tranche
ang.d = 2 * #PI / morceau
c = 0
For a = 1 To tranche
dist.d = Abs((a - 1) * epais - rayon)
dist = rayon * rayon - dist * dist
If dist < 0 : dist = 0 : EndIf
ray_pla_1.d = Sqr(dist)
dist.d = Abs(a * epais - rayon)
dist = rayon * rayon - dist * dist
If dist < 0 : dist = 0 : EndIf
ray_pla.d = Sqr(dist)
For b = 1 To morceau
Obj_S(c)\x1 = ray_pla * Cos(ang * (b - 1)) + centre_x
Obj_S(c)\x2 = ray_pla_1 * Cos(ang * (b - 1)) + centre_x
Obj_S(c)\x3 = ray_pla_1 * Cos(b * ang) + centre_x
Obj_S(c)\x4 = ray_pla * Cos(b * ang) + centre_x
Obj_S(c)\y1 = a * epais - rayon + centre_y
Obj_S(c)\y2 = (a - 1) * epais - rayon + centre_y
Obj_S(c)\y3 = (a - 1) * epais - rayon + centre_y
Obj_S(c)\y4 = a * epais - rayon + centre_y
Obj_S(c)\z1 = ray_pla * Sin(ang * (b - 1)) + centre_z
Obj_S(c)\z2 = ray_pla_1 * Sin(ang * (b - 1)) + centre_z
Obj_S(c)\z3 = ray_pla_1 * Sin(b * ang) + centre_z
Obj_S(c)\z4 = ray_pla * Sin(b * ang) + centre_z
; Obj_S(c)\color = RGB(255 * b / morceau, 0, 255 * a / tranche)
Obj_S(c)\color = color
c + 1
Next
Next
CopyMemory(obj_S(), *objet, SizeOf(FACE) * tranche * morceau)
Dim Obj_S.FACE(0)
EndProcedure
Procedure Tube(*objet.FACE, x1.d, y1.d, z1.d, x2.d, y2.d, z2.d, rayon.d, morceau.l, color.l)
Dim Obj_T.FACE(morceau - 1)
a.d = x2 - x1
b.d = y2 - y1
c.d = z2 - z1
dist.d = Sqr(a * a + b * b + c * c)
a = rayon * a / dist
b = rayon * b / dist
c = rayon * c / dist
distab.d = Sqr(a * a + b * b)
If distab
alpha.d = ACos(a / distab)
If b < 0
alpha = - alpha
EndIf
Else
alpha.d = 0
EndIf
If rayon
phi.d = ACos(distab / rayon)
If c < 0
phi = -phi
EndIf
Else
phi.d = 0
EndIf
ang.d = 2 * #PI / morceau
cos_alpha.d = Cos(alpha)
sin_alpha.d = Sin(alpha)
cos_phi.d = Cos(phi)
sin_phi.d = Sin(phi)
For curs = 0 To morceau - 1
Obj_T(curs)\x1 = rayon * (-Sin(curs * ang) * sin_phi * cos_alpha - Cos(curs * ang) * sin_alpha) + x1
Obj_T(curs)\x2 = rayon * (-Sin(curs * ang + ang) * sin_phi * cos_alpha - Cos(curs * ang + ang) * sin_alpha) + x1
Obj_T(curs)\x3 = rayon * (-Sin(curs * ang + ang) * sin_phi * cos_alpha - Cos(curs * ang + ang) * sin_alpha) + x2
Obj_T(curs)\x4 = rayon * (-Sin(curs * ang) * sin_phi * cos_alpha - Cos(curs * ang) * sin_alpha) + x2
Obj_T(curs)\y1 = rayon * (-Sin(curs * ang) * sin_phi * sin_alpha + Cos(curs * ang) * cos_alpha) + y1
Obj_T(curs)\y2 = rayon * (-Sin(curs * ang + ang) * sin_phi * sin_alpha + Cos(curs * ang + ang) * cos_alpha) + y1
Obj_T(curs)\y3 = rayon * (-Sin(curs * ang + ang) * sin_phi * sin_alpha + Cos(curs * ang + ang) * cos_alpha) + y2
Obj_T(curs)\y4 = rayon * (-Sin(curs * ang) * sin_phi * sin_alpha + Cos(curs * ang) * cos_alpha) + y2
Obj_T(curs)\z1 = rayon * (Sin(curs * ang) * cos_phi) + z1
Obj_T(curs)\z2 = rayon * (Sin(curs * ang + ang) * cos_phi) + z1
Obj_T(curs)\z3 = rayon * (Sin(curs * ang + ang) * cos_phi) + z2
Obj_T(curs)\z4 = rayon * (Sin(curs * ang) * cos_phi) + z2
Obj_T(curs)\color = color
Next
CopyMemory(Obj_T(), *objet, SizeOf(FACE) * morceau)
Dim Obj_T.FACE(0)
EndProcedure
Procedure Tore(*objet.FACE, centre_x, centre_y, centre_z, rayon_tore, dist_centre_cercle, tranche, morceau)
Dim Obj_T.FACE(tranche * morceau - 1)
ang1.d = 2 * #PI / tranche
ang.d = 2 * #PI / morceau
CopyMemory(obj_T(), *objet, SizeOf(FACE) * tranche * morceau)
Dim Obj_T.FACE(0)
EndProcedure
Procedure Display_3D(*objet.FACE, dimension, x_center.l, y_center.l, rotX.d, rotY.d, rotZ.d, Effect_rotation.l, zoom.d, zooZ.d, facteur_perspective.d, mode.l)
; rotX.d ; angle en degré de rotation sur l'axe X
; rotY.d ; angle en degré de rotation sur l'axe Y
; rotZ.d ; angle en degré de rotation sur l'axe Z
; Effect_rotation.l ; 1 pour effectuer la rotation ou la 1ere fois, 0 sinon (juste pour affichage)
; zoom.d ; facteur de zoom apppliquer a toute les axes
; zooZ.d ; facteur de zoom apppliquer a l'axe Z
; facteur_perspective.d ; facteur de 'perspective' , 0 pour pas de perspective
If Effect_rotation = 1
; copie du tableau passé en parametre
Dim Obj.FACE(dimension)
CopyMemory(*objet, Obj(), SizeOf(FACE) * (dimension + 1))
; convertion des angles en radian
rotx = Convert1(rotx, 0)
roty = Convert1(roty, 0)
rotz = Convert1(rotz, 0)
; rotz = ACos(Sin(roty))
; If ASin(Cos(rotx)) < 0
; rotz + #PI / 2
; EndIf
angle.d = 0
;{ rotation
For curs = 0 To dimension
For point = 1 To 4
If point = 1
X.d = Obj(curs)\x1
Y.d = Obj(curs)\y1
Z.d = Obj(curs)\z1
ElseIf point = 2
X.d = Obj(curs)\x2
Y.d = Obj(curs)\y2
Z.d = Obj(curs)\z2
ElseIf point = 3
X.d = Obj(curs)\x3
Y.d = Obj(curs)\y3
Z.d = Obj(curs)\z3
ElseIf point = 4
X.d = Obj(curs)\x4
Y.d = Obj(curs)\y4
Z.d = Obj(curs)\z4
EndIf
X * zoom
Y * zoom
Z * zoom; * zooZ
; ## passage dans le repère rotaté de rotx
; Xa.d = X
Ya.d = Y * Cos(rotx) - Z * Sin(rotx)
Za.d = Y * Sin(rotx) + Z * Cos(rotx)
; ## passage dans le repère rotaté de roty
Xb.d = X * Cos(roty) + Za * Sin(roty)
; Yb.d = Ya
Zb.d = -X * Sin(roty) + Za * Cos(roty)
; ## passage dans le repère rotaté de rotz
X = Xb * Cos(rotz) - Ya * Sin(rotz)
Y = Xb * Sin(rotz) + Ya * Cos(rotz)
Z = Zb
; If rotz ; rotation autour de z
; dist.d = Sqr(X * X + Y * Y)
;
; If dist
; angle = ACos(X / dist)
; If Y < 0
; angle = - angle
; EndIf
; angle + rotz
; X = dist * Cos(angle)
; Y = dist * Sin(angle)
; EndIf
; EndIf
;
; If roty ; rotation autour de y
; dist.d = Sqr(Z * Z + X * X)
;
; If dist
; angle = ACos(Z / dist)
; If X < 0
; angle = - angle
; EndIf
; angle + roty
; Z = dist * Cos(angle)
; X = dist * Sin(angle)
; EndIf
; EndIf
;
; If rotx ; rotation autour de x
; dist.d = Sqr(Y * Y + Z * Z)
;
; If dist
; angle = ACos(Y / dist)
; If Z < 0
; angle = - angle
; EndIf
; angle + rotx
; Y = dist * Cos(angle)
; Z = dist * Sin(angle)
; EndIf
; EndIf
If point = 1
Obj(curs)\x1 = X.d
Obj(curs)\y1 = Y.d
Obj(curs)\z1 = Z.d
Obj(curs)\z_min = Z
ElseIf point = 2
Obj(curs)\x2 = X.d
Obj(curs)\y2 = Y.d
Obj(curs)\z2 = Z.d
ElseIf point = 3
Obj(curs)\x3 = X.d
Obj(curs)\y3 = Y.d
Obj(curs)\z3 = Z.d
ElseIf point = 4
Obj(curs)\x4 = X.d
Obj(curs)\y4 = Y.d
Obj(curs)\z4 = Z.d
EndIf
If Z < Obj(curs)\z_min : Obj(curs)\z_min = Z : EndIf
Next
Next
;}
SortStructuredArray(Obj(), 0, OffsetOf(FACE\z_min), #PB_Sort_Double)
EndIf
;{ affichage des lignes
For curs = 0 To dimension
coef_1.d = Pow(2.718281828459, -facteur_perspective * Obj(curs)\z1)
coef_2.d = Pow(2.718281828459, -facteur_perspective * Obj(curs)\z2)
coef_3.d = Pow(2.718281828459, -facteur_perspective * Obj(curs)\z3)
coef_4.d = Pow(2.718281828459, -facteur_perspective * Obj(curs)\z4)
x1.d = Obj(curs)\x1 * coef_1 + x_center
x2.d = Obj(curs)\x2 * coef_2 + x_center
x3.d = Obj(curs)\x3 * coef_3 + x_center
x4.d = Obj(curs)\x4 * coef_4 + x_center
y1.d = Obj(curs)\y1 * coef_1 + y_center
y2.d = Obj(curs)\y2 * coef_2 + y_center
y3.d = Obj(curs)\y3 * coef_3 + y_center
y4.d = Obj(curs)\y4 * coef_4 + y_center
x = (x1 + x2 + x3 + x4) / 4
y = (y1 + y2 + y3 + y4) / 4
LineXY(x1, y1, x2, y2, Obj(curs)\color)
LineXY(x2, y2, x3, y3, Obj(curs)\color)
LineXY(x3, y3, x4, y4, Obj(curs)\color)
LineXY(x4, y4, x1, y1, Obj(curs)\color)
If mode = 1
; FillArea(x, y, Obj(curs)\color, Obj(curs)\color)
FillTriangle(x1, y1, x2, y2, x3, y3, Obj(curs)\color)
FillTriangle(x1, y1, x3, y3, x4, y4, Obj(curs)\color)
EndIf
If mode = 2
DrawText(x1, y1, "1", Obj(curs)\color)
DrawText(x2, y2, "2", Obj(curs)\color)
DrawText(x3, y3, "3", Obj(curs)\color)
DrawText(x4, y4, "4", Obj(curs)\color)
EndIf
Next
;}
EndProcedure
Procedure Display_All_3D(*listobjet.l, nb_objet, x_center.l, y_center.l, rotX.d, rotY.d, rotZ.d, Effect_rotation.l, zoom.d, zooZ.d, facteur_perspective.d, mode.l)
Dim Obj_all.List(nb_objet - 1)
CopyMemory(*listobjet, Obj_all(), SizeOf(List) * (nb_objet))
; convertion des angles en radian
rotx1 = Convert1(rotx, 0)
roty1 = Convert1(roty, 0)
rotz1 = Convert1(rotz, 0)
angle.d = 0
;{ rotation
For curs = 0 To nb_objet - 1
X.d = Obj_all(curs)\x
Y.d = Obj_all(curs)\y
Z.d = Obj_all(curs)\z
X * zoom
Y * zoom
Z * zoom * zooZ
; ## passage dans le repère rotaté de rotx
; Xa.d = X
Ya.d = Y * Cos(rotx1) - Z * Sin(rotx1)
Za.d = Y * Sin(rotx1) + Z * Cos(rotx1)
; ## passage dans le repère rotaté de roty
Xb.d = X * Cos(roty1) + Za * Sin(roty1)
; Yb.d = Ya
Zb.d = -X * Sin(roty1) + Za * Cos(roty1)
; ## passage dans le repère rotaté de rotz
X = Xb * Cos(rotz1) - Ya * Sin(rotz1)
Y = Xb * Sin(rotz1) + Ya * Cos(rotz1)
Z = Zb
; If rotz ; rotation autour de z
; dist.d = Sqr(X * X + Y * Y)
;
; If dist
; angle = ACos(X / dist)
; If Y < 0
; angle = - angle
; EndIf
; angle + rotz1
; X = dist * Cos(angle)
; Y = dist * Sin(angle)
; EndIf
; EndIf
;
; If roty ; rotation autour de y
; dist.d = Sqr(Z * Z + X * X)
;
; If dist
; angle = ACos(Z / dist)
; If X < 0
; angle = - angle
; EndIf
; angle + roty1
; Z = dist * Cos(angle)
; X = dist * Sin(angle)
; EndIf
; EndIf
;
; If rotx ; rotation autour de x
; dist.d = Sqr(Y * Y + Z * Z)
;
; If dist
; angle = ACos(Y / dist)
; If Z < 0
; angle = - angle
; EndIf
; angle + rotx1
; Y = dist * Cos(angle)
; Z = dist * Sin(angle)
; EndIf
; EndIf
Obj_all(curs)\x = X.d
Obj_all(curs)\y = Y.d
Obj_all(curs)\z = Z.d
Next
;}
SortStructuredArray(Obj_all(), 0, OffsetOf(List\z) , #PB_Sort_Double)
For curs = 0 To nb_objet - 1
Display_3D(obj_all(curs)\adresse, obj_all(curs)\dimension, x_center.l, y_center.l, rotX.d, rotY.d, rotZ.d, Effect_rotation.l, zoom.d, zooZ.d, facteur_perspective.d, mode.l)
Next
EndProcedure
; ##########################################################################################
; ##########################################################################################
#Screen_W = 600
#Screen_H = 500
OpenWindow(0, 0, 0, #Screen_W, #Screen_H, "", #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget)
If InitSprite() = 0 Or InitMouse() = 0 Or InitKeyboard() = 0 Or InitSprite3D() = 0 : End : EndIf
OpenWindowedScreen(WindowID(0), 0, 0, #Screen_W, #Screen_H, 0, 0, 0)
KeyboardMode(1)
nb_objet = 11
;{
; Macro def
; Dim aa.FACE(dimension)
; Dim ab.FACE(dimension)
; Dim ac.FACE(dimension)
; Dim ad.FACE(dimension)
; Dim ae.FACE(dimension)
; Dim af.FACE(dimension)
; Dim ag.FACE(dimension)
; Dim ah.FACE(dimension)
;
; ;{ definition des spheres
; Sphere(aa(), 0, 0, 0, 10, tr, mo, #Green)
; Sphere(ab(), 20, 0, 0, 10, tr, mo, #Green)
; Sphere(ac(), 40, 0, 0, 10, tr, mo, #Green)
; Sphere(ad(), 60, 0, 0, 10, tr, mo, #Green)
; Sphere(ae(), 0, 20, 0, 10, tr, mo, #Green)
; Sphere(af(), 20, 20, 0, 10, tr, mo, #Green)
; Sphere(ag(), 40, 20, 0, 10, tr, mo, #Green)
; Sphere(ah(), 60, 20, 0, 10, tr, mo, #Green)
;
; Dim List.list(nb_objet - 1)
;
; ;{ list
; a = 0
; list(a)\adresse = @aa()
; list(a)\dimension = dimension
; list(a)\x = 0
; list(a)\y = 0
; list(a)\z = 0
;
; a + 1
; list(a)\adresse = @ab()
; list(a)\dimension = dimension
; list(a)\x = 20
; list(a)\y = 0
; list(a)\z = 0
;
; a + 1
; list(a)\adresse = @ac()
; list(a)\dimension = dimension
; list(a)\x = 40
; list(a)\y = 0
; list(a)\z = 0
;
; a + 1
; list(a)\adresse = @ad()
; list(a)\dimension = dimension
; list(a)\x = 60
; list(a)\y = 0
; list(a)\z = 0
;
; a + 1
; list(a)\adresse = @ae()
; list(a)\dimension = dimension
; list(a)\x = 0
; list(a)\y = 20
; list(a)\z = 0
;
; a + 1
; list(a)\adresse = @af()
; list(a)\dimension = dimension
; list(a)\x = 20
; list(a)\y = 20
; list(a)\z = 0
;
; a + 1
; list(a)\adresse = @ag()
; list(a)\dimension = dimension
; list(a)\x = 40
; list(a)\y = 20
; list(a)\z = 0
;
; a + 1
; list(a)\adresse = @ah()
; list(a)\dimension = dimension
; list(a)\x = 60
; list(a)\y = 20
; list(a)\z = 0
; ;}
; EndMacro
;}
;{
Macro def
Dim aa.FACE(dimension)
Dim ab.FACE(dimension)
Dim ac.FACE(dimension)
Dim ad.FACE(dimension)
Dim ae.FACE(dimension)
Dim af.FACE(dimension)
Dim ag.FACE(dimension)
Dim ah.FACE(dimension)
Dim ai.FACE(dimension)
Dim aj.FACE(dimension)
Dim ak.FACE(dimension)
;{ definition des spheres
Sphere(aa(), 0, 0, 0, 10, tr, mo, #White)
Sphere(ab(), 20, 0, 0, 10, tr, mo, #Red)
Sphere(ac(), 40, 0, 0, 10, tr, mo, #Red)
Sphere(ad(), 60, 0, 0, 10, tr, mo, #Red)
Sphere(ae(), 0, 20, 0, 10, tr, mo, #Green)
Sphere(af(), 0, 40, 0, 10, tr, mo, #Green)
Sphere(ag(), 0, 60, 0, 10, tr, mo, #Green)
Sphere(ah(), 0, 0, 20, 10, tr, mo, #Blue)
Sphere(ai(), 0, 0, 40, 10, tr, mo, #Blue)
Sphere(aj(), 0, 0, 60, 10, tr, mo, #Blue)
Sphere(ak(), 60, 60, 60, 10, tr, mo, #Yellow)
Dim List.List(nb_objet - 1)
;{ list
a = 0
List(a)\adresse = @aa()
List(a)\dimension = dimension
List(a)\x = 0
List(a)\y = 0
List(a)\z = 0
a + 1
List(a)\adresse = @ab()
List(a)\dimension = dimension
List(a)\x = 20
List(a)\y = 0
List(a)\z = 0
a + 1
List(a)\adresse = @ac()
List(a)\dimension = dimension
List(a)\x = 40
List(a)\y = 0
List(a)\z = 0
a + 1
List(a)\adresse = @ad()
List(a)\dimension = dimension
List(a)\x = 60
List(a)\y = 0
List(a)\z = 0
a + 1
List(a)\adresse = @ae()
List(a)\dimension = dimension
List(a)\x = 0
List(a)\y = 20
List(a)\z = 0
a + 1
List(a)\adresse = @af()
List(a)\dimension = dimension
List(a)\x = 0
List(a)\y = 40
List(a)\z = 0
a + 1
List(a)\adresse = @ag()
List(a)\dimension = dimension
List(a)\x = 0
List(a)\y = 60
List(a)\z = 0
a + 1
List(a)\adresse = @ah()
List(a)\dimension = dimension
List(a)\x = 0
List(a)\y = 0
List(a)\z = 20
a + 1
List(a)\adresse = @ai()
List(a)\dimension = dimension
List(a)\x = 0
List(a)\y = 0
List(a)\z = 40
a + 1
List(a)\adresse = @aj()
List(a)\dimension = dimension
List(a)\x = 0
List(a)\y = 0
List(a)\z = 60
a + 1
List(a)\adresse = @ak()
List(a)\dimension = dimension
List(a)\x = 60
List(a)\y = 60
List(a)\z = 60
;}
EndMacro
;}
def
vit = 10
zoom.d = 1.5
zoom_z.d = 1
fact.d = -0.004
Repeat
event = WindowEvent()
ExamineKeyboard()
If KeyboardPushed(#PB_Key_Pad7) : rot_x - vit : EndIf
If KeyboardPushed(#PB_Key_Pad8) : rot_x + vit : EndIf
If KeyboardPushed(#PB_Key_Pad4) : rot_y - vit : EndIf
If KeyboardPushed(#PB_Key_Pad5) : rot_y + vit : EndIf
If KeyboardPushed(#PB_Key_Pad1) : rot_z - vit : EndIf
If KeyboardPushed(#PB_Key_Pad2) : rot_z + vit : EndIf
If KeyboardPushed(#PB_Key_Pad9) : zoom * 1.5 : EndIf
If KeyboardPushed(#PB_Key_Pad3) : zoom / 1.5 : EndIf
If KeyboardPushed(#PB_Key_PageUp) : fact + 0.002 : EndIf
If KeyboardPushed(#PB_Key_PageDown) : fact - 0.002 : EndIf
If KeyboardPushed(#PB_Key_F1) : mode = 0 : EndIf
If KeyboardPushed(#PB_Key_F2) : mode = 1 : EndIf
If KeyboardPushed(#PB_Key_F3) : mode = 2 : EndIf
If rot_x > 360 : rot_x - 360 : EndIf
If rot_y > 360 : rot_y - 360 : EndIf
If rot_z > 360 : rot_z - 360 : EndIf
If rot_x < 0 : rot_x + 360 : EndIf
If rot_y < 0 : rot_y + 360 : EndIf
If rot_z < 0 : rot_z + 360 : EndIf
;{ changement des parametres des spheres
If KeyboardPushed(#PB_Key_A) Or KeyboardPushed(#PB_Key_Z) Or KeyboardPushed(#PB_Key_Q) Or KeyboardPushed(#PB_Key_S)
If KeyboardPushed(#PB_Key_A) : tr + 1 : EndIf
If KeyboardPushed(#PB_Key_Z) And tr > 2 : tr - 1 : EndIf
If KeyboardPushed(#PB_Key_Q) : mo + 1 : EndIf
If KeyboardPushed(#PB_Key_S) And mo > 2 : mo - 1 : EndIf
dimension = tr * mo
dimension_t = mo - 1
def
EndIf
;}
Delay(10)
ClearScreen(0)
If StartDrawing(ScreenOutput())
Display_All_3D(@list(), nb_objet, #Screen_W / 2, #Screen_H / 2, rot_x, rot_y, rot_z, 1, zoom, 1, fact, mode)
DrawText(0, 0, Str(rot_x), #White, 0)
DrawText(0, 20, Str(rot_y), #White, 0)
DrawText(0, 40, Str(rot_z), #White, 0)
StopDrawing()
EndIf
FlipBuffers()
Until event = #PB_Event_CloseWindow Or KeyboardPushed(#PB_Key_Escape)
End
Code : Tout sélectionner
If KeyboardPushed(#PB_Key_Z) : NC_CameraMove(@Camera, 10, 0, 0) : EndIf
If KeyboardPushed(#PB_Key_S) : NC_CameraMove(@Camera, -10, 0, 0) : EndIf
If KeyboardPushed(#PB_Key_Q) : NC_CameraMove(@Camera, 0, 10, 0) : EndIf
If KeyboardPushed(#PB_Key_D) : NC_CameraMove(@Camera, 0, -10, 0) : EndIf
If KeyboardPushed(#PB_Key_Up) : NC_CameraLocate(@Camera, Camera\cx, Camera\cy + 10, Camera\cz) : EndIf
If KeyboardPushed(#PB_Key_Down) : NC_CameraLocate(@Camera, Camera\cx, Camera\cy - 10, Camera\cz) : EndIf
If KeyboardPushed(#PB_Key_Left) : NC_CameraLocate(@Camera, Camera\cx + 10, Camera\cy, Camera\cz) : EndIf
If KeyboardPushed(#PB_Key_Right) : NC_CameraLocate(@Camera, Camera\cx - 10, Camera\cy, Camera\cz) : EndIf
If MouseDeltaX() Or MouseDeltaY() : NC_CameraLookAt(@Camera, camera\cx + camera\ax + MouseDeltaX() / coef, camera\cy + camera\ay + MouseDeltaY() / coef, camera\cz + camera\az) : EndIf
If KeyboardPushed(#PB_Key_Pad9) : NC_CameraFocale(@Camera, Camera\P + 1) : EndIf
If KeyboardPushed(#PB_Key_Pad3) : NC_CameraFocale(@Camera, Camera\P - 1) : EndIf
If KeyboardPushed(#PB_Key_Pad7) : NC_CameraFOV(@Camera, ((360 * Camera\FOV) / #PI) + 2) : EndIf
If KeyboardPushed(#PB_Key_Pad8) : NC_CameraFOV(@Camera, ((360 * Camera\FOV) / #PI) - 2) : EndIf
If KeyboardPushed(#PB_Key_F1) : mode = 0 : EndIf
If KeyboardPushed(#PB_Key_F2) : mode = 1 : EndIf
If KeyboardPushed(#PB_Key_F3) : mode = 2 : EndIf
If KeyboardPushed(#PB_Key_Pad5) : NC_CameraLookAt(@Camera, 0, 0, 0) : EndIf
Code : Tout sélectionner
Structure point_3D
k.d
x.d
y.d
EndStructure
Structure triangle
sommet1.l
sommet2.l
sommet3.l
color.l
EndStructure
Structure pt
x.d
y.d
z.d
color.l
EndStructure
Structure vec
x.d
y.d
z.d
EndStructure
Structure camera
; Données à définir
ecranX.l ; position en x de l'écran
ecranY.l ; position en y de l'écran
ecranL.l ; largeur d'écran
ecranH.l ; Hauteur d'écran
cx.d ; position en x de la caméra "dans le monde 3D"
cy.d ; position en y de la caméra
cz.d ; position en z de la caméra
P.d ; Profondeur du champ
FOV.d ; Field Of Vision en rad doit être compris entre 0 et #PI
; Données à calculer
Opx.d
Opy.d
Opz.d
; coordonnée du vec(n) au plan de la caméra, à définir par un calcul
ax.d
ay.d
az.d
; coordonnée du vec(x) au plan de la caméra, à définir par un calcul : vec(x) = vec(z) - (vec(z).vec(n))*vec(n)
xx.d
xy.d
xz.d
; coordonnée du vec(y) au plan de la caméra, à définir par un calcul : vec(y) = vec(n) ^ vec(x)
yx.d
yy.d
yz.d
; constante du plan d
d.d
H.d ; Hauteur du champ / 2
L.d ; largeur du champ / 2
rapport.d ; rapport entre la taille du plan de focale de la cam et l'écran d'affichage
ecran_centre_X.d
ecran_centre_Y.d
EndStructure
Procedure.d Convert1(degre.d, radian.d) ; Convertti un nombre en degré en radian ou si degre = 0, le contraire
If degre = 0
ProcedureReturn ((180 * radian) / #PI)
EndIf
ProcedureReturn ((#PI * degre) / 180)
EndProcedure
; Forme volumique complexe prédessinnées
Procedure Sphere(*objet.pt, *sommet.triangle, centre_x.d, centre_y.d, centre_z.d, rayon.d, tranche, morceau, color)
Dim Obj_S.pt(tranche * morceau * 4)
epais.d = rayon * 2 / tranche
ang.d = 2 * #PI / morceau
c = 0
For a = 1 To tranche
dist.d = Abs((a - 1) * epais - rayon)
dist = rayon * rayon - dist * dist
If dist < 0 : dist = 0 : EndIf
ray_pla_1.d = Sqr(dist)
dist.d = Abs(a * epais - rayon)
dist = rayon * rayon - dist * dist
If dist < 0 : dist = 0 : EndIf
ray_pla.d = Sqr(dist)
For b = 1 To morceau
c + 1
Obj_S(c)\x = ray_pla * Cos(ang * (b - 1)) + centre_x
Obj_S(c)\y = a * epais - rayon + centre_y
Obj_S(c)\z = ray_pla * Sin(ang * (b - 1)) + centre_z
c + 1
Obj_S(c)\x = ray_pla_1 * Cos(ang * (b - 1)) + centre_x
Obj_S(c)\y = (a - 1) * epais - rayon + centre_y
Obj_S(c)\z = ray_pla_1 * Sin(ang * (b - 1)) + centre_z
c + 1
Obj_S(c)\x = ray_pla_1 * Cos(b * ang) + centre_x
Obj_S(c)\y = (a - 1) * epais - rayon + centre_y
Obj_S(c)\z = ray_pla_1 * Sin(b * ang) + centre_z
c + 1
Obj_S(c)\x = ray_pla * Cos(b * ang) + centre_x
Obj_S(c)\y = a * epais - rayon + centre_y
Obj_S(c)\z = ray_pla * Sin(b * ang) + centre_z
*sommet + SizeOf(triangle)
*sommet\sommet1 = c - 3 - 1
*sommet\sommet2 = c - 2 - 1
*sommet\sommet3 = c - 1 - 1
*sommet\color = Random(#White)
*sommet + SizeOf(triangle)
*sommet\sommet1 = c - 3 - 1
*sommet\sommet2 = c - 1 - 1
*sommet\sommet3 = c - 1
*sommet\color = Random(#White)
Next
Next
Obj_S(0)\x = c
CopyMemory(obj_S(), *objet, SizeOf(pt) * tranche * morceau)
Dim Obj_S.pt(0)
EndProcedure
; Fonction auxiliaires
Procedure FillTriangle(x1, y1, x2, y2, x3, y3, color) ; dessine un triangle plein sans trou
For boucle = 0 To 1
If x1 > x2 : x = x2 : x2 = x1 : x1 = x : y = y2 : y2 = y1 : y1 = y : EndIf
If x2 > x3 : x = x3 : x3 = x2 : x2 = x : y = y3 : y3 = y2 : y2 = y : EndIf
Next
If x1 = x2
Else
a.d = (y2 - y1) / (x2 - x1)
b.d = y2 - a * x2
a1.d = (y1 - y3) / (x1 - x3)
b1.d = y3 - a1 * x3
For x = x1 To x2
LineXY(x, a * x + b, x, a1 * x + b1, color)
Next
EndIf
If x2 = x3
Else
a.d = (y2 - y3) / (x2 - x3)
b.d = y2 - a * x2
a1.d = (y1 - y3) / (x1 - x3)
b1.d = y1 - a1 * x1
For x = x2 To x3
LineXY(x, a * x + b, x, a1 * x + b1, color)
Next
EndIf
EndProcedure
; Fonction interne pour le fonctionnement de la caméra
Procedure CameraPlan(*ca.camera, cible_x.d, cible_y.d, cible_z.d, mode.l) ; Calcul de toutes les données de la camera dépendant des données initiales
; mode défini si les vecteurs sont recalculés (mode = 0) ou pas (mode = 1)
If mode = 0
; calcul de vec(n)
*ca\ax = cible_x - *ca\cx
*ca\ay = cible_y - *ca\cy
*ca\az = cible_z - *ca\cz
norme.d = Sqr(*ca\ax * *ca\ax + *ca\ay * *ca\ay + *ca\az * *ca\az)
*ca\ax / norme
*ca\ay / norme
*ca\az / norme
EndIf
; coordonnées de Op
*ca\Opx = *ca\cx + *ca\ax * *ca\P
*ca\Opy = *ca\cy + *ca\ay * *ca\P
*ca\Opz = *ca\cz + *ca\az * *ca\P
; calcul de d
*ca\d = - *ca\Opx * *ca\ax - *ca\Opy * *ca\ay - *ca\Opz * *ca\az
If mode = 0
; définition de vec(x)
; test d'alignement sur Z
; *ca\xx = - *ca\az * *ca\ax
; *ca\xy = - *ca\az * *ca\ay
; *ca\xz = 1 - *ca\az * *ca\az
; test d'alignement sur X
*ca\xx = 1- *ca\ax * *ca\ax
*ca\xy = - *ca\ax * *ca\ay
*ca\xz = - *ca\ax * *ca\az
norme.d = Sqr(*ca\xx * *ca\xx + *ca\xy * *ca\xy + *ca\xz * *ca\xz)
*ca\xx / norme
*ca\xy / norme
*ca\xz / norme
; définition de vec(y) (produit vectoriel)
*ca\yx = -*ca\az * *ca\xy + *ca\ay * *ca\xz
*ca\yy = -*ca\ax * *ca\xz + *ca\az * *ca\xx
*ca\yz = -*ca\ay * *ca\xx + *ca\ax * *ca\xy
EndIf
; calcul de L.d ; Largeur du champ / 2
*ca\L = *ca\P * Tan(*ca\FOV)
; calcul du rapport de la cam
*ca\rapport = *ca\ecranL / (*ca\L * 2)
; calcul de H.d ; Hauteur du champ / 2
*ca\H = (*ca\ecranH / *ca\rapport) / 2
EndProcedure
; Fonction de gestion de la caméra :
Procedure NC_CreateCamera(*Cam.camera, X.l, Y.l, Width.l, Height.l) ; ;-) NC pour No Carte graphique
*Cam\ecranX = X
*Cam\ecranY = Y
*Cam\ecranL = Width
*Cam\ecranH = Height
*Cam\ecran_centre_X = Width / 2 + X
*Cam\ecran_centre_Y = Height / 2 + Y
*Cam\FOV = (#PI * (45 / 2)) / 180 ; par defaut crée une caméra de FOV 45°
*Cam\cx = 0
*Cam\cy = 0
*Cam\cz = 0
*Cam\P = 40
; *Cam\rapport = 100 ; inutile avec l'introduction de FOV
CameraPlan(*Cam, 10, 10, 10, 0)
EndProcedure
Procedure NC_CameraFocale(*Cam.camera, Focale.d) ; Change la distance du plan focal de la camera, par défaut il est de 40
*Cam\P = Focale
CameraPlan(*Cam, 0, 0, 0, 1)
EndProcedure
Procedure NC_CameraFOV(*Cam.camera, FOV.d) ; Change le champ de vision de la camera en degré, par défaut il est de 40, il va de 0° à 180° (non compris)
*Cam\FOV = (#PI * (FOV / 2)) / 180
CameraPlan(*Cam, 0, 0, 0, 1)
EndProcedure
Procedure NC_CameraLocate(*Cam.camera, x.d, y.d, z.d) ; Change les coordonées absolues de la caméra
*Cam\cx = x
*Cam\cy = y
*Cam\cz = z
CameraPlan(*Cam, 0, 0, 0, 1)
EndProcedure
Procedure NC_CameraLookAt(*Cam.camera, xcible.d, ycible.d, zcible.d) ; oriente la camera vers un point
CameraPlan(*Cam, xcible, ycible, zcible, 0)
EndProcedure
Procedure NC_CameraMove(*Cam.camera, dx.d, dy.d, dz.d) ; deplace la caméra par rapport à ses axes internes (pour changer la position absolue voir CameraLocate_NC())
*Cam\cx + dx * *Cam\ax + dz * *Cam\yx - dy * *Cam\xx
*Cam\cy + dx * *Cam\ay + dz * *Cam\yy - dy * *Cam\xy
*Cam\cz + dx * *Cam\az + dz * *Cam\yz - dy * *Cam\xz
CameraPlan(*Cam, 0, 0, 0, 1)
EndProcedure
; Fonction d'affichage des objets 3D
Procedure Display_3D(*ca.camera, *coord.pt, *triangle.triangle)
nb_points = *coord\x
sizeofpt = SizeOf(pt) ; a remplacer par une constante lorsque la structure sera definie une fois pour toute
; nbpointdessine = 0 ; uniquement du debug
nbtriangledessine = 0 ; uniquement du debug
Dim tableau.point_3D(nb_points - 1) ; le premier point sert à stocker le nb de point total
For a = 1 To nb_points
*coord + sizeofpt ; on avance d'une case dans le tableau (qui n'a qu'une seule colonne)
; calcul des coordonnées de la projection de M(x,y,z) sur le plan de la camera
A0.d = (*coord\y - *ca\cy) / (*coord\x - *ca\cx)
B0.d = (*coord\z - *ca\cz) / (*coord\x - *ca\cx)
B.vec\x = (- *ca\d + (A0 * *ca\cx - *ca\cy) * *ca\ay + (B0 * *ca\cx - *ca\cz) * *ca\az) / (*ca\ay * A0 + *ca\ax + *ca\az * B0)
A1.d = (*coord\x - *ca\cx) / (*coord\y - *ca\cy)
B1.d = (*coord\z - *ca\cz) / (*coord\y - *ca\cy)
B\y = (- *ca\d + (A1 * *ca\cy - *ca\cx) * *ca\ax + (B1 * *ca\cy - *ca\cz) * *ca\az) / (*ca\ax * A1 + *ca\ay + *ca\az * B1)
A2.d = (*coord\x - *ca\cx) / (*coord\z - *ca\cz)
B2.d = (*coord\y - *ca\cy) / (*coord\z - *ca\cz)
B\z = (- *ca\d + (A2 * *ca\cz - *ca\cx) * *ca\ax + (B2 * *ca\cz - *ca\cy) * *ca\ay) / (*ca\ax * A2 + *ca\az + *ca\ay * B2)
If (*coord\x - *ca\cx) <> 0 ; on n'affiche pas les points sur la caméra !!
k.d = (B\x - *ca\cx) / (*coord\x - *ca\cx)
If k <= 1 And k > 0 ; on teste si le point M est bien situé devant la caméra et apres le plan de focale
; coordonnées de B exprimées dans le plan focal : Bx = vec(Op B).vec(x) , By = vec(Op B).vec(y)
Bx.d = (B\x - *ca\Opx) * *ca\xx + (B\y - *ca\Opy) * *ca\xy + (B\z - *ca\Opz) * *ca\xz
By.d = (B\x - *ca\Opx) * *ca\yx + (B\y - *ca\Opy) * *ca\yy + (B\z - *ca\Opz) * *ca\yz
tableau(a - 1)\x = *ca\ecran_centre_X + Bx * *ca\rapport
tableau(a - 1)\y = *ca\ecran_centre_Y + By * *ca\rapport
tableau(a - 1)\k = k
; ; commenté pour tester l'affichage de triangle et non plus de points seuls
; ; test si le point rentre dans l'écran:
; If Bx < *ca\L And Bx > -*ca\L And By < *ca\H And By > -*ca\H
; ScreenX.d = *ca\ecran_centre_X + Bx * *ca\rapport
; ScreenY.d = *ca\ecran_centre_Y + By * *ca\rapport
;
; Circle(ScreenX, ScreenY, 1, *coord\color)
;
; ; If *coord\color = #Blue
; ; Debug Bx
; ; EndIf
;
; nbpointdessine + 1
; EndIf
EndIf
EndIf
Next
; SortStructuredArray(tableau(), 1, OffsetOf(point_3D\k), #PB_Sort_Double)
nb_tri = *triangle\sommet1
sizeoftriangle = SizeOf(triangle)
For a = 1 To nb_tri
*triangle + sizeoftriangle
If tableau(*triangle\sommet1)\k > 0 And tableau(*triangle\sommet1)\k <= 1 And tableau(*triangle\sommet2)\k > 0 And tableau(*triangle\sommet2)\k <= 1 And tableau(*triangle\sommet3)\k > 0 And tableau(*triangle\sommet3)\k <= 1
FillTriangle(tableau(*triangle\sommet1)\x ,tableau(*triangle\sommet1)\y, tableau(*triangle\sommet2)\x, tableau(*triangle\sommet2)\y, tableau(*triangle\sommet3)\x, tableau(*triangle\sommet3)\y, *triangle\color)
nbtriangledessine + 1
EndIf
Next
; ProcedureReturn nbpointdessine
ProcedureReturn nbtriangledessine
EndProcedure
; ##########################################################################################
; ##########################################################################################
#Screen_W = 600
#Screen_H = 500
OpenWindow(0, 0, 0, #Screen_W, #Screen_H, "", #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget)
If InitSprite() = 0 Or InitMouse() = 0 Or InitKeyboard() = 0 Or InitSprite3D() = 0 : End : EndIf
OpenWindowedScreen(WindowID(0), 0, 0, #Screen_W, #Screen_H, 0, 0, 0)
KeyboardMode(1)
; definition des sommets
;{ repère
Dim co.pt(4) ; 4 points
co(0)\x = 4 ; nombre de points
;{ repère
x = 20
y = 0
z = 0
; centre
co(1)\x = x
co(1)\y = y
co(1)\z = z
co(1)\color = #White
; x
co(2)\x = 10 + x
co(2)\y = y
co(2)\z = z
co(2)\color = #Red
; y
co(3)\x = x
co(3)\y = 10 + y
co(3)\z = z
co(3)\color = #Green
; z
co(4)\x = x
co(4)\y = y
co(4)\z = 10 + z
co(4)\color = #Blue
;}
; définition des triangles (l'index des sommets commence à 0)
Dim triangle.triangle(3)
triangle(0)\sommet1 = 3
;{ triangle du repère
; xOy
triangle(1)\sommet1 = 1
triangle(1)\sommet2 = 0
triangle(1)\sommet3 = 2
triangle(1)\color = #Blue
; yOz
triangle(2)\sommet1 = 2
triangle(2)\sommet2 = 0
triangle(2)\sommet3 = 3
triangle(2)\color = #Red
; zOx
triangle(3)\sommet1 = 3
triangle(3)\sommet2 = 0
triangle(3)\sommet3 = 1
triangle(3)\color = #Green
;}
;}
;{ Sphère
tranche = 10
morceau = 10
Dim Sphere_pt.pt(tranche * morceau * 4)
Dim Sphere_tr.triangle(tranche * morceau * 2)
Sphere(@Sphere_pt(), @Sphere_tr(0), 20, 0, 0, 20, tranche, morceau, 0)
Sphere_tr(0)\sommet1 = 200
;}
NC_CreateCamera(@Camera.camera, 0, 0, #Screen_W, #Screen_H)
NC_CameraLocate(@Camera, 500, 500, 500)
NC_CameraLookAt(@Camera, 0, 0, 0)
coef.d = 1000
Repeat
event = WindowEvent()
ExamineKeyboard()
ExamineMouse()
If KeyboardPushed(#PB_Key_Z) : NC_CameraMove(@Camera, 10, 0, 0) : EndIf
If KeyboardPushed(#PB_Key_S) : NC_CameraMove(@Camera, -10, 0, 0) : EndIf
If KeyboardPushed(#PB_Key_Q) : NC_CameraMove(@Camera, 0, 10, 0) : EndIf
If KeyboardPushed(#PB_Key_D) : NC_CameraMove(@Camera, 0, -10, 0) : EndIf
If KeyboardPushed(#PB_Key_Up) : NC_CameraLocate(@Camera, Camera\cx, Camera\cy + 10, Camera\cz) : EndIf
If KeyboardPushed(#PB_Key_Down) : NC_CameraLocate(@Camera, Camera\cx, Camera\cy - 10, Camera\cz) : EndIf
If KeyboardPushed(#PB_Key_Left) : NC_CameraLocate(@Camera, Camera\cx + 10, Camera\cy, Camera\cz) : EndIf
If KeyboardPushed(#PB_Key_Right) : NC_CameraLocate(@Camera, Camera\cx - 10, Camera\cy, Camera\cz) : EndIf
If MouseDeltaX() Or MouseDeltaY() : NC_CameraLookAt(@Camera, camera\cx + camera\ax + MouseDeltaX() / coef, camera\cy + camera\ay + MouseDeltaY() / coef, camera\cz + camera\az) : EndIf
If KeyboardPushed(#PB_Key_Pad9) : NC_CameraFocale(@Camera, Camera\P + 1) : EndIf
If KeyboardPushed(#PB_Key_Pad3) : NC_CameraFocale(@Camera, Camera\P - 1) : EndIf
If KeyboardPushed(#PB_Key_Pad7) : NC_CameraFOV(@Camera, ((360 * Camera\FOV) / #PI) + 2) : EndIf
If KeyboardPushed(#PB_Key_Pad8) : NC_CameraFOV(@Camera, ((360 * Camera\FOV) / #PI) - 2) : EndIf
If KeyboardPushed(#PB_Key_F1) : mode = 0 : EndIf
If KeyboardPushed(#PB_Key_F2) : mode = 1 : EndIf
If KeyboardPushed(#PB_Key_F3) : mode = 2 : EndIf
If KeyboardPushed(#PB_Key_Pad5) : NC_CameraLookAt(@Camera, 0, 0, 0) : EndIf
Delay(10)
ClearScreen(0)
If StartDrawing(ScreenOutput())
; MeasureHiResIntervalStart()
res = ElapsedMilliseconds()
; re = Display_3D(@Camera, @co(0), @triangle(0))
re = Display_3D(@Camera, @Sphere_pt(0), @Sphere_tr(0))
res = ElapsedMilliseconds() - res
; res.d = MeasureHiResIntervalStop()
DrawText(0, 0, StrD(res * 1000, 3) + " ms")
DrawText(0, 20, "Cam X = " + Str(camera\cx), #White, #Black)
DrawText(0, 40, "Cam Y = " + Str(camera\cy), #White, #Black)
DrawText(0, 60, "P = " + Str(camera\P), #White, #Black)
DrawText(0, 80, "nb points = " + Str(re), #White, #Black)
DrawText(0, 80, "nb triangles = " + Str(re), #White, #Black)
StopDrawing()
EndIf
FlipBuffers()
Until event = #PB_Event_CloseWindow Or KeyboardPushed(#PB_Key_Escape)
End
Essaye de recentré les Point2D après projection , càd que dès lors que tu as fait ta projection 3D->2DEt puis il y les déplacements de caméra qui sont bizarre : tout va en diagonale -_-
POINT 2D + TAILLE ECRAN / 2
Code : Tout sélectionner
tableau(a - 1)\x = *ca\ecran_centre_X + Bx * *ca\rapport
tableau(a - 1)\y = *ca\ecran_centre_Y + By * *ca\rapport
Code : Tout sélectionner
sizeofpt = SizeOf(pt)