Comme j'avais dis il y a quelque temps déjà , la perspective est foireuse , faire un jeu avec sa , c'est la gerbe assuré.
pour ceux que cela intéresse , voici comment les moteurs 3D fonctionnent au niveau des transformations géométrique ( projection à l'écran )
le code n'est pas si gros que ca , la plupart c'est des routines sur les vecteurs & matrice4x4.
Code : Tout sélectionner
; ----------------------------------------------------------------------------------------
;
; ----------------------------------------------------------------------------------------
#PI_OVER_180 = 0.0174532925199432957
#PI_OVER_360 = 0.0087266462599716478
; ----------------------------------------------------------------------------------------
;
; ----------------------------------------------------------------------------------------
Structure vector3
x.f : y.f : z.f
EndStructure
; ----------------------------------------------------------------------------------------
;
; ----------------------------------------------------------------------------------------
Structure matrix4
m.f[16]
EndStructure
; ----------------------------------------------------------------------------------------
;
; ----------------------------------------------------------------------------------------
ProcedureDLL vector3(x.f=0, y.f=0, z.f=0)
*v.vector3 = AllocateMemory(SizeOf(vector3))
*v\x = x
*v\y = y
*v\z = z
ProcedureReturn *v
EndProcedure
; ----------------------------------------------------------------------------------------
;
; ----------------------------------------------------------------------------------------
ProcedureDLL free_vector3(*v.vector3)
FreeMemory(*v)
EndProcedure
; ----------------------------------------------------------------------------------------
;
; ----------------------------------------------------------------------------------------
ProcedureDLL vector3_add(*ReturnVector.vector3, *V1.vector3, *V2.vector3)
*ReturnVector\x = *V1\x + *V2\x
*ReturnVector\y = *V1\y + *V2\y
*ReturnVector\z = *V1\z + *V2\z
EndProcedure
; ----------------------------------------------------------------------------------------
;
; ----------------------------------------------------------------------------------------
ProcedureDLL vector3_subtract(*ReturnVector.vector3, *V1.vector3, *V2.vector3)
*ReturnVector\x = *V1\x - *V2\x
*ReturnVector\y = *V1\y - *V2\y
*ReturnVector\z = *V1\z - *V2\z
EndProcedure
; ----------------------------------------------------------------------------------------
;
; ----------------------------------------------------------------------------------------
ProcedureDLL vector3_multiply(*ReturnVector.vector3, *V1.vector3, *V2.vector3)
*ReturnVector\x = *V1\x * *V2\x
*ReturnVector\y = *V1\y * *V2\y
*ReturnVector\z = *V1\z * *V2\z
EndProcedure
; ----------------------------------------------------------------------------------------
;
; ----------------------------------------------------------------------------------------
ProcedureDLL vector3_crossProduct(*ReturnVector.vector3, *V1.vector3, *V2.vector3)
*ReturnVector\x = *V1\y * *V2\z - *V2\y * *V1\z
*ReturnVector\y = *V1\z * *V2\x - *V2\z * *V1\x
*ReturnVector\z = *V1\x * *V2\y - *V2\x * *V1\y
EndProcedure
; ----------------------------------------------------------------------------------------
;
; ----------------------------------------------------------------------------------------
ProcedureDLL.d vector3_dotProduct(*V1.vector3, *V2.vector3)
ProcedureReturn (*V1\x * *V2\x) + (*V1\y * *V2\y) + (*V1\z * *V2\z)
EndProcedure
; ----------------------------------------------------------------------------------------
;
; ----------------------------------------------------------------------------------------
ProcedureDLL.f vector3_length(x.f, y.f, z.f)
ProcedureReturn Sqr(x * x + y * y + z * z)
EndProcedure
; ----------------------------------------------------------------------------------------
;
; ----------------------------------------------------------------------------------------
ProcedureDLL vector3_normalize(*NormVector.vector3)
length.f = vector3_length(*NormVector\x, *NormVector\y, *NormVector\z)
*NormVector\x = *NormVector\x / length
*NormVector\y = *NormVector\y / length
*NormVector\z = *NormVector\z / length
EndProcedure
; ----------------------------------------------------------------------------------------
;
; ----------------------------------------------------------------------------------------
ProcedureDLL vector3_scale(*Vector.vector3,Scale.f)
*Vector\x * Scale
*Vector\y * Scale
*Vector\z * Scale
EndProcedure
; ----------------------------------------------------------------------------------------
;
; ----------------------------------------------------------------------------------------
ProcedureDLL.i matrix4(*pointer=#Null)
*m.matrix4 = AllocateMemory(SizeOf(matrix4))
If *pointer<>#Null
CopyMemory(*pointer,@*m\m,64)
EndIf
ProcedureReturn *m
EndProcedure
; ----------------------------------------------------------------------------------------
;
; ----------------------------------------------------------------------------------------
ProcedureDLL free_matrix4(*m.matrix4)
FreeMemory(*m)
EndProcedure
; ----------------------------------------------------------------------------------------
;
; ----------------------------------------------------------------------------------------
ProcedureDLL matrix4_identity(*m.matrix4)
With *m
\m[0] = 1 : \m[4] = 0 : \m[8] = 0 : \m[12] = 0
\m[1] = 0 : \m[5] = 1 : \m[9] = 0 : \m[13] = 0
\m[2] = 0 : \m[6] = 0 : \m[10] = 1 : \m[14] = 0
\m[3] = 0 : \m[7] = 0 : \m[11] = 0 : \m[15] = 1
EndWith
EndProcedure
; ----------------------------------------------------------------------------------------
;
; ----------------------------------------------------------------------------------------
ProcedureDLL matrix4_multiply(*mB.matrix4, *mA.matrix4)
Protected temp.matrix4
For i = 0 To 3
temp\m[i*4+0] = *mA\m[i*4] * *mB\m[0] + *mA\m[i*4+1] * *mB\m[4] + *mA\m[i*4+2] * *mB\m[8] + *mA\m[i*4+3] * *mB\m[12]
temp\m[i*4+1] = *mA\m[i*4] * *mB\m[1] + *mA\m[i*4+1] * *mB\m[5] + *mA\m[i*4+2] * *mB\m[9] + *mA\m[i*4+3] * *mB\m[13]
temp\m[i*4+2] = *mA\m[i*4] * *mB\m[2] + *mA\m[i*4+1] * *mB\m[6] + *mA\m[i*4+2] * *mB\m[10] + *mA\m[i*4+3] * *mB\m[14]
temp\m[i*4+3] = *mA\m[i*4] * *mB\m[3] + *mA\m[i*4+1] * *mB\m[7] + *mA\m[i*4+2] * *mB\m[11] + *mA\m[i*4+3] * *mB\m[15]
Next
CopyStructure(@temp,*mB,matrix4)
EndProcedure
; ----------------------------------------------------------------------------------------
;
; ----------------------------------------------------------------------------------------
ProcedureDLL matrix4_perspective(*m.matrix4, fov.f, aspect.f, zNear.f, zFar.f)
Protected temp.matrix4
Protected fov2.f = fov * #PI_OVER_180
Protected t.f = zNear * Tan(fov/2)
Protected r.f = t * aspect
temp\m[0] = zNear / r
temp\m[1] = 0
temp\m[2] = 0
temp\m[3] = 0
temp\m[4] = 0
temp\m[5] = zNear / t
temp\m[6] = 0
temp\m[7] = 0
temp\m[8] = 0
temp\m[9] = 0
temp\m[10] = -1*(zFar+zNear)/(zFar-zNear)
temp\m[11] = (-2*zFar*zNear)/(zFar-zNear)
temp\m[12] = 0
temp\m[13] = 0
temp\m[14] = -1
temp\m[15] = 1
matrix4_multiply(*m,@temp)
EndProcedure
; ----------------------------------------------------------------------------------------
;
; ----------------------------------------------------------------------------------------
Procedure matrix4_translate(*m.matrix4, x.f, y.f, z.f)
Protected temp.matrix4
temp\m[0] = 1 : temp\m[4] = 0 : temp\m[8] = 0 : temp\m[12] = x
temp\m[1] = 0 : temp\m[5] = 1 : temp\m[9] = 0 : temp\m[13] = y
temp\m[2] = 0 : temp\m[6] = 0 : temp\m[10] = 1 : temp\m[14] = z
temp\m[3] = 0 : temp\m[7] = 0 : temp\m[11] = 0 : temp\m[15] = 1
matrix4_multiply(*m,@temp)
EndProcedure
; ----------------------------------------------------------------------------------------
;
; ----------------------------------------------------------------------------------------
Procedure matrix4_scale(*m.matrix4, x.f, y.f, z.f)
Protected temp.matrix4
temp\m[0] = x : temp\m[4] = 0 : temp\m[8] = 0 : temp\m[12] = 0
temp\m[1] = 0 : temp\m[5] = y : temp\m[9] = 0 : temp\m[13] = 0
temp\m[2] = 0 : temp\m[6] = 0 : temp\m[10] = z : temp\m[14] = 0
temp\m[3] = 0 : temp\m[7] = 0 : temp\m[11] = 0 : temp\m[15] = 1
matrix4_multiply(*m,@temp)
EndProcedure
; ----------------------------------------------------------------------------------------
;
; ----------------------------------------------------------------------------------------
ProcedureDLL matrix4_rotate(*m.matrix4, a.f, x.f, y.f, z.f)
Protected angle.f = a * #PI_OVER_180
Protected temp.matrix4
temp\m[0] = 1+(1-Cos(angle))*(x*x-1)
temp\m[1] = -z*Sin(angle)+(1-Cos(angle))*x*y
temp\m[2] = y*Sin(angle)+(1-Cos(angle))*x*z
temp\m[3] = 0
temp\m[4] = z*Sin(angle)+(1-Cos(angle))*x*y
temp\m[5] = 1+(1-Cos(angle))*(y*y-1)
temp\m[6] = -x*Sin(angle)+(1-Cos(angle))*y*z
temp\m[7] = 0
temp\m[8] = -y*Sin(angle)+(1-Cos(angle))*x*z
temp\m[9] = x*Sin(angle)+(1-Cos(angle))*y*z
temp\m[10] = 1+(1-Cos(angle))*(z*z-1)
temp\m[11] = 0
temp\m[12] = 0
temp\m[13] = 0
temp\m[14] = 0
temp\m[15] = 1
matrix4_multiply(*m,@temp)
EndProcedure
; ----------------------------------------------------------------------------------------
;
; ----------------------------------------------------------------------------------------
ProcedureDLL matrix4_ortho(*m.matrix4, left.f, right.f, bottom.f, top.f, zNear.f, zFar.f)
Protected temp.matrix4
temp\m[0] = 2 / (right - left)
temp\m[1] = 0
temp\m[2] = 0
temp\m[3] = -(( right + left ) / (right - left))
temp\m[4] = 0
temp\m[5] = 2 / (top - bottom)
temp\m[6] = 0
temp\m[7] = -(( top + bottom) / (top - bottom))
temp\m[8] = 0
temp\m[9] = 0
temp\m[10] = 2 / ( zFar - zNear)
temp\m[11] = -((zFar + zNear) / (zFar - zNear))
temp\m[12] = 0
temp\m[13] = 0
temp\m[14] = 0
temp\m[15] = 1
matrix4_multiply(*m,@temp)
EndProcedure
; ----------------------------------------------------------------------------------------
;
; ----------------------------------------------------------------------------------------
ProcedureDLL.i matrix4_coordinate(*m.matrix4,*v.vector3)
*temp.vector3 = AllocateMemory(SizeOf(vector3))
*temp\x = *v\x * *m\m[0] + *v\y * *m\m[4] + *v\z * *m\m[8] + *m\m[12]
*temp\y = *v\x * *m\m[1] + *v\y * *m\m[5] + *v\z * *m\m[9] + *m\m[13]
*temp\z = *v\x * *m\m[2] + *v\y * *m\m[6] + *v\z * *m\m[10] + *m\m[14]
ProcedureReturn *temp
EndProcedure
; ----------------------------------------------------------------------------------------
;
; ----------------------------------------------------------------------------------------
#NB_STAR = 5000
Structure Stars
position.vector3
rotation.vector3
mat_view.matrix4
EndStructure
Structure StarsRendering
ScreenCoordinate.vector3
EndStructure
Global NewList StarsRendering.StarsRendering()
Dim Star.Stars(#NB_STAR-1)
For i = 0 To #NB_STAR-1
Star(i)\position\x = -Random(50000) + Random(50000)
Star(i)\position\y = -Random(50000) + Random(50000)
Star(i)\position\z = -Random(50000) + Random(50000)
Next
; ----------------------------------------------------------------------------------------
;-OpenScreen()
; ----------------------------------------------------------------------------------------
Global ScreenW = 1024
Global ScreenH = 768
InitSprite() : InitKeyboard()
Global Window = OpenWindow(#PB_Any,0,0,ScreenW,ScreenH, "FlyInTheSky")
Global wHwd = WindowID(Window)
OpenWindowedScreen(wHwd,0,0,ScreenW,ScreenH,1,0,0)
; ----------------------------------------------------------------------------------------
;-Setup 3D
; ----------------------------------------------------------------------------------------
; Matrice de perspective
Global *MATRICE_PROJECTION = matrix4()
matrix4_identity(*MATRICE_PROJECTION)
matrix4_perspective(*MATRICE_PROJECTION,45,ScreenW/ScreenH,1,1000)
;Matrice modelview (camera)
Global *MATRIX_MODELVIEW = matrix4()
KeyboardMode(#PB_Keyboard_International)
Repeat
ClearScreen(0)
ExamineKeyboard()
If KeyboardPushed(#PB_Key_Up)
CamZ + 100
EndIf
If KeyboardPushed(#PB_Key_Down)
CamZ - 100
EndIf
If KeyboardPushed(#PB_Key_PageDown)
CamPitch.f + 1
EndIf
If KeyboardPushed(#PB_Key_PageUp)
CamPitch.f - 1
EndIf
If KeyboardPushed(#PB_Key_Right)
CamYaw.f + 1
EndIf
If KeyboardPushed(#PB_Key_Left)
CamYaw.f - 1
EndIf
ClearList(StarsRendering())
matrix4_identity(*MATRIX_MODELVIEW)
matrix4_rotate(*MATRIX_MODELVIEW,CamPitch,1,0,0)
matrix4_rotate(*MATRIX_MODELVIEW,CamYaw ,0,1,0)
matrix4_rotate(*MATRIX_MODELVIEW,CamRoll ,0,0,1)
matrix4_translate(*MATRIX_MODELVIEW,CamX,CamY,CamZ)
*MATRICE_PROJVIEW.matrix4 = matrix4(*MATRICE_PROJECTION)
matrix4_multiply(*MATRICE_PROJVIEW,*MATRIX_MODELVIEW)
For i = 0 To #NB_STAR-1
matrix4_identity(@Star(i)\mat_view)
matrix4_translate(@Star(i)\mat_view,Star(i)\position\x,Star(i)\position\y,Star(i)\position\z)
*MATRIX_MODELPROJ.matrix4 = matrix4(@Star(i)\mat_view)
matrix4_multiply(*MATRICE_PROJVIEW,*MATRIX_MODELPROJ)
;On projette :
*ScreenCoordinate.vector3 = matrix4_coordinate(*MATRICE_PROJVIEW,@Star(i)\position)
*ScreenCoordinate\x * 0.5 / *ScreenCoordinate\z + 0.5
*ScreenCoordinate\y * 0.5 / *ScreenCoordinate\z + 0.5
*ScreenCoordinate\x * ScreenW
*ScreenCoordinate\y * ScreenH
If *ScreenCoordinate\z>1
If *ScreenCoordinate\x>0 And *ScreenCoordinate\x<ScreenW-1 And *ScreenCoordinate\y>0 And *ScreenCoordinate\y<ScreenH-1
AddElement(StarsRendering())
StarsRendering()\ScreenCoordinate\x = *ScreenCoordinate\x
StarsRendering()\ScreenCoordinate\y = *ScreenCoordinate\y
StarsRendering()\ScreenCoordinate\z = *ScreenCoordinate\z
EndIf
EndIf
free_vector3(*ScreenCoordinate)
Next
free_matrix4(*MATRICE_PROJVIEW)
StartDrawing(ScreenOutput())
ForEach StarsRendering()
Plot(StarsRendering()\ScreenCoordinate\x,StarsRendering()\ScreenCoordinate\y,$FFFFFF)
Next
DrawText(10,10,"Move with Up/Down key")
DrawText(10,30,"Rotate yaw with Right/Left key")
DrawText(10,50,"Rotate pitch with pageup/down key")
StopDrawing()
FlipBuffers()
Until WindowEvent() = #PB_Event_CloseWindow