Publié : mar. 24/avr./2007 21:34
J'ai pas pu m'empécher ^^
voici une mouture de code qui t'aidera sans aucun doute :
Le code est long, mais il manque pas mal de chose, comme la gestion des faces et autres joyeustés
Donc pour faire simple :
se code est réutilisable ( les fonctions et structures ) je te laisse l'amelliorer
Ce pseudo moteur possède un "Pipeline" primaire qui regroupe tout les mesh passé en paramètre de la fonction MeshProjection()
ce pipeline est sous forme de liste chainée , ce pipeline est appelé lors du rendu avec l'appel de CameraRendering() , et ensuite ce pipeline est remis à zero en attente de nouveaux mesh à afficher.
Se pipeline ne gère pas le clipping , càd tout ce qui se trouve derrière la camera sera rendu quand meme, a toi de rajouté une condition basic lors de l'affichage du " Circle()" : if 3DZ>0 ou 3DZ<0 , comme tu veut...
Pour la théorie, tu remarqueras que chaque mesh possède ses propres matrices, rotation , translation,mise a l'échelle etc...
on calcul dans un premier temps les coordonées des vertices suivant ces matrices de transformation, ensuite on envois le mesh dans le pipeline.
La caméra quand à elle , récupère tout ce qui sort du pipeline, puis recalcule à nouveau les vertices dans l'espace 3D suivant ses propres matrices de transformations, et il n'y a plus qu'a convertir les vertices en coordonées 2D puis de les affichés à l'écran
Vouali
@++
voici une mouture de code qui t'aidera sans aucun doute :
Code : Tout sélectionner
Global SCREEN_W.l=800
Global SCREEN_H.l=600
;-STRUCT
Structure VECTOR3
x.f : y.f : z.f
EndStructure
Structure MATRIX4x4
_11.f : _21.f : _31.f : _41.f
_12.f : _22.f : _32.f : _42.f
_13.f : _23.f : _33.f : _43.f
_14.f : _24.f : _34.f : _44.f
EndStructure
Structure FACES
_A.l : _B.l : _C.l
AB.l : BC.l : CA.l
EndStructure
Structure MESH
*Sommets_List.l
*Point3D_List.l
*Point2D_List.l
*Face_List.l
Nbr_Vertice.l
Position.VECTOR3
Rotation.VECTOR3
ScaleFactor.f
Mat_Projection.MATRIX4x4
Mat_Rotation.MATRIX4x4
Mat_Translate.MATRIX4x4
Mat_Scale.MATRIX4x4
Mat_Identity.MATRIX4x4
EndStructure
Structure CAMERA
Position.VECTOR3
Rotation.VECTOR3
Mat_Projection.MATRIX4x4
Mat_Rotation.MATRIX4x4
Mat_Translate.MATRIX4x4
Mat_Scale.MATRIX4x4
Mat_Identity.MATRIX4x4
EndStructure
Global NewList PipeLine.l()
;-MATRICES PROCS
Procedure MATRICE_ROTATE(*MATRICE.MATRIX4x4 , Xa.f,Ya.f,Za.f)
*MATRICE\_11 = Cos(Za)*Cos(Ya) : *MATRICE\_21 = Sin(Za)*Cos(Ya) : *MATRICE\_31 = -Sin(Ya) : *MATRICE\_41 = 0
*MATRICE\_12 = Cos(Za)*Sin(Ya)*Sin(Xa) - Sin(Za)*Cos(Xa) : *MATRICE\_22 = Sin(Za)*Sin(Ya)*Sin(Xa) + Cos(Xa)*Cos(Za) : *MATRICE\_32 = Sin(Xa)*Cos(Ya) : *MATRICE\_42 = 0
*MATRICE\_13 = Cos(Za)*Sin(Ya)*Cos(Xa) + Sin(Za)*Sin(Xa) : *MATRICE\_23 = Sin(Za)*Sin(Ya)*Cos(Xa) - Cos(Za)*Sin(Xa) : *MATRICE\_33 = Cos(Xa)*Cos(Ya) : *MATRICE\_43 = 0
*MATRICE\_14 = 0 : *MATRICE\_24 = 0 : *MATRICE\_34 = 0 : *MATRICE\_44 = 1
EndProcedure
Procedure MATRICE_ROTATE_X(*MATRICE.MATRIX4x4,Angle.f)
*MATRICE\_11 = 1 : *MATRICE\_21 = 0 : *MATRICE\_31 = 0 : *MATRICE\_41 = 0
*MATRICE\_12 = 0 : *MATRICE\_22 = Cos(Angle) : *MATRICE\_32 = -Sin(Angle) : *MATRICE\_42 = 0
*MATRICE\_13 = 0 : *MATRICE\_23 = Sin(Angle) : *MATRICE\_33 = Cos(Angle) : *MATRICE\_43 = 0
*MATRICE\_14 = 0 : *MATRICE\_24 = 0 : *MATRICE\_34 = 0 : *MATRICE\_44 = 1
EndProcedure
Procedure MATRICE_ROTATE_Y(*MATRICE.MATRIX4x4,Angle.f)
*MATRICE\_11 = Cos(Angle) : *MATRICE\_21 = 0 : *MATRICE\_31 = -Sin(Angle) : *MATRICE\_41 = 0
*MATRICE\_12 = 0 : *MATRICE\_22 = 1 : *MATRICE\_32 = 0 : *MATRICE\_42 = 0
*MATRICE\_13 = Sin(Angle) : *MATRICE\_23 = 0 : *MATRICE\_33 = Cos(Angle) : *MATRICE\_43 = 0
*MATRICE\_14 = 0 : *MATRICE\_24 = 0 : *MATRICE\_34 = 0 : *MATRICE\_44 = 1
EndProcedure
Procedure MATRICE_ROTATE_Z(*MATRICE.MATRIX4x4,Angle.f)
*MATRICE\_11 = Cos(Angle) : *MATRICE\_21 = -Sin(Angle): *MATRICE\_31 = 0 : *MATRICE\_41 = 0
*MATRICE\_12 = Sin(Angle) : *MATRICE\_22 = Cos(Angle) : *MATRICE\_32 = 0 : *MATRICE\_42 = 0
*MATRICE\_13 = 0 : *MATRICE\_23 = 0 : *MATRICE\_33 = 1 : *MATRICE\_43 = 0
*MATRICE\_14 = 0 : *MATRICE\_24 = 0 : *MATRICE\_34 = 0 : *MATRICE\_44 = 1
EndProcedure
Procedure MATRICE_SCALE(*MATRICE.MATRIX4x4,Factor.f)
*MATRICE\_11 * Factor
*MATRICE\_22 * Factor
*MATRICE\_33 * Factor
*MATRICE\_44 * Factor
EndProcedure
Procedure MATRICE_SCALEXYZ(*MATRICE.MATRIX4x4,xFactor.f,yFactor.f,zFactor.f)
*MATRICE\_11 * xFactor
*MATRICE\_22 * yFactor
*MATRICE\_33 * zFactor
*MATRICE\_44 * 1
EndProcedure
Procedure MATRICE_TRANSLATE(*MATRICE.MATRIX4x4 , x.f,y.f,z.f)
Global V.VECTOR3
*MATRICE\_11 = 1 : *MATRICE\_21 = 0 : *MATRICE\_31 = 0 : *MATRICE\_41 = x
*MATRICE\_12 = 0 : *MATRICE\_22 = 1 : *MATRICE\_32 = 0 : *MATRICE\_42 = y
*MATRICE\_13 = 0 : *MATRICE\_23 = 0 : *MATRICE\_33 = 1 : *MATRICE\_43 = z
*MATRICE\_14 = 0 : *MATRICE\_24 = 0 : *MATRICE\_34 = 0 : *MATRICE\_44 = 1
V\x=*MATRICE\_41
V\y=*MATRICE\_42
V\z=*MATRICE\_43
EndProcedure
Procedure MATRICE_MULTIPLY(*m1.MATRIX4x4,*m2.MATRIX4x4,*MatriceF.MATRIX4x4)
*MatriceF\_11 = *m1\_11 * *m2\_11 + *m1\_12 * *m2\_21 + *m1\_13 * *m2\_31 + *m1\_14 * *m2\_41
*MatriceF\_12 = *m1\_11 * *m2\_12 + *m1\_12 * *m2\_22 + *m1\_13 * *m2\_32 + *m1\_14 * *m2\_42
*MatriceF\_13 = *m1\_11 * *m2\_13 + *m1\_12 * *m2\_23 + *m1\_13 * *m2\_33 + *m1\_14 * *m2\_43
*MatriceF\_14 = *m1\_11 * *m2\_14 + *m1\_12 * *m2\_24 + *m1\_13 * *m2\_34 + *m1\_14 * *m2\_44
*MatriceF\_21 = *m1\_21 * *m2\_11 + *m1\_22 * *m2\_21 + *m1\_23 * *m2\_31 + *m1\_24 * *m2\_41
*MatriceF\_22 = *m1\_21 * *m2\_12 + *m1\_22 * *m2\_22 + *m1\_23 * *m2\_32 + *m1\_24 * *m2\_42
*MatriceF\_23 = *m1\_21 * *m2\_13 + *m1\_22 * *m2\_23 + *m1\_23 * *m2\_33 + *m1\_24 * *m2\_43
*MatriceF\_24 = *m1\_21 * *m2\_14 + *m1\_22 * *m2\_24 + *m1\_23 * *m2\_34 + *m1\_24 * *m2\_44
*MatriceF\_31 = *m1\_31 * *m2\_11 + *m1\_32 * *m2\_21 + *m1\_33 * *m2\_31 + *m1\_34 * *m2\_41
*MatriceF\_32 = *m1\_31 * *m2\_12 + *m1\_32 * *m2\_22 + *m1\_33 * *m2\_32 + *m1\_34 * *m2\_42
*MatriceF\_33 = *m1\_31 * *m2\_13 + *m1\_32 * *m2\_23 + *m1\_33 * *m2\_33 + *m1\_34 * *m2\_43
*MatriceF\_34 = *m1\_31 * *m2\_14 + *m1\_32 * *m2\_24 + *m1\_33 * *m2\_34 + *m1\_34 * *m2\_44
*MatriceF\_41 = *m1\_41 * *m2\_11 + *m1\_42 * *m2\_21 + *m1\_43 * *m2\_31 + *m1\_44 * *m2\_41
*MatriceF\_42 = *m1\_41 * *m2\_12 + *m1\_42 * *m2\_22 + *m1\_43 * *m2\_32 + *m1\_44 * *m2\_42
*MatriceF\_43 = *m1\_41 * *m2\_13 + *m1\_42 * *m2\_23 + *m1\_43 * *m2\_33 + *m1\_44 * *m2\_43
*MatriceF\_44 = *m1\_41 * *m2\_14 + *m1\_42 * *m2\_24 + *m1\_43 * *m2\_34 + *m1\_44 * *m2\_44
EndProcedure
Procedure MATRICE_ADD(*m1.MATRIX4x4,*m2.MATRIX4x4)
*m1\_11 = *m1\_11 + *m2\_11
*m1\_12 = *m1\_12 + *m2\_12
*m1\_13 = *m1\_13 + *m2\_13
*m1\_14 = *m1\_14 + *m2\_14
*m1\_21 = *m1\_21 + *m2\_21
*m1\_22 = *m1\_22 + *m2\_22
*m1\_23 = *m1\_23 + *m2\_23
*m1\_24 = *m1\_24 + *m2\_24
*m1\_31 = *m1\_31 + *m2\_31
*m1\_32 = *m1\_32 + *m2\_32
*m1\_33 = *m1\_33 + *m2\_33
*m1\_34 = *m1\_34 + *m2\_34
*m1\_41 = *m1\_41 + *m2\_41
*m1\_42 = *m1\_42 + *m2\_42
*m1\_43 = *m1\_43 + *m2\_43
*m1\_44 = *m1\_44 + *m2\_44
EndProcedure
;-MESHS PROCS
Procedure CreateEmptyMesh()
*Mesh.MESH = AllocateMemory(SizeOf(MESH))
ProcedureReturn *Mesh
EndProcedure
Procedure AllocateVertex(*Mesh.MESH,Number)
*Mesh\Sommets_List = AllocateMemory(SizeOf(VECTOR3)*Number+SizeOf(VECTOR3))
*Mesh\Point3D_List = AllocateMemory(SizeOf(VECTOR3)*Number+SizeOf(VECTOR3))
*Mesh\Point2D_List = AllocateMemory(SizeOf(POINT)*Number+SizeOf(POINT))
*Mesh\Nbr_Vertice = Number
EndProcedure
Procedure AllocateFace(*Mesh.MESH,Number)
*Mesh\Face_List = AllocateMemory(SizeOf(FACES)*Number+SizeOf(FACES))
EndProcedure
Procedure SET_VERTEX(*Mesh.MESH,Vertex,x.f,y.f,z.f)
PokeF( *Mesh\Sommets_List+((Vertex*SizeOf(VECTOR3))+0),x)
PokeF( *Mesh\Sommets_List+((Vertex*SizeOf(VECTOR3))+4),y)
PokeF( *Mesh\Sommets_List+((Vertex*SizeOf(VECTOR3))+8),z)
EndProcedure
Procedure.f GET_VERTEX(*Mesh.MESH,Vertex,Axis)
Select Axis
Case 0 : ProcedureReturn PeekF(*Mesh\Sommets_List+((Vertex*SizeOf(VECTOR3))+0))
Case 1 : ProcedureReturn PeekF(*Mesh\Sommets_List+((Vertex*SizeOf(VECTOR3))+4))
Case 2 : ProcedureReturn PeekF(*Mesh\Sommets_List+((Vertex*SizeOf(VECTOR3))+8))
EndSelect
EndProcedure
Procedure SET_POINT2D(*Mesh.MESH,Vertex,x.f,y.f)
If Vertex<=*Mesh\Nbr_Vertice
PokeF(*Mesh\Point2D_List+(Vertex*8)+0,x)
PokeF(*Mesh\Point2D_List+(Vertex*8)+4,y)
EndIf
EndProcedure
Procedure.f GET_POINT2D(*Mesh.MESH,Vertex,Axis)
Select Axis
Case 0 : ProcedureReturn PeekF(*Mesh\Point2D_List+((Vertex*8)+0))
Case 1 : ProcedureReturn PeekF(*Mesh\Point2D_List+((Vertex*8)+4))
EndSelect
EndProcedure
Procedure SET_POINT3D(*Mesh.MESH,Vertex,x.f,y.f,z.f)
If Vertex<=*Mesh\Nbr_Vertice
PokeF(*Mesh\Point3D_List+(Vertex*SizeOf(VECTOR3))+0,x)
PokeF(*Mesh\Point3D_List+(Vertex*SizeOf(VECTOR3))+4,y)
PokeF(*Mesh\Point3D_List+(Vertex*SizeOf(VECTOR3))+8,z)
EndIf
EndProcedure
Procedure.f GET_POINT3D(*Mesh.MESH,Vertex,Axis)
Select Axis
Case 0 : ProcedureReturn PeekF(*Mesh\Point3D_List+((Vertex*SizeOf(VECTOR3))+0))
Case 1 : ProcedureReturn PeekF(*Mesh\Point3D_List+((Vertex*SizeOf(VECTOR3))+4))
Case 2 : ProcedureReturn PeekF(*Mesh\Point3D_List+((Vertex*SizeOf(VECTOR3))+8))
EndSelect
EndProcedure
Procedure VERTEX_EXIST(*Mesh.MESH,Vertex)
If Vertex<=*Mesh\Nbr_Vertice
ProcedureReturn 1
Else
ProcedureReturn -1
EndIf
EndProcedure
Procedure MeshPosition(*Mesh.MESH,x.f,y.f,z.f)
*Mesh\Position\x=x
*Mesh\Position\y=y
*Mesh\Position\z=z
EndProcedure
Procedure MeshRotation(*Mesh.MESH,x.f,y.f,z.f)
*Mesh\Rotation\x=x
*Mesh\Rotation\y=y
*Mesh\Rotation\z=z
EndProcedure
Procedure Meshscale(*Mesh.MESH,Factor.f)
*Mesh\ScaleFactor = Factor
EndProcedure
Procedure MeshProjection(*Mesh.MESH)
AddElement(PipeLine())
PipeLine() = *Mesh
With *Mesh
MATRICE_TRANSLATE(\Mat_Translate,\Position\x,\Position\y,\Position\z)
MATRICE_ROTATE(\Mat_Rotation,\Rotation\x,\Rotation\y,\Rotation\z)
MATRICE_SCALE(\Mat_Translate,\ScaleFactor)
MATRICE_MULTIPLY(\Mat_Rotation,\Mat_Translate,\Mat_Projection)
For Vx = 1 To \Nbr_Vertice
VERTEXx.f = GET_VERTEX(*Mesh,Vx,0)
VERTEXy.f = GET_VERTEX(*Mesh,Vx,1)
VERTEXz.f = GET_VERTEX(*Mesh,Vx,2)
POINT3Dx.f = \Mat_Projection\_11*VERTEXx + \Mat_Projection\_21*VERTEXy + \Mat_Projection\_31*VERTEXz + \Mat_Projection\_41
POINT3Dy.f = \Mat_Projection\_12*VERTEXx + \Mat_Projection\_22*VERTEXy + \Mat_Projection\_32*VERTEXz + \Mat_Projection\_42
POINT3Dz.f = \Mat_Projection\_13*VERTEXx + \Mat_Projection\_23*VERTEXy + \Mat_Projection\_33*VERTEXz + \Mat_Projection\_43
SET_POINT3D(*Mesh,Vx,POINT3Dx,POINT3Dy,POINT3Dz)
Next
EndWith
EndProcedure
;-CAMERAS PROCS
Procedure CreateCam()
*Cam.CAMERA = AllocateMemory(SizeOf(CAMERA))
ProcedureReturn *Cam
EndProcedure
Procedure CameraRendering(*camera.CAMERA,FOV.f=0.00063)
With *camera
MATRICE_TRANSLATE(\Mat_Translate,\Position\x,\Position\y,\Position\z)
MATRICE_ROTATE(\Mat_Rotation,\Rotation\x,\Rotation\y,\Rotation\z)
MATRICE_MULTIPLY(\Mat_Translate,\Mat_Rotation,\Mat_Projection)
ForEach PipeLine()
*Mesh.MESH = PipeLine()
For Vx = 1 To *Mesh\Nbr_Vertice
POINT3Dx.f = GET_POINT3D(*Mesh,Vx,0)
POINT3Dy.f = GET_POINT3D(*Mesh,Vx,1)
POINT3Dz.f = GET_POINT3D(*Mesh,Vx,2)
POINT3Dx + \Mat_Projection\_11*POINT3Dx + \Mat_Projection\_21*POINT3Dy + \Mat_Projection\_31*POINT3Dz + \Mat_Projection\_41
POINT3Dy + \Mat_Projection\_12*POINT3Dx + \Mat_Projection\_22*POINT3Dy + \Mat_Projection\_32*POINT3Dz + \Mat_Projection\_42
POINT3Dz + \Mat_Projection\_13*POINT3Dx + \Mat_Projection\_23*POINT3Dy + \Mat_Projection\_33*POINT3Dz + \Mat_Projection\_43
POINT2Dx.f=(POINT3Dx*955)/(POINT3Dz+1)+SCREEN_W/2
POINT2Dy.f=(POINT3Dy*955)/(POINT3Dz+1)+SCREEN_H/2
SET_POINT2D(*Mesh,Vx,POINT2Dx,POINT2Dy)
SET_POINT3D(*Mesh,Vx,POINT3Dx,POINT3Dy,POINT3Dz)
; a étudier
POINT2Dx=POINT3Dx/(POINT3Dz*FOV)+SCREEN_W/2
POINT2Dy=POINT3Dy/(POINT3Dz*FOV)+SCREEN_H/2
;2D.X = 3D.X / (3D.Z * FOV)
;2D.Y = 3D.Y / (3D.Z * FOV)
If POINT2Dx>0 And POINT2Dx<SCREEN_W And POINT2Dy>0 And POINT2Dy<SCREEN_H
Circle(POINT2Dx,POINT2Dy,2)
;DrawText(POINT2Dx-5,POINT2Dy-20,"Z="+StrF(POINT3Dz))
EndIf
Next
Next
EndWith
ClearList(PipeLine())
EndProcedure
Procedure CameraPosition(*camera.CAMERA,x.f,y.f,z.f)
*camera\Position\x=x
*camera\Position\y=y
*camera\Position\z=z
EndProcedure
Procedure CameraRotation(*camera.CAMERA,x.f,y.f,z.f)
*camera\Rotation\x+x
*camera\Rotation\y+y
*camera\Rotation\z+z
EndProcedure
;-EXEMPLE
If InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0 Or InitSound() = 0
End
EndIf
OpenScreen(SCREEN_W,SCREEN_H,32,"")
; ******************************************
; CUBE
; ******************************************
Cube = CreateEmptyMesh() ; Création d'un mesh vide
AllocateVertex(Cube,8) ; Allocation de 8 vertices
; On place nos vertices
SET_VERTEX(Cube,1,-100,-100,100)
SET_VERTEX(Cube,2,100,-100,100)
SET_VERTEX(Cube,3,100,100,100)
SET_VERTEX(Cube,4,-100,100,100)
SET_VERTEX(Cube,5,-100,-100,-100)
SET_VERTEX(Cube,6,100,-100,-100)
SET_VERTEX(Cube,7,100,100,-100)
SET_VERTEX(Cube,8,-100,100,-100)
; ******************************************
; SPHERE ( thx comtois ;) )
; ******************************************
Sphere = CreateEmptyMesh()
Meridian=20
Parallel=20
AllocateVertex(Sphere,Meridian*Parallel+Parallel)
Vx=0
For i = 0 To Meridian
theta.f =i*3.14159*2/(Meridian+1)
ctheta.f=Cos(theta)
stheta.f=Sin(theta)
For j = 1 To Parallel
Vx+1
Alpha.f =j*3.14159/(Parallel+1)
calpha.f = Cos(Alpha)
salpha.f = Sin(Alpha)
SET_VERTEX(Sphere,Vx, salpha*ctheta,salpha*stheta,calpha)
Next
Next
Camera = CreateCam()
MeshPosition(Cube,0,0,-1000)
Repeat
ExamineKeyboard() : ExamineMouse()
ClearScreen(RGB(255,255,255))
y.f + 0.01
; Meshs
Meshscale(Cube,1)
MeshPosition(Cube,-100,0,1000)
MeshRotation(Cube,0,y,0)
MeshProjection(Cube)
Meshscale(Sphere,100)
MeshPosition(Sphere,250,0,1000)
MeshRotation(Sphere,0,y,0)
MeshProjection(Sphere)
;Camera
CameraRotation(Camera,-MouseDeltaY()/1000,MouseDeltaX()/1000,0)
StartDrawing(ScreenOutput())
CameraRendering(Camera) ; Rendering
StopDrawing()
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)
Le code est long, mais il manque pas mal de chose, comme la gestion des faces et autres joyeustés

Donc pour faire simple :
se code est réutilisable ( les fonctions et structures ) je te laisse l'amelliorer

Ce pseudo moteur possède un "Pipeline" primaire qui regroupe tout les mesh passé en paramètre de la fonction MeshProjection()
ce pipeline est sous forme de liste chainée , ce pipeline est appelé lors du rendu avec l'appel de CameraRendering() , et ensuite ce pipeline est remis à zero en attente de nouveaux mesh à afficher.
Se pipeline ne gère pas le clipping , càd tout ce qui se trouve derrière la camera sera rendu quand meme, a toi de rajouté une condition basic lors de l'affichage du " Circle()" : if 3DZ>0 ou 3DZ<0 , comme tu veut...
Pour la théorie, tu remarqueras que chaque mesh possède ses propres matrices, rotation , translation,mise a l'échelle etc...
on calcul dans un premier temps les coordonées des vertices suivant ces matrices de transformation, ensuite on envois le mesh dans le pipeline.
La caméra quand à elle , récupère tout ce qui sort du pipeline, puis recalcule à nouveau les vertices dans l'espace 3D suivant ses propres matrices de transformations, et il n'y a plus qu'a convertir les vertices en coordonées 2D puis de les affichés à l'écran

Vouali

@++