For type # PB_Mesh_TriangleList it takes 3 consecutive index to define a triangle.
.
 is loaded from a file, the type is necessarily # PB_Mesh_TriangleList.
Code: Select all
IncludeFile "Screen3DRequester.pb"
Structure Vector3
  x.f
  y.f
  z.f
EndStructure
Macro SubVector3(n, v, w)
  n\x = v\x - w\x
  n\y = v\y - w\y
  n\z = v\z - w\z
EndMacro
Define.Vector3 Normal, v1, v2, v3
#CameraSpeed = 1
#NbX=30
#NbZ=30
Global.f AngleVague, WaveFrequency, WavePeriodX, WavePeriodZ, WaveAmplitude
WaveFrequency=3  ;=waves/second
WavePeriodX  =9  ;=1/Wave lenght
WavePeriodZ  =11 ;=1/Wave lenght
WaveAmplitude=3
Define.f KeyX, KeyY, MouseX, MouseY
Global Dim MeshData.PB_MeshVertex(0)
Global Dim MeshDataInd.PB_MeshFace(0)
Declare UpdateMatrix()
Declare CreateMatrix()
If InitEngine3D()
  
  InitSprite()
  InitKeyboard()
  InitMouse()
  
  If Screen3DRequester()
    
    Add3DArchive("Data/Textures", #PB_3DArchive_FileSystem)
    Add3DArchive("Data/Packs/skybox.zip", #PB_3DArchive_Zip)
    Add3DArchive("Data/Scripts", #PB_3DArchive_FileSystem)
    Parse3DScripts()
    
    ;-Material 
    CreateMaterial(1, LoadTexture(1, "MRAMOR6X6.jpg"))
    MaterialCullingMode(1, 1)
    
    ;-Mesh
    CreateMatrix()
    
    ;-Camera
    CreateCamera(0, 0, 0, 100, 100)
    MoveCamera(0,0,150,80, #PB_Absolute)
    CameraLookAt(0, 0, 0, 0)
    CameraBackColor(0, RGB(90, 0, 0))
    
    ;-Light
    CreateLight(0, RGB(255, 255, 255), 5, 15, 5)
    AmbientColor(RGB(30, 30, 30))
    
    ;- Skybox
    SkyBox("stevecube.jpg")
    
    Repeat
      Screen3DEvents()
      
      If ExamineKeyboard()
        
        If KeyboardPushed(#PB_Key_Left)
          KeyX = -#CameraSpeed
        ElseIf KeyboardPushed(#PB_Key_Right)
          KeyX = #CameraSpeed
        Else
          KeyX = 0
        EndIf
        
        If KeyboardPushed(#PB_Key_Up)
          KeyY = -#CameraSpeed
        ElseIf KeyboardPushed(#PB_Key_Down)
          KeyY = #CameraSpeed
        Else
          KeyY = 0
        EndIf
        
      EndIf
      
      If ExamineMouse()
        MouseX = -(MouseDeltaX()/10)
        MouseY = -(MouseDeltaY()/10)
      EndIf
      MoveCamera  (0, KeyX, 0, KeyY)
      RotateCamera(0,  MouseY, MouseX, 0, #PB_Relative) 
      
      ; Waves
      UpdateMatrix()
      AngleVague = AngleVague+WaveFrequency
      
      RenderWorld()
      
      FlipBuffers()
    Until KeyboardPushed(#PB_Key_Escape) Or Quit = 1
  EndIf
  
Else
  MessageRequester("Error", "The 3D Engine can't be initialized", 0)
EndIf
End
;-Procédures
Procedure Normalize(*V.Vector3)
  Protected.f magSq, oneOverMag
  
  magSq = *V\x * *V\x + *V\y * *V\y + *V\z * *V\z
  If magsq > 0
    oneOverMag = 1.0 / Sqr(magSq)
    *V\x * oneOverMag
    *V\y * oneOverMag
    *V\z * oneOverMag
  EndIf 
  
EndProcedure
Procedure NormalFace(*n.Vector3, *v1.Vector3, *v2.Vector3, *v3.Vector3)
  Protected.Vector3 v2v1, v3v1
  SubVector3(v2v1, *v2, *v1)
  SubVector3(v3v1, *v3, *v1)
  
  *n\x = v2v1\y * v3v1\z - v2v1\z * v3v1\y
  *n\y = v2v1\z * v3v1\x - v2v1\x * v3v1\z
  *n\z = v2v1\x * v3v1\y - v2v1\y * v3v1\x
EndProcedure  
Procedure DrawMatrix()
  Protected.l a, b, c, Nb
  Protected.w P1, P2, P3, P4
  
  For b=0 To #Nbz
    For a=0 To #NbX
      ;les coordonnées de vertex
      y.f=Sin(Radian((AngleVague+a*WavePeriodX+b*WavePeriodZ)))*WaveAmplitude
      MeshVertexPosition(a - #NbX/2, y, b - #Nbz/2)
      MeshVertexNormal(0,1,0)
      MeshVertexTextureCoordinate(a/#NbX, b/#Nbz)
    Next a
  Next b
  
  Nb=#NbX+1
  For b=0 To #NbZ-1
    For a=0 To #NbX-1
      P1=a+(b*Nb)
      P2=P1+1
      P3=a+(b+1)*Nb
      P4=P3+1
      
      MeshFace(P3, P2, P1)
      MeshFace(P2, P3, P4)
    Next
  Next
EndProcedure 
Procedure CreateMatrix()
  
  CreateMesh(0, #PB_Mesh_TriangleList, #True)
  DrawMatrix()
  FinishMesh(#True)
  SetMeshMaterial(0, MaterialID(1))
  
  CreateNode(0)
  CreateEntity(0, MeshID(0), #PB_Material_None)
  ScaleEntity(0, 3, 3, 3)
  
  GetMeshData(0,0, MeshData(), #PB_Mesh_Vertex, 0, MeshVertexCount(0, 0)-1)
  GetMeshData(0,0, MeshDataInd(), #PB_Mesh_Face, 0, MeshIndexCount(0, 0)-1)
  
EndProcedure
Procedure UpdateMatrix()
  Protected a, b, c, i, j
  Protected N.Vector3, V1.Vector3, V2.Vector3, V3.Vector3
  Protected.f magSq, oneOverMag
  
  For b=0 To #Nbz
    For a=0 To #NbX
      ;les coordonnées de vertex
      MeshData(c)\y=Sin(Radian((AngleVague+a*WavePeriodX+b*WavePeriodZ)))*WaveAmplitude
      ;Init les normales
      MeshData(c)\NormalX = 0
      MeshData(c)\NormalY = 0
      MeshData(c)\NormalZ = 0
      c + 1
    Next a
  Next b
  
  ;Calcul les normales
  For j=0 To ArraySize(MeshDataInd())-2 Step 3
    
    V1\x = MeshData(MeshDataInd(j  )\Index)\x
    V1\y = MeshData(MeshDataInd(j  )\Index)\y
    V1\z = MeshData(MeshDataInd(j  )\Index)\z
    V2\x = MeshData(MeshDataInd(j+1)\Index)\x
    V2\y = MeshData(MeshDataInd(j+1)\Index)\y
    V2\z = MeshData(MeshDataInd(j+1)\Index)\z  
    V3\x = MeshData(MeshDataInd(j+2)\Index)\x
    V3\y = MeshData(MeshDataInd(j+2)\Index)\y
    V3\z = MeshData(MeshDataInd(j+2)\Index)\z    
    NormalFace(@N, @V1, @V2, @V3)
    ;Normalize(@N)
    MeshData(MeshDataInd(j  )\Index)\NormalX + N\x
    MeshData(MeshDataInd(j  )\Index)\NormalY + N\y
    MeshData(MeshDataInd(j  )\Index)\NormalZ + N\z
    MeshData(MeshDataInd(j+1)\Index)\NormalX + N\x
    MeshData(MeshDataInd(j+1)\Index)\NormalY + N\y
    MeshData(MeshDataInd(j+1)\Index)\NormalZ + N\z  
    MeshData(MeshDataInd(j+2)\Index)\NormalX + N\x
    MeshData(MeshDataInd(j+2)\Index)\NormalY + N\y
    MeshData(MeshDataInd(j+2)\Index)\NormalZ + N\z     
  Next
  
  For i=0 To ArraySize(MeshData())
    
    magSq = MeshData(i)\NormalX * MeshData(i)\NormalX + 
            MeshData(i)\NormalY * MeshData(i)\NormalY + 
            MeshData(i)\NormalZ * MeshData(i)\NormalZ 
    
    If magsq > 0
      oneOverMag = 1.0 / Sqr(magSq)
      MeshData(i)\NormalX * oneOverMag
      MeshData(i)\NormalY * oneOverMag
      MeshData(i)\NormalZ * oneOverMag
    EndIf 
    
  Next 
  
  SetMeshData(0,0, MeshData(), #PB_Mesh_Vertex | #PB_Mesh_Normal, 0, MeshVertexCount(0, 0)-1)
EndProcedure