Je suis ravis que ça vous plaise, si vous voulez on peut essayer de développer un petit moteur sympas à partir de ce début de moteur et de ce que vous avez fait de votre coté.
Bon je vous donne les sources mais je vous préviens ce n’est ni commenté (à part 2 ou 3 procédures), ni harmonisé (des procédures similaires n’ont pas exactement les mêmes arguments), ni super optimisé (mais quand même un peu).
Voila le code source (il est relativement ralongé par des fonctions redondantes) :
Pour l'instant je passe par un tableau pour la texture mais c'est temporaire. Certaines choses ne sont pas optimisées pour être plus simple à comprendre et parceque les structures ne sont définitives (notament des variables utilisées à la place de constantes).
Encore deux petites choses à ajouter : les facettes sont pour le moment triées par entité, il faudrait les trier à la fin pour avoir un affichage plus réaliste (et ne pas du tout les trier et implémenter le Z-buffer pour encore plus de réalisme), et les lumières semblent un brin foireuses.
Et voilà le code du chargeur de .asc (le format ascii de 3DSM) :
Code : Tout sélectionner
; Chargeur de fichiers .ASC - Par Gratteur - 2007
Procedure SommetsASC(fichier, nb_sommets, *sommets.SommetObjet, texture.b)
Protected txt.s, pos
For k=0 To nb_sommets-1
txt = ReadString(fichier)
If Left(txt, 6) = "Vertex"
pos = FindString(txt, "X", 12)+3
*sommets\x = ValF(StringField(Mid(txt, pos, 20), 1, " "))
pos = FindString(txt, "Y", pos)+3
*sommets\y = ValF(StringField(Mid(txt, pos, 20), 1, " "))
pos = FindString(txt, "Z", pos)+3
*sommets\z = ValF(StringField(Mid(txt, pos, 20), 1, " "))
If texture
pos = FindString(txt, "U", pos)+3
*sommets\u = ValF(StringField(Mid(txt, pos, 20), 1, " "))*ltexture
pos = FindString(txt, "V", pos)+3
*sommets\v = ValF(StringField(Mid(txt, pos, 20), 1, " "))*htexture
EndIf
*sommets+sizeof\sommetobjet
Else
k-1
EndIf
If Eof(fichier)
Break
EndIf
Next k
EndProcedure
Procedure FacettesASC(fichier, nb_facettes, *facettes.FacetteObjet)
Protected txt.s
For k=0 To nb_facettes-1
txt = ReadString(fichier)
If Left(txt, 4) = "Face"
txt = Right(txt, Len(txt)-(10+Len(Str(k))))
*facettes\a = Val(Mid(StringField(txt, 1, " "), 3, 5))
*facettes\b = Val(Mid(StringField(txt, 2, " "), 3, 5))
*facettes\c = Val(Mid(StringField(txt, 3, " "), 3, 5))
*facettes\ab = Val(Mid(StringField(txt, 4, " "), 4, 5))
*facettes\bc = Val(Mid(StringField(txt, 5, " "), 4, 5))
*facettes\ca = Val(Mid(StringField(txt, 6, " "), 4, 5))
*facettes+sizeof\facetteobjet
Else
k-1
EndIf
If Eof(fichier)
Break
EndIf
Next k
EndProcedure
Procedure ChargerASC(nom.s)
Protected *resultat, *mem, fichier, txt.s, nb_sommets, nb_facettes, texture.b
fichier = ReadFile(#PB_Any, nom)
If fichier
While Eof(fichier) = 0
If Left(ReadString(fichier), 12) = "Named object"
Repeat
txt = ReadString(fichier)
nb_sommets = FindString(txt, "Vertices", 0)
nb_facettes = FindString(txt, "Faces", 0)
Until (nb_sommets And nb_facettes) Or Eof(fichier)
If nb_sommets And nb_facettes
nb_sommets+10
nb_sommets = Val(Trim(Mid(txt, nb_sommets, nb_facettes-nb_sommets)))
nb_facettes+7
nb_facettes = Val(Trim(Mid(txt, nb_facettes, Len(txt)+1-nb_facettes)))
If nb_sommets And nb_facettes
Repeat
txt = ReadString(fichier)
If Left(txt, 6) = "Mapped"
texture = #True
txt = ReadString(fichier)
Break
EndIf
Until Left(txt, 11) = "Vertex list" Or Eof(fichier)
If Eof(fichier) = 0
*resultat = AllocateMemory(sizeof\resultatASC+nb_sommets*sizeof\sommetobjet+nb_facettes*sizeof\facetteobjet)
If *resultat
*mem = *resultat
PokeL(*mem, nb_sommets) : *mem+4
PokeL(*mem, nb_facettes) : *mem+4
Repeat
If Left(txt, 11) = "Vertex list"
SommetsASC(fichier, nb_sommets, *mem, texture) : *mem+nb_sommets*sizeof\sommetobjet
Break
EndIf
txt = ReadString(fichier)
Until Eof(fichier)
Repeat
If Left(ReadString(fichier), 9) = "Face list"
FacettesASC(fichier, nb_facettes, *mem) ; *mem+nb_facettes*sizeof\facetteobjet
Break
EndIf
Until Eof(fichier)
EndIf
EndIf
EndIf
Break
EndIf
EndIf
Wend
CloseFile(fichier)
EndIf
ProcedureReturn *resultat
EndProcedure
C'est carrément fait à la va vite et ça ne charge que le premier objet du fichier pour les besoins du fichier.
On peut encore beaucoup accélérer tout ça en travaillant directement dans le buffer vidéo et non avec la fonction plot().
Bon je retourne à mes révisions et je regarde ton moteur demain Cpl.Bator. ++
ps : Pour lire facilement le code je vous conseille de commencer par les fonctions :
- LoadObject()
- NewEntity()
- Projection()
- DisplaySommets()
Et ensuite de remonter les différents types d'affichage.
Mais vous pouvez aussi commencer par un cube :
Code : Tout sélectionner
; Cube3D - Par Gratteur - 2007
Global fps
#largeur = 800
#hauteur = 600
#noir = 0
#rouge = 255
#blanc = 16777215
#CPI = 0.017453292
Structure Sommet
x.w
y.w
z.w
xy.l
EndStructure
Structure Point3D
x.w
y.w
z.w
EndStructure
Structure Point2D
x.w
y.w
EndStructure
Structure Objet3D
nb_points.l
sommet.l
point3D.l
point2D.l
EndStructure
Global cube1.Objet3D, Dim cube1p2D.Point2D(8), Dim cube1p3D.Point3D(8), Dim cube1s.Sommet(8)
Procedure InitGameTimer()
Shared _GT_DevCaps.timecaps
timeGetDevCaps_(_GT_DevCaps,SizeOf(timecaps))
timeBeginPeriod_(_GT_DevCaps\wperiodmin)
EndProcedure
Procedure StopGameTimer()
Shared _GT_DevCaps.timecaps
timeEndPeriod_(_GT_DevCaps\wperiodmin)
EndProcedure
Procedure Timer()
Static sfps, images, timer
Protected t = timeGetTime_()
If t-timer >= 1000
timer = t
fps = images-1
images = 1
If fps < 0
fps = 0
EndIf
Else
images+1
EndIf
EndProcedure
Procedure DisplayFPS()
Box(4, 6, 48, 14, #blanc)
DrawingMode(#PB_2DDrawing_Outlined)
Box(3, 5, 50, 16, 0)
DrawingMode(#PB_2DDrawing_Transparent)
If fps < 10
DrawText(5, 5, " "+Str(fps)+ " FPS", 0)
Else
DrawText(5, 5, Str(fps)+ " FPS", 0)
EndIf
DrawingMode(#PB_2DDrawing_Default)
EndProcedure
Procedure Ligne(p1, p2, point2D.Point2D(1))
LineXY(point2D(p1)\x, point2D(p1)\y, point2D(p2)\x, point2D(p2)\y)
EndProcedure
Procedure FilDeFerCube1(point2D.Point2D(1))
Ligne(0,1,point2D()) : Ligne(1,2,point2D()) : Ligne(2,3,point2D()) : Ligne(3,0,point2D())
Ligne(4,5,point2D()) : Ligne(5,6,point2D()) : Ligne(6,7,point2D()) : Ligne(7,4,point2D())
Ligne(0,5,point2D()) : Ligne(1,4,point2D()) : Ligne(2,7,point2D()) : Ligne(3,6,point2D())
EndProcedure
Procedure SommetCube1(point2D.Point2D(1))
For i=0 To 7
If point2D(i)\x >= 0 And point2D(i)\y >= 0 And point2D(i)\x < #largeur And point2D(i)\y < #hauteur
Plot(point2D(i)\x, point2D(i)\y)
EndIf
Next i
EndProcedure
Procedure ProjectionCube1(point2D.Point2D(1), point3D.Point3D(1))
Protected xoff = 400, yoff = 300, zoff = 300, d = 8, div
For i=0 To 7
div = point3D(i)\z+zoff
point2D(i)\x = (point3D(i)\x<<d)/div + xoff
point2D(i)\y = (point3D(i)\y<<d)/div + yoff
Next i
EndProcedure
Procedure InitialiserCube1()
cube1s(0)\x = -100 : cube1s(0)\y = -100 : cube1s(0)\z = -100
cube1s(1)\x = 100 : cube1s(1)\y = -100 : cube1s(1)\z = -100
cube1s(2)\x = 100 : cube1s(2)\y = 100 : cube1s(2)\z = -100
cube1s(3)\x = -100 : cube1s(3)\y = 100 : cube1s(3)\z = -100
cube1s(4)\x = 100 : cube1s(4)\y = -100 : cube1s(4)\z = 100
cube1s(5)\x = -100 : cube1s(5)\y = -100 : cube1s(5)\z = 100
cube1s(6)\x = -100 : cube1s(6)\y = 100 : cube1s(6)\z = 100
cube1s(7)\x = 100 : cube1s(7)\y = 100 : cube1s(7)\z = 100
For i=0 To 7
cube1s(i)\xy = -(cube1s(i)\x*cube1s(i)\y)
cube1p3D(i)\x = cube1s(i)\x
cube1p3D(i)\y = cube1s(i)\y
cube1p3D(i)\z = cube1s(i)\z
Next i
cube1\nb_points = 8
cube1\sommet = @cube1s()
cube1\point3D = @cube1p3D()
cube1\point2D = @cube1p2D()
ProjectionCube1(cube1p2D(), cube1p3D())
EndProcedure
Procedure Rotation(x.f, y.f, z.f, point3D.Point3D(1), sommet.Sommet(1))
Protected Dim a.f(3), Dim matrice.f(3,3)
x*#CPI : y*#CPI : z*#CPI
matrice(0,0) = Cos(z)*Cos(y)
matrice(1,0) = Sin(z)*Cos(y)
matrice(2,0) = -Sin(y)
matrice(0,1) = Cos(z)*Sin(y)*Sin(x) - Sin(z)*Cos(x)
matrice(1,1) = Sin(z)*Sin(y)*Sin(x) + Cos(x)*Cos(z)
matrice(2,1) = Sin(x)*Cos(y)
matrice(0,2) = Cos(z)*Sin(y)*Cos(x) + Sin(z)*Sin(x)
matrice(1,2) = Sin(z)*Sin(y)*Cos(x) - Cos(z)*Sin(x)
matrice(2,2) = Cos(x)*Cos(y)
a(0) = -(matrice(0,1)*matrice(0,0))
a(1) = -(matrice(1,1)*matrice(1,0))
a(2) = -(matrice(2,1)*matrice(2,0))
For i=0 To 7
point3D(i)\x = (matrice(0,1)+sommet(i)\x)*(matrice(0,0)+sommet(i)\y) + a(0)+sommet(i)\xy + matrice(0,2)*sommet(i)\z
point3D(i)\y = (matrice(1,1)+sommet(i)\x)*(matrice(1,0)+sommet(i)\y) + a(1)+sommet(i)\xy + matrice(1,2)*sommet(i)\z
point3D(i)\z = (matrice(2,1)+sommet(i)\x)*(matrice(2,0)+sommet(i)\y) + a(2)+sommet(i)\xy + matrice(2,2)*sommet(i)\z
Next i
EndProcedure
Procedure Initialisation()
Protected op = #PB_Window_Invisible|#PB_Window_SystemMenu|#PB_Window_TitleBar|#PB_Window_ScreenCentered
OpenWindow(0, 0, 0, #largeur, #hauteur, "Moteur 3D", op)
InitSprite()
OpenWindowedScreen(WindowID(0), 0, 0, #largeur, #hauteur, 0, 0, 0)
SetFrameRate(60)
InitGameTimer()
HideWindow(0, 0)
InitialiserCube1()
EndProcedure
Procedure Main()
Protected image, ax, ay, az
Repeat
If image = 1
image = 0
ax = (ax+1)%360
ay = (ay+2)%360
az = (az+1)%360
Rotation(ax,ay,az,cube1p3D(),cube1s())
ProjectionCube1(cube1p2D(),cube1p3D())
Else
image+1
EndIf
ClearScreen(#noir)
If StartDrawing(ScreenOutput())
FrontColor(#blanc)
;SommetCube1(cube1p2D())
FilDeFerCube1(cube1p2D())
DisplayFPS()
StopDrawing()
EndIf
FlipBuffers()
Timer()
Delay(1)
Until WindowEvent() = #PB_Event_CloseWindow
EndProcedure
Procedure Quitter()
StopGameTimer()
End
EndProcedure
Initialisation()
Main()
Quitter()