Horloge lumineuse (PB 4.30)

Généralités sur la programmation 3D
kelebrindae
Messages : 579
Inscription : ven. 11/mai/2007 15:21

Horloge lumineuse (PB 4.30)

Message par kelebrindae »

Bonjour à tous,

Une petite horloge lumineuse codée à l'arrache (2 heures), pour valider les possibilités des lumières.
Résultat: les ombres sortent plutôt bien, comme quoi PB se débrouille pas si mal que ça en 3D! :)

Par contre, j'ai l'impression (infondée et sans doute fausse) que les résultats à l'écran peuvent beaucoup varier selon la carte graphique; 'faudrait que je poste une capture d'écran pour que vous voyiez à quoi ça ressemble chez moi, histoire de voir si vous avez la même chose. A tester, donc.

Autre chose: si ça rame chez vous, modifiez la valeur de la constante #QUALITY, en début de code; ça réduira le nombre de polygones des meshes (que j'ai mis assez élevé par défaut, pour obtenir des éclairages plus jolis).

Voici le code:

Code : Tout sélectionner

;- Initialization
Global FullScreen.b
Resultat = MessageRequester("Light Clock","Full Screen ?",#PB_MessageRequester_YesNo) 
If Resultat = 6      
  FullScreen=#True 
Else            
  FullScreen=#False
EndIf 

If InitEngine3D() = 0
  MessageRequester( "Error" , "Can't initialize 3D, check if engine3D.dll is available" , 0 ) 
End 
ElseIf InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0 
  MessageRequester( "Error" , "Can't find DirectX 7.0 or above" , 0 ) 
  End 
EndIf 

If Fullscreen = #True
  OpenScreen(1024,768,32,"Light Clock") 
Else 
  OpenWindow(0,0, 0, 800 , 600 ,"Light Clock") 
  OpenWindowedScreen(WindowID(0),0,0, 800 , 600,0,0,0) 
EndIf 

#CAMERA = 0
#RAD2DEGMULT = 57.295779513082320877  ;(180/#PI)
#DEG2RADMULT = 0.0174532925199432958  ;(#PI/180)
#QUALITY = 1  ; 1 = good, 2 = medium, 3 = low, 4 = mini

; Cylinder mesh caps
Enumeration
  #CYLCAP_NONE
  #CYLCAP_BOTH
  #CYLCAP_TOP
  #CYLCAP_BOTTOM
EndEnumeration


;- Structures and global definitions
Structure Vertex 
  px.f 
  py.f 
  pz.f 
  nx.f 
  ny.f 
  nz.f 
  Couleur.l 
  U.f 
  V.f 
EndStructure 

Structure Polygon 
  numVert1.w 
  numVert2.w 
  numVert3.w 
EndStructure 

Global groundMesh.i, gnomonMesh.i, boxMesh.i
Global groundEntity.i, gnomonEntity.i
Global Dim boxEntity.i(12)
Global hours.f, mins.f, secs.f
Global oldTimer.i, newTimer.i, movement.i
Global dist.f,i.i
;- ------ Procedures ------
EnableExplicit

;- -- Meshes and entities --

;************************************************************************************
; Name: createPlainMesh
; Purpose: creates a plain
; Parameters: 
;   - number of subdivisions (given "3", the plain will be a 3x3 grid)
;   - sizeX, sizeZ : size of the box
;   - pivotX, pivotZ : location of the pivot of the box, around which it rotates (default = center = 0,0)
;   - Uorigin, Vorigin : UV map coordinates (default = top left of the map = 0,0)
;   - Uscale, Vscale : UV map scale (default = 1,1)
;   - color of the vertices (default = white)
; Return-Value: number of the resulting mesh, -1 if creation failed
;************************************************************************************
Procedure.l createPlainMesh(nbdiv.w,sizeX.f,sizeZ.f,pivotX.f = 0,pivotZ.f = 0,Uorigin.f = 0,Vorigin.f = 0,Uscale.f = 1,Vscale.f = 1,color.l = $FFFFFF)

  Protected sizediv.f
  Protected x1.f,y1.f,z1.f                  ; vertex position
  Protected x2.f,y2.f,z2.f                  ; vertex position
  Protected x3.f,y3.f,z3.f                  ; vertex position
  Protected x4.f,y4.f,z4.f                  ; vertex position
  Protected nx.f,ny.f,nz.f                  ; vertex normals
  Protected u.f,v.f                         ; vertex UV coords (texture mapping)
  Protected numvert.w,numvert0.w            ; vertices of a poly
  Protected *PtrV.Vertex,*PtrV0.Vertex      ; vertices buffer in memory
  Protected *ptrP.Polygon,*ptrP0.Polygon    ; Polys buffer in memory
  Protected *vertexBuffer.l
  Protected *polygonBuffer.l
  Protected num.l,i.l,j.l,nbtri.l,nbvert
  Protected maxSize.f
  Protected newmesh.l                       ; Procedure Result

  nbtri  = (nbDiv * nbDiv * 2) ; nb divisions * nb divisions * 2 triangles per division
  nbvert = (nbDiv * nbDiv * 4) ; nb divisions * nb divisions * 4 vertices per division
  
  ; Allocate the needed memory for vertices
  *vertexBuffer = AllocateMemory(SizeOf(Vertex)*nbVert) 
  *PtrV = *vertexBuffer 
  
  ; Allocate the needed memory for faces info
  *polygonBuffer=AllocateMemory(SizeOf(Polygon)*nbTri) 
  *ptrP=*polygonBuffer

  sizeDiv = 1/nbDiv
  ; Top
  x1=-0.5:y1=0:z1=-0.5
  x2=-0.5+sizeDiv:y2=0:z2 = z1
  x3=x2:y3=0:z3=-0.5+sizeDiv
  x4=x1:y4=0:z4=z3
  
  For i=1 To nbDiv
    For j=1 To nbDiv
      
      ; 1 square = 4 vertices
      *PtrV\px = x1
      *PtrV\py = y1
      *PtrV\pz = z1
      *PtrV\nx = 0 
      *PtrV\ny = 0.5
      *PtrV\nz = 0
      *PtrV\couleur = color
      *PtrV\u = uorigin + (uscale/nbdiv)*(i-1)
      *PtrV\v = vorigin + (vscale/nbdiv)*(j-1)
      *PtrV + SizeOf(Vertex) 

      *PtrV\px = x2
      *PtrV\py = y2
      *PtrV\pz = z2  
      *PtrV\nx = 0 
      *PtrV\ny = 0.5
      *PtrV\nz = 0
      *PtrV\couleur = color
      *PtrV\u = uorigin + (uscale/nbdiv)*(i-1) + uscale/nbdiv
      *PtrV\v = vorigin + (vscale/nbdiv)*(j-1)
      *PtrV + SizeOf(Vertex) 

      *PtrV\px = x3 
      *PtrV\py = y3
      *PtrV\pz = z3  
      *PtrV\nx = 0 
      *PtrV\ny = 0.5
      *PtrV\nz = 0
      *PtrV\couleur = color
      *PtrV\u = uorigin + (uscale/nbdiv)*(i-1) + uscale/nbdiv
      *PtrV\v = vorigin + (vscale/nbdiv)*(j-1) + vscale/nbdiv
      *PtrV + SizeOf(Vertex) 
      
      *PtrV\px = x4 
      *PtrV\py = y4
      *PtrV\pz = z4 
      *PtrV\nx = 0 
      *PtrV\ny = 0.5
      *PtrV\nz = 0
      *PtrV\couleur = color
      *PtrV\u = uorigin + (uscale/nbdiv)*(i-1)
      *PtrV\v = vorigin + (vscale/nbdiv)*(j-1) + vscale/nbdiv
      *PtrV + SizeOf(Vertex) 

      ; 1 square = 2 triangles
      *ptrP\numVert1=numvert+3  
      *ptrP\numVert2=numvert+2
      *ptrP\numVert3=numvert 
      *ptrP + SizeOf(Polygon)

      *ptrP\numVert1=numvert  
      *ptrP\numVert2=numvert+2
      *ptrP\numVert3=numvert+1
      *ptrP + SizeOf(Polygon)
      
      numvert+4     

      z1=z4
      z2=z3
      z3+sizeDiv
      z4=z3

    Next j
    
    x1=x2
    x4=x3
    x2+sizeDiv
    x3=x2
    z1=-0.5
    z2=z1
    z3=-0.5+sizeDiv
    z4=z3
     
  Next i
  numvert0=numvert
  

  ; Resize
  If sizeX<>1 Or sizeZ<>1
    *ptrV = *vertexBuffer
    For i=1 To nbVert
      *PtrV\px = *PtrV\px*sizeX - pivotX
      *PtrV\pz = *PtrV\pz*sizeZ - pivotZ
      
      *PtrV+SizeOf(vertex)
    Next i  
  EndIf

  ; Create mesh from stored infos
  maxSize = sizeX
  If sizeZ > maxSize
    maxSize = sizeZ
  EndIf
  
  newMesh = CreateMesh(#PB_Any,maxSize)
  If IsMesh(newMesh) 
    SetMeshData(newMesh,#PB_Mesh_Vertex | #PB_Mesh_Normal | #PB_Mesh_UVCoordinate | #PB_Mesh_Color,*vertexBuffer,nbVert) 
    SetMeshData(newMesh,#PB_Mesh_Face,*polygonBuffer,nbTri)     
    FreeMemory(*vertexBuffer)
    FreeMemory(*polygonBuffer)
    ProcedureReturn newMesh
  Else 
    ; free memory if "createMesh" has failed
    FreeMemory(*vertexBuffer)
    FreeMemory(*polygonBuffer)
    ProcedureReturn -1    
  EndIf 

EndProcedure
;************************************************************************************
; Name: createBoxMesh
; Purpose: creates a "box" mesh
; Parameters: 
;   - number of subdivisions (given "3", each face of the box will be a 3x3 grid)
;   - sizeX, sizeY, sizeZ : size of the box
;   - pivotX, pivotY, pivotZ : location of the pivot of the box, around which it rotates (default = center = 0,0,0)
;   - Uorigin, Vorigin : UV map coordinates (default = top left of the map = 0,0)
;   - Uscale, Vscale : UV map scale (default = 1,1)
;   - color of the vertices (default = white)
; Return-Value: number of the resulting mesh, -1 if creation failed
;************************************************************************************
Procedure.l createBoxMesh(nbdiv.w,sizeX.f,sizeY.f,sizeZ.f,pivotX.f = 0,pivotY.f = 0,pivotZ.f = 0,Uorigin.f = 0,Vorigin.f = 0,Uscale.f = 1,Vscale.f = 1,color.l = $FFFFFF)

  Protected sizediv.f
  Protected x1.f,y1.f,z1.f                  ; vertex position
  Protected x2.f,y2.f,z2.f                  ; vertex position
  Protected x3.f,y3.f,z3.f                  ; vertex position
  Protected x4.f,y4.f,z4.f                  ; vertex position
  Protected nx.f,ny.f,nz.f                  ; vertex normals
  Protected u.f,v.f                         ; vertex UV coords (texture mapping)
  Protected numvert.w,numvert0.w            ; vertices of a poly
  Protected *PtrV.Vertex,*PtrV0.Vertex      ; vertices buffer in memory
  Protected *ptrP.Polygon,*ptrP0.Polygon    ; Polys buffer in memory
  Protected *vertexBuffer.l
  Protected *polygonBuffer.l
  Protected num.l,i.l,j.l,nbtri.l,nbvert
  Protected maxSize.f
  Protected newmesh.l                       ; Procedure Result

  nbtri  = 6 * (nbDiv * nbDiv * 2) ; 6 sides * nb divisions * nb divisions * 2 triangles per division
  nbvert = 6 * (nbDiv * nbDiv * 4) ; 6 sides * nb divisions * nb divisions * 4 vertices per division
  
  ; Allocate the needed memory for vertices
  *vertexBuffer = AllocateMemory(SizeOf(Vertex)*nbVert) 
  *PtrV = *vertexBuffer 
  
  ; Allocate the needed memory for faces info
  *polygonBuffer=AllocateMemory(SizeOf(Polygon)*nbTri) 
  *ptrP=*polygonBuffer

  sizeDiv = 1/nbDiv
  ; Top
  x1=-0.5:y1=0.5:z1=-0.5
  x2=-0.5+sizeDiv:y2=0.5:z2 = z1
  x3=x2:y3=0.5:z3=-0.5+sizeDiv
  x4=x1:y4=0.5:z4=z3
  
  For i=1 To nbDiv
    For j=1 To nbDiv
      
      ; 1 square = 4 vertices
      *PtrV\px = x1
      *PtrV\py = y1
      *PtrV\pz = z1
      *PtrV\nx = *PtrV\px 
      *PtrV\ny = *PtrV\py
      *PtrV\nz = *PtrV\pz
      *PtrV\couleur = color
      *PtrV\u = uorigin + (uscale/nbdiv)*(i-1)
      *PtrV\v = vorigin + (vscale/nbdiv)*(j-1)
      *PtrV + SizeOf(Vertex) 

      *PtrV\px = x2
      *PtrV\py = y2
      *PtrV\pz = z2  
      *PtrV\nx = *PtrV\px 
      *PtrV\ny = *PtrV\py
      *PtrV\nz = *PtrV\pz
      *PtrV\couleur = color
      *PtrV\u = uorigin + (uscale/nbdiv)*(i-1) + uscale/nbdiv
      *PtrV\v = vorigin + (vscale/nbdiv)*(j-1)
      *PtrV + SizeOf(Vertex) 

      *PtrV\px = x3 
      *PtrV\py = y3
      *PtrV\pz = z3  
      *PtrV\nx = *PtrV\px 
      *PtrV\ny = *PtrV\py
      *PtrV\nz = *PtrV\pz
      *PtrV\couleur = color
      *PtrV\u = uorigin + (uscale/nbdiv)*(i-1) + uscale/nbdiv
      *PtrV\v = vorigin + (vscale/nbdiv)*(j-1) + vscale/nbdiv
      *PtrV + SizeOf(Vertex) 
      
      *PtrV\px = x4 
      *PtrV\py = y4
      *PtrV\pz = z4 
      *PtrV\nx = *PtrV\px 
      *PtrV\ny = *PtrV\py
      *PtrV\nz = *PtrV\pz
      *PtrV\couleur = color
      *PtrV\u = uorigin + (uscale/nbdiv)*(i-1)
      *PtrV\v = vorigin + (vscale/nbdiv)*(j-1) + vscale/nbdiv
      *PtrV + SizeOf(Vertex) 

      ; 1 square = 2 triangles
      *ptrP\numVert1=numvert+3  
      *ptrP\numVert2=numvert+2
      *ptrP\numVert3=numvert 
      *ptrP + SizeOf(Polygon)

      *ptrP\numVert1=numvert  
      *ptrP\numVert2=numvert+2
      *ptrP\numVert3=numvert+1
      *ptrP + SizeOf(Polygon)
      
      numvert+4     

      z1=z4
      z2=z3
      z3+sizeDiv
      z4=z3

    Next j
    
    x1=x2
    x4=x3
    x2+sizeDiv
    x3=x2
    z1=-0.5
    z2=z1
    z3=-0.5+sizeDiv
    z4=z3
     
  Next i
  numvert0=numvert
  
  ; Bottom
  *PtrV0 = *vertexBuffer   
  For i=1 To numvert0
    *PtrV\px = -*PtrV0\px
    *PtrV\py = -*PtrV0\py
    *PtrV\pz = *PtrV0\pz  
    *PtrV\nx = *PtrV\px 
    *PtrV\ny = *PtrV\py
    *PtrV\nz = *PtrV\pz
    *PtrV\couleur = *PtrV0\couleur
    *PtrV\u = *PtrV0\u
    *PtrV\v = *PtrV0\v
    
    *PtrV + SizeOf(Vertex) 
    *PtrV0 + SizeOf(Vertex) 
    numvert+1
    
    If i%4=0
      *ptrP\numVert1=numvert - 2 
      *ptrP\numVert2=numvert - 3
      *ptrP\numVert3=numvert - 4 
      *ptrP + SizeOf(Polygon)  
    
      *ptrP\numVert1=numvert - 4 
      *ptrP\numVert2=numvert - 1
      *ptrP\numVert3=numvert - 2 
      *ptrP + SizeOf(Polygon)   
    EndIf
    
  Next i

  ; Right
  *PtrV0 = *vertexBuffer   
  For i=1 To numvert0
    *PtrV\px = *PtrV0\py
    *PtrV\py = -*PtrV0\px
    *PtrV\pz = *PtrV0\pz  
    *PtrV\nx = *PtrV\px 
    *PtrV\ny = *PtrV\py
    *PtrV\nz = *PtrV\pz
    *PtrV\couleur = *PtrV0\couleur
    *PtrV\u = 1-*PtrV0\v
    *PtrV\v = *PtrV0\u
    
    *PtrV + SizeOf(Vertex) 
    *PtrV0 + SizeOf(Vertex) 
    numvert+1
    
    If i%4=0
      *ptrP\numVert1=numvert - 2 
      *ptrP\numVert2=numvert - 3
      *ptrP\numVert3=numvert - 4 
      *ptrP + SizeOf(Polygon)  
     
      *ptrP\numVert1=numvert - 4 
      *ptrP\numVert2=numvert - 1
      *ptrP\numVert3=numvert - 2 
      *ptrP + SizeOf(Polygon)  
    EndIf
    
  Next i

  ; Left
  *PtrV0 = *vertexBuffer   
  For i=1 To numvert0
    *PtrV\px = -*PtrV0\py
    *PtrV\py = -*PtrV0\px
    *PtrV\pz = *PtrV0\pz  
    *PtrV\nx = *PtrV\px 
    *PtrV\ny = *PtrV\py
    *PtrV\nz = *PtrV\pz
    *PtrV\couleur = *PtrV0\couleur
    *PtrV\u = *PtrV0\v
    *PtrV\v = *PtrV0\u
    
    *PtrV + SizeOf(Vertex) 
    *PtrV0 + SizeOf(Vertex) 
    numvert+1
    
    If i%4=0
      *ptrP\numVert1=numvert - 4 
      *ptrP\numVert2=numvert - 3
      *ptrP\numVert3=numvert - 2 
      *ptrP + SizeOf(Polygon)  
    
      *ptrP\numVert1=numvert - 2 
      *ptrP\numVert2=numvert - 1
      *ptrP\numVert3=numvert - 4 
      *ptrP + SizeOf(Polygon)  
    EndIf
    
  Next i

  ; Front
  *PtrV0 = *vertexBuffer   
  For i=1 To numvert0
    *PtrV\px = -*PtrV0\pz
    *PtrV\py = -*PtrV0\px
    *PtrV\pz = -*PtrV0\py  
    *PtrV\nx = *PtrV\px 
    *PtrV\ny = *PtrV\py
    *PtrV\nz = *PtrV\pz
    *PtrV\couleur = *PtrV0\couleur
    *PtrV\u = *PtrV0\v
    *PtrV\v = *PtrV0\u
    
    *PtrV + SizeOf(Vertex) 
    *PtrV0 + SizeOf(Vertex) 
    numvert+1
    
    If i%4=0
      *ptrP\numVert1=numvert - 4 
      *ptrP\numVert2=numvert - 3
      *ptrP\numVert3=numvert - 2 
      *ptrP + SizeOf(Polygon)  
    
      *ptrP\numVert1=numvert - 2 
      *ptrP\numVert2=numvert - 1
      *ptrP\numVert3=numvert - 4 
      *ptrP + SizeOf(Polygon)  
    EndIf
    
  Next i
  
  ; Back
  *PtrV0 = *vertexBuffer   
  For i=1 To numvert0
    *PtrV\px = -*PtrV0\pz
    *PtrV\py = -*PtrV0\px
    *PtrV\pz = *PtrV0\py  
    *PtrV\nx = *PtrV\px 
    *PtrV\ny = *PtrV\py
    *PtrV\nz = *PtrV\pz
    *PtrV\couleur = *PtrV0\couleur
    *PtrV\u = 1-*PtrV0\v
    *PtrV\v = *PtrV0\u
    
    *PtrV + SizeOf(Vertex) 
    *PtrV0 + SizeOf(Vertex) 
    numvert+1
    
    If i%4=0
      *ptrP\numVert1=numvert - 2 
      *ptrP\numVert2=numvert - 3
      *ptrP\numVert3=numvert - 4 
      *ptrP + SizeOf(Polygon)  
    
      *ptrP\numVert1=numvert - 4 
      *ptrP\numVert2=numvert - 1
      *ptrP\numVert3=numvert - 2 
      *ptrP + SizeOf(Polygon)  
    EndIf
    
  Next i

  ; Resize
  If sizeX<>1 Or sizeY<>1 Or sizeZ<>1
    *ptrV = *vertexBuffer
    For i=1 To nbVert
      *PtrV\px = *PtrV\px*sizeX - pivotX
      *PtrV\py = *PtrV\py*sizeY - pivotY
      *PtrV\pz = *PtrV\pz*sizeZ - pivotZ
      
      *PtrV+SizeOf(vertex)
    Next i  
  EndIf

  ; Create mesh from stored infos
  maxSize = sizeX
  If sizeY > sizeX
    maxSize = sizeY
  EndIf
  If sizeZ > maxSize
    maxSize = sizeZ
  EndIf
  
  newMesh = CreateMesh(#PB_Any,maxSize)
  If IsMesh(newMesh) 
    SetMeshData(newMesh,#PB_Mesh_Vertex | #PB_Mesh_Normal | #PB_Mesh_UVCoordinate | #PB_Mesh_Color,*vertexBuffer,nbVert) 
    SetMeshData(newMesh,#PB_Mesh_Face,*polygonBuffer,nbTri)     
    FreeMemory(*vertexBuffer)
    FreeMemory(*polygonBuffer)
    ProcedureReturn newMesh
  Else 
    ; free memory if "createMesh" has failed
    FreeMemory(*vertexBuffer)
    FreeMemory(*polygonBuffer)
    ProcedureReturn -1    
  EndIf 

EndProcedure


;************************************************************************************
; Name: createCylinderMesh
; Purpose: create a cylinder mesh
; Parameters: 
;   - number of sides ("3" gives a prism, "4" gives a box)
;   - height
;   - radius
;   - uncapped (=0), caps on top an bottom (=1), top cap only (=2), bottom cap only (=3). (default = 1)
;   - color of the vertices (default = white)
; Return-Value: number of the resulting mesh, -1 if creation failed
;************************************************************************************
Procedure.l createCylinderMesh(nbSides.l,height.f,radius.f,capped.b = 1,coul.l = $FFFFFF)
  Protected *PtrV.Vertex,*vertexBuffer.l    ; vertices buffer in memory
  Protected *PtrF.Polygon,*facetriBuffer.l  ; Faces buffer in memory
  Protected i.l,nbVert.l,nbTri.l, numVertTop.l,numVertBottom.l
  Protected h2.f,theta.f
  Protected newmesh.l                       ; Procedure Result
   
  If nbSides<3
    ProcedureReturn 0
  EndIf

  h2 = height / 2.0
  nbVert = 4*(nbSides+1)+2
  If capped = #CYLCAP_TOP Or capped = #CYLCAP_BOTTOM
    nbVert-1
  Else
    If capped = #CYLCAP_NONE
      nbVert-2
    EndIf
  EndIf   
  
  *vertexBuffer = AllocateMemory(SizeOf(Vertex)*nbVert)
  *PtrV = *vertexBuffer
   
  ;Vertices at the bottom of the cylinder
  For i = 0 To nbSides
    theta =2*#PI*i/nbSides
     
    *PtrV\px = radius*Cos(theta)
    *PtrV\py = -h2
    *PtrV\pz = radius*Sin(theta)
    *PtrV\nx = Cos(theta)
    *PtrV\ny = 0
    *PtrV\nz = Sin(theta)
    *PtrV\couleur = Coul
    *PtrV\u = Theta / (2.0*#PI)
    *PtrV\v = 0
    *PtrV + SizeOf(Vertex)
  Next i

   
  ;Vertices at the top of the cylinder
  For i = 0 To nbSides
    theta =2*#PI*i/nbSides
     
    *PtrV\px = radius*Cos(theta)
    *PtrV\py = h2
    *PtrV\pz = radius*Sin(theta)
    *PtrV\nx = Cos(theta)
    *PtrV\ny = 0
    *PtrV\nz = Sin(theta)
    *PtrV\couleur = Coul
    *PtrV\u = Theta / (2.0*#PI)
    *PtrV\v = 1
    *PtrV + SizeOf(Vertex)
  Next i

      
  ;Vertices at the bottom of the cylinder
  For i = 0 To nbSides
    theta =2*#PI*i/nbSides
     
    *PtrV\px = radius*Cos(theta)
    *PtrV\py = -h2
    *PtrV\pz = radius*Sin(theta)
    *PtrV\nx = 0
    *PtrV\ny = -1
    *PtrV\nz = 0
    *PtrV\couleur = Coul
    *PtrV\u = Theta / (2.0*#PI)
    *PtrV\v = 1
    *PtrV + SizeOf(Vertex)
  Next i
               
  ;Vertices at the top of the cylinder
  For i = 0 To nbSides
    theta =2*#PI*i/nbSides
     
    *PtrV\px = radius*Cos(theta)
    *PtrV\py = h2
    *PtrV\pz = radius*Sin(theta)
    *PtrV\nx = 0
    *PtrV\ny = 1
    *PtrV\nz = 0
    *PtrV\couleur = Coul
    *PtrV\u = Theta / (2.0*#PI)
    *PtrV\v = 1
    *PtrV + SizeOf(Vertex)
  Next i
   
  ;Bottom cap center
  If capped = #CYLCAP_BOTH Or capped = #CYLCAP_BOTTOM
    numVertBottom = (*PtrV - *vertexBuffer) / SizeOf(Vertex)
    
    *PtrV\px = 0
    *PtrV\py = -h2
    *PtrV\pz = 0
    *PtrV\nx = 0
    *PtrV\ny = -1
    *PtrV\nz = 0
    *PtrV\couleur = Coul
    *PtrV\u = 0.5
    *PtrV\v = 0.5
    *PtrV + SizeOf(Vertex)
  EndIf
  
  ;Top cap center
  If capped = #CYLCAP_BOTH Or capped = #CYLCAP_TOP
    numVertTop = (*PtrV - *vertexBuffer) / SizeOf(Vertex)
    
    *PtrV\px = 0
    *PtrV\py = h2
    *PtrV\pz = 0
    *PtrV\nx = 0
    *PtrV\ny = 1
    *PtrV\nz = 0
    *PtrV\couleur = Coul
    *PtrV\u = 0.5
    *PtrV\v = 0.5
  EndIf 
   
  ;Facets
  nbTri = 4*nbSides
  If capped = #CYLCAP_BOTTOM Or capped = #CYLCAP_TOP
    nbTri - nbSides
  Else
    If capped = #CYLCAP_NONE
      nbTri - (nbSides*2)
    EndIf
  EndIf
    
  *facetriBuffer=AllocateMemory(SizeOf(Polygon)*nbTri)
  *PtrF=*facetriBuffer
  
  For i=0 To nbSides-1
      *PtrF\numVert3=i
      *PtrF\numVert2=i + 1
      *PtrF\numVert1=nbSides + i + 2
      *PtrF + SizeOf(Polygon)
    
    
      *PtrF\numVert1=i 
      *PtrF\numVert3=nbSides + i + 2
      *PtrF\numVert2=nbSides + i + 1
      *PtrF + SizeOf(Polygon)
  Next i
   
  
  ;Bottom cap
  If capped = #CYLCAP_BOTH Or capped = #CYLCAP_BOTTOM   
    For i=0 To nbSides-1
      *PtrF\numVert1= numVertBottom
      *PtrF\numVert2= 2 * nbSides + 2 + i
      *PtrF\numVert3= 2 * nbSides + 3 + i
      *PtrF + SizeOf(Polygon)
    Next i      
  EndIf 
  ;Top cap
  If capped = #CYLCAP_BOTH Or capped = #CYLCAP_TOP  
    For i=0 To nbSides-1
      *PtrF\numVert1= numVertTop
      *PtrF\numVert3= 3 * nbSides + 3 + i
      *PtrF\numVert2= 3 * nbSides + 4 + i
      *PtrF + SizeOf(Polygon)
    Next i      
  EndIf
  
  ; Create mesh from stored infos
  newmesh = CreateMesh(#PB_Any,radius)
  If IsMesh(newmesh) 
    SetMeshData(newmesh,#PB_Mesh_Vertex | #PB_Mesh_Normal | #PB_Mesh_UVCoordinate | #PB_Mesh_Color,*vertexBuffer,nbVert) 
    SetMeshData(newmesh,#PB_Mesh_Face,*facetriBuffer,nbTri) 
    ; and don't forget to free memory
    FreeMemory(*vertexBuffer)
    FreeMemory(*facetriBuffer)
    ProcedureReturn newmesh 
  Else 
    ; even if "createMesh" has failed
    FreeMemory(*vertexBuffer)
    FreeMemory(*facetriBuffer)
    ProcedureReturn -1    
  EndIf 
   
EndProcedure

DisableExplicit

;- ----- Main -----

;- Camera
CreateCamera(#CAMERA, 0, 0, 100, 100)
CameraLocate(#CAMERA, 50, 120, 0)
CameraLookAt(#CAMERA,0,0,0)

;- Light
AmbientColor(RGB(20,20,20))
CreateLight(0,RGB(255, 0, 0))
CreateLight(1,RGB(0, 255, 0))
CreateLight(2,RGB(0, 0, 255))
WorldShadows(#PB_Shadow_Additive)

;- Materials
Add3DArchive(".", #PB_3DArchive_FileSystem)
CreateImage(0,64,64)
StartDrawing(ImageOutput(0))
  Box(0,0,64,64,$FFFFFF)
StopDrawing()
SaveImage(0,"temp.bmp")
LoadTexture(0,"temp.bmp")
CreateMaterial(0,TextureID(0))
MaterialAmbientColor(0,#PB_Material_AmbientColors)

LoadFont(1, "Garamond", 48,#PB_Font_Bold|#PB_Font_HighQuality)
StartDrawing(ImageOutput(0))
DrawingMode(#PB_2DDrawing_Transparent)
DrawingFont(FontID(1))
For i = 1 To 12
  Box(0,0,64,64,$FFFFFF)
  If i<10
    DrawText(15,-5,Str(i),$000000)
  Else
    DrawText(5,-5,Str(i),$000000)
  EndIf
  SaveImage(0,"temp"+Str(i)+".bmp")
  LoadTexture(i,"temp"+Str(i)+".bmp")
  CreateMaterial(i,TextureID(i))   
Next i
StopDrawing()
FreeImage(0)

;- Meshes
groundmesh = CreatePlainMesh(20/#QUALITY,200,200)
gnomonMesh = createCylinderMesh(16/#QUALITY,20,2,#CYLCAP_TOP,$FFFFFF)
boxMesh = createBoxMesh(8/#QUALITY,15,20,1)

;- Entities
groundEntity = CreateEntity(#PB_Any,MeshID(groundmesh),MaterialID(0))
gnomonEntity = CreateEntity(#PB_Any,MeshID(gnomonMesh),MaterialID(0))
EntityLocate(gnomonEntity,0,10,0)

For i=1 To 12
  boxEntity(i) = CreateEntity(#PB_Any,MeshID(boxMesh),MaterialID(i))
  EntityLocate(boxEntity(i),50*Cos((180+30*i)*#DEG2RADMULT),10,50*Sin((180+30*i)*#DEG2RADMULT))
  RotateEntity(boxEntity(i),0,90 + i*-30,0)
Next i

;- **** MAIN LOOP *******************************************************************************
secs = Second(Date())
mins = Minute(Date()) + secs/60
hours = Hour(Date()) + mins/60 + secs/3600
oldtimer = ElapsedMilliseconds()
dist = 48
Repeat
  If FullScreen = #False 
    While WindowEvent() : Wend 
  EndIf  
  
  ;- Keyboard
  ExamineKeyboard()
  
  If KeyboardReleased(#PB_Key_F1)
    MessageRequester("Statistics",Str(CountRenderedTriangles()) + " polygons, " + Str(Engine3DFrameRate(#PB_Engine3D_Average)) + " Fps")
  EndIf

  ;- Move lights
  newtimer = ElapsedMilliseconds()
  movement = newtimer-oldtimer
  oldtimer = newtimer
  secs+movement/1000
  If secs>=60
    secs-60
  EndIf
  LightLocate(0,dist*Cos(secs*6*#DEG2RADMULT),10,dist*Sin(secs*6*#DEG2RADMULT))
  
  mins+movement/60000
  If mins>=60
    mins-60
  EndIf
  LightLocate(1,dist*Cos(mins*6*#DEG2RADMULT),10,dist*Sin(mins*6*#DEG2RADMULT))
  
  hours+movement/3600000
  If hours>=24
    hours-24
  EndIf
  LightLocate(2,dist*Cos(hours*30*#DEG2RADMULT),10,dist*Sin(hours*30*#DEG2RADMULT))

  ; Show it all
  RenderWorld()
  
  ; Flip buffers to avoid tearing  
  FlipBuffers()
  
  Delay(1)
Until KeyboardPushed(#PB_Key_Escape)
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

superbe !!

sur mon nc10 j'ai un plantage si je choisi plein ecran !!
mais pas en mode fenetré :)
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Message par Le Soldat Inconnu »

Extra, j'ai fais mumuse avec les couleurs et la position des lumières

Code : Tout sélectionner

;- Initialization

If InitEngine3D() = 0
  MessageRequester( "Error", "Can't initialize 3D, check if engine3D.dll is available", 0 )
  End
ElseIf InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0
  MessageRequester( "Error", "Can't find DirectX 7.0 or above", 0 )
  End
EndIf

ExamineDesktops()
OpenScreen(DesktopWidth(0), DesktopHeight(0), DesktopDepth(0), "Light Clock")

#CAMERA = 0
#RAD2DEGMULT = 57.295779513082320877 ; (180/#PI)
#DEG2RADMULT = 0.0174532925199432958 ; (#PI/180)
#QUALITY = 1 ; 1 = good, 2 = medium, 3 = low, 4 = mini

; Cylinder mesh caps
Enumeration
  #CYLCAP_NONE
  #CYLCAP_BOTH
  #CYLCAP_TOP
  #CYLCAP_BOTTOM
EndEnumeration


;- Structures and global definitions
Structure Vertex
  px.f
  py.f
  pz.f
  nx.f
  ny.f
  nz.f
  Couleur.l
  u.f
  V.f
EndStructure

Structure Polygon
  numVert1.w
  numVert2.w
  numVert3.w
EndStructure

Global groundMesh.i, gnomonMesh.i, boxMesh.i
Global groundEntity.i, gnomonEntity.i
Global Dim boxEntity.i(12)
Global hours.f, mins.f, secs.f
Global oldTimer.i, newTimer.i, movement.i
Global dist.f, i.i
;- ------ Procedures ------
EnableExplicit

;- -- Meshes and entities --

; ************************************************************************************
; Name: createPlainMesh
; Purpose: creates a plain
; Parameters:
;- number of subdivisions (given "3", the plain will be a 3x3 grid)
;- sizeX, sizeZ : size of the box
;- pivotX, pivotZ : location of the pivot of the box, around which it rotates (default = center = 0,0)
;- Uorigin, Vorigin : UV map coordinates (default = top left of the map = 0,0)
;- Uscale, Vscale : UV map scale (default = 1,1)
;- color of the vertices (default = white)
; Return-Value: number of the resulting mesh, -1 if creation failed
; ************************************************************************************
Procedure.l createPlainMesh(nbdiv.w, sizeX.f, sizeZ.f, pivotX.f = 0, pivotZ.f = 0, Uorigin.f = 0, Vorigin.f = 0, Uscale.f = 1, Vscale.f = 1, Color.l = $FFFFFF)
  
  Protected sizediv.f
  Protected x1.f, y1.f, z1.f ; vertex position
  Protected x2.f, y2.f, z2.f ; vertex position
  Protected x3.f, y3.f, z3.f ; vertex position
  Protected x4.f, y4.f, z4.f ; vertex position
  Protected nx.f, ny.f, nz.f ; vertex normals
  Protected u.f, V.f ; vertex UV coords (texture mapping)
  Protected numvert.w, numvert0.w ; vertices of a poly
  Protected * PtrV.Vertex, *PtrV0.Vertex ; vertices buffer in memory
  Protected * ptrP.Polygon, *ptrP0.Polygon ; Polys buffer in memory
  Protected * vertexBuffer.l
  Protected * polygonBuffer.l
  Protected num.l, i.l, j.l, nbtri.l, nbvert
  Protected maxSize.f
  Protected newmesh.l ; Procedure Result
  
  nbtri = (nbdiv * nbdiv * 2) ; nb divisions * nb divisions * 2 triangles per division
  nbvert = (nbdiv * nbdiv * 4) ; nb divisions * nb divisions * 4 vertices per division
  
  ; Allocate the needed memory for vertices
  *vertexBuffer = AllocateMemory(SizeOf(Vertex) * nbvert)
  *PtrV = *vertexBuffer
  
  ; Allocate the needed memory for faces info
  *polygonBuffer = AllocateMemory(SizeOf(Polygon) * nbtri)
  *ptrP = *polygonBuffer
  
  sizediv = 1 / nbdiv
  ; Top
  x1 = -0.5 : y1 = 0 : z1 = -0.5
  x2 = -0.5 + sizediv : y2 = 0 : z2 = z1
  x3 = x2 : y3 = 0 : z3 = -0.5 + sizediv
  x4 = x1 : y4 = 0 : z4 = z3
  
  For i = 1 To nbdiv
    For j = 1 To nbdiv
      
      ; 1 square = 4 vertices
      *PtrV\px = x1
      *PtrV\py = y1
      *PtrV\pz = z1
      *PtrV\nx = 0
      *PtrV\ny = 0.5
      *PtrV\nz = 0
      *PtrV\Couleur = Color
      *PtrV\u = Uorigin + (Uscale / nbdiv) * (i - 1)
      *PtrV\V = Vorigin + (Vscale / nbdiv) * (j - 1)
      *PtrV + SizeOf(Vertex)
      
      *PtrV\px = x2
      *PtrV\py = y2
      *PtrV\pz = z2
      *PtrV\nx = 0
      *PtrV\ny = 0.5
      *PtrV\nz = 0
      *PtrV\Couleur = Color
      *PtrV\u = Uorigin + (Uscale / nbdiv) * (i - 1) + Uscale / nbdiv
      *PtrV\V = Vorigin + (Vscale / nbdiv) * (j - 1)
      *PtrV + SizeOf(Vertex)
      
      *PtrV\px = x3
      *PtrV\py = y3
      *PtrV\pz = z3
      *PtrV\nx = 0
      *PtrV\ny = 0.5
      *PtrV\nz = 0
      *PtrV\Couleur = Color
      *PtrV\u = Uorigin + (Uscale / nbdiv) * (i - 1) + Uscale / nbdiv
      *PtrV\V = Vorigin + (Vscale / nbdiv) * (j - 1) + Vscale / nbdiv
      *PtrV + SizeOf(Vertex)
      
      *PtrV\px = x4
      *PtrV\py = y4
      *PtrV\pz = z4
      *PtrV\nx = 0
      *PtrV\ny = 0.5
      *PtrV\nz = 0
      *PtrV\Couleur = Color
      *PtrV\u = Uorigin + (Uscale / nbdiv) * (i - 1)
      *PtrV\V = Vorigin + (Vscale / nbdiv) * (j - 1) + Vscale / nbdiv
      *PtrV + SizeOf(Vertex)
      
      ; 1 square = 2 triangles
      *ptrP\numVert1 = numvert + 3
      *ptrP\numVert2 = numvert + 2
      *ptrP\numVert3 = numvert
      *ptrP + SizeOf(Polygon)
      
      *ptrP\numVert1 = numvert
      *ptrP\numVert2 = numvert + 2
      *ptrP\numVert3 = numvert + 1
      *ptrP + SizeOf(Polygon)
      
      numvert + 4
      
      z1 = z4
      z2 = z3
      z3 + sizediv
      z4 = z3
      
    Next j
    
    x1 = x2
    x4 = x3
    x2 + sizediv
    x3 = x2
    z1 = -0.5
    z2 = z1
    z3 = -0.5 + sizediv
    z4 = z3
    
  Next i
  numvert0 = numvert
  
  
  ; Resize
  If sizeX <> 1 Or sizeZ <> 1
    *PtrV = *vertexBuffer
    For i = 1 To nbvert
      *PtrV\px = *PtrV\px * sizeX - pivotX
      *PtrV\pz = *PtrV\pz * sizeZ - pivotZ
      
      *PtrV + SizeOf(Vertex)
    Next i
  EndIf
  
  ; Create mesh from stored infos
  maxSize = sizeX
  If sizeZ > maxSize
    maxSize = sizeZ
  EndIf
  
  newmesh = CreateMesh(#PB_Any, maxSize)
  If IsMesh(newmesh)
    SetMeshData(newmesh, #PB_Mesh_Vertex | #PB_Mesh_Normal | #PB_Mesh_UVCoordinate | #PB_Mesh_Color, *vertexBuffer, nbvert)
    SetMeshData(newmesh, #PB_Mesh_Face, *polygonBuffer, nbtri)
    FreeMemory(*vertexBuffer)
    FreeMemory(*polygonBuffer)
    ProcedureReturn newmesh
  Else
    ; free memory if "createMesh" has failed
    FreeMemory(*vertexBuffer)
    FreeMemory(*polygonBuffer)
    ProcedureReturn - 1
  EndIf
  
EndProcedure
; ************************************************************************************
; Name: createBoxMesh
; Purpose: creates a "box" mesh
; Parameters:
;- number of subdivisions (given "3", each face of the box will be a 3x3 grid)
;- sizeX, sizeY, sizeZ : size of the box
;- pivotX, pivotY, pivotZ : location of the pivot of the box, around which it rotates (default = center = 0,0,0)
;- Uorigin, Vorigin : UV map coordinates (default = top left of the map = 0,0)
;- Uscale, Vscale : UV map scale (default = 1,1)
;- color of the vertices (default = white)
; Return-Value: number of the resulting mesh, -1 if creation failed
; ************************************************************************************
Procedure.l createBoxMesh(nbdiv.w, sizeX.f, sizeY.f, sizeZ.f, pivotX.f = 0, pivotY.f = 0, pivotZ.f = 0, Uorigin.f = 0, Vorigin.f = 0, Uscale.f = 1, Vscale.f = 1, Color.l = $FFFFFF)
  
  Protected sizediv.f
  Protected x1.f, y1.f, z1.f ; vertex position
  Protected x2.f, y2.f, z2.f ; vertex position
  Protected x3.f, y3.f, z3.f ; vertex position
  Protected x4.f, y4.f, z4.f ; vertex position
  Protected nx.f, ny.f, nz.f ; vertex normals
  Protected u.f, V.f ; vertex UV coords (texture mapping)
  Protected numvert.w, numvert0.w ; vertices of a poly
  Protected * PtrV.Vertex, *PtrV0.Vertex ; vertices buffer in memory
  Protected * ptrP.Polygon, *ptrP0.Polygon ; Polys buffer in memory
  Protected * vertexBuffer.l
  Protected * polygonBuffer.l
  Protected num.l, i.l, j.l, nbtri.l, nbvert
  Protected maxSize.f
  Protected newmesh.l ; Procedure Result
  
  nbtri = 6 * (nbdiv * nbdiv * 2) ; 6 sides * nb divisions * nb divisions * 2 triangles per division
  nbvert = 6 * (nbdiv * nbdiv * 4) ; 6 sides * nb divisions * nb divisions * 4 vertices per division
  
  ; Allocate the needed memory for vertices
  *vertexBuffer = AllocateMemory(SizeOf(Vertex) * nbvert)
  *PtrV = *vertexBuffer
  
  ; Allocate the needed memory for faces info
  *polygonBuffer = AllocateMemory(SizeOf(Polygon) * nbtri)
  *ptrP = *polygonBuffer
  
  sizediv = 1 / nbdiv
  ; Top
  x1 = -0.5 : y1 = 0.5 : z1 = -0.5
  x2 = -0.5 + sizediv : y2 = 0.5 : z2 = z1
  x3 = x2 : y3 = 0.5 : z3 = -0.5 + sizediv
  x4 = x1 : y4 = 0.5 : z4 = z3
  
  For i = 1 To nbdiv
    For j = 1 To nbdiv
      
      ; 1 square = 4 vertices
      *PtrV\px = x1
      *PtrV\py = y1
      *PtrV\pz = z1
      *PtrV\nx = *PtrV\px
      *PtrV\ny = *PtrV\py
      *PtrV\nz = *PtrV\pz
      *PtrV\Couleur = Color
      *PtrV\u = Uorigin + (Uscale / nbdiv) * (i - 1)
      *PtrV\V = Vorigin + (Vscale / nbdiv) * (j - 1)
      *PtrV + SizeOf(Vertex)
      
      *PtrV\px = x2
      *PtrV\py = y2
      *PtrV\pz = z2
      *PtrV\nx = *PtrV\px
      *PtrV\ny = *PtrV\py
      *PtrV\nz = *PtrV\pz
      *PtrV\Couleur = Color
      *PtrV\u = Uorigin + (Uscale / nbdiv) * (i - 1) + Uscale / nbdiv
      *PtrV\V = Vorigin + (Vscale / nbdiv) * (j - 1)
      *PtrV + SizeOf(Vertex)
      
      *PtrV\px = x3
      *PtrV\py = y3
      *PtrV\pz = z3
      *PtrV\nx = *PtrV\px
      *PtrV\ny = *PtrV\py
      *PtrV\nz = *PtrV\pz
      *PtrV\Couleur = Color
      *PtrV\u = Uorigin + (Uscale / nbdiv) * (i - 1) + Uscale / nbdiv
      *PtrV\V = Vorigin + (Vscale / nbdiv) * (j - 1) + Vscale / nbdiv
      *PtrV + SizeOf(Vertex)
      
      *PtrV\px = x4
      *PtrV\py = y4
      *PtrV\pz = z4
      *PtrV\nx = *PtrV\px
      *PtrV\ny = *PtrV\py
      *PtrV\nz = *PtrV\pz
      *PtrV\Couleur = Color
      *PtrV\u = Uorigin + (Uscale / nbdiv) * (i - 1)
      *PtrV\V = Vorigin + (Vscale / nbdiv) * (j - 1) + Vscale / nbdiv
      *PtrV + SizeOf(Vertex)
      
      ; 1 square = 2 triangles
      *ptrP\numVert1 = numvert + 3
      *ptrP\numVert2 = numvert + 2
      *ptrP\numVert3 = numvert
      *ptrP + SizeOf(Polygon)
      
      *ptrP\numVert1 = numvert
      *ptrP\numVert2 = numvert + 2
      *ptrP\numVert3 = numvert + 1
      *ptrP + SizeOf(Polygon)
      
      numvert + 4
      
      z1 = z4
      z2 = z3
      z3 + sizediv
      z4 = z3
      
    Next j
    
    x1 = x2
    x4 = x3
    x2 + sizediv
    x3 = x2
    z1 = -0.5
    z2 = z1
    z3 = -0.5 + sizediv
    z4 = z3
    
  Next i
  numvert0 = numvert
  
  ; Bottom
  *PtrV0 = *vertexBuffer
  For i = 1 To numvert0
    *PtrV\px = - * PtrV0\px
    *PtrV\py = - * PtrV0\py
    *PtrV\pz = *PtrV0\pz
    *PtrV\nx = *PtrV\px
    *PtrV\ny = *PtrV\py
    *PtrV\nz = *PtrV\pz
    *PtrV\Couleur = *PtrV0\Couleur
    *PtrV\u = *PtrV0\u
    *PtrV\V = *PtrV0\V
    
    *PtrV + SizeOf(Vertex)
    *PtrV0 + SizeOf(Vertex)
    numvert + 1
    
    If i %4 = 0
      *ptrP\numVert1 = numvert - 2
      *ptrP\numVert2 = numvert - 3
      *ptrP\numVert3 = numvert - 4
      *ptrP + SizeOf(Polygon)
      
      *ptrP\numVert1 = numvert - 4
      *ptrP\numVert2 = numvert - 1
      *ptrP\numVert3 = numvert - 2
      *ptrP + SizeOf(Polygon)
    EndIf
    
  Next i
  
  ; Right
  *PtrV0 = *vertexBuffer
  For i = 1 To numvert0
    *PtrV\px = *PtrV0\py
    *PtrV\py = - * PtrV0\px
    *PtrV\pz = *PtrV0\pz
    *PtrV\nx = *PtrV\px
    *PtrV\ny = *PtrV\py
    *PtrV\nz = *PtrV\pz
    *PtrV\Couleur = *PtrV0\Couleur
    *PtrV\u = 1 - * PtrV0\V
    *PtrV\V = *PtrV0\u
    
    *PtrV + SizeOf(Vertex)
    *PtrV0 + SizeOf(Vertex)
    numvert + 1
    
    If i %4 = 0
      *ptrP\numVert1 = numvert - 2
      *ptrP\numVert2 = numvert - 3
      *ptrP\numVert3 = numvert - 4
      *ptrP + SizeOf(Polygon)
      
      *ptrP\numVert1 = numvert - 4
      *ptrP\numVert2 = numvert - 1
      *ptrP\numVert3 = numvert - 2
      *ptrP + SizeOf(Polygon)
    EndIf
    
  Next i
  
  ; Left
  *PtrV0 = *vertexBuffer
  For i = 1 To numvert0
    *PtrV\px = - * PtrV0\py
    *PtrV\py = - * PtrV0\px
    *PtrV\pz = *PtrV0\pz
    *PtrV\nx = *PtrV\px
    *PtrV\ny = *PtrV\py
    *PtrV\nz = *PtrV\pz
    *PtrV\Couleur = *PtrV0\Couleur
    *PtrV\u = *PtrV0\V
    *PtrV\V = *PtrV0\u
    
    *PtrV + SizeOf(Vertex)
    *PtrV0 + SizeOf(Vertex)
    numvert + 1
    
    If i %4 = 0
      *ptrP\numVert1 = numvert - 4
      *ptrP\numVert2 = numvert - 3
      *ptrP\numVert3 = numvert - 2
      *ptrP + SizeOf(Polygon)
      
      *ptrP\numVert1 = numvert - 2
      *ptrP\numVert2 = numvert - 1
      *ptrP\numVert3 = numvert - 4
      *ptrP + SizeOf(Polygon)
    EndIf
    
  Next i
  
  ; Front
  *PtrV0 = *vertexBuffer
  For i = 1 To numvert0
    *PtrV\px = - * PtrV0\pz
    *PtrV\py = - * PtrV0\px
    *PtrV\pz = - * PtrV0\py
    *PtrV\nx = *PtrV\px
    *PtrV\ny = *PtrV\py
    *PtrV\nz = *PtrV\pz
    *PtrV\Couleur = *PtrV0\Couleur
    *PtrV\u = *PtrV0\V
    *PtrV\V = *PtrV0\u
    
    *PtrV + SizeOf(Vertex)
    *PtrV0 + SizeOf(Vertex)
    numvert + 1
    
    If i %4 = 0
      *ptrP\numVert1 = numvert - 4
      *ptrP\numVert2 = numvert - 3
      *ptrP\numVert3 = numvert - 2
      *ptrP + SizeOf(Polygon)
      
      *ptrP\numVert1 = numvert - 2
      *ptrP\numVert2 = numvert - 1
      *ptrP\numVert3 = numvert - 4
      *ptrP + SizeOf(Polygon)
    EndIf
    
  Next i
  
  ; Back
  *PtrV0 = *vertexBuffer
  For i = 1 To numvert0
    *PtrV\px = - * PtrV0\pz
    *PtrV\py = - * PtrV0\px
    *PtrV\pz = *PtrV0\py
    *PtrV\nx = *PtrV\px
    *PtrV\ny = *PtrV\py
    *PtrV\nz = *PtrV\pz
    *PtrV\Couleur = *PtrV0\Couleur
    *PtrV\u = 1 - * PtrV0\V
    *PtrV\V = *PtrV0\u
    
    *PtrV + SizeOf(Vertex)
    *PtrV0 + SizeOf(Vertex)
    numvert + 1
    
    If i %4 = 0
      *ptrP\numVert1 = numvert - 2
      *ptrP\numVert2 = numvert - 3
      *ptrP\numVert3 = numvert - 4
      *ptrP + SizeOf(Polygon)
      
      *ptrP\numVert1 = numvert - 4
      *ptrP\numVert2 = numvert - 1
      *ptrP\numVert3 = numvert - 2
      *ptrP + SizeOf(Polygon)
    EndIf
    
  Next i
  
  ; Resize
  If sizeX <> 1 Or sizeY <> 1 Or sizeZ <> 1
    *PtrV = *vertexBuffer
    For i = 1 To nbvert
      *PtrV\px = *PtrV\px * sizeX - pivotX
      *PtrV\py = *PtrV\py * sizeY - pivotY
      *PtrV\pz = *PtrV\pz * sizeZ - pivotZ
      
      *PtrV + SizeOf(Vertex)
    Next i
  EndIf
  
  ; Create mesh from stored infos
  maxSize = sizeX
  If sizeY > sizeX
    maxSize = sizeY
  EndIf
  If sizeZ > maxSize
    maxSize = sizeZ
  EndIf
  
  newmesh = CreateMesh(#PB_Any, maxSize)
  If IsMesh(newmesh)
    SetMeshData(newmesh, #PB_Mesh_Vertex | #PB_Mesh_Normal | #PB_Mesh_UVCoordinate | #PB_Mesh_Color, *vertexBuffer, nbvert)
    SetMeshData(newmesh, #PB_Mesh_Face, *polygonBuffer, nbtri)
    FreeMemory(*vertexBuffer)
    FreeMemory(*polygonBuffer)
    ProcedureReturn newmesh
  Else
    ; free memory if "createMesh" has failed
    FreeMemory(*vertexBuffer)
    FreeMemory(*polygonBuffer)
    ProcedureReturn - 1
  EndIf
  
EndProcedure


; ************************************************************************************
; Name: createCylinderMesh
; Purpose: create a cylinder mesh
; Parameters:
;- number of sides ("3" gives a prism, "4" gives a box)
;- height
;- radius
;- uncapped (=0), caps on top an bottom (=1), top cap only (=2), bottom cap only (=3). (default = 1)
;- color of the vertices (default = white)
; Return-Value: number of the resulting mesh, -1 if creation failed
; ************************************************************************************
Procedure.l createCylinderMesh(nbSides.l, height.f, Radius.f, capped.b = 1, coul.l = $FFFFFF)
  Protected * PtrV.Vertex, *vertexBuffer.l ; vertices buffer in memory
  Protected * PtrF.Polygon, *facetriBuffer.l ; Faces buffer in memory
  Protected i.l, nbvert.l, nbtri.l, numVertTop.l, numVertBottom.l
  Protected h2.f, theta.f
  Protected newmesh.l ; Procedure Result
  
  If nbSides < 3
    ProcedureReturn 0
  EndIf
  
  h2 = height / 2.0
  nbvert = 4 * (nbSides + 1) + 2
  If capped = #CYLCAP_TOP Or capped = #CYLCAP_BOTTOM
    nbvert - 1
  Else
    If capped = #CYLCAP_NONE
      nbvert - 2
    EndIf
  EndIf
  
  *vertexBuffer = AllocateMemory(SizeOf(Vertex) * nbvert)
  *PtrV = *vertexBuffer
  
  ; Vertices at the bottom of the cylinder
  For i = 0 To nbSides
    theta = 2 * #PI * i / nbSides
    
    *PtrV\px = Radius * Cos(theta)
    *PtrV\py = -h2
    *PtrV\pz = Radius * Sin(theta)
    *PtrV\nx = Cos(theta)
    *PtrV\ny = 0
    *PtrV\nz = Sin(theta)
    *PtrV\Couleur = coul
    *PtrV\u = theta / (2.0 * #PI)
    *PtrV\V = 0
    *PtrV + SizeOf(Vertex)
  Next i
  
  
  ; Vertices at the top of the cylinder
  For i = 0 To nbSides
    theta = 2 * #PI * i / nbSides
    
    *PtrV\px = Radius * Cos(theta)
    *PtrV\py = h2
    *PtrV\pz = Radius * Sin(theta)
    *PtrV\nx = Cos(theta)
    *PtrV\ny = 0
    *PtrV\nz = Sin(theta)
    *PtrV\Couleur = coul
    *PtrV\u = theta / (2.0 * #PI)
    *PtrV\V = 1
    *PtrV + SizeOf(Vertex)
  Next i
  
  
  ; Vertices at the bottom of the cylinder
  For i = 0 To nbSides
    theta = 2 * #PI * i / nbSides
    
    *PtrV\px = Radius * Cos(theta)
    *PtrV\py = -h2
    *PtrV\pz = Radius * Sin(theta)
    *PtrV\nx = 0
    *PtrV\ny = -1
    *PtrV\nz = 0
    *PtrV\Couleur = coul
    *PtrV\u = theta / (2.0 * #PI)
    *PtrV\V = 1
    *PtrV + SizeOf(Vertex)
  Next i
  
  ; Vertices at the top of the cylinder
  For i = 0 To nbSides
    theta = 2 * #PI * i / nbSides
    
    *PtrV\px = Radius * Cos(theta)
    *PtrV\py = h2
    *PtrV\pz = Radius * Sin(theta)
    *PtrV\nx = 0
    *PtrV\ny = 1
    *PtrV\nz = 0
    *PtrV\Couleur = coul
    *PtrV\u = theta / (2.0 * #PI)
    *PtrV\V = 1
    *PtrV + SizeOf(Vertex)
  Next i
  
  ; Bottom cap center
  If capped = #CYLCAP_BOTH Or capped = #CYLCAP_BOTTOM
    numVertBottom = (*PtrV - * vertexBuffer) / SizeOf(Vertex)
    
    *PtrV\px = 0
    *PtrV\py = -h2
    *PtrV\pz = 0
    *PtrV\nx = 0
    *PtrV\ny = -1
    *PtrV\nz = 0
    *PtrV\Couleur = coul
    *PtrV\u = 0.5
    *PtrV\V = 0.5
    *PtrV + SizeOf(Vertex)
  EndIf
  
  ; Top cap center
  If capped = #CYLCAP_BOTH Or capped = #CYLCAP_TOP
    numVertTop = (*PtrV - * vertexBuffer) / SizeOf(Vertex)
    
    *PtrV\px = 0
    *PtrV\py = h2
    *PtrV\pz = 0
    *PtrV\nx = 0
    *PtrV\ny = 1
    *PtrV\nz = 0
    *PtrV\Couleur = coul
    *PtrV\u = 0.5
    *PtrV\V = 0.5
  EndIf
  
  ; Facets
  nbtri = 4 * nbSides
  If capped = #CYLCAP_BOTTOM Or capped = #CYLCAP_TOP
    nbtri - nbSides
  Else
    If capped = #CYLCAP_NONE
      nbtri - (nbSides * 2)
    EndIf
  EndIf
  
  *facetriBuffer = AllocateMemory(SizeOf(Polygon) * nbtri)
  *PtrF = *facetriBuffer
  
  For i = 0 To nbSides - 1
    *PtrF\numVert3 = i
    *PtrF\numVert2 = i + 1
    *PtrF\numVert1 = nbSides + i + 2
    *PtrF + SizeOf(Polygon)
    
    
    *PtrF\numVert1 = i
    *PtrF\numVert3 = nbSides + i + 2
    *PtrF\numVert2 = nbSides + i + 1
    *PtrF + SizeOf(Polygon)
  Next i
  
  
  ; Bottom cap
  If capped = #CYLCAP_BOTH Or capped = #CYLCAP_BOTTOM
    For i = 0 To nbSides - 1
      *PtrF\numVert1 = numVertBottom
      *PtrF\numVert2 = 2 * nbSides + 2 + i
      *PtrF\numVert3 = 2 * nbSides + 3 + i
      *PtrF + SizeOf(Polygon)
    Next i
  EndIf
  ; Top cap
  If capped = #CYLCAP_BOTH Or capped = #CYLCAP_TOP
    For i = 0 To nbSides - 1
      *PtrF\numVert1 = numVertTop
      *PtrF\numVert3 = 3 * nbSides + 3 + i
      *PtrF\numVert2 = 3 * nbSides + 4 + i
      *PtrF + SizeOf(Polygon)
    Next i
  EndIf
  
  ; Create mesh from stored infos
  newmesh = CreateMesh(#PB_Any, Radius)
  If IsMesh(newmesh)
    SetMeshData(newmesh, #PB_Mesh_Vertex | #PB_Mesh_Normal | #PB_Mesh_UVCoordinate | #PB_Mesh_Color, *vertexBuffer, nbvert)
    SetMeshData(newmesh, #PB_Mesh_Face, *facetriBuffer, nbtri)
    ; and don't forget to free memory
    FreeMemory(*vertexBuffer)
    FreeMemory(*facetriBuffer)
    ProcedureReturn newmesh
  Else
    ; even if "createMesh" has failed
    FreeMemory(*vertexBuffer)
    FreeMemory(*facetriBuffer)
    ProcedureReturn - 1
  EndIf
  
EndProcedure

DisableExplicit

;- ----- Main -----

;- Camera
CreateCamera(#CAMERA, 0, 0, 100, 100)
CameraLocate(#CAMERA, 50, 140, 0)
CameraLookAt(#CAMERA, 0, 0, 0)

;- Light
AmbientColor(0)
CreateLight(0, $FF9090)
CreateLight(1, $9090FF)
CreateLight(2, $90FF90)
WorldShadows(#PB_Shadow_Additive)

;- Materials
Add3DArchive(".", #PB_3DArchive_FileSystem)
CreateImage(0, 64, 64)
StartDrawing(ImageOutput(0))
  Box(0, 0, 64, 64, $FFFFFF)
StopDrawing()
SaveImage(0, "temp.bmp")
LoadTexture(0, "temp.bmp")
CreateMaterial(0, TextureID(0))
MaterialAmbientColor(0, #PB_Material_AmbientColors)

LoadFont(1, "Garamond", 48, #PB_Font_Bold | #PB_Font_HighQuality)
StartDrawing(ImageOutput(0))
  DrawingMode(#PB_2DDrawing_Transparent)
  DrawingFont(FontID(1))
  For i = 1 To 12
    Box(0, 0, 64, 64, $FFFFFF)
    If i < 10
      DrawText(15, -5, Str(i), $000000)
    Else
      DrawText(5, -5, Str(i), $000000)
    EndIf
    SaveImage(0, "temp" + Str(i) + ".bmp")
    LoadTexture(i, "temp" + Str(i) + ".bmp")
    CreateMaterial(i, TextureID(i))
  Next i
StopDrawing()
FreeImage(0)

;- Meshes
groundMesh = createPlainMesh(20 / #QUALITY, 200, 200)
gnomonMesh = createCylinderMesh(16 / #QUALITY, 20, 2, #CYLCAP_TOP, $FFFFFF)
boxMesh = createBoxMesh(8 / #QUALITY, 15, 20, 1)

;- Entities
groundEntity = CreateEntity(#PB_Any, MeshID(groundMesh), MaterialID(0))
gnomonEntity = CreateEntity(#PB_Any, MeshID(gnomonMesh), MaterialID(0))
EntityLocate(gnomonEntity, 0, 10, 0)

For i = 1 To 12
  boxEntity(i) = CreateEntity(#PB_Any, MeshID(boxMesh), MaterialID(i))
  EntityLocate(boxEntity(i), 50 * Cos((180 + 30 * i) * #DEG2RADMULT), 10, 50 * Sin((180 + 30 * i) * #DEG2RADMULT))
  RotateEntity(boxEntity(i), 0, 90 + i * - 30, 0)
Next i

;- **** MAIN LOOP *******************************************************************************
secs = Second(Date())
mins = Minute(Date()) + secs / 60
hours = Hour(Date()) + mins / 60 + secs / 3600
oldTimer = ElapsedMilliseconds()
dist = 35
haut = 20
Repeat
  If FullScreen = #False
    While WindowEvent() : Wend
  EndIf
  
  ;- Keyboard
  ExamineKeyboard()
  
  If KeyboardReleased(#PB_Key_F1)
    MessageRequester("Statistics", Str(CountRenderedTriangles()) + " polygons, " + Str(Engine3DFrameRate(#PB_Engine3D_Average)) + " Fps")
  EndIf
  
  ;- Move lights
  newTimer = ElapsedMilliseconds()
  movement = newTimer - oldTimer
  oldTimer = newTimer
  secs + movement / 1000
  If secs >= 60
    secs - 60
  EndIf
  LightLocate(0, dist * Cos(secs * 6 * #DEG2RADMULT), haut, dist * Sin(secs * 6 * #DEG2RADMULT))
  
  mins + movement / 60000
  If mins >= 60
    mins - 60
  EndIf
  LightLocate(1, dist * Cos(mins * 6 * #DEG2RADMULT), haut, dist * Sin(mins * 6 * #DEG2RADMULT))
  
  hours + movement / 3600000
  If hours >= 24
    hours - 24
  EndIf
  LightLocate(2, dist * Cos(hours * 30 * #DEG2RADMULT), dist / 2, dist * Sin(hours * 30 * #DEG2RADMULT))
  
  ; Show it all
  RenderWorld()
  
  ; Flip buffers to avoid tearing
  FlipBuffers()
  
  Delay(1)
Until KeyboardPushed(#PB_Key_Escape)
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Message par Le Soldat Inconnu »

Dobro, j'ai fait une retouche sur la taille de l'écran.

Essai voir sur ton NC maintenant, ca doit marcher fullscreen :)
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
tmyke
Messages : 1554
Inscription : lun. 24/juil./2006 6:44
Localisation : vosges (France) 47°54'39.06"N 6°20'06.39"E

Message par tmyke »

excellent code kelebrindae, très chouette bravo :)
(marche nickel sur mon petit portable Fullscreen et en fenêtre).
Force et sagesse...
kelebrindae
Messages : 579
Inscription : ven. 11/mai/2007 15:21

Message par kelebrindae »

Merci à tous! :D

J'ai fait des petites retouches:
- J'ai repris la modif' du Soldat Inconnu pour la position des lumières, c'est plus joli comme ça;
- Pour les chiffres, j'ai troqué la police "Garamond" (qui n'est pas forcément présente sur le PC) pour le "Times New Roman" (plus standard).

Par contre,

Code : Tout sélectionner

ExamineDesktops()
OpenScreen(DesktopWidth(0), DesktopHeight(0), DesktopDepth(0), "Light Clock")
ne marche pas chez moi. :(
Du coup, je ne l'ai pas repris, mais ça oblige à modifier la résolution "full screen" à la main dans le code (ligne 19) si ça plante. C'est pas génial...

Code mis à jour:

Code : Tout sélectionner

;- Initialization
Global FullScreen.b
Resultat = MessageRequester("Light Clock","Full Screen ?",#PB_MessageRequester_YesNo)
If Resultat = 6     
  FullScreen=#True
Else           
  FullScreen=#False
EndIf

If InitEngine3D() = 0
  MessageRequester( "Error" , "Can't initialize 3D, check if engine3D.dll is available" , 0 )
End
ElseIf InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0
  MessageRequester( "Error" , "Can't find DirectX 7.0 or above" , 0 )
  End
EndIf

If Fullscreen = #True
  OpenScreen(1440,900,32,"Light Clock")
Else
  OpenWindow(0,0, 0, 800 , 600 ,"Light Clock")
  OpenWindowedScreen(WindowID(0),0,0, 800 , 600,0,0,0)
EndIf

#CAMERA = 0
#RAD2DEGMULT = 57.295779513082320877  ;(180/#PI)
#DEG2RADMULT = 0.0174532925199432958  ;(#PI/180)
#QUALITY = 1  ; 1 = good, 2 = medium, 3 = low, 4 = mini

; Cylinder mesh caps
Enumeration
  #CYLCAP_NONE
  #CYLCAP_BOTH
  #CYLCAP_TOP
  #CYLCAP_BOTTOM
EndEnumeration


;- Structures and global definitions
Structure Vertex
  px.f
  py.f
  pz.f
  nx.f
  ny.f
  nz.f
  Couleur.l
  U.f
  V.f
EndStructure

Structure Polygon
  numVert1.w
  numVert2.w
  numVert3.w
EndStructure

Global groundMesh.i, gnomonMesh.i, boxMesh.i
Global groundEntity.i, gnomonEntity.i
Global Dim boxEntity.i(12)
Global hours.f, mins.f, secs.f
Global oldTimer.i, newTimer.i, movement.i
Global dist.f,hauteur.f,i.i
;- ------ Procedures ------
EnableExplicit

;- -- Meshes and entities --

;************************************************************************************
; Name: createPlainMesh
; Purpose: creates a plain
; Parameters:
;   - number of subdivisions (given "3", the plain will be a 3x3 grid)
;   - sizeX, sizeZ : size of the box
;   - pivotX, pivotZ : location of the pivot of the box, around which it rotates (default = center = 0,0)
;   - Uorigin, Vorigin : UV map coordinates (default = top left of the map = 0,0)
;   - Uscale, Vscale : UV map scale (default = 1,1)
;   - color of the vertices (default = white)
; Return-Value: number of the resulting mesh, -1 if creation failed
;************************************************************************************
Procedure.l createPlainMesh(nbdiv.w,sizeX.f,sizeZ.f,pivotX.f = 0,pivotZ.f = 0,Uorigin.f = 0,Vorigin.f = 0,Uscale.f = 1,Vscale.f = 1,color.l = $FFFFFF)

  Protected sizediv.f
  Protected x1.f,y1.f,z1.f                  ; vertex position
  Protected x2.f,y2.f,z2.f                  ; vertex position
  Protected x3.f,y3.f,z3.f                  ; vertex position
  Protected x4.f,y4.f,z4.f                  ; vertex position
  Protected nx.f,ny.f,nz.f                  ; vertex normals
  Protected u.f,v.f                         ; vertex UV coords (texture mapping)
  Protected numvert.w,numvert0.w            ; vertices of a poly
  Protected *PtrV.Vertex,*PtrV0.Vertex      ; vertices buffer in memory
  Protected *ptrP.Polygon,*ptrP0.Polygon    ; Polys buffer in memory
  Protected *vertexBuffer.l
  Protected *polygonBuffer.l
  Protected num.l,i.l,j.l,nbtri.l,nbvert
  Protected maxSize.f
  Protected newmesh.l                       ; Procedure Result

  nbtri  = (nbDiv * nbDiv * 2) ; nb divisions * nb divisions * 2 triangles per division
  nbvert = (nbDiv * nbDiv * 4) ; nb divisions * nb divisions * 4 vertices per division
 
  ; Allocate the needed memory for vertices
  *vertexBuffer = AllocateMemory(SizeOf(Vertex)*nbVert)
  *PtrV = *vertexBuffer
 
  ; Allocate the needed memory for faces info
  *polygonBuffer=AllocateMemory(SizeOf(Polygon)*nbTri)
  *ptrP=*polygonBuffer

  sizeDiv = 1/nbDiv
  ; Top
  x1=-0.5:y1=0:z1=-0.5
  x2=-0.5+sizeDiv:y2=0:z2 = z1
  x3=x2:y3=0:z3=-0.5+sizeDiv
  x4=x1:y4=0:z4=z3
 
  For i=1 To nbDiv
    For j=1 To nbDiv
     
      ; 1 square = 4 vertices
      *PtrV\px = x1
      *PtrV\py = y1
      *PtrV\pz = z1
      *PtrV\nx = 0
      *PtrV\ny = 1
      *PtrV\nz = 0
      *PtrV\couleur = color
      *PtrV\u = uorigin + (uscale/nbdiv)*(i-1)
      *PtrV\v = vorigin + (vscale/nbdiv)*(j-1)
      *PtrV + SizeOf(Vertex)

      *PtrV\px = x2
      *PtrV\py = y2
      *PtrV\pz = z2 
      *PtrV\nx = 0
      *PtrV\ny = 1
      *PtrV\nz = 0
      *PtrV\couleur = color
      *PtrV\u = uorigin + (uscale/nbdiv)*(i-1) + uscale/nbdiv
      *PtrV\v = vorigin + (vscale/nbdiv)*(j-1)
      *PtrV + SizeOf(Vertex)

      *PtrV\px = x3
      *PtrV\py = y3
      *PtrV\pz = z3 
      *PtrV\nx = 0
      *PtrV\ny = 1
      *PtrV\nz = 0
      *PtrV\couleur = color
      *PtrV\u = uorigin + (uscale/nbdiv)*(i-1) + uscale/nbdiv
      *PtrV\v = vorigin + (vscale/nbdiv)*(j-1) + vscale/nbdiv
      *PtrV + SizeOf(Vertex)
     
      *PtrV\px = x4
      *PtrV\py = y4
      *PtrV\pz = z4
      *PtrV\nx = 0
      *PtrV\ny = 1
      *PtrV\nz = 0
      *PtrV\couleur = color
      *PtrV\u = uorigin + (uscale/nbdiv)*(i-1)
      *PtrV\v = vorigin + (vscale/nbdiv)*(j-1) + vscale/nbdiv
      *PtrV + SizeOf(Vertex)

      ; 1 square = 2 triangles
      *ptrP\numVert1=numvert+3 
      *ptrP\numVert2=numvert+2
      *ptrP\numVert3=numvert
      *ptrP + SizeOf(Polygon)

      *ptrP\numVert1=numvert 
      *ptrP\numVert2=numvert+2
      *ptrP\numVert3=numvert+1
      *ptrP + SizeOf(Polygon)
     
      numvert+4     

      z1=z4
      z2=z3
      z3+sizeDiv
      z4=z3

    Next j
   
    x1=x2
    x4=x3
    x2+sizeDiv
    x3=x2
    z1=-0.5
    z2=z1
    z3=-0.5+sizeDiv
    z4=z3
     
  Next i
  numvert0=numvert
 

  ; Resize
  If sizeX<>1 Or sizeZ<>1
    *ptrV = *vertexBuffer
    For i=1 To nbVert
      *PtrV\px = *PtrV\px*sizeX - pivotX
      *PtrV\pz = *PtrV\pz*sizeZ - pivotZ
     
      *PtrV+SizeOf(vertex)
    Next i 
  EndIf

  ; Create mesh from stored infos
  maxSize = sizeX
  If sizeZ > maxSize
    maxSize = sizeZ
  EndIf
 
  newMesh = CreateMesh(#PB_Any,maxSize)
  If IsMesh(newMesh)
    SetMeshData(newMesh,#PB_Mesh_Vertex | #PB_Mesh_Normal | #PB_Mesh_UVCoordinate | #PB_Mesh_Color,*vertexBuffer,nbVert)
    SetMeshData(newMesh,#PB_Mesh_Face,*polygonBuffer,nbTri)     
    FreeMemory(*vertexBuffer)
    FreeMemory(*polygonBuffer)
    ProcedureReturn newMesh
  Else
    ; free memory if "createMesh" has failed
    FreeMemory(*vertexBuffer)
    FreeMemory(*polygonBuffer)
    ProcedureReturn -1   
  EndIf

EndProcedure
;************************************************************************************
; Name: createBoxMesh
; Purpose: creates a "box" mesh
; Parameters:
;   - number of subdivisions (given "3", each face of the box will be a 3x3 grid)
;   - sizeX, sizeY, sizeZ : size of the box
;   - pivotX, pivotY, pivotZ : location of the pivot of the box, around which it rotates (default = center = 0,0,0)
;   - Uorigin, Vorigin : UV map coordinates (default = top left of the map = 0,0)
;   - Uscale, Vscale : UV map scale (default = 1,1)
;   - color of the vertices (default = white)
; Return-Value: number of the resulting mesh, -1 if creation failed
;************************************************************************************
Procedure.l createBoxMesh(nbdiv.w,sizeX.f,sizeY.f,sizeZ.f,pivotX.f = 0,pivotY.f = 0,pivotZ.f = 0,Uorigin.f = 0,Vorigin.f = 0,Uscale.f = 1,Vscale.f = 1,color.l = $FFFFFF)

  Protected sizediv.f
  Protected x1.f,y1.f,z1.f                  ; vertex position
  Protected x2.f,y2.f,z2.f                  ; vertex position
  Protected x3.f,y3.f,z3.f                  ; vertex position
  Protected x4.f,y4.f,z4.f                  ; vertex position
  Protected nx.f,ny.f,nz.f                  ; vertex normals
  Protected u.f,v.f                         ; vertex UV coords (texture mapping)
  Protected numvert.w,numvert0.w            ; vertices of a poly
  Protected *PtrV.Vertex,*PtrV0.Vertex      ; vertices buffer in memory
  Protected *ptrP.Polygon,*ptrP0.Polygon    ; Polys buffer in memory
  Protected *vertexBuffer.l
  Protected *polygonBuffer.l
  Protected num.l,i.l,j.l,nbtri.l,nbvert
  Protected maxSize.f
  Protected newmesh.l                       ; Procedure Result

  nbtri  = 6 * (nbDiv * nbDiv * 2) ; 6 sides * nb divisions * nb divisions * 2 triangles per division
  nbvert = 6 * (nbDiv * nbDiv * 4) ; 6 sides * nb divisions * nb divisions * 4 vertices per division
 
  ; Allocate the needed memory for vertices
  *vertexBuffer = AllocateMemory(SizeOf(Vertex)*nbVert)
  *PtrV = *vertexBuffer
 
  ; Allocate the needed memory for faces info
  *polygonBuffer=AllocateMemory(SizeOf(Polygon)*nbTri)
  *ptrP=*polygonBuffer

  sizeDiv = 1/nbDiv
  ; Top
  x1=-0.5:y1=0.5:z1=-0.5
  x2=-0.5+sizeDiv:y2=0.5:z2 = z1
  x3=x2:y3=0.5:z3=-0.5+sizeDiv
  x4=x1:y4=0.5:z4=z3
 
  For i=1 To nbDiv
    For j=1 To nbDiv
     
      ; 1 square = 4 vertices
      *PtrV\px = x1
      *PtrV\py = y1
      *PtrV\pz = z1
      *PtrV\nx = *PtrV\px
      *PtrV\ny = *PtrV\py
      *PtrV\nz = *PtrV\pz
      *PtrV\couleur = color
      *PtrV\u = uorigin + (uscale/nbdiv)*(i-1)
      *PtrV\v = vorigin + (vscale/nbdiv)*(j-1)
      *PtrV + SizeOf(Vertex)

      *PtrV\px = x2
      *PtrV\py = y2
      *PtrV\pz = z2 
      *PtrV\nx = *PtrV\px
      *PtrV\ny = *PtrV\py
      *PtrV\nz = *PtrV\pz
      *PtrV\couleur = color
      *PtrV\u = uorigin + (uscale/nbdiv)*(i-1) + uscale/nbdiv
      *PtrV\v = vorigin + (vscale/nbdiv)*(j-1)
      *PtrV + SizeOf(Vertex)

      *PtrV\px = x3
      *PtrV\py = y3
      *PtrV\pz = z3 
      *PtrV\nx = *PtrV\px
      *PtrV\ny = *PtrV\py
      *PtrV\nz = *PtrV\pz
      *PtrV\couleur = color
      *PtrV\u = uorigin + (uscale/nbdiv)*(i-1) + uscale/nbdiv
      *PtrV\v = vorigin + (vscale/nbdiv)*(j-1) + vscale/nbdiv
      *PtrV + SizeOf(Vertex)
     
      *PtrV\px = x4
      *PtrV\py = y4
      *PtrV\pz = z4
      *PtrV\nx = *PtrV\px
      *PtrV\ny = *PtrV\py
      *PtrV\nz = *PtrV\pz
      *PtrV\couleur = color
      *PtrV\u = uorigin + (uscale/nbdiv)*(i-1)
      *PtrV\v = vorigin + (vscale/nbdiv)*(j-1) + vscale/nbdiv
      *PtrV + SizeOf(Vertex)

      ; 1 square = 2 triangles
      *ptrP\numVert1=numvert+3 
      *ptrP\numVert2=numvert+2
      *ptrP\numVert3=numvert
      *ptrP + SizeOf(Polygon)

      *ptrP\numVert1=numvert 
      *ptrP\numVert2=numvert+2
      *ptrP\numVert3=numvert+1
      *ptrP + SizeOf(Polygon)
     
      numvert+4     

      z1=z4
      z2=z3
      z3+sizeDiv
      z4=z3

    Next j
   
    x1=x2
    x4=x3
    x2+sizeDiv
    x3=x2
    z1=-0.5
    z2=z1
    z3=-0.5+sizeDiv
    z4=z3
     
  Next i
  numvert0=numvert
 
  ; Bottom
  *PtrV0 = *vertexBuffer   
  For i=1 To numvert0
    *PtrV\px = -*PtrV0\px
    *PtrV\py = -*PtrV0\py
    *PtrV\pz = *PtrV0\pz 
    *PtrV\nx = *PtrV\px
    *PtrV\ny = *PtrV\py
    *PtrV\nz = *PtrV\pz
    *PtrV\couleur = *PtrV0\couleur
    *PtrV\u = *PtrV0\u
    *PtrV\v = *PtrV0\v
   
    *PtrV + SizeOf(Vertex)
    *PtrV0 + SizeOf(Vertex)
    numvert+1
   
    If i%4=0
      *ptrP\numVert1=numvert - 2
      *ptrP\numVert2=numvert - 3
      *ptrP\numVert3=numvert - 4
      *ptrP + SizeOf(Polygon) 
   
      *ptrP\numVert1=numvert - 4
      *ptrP\numVert2=numvert - 1
      *ptrP\numVert3=numvert - 2
      *ptrP + SizeOf(Polygon)   
    EndIf
   
  Next i

  ; Right
  *PtrV0 = *vertexBuffer   
  For i=1 To numvert0
    *PtrV\px = *PtrV0\py
    *PtrV\py = -*PtrV0\px
    *PtrV\pz = *PtrV0\pz 
    *PtrV\nx = *PtrV\px
    *PtrV\ny = *PtrV\py
    *PtrV\nz = *PtrV\pz
    *PtrV\couleur = *PtrV0\couleur
    *PtrV\u = 1-*PtrV0\v
    *PtrV\v = *PtrV0\u
   
    *PtrV + SizeOf(Vertex)
    *PtrV0 + SizeOf(Vertex)
    numvert+1
   
    If i%4=0
      *ptrP\numVert1=numvert - 2
      *ptrP\numVert2=numvert - 3
      *ptrP\numVert3=numvert - 4
      *ptrP + SizeOf(Polygon) 
     
      *ptrP\numVert1=numvert - 4
      *ptrP\numVert2=numvert - 1
      *ptrP\numVert3=numvert - 2
      *ptrP + SizeOf(Polygon) 
    EndIf
   
  Next i

  ; Left
  *PtrV0 = *vertexBuffer   
  For i=1 To numvert0
    *PtrV\px = -*PtrV0\py
    *PtrV\py = -*PtrV0\px
    *PtrV\pz = *PtrV0\pz 
    *PtrV\nx = *PtrV\px
    *PtrV\ny = *PtrV\py
    *PtrV\nz = *PtrV\pz
    *PtrV\couleur = *PtrV0\couleur
    *PtrV\u = *PtrV0\v
    *PtrV\v = *PtrV0\u
   
    *PtrV + SizeOf(Vertex)
    *PtrV0 + SizeOf(Vertex)
    numvert+1
   
    If i%4=0
      *ptrP\numVert1=numvert - 4
      *ptrP\numVert2=numvert - 3
      *ptrP\numVert3=numvert - 2
      *ptrP + SizeOf(Polygon) 
   
      *ptrP\numVert1=numvert - 2
      *ptrP\numVert2=numvert - 1
      *ptrP\numVert3=numvert - 4
      *ptrP + SizeOf(Polygon) 
    EndIf
   
  Next i

  ; Front
  *PtrV0 = *vertexBuffer   
  For i=1 To numvert0
    *PtrV\px = -*PtrV0\pz
    *PtrV\py = -*PtrV0\px
    *PtrV\pz = -*PtrV0\py 
    *PtrV\nx = *PtrV\px
    *PtrV\ny = *PtrV\py
    *PtrV\nz = *PtrV\pz
    *PtrV\couleur = *PtrV0\couleur
    *PtrV\u = *PtrV0\v
    *PtrV\v = *PtrV0\u
   
    *PtrV + SizeOf(Vertex)
    *PtrV0 + SizeOf(Vertex)
    numvert+1
   
    If i%4=0
      *ptrP\numVert1=numvert - 4
      *ptrP\numVert2=numvert - 3
      *ptrP\numVert3=numvert - 2
      *ptrP + SizeOf(Polygon) 
   
      *ptrP\numVert1=numvert - 2
      *ptrP\numVert2=numvert - 1
      *ptrP\numVert3=numvert - 4
      *ptrP + SizeOf(Polygon) 
    EndIf
   
  Next i
 
  ; Back
  *PtrV0 = *vertexBuffer   
  For i=1 To numvert0
    *PtrV\px = -*PtrV0\pz
    *PtrV\py = -*PtrV0\px
    *PtrV\pz = *PtrV0\py 
    *PtrV\nx = *PtrV\px
    *PtrV\ny = *PtrV\py
    *PtrV\nz = *PtrV\pz
    *PtrV\couleur = *PtrV0\couleur
    *PtrV\u = 1-*PtrV0\v
    *PtrV\v = *PtrV0\u
   
    *PtrV + SizeOf(Vertex)
    *PtrV0 + SizeOf(Vertex)
    numvert+1
   
    If i%4=0
      *ptrP\numVert1=numvert - 2
      *ptrP\numVert2=numvert - 3
      *ptrP\numVert3=numvert - 4
      *ptrP + SizeOf(Polygon) 
   
      *ptrP\numVert1=numvert - 4
      *ptrP\numVert2=numvert - 1
      *ptrP\numVert3=numvert - 2
      *ptrP + SizeOf(Polygon) 
    EndIf
   
  Next i

  ; Resize
  If sizeX<>1 Or sizeY<>1 Or sizeZ<>1
    *ptrV = *vertexBuffer
    For i=1 To nbVert
      *PtrV\px = *PtrV\px*sizeX - pivotX
      *PtrV\py = *PtrV\py*sizeY - pivotY
      *PtrV\pz = *PtrV\pz*sizeZ - pivotZ
     
      *PtrV+SizeOf(vertex)
    Next i 
  EndIf

  ; Create mesh from stored infos
  maxSize = sizeX
  If sizeY > sizeX
    maxSize = sizeY
  EndIf
  If sizeZ > maxSize
    maxSize = sizeZ
  EndIf
 
  newMesh = CreateMesh(#PB_Any,maxSize)
  If IsMesh(newMesh)
    SetMeshData(newMesh,#PB_Mesh_Vertex | #PB_Mesh_Normal | #PB_Mesh_UVCoordinate | #PB_Mesh_Color,*vertexBuffer,nbVert)
    SetMeshData(newMesh,#PB_Mesh_Face,*polygonBuffer,nbTri)     
    FreeMemory(*vertexBuffer)
    FreeMemory(*polygonBuffer)
    ProcedureReturn newMesh
  Else
    ; free memory if "createMesh" has failed
    FreeMemory(*vertexBuffer)
    FreeMemory(*polygonBuffer)
    ProcedureReturn -1   
  EndIf

EndProcedure


;************************************************************************************
; Name: createCylinderMesh
; Purpose: create a cylinder mesh
; Parameters:
;   - number of sides ("3" gives a prism, "4" gives a box)
;   - height
;   - radius
;   - uncapped (=0), caps on top an bottom (=1), top cap only (=2), bottom cap only (=3). (default = 1)
;   - color of the vertices (default = white)
; Return-Value: number of the resulting mesh, -1 if creation failed
;************************************************************************************
Procedure.l createCylinderMesh(nbSides.l,height.f,radius.f,capped.b = 1,coul.l = $FFFFFF)
  Protected *PtrV.Vertex,*vertexBuffer.l    ; vertices buffer in memory
  Protected *PtrF.Polygon,*facetriBuffer.l  ; Faces buffer in memory
  Protected i.l,nbVert.l,nbTri.l, numVertTop.l,numVertBottom.l
  Protected h2.f,theta.f
  Protected newmesh.l                       ; Procedure Result
   
  If nbSides<3
    ProcedureReturn 0
  EndIf

  h2 = height / 2.0
  nbVert = 4*(nbSides+1)+2
  If capped = #CYLCAP_TOP Or capped = #CYLCAP_BOTTOM
    nbVert-1
  Else
    If capped = #CYLCAP_NONE
      nbVert-2
    EndIf
  EndIf   
 
  *vertexBuffer = AllocateMemory(SizeOf(Vertex)*nbVert)
  *PtrV = *vertexBuffer
   
  ;Vertices at the bottom of the cylinder
  For i = 0 To nbSides
    theta =2*#PI*i/nbSides
     
    *PtrV\px = radius*Cos(theta)
    *PtrV\py = -h2
    *PtrV\pz = radius*Sin(theta)
    *PtrV\nx = Cos(theta)
    *PtrV\ny = 0
    *PtrV\nz = Sin(theta)
    *PtrV\couleur = Coul
    *PtrV\u = Theta / (2.0*#PI)
    *PtrV\v = 0
    *PtrV + SizeOf(Vertex)
  Next i

   
  ;Vertices at the top of the cylinder
  For i = 0 To nbSides
    theta =2*#PI*i/nbSides
     
    *PtrV\px = radius*Cos(theta)
    *PtrV\py = h2
    *PtrV\pz = radius*Sin(theta)
    *PtrV\nx = Cos(theta)
    *PtrV\ny = 0
    *PtrV\nz = Sin(theta)
    *PtrV\couleur = Coul
    *PtrV\u = Theta / (2.0*#PI)
    *PtrV\v = 1
    *PtrV + SizeOf(Vertex)
  Next i

     
  ;Vertices at the bottom of the cylinder
  For i = 0 To nbSides
    theta =2*#PI*i/nbSides
     
    *PtrV\px = radius*Cos(theta)
    *PtrV\py = -h2
    *PtrV\pz = radius*Sin(theta)
    *PtrV\nx = 0
    *PtrV\ny = -1
    *PtrV\nz = 0
    *PtrV\couleur = Coul
    *PtrV\u = Theta / (2.0*#PI)
    *PtrV\v = 1
    *PtrV + SizeOf(Vertex)
  Next i
               
  ;Vertices at the top of the cylinder
  For i = 0 To nbSides
    theta =2*#PI*i/nbSides
     
    *PtrV\px = radius*Cos(theta)
    *PtrV\py = h2
    *PtrV\pz = radius*Sin(theta)
    *PtrV\nx = 0
    *PtrV\ny = 1
    *PtrV\nz = 0
    *PtrV\couleur = Coul
    *PtrV\u = Theta / (2.0*#PI)
    *PtrV\v = 1
    *PtrV + SizeOf(Vertex)
  Next i
   
  ;Bottom cap center
  If capped = #CYLCAP_BOTH Or capped = #CYLCAP_BOTTOM
    numVertBottom = (*PtrV - *vertexBuffer) / SizeOf(Vertex)
   
    *PtrV\px = 0
    *PtrV\py = -h2
    *PtrV\pz = 0
    *PtrV\nx = 0
    *PtrV\ny = -1
    *PtrV\nz = 0
    *PtrV\couleur = Coul
    *PtrV\u = 0.5
    *PtrV\v = 0.5
    *PtrV + SizeOf(Vertex)
  EndIf
 
  ;Top cap center
  If capped = #CYLCAP_BOTH Or capped = #CYLCAP_TOP
    numVertTop = (*PtrV - *vertexBuffer) / SizeOf(Vertex)
   
    *PtrV\px = 0
    *PtrV\py = h2
    *PtrV\pz = 0
    *PtrV\nx = 0
    *PtrV\ny = 1
    *PtrV\nz = 0
    *PtrV\couleur = Coul
    *PtrV\u = 0.5
    *PtrV\v = 0.5
  EndIf
   
  ;Facets
  nbTri = 4*nbSides
  If capped = #CYLCAP_BOTTOM Or capped = #CYLCAP_TOP
    nbTri - nbSides
  Else
    If capped = #CYLCAP_NONE
      nbTri - (nbSides*2)
    EndIf
  EndIf
   
  *facetriBuffer=AllocateMemory(SizeOf(Polygon)*nbTri)
  *PtrF=*facetriBuffer
 
  For i=0 To nbSides-1
      *PtrF\numVert3=i
      *PtrF\numVert2=i + 1
      *PtrF\numVert1=nbSides + i + 2
      *PtrF + SizeOf(Polygon)
   
   
      *PtrF\numVert1=i
      *PtrF\numVert3=nbSides + i + 2
      *PtrF\numVert2=nbSides + i + 1
      *PtrF + SizeOf(Polygon)
  Next i
   
 
  ;Bottom cap
  If capped = #CYLCAP_BOTH Or capped = #CYLCAP_BOTTOM   
    For i=0 To nbSides-1
      *PtrF\numVert1= numVertBottom
      *PtrF\numVert2= 2 * nbSides + 2 + i
      *PtrF\numVert3= 2 * nbSides + 3 + i
      *PtrF + SizeOf(Polygon)
    Next i     
  EndIf
  ;Top cap
  If capped = #CYLCAP_BOTH Or capped = #CYLCAP_TOP 
    For i=0 To nbSides-1
      *PtrF\numVert1= numVertTop
      *PtrF\numVert3= 3 * nbSides + 3 + i
      *PtrF\numVert2= 3 * nbSides + 4 + i
      *PtrF + SizeOf(Polygon)
    Next i     
  EndIf
 
  ; Create mesh from stored infos
  newmesh = CreateMesh(#PB_Any,radius)
  If IsMesh(newmesh)
    SetMeshData(newmesh,#PB_Mesh_Vertex | #PB_Mesh_Normal | #PB_Mesh_UVCoordinate | #PB_Mesh_Color,*vertexBuffer,nbVert)
    SetMeshData(newmesh,#PB_Mesh_Face,*facetriBuffer,nbTri)
    ; and don't forget to free memory
    FreeMemory(*vertexBuffer)
    FreeMemory(*facetriBuffer)
    ProcedureReturn newmesh
  Else
    ; even if "createMesh" has failed
    FreeMemory(*vertexBuffer)
    FreeMemory(*facetriBuffer)
    ProcedureReturn -1   
  EndIf
   
EndProcedure

DisableExplicit

;- ----- Main -----

;- Camera
CreateCamera(#CAMERA, 0, 0, 100, 100)
CameraLocate(#CAMERA, 50, 120, 0)
CameraLookAt(#CAMERA,0,0,0)

;- Light
AmbientColor(RGB(20,20,20))
CreateLight(0,RGB(255, 0, 0))
CreateLight(1,RGB(0, 255, 0))
CreateLight(2,RGB(0, 0, 255))
WorldShadows(#PB_Shadow_Additive)

;- Materials
Add3DArchive(".", #PB_3DArchive_FileSystem)
CreateImage(0,64,64)
StartDrawing(ImageOutput(0))
  Box(0,0,64,64,$FFFFFF)
StopDrawing()
SaveImage(0,"temp.bmp")
LoadTexture(0,"temp.bmp")
CreateMaterial(0,TextureID(0))
;MaterialAmbientColor(0,#PB_Material_AmbientColors)

LoadFont(1, "Times new roman", 48,#PB_Font_Bold|#PB_Font_HighQuality)
StartDrawing(ImageOutput(0))
DrawingMode(#PB_2DDrawing_Transparent)
DrawingFont(FontID(1))
For i = 1 To 12
  Box(0,0,64,64,$FFFFFF)
  If i<10
    DrawText(15,-5,Str(i),$000000)
  Else
    DrawText(0,-5,Str(i),$000000)
  EndIf
  SaveImage(0,"temp"+Str(i)+".bmp")
  LoadTexture(i,"temp"+Str(i)+".bmp")
  CreateMaterial(i,TextureID(i))   
Next i
StopDrawing()
FreeImage(0)

;- Meshes
groundmesh = CreatePlainMesh(30/#QUALITY,200,200)
gnomonMesh = createCylinderMesh(16/#QUALITY,20,2,#CYLCAP_TOP,$FFFFFF)
boxMesh = createBoxMesh(8/#QUALITY,15,20,1)

;- Entities
groundEntity = CreateEntity(#PB_Any,MeshID(groundmesh),MaterialID(0))
gnomonEntity = CreateEntity(#PB_Any,MeshID(gnomonMesh),MaterialID(0))
EntityLocate(gnomonEntity,0,10,0)

For i=1 To 12
  boxEntity(i) = CreateEntity(#PB_Any,MeshID(boxMesh),MaterialID(i))
  EntityLocate(boxEntity(i),50*Cos((180+30*i)*#DEG2RADMULT),10,50*Sin((180+30*i)*#DEG2RADMULT))
  RotateEntity(boxEntity(i),0,90 + i*-30,0)
Next i

;- **** MAIN LOOP *******************************************************************************
secs = Second(Date())
mins = Minute(Date()) + secs/60
hours = Hour(Date()) + mins/60 + secs/3600
oldtimer = ElapsedMilliseconds()
dist = 40
hauteur = 18
Repeat
  If FullScreen = #False
    While WindowEvent() : Wend
  EndIf 
 
  ;- Keyboard
  ExamineKeyboard()
 
  If KeyboardReleased(#PB_Key_F1)
    MessageRequester("Statistics",Str(CountRenderedTriangles()) + " polygons, " + Str(Engine3DFrameRate(#PB_Engine3D_Average)) + " Fps")
  EndIf

  ;- Move lights
  newtimer = ElapsedMilliseconds()
  movement = newtimer-oldtimer
  oldtimer = newtimer
  secs+movement/1000
  If secs>=60
    secs-60
  EndIf
  LightLocate(0,dist*Cos(secs*6*#DEG2RADMULT),hauteur,dist*Sin(secs*6*#DEG2RADMULT))
 
  mins+movement/60000
  If mins>=60
    mins-60
  EndIf
  LightLocate(1,dist*Cos(mins*6*#DEG2RADMULT),hauteur,dist*Sin(mins*6*#DEG2RADMULT))
 
  hours+movement/3600000
  If hours>=24
    hours-24
  EndIf
  LightLocate(2,dist*Cos(hours*30*#DEG2RADMULT),hauteur,dist*Sin(hours*30*#DEG2RADMULT))

  ; Show it all
  RenderWorld()
 
  ; Flip buffers to avoid tearing 
  FlipBuffers()
 
  Delay(1)
Until KeyboardPushed(#PB_Key_Escape) 
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Message par Le Soldat Inconnu »

une petite modif qui supprime les BMP créés histoire de ne pas en mettre partout

et j'ai bougé les lumières pour faires des aiguilles de différentes tailles

Regarde aussi le centrage des heures sur les rectangles, j'ai fais un calcul de positionnement en fonction de la taille du texte.

Code : Tout sélectionner

;- Initialization

If ExamineDesktops()
  If InitEngine3D() = 0
    MessageRequester( "Error", "Can't initialize 3D, check if engine3D.dll is available", 0 )
    End
  ElseIf InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0
    MessageRequester( "Error", "Can't find DirectX 7.0 or above", 0 )
    End
  EndIf
  If OpenScreen(DesktopWidth(0), DesktopHeight(0), DesktopDepth(0), "Light Clock") = 0
    MessageRequester( "Error", "Can't open screen", 0 )
    End
  EndIf
Else
  End
EndIf

#CAMERA = 0
#RAD2DEGMULT = 57.295779513082320877 ; (180/#PI)
#DEG2RADMULT = 0.0174532925199432958 ; (#PI/180)
#QUALITY = 1 ; 1 = good, 2 = medium, 3 = low, 4 = mini

; Cylinder mesh caps
Enumeration
  #CYLCAP_NONE
  #CYLCAP_BOTH
  #CYLCAP_TOP
  #CYLCAP_BOTTOM
EndEnumeration


;- Structures and global definitions
Structure Vertex
  px.f
  py.f
  pz.f
  nx.f
  ny.f
  nz.f
  Couleur.l
  u.f
  V.f
EndStructure

Structure Polygon
  numVert1.w
  numVert2.w
  numVert3.w
EndStructure

Global groundMesh.i, gnomonMesh.i, boxMesh.i
Global groundEntity.i, gnomonEntity.i
Global Dim boxEntity.i(12)
Global hours.f, mins.f, secs.f
Global oldTimer.i, newTimer.i, movement.i
Global dist.f, i.i
;- ------ Procedures ------
EnableExplicit

;- -- Meshes and entities --

; ************************************************************************************
; Name: createPlainMesh
; Purpose: creates a plain
; Parameters:
;- number of subdivisions (given "3", the plain will be a 3x3 grid)
;- sizeX, sizeZ : size of the box
;- pivotX, pivotZ : location of the pivot of the box, around which it rotates (default = center = 0,0)
;- Uorigin, Vorigin : UV map coordinates (default = top left of the map = 0,0)
;- Uscale, Vscale : UV map scale (default = 1,1)
;- color of the vertices (default = white)
; Return-Value: number of the resulting mesh, -1 if creation failed
; ************************************************************************************
Procedure.l createPlainMesh(nbdiv.w, sizeX.f, sizeZ.f, pivotX.f = 0, pivotZ.f = 0, Uorigin.f = 0, Vorigin.f = 0, Uscale.f = 1, Vscale.f = 1, color.l = $FFFFFF)
  
  Protected sizediv.f
  Protected x1.f, y1.f, z1.f ; vertex position
  Protected x2.f, y2.f, z2.f ; vertex position
  Protected x3.f, y3.f, z3.f ; vertex position
  Protected x4.f, y4.f, z4.f ; vertex position
  Protected nx.f, ny.f, nz.f ; vertex normals
  Protected u.f, V.f ; vertex UV coords (texture mapping)
  Protected numvert.w, numvert0.w ; vertices of a poly
  Protected * PtrV.Vertex, *PtrV0.Vertex ; vertices buffer in memory
  Protected * ptrP.Polygon, *ptrP0.Polygon ; Polys buffer in memory
  Protected * vertexBuffer.l
  Protected * polygonBuffer.l
  Protected num.l, i.l, j.l, nbtri.l, nbvert
  Protected maxSize.f
  Protected newmesh.l ; Procedure Result
  
  nbtri = (nbdiv * nbdiv * 2) ; nb divisions * nb divisions * 2 triangles per division
  nbvert = (nbdiv * nbdiv * 4) ; nb divisions * nb divisions * 4 vertices per division
  
  ; Allocate the needed memory for vertices
  *vertexBuffer = AllocateMemory(SizeOf(Vertex) * nbvert)
  *PtrV = *vertexBuffer
  
  ; Allocate the needed memory for faces info
  *polygonBuffer = AllocateMemory(SizeOf(Polygon) * nbtri)
  *ptrP = *polygonBuffer
  
  sizediv = 1 / nbdiv
  ; Top
  x1 = -0.5 : y1 = 0 : z1 = -0.5
  x2 = -0.5 + sizediv : y2 = 0 : z2 = z1
  x3 = x2 : y3 = 0 : z3 = -0.5 + sizediv
  x4 = x1 : y4 = 0 : z4 = z3
  
  For i = 1 To nbdiv
    For j = 1 To nbdiv
      
      ; 1 square = 4 vertices
      *PtrV\px = x1
      *PtrV\py = y1
      *PtrV\pz = z1
      *PtrV\nx = 0
      *PtrV\ny = 0.5
      *PtrV\nz = 0
      *PtrV\Couleur = Color
      *PtrV\u = Uorigin + (Uscale / nbdiv) * (i - 1)
      *PtrV\V = Vorigin + (Vscale / nbdiv) * (j - 1)
      *PtrV + SizeOf(Vertex)
      
      *PtrV\px = x2
      *PtrV\py = y2
      *PtrV\pz = z2
      *PtrV\nx = 0
      *PtrV\ny = 0.5
      *PtrV\nz = 0
      *PtrV\Couleur = Color
      *PtrV\u = Uorigin + (Uscale / nbdiv) * (i - 1) + Uscale / nbdiv
      *PtrV\V = Vorigin + (Vscale / nbdiv) * (j - 1)
      *PtrV + SizeOf(Vertex)
      
      *PtrV\px = x3
      *PtrV\py = y3
      *PtrV\pz = z3
      *PtrV\nx = 0
      *PtrV\ny = 0.5
      *PtrV\nz = 0
      *PtrV\Couleur = Color
      *PtrV\u = Uorigin + (Uscale / nbdiv) * (i - 1) + Uscale / nbdiv
      *PtrV\V = Vorigin + (Vscale / nbdiv) * (j - 1) + Vscale / nbdiv
      *PtrV + SizeOf(Vertex)
      
      *PtrV\px = x4
      *PtrV\py = y4
      *PtrV\pz = z4
      *PtrV\nx = 0
      *PtrV\ny = 0.5
      *PtrV\nz = 0
      *PtrV\Couleur = Color
      *PtrV\u = Uorigin + (Uscale / nbdiv) * (i - 1)
      *PtrV\V = Vorigin + (Vscale / nbdiv) * (j - 1) + Vscale / nbdiv
      *PtrV + SizeOf(Vertex)
      
      ; 1 square = 2 triangles
      *ptrP\numVert1 = numvert + 3
      *ptrP\numVert2 = numvert + 2
      *ptrP\numVert3 = numvert
      *ptrP + SizeOf(Polygon)
      
      *ptrP\numVert1 = numvert
      *ptrP\numVert2 = numvert + 2
      *ptrP\numVert3 = numvert + 1
      *ptrP + SizeOf(Polygon)
      
      numvert + 4
      
      z1 = z4
      z2 = z3
      z3 + sizediv
      z4 = z3
      
    Next j
    
    x1 = x2
    x4 = x3
    x2 + sizediv
    x3 = x2
    z1 = -0.5
    z2 = z1
    z3 = -0.5 + sizediv
    z4 = z3
    
  Next i
  numvert0 = numvert
  
  
  ; Resize
  If sizeX <> 1 Or sizeZ <> 1
    *PtrV = *vertexBuffer
    For i = 1 To nbvert
      *PtrV\px = *PtrV\px * sizeX - pivotX
      *PtrV\pz = *PtrV\pz * sizeZ - pivotZ
      
      *PtrV + SizeOf(Vertex)
    Next i
  EndIf
  
  ; Create mesh from stored infos
  maxSize = sizeX
  If sizeZ > maxSize
    maxSize = sizeZ
  EndIf
  
  newmesh = CreateMesh(#PB_Any, maxSize)
  If IsMesh(newmesh)
    SetMeshData(newmesh, #PB_Mesh_Vertex | #PB_Mesh_Normal | #PB_Mesh_UVCoordinate | #PB_Mesh_Color, *vertexBuffer, nbvert)
    SetMeshData(newmesh, #PB_Mesh_Face, *polygonBuffer, nbtri)
    FreeMemory(*vertexBuffer)
    FreeMemory(*polygonBuffer)
    ProcedureReturn newmesh
  Else
    ; free memory if "createMesh" has failed
    FreeMemory(*vertexBuffer)
    FreeMemory(*polygonBuffer)
    ProcedureReturn - 1
  EndIf
  
EndProcedure
; ************************************************************************************
; Name: createBoxMesh
; Purpose: creates a "box" mesh
; Parameters:
;- number of subdivisions (given "3", each face of the box will be a 3x3 grid)
;- sizeX, sizeY, sizeZ : size of the box
;- pivotX, pivotY, pivotZ : location of the pivot of the box, around which it rotates (default = center = 0,0,0)
;- Uorigin, Vorigin : UV map coordinates (default = top left of the map = 0,0)
;- Uscale, Vscale : UV map scale (default = 1,1)
;- color of the vertices (default = white)
; Return-Value: number of the resulting mesh, -1 if creation failed
; ************************************************************************************
Procedure.l createBoxMesh(nbdiv.w, sizeX.f, sizeY.f, sizeZ.f, pivotX.f = 0, pivotY.f = 0, pivotZ.f = 0, Uorigin.f = 0, Vorigin.f = 0, Uscale.f = 1, Vscale.f = 1, color.l = $FFFFFF)
  
  Protected sizediv.f
  Protected x1.f, y1.f, z1.f ; vertex position
  Protected x2.f, y2.f, z2.f ; vertex position
  Protected x3.f, y3.f, z3.f ; vertex position
  Protected x4.f, y4.f, z4.f ; vertex position
  Protected nx.f, ny.f, nz.f ; vertex normals
  Protected u.f, V.f ; vertex UV coords (texture mapping)
  Protected numvert.w, numvert0.w ; vertices of a poly
  Protected * PtrV.Vertex, *PtrV0.Vertex ; vertices buffer in memory
  Protected * ptrP.Polygon, *ptrP0.Polygon ; Polys buffer in memory
  Protected * vertexBuffer.l
  Protected * polygonBuffer.l
  Protected num.l, i.l, j.l, nbtri.l, nbvert
  Protected maxSize.f
  Protected newmesh.l ; Procedure Result
  
  nbtri = 6 * (nbdiv * nbdiv * 2) ; 6 sides * nb divisions * nb divisions * 2 triangles per division
  nbvert = 6 * (nbdiv * nbdiv * 4) ; 6 sides * nb divisions * nb divisions * 4 vertices per division
  
  ; Allocate the needed memory for vertices
  *vertexBuffer = AllocateMemory(SizeOf(Vertex) * nbvert)
  *PtrV = *vertexBuffer
  
  ; Allocate the needed memory for faces info
  *polygonBuffer = AllocateMemory(SizeOf(Polygon) * nbtri)
  *ptrP = *polygonBuffer
  
  sizediv = 1 / nbdiv
  ; Top
  x1 = -0.5 : y1 = 0.5 : z1 = -0.5
  x2 = -0.5 + sizediv : y2 = 0.5 : z2 = z1
  x3 = x2 : y3 = 0.5 : z3 = -0.5 + sizediv
  x4 = x1 : y4 = 0.5 : z4 = z3
  
  For i = 1 To nbdiv
    For j = 1 To nbdiv
      
      ; 1 square = 4 vertices
      *PtrV\px = x1
      *PtrV\py = y1
      *PtrV\pz = z1
      *PtrV\nx = *PtrV\px
      *PtrV\ny = *PtrV\py
      *PtrV\nz = *PtrV\pz
      *PtrV\Couleur = Color
      *PtrV\u = Uorigin + (Uscale / nbdiv) * (i - 1)
      *PtrV\V = Vorigin + (Vscale / nbdiv) * (j - 1)
      *PtrV + SizeOf(Vertex)
      
      *PtrV\px = x2
      *PtrV\py = y2
      *PtrV\pz = z2
      *PtrV\nx = *PtrV\px
      *PtrV\ny = *PtrV\py
      *PtrV\nz = *PtrV\pz
      *PtrV\Couleur = Color
      *PtrV\u = Uorigin + (Uscale / nbdiv) * (i - 1) + Uscale / nbdiv
      *PtrV\V = Vorigin + (Vscale / nbdiv) * (j - 1)
      *PtrV + SizeOf(Vertex)
      
      *PtrV\px = x3
      *PtrV\py = y3
      *PtrV\pz = z3
      *PtrV\nx = *PtrV\px
      *PtrV\ny = *PtrV\py
      *PtrV\nz = *PtrV\pz
      *PtrV\Couleur = Color
      *PtrV\u = Uorigin + (Uscale / nbdiv) * (i - 1) + Uscale / nbdiv
      *PtrV\V = Vorigin + (Vscale / nbdiv) * (j - 1) + Vscale / nbdiv
      *PtrV + SizeOf(Vertex)
      
      *PtrV\px = x4
      *PtrV\py = y4
      *PtrV\pz = z4
      *PtrV\nx = *PtrV\px
      *PtrV\ny = *PtrV\py
      *PtrV\nz = *PtrV\pz
      *PtrV\Couleur = Color
      *PtrV\u = Uorigin + (Uscale / nbdiv) * (i - 1)
      *PtrV\V = Vorigin + (Vscale / nbdiv) * (j - 1) + Vscale / nbdiv
      *PtrV + SizeOf(Vertex)
      
      ; 1 square = 2 triangles
      *ptrP\numVert1 = numvert + 3
      *ptrP\numVert2 = numvert + 2
      *ptrP\numVert3 = numvert
      *ptrP + SizeOf(Polygon)
      
      *ptrP\numVert1 = numvert
      *ptrP\numVert2 = numvert + 2
      *ptrP\numVert3 = numvert + 1
      *ptrP + SizeOf(Polygon)
      
      numvert + 4
      
      z1 = z4
      z2 = z3
      z3 + sizediv
      z4 = z3
      
    Next j
    
    x1 = x2
    x4 = x3
    x2 + sizediv
    x3 = x2
    z1 = -0.5
    z2 = z1
    z3 = -0.5 + sizediv
    z4 = z3
    
  Next i
  numvert0 = numvert
  
  ; Bottom
  *PtrV0 = *vertexBuffer
  For i = 1 To numvert0
    *PtrV\px = - * PtrV0\px
    *PtrV\py = - * PtrV0\py
    *PtrV\pz = *PtrV0\pz
    *PtrV\nx = *PtrV\px
    *PtrV\ny = *PtrV\py
    *PtrV\nz = *PtrV\pz
    *PtrV\Couleur = *PtrV0\Couleur
    *PtrV\u = *PtrV0\u
    *PtrV\V = *PtrV0\V
    
    *PtrV + SizeOf(Vertex)
    *PtrV0 + SizeOf(Vertex)
    numvert + 1
    
    If i %4 = 0
      *ptrP\numVert1 = numvert - 2
      *ptrP\numVert2 = numvert - 3
      *ptrP\numVert3 = numvert - 4
      *ptrP + SizeOf(Polygon)
      
      *ptrP\numVert1 = numvert - 4
      *ptrP\numVert2 = numvert - 1
      *ptrP\numVert3 = numvert - 2
      *ptrP + SizeOf(Polygon)
    EndIf
    
  Next i
  
  ; Right
  *PtrV0 = *vertexBuffer
  For i = 1 To numvert0
    *PtrV\px = *PtrV0\py
    *PtrV\py = - * PtrV0\px
    *PtrV\pz = *PtrV0\pz
    *PtrV\nx = *PtrV\px
    *PtrV\ny = *PtrV\py
    *PtrV\nz = *PtrV\pz
    *PtrV\Couleur = *PtrV0\Couleur
    *PtrV\u = 1 - * PtrV0\V
    *PtrV\V = *PtrV0\u
    
    *PtrV + SizeOf(Vertex)
    *PtrV0 + SizeOf(Vertex)
    numvert + 1
    
    If i %4 = 0
      *ptrP\numVert1 = numvert - 2
      *ptrP\numVert2 = numvert - 3
      *ptrP\numVert3 = numvert - 4
      *ptrP + SizeOf(Polygon)
      
      *ptrP\numVert1 = numvert - 4
      *ptrP\numVert2 = numvert - 1
      *ptrP\numVert3 = numvert - 2
      *ptrP + SizeOf(Polygon)
    EndIf
    
  Next i
  
  ; Left
  *PtrV0 = *vertexBuffer
  For i = 1 To numvert0
    *PtrV\px = - * PtrV0\py
    *PtrV\py = - * PtrV0\px
    *PtrV\pz = *PtrV0\pz
    *PtrV\nx = *PtrV\px
    *PtrV\ny = *PtrV\py
    *PtrV\nz = *PtrV\pz
    *PtrV\Couleur = *PtrV0\Couleur
    *PtrV\u = *PtrV0\V
    *PtrV\V = *PtrV0\u
    
    *PtrV + SizeOf(Vertex)
    *PtrV0 + SizeOf(Vertex)
    numvert + 1
    
    If i %4 = 0
      *ptrP\numVert1 = numvert - 4
      *ptrP\numVert2 = numvert - 3
      *ptrP\numVert3 = numvert - 2
      *ptrP + SizeOf(Polygon)
      
      *ptrP\numVert1 = numvert - 2
      *ptrP\numVert2 = numvert - 1
      *ptrP\numVert3 = numvert - 4
      *ptrP + SizeOf(Polygon)
    EndIf
    
  Next i
  
  ; Front
  *PtrV0 = *vertexBuffer
  For i = 1 To numvert0
    *PtrV\px = - * PtrV0\pz
    *PtrV\py = - * PtrV0\px
    *PtrV\pz = - * PtrV0\py
    *PtrV\nx = *PtrV\px
    *PtrV\ny = *PtrV\py
    *PtrV\nz = *PtrV\pz
    *PtrV\Couleur = *PtrV0\Couleur
    *PtrV\u = *PtrV0\V
    *PtrV\V = *PtrV0\u
    
    *PtrV + SizeOf(Vertex)
    *PtrV0 + SizeOf(Vertex)
    numvert + 1
    
    If i %4 = 0
      *ptrP\numVert1 = numvert - 4
      *ptrP\numVert2 = numvert - 3
      *ptrP\numVert3 = numvert - 2
      *ptrP + SizeOf(Polygon)
      
      *ptrP\numVert1 = numvert - 2
      *ptrP\numVert2 = numvert - 1
      *ptrP\numVert3 = numvert - 4
      *ptrP + SizeOf(Polygon)
    EndIf
    
  Next i
  
  ; Back
  *PtrV0 = *vertexBuffer
  For i = 1 To numvert0
    *PtrV\px = - * PtrV0\pz
    *PtrV\py = - * PtrV0\px
    *PtrV\pz = *PtrV0\py
    *PtrV\nx = *PtrV\px
    *PtrV\ny = *PtrV\py
    *PtrV\nz = *PtrV\pz
    *PtrV\Couleur = *PtrV0\Couleur
    *PtrV\u = 1 - * PtrV0\V
    *PtrV\V = *PtrV0\u
    
    *PtrV + SizeOf(Vertex)
    *PtrV0 + SizeOf(Vertex)
    numvert + 1
    
    If i %4 = 0
      *ptrP\numVert1 = numvert - 2
      *ptrP\numVert2 = numvert - 3
      *ptrP\numVert3 = numvert - 4
      *ptrP + SizeOf(Polygon)
      
      *ptrP\numVert1 = numvert - 4
      *ptrP\numVert2 = numvert - 1
      *ptrP\numVert3 = numvert - 2
      *ptrP + SizeOf(Polygon)
    EndIf
    
  Next i
  
  ; Resize
  If sizeX <> 1 Or sizeY <> 1 Or sizeZ <> 1
    *PtrV = *vertexBuffer
    For i = 1 To nbvert
      *PtrV\px = *PtrV\px * sizeX - pivotX
      *PtrV\py = *PtrV\py * sizeY - pivotY
      *PtrV\pz = *PtrV\pz * sizeZ - pivotZ
      
      *PtrV + SizeOf(Vertex)
    Next i
  EndIf
  
  ; Create mesh from stored infos
  maxSize = sizeX
  If sizeY > sizeX
    maxSize = sizeY
  EndIf
  If sizeZ > maxSize
    maxSize = sizeZ
  EndIf
  
  newmesh = CreateMesh(#PB_Any, maxSize)
  If IsMesh(newmesh)
    SetMeshData(newmesh, #PB_Mesh_Vertex | #PB_Mesh_Normal | #PB_Mesh_UVCoordinate | #PB_Mesh_Color, *vertexBuffer, nbvert)
    SetMeshData(newmesh, #PB_Mesh_Face, *polygonBuffer, nbtri)
    FreeMemory(*vertexBuffer)
    FreeMemory(*polygonBuffer)
    ProcedureReturn newmesh
  Else
    ; free memory if "createMesh" has failed
    FreeMemory(*vertexBuffer)
    FreeMemory(*polygonBuffer)
    ProcedureReturn - 1
  EndIf
  
EndProcedure


; ************************************************************************************
; Name: createCylinderMesh
; Purpose: create a cylinder mesh
; Parameters:
;- number of sides ("3" gives a prism, "4" gives a box)
;- height
;- radius
;- uncapped (=0), caps on top an bottom (=1), top cap only (=2), bottom cap only (=3). (default = 1)
;- color of the vertices (default = white)
; Return-Value: number of the resulting mesh, -1 if creation failed
; ************************************************************************************
Procedure.l createCylinderMesh(nbSides.l, height.f, radius.f, capped.b = 1, coul.l = $FFFFFF)
  Protected * PtrV.Vertex, *vertexBuffer.l ; vertices buffer in memory
  Protected * PtrF.Polygon, *facetriBuffer.l ; Faces buffer in memory
  Protected i.l, nbvert.l, nbtri.l, numVertTop.l, numVertBottom.l
  Protected h2.f, theta.f
  Protected newmesh.l ; Procedure Result
  
  If nbSides < 3
    ProcedureReturn 0
  EndIf
  
  h2 = height / 2.0
  nbvert = 4 * (nbSides + 1) + 2
  If capped = #CYLCAP_TOP Or capped = #CYLCAP_BOTTOM
    nbvert - 1
  Else
    If capped = #CYLCAP_NONE
      nbvert - 2
    EndIf
  EndIf
  
  *vertexBuffer = AllocateMemory(SizeOf(Vertex) * nbvert)
  *PtrV = *vertexBuffer
  
  ; Vertices at the bottom of the cylinder
  For i = 0 To nbSides
    theta = 2 * #PI * i / nbSides
    
    *PtrV\px = Radius * Cos(theta)
    *PtrV\py = -h2
    *PtrV\pz = Radius * Sin(theta)
    *PtrV\nx = Cos(theta)
    *PtrV\ny = 0
    *PtrV\nz = Sin(theta)
    *PtrV\Couleur = coul
    *PtrV\u = theta / (2.0 * #PI)
    *PtrV\V = 0
    *PtrV + SizeOf(Vertex)
  Next i
  
  
  ; Vertices at the top of the cylinder
  For i = 0 To nbSides
    theta = 2 * #PI * i / nbSides
    
    *PtrV\px = Radius * Cos(theta)
    *PtrV\py = h2
    *PtrV\pz = Radius * Sin(theta)
    *PtrV\nx = Cos(theta)
    *PtrV\ny = 0
    *PtrV\nz = Sin(theta)
    *PtrV\Couleur = coul
    *PtrV\u = theta / (2.0 * #PI)
    *PtrV\V = 1
    *PtrV + SizeOf(Vertex)
  Next i
  
  
  ; Vertices at the bottom of the cylinder
  For i = 0 To nbSides
    theta = 2 * #PI * i / nbSides
    
    *PtrV\px = Radius * Cos(theta)
    *PtrV\py = -h2
    *PtrV\pz = Radius * Sin(theta)
    *PtrV\nx = 0
    *PtrV\ny = -1
    *PtrV\nz = 0
    *PtrV\Couleur = coul
    *PtrV\u = theta / (2.0 * #PI)
    *PtrV\V = 1
    *PtrV + SizeOf(Vertex)
  Next i
  
  ; Vertices at the top of the cylinder
  For i = 0 To nbSides
    theta = 2 * #PI * i / nbSides
    
    *PtrV\px = Radius * Cos(theta)
    *PtrV\py = h2
    *PtrV\pz = Radius * Sin(theta)
    *PtrV\nx = 0
    *PtrV\ny = 1
    *PtrV\nz = 0
    *PtrV\Couleur = coul
    *PtrV\u = theta / (2.0 * #PI)
    *PtrV\V = 1
    *PtrV + SizeOf(Vertex)
  Next i
  
  ; Bottom cap center
  If capped = #CYLCAP_BOTH Or capped = #CYLCAP_BOTTOM
    numVertBottom = (*PtrV - * vertexBuffer) / SizeOf(Vertex)
    
    *PtrV\px = 0
    *PtrV\py = -h2
    *PtrV\pz = 0
    *PtrV\nx = 0
    *PtrV\ny = -1
    *PtrV\nz = 0
    *PtrV\Couleur = coul
    *PtrV\u = 0.5
    *PtrV\V = 0.5
    *PtrV + SizeOf(Vertex)
  EndIf
  
  ; Top cap center
  If capped = #CYLCAP_BOTH Or capped = #CYLCAP_TOP
    numVertTop = (*PtrV - * vertexBuffer) / SizeOf(Vertex)
    
    *PtrV\px = 0
    *PtrV\py = h2
    *PtrV\pz = 0
    *PtrV\nx = 0
    *PtrV\ny = 1
    *PtrV\nz = 0
    *PtrV\Couleur = coul
    *PtrV\u = 0.5
    *PtrV\V = 0.5
  EndIf
  
  ; Facets
  nbtri = 4 * nbSides
  If capped = #CYLCAP_BOTTOM Or capped = #CYLCAP_TOP
    nbtri - nbSides
  Else
    If capped = #CYLCAP_NONE
      nbtri - (nbSides * 2)
    EndIf
  EndIf
  
  *facetriBuffer = AllocateMemory(SizeOf(Polygon) * nbtri)
  *PtrF = *facetriBuffer
  
  For i = 0 To nbSides - 1
    *PtrF\numVert3 = i
    *PtrF\numVert2 = i + 1
    *PtrF\numVert1 = nbSides + i + 2
    *PtrF + SizeOf(Polygon)
    
    
    *PtrF\numVert1 = i
    *PtrF\numVert3 = nbSides + i + 2
    *PtrF\numVert2 = nbSides + i + 1
    *PtrF + SizeOf(Polygon)
  Next i
  
  
  ; Bottom cap
  If capped = #CYLCAP_BOTH Or capped = #CYLCAP_BOTTOM
    For i = 0 To nbSides - 1
      *PtrF\numVert1 = numVertBottom
      *PtrF\numVert2 = 2 * nbSides + 2 + i
      *PtrF\numVert3 = 2 * nbSides + 3 + i
      *PtrF + SizeOf(Polygon)
    Next i
  EndIf
  ; Top cap
  If capped = #CYLCAP_BOTH Or capped = #CYLCAP_TOP
    For i = 0 To nbSides - 1
      *PtrF\numVert1 = numVertTop
      *PtrF\numVert3 = 3 * nbSides + 3 + i
      *PtrF\numVert2 = 3 * nbSides + 4 + i
      *PtrF + SizeOf(Polygon)
    Next i
  EndIf
  
  ; Create mesh from stored infos
  newmesh = CreateMesh(#PB_Any, Radius)
  If IsMesh(newmesh)
    SetMeshData(newmesh, #PB_Mesh_Vertex | #PB_Mesh_Normal | #PB_Mesh_UVCoordinate | #PB_Mesh_Color, *vertexBuffer, nbvert)
    SetMeshData(newmesh, #PB_Mesh_Face, *facetriBuffer, nbtri)
    ; and don't forget to free memory
    FreeMemory(*vertexBuffer)
    FreeMemory(*facetriBuffer)
    ProcedureReturn newmesh
  Else
    ; even if "createMesh" has failed
    FreeMemory(*vertexBuffer)
    FreeMemory(*facetriBuffer)
    ProcedureReturn - 1
  EndIf
  
EndProcedure

DisableExplicit

;- ----- Main -----

;- Camera
CreateCamera(#CAMERA, 0, 0, 100, 100)
CameraLocate(#CAMERA, 50, 140, 0)
CameraLookAt(#CAMERA, 0, 0, 0)

;- Light
AmbientColor(0)
CreateLight(0, $FF9090)
CreateLight(1, $9090FF)
CreateLight(2, $90FF90)
WorldShadows(#PB_Shadow_Additive)

;- Materials
Add3DArchive(".", #PB_3DArchive_FileSystem)
CreateImage(0, 64, 64)
StartDrawing(ImageOutput(0))
  Box(0, 0, 64, 64, $FFFFFF)
StopDrawing()
SaveImage(0, "temp.bmp")
LoadTexture(0, "temp.bmp")
DeleteFile("temp.bmp")
CreateMaterial(0, TextureID(0))
MaterialAmbientColor(0, #PB_Material_AmbientColors)

LoadFont(1, "Arial", 40, #PB_Font_Bold | #PB_Font_HighQuality)
StartDrawing(ImageOutput(0))
  DrawingMode(#PB_2DDrawing_Transparent)
  DrawingFont(FontID(1))
  For i = 1 To 12
    Box(0, 0, 64, 64, $FFFFFF)
    DrawText((64 - TextWidth(Str(i)))/2, (64 - TextHeight(Str(i)))/2, Str(i), $000000)
    SaveImage(0, "temp" + Str(i) + ".bmp")
    LoadTexture(i, "temp" + Str(i) + ".bmp")
    DeleteFile("temp" + Str(i) + ".bmp")
    CreateMaterial(i, TextureID(i))
  Next i
StopDrawing()
FreeImage(0)

;- Meshes
groundMesh = createPlainMesh(20 / #QUALITY, 200, 200)
gnomonMesh = createCylinderMesh(16 / #QUALITY, 20, 2, #CYLCAP_TOP, $FFFFFF)
boxMesh = createBoxMesh(8 / #QUALITY, 15, 20, 1)

;- Entities
groundEntity = CreateEntity(#PB_Any, MeshID(groundMesh), MaterialID(0))
gnomonEntity = CreateEntity(#PB_Any, MeshID(gnomonMesh), MaterialID(0))
EntityLocate(gnomonEntity, 0, 10, 0)

For i = 1 To 12
  boxEntity(i) = CreateEntity(#PB_Any, MeshID(boxMesh), MaterialID(i))
  EntityLocate(boxEntity(i), 50 * Cos((180 + 30 * i) * #DEG2RADMULT), 10, 50 * Sin((180 + 30 * i) * #DEG2RADMULT))
  RotateEntity(boxEntity(i), 0, 90 + i * - 30, 0)
Next i

;- **** MAIN LOOP *******************************************************************************
secs = Second(Date())
mins = Minute(Date()) + secs / 60
hours = Hour(Date()) + mins / 60 + secs / 3600
oldTimer = ElapsedMilliseconds()
Repeat
  If FullScreen = #False
    While WindowEvent() : Wend
  EndIf
  
  ;- Keyboard
  ExamineKeyboard()
  
  If KeyboardReleased(#PB_Key_F1)
    MessageRequester("Statistics", Str(CountRenderedTriangles()) + " polygons, " + Str(Engine3DFrameRate(#PB_Engine3D_Average)) + " Fps")
  EndIf
  
  ;- Move lights
  newTimer = ElapsedMilliseconds()
  movement = newTimer - oldTimer
  oldTimer = newTimer
  secs + movement / 1000
  If secs >= 60
    secs - 60
  EndIf
  LightLocate(0, 45 * Cos(secs * 6 * #DEG2RADMULT), 20, 45 * Sin(secs * 6 * #DEG2RADMULT))
  
  mins + movement / 60000
  If mins >= 60
    mins - 60
  EndIf
  LightLocate(1, 30 * Cos(mins * 6 * #DEG2RADMULT), 15, 28 * Sin(mins * 6 * #DEG2RADMULT))
  
  hours + movement / 3600000
  If hours >= 24
    hours - 24
  EndIf
  LightLocate(2, 15 * Cos(hours * 30 * #DEG2RADMULT), 10, 12 * Sin(hours * 30 * #DEG2RADMULT))
  
  ; Show it all
  RenderWorld()
  
  ; Flip buffers to avoid tearing
  FlipBuffers()
  
  Delay(1)
Until KeyboardPushed(#PB_Key_Escape)
Je sens que je vais me faire un écran de veille avec ça
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Message par Ollivier »

Wouaw! Très bon! Félicitations!

Ollivier
kelebrindae
Messages : 579
Inscription : ven. 11/mai/2007 15:21

Message par kelebrindae »

@Ollivier: Merci! :D

@LSI:
Décidément, le "examineDesktop" du début ne fonctionne pas chez moi (sur mon portable comme sur mon PC de bureau). Etrange... :?

Par contre, le centrage des chiffres et la suppression des BMP, c'est nickel!
Pour la taille des "aiguilles", j'avais testé autre chose: en augmentant la hauteur de la source lumineuse, on raccourci l'ombre => en mettant la lumière n°2 (celle des heures) à une hauteur de 45 et la n°1 (celle des minutes) à 38, on obtient des aiguille plus faciles à lire. Par contre, les sources lumineuses portent alors plus loin et "inondent" un peu la scène; j'aime moins, mais c'est une histoire de goût...

J'avais pensé à en faire un écran de veille aussi, mais comme je ne vais jamais au bout de des projets, tu peux y aller sans problème :wink:

Ah, un dernier truc: j'ai mis une capture d'écran ici:
Image
afin que l'on puisse valider que l'on a tous le même résultat, visuellement parlant (j'ai toujours des doutes). Cette capture correspond à la version du code présente dans mon post de Mardi 19/Mai/2009 21:40 (3 crans au-dessus) en mode fenêtré 800x600x32 avec #QUALITY = 1.

A+
Avatar de l’utilisateur
Progi1984
Messages : 2659
Inscription : mar. 14/déc./2004 13:56
Localisation : France > Rennes
Contact :

Message par Progi1984 »

Tite question : quelqu'un a réussi à le faire fonctionner sous Linux ?
Anonyme

Message par Anonyme »

oui , ca marche.
Azur
Messages : 40
Inscription : ven. 22/mai/2009 23:58

Message par Azur »

Oui alors là franchement, félicitations.
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Message par Le Soldat Inconnu »

je vois la même chose que toi kelebrindae :)
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
tmyke
Messages : 1554
Inscription : lun. 24/juil./2006 6:44
Localisation : vosges (France) 47°54'39.06"N 6°20'06.39"E

Message par tmyke »

kelebrindae a écrit : afin que l'on puisse valider que l'on a tous le même résultat, visuellement parlant (j'ai toujours des doutes). Cette capture correspond à la version du code présente dans mon post de Mardi 19/Mai/2009 21:40 (3 crans au-dessus) en mode fenêtré 800x600x32 avec #QUALITY = 1.

A+
Cela correspond bien a ton screen chez moi aussi (Windows XP, ATI9700pro.)
:D
Force et sagesse...
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Message par djes »

Super idée, et belle réalisation! :D
Tu pourrais peut-être ajouter un anneau plus petit (et moins haut) pour les secondes.
Sinon, n'oublie pas de mettre nom et date en haut du code et éventuellement le lien vers le topic. Comme ça si quelqu'un le met ailleurs on pourra retrouver la source et l'auteur.
Répondre