
(et bien avant le PB ^^)
Donc j'ai voulu faire un chtit truc en 2D parce que ca faisait longtemps. C'est un tout début de petit moteur 3D plat

Il manque un tas de fonctions pour qu'on puisse parler de moteur et c'est sûr je vais pas concurencer OGRE


Bon bien sûr open source, si quelqu'un veut m'aider y'a plein de fonctions simples à faire (positions ,rotations, orientation, mouvements et j'en passe =)
Aussi j'ai fait quelque chose de "vectoriel" dans le sens où ca s'adapte directement à la surface de dessin

Code : Tout sélectionner
; > ---------------------------------------------------------------------- <
;-Triangle 3D par Dr. Dri
; > ---------------------------------------------------------------------- <
; > ---------------------- <
;-Triangle 3D : Déclarations <- la flemme pour le moment
; > ---------------------- <
Declare T3D_ObjetExiste(obj.l)
; > ---------------- <
;-Triangle 3D : Floats
; > ---------------- <
Procedure.f WrapValue(Angle.f) ;Merci DarkBasic :-)
Angle - Int(Angle / 360) * 360
If Angle < 0
Angle + 360
EndIf
ProcedureReturn Angle
EndProcedure
Procedure ClampF(Value.f, Min.f, Max.f) ;Merci Flype ^_^
If Value < Min : Value = Min : EndIf
If Value > Max : Value = Max : EndIf
ProcedureReturn Value
EndProcedure
; > ------------------- <
;-Triangle 3D : 2DDrawing
; > ------------------- <
Procedure.l IsDrawing()
!extrn _PB_2DDrawing_CurrentDC
!MOV eax, dword [_PB_2DDrawing_CurrentDC]
ProcedureReturn
EndProcedure
Procedure.l DrawingSurfaceWidth()
Protected Width.l, Box.Rect
If GetClipBox_(IsDrawing(), @Box)
Width = Box\right - Box\left
EndIf
ProcedureReturn Width
EndProcedure
Procedure.l DrawingSurfaceHeight()
Protected Height.l, Box.Rect
If GetClipBox_(IsDrawing(), @Box)
Height = Box\bottom - Box\top
EndIf
ProcedureReturn Height
EndProcedure
; > --------------------- <
;-Triangle 3D : DataSection
; > --------------------- <
DataSection
T3D_Cube_Points:
Data.f -0.5, -0.5, -0.5
Data.f -0.5, -0.5, 0.5
Data.f -0.5, 0.5, -0.5
Data.f -0.5, 0.5, 0.5
Data.f 0.5, -0.5, -0.5
Data.f 0.5, -0.5, 0.5
Data.f 0.5, 0.5, -0.5
Data.f 0.5, 0.5, 0.5
T3D_Cube_Faces:
Data.l 1, 3, 7
Data.l 1, 7, 5
Data.l 0, 4, 6
Data.l 0, 6, 2
Data.l 2, 6, 7
Data.l 2, 7, 3
Data.l 0, 1, 5
Data.l 0, 5, 4
Data.l 0, 2, 3
Data.l 0, 3, 1
Data.l 4, 5, 7
Data.l 4, 7, 6
EndDataSection
; > -------------------------- <
;-Triangle 3D : Types de données
; > -------------------------- <
Structure T3D_Point
;coordonnées dans l'espace objet
x.f
y.f
z.f
;coordonnées dans l'espace camera
cx.f
cy.f
cz.f
;coordonnées sur la surface de dessin
sx.l
sy.l
EndStructure
Structure T3D_Face
;liste des points
points.l[3]
;couleur de la face
r.b
g.b
b.b
;normale de la face dans l'espace camera
nx.f
ny.f
nz.f
;même taille que la structure T3D_Point =)
pad.b[SizeOf(T3D_Point) - 27]
EndStructure
Structure T3D_Objet
;coordonnées dans l'espace
x.f
y.f
z.f
;orientation dans l'espace
ax.f
ay.f
az.f
;taille de l'objet
sx.f
sy.f
sz.f
;coordonnées dans l'espace camera
cx.f
cy.f
cz.f
;orientation dans l'espace camera
cax.f
cay.f
caz.f
;propriétés spéciales
visible.l
;structure de l'objet
nb_points.l
nb_faces.l
StructureUnion
points.T3D_Point[0] ;c'est pour ça qu'il faut que ces
faces .T3D_Face [0] ;structures aient la même taille!
EndStructureUnion
EndStructure
Structure T3D_Camera
;coordonnées dans l'espace
x.f
y.f
z.f
;orientation dans l'espace
ax.f
ay.f
az.f
;champ de vision
fov.f
tan.f
distance.f
distance_max.f
;dimensions de la surface de dessin
l.l
h.l
EndStructure
; > ---------------------------------- <
;-Triangle 3D : Liste des objets globaux
; > ---------------------------------- <
NewList T3D_Objets.l()
Dim T3D_ZBuffer.f(0, 0)
; > ------------------------------ <
;-Triangle 3D : Fonctions des points
; > ------------------------------ <
;rien pour le moment
; > ----------------------------- <
;-Triangle 3D : Fonctions des faces
; > ----------------------------- <
Procedure T3D_CouleurFace(*obj.T3D_Objet, Face.l, r.l, g.l, b.l)
If Face >= 0 And T3D_ObjetExiste(*obj) And Face < *obj\nb_faces
Face + *obj\nb_points
*obj\faces[Face]\r = r
*obj\faces[Face]\g = g
*obj\faces[Face]\b = b
EndIf
EndProcedure
; > ------------------------------ <
;-Triangle 3D : Fonctions des objets
; > ------------------------------ <
Procedure.l T3D_CreerObjet(nPoints.l, pPoints.l, nFaces.l, pFaces.l)
Protected *obj.T3D_Objet, i.l, *f.Float, *l.Long
If nPoints > 3 And nFaces > 3 And pPoints And pFaces
i = nPoints + nFaces - 1
*obj = AllocateMemory( SizeOf(T3D_Objet) + i * SizeOf(T3D_Face) )
If *obj
*obj\nb_points = nPoints
*obj\nb_faces = nFaces
i = 0
*f = pPoints
*l = pFaces
While nPoints > 0
*obj\points[i]\x = *f\f : *f + SizeOf(Long)
*obj\points[i]\y = *f\f : *f + SizeOf(Long)
*obj\points[i]\z = *f\f : *f + SizeOf(Long)
i + 1
nPoints - 1
Wend
While nFaces > 0
*obj\faces[i]\points[0] = *l\l : *l + SizeOf(Float)
*obj\faces[i]\points[1] = *l\l : *l + SizeOf(Float)
*obj\faces[i]\points[2] = *l\l : *l + SizeOf(Float)
i + 1
nFaces - 1
Wend
*obj\visible = #True
AddElement( T3D_Objets() )
T3D_Objets() = *obj
EndIf
EndIf
ProcedureReturn *obj
EndProcedure
Procedure.l T3D_CreerObjetCube(x.f, y.f, z.f, Taille.f)
Protected *obj.T3D_Objet
*obj = T3D_CreerObjet(8, ?T3D_Cube_Points, 12, ?T3D_Cube_Faces)
If *obj
*obj\x = x
*obj\y = y
*obj\z = z
*obj\sx = Taille
*obj\sy = Taille
*obj\sz = Taille
EndIf
ProcedureReturn *obj
EndProcedure
Procedure.l T3D_ObjetExiste(obj.l)
Protected Existe.l
If obj And CountList( T3D_Objets() )
ResetList( T3D_Objets() )
While NextElement( T3D_Objets() ) And ~Existe
If T3D_Objets() = obj : Existe = #True : EndIf
Wend
EndIf
ProcedureReturn Existe
EndProcedure
Procedure T3D_RotationObjet(*obj.T3D_Objet, dax.f, day.f, daz.f)
If T3D_ObjetExiste(*obj)
*obj\ax + dax
*obj\ay + day
*obj\az + daz
EndIf
EndProcedure
Procedure T3D_CacherObjet(*obj.T3D_Objet, Cacher.l)
If T3D_ObjetExiste(*obj)
*obj\visible = (Cacher = 0) Or #False
EndIf
EndProcedure
Procedure T3D_TransformerObjet(*obj.T3D_Objet, *cam.T3D_Camera, cax.f, sax.f, cay.f, say.f, caz.f, saz.f)
Protected x.f, y.f, z.f, tx.f, ty.f, tz.f
Protected sx.l, sy.l, i.l
Protected ax.f, ay.f, az.f
;passage dans l'espace caméra
x = Abs(*obj\x - *cam\x)
y = Abs(*obj\y - *cam\y)
z = Abs(*obj\z - *cam\z)
;rotation autour de l'axe x
ty = y : tz = z
y = cax * ty - sax * tz
z = sax * ty + cax * tz
;rotation autour de l'axe y
tx = x : tz = z
x = say * tz + cay * tx
z = cay * tz - say * tx
;rotation autour de l'axe z
tx = x : ty = y
x = caz * tx - saz * ty
y = saz * tx + caz * ty
;translation
x + *cam\x
y + *cam\y
z + *cam\z
;mise à jour
*obj\cx = x
*obj\cy = y
*obj\cz = z
;orientation par rapport à la caméra
*obj\cax = *obj\ax + *cam\ax
*obj\cay = *obj\ay + *cam\ay
*obj\caz = *obj\az + *cam\az
;radians
ax = *obj\cax * 0.01745329
ay = *obj\cay * 0.01745329
az = *obj\caz * 0.01745329
;on en a fini avec ces variables
;mais on a un autre job pour elles ^^
cax = Cos(ax) : sax = Sin(ax)
cay = Cos(ay) : say = Sin(ay)
caz = Cos(az) : saz = Sin(az)
While i < *obj\nb_points
;mise à l'échelle
x = *obj\points[i]\x * *obj\sx
y = *obj\points[i]\y * *obj\sy
z = *obj\points[i]\z * *obj\sz
;rotation autour de l'axe x
ty = y : tz = z
y = cax * ty - sax * tz
z = sax * ty + cax * tz
;rotation autour de l'axe y
tx = x : tz = z
x = say * tz + cay * tx
z = cay * tz - say * tx
;rotation autour de l'axe z
tx = x : ty = y
x = caz * tx - saz * ty
y = saz * tx + caz * ty
;translation
x + *obj\cx
y + *obj\cy
z + *obj\cz
;mise à jour
*obj\points[i]\cx = x
*obj\points[i]\cy = y
*obj\points[i]\cz = z
;projection
*obj\points[i]\sx = *cam\l + *cam\distance * x / z
*obj\points[i]\sy = *cam\h - *cam\distance * y / z
i + 1
Wend
EndProcedure
Procedure T3D_RenduObjet(*obj.T3D_Objet)
Protected i.l, nFaces.l, visible.l, r.l, g.l, b.l
Protected x1.l, y1.l, x2.l, y2.l, x3.l, y3.l
i = *obj\nb_points
nFaces = *obj\nb_faces + i
While i < nFaces
x1 = *obj\points[ *obj\faces[i]\points[0] ]\sx
y1 = *obj\points[ *obj\faces[i]\points[0] ]\sy
x2 = *obj\points[ *obj\faces[i]\points[1] ]\sx
y2 = *obj\points[ *obj\faces[i]\points[1] ]\sy
x3 = *obj\points[ *obj\faces[i]\points[2] ]\sx
y3 = *obj\points[ *obj\faces[i]\points[2] ]\sy
visible = (x1 * y2) - (y1 * x2) + (x2 * y3) - (y2 * x3) + (x3 * y1) - (y3 * x1)
If visible < 0
r = *obj\faces[i]\r & $FF
g = *obj\faces[i]\g & $FF
b = *obj\faces[i]\b & $FF
;éclairage
;à venir
FrontColor(r, g, b)
Polygon_(IsDrawing(), @x1, 3)
EndIf
i + 1
Wend
EndProcedure
; > ------------------------------- <
;-Triangle 3D : Fonctions des caméras
; > ------------------------------- <
Procedure.l T3D_CreerCamera(FOV.f, DistanceMax.f)
Protected *cam.T3D_Camera
*cam = AllocateMemory( SizeOf(T3D_Camera) )
If *cam
FOV = WrapValue(FOV)
FOV = ClampF(FOV, 30, 90)
*cam\fov = FOV
*cam\tan = 1 / Tan(FOV * 0.00872664)
*cam\distance_max = Abs(DistanceMax)
EndIf
ProcedureReturn *cam
EndProcedure
Procedure T3D_RotationCamera(*cam.T3D_Camera, dax.f, day.f, daz.f)
;If T3D_CameraExiste(*cam)
*cam\ax + dax
*cam\ay + day
*cam\az + daz
;EndIf
EndProcedure
Procedure T3D_OrientationCamera(*cam.T3D_Camera, ax.f, ay.f, az.f)
;If T3D_CameraExiste(*cam)
*cam\ax = ax
*cam\ay = ay
*cam\az = az
;EndIf
EndProcedure
Procedure T3D_PositionCamera(*cam.T3D_Camera, x.f, y.f, z.f)
;If T3D_CameraExiste(*cam)
*cam\x = x
*cam\y = y
*cam\z = z
;EndIf
EndProcedure
Procedure.l T3D_RenduCamera(*cam.T3D_Camera)
Protected Rendu.l, *obj.T3D_Objet
Protected cax.f, sax.f, cay.f, say.f, caz.f, saz.f, ax.f, ay.f, az.f
If *cam And CountList( T3D_Objets() ) And IsDrawing()
;radians
ax = *cam\ax * 0.01745329
ay = *cam\ay * 0.01745329
az = *cam\az * 0.01745329
;on en a fini avec ces variables
;mais on a un autre job pour elles ^^
cax = Cos(ax) : sax = Sin(ax)
cay = Cos(ay) : say = Sin(ay)
caz = Cos(az) : saz = Sin(az)
;calibre la caméra sur la surface de dessin
*cam\l = DrawingSurfaceWidth ()
*cam\h = DrawingSurfaceHeight()
;Dim T3D_ZBuffer(*cam\l, *cam\h)
*cam\l / 2
*cam\h / 2
*cam\distance = *cam\l * *cam\tan
;place les objets dans l'espace camera
ForEach T3D_Objets()
*obj = T3D_Objets()
If *obj\visible
T3D_TransformerObjet(*obj, *cam, cax, sax, cay, say, caz, saz)
Else
*obj\cz = *cam\distance_max
EndIf
Next
;trie les objets
ForEach T3D_Objets()
*obj = T3D_Objets()
Next
;affiche les objets
ForEach T3D_Objets()
*obj = T3D_Objets()
If *obj\cz >= 0
If *obj\visible
T3D_RenduObjet(*obj)
EndIf
If *obj\cz >= *cam\distance_max : Break : EndIf
EndIf
Next
Rendu = #True
EndIf
ProcedureReturn Rendu
EndProcedure
;-test
cam1 = T3D_CreerCamera(60, 400)
cam2 = T3D_CreerCamera(60, 400)
cam3 = T3D_CreerCamera(60, 400)
cam4 = T3D_CreerCamera(60, 400)
cube1 = T3D_CreerObjetCube(10, 0, 100, 10)
cube2 = T3D_CreerObjetCube(10, 0, 40, 10)
;initialisation des "vues"
T3D_PositionCamera (cam2, 0, 50, 120)
T3D_OrientationCamera(cam2, 90, 0, 0)
T3D_PositionCamera (cam3, 40, 0, 100)
T3D_OrientationCamera(cam3, 0, -90, 0)
T3D_PositionCamera (cam4, 20, 50, 0)
T3D_OrientationCamera(cam4, 45, -45, 0)
i = 0
While i < 12
i + 2
If (i/2) & %001 : r = 1 : Else : r = 0 : EndIf
If (i/2) & %010 : g = 1 : Else : g = 0 : EndIf
If (i/2) & %100 : b = 1 : Else : b = 0 : EndIf
i - 2
T3D_CouleurFace(cube1, i, b*$80, g*$80, r*$80)
T3D_CouleurFace(cube2, i, r*$FF, b*$FF, g*$FF)
i + 1
Wend
InitSprite()
InitKeyboard()
ExamineDesktops()
w = DesktopWidth(0)
h = DesktopHeight(0)
d = DesktopDepth(0)
OpenScreen(w, h, d, "T3D")
CreateSprite(0, w/2, h/2)
w/2
h/2
depart = ElapsedMilliseconds()
Repeat
ExamineKeyboard()
duree = ElapsedMilliseconds() - depart
depart = ElapsedMilliseconds()
;Test
;T3D_RotationCamera(cam1, 0, 0, duree*0.05)
;T3D_RotationObjet (cube2, 0, 0, -duree*0.05)
If KeyboardPushed(#PB_Key_Space)
T3D_RotationObjet(cube1, duree*0.05, duree*0.15, duree*0.10)
T3D_RotationObjet(cube2, duree*0.20, duree*0.25, duree*0.15)
EndIf
If StartDrawing( SpriteOutput(0) )
Box(0, 0, w, h, $000000)
T3D_RenduCamera(cam1)
FrontColor(0, 0 ,0)
DrawText("Vue de face")
StopDrawing()
EndIf
DisplaySprite(0, 0, h)
If StartDrawing( SpriteOutput(0) )
Box(0, 0, w, h, $000000)
T3D_RenduCamera(cam2)
FrontColor(0, 0 ,0)
DrawText("Vue de dessus")
StopDrawing()
EndIf
DisplaySprite(0, 0, 0)
If StartDrawing( SpriteOutput(0) )
Box(0, 0, w, h, $000000)
T3D_RenduCamera(cam3)
FrontColor(0, 0 ,0)
DrawText("Vue de côté")
StopDrawing()
EndIf
DisplaySprite(0, w, 0)
If StartDrawing( SpriteOutput(0) )
Box(0, 0, w, h, $000000)
T3D_RenduCamera(cam4)
FrontColor(0, 0 ,0)
DrawText("Vue en perspective")
StopDrawing()
EndIf
DisplaySprite(0, w, h)
If StartDrawing( ScreenOutput() )
LineXY(w, 0, w, h*2, $FFFFFF)
LineXY(0, h, w*2, h, $FFFFFF)
StopDrawing()
EndIf
If KeyboardPushed(#PB_Key_C)
If PB_Key_C = 0
PB_Key_C = 1
cacher = ~cacher & 1
T3D_CacherObjet(cube2, cacher)
EndIf
Else
PB_Key_C = 0
EndIf
FlipBuffers(0)
Until KeyboardPushed(#PB_Key_Escape)
Dri
