Page 1 sur 1

[Résolu] Calcul des normales d'un mesh: Normal smoothing

Publié : ven. 13/juin/2008 10:26
par kelebrindae
Bonjour,

J'ai ici un code qui part d'un mesh quelconque, puis subdivise ses faces et "sphérise" le tout en mettant tous les vertices à une distance identique du centre du mesh. (les spécialistes auront peut-être reconnu là l'algo qui permet de construire une géosphère).

Là dessus, je veux recalculer les normales des vertices du mesh afin de "smoother" le rendu (= lisser les facettes).
Avec une sphère de taille 1, c'est assez simple (la normale du vertex est égale à sa position, je crois), mais je veux une procédure qui puisse marcher avec n'importe quel mesh, histoire de me familiariser avec le concept.

Mais curieusement, le rendu me semble présenter des défauts: j'ai l'impression que l'éclairage de certains triangles est "inversé": à la limite lumière/ombre, ça fait un motif dentelé bizarroïde. :?
Image

Est-ce mon calcul des normales qui est faux, ou bien me plante-je en construisant le mesh (genre: un triangle construit avec les vertices dans le mauvais ordre) ?

Voici le code:

Code : Tout sélectionner

; Author: Kelebrindae
; Date: june,13,2008
; PB version: v4.10
; OS: Windows XP

#SQRT03=0.577350269189625764

;- Initialisation 
Resultat = MessageRequester("Mesh Subdivision","Full Screen ?",#PB_MessageRequester_YesNo) 
If Resultat = 6      
  FullScreen=1 
Else            
  FullScreen=0 
EndIf 

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

If Fullscreen  
  OpenScreen(800,600,32,"Mesh Subdivision") 
Else 
  OpenWindow(0,0, 0, 800 , 600 ,"Mesh Subdivision",#PB_Window_ScreenCentered) 
  OpenWindowedScreen(WindowID(0),0,0, 800 , 600,0,0,0) 
EndIf 

;- Data structures and definitions
Global CameraMode.l 

Structure Vector3
  x.f
  y.f
  z.f
EndStructure

Structure Vertex 
  px.f 
  py.f 
  pz.f 
  nx.f 
  ny.f 
  nz.f 
  couleur.l 
  U.f 
  V.f 
EndStructure 

Structure FaceTri 
  f1.w 
  f2.w 
  f3.w 
EndStructure
  
Structure dynMesh_struct
  id.s
  numMesh.l
  sizeX.f
  sizeY.f
  sizeZ.f
  nbVert.l
  nbTri.l
  *vertexBuffer.Vertex
  *faceBuffer.faceTri
EndStructure
#MAXMESH=2
Global Dim dynMesh.dynMesh_struct(#MAXMESH)

Enumeration
  #octahedron
  #pointyCube
EndEnumeration

  EnableExplicit


;- ---- Procedures ----
;************************************************************************************
; Name: NormalizeVector
; Purpose: Normalizes a vector to the length 1 without changing its orientation.
; Parameters:
;   - vector to normalize
;************************************************************************************
Procedure.l NormalizeVector(*Vec1.Vector3)
  Protected length.f
 
  length.f = Sqr(*Vec1\x * *Vec1\x + *Vec1\y * *Vec1\y + *Vec1\z * *Vec1\z)

  *Vec1\x / length
  *Vec1\y / length
  *Vec1\z / length

EndProcedure

; Macro version 
Macro NORME(V)
  (Sqr(V\x * V\x + V\y * V\y + V\z * V\z))
EndMacro 

;************************************************************************************
; Name: CreateDynMesh
; Purpose: Creates a mesh, scaled and UV mapped dynamically, and stores vertices/faces
;          infos in the "dynMesh" array
; Parameters:
;   - id of the mesh
;   - mesh type: #octahedron,#pointyCube
;   - X size
;   - Y size
;   - Z size
;   - origin of mapping coord U 
;   - origin of mapping coord V
;   - Vertices color
; Return value: mesh indice in the "dynMesh" array, or -1 if an error occurs
;************************************************************************************
Procedure.l CreateDynMesh(id.s,solid.l,sizeX.f,sizeY.f,sizeZ.f,Uorigin.f,Vorigin.f,Uscale.f,Vscale.f,color.l) 

  Protected x.f,y.f,z.f                     ; vertex position
  Protected nx.f,ny.f,nz.f                  ; vertex normals
  Protected u.f,v.f                         ; vertex UV coords (texture mapping)
  Protected v1.w,v2.w,v3.w
  Protected *PtrV.Vertex                    ; vertices buffer in memory
  Protected *PtrF.FaceTri                   ; Faces buffer in memory
  Protected num.l,i.l
  
  ; Restore the good set of meshdatas
  Select solid    
    Case #octahedron
      Restore octahedron
    
    Case #pointyCube
      Restore pointyCube
    
    Default
      ProcedureReturn -1 
  EndSelect 


  ; Find first free slot in dynMesh()
  While num<#MAXMESH And dynMesh(num)\nummesh>0
    num+1
  Wend

  ; Read number of vertices and triangles
  Read dynMesh(num)\nbVert
  Read dynMesh(num)\nbTri

  ; Allocate the needed memory for vertices
  dynMesh(num)\vertexBuffer = AllocateMemory(SizeOf(Vertex)*dynMesh(num)\nbVert) 
  *PtrV = dynMesh(num)\vertexBuffer 
  
  ; Allocate the needed memory for faces
  dynMesh(num)\faceBuffer=AllocateMemory(SizeOf(FaceTri)*dynMesh(num)\nbTri) 
  *PtrF=dynMesh(num)\faceBuffer

  ; Read and store vertices position, normals, uv coords
  For i = 1 To dynMesh(num)\nbVert
    Read x
    Read y
    Read z
    Read nx
    Read ny
    Read nz
    Read u
    Read v
  
    *PtrV\px = x * sizex
    *PtrV\py = y * sizey
    *PtrV\pz = z * sizez
    
    *PtrV\nx = nx 
    *PtrV\ny = ny
    *PtrV\nz = nz 
    *PtrV\couleur = color
    *PtrV\u = uorigin + (u * uscale)
    *PtrV\v = vorigin + (v * vscale)
    *PtrV + SizeOf(Vertex) 
  Next i    

  ;Read and store faces infos
  For i=1 To dynMesh(num)\nbTri 
    Read v1
    Read v2
    Read v3 
     
    *PtrF\f1=v1  
    *PtrF\f2=v2 
    *PtrF\f3=v3 
    *PtrF + SizeOf(FaceTri) 
  Next i 
     

  ; Create mesh from stored infos
  dynMesh(num)\numMesh = CreateMesh(#PB_Any,dynMesh(num)\nbVert)
  If IsMesh(dynMesh(num)\numMesh) 
    SetMeshData(dynMesh(num)\numMesh,#PB_Mesh_Vertex | #PB_Mesh_Normal | #PB_Mesh_UVCoordinate | #PB_Mesh_Color,dynMesh(num)\vertexBuffer,dynMesh(num)\nbVert) 
    SetMeshData(dynMesh(num)\numMesh,#PB_Mesh_Face,dynMesh(num)\faceBuffer,dynMesh(num)\nbTri) 
    
    dynMesh(num)\id = id
    dynMesh(num)\sizeX = sizeX
    dynMesh(num)\sizeY = sizeY
    dynMesh(num)\sizeZ = sizeZ

    ProcedureReturn num 
  Else 
    ; free memory if "createMesh" has failed
    FreeMemory(dynMesh(num)\vertexBuffer)
    FreeMemory(dynMesh(num)\faceBuffer)
    ProcedureReturn -1    
  EndIf 
    
EndProcedure    

;************************************************************************************
; Name: deleteDynMesh
; Purpose: deletes a mesh and all vertices/faces infos in the "dynMesh" array
; Parameters:
;   - mesh indice in the "dynMesh" array
;   - mesh type: #octahedron,#pointyCube
;************************************************************************************
Procedure deleteDynMesh(num.l)

    If dynMesh(num)\numMesh=0
      ProcedureReturn -1
    EndIf

    ;FreeMesh(dynMesh(num)\numMesh)
    FreeMemory(dynMesh(num)\vertexBuffer)
    FreeMemory(dynMesh(num)\faceBuffer)
    dynMesh(num)\numMesh=0
  
EndProcedure

;************************************************************************************
; Name: inflateMesh
; Purpose: normalizes each vertex' position so they're at the same distance from the center
;          of the mesh => makes the mesh spheric
; Parameters:
;   - mesh indice in the "dynMesh" array
;   - mesh type: #octahedron,#pointyCube
;************************************************************************************
Procedure inflateMesh(numMesh.l)
  Protected i.l
  Protected *ptrVert.Vertex
  Protected vector3.Vector3
  Protected NormeVecteur.f

  *ptrVert = dynMesh(numMesh)\vertexBuffer
  For i = 1 To dynmesh(numMesh)\nbVert

    vector3\x = *ptrVert\px
    vector3\y = *ptrVert\py
    vector3\z = *ptrVert\pz
    
    NormalizeVector(@vector3)
    
    ; Equivalent:
;     NormeVecteur = NORME(vector3)
;     If NormeVecteur <> 0.0
;       vector3\x / NormeVecteur
;       vector3\y / NormeVecteur
;       vector3\z / NormeVecteur
;     EndIf  
       
    *ptrVert\px = vector3\x * dynMesh(numMesh)\sizeX
    *ptrVert\py = vector3\y * dynMesh(numMesh)\sizeY
    *ptrVert\pz = vector3\z * dynMesh(numMesh)\sizeZ
    *ptrVert\nx = vector3\x 
    *ptrVert\ny = vector3\y 
    *ptrVert\nz = vector3\z

    *ptrVert+SizeOf(Vertex)
  Next i
  
EndProcedure

;************************************************************************************
; Name: subdivideTriangle
; Purpose: Subdivides a triangle of the mesh into 4 smaller triangles
;   - mesh indice in the "dynMesh" array
;   - triangle to subdivide
;************************************************************************************
Procedure subdivideTriangle(nummesh.l,numtri.l)

  Protected VertexA.Vertex
  Protected VertexB.Vertex
  Protected VertexC.Vertex
  Protected *PtrV0.Vertex,*PtrV1.Vertex,*PtrV2.Vertex
  Protected *PtrNewV.vertex,*PtrNewF.faceTri
  Protected oldNbVert.w,oldNbFace.l,newVertNum.w

  Debug "Mesh n°" + Str(nummesh) + ", " + Str(dynmesh(nummesh)\nbvert) + " vertices, " + Str(dynmesh(nummesh)\nbtri) + " triangles"
  Debug "Subdivision du triangle n°" + Str(numtri)
  Debug "   ->Taille mémoire pour vertices/faces: " + Str(MemorySize(dynMesh(nummesh)\vertexBuffer)) + " / " + Str(MemorySize(dynMesh(nummesh)\faceBuffer))
  Debug "   ->Taille mémoire des structures vertices/faces: " + Str(SizeOf(Vertex)) + " / " + Str(SizeOf(faceTri))
 

  ; Store current end of vertices/faces datas
  oldNbVert = dynMesh(nummesh)\nbVert
  oldNbFace = dynMesh(nummesh)\nbTri
  newVertNum = oldNbVert
       
  ; Extend allocated memory for new vertices and faces
  dynmesh(nummesh)\nbvert+9
  dynMesh(nummesh)\vertexBuffer = ReAllocateMemory(dynMesh(nummesh)\vertexBuffer,SizeOf(Vertex)*dynMesh(nummesh)\nbVert) 
  dynmesh(nummesh)\nbtri+3
  dynMesh(nummesh)\faceBuffer = ReAllocateMemory(dynMesh(nummesh)\faceBuffer,SizeOf(FaceTri)*dynMesh(nummesh)\nbTri) 
  ; NB: on ajoute que 3 triangles, car le triangle subdivisé est réutilisé
  
  
  Debug "   Augmentation nb vertices/faces à: " + Str(dynmesh(nummesh)\nbvert) + " / " + Str(dynmesh(nummesh)\nbtri)
  Debug "   ->Taille mémoire demandée pour vertices/faces: " + Str(SizeOf(Vertex) * dynmesh(nummesh)\nbvert) + " / " + Str(SizeOf(FaceTri) * dynmesh(nummesh)\nbtri)
  Debug "   Resultat de ReAllocate: " + Str(dynMesh(nummesh)\vertexBuffer) + " / " + Str(dynMesh(nummesh)\FaceBuffer)
  Debug "   ->Nouvelle taille mémoire: " + Str(MemorySize(dynMesh(nummesh)\vertexBuffer)) + " / " + Str(MemorySize(dynMesh(nummesh)\faceBuffer))


  ; le triangle est divisé en 4
  ; Phase 1: on repère l'emplacement des vertices du triangle
  *PtrV0 = dynMesh(nummesh)\vertexBuffer + (numtri * SizeOf(Vertex) * 3)
  *PtrV1 = dynMesh(nummesh)\vertexBuffer + (numtri * SizeOf(Vertex) * 3) + SizeOf(Vertex)
  *PtrV2 = dynMesh(nummesh)\vertexBuffer + (numtri * SizeOf(Vertex) * 3) + SizeOf(Vertex) * 2

  Debug "      Vertex réf., n°" + Str((*PtrV0 - dynMesh(nummesh)\vertexBuffer)/SizeOf(Vertex)) + ": " + StrF(*PtrV0\px)+","+StrF(*PtrV0\py)+","+StrF(*PtrV0\pz)
  Debug "      Vertex réf., n°" + Str((*PtrV1 - dynMesh(nummesh)\vertexBuffer)/SizeOf(Vertex)) + ": " + StrF(*PtrV1\px)+","+StrF(*PtrV1\py)+","+StrF(*PtrV1\pz)
  Debug "      Vertex réf., n°" + Str((*PtrV2 - dynMesh(nummesh)\vertexBuffer)/SizeOf(Vertex)) + ": " + StrF(*PtrV2\px)+","+StrF(*PtrV2\py)+","+StrF(*PtrV2\pz)


  ; Phase 2: on calcule la position des nouveaux vertices
  VertexA\px = (*PtrV0\px + *PtrV1\px) / 2.0
  VertexA\py = (*PtrV0\py + *PtrV1\py) / 2.0
  VertexA\pz = (*PtrV0\pz + *PtrV1\pz) / 2.0
  VertexA\nx = VertexA\px / dynMesh(nummesh)\sizex
  VertexA\ny = VertexA\py / dynMesh(nummesh)\sizey
  VertexA\nz = VertexA\pz / dynMesh(nummesh)\sizez
  VertexA\couleur = (*PtrV0\couleur + *PtrV1\couleur) / 2.0
  VertexA\U =  (*PtrV0\U + *PtrV1\U) / 2.0
  VertexA\V =  (*PtrV0\V + *PtrV1\V) / 2.0

  VertexB\px = (*PtrV0\px + *PtrV2\px) / 2.0
  VertexB\py = (*PtrV0\py + *PtrV2\py) / 2.0
  VertexB\pz = (*PtrV0\pz + *PtrV2\pz) / 2.0
  VertexB\nx = VertexB\px / dynMesh(nummesh)\sizex
  VertexB\ny = VertexB\py / dynMesh(nummesh)\sizey
  VertexB\nz = VertexB\pz / dynMesh(nummesh)\sizez 
  VertexB\couleur = (*PtrV0\couleur + *PtrV2\couleur) / 2.0
  VertexB\U =  (*PtrV0\U + *PtrV2\U) / 2.0
  VertexB\V =  (*PtrV0\V + *PtrV2\V) / 2.0

  VertexC\px = (*PtrV1\px + *PtrV2\px) / 2.0
  VertexC\py = (*PtrV1\py + *PtrV2\py) / 2.0
  VertexC\pz = (*PtrV1\pz + *PtrV2\pz) / 2.0
  VertexC\nx = VertexC\px / dynMesh(nummesh)\sizex
  VertexC\ny = VertexC\py / dynMesh(nummesh)\sizey
  VertexC\nz = VertexC\pz / dynMesh(nummesh)\sizez
  VertexC\couleur = (*PtrV1\couleur + *PtrV2\couleur) / 2.0
  VertexC\U =  (*PtrV1\U + *PtrV2\U) / 2.0
  VertexC\V =  (*PtrV1\V + *PtrV2\V) / 2.0

  ; on écrira les nouveaux vertices/faces à ces endroits:
  *PtrNewV = dynMesh(nummesh)\vertexBuffer + (SizeOf(Vertex) * (oldNbVert) )
  *PtrNewF = dynMesh(nummesh)\faceBuffer + (SizeOf(FaceTri) * (oldNbFace) )  

  ; Add a new triangle...
  ;AddTri( *PtrV1, VertexC, VertexA)
  *PtrNewV\px = *PtrV1\px
  *PtrNewV\py = *PtrV1\py
  *PtrNewV\pz = *PtrV1\pz
  *PtrNewV\nx = *PtrV1\nx 
  *PtrNewV\ny = *PtrV1\ny
  *PtrNewV\nz = *PtrV1\nz 
  *PtrNewV\couleur = *PtrV1\couleur 
  *PtrNewV\u = *PtrV1\u
  *PtrNewV\v = *PtrV1\v
  Debug "         New Vertex, n°" + Str((*PtrNewV - dynMesh(nummesh)\vertexBuffer)/SizeOf(Vertex)) + ": " + StrF(*PtrNewV\px)+","+StrF(*PtrNewV\py)+","+StrF(*PtrNewV\pz)
  *PtrNewV + SizeOf(Vertex)

  *PtrNewV\px = VertexC\px
  *PtrNewV\py = VertexC\py
  *PtrNewV\pz = VertexC\pz
  *PtrNewV\nx = VertexC\nx 
  *PtrNewV\ny = VertexC\ny
  *PtrNewV\nz = VertexC\nz 
  *PtrNewV\couleur = VertexC\couleur 
  *PtrNewV\u = VertexC\u
  *PtrNewV\v = VertexC\v
  Debug "         New Vertex, n°" + Str((*PtrNewV - dynMesh(nummesh)\vertexBuffer)/SizeOf(Vertex)) + ": " + StrF(*PtrNewV\px)+","+StrF(*PtrNewV\py)+","+StrF(*PtrNewV\pz)
  *PtrNewV + SizeOf(Vertex)

  *PtrNewV\px = VertexA\px
  *PtrNewV\py = VertexA\py
  *PtrNewV\pz = VertexA\pz
  *PtrNewV\nx = VertexA\nx 
  *PtrNewV\ny = VertexA\ny
  *PtrNewV\nz = VertexA\nz 
  *PtrNewV\couleur = VertexA\couleur 
  *PtrNewV\u = VertexA\u
  *PtrNewV\v = VertexA\v
  Debug "         New Vertex, n°" + Str((*PtrNewV - dynMesh(nummesh)\vertexBuffer)/SizeOf(Vertex)) + ": " + StrF(*PtrNewV\px)+","+StrF(*PtrNewV\py)+","+StrF(*PtrNewV\pz)
  *PtrNewV + SizeOf(Vertex)
  
  *PtrNewF\f1=newVertNum  
  *PtrNewF\f2=newVertNum +1
  *PtrNewF\f3=newVertNum +2
  Debug "           => new triangle, n°" + Str((*PtrNewF - dynMesh(nummesh)\faceBuffer)/SizeOf(FaceTri)) + ": " + Str(*PtrNewF\f1)+","+Str(*PtrNewF\f2)+","+Str(*PtrNewF\f3)
  *PtrNewF + SizeOf(FaceTri) 
  newVertNum+3
   
  ; ...add another...
  ;AddTri( *PtrV2, VertexB, VertexC)
  *PtrNewV\px = *PtrV2\px
  *PtrNewV\py = *PtrV2\py
  *PtrNewV\pz = *PtrV2\pz
  *PtrNewV\nx = *PtrV2\nx 
  *PtrNewV\ny = *PtrV2\ny
  *PtrNewV\nz = *PtrV2\nz 
  *PtrNewV\couleur = *PtrV2\couleur 
  *PtrNewV\u = *PtrV2\u
  *PtrNewV\v = *PtrV2\v
  Debug "         New Vertex, n°" + Str((*PtrNewV - dynMesh(nummesh)\vertexBuffer)/SizeOf(Vertex)) + ": " + StrF(*PtrNewV\px)+","+StrF(*PtrNewV\py)+","+StrF(*PtrNewV\pz)
  *PtrNewV + SizeOf(Vertex)

  *PtrNewV\px = VertexB\px
  *PtrNewV\py = VertexB\py
  *PtrNewV\pz = VertexB\pz
  *PtrNewV\nx = VertexB\nx 
  *PtrNewV\ny = VertexB\ny
  *PtrNewV\nz = VertexB\nz 
  *PtrNewV\couleur = VertexB\couleur 
  *PtrNewV\u = VertexB\u
  *PtrNewV\v = VertexB\v
  Debug "         New Vertex, n°" + Str((*PtrNewV - dynMesh(nummesh)\vertexBuffer)/SizeOf(Vertex)) + ": " + StrF(*PtrNewV\px)+","+StrF(*PtrNewV\py)+","+StrF(*PtrNewV\pz)
  *PtrNewV + SizeOf(Vertex)

  *PtrNewV\px = VertexC\px
  *PtrNewV\py = VertexC\py
  *PtrNewV\pz = VertexC\pz
  *PtrNewV\nx = VertexC\nx 
  *PtrNewV\ny = VertexC\ny
  *PtrNewV\nz = VertexC\nz 
  *PtrNewV\couleur = VertexC\couleur 
  *PtrNewV\u = VertexC\u
  *PtrNewV\v = VertexC\v
  Debug "         New Vertex, n°" + Str((*PtrNewV - dynMesh(nummesh)\vertexBuffer)/SizeOf(Vertex)) + ": " + StrF(*PtrNewV\px)+","+StrF(*PtrNewV\py)+","+StrF(*PtrNewV\pz)
  *PtrNewV + SizeOf(Vertex)
  
  *PtrNewF\f1=newVertNum 
  *PtrNewF\f2=newVertNum +1
  *PtrNewF\f3=newVertNum +2
  Debug "           => new triangle, n°" + Str((*PtrNewF - dynMesh(nummesh)\faceBuffer)/SizeOf(FaceTri)) + ": " + Str(*PtrNewF\f1)+","+Str(*PtrNewF\f2)+","+Str(*PtrNewF\f3)
  *PtrNewF + SizeOf(FaceTri) 
  newVertNum+3

  ; ...and another...
  ;AddTri( VertexA, VertexC, VertexB)
  *PtrNewV\px = VertexA\px
  *PtrNewV\py = VertexA\py
  *PtrNewV\pz = VertexA\pz
  *PtrNewV\nx = VertexA\nx 
  *PtrNewV\ny = VertexA\ny
  *PtrNewV\nz = VertexA\nz 
  *PtrNewV\couleur = VertexA\couleur 
  *PtrNewV\u = VertexA\u
  *PtrNewV\v = VertexA\v
  Debug "         New Vertex, n°" + Str((*PtrNewV - dynMesh(nummesh)\vertexBuffer)/SizeOf(Vertex)) + ": " + StrF(*PtrNewV\px)+","+StrF(*PtrNewV\py)+","+StrF(*PtrNewV\pz)
  *PtrNewV + SizeOf(Vertex)
  
  *PtrNewV\px = VertexC\px
  *PtrNewV\py = VertexC\py
  *PtrNewV\pz = VertexC\pz
  *PtrNewV\nx = VertexC\nx 
  *PtrNewV\ny = VertexC\ny
  *PtrNewV\nz = VertexC\nz 
  *PtrNewV\couleur = VertexC\couleur 
  *PtrNewV\u = VertexC\u
  *PtrNewV\v = VertexC\v
  Debug "         New Vertex, n°" + Str((*PtrNewV - dynMesh(nummesh)\vertexBuffer)/SizeOf(Vertex)) + ": " + StrF(*PtrNewV\px)+","+StrF(*PtrNewV\py)+","+StrF(*PtrNewV\pz)
  *PtrNewV + SizeOf(Vertex)

  *PtrNewV\px = VertexB\px
  *PtrNewV\py = VertexB\py
  *PtrNewV\pz = VertexB\pz
  *PtrNewV\nx = VertexB\nx 
  *PtrNewV\ny = VertexB\ny
  *PtrNewV\nz = VertexB\nz 
  *PtrNewV\couleur = VertexB\couleur 
  *PtrNewV\u = VertexB\u
  *PtrNewV\v = VertexB\v
  Debug "         New Vertex, n°" + Str((*PtrNewV - dynMesh(nummesh)\vertexBuffer)/SizeOf(Vertex)) + ": " + StrF(*PtrNewV\px)+","+StrF(*PtrNewV\py)+","+StrF(*PtrNewV\pz)
  *PtrNewV + SizeOf(Vertex)
  
  *PtrNewF\f1=newVertNum 
  *PtrNewF\f2=newVertNum +1
  *PtrNewF\f3=newVertNum +2
  Debug "           => new triangle, n°" + Str((*PtrNewF - dynMesh(nummesh)\faceBuffer)/SizeOf(FaceTri)) + ": " + Str(*PtrNewF\f1)+","+Str(*PtrNewF\f2)+","+Str(*PtrNewF\f3)
  *PtrNewF + SizeOf(FaceTri) 
  newVertNum+3

   
  ; ...then resize base triangle.
  *PtrV1\px = VertexA\px
  *PtrV1\py = VertexA\py
  *PtrV1\pz = VertexA\pz
  *PtrV1\nx = VertexA\nx
  *PtrV1\ny = VertexA\ny
  *PtrV1\nz = VertexA\nz
  *PtrV1\U  = VertexA\U
  *PtrV1\V  = VertexA\V
  Debug "         Reposition Vertex, n°" + Str((*PtrV1 - dynMesh(nummesh)\vertexBuffer)/SizeOf(Vertex)) + ": " + StrF(*PtrV1\px)+","+StrF(*PtrV1\py)+","+StrF(*PtrV1\pz)

  *PtrV2\px = VertexB\px
  *PtrV2\py = VertexB\py
  *PtrV2\pz = VertexB\pz
  *PtrV2\nx = VertexB\nx
  *PtrV2\ny = VertexB\ny
  *PtrV2\nz = VertexB\nz
  *PtrV2\U  = VertexB\U
  *PtrV2\V  = VertexB\V
  Debug "         Reposition Vertex, n°" + Str((*PtrV2 - dynMesh(nummesh)\vertexBuffer)/SizeOf(Vertex)) + ": " + StrF(*PtrV2\px)+","+StrF(*PtrV2\py)+","+StrF(*PtrV2\pz)
  
  Debug "---------------------------------------------------"
EndProcedure

;************************************************************************************
; Name: subdivideMesh
; Purpose: Subdivides each triangle of a mesh, then inflates the mesh to make it look spheric
;   - mesh indice in the "dynMesh" array
;   - how many times the process will be repeated
;************************************************************************************
Procedure subdivideMesh(nummesh.l,nbiteration.b)
   Protected i.l,j.l,top.l

   ; subdivision
   For j = 1 To nbiteration
      top =  dynMesh(nummesh)\nbTri - 1
      For i = 0 To top
         subdivideTriangle(nummesh,i)
      Next i
   Next j
   
   ; "Spherify"
   inflateMesh(nummesh)
   
   ; modify mesh infos
   SetMeshData(dynMesh(nummesh)\numMesh,#PB_Mesh_Vertex | #PB_Mesh_Normal | #PB_Mesh_Color | #PB_Mesh_UVCoordinate,dynMesh(nummesh)\vertexBuffer,dynMesh(nummesh)\nbVert) 
   SetMeshData(dynMesh(nummesh)\numMesh,#PB_Mesh_Face,dynMesh(nummesh)\faceBuffer,dynMesh(nummesh)\nbTri) 

EndProcedure

;************************************************************************************
; Name: subdivideMesh
; Purpose: Subdivides each triangle of a mesh, then inflates the mesh to make it look spheric
;   - mesh indice in the "dynMesh" array
;   - how many times the process will be repeated
;************************************************************************************
Procedure normalizeMesh(nummesh.l)

  Protected *ptrVert.vertex,*PtrV0.vertex,*PtrV1.vertex,*PtrV2.vertex
  Protected *ptrFace.faceTri
  Protected normVect1.Vector3,normVect2.Vector3,faceNormal.Vector3
  Protected i.l,j.l,length.f
  
 ; Initialize vertices' normals to 0
  *ptrVert = dynMesh(numMesh)\vertexBuffer
  For i = 1 To dynmesh(numMesh)\nbVert
    *ptrVert\nx = 0
    *ptrVert\ny = 0
    *ptrVert\nz = 0

    *ptrVert+SizeOf(Vertex)
  Next i
  
  ; For each facet of the mesh:
  *ptrFace = dynMesh(nummesh)\faceBuffer
  For i = 1 To dynMesh(nummesh)\nbTri
    Debug "Face n°" + Str(i-1) + " - vertices " + Str(*ptrface\f1)+","+ Str(*ptrface\f2)+","+ Str(*ptrface\f3)
  
    ; Get facet normal
    *PtrV0 = dynMesh(nummesh)\vertexBuffer + (*ptrface\f1 * SizeOf(Vertex))
    *PtrV1 = dynMesh(nummesh)\vertexBuffer + (*ptrface\f2 * SizeOf(Vertex))
    *PtrV2 = dynMesh(nummesh)\vertexBuffer + (*ptrface\f3 * SizeOf(Vertex))
  
    normVect1\x = (*PtrV1\px - *PtrV0\px)
    normVect1\y = (*PtrV1\py - *PtrV0\py)
    normVect1\z = (*PtrV1\pz - *PtrV0\pz)
    
    normVect2\x = (*PtrV2\px - *PtrV0\px)
    normVect2\y = (*PtrV2\py - *PtrV0\py)
    normVect2\z = (*PtrV2\pz - *PtrV0\pz)
    
    faceNormal\x = ((normVect1\y * normVect2\z) - (normVect1\z * normVect2\y))
    faceNormal\y = ((normVect1\z * normVect2\x) - (normVect1\x * normVect2\z))
    faceNormal\z = ((normVect1\x * normVect2\y) - (normVect1\y * normVect2\x))
    
    Length = Sqr(faceNormal\x*faceNormal\x + faceNormal\y*faceNormal\y + faceNormal\z*faceNormal\z)
    faceNormal\x / Length
    faceNormal\y / Length
    faceNormal\z / Length   
    Debug "=> Normal = "+StrF(faceNormal\x)+","+StrF(faceNormal\y)+","+StrF(faceNormal\z)
    
    ; First vertex of face
    *ptrVert = dynMesh(numMesh)\vertexBuffer
    ; for all vertices at the same position, add face normal to vertex normal
    For j = 1 To dynmesh(numMesh)\nbVert
      If *ptrVert\px = *ptrV0\px And *ptrVert\py = *ptrV0\py And *ptrVert\pz = *ptrV0\pz 
        *ptrVert\nx + faceNormal\x
        *ptrVert\ny + faceNormal\y
        *ptrVert\nz + faceNormal\z
        Debug "   vertex " + Str(*ptrface\f1) +" = vertex " + Str(j-1)
      EndIf
      *ptrVert+SizeOf(Vertex)
    Next j
    
    ; Second vertex of face
    *ptrVert = dynMesh(numMesh)\vertexBuffer
    ; for all vertices at the same position, add face normal to vertex normal
    For j = 1 To dynmesh(numMesh)\nbVert
      If *ptrVert\px = *ptrV1\px And *ptrVert\py = *ptrV1\py And *ptrVert\pz = *ptrV1\pz 
        *ptrVert\nx + faceNormal\x
        *ptrVert\ny + faceNormal\y
        *ptrVert\nz + faceNormal\z
        Debug "   vertex " + Str(*ptrface\f2) +" = vertex " + Str(j-1)
      EndIf
      *ptrVert+SizeOf(Vertex)
    Next j
       
    ; Third vertex of face
    *ptrVert = dynMesh(numMesh)\vertexBuffer
    ; for all vertices at the same position, add face normal to vertex normal
    For j = 1 To dynmesh(numMesh)\nbVert
      If *ptrVert\px = *ptrV2\px And *ptrVert\py = *ptrV2\py And *ptrVert\pz = *ptrV2\pz 
        *ptrVert\nx + faceNormal\x
        *ptrVert\ny + faceNormal\y
        *ptrVert\nz + faceNormal\z
        Debug "   vertex " + Str(*ptrface\f3) +" = vertex " + Str(j-1)
      EndIf
      *ptrVert+SizeOf(Vertex)
    Next j
    
    *ptrFace+SizeOf(faceTri)
  Next i
  
  ; Then, average (= normalize) all the vertices' normals
  *ptrVert = dynMesh(numMesh)\vertexBuffer
  For j = 1 To dynmesh(numMesh)\nbVert
    normVect1\x = *ptrVert\nx
    normVect1\y = *ptrVert\ny
    normVect1\z = *ptrVert\nz
    
    NormalizeVector(@normVect1)
    
    *ptrVert\nx = normVect1\x
    *ptrVert\ny = normVect1\y
    *ptrVert\nz = normVect1\z  
    
    *ptrVert+SizeOf(Vertex)
  Next j
  
     ; modify mesh infos
   SetMeshData(dynMesh(nummesh)\numMesh,#PB_Mesh_Vertex | #PB_Mesh_Normal | #PB_Mesh_Color | #PB_Mesh_UVCoordinate,dynMesh(nummesh)\vertexBuffer,dynMesh(nummesh)\nbVert) 

EndProcedure

;************************************************************************************

;- ---- Main loop ----
;-Mesh 
; Change parameters 2 to 8 to test the effects on size and texturing
Global myOctaMesh.l
myOctaMesh = CreateDynMesh("Octa",#octahedron,3,3,3,0,0,4,4,RGB(0,127,200)) 

;-Texture 
CreateTexture(0,128, 128) 
StartDrawing(TextureOutput(0)) 
  Box(0, 0, 128, 128, $FFFFFF) 
  DrawingMode(#PB_2DDrawing_Outlined)
  Box(0, 0, 128, 128, $0000FF) 
StopDrawing()  


;-Material
CreateMaterial(0,TextureID(0)) 

;-Entity 
CreateEntity(0,MeshID(dynMesh(myOctaMesh)\numMesh),MaterialID(0))

;-Camera 
CreateCamera(0, 0, 0 , 100 , 100) 
MoveCamera(0,0,0,-15) 
CameraLookAt(0,0,0,0) 

;-Light 
AmbientColor(RGB(63,63,63)) 
CreateLight(0,RGB(255,255,255),200,300,0) 
;CreateLight(1,RGB(255,127,0),-200,-200,200) 


Global pas.f,angle.f
pas = 0.8
angle = 0
Repeat 
   If fullscreen = 0 
      While WindowEvent() : Wend 
   EndIf
   
   ; Rotate 
   Angle + Pas 
   RotateEntity(0, angle,angle/2,-angle) 


   ; Wireframe or not
   If ExamineKeyboard() 
      If KeyboardReleased(#PB_Key_F1) 
       CameraMode=1-CameraMode 
       CameraRenderMode(0,CameraMode) 
       AmbientColor(RGB(105+cameramode*150,105+cameramode*150,105+cameramode*150)) 
     EndIf 
     
     If KeyboardReleased(#PB_Key_S) 
       subdivideMesh(0,1)
     EndIf     
     
     If KeyboardReleased(#PB_Key_N) 
       normalizeMesh(0)
     EndIf     
     
   EndIf 
   
  ; show it all
  RenderWorld() 
   
  ; A little help
  StartDrawing(ScreenOutput())
  DrawText(0,0,"[F1] to change RenderMode, [S] to subdivide mesh, [N] to smooth normals ", $00FFFF, $BB0000)
  DrawText(0,15,Str(dynMesh(0)\nbVert) + " vertices, taille du buffer = " + Str(MemorySize(dynMesh(0)\vertexBuffer)) + " octets", $00FFFF, $BB0000)
  DrawText(0,30,Str(dynMesh(0)\nbTri) + " faces, taille du buffer = " + Str(MemorySize(dynMesh(0)\FaceBuffer)) + " octets", $00FFFF, $BB0000)
  StopDrawing() 
  
  ; Flip buffers to avoid tearing  
  FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape) 

deleteDynMesh(myOctaMesh)


DataSection:
octahedron:
; Nb sommets / Nb faces
Data.l 24,8

; Vertices: pos / normals / uv
Data.f 0,1,0
Data.f 0,1,0
Data.f 0.5,0.5
Data.f 0,0,1
Data.f 0,0,1
Data.f 0,0
Data.f 1,0,0
Data.f 1,0,0
Data.f 1,0

Data.f 0,1,0
Data.f 0,1,0
Data.f 0.5,0.5
Data.f 1,0,0
Data.f 1,0,0
Data.f 1,0
Data.f 0,0,-1
Data.f 0,0,-1
Data.f 1,1

Data.f 0,1,0
Data.f 0,1,0
Data.f 0.5,0.5
Data.f 0,0,-1
Data.f 0,0,-1
Data.f 1,1
Data.f -1,0,0
Data.f -1,0,0
Data.f 0,1

Data.f 0,1,0
Data.f 0,1,0
Data.f 0.5,0.5
Data.f -1,0,0
Data.f -1,0,0
Data.f 0,1
Data.f 0,0,1
Data.f 0,0,1
Data.f 0,0

Data.f 0,-1,0
Data.f 0,-1,0
Data.f 0.5,0.5
Data.f 1,0,0
Data.f 1,0,0
Data.f 1,0
Data.f 0,0,1
Data.f 0,0,1
Data.f 0,0

Data.f 0,-1,0
Data.f 0,-1,0
Data.f 0.5,0.5
Data.f 0,0,-1
Data.f 0,0,-1
Data.f 1,1
Data.f 1,0,0
Data.f 1,0,0
Data.f 1,0

Data.f 0,-1,0
Data.f 0,-1,0
Data.f 0.5,0.5
Data.f -1,0,0
Data.f -1,0,0
Data.f 0,1
Data.f 0,0,-1
Data.f 0,0,-1
Data.f 1,1

Data.f 0,-1,0
Data.f 0,-1,0
Data.f 0.5,0.5
Data.f 0,0,1
Data.f 0,0,1
Data.f 0,0
Data.f -1,0,0
Data.f -1,0,0
Data.f 0,1

; Faces
Data.w 0,1,2
Data.w 3,4,5
Data.w 6,7,8
Data.w 9,10,11
Data.w 12,13,14
Data.w 15,16,17
Data.w 18,19,20
Data.w 21,22,23



PointyCube:
; Nb sommets / Nb faces
Data.l 72,24

; Vertices: pos / uv
Data.f 0,1,0
Data.f 0,1,0
Data.f 0.5,0.5
Data.f -#SQRT03,#SQRT03,#SQRT03
Data.f -#SQRT03,#SQRT03,#SQRT03
Data.f 0,0
Data.f #SQRT03,#SQRT03,#SQRT03
Data.f #SQRT03,#SQRT03,#SQRT03
Data.f 1,0
Data.f 0,1,0
Data.f 0,1,0
Data.f 0.5,0.5
Data.f #SQRT03,#SQRT03,#SQRT03
Data.f #SQRT03,#SQRT03,#SQRT03
Data.f 1,0
Data.f #SQRT03,#SQRT03,-#SQRT03
Data.f #SQRT03,#SQRT03,-#SQRT03
Data.f 1,1
Data.f 0,1,0
Data.f 0,1,0
Data.f 0.5,0.5
Data.f #SQRT03,#SQRT03,-#SQRT03
Data.f #SQRT03,#SQRT03,-#SQRT03
Data.f 1,1
Data.f -#SQRT03,#SQRT03,-#SQRT03
Data.f -#SQRT03,#SQRT03,-#SQRT03
Data.f 0,1
Data.f 0,1,0
Data.f 0,1,0
Data.f 0.5,0.5
Data.f -#SQRT03,#SQRT03,-#SQRT03
Data.f -#SQRT03,#SQRT03,-#SQRT03
Data.f 0,1
Data.f -#SQRT03,#SQRT03,#SQRT03
Data.f -#SQRT03,#SQRT03,#SQRT03
Data.f 0,0
Data.f 0,-1,0
Data.f 0,-1,0
Data.f 0.5,0.5
Data.f #SQRT03,-#SQRT03,#SQRT03
Data.f #SQRT03,-#SQRT03,#SQRT03
Data.f 0,0
Data.f -#SQRT03,-#SQRT03,#SQRT03
Data.f -#SQRT03,-#SQRT03,#SQRT03
Data.f 1,0
Data.f 0,-1,0
Data.f 0,-1,0
Data.f 0.5,0.5
Data.f #SQRT03,-#SQRT03,-#SQRT03
Data.f #SQRT03,-#SQRT03,-#SQRT03
Data.f 1,0
Data.f #SQRT03,-#SQRT03,#SQRT03
Data.f #SQRT03,-#SQRT03,#SQRT03
Data.f 1,1
Data.f 0,-1,0
Data.f 0,-1,0
Data.f 0.5,0.5
Data.f -#SQRT03,-#SQRT03,-#SQRT03
Data.f -#SQRT03,-#SQRT03,-#SQRT03
Data.f 1,1
Data.f #SQRT03,-#SQRT03,-#SQRT03
Data.f #SQRT03,-#SQRT03,-#SQRT03
Data.f 0,1
Data.f 0,-1,0
Data.f 0,-1,0
Data.f 0.5,0.5
Data.f -#SQRT03,-#SQRT03,#SQRT03
Data.f -#SQRT03,-#SQRT03,#SQRT03
Data.f 0,1
Data.f -#SQRT03,-#SQRT03,-#SQRT03
Data.f -#SQRT03,-#SQRT03,-#SQRT03
Data.f 0,0
Data.f 1,0,0
Data.f 1,0,0
Data.f 0.5,0.5
Data.f #SQRT03,#SQRT03,-#SQRT03
Data.f #SQRT03,#SQRT03,-#SQRT03
Data.f 0,0
Data.f #SQRT03,#SQRT03,#SQRT03
Data.f #SQRT03,#SQRT03,#SQRT03
Data.f 1,0
Data.f 1,0,0
Data.f 1,0,0
Data.f 0.5,0.5
Data.f #SQRT03,#SQRT03,#SQRT03
Data.f #SQRT03,#SQRT03,#SQRT03
Data.f 1,0
Data.f #SQRT03,-#SQRT03,#SQRT03
Data.f #SQRT03,-#SQRT03,#SQRT03
Data.f 1,1
Data.f 1,0,0
Data.f 1,0,0
Data.f 0.5,0.5
Data.f #SQRT03,-#SQRT03,#SQRT03
Data.f #SQRT03,-#SQRT03,#SQRT03
Data.f 1,1
Data.f #SQRT03,-#SQRT03,-#SQRT03
Data.f #SQRT03,-#SQRT03,-#SQRT03
Data.f 0,1
Data.f 1,0,0
Data.f 1,0,0
Data.f 0.5,0.5
Data.f #SQRT03,-#SQRT03,-#SQRT03
Data.f #SQRT03,-#SQRT03,-#SQRT03
Data.f 0,1
Data.f #SQRT03,#SQRT03,-#SQRT03
Data.f #SQRT03,#SQRT03,-#SQRT03
Data.f 0,0
Data.f -1,0,0
Data.f -1,0,0
Data.f 0.5,0.5
Data.f -#SQRT03,#SQRT03,#SQRT03
Data.f -#SQRT03,#SQRT03,#SQRT03
Data.f 0,0
Data.f -#SQRT03,#SQRT03,-#SQRT03
Data.f -#SQRT03,#SQRT03,-#SQRT03
Data.f 1,0
Data.f -1,0,0
Data.f -1,0,0
Data.f 0.5,0.5
Data.f -#SQRT03,-#SQRT03,#SQRT03
Data.f -#SQRT03,-#SQRT03,#SQRT03
Data.f 1,0
Data.f -#SQRT03,#SQRT03,#SQRT03
Data.f -#SQRT03,#SQRT03,#SQRT03
Data.f 1,1
Data.f -1,0,0
Data.f -1,0,0
Data.f 0.5,0.5
Data.f -#SQRT03,-#SQRT03,-#SQRT03
Data.f -#SQRT03,-#SQRT03,-#SQRT03
Data.f 1,1
Data.f -#SQRT03,-#SQRT03,#SQRT03
Data.f -#SQRT03,-#SQRT03,#SQRT03
Data.f 0,1
Data.f -1,0,0
Data.f -1,0,0
Data.f 0.5,0.5
Data.f -#SQRT03,#SQRT03,-#SQRT03
Data.f -#SQRT03,#SQRT03,-#SQRT03
Data.f 0,1
Data.f -#SQRT03,-#SQRT03,-#SQRT03
Data.f -#SQRT03,-#SQRT03,-#SQRT03
Data.f 0,0
Data.f 0,0,-1
Data.f 0,0,-1
Data.f 0.5,0.5
Data.f -#SQRT03,#SQRT03,-#SQRT03
Data.f -#SQRT03,#SQRT03,-#SQRT03
Data.f 0,0
Data.f #SQRT03,#SQRT03,-#SQRT03
Data.f #SQRT03,#SQRT03,-#SQRT03
Data.f 1,0
Data.f 0,0,-1
Data.f 0,0,-1
Data.f 0.5,0.5
Data.f #SQRT03,#SQRT03,-#SQRT03
Data.f #SQRT03,#SQRT03,-#SQRT03
Data.f 1,0
Data.f #SQRT03,-#SQRT03,-#SQRT03
Data.f #SQRT03,-#SQRT03,-#SQRT03
Data.f 1,1
Data.f 0,0,-1
Data.f 0,0,-1
Data.f 0.5,0.5
Data.f #SQRT03,-#SQRT03,-#SQRT03
Data.f #SQRT03,-#SQRT03,-#SQRT03
Data.f 1,1
Data.f -#SQRT03,-#SQRT03,-#SQRT03
Data.f -#SQRT03,-#SQRT03,-#SQRT03
Data.f 0,1
Data.f 0,0,-1
Data.f 0,0,-1
Data.f 0.5,0.5
Data.f -#SQRT03,-#SQRT03,-#SQRT03
Data.f -#SQRT03,-#SQRT03,-#SQRT03
Data.f 0,1
Data.f -#SQRT03,#SQRT03,-#SQRT03
Data.f -#SQRT03,#SQRT03,-#SQRT03
Data.f 0,0
Data.f 0,0,1
Data.f 0,0,1
Data.f 0.5,0.5
Data.f #SQRT03,#SQRT03,#SQRT03
Data.f #SQRT03,#SQRT03,#SQRT03
Data.f 0,0
Data.f -#SQRT03,#SQRT03,#SQRT03
Data.f -#SQRT03,#SQRT03,#SQRT03
Data.f 1,0
Data.f 0,0,1
Data.f 0,0,1
Data.f 0.5,0.5
Data.f #SQRT03,-#SQRT03,#SQRT03
Data.f #SQRT03,-#SQRT03,#SQRT03
Data.f 1,0
Data.f #SQRT03,#SQRT03,#SQRT03
Data.f #SQRT03,#SQRT03,#SQRT03
Data.f 1,1
Data.f 0,0,1
Data.f 0,0,1
Data.f 0.5,0.5
Data.f -#SQRT03,-#SQRT03,#SQRT03
Data.f -#SQRT03,-#SQRT03,#SQRT03
Data.f 1,1
Data.f #SQRT03,-#SQRT03,#SQRT03
Data.f #SQRT03,-#SQRT03,#SQRT03
Data.f 0,1
Data.f 0,0,1
Data.f 0,0,1
Data.f 0.5,0.5
Data.f -#SQRT03,#SQRT03,#SQRT03
Data.f -#SQRT03,#SQRT03,#SQRT03
Data.f 0,1
Data.f -#SQRT03,-#SQRT03,#SQRT03
Data.f -#SQRT03,-#SQRT03,#SQRT03
Data.f 0,0

; Faces
Data.w 0,1,2
Data.w 3,4,5
Data.w 6,7,8
Data.w 9,10,11
Data.w 12,13,14
Data.w 15,16,17
Data.w 18,19,20
Data.w 21,22,23
Data.w 24,25,26
Data.w 27,28,29
Data.w 30,31,32
Data.w 33,34,35
Data.w 36,37,38
Data.w 39,40,41
Data.w 42,43,44
Data.w 45,46,47
Data.w 48,49,50
Data.w 51,52,53
Data.w 54,55,56
Data.w 57,58,59
Data.w 60,61,62
Data.w 63,64,65
Data.w 66,67,68
Data.w 69,70,71


EndDataSection
Merci d'avance.

Publié : ven. 13/juin/2008 11:07
par Anonyme
Je dirais que c'est parfait , faut un nombre important de faces pour avoir un éclairage correct.

Publié : ven. 13/juin/2008 11:38
par Ollivier
Je me permets 1 critique : les datas, pourras-tu y remédier ? Je ne connais pas l'algo, notamment si on peut partir d'une forme initiale moins dure à calculer sans data (ex : le cube).

J'avais eu cette idée de «gonfler une forme» un peu comme un ballon gonflable. Mais j'avais vite abandonné cette possibilité à cause de mon manque de savoir en Maths.

Alors bravo pour ce code qui fait preuve d'un bon labeur !

Publié : ven. 13/juin/2008 15:52
par Ollivier
Pour le «dentelage», tu as une ligne

Code : Tout sélectionner

CreateMaterial(0, etc...
Juste après, tu peux rajouter

Code : Tout sélectionner

MaterialShadingMode(0, #Pb_Material_Phong)
Je vais voir si je peux enlever les datas...

Publié : sam. 14/juin/2008 17:44
par kelebrindae
@Ollivier:
Merci pour le truc du "Phong", je n'y avais pas pensé... :D

Pour les datas, ça ne devrait pas être trop dur à virer.
Déjà, puisque la procédure de lissage des normales a l'air de fonctionner, tu peux virer les datas correspondant aux normales du mesh.

Pour ce qui est de la position des vertices: Tu as sans doute remarqué qu'il y a deux séries de datas: la première pour l'octahedron, et la seconde pour un objet que j'ai appelé un "pointy cube".
=> Ces deux objets répondent aux mêmes contraintes: tous les vertices sont à une distance 1 du centre du mesh, et les jointures entre les faces ont toujours la même configuration; ces contraintes garantissent que la subdivision des triangles conduit à des polygones de taille équivalente et répartis régulièrement sur le mesh.

L'octahedron devrait être facile à reproduire: un vertex à (1,0,0), un autre à (0,0,1), un autre à (-1,0,0) un autre à (0,0,-1), une pointe à (0,1,0) et l'autre à (0,-1,0).

Le "pointy cube" est une sorte de mélange entre un cube classique et un octahedron: il s'agit d'un cube doté de 4 triangles par faces; un peu comme 6 pyramides assemblées. Il devrait être possible de la calculer aussi.

Ceci dit, je trouve que ton répugnance à utiliser des Datas tient de la préoccupation de puriste: oui, ce n'est pas très beau de stocker des infos en dur dans le code; mais en même temps, si ça peut éviter de se casser la tête pendant des heures pour le même résultat, c'est que du bonheur. C'est comme si tu programmais un jeu en voulant tout générer: textures, meshes, animations, sons, ou même polices de caractères; ce n'est guère possible, et à un moment ou à un autre, tu seras bien obligé de charger quelque chose de pré-calculé. Et puis même en terme de perfs, je ne suis pas sûr que lire des datas soit plus pénalisant que de tout calculer...

Qu'en penses-tu ?

Publié : mer. 18/juin/2008 9:20
par Ollivier
Je pense que tu as raison : c'est toi qui connait ton code et la fin que tu souhaites y voir !

Seulement parfois, des prises de tête peuvent servir... A toi de voir. Point de vue perf, que les Read soient lents ou rapides, ça n'est pas trop un souci, puisque tu stockes une fois pour toute tes données.

Par contre, de visu, je préfère personnellement une routine cloisonnée sous procédure plutôt qu'une procédure + une liste de Datas. Est-ce une préoccupation de puriste? A contrario à une préoccupation d'efficacité à court terme, et comme exigée par le marché, là aussi tu as raison. L'essentiel est le rapport qualité de création sur la durée de création. Or, ce n'est pas forcément ma préoccupation.

Ollivier

Publié : jeu. 19/juin/2008 9:14
par kelebrindae
Ce n'était surtout pas une critique => ta démarche est la bonne quand on cherche à réellement comprendre ce que fait un programme et pourquoi il le fait; Se contenter de datas pour générer des formes géométriques régulières est une solution de facilité.

Et en effet, j'ai plutôt en tête une logique de productivité: d'abord parce que je n'ai guère de temps libre (et beaucoup d'enfants; les deux quantités sont inversement proportionnelles), et puis parce que le bout de code ci-dessus n'est qu'une étape de mon projet super-ultra-hyper-secret.

Je posterai l'étape suivante dans les jours qui viennent, si tout va bien...

Publié : jeu. 19/juin/2008 14:21
par Ollivier
:D

Tout le monde a son petit jardin secret !

Ollivier