Page 1 sur 2

Premiers pas en 3D

Publié : dim. 06/avr./2008 23:13
par Octavius
Bonjour!

Je me suis mis à apprendre la 3D sous Purebasic, et là mon défi c'est d'essayer de fabriquer un joli rubik's cube. Or j'ai presque réussi, mais l'une des faces (les faces vertes) ne s'affiche pas correctement et je n'arrive pas à comprendre pourquoi.

Mon rubik's cube est composé de 27 cubes, je les construit grâce à des datas et ensuite je les assemble.

Voici mon code (déplacez la souris pour voir les faces du rubik's cube, cliquez-gauche pour changer la caméra de côté, j'ai pas eu le temps d'élaborer une navigation plus aboutie pour l'instant) :

Code : Tout sélectionner

;Virtual Cube

;***************
;-Initialisation
;***************
;{
InitEngine3D()
InitSprite()
InitKeyboard()
InitMouse()

;Constantes
#Texture=0
#Matiere=0
#Camera=0
#Lumiere=0
#Cube=27

#Jaune=65535
#Rouge=255
#Vert=32768
#Bleu=16711680
#Orange=33023
#Blanc=16777215

;Structure d'un sommet, position, normale, couleur, coordonnées u/v
Structure som
  px.f
  py.f
  pz.f
  nx.f
  ny.f
  nz.f
  col.l
  u.f
  v.f
EndStructure

;Les trois points qui forment un triangle
Structure tri
  p1.w
  p2.w
  p3.w
EndStructure

;Structure du cube
Structure mesh
  *Sommet.som
  *Triangle.tri
EndStructure

;Positions du cube et couleurs de ses faces
Structure cube
  x.b
  y.b
  z.b
  above.l
  below.l
  back.l
  front.l
  right.l
  left.l
EndStructure

Cube.mesh
Cube\Sommet=AllocateMemory(SizeOf(som)*24)  ;24 sommets par cube
Cube\Triangle=AllocateMemory(SizeOf(tri)*12)  ;12 triangles par cube
Dim Coord.cube(27)  ;27 positions différentes pour les 27 cubes
CopyMemory(?Sommets,Cube\Sommet,SizeOf(som)*24)
CopyMemory(?Triangles,Cube\Triangle,SizeOf(tri)*12)
CopyMemory(?Coordonnees,@Coord(),SizeOf(cube)*27)
;}

Procedure.l ReverseRGB(col.l)
  ProcedureReturn RGB(Blue(col),Green(col),Red(col))
EndProcedure

;Ouverture d'un écran ayant les dimensions du bureau
ExamineDesktops()
OpenScreen(DesktopWidth(0),DesktopHeight(0),DesktopDepth(0),"Virtual Cube")

;Création de la texture blanche
CreateTexture(#Texture,64,64)
StartDrawing(TextureOutput(#Texture))
  Box(0,0,64,64,0)
  Box(2,2,60,60,#Blanc)
StopDrawing()

;Création de la matière
CreateMaterial(#Matiere,TextureID(#Texture))
MaterialAmbientColor(#Matiere,#PB_Material_AmbientColors)

;Création des 27 cubes numérotés de 0 à 26
For i=0 To #Cube-1
  ;Création d'un mesh avec 100 vertex maximum pour chaque cube
  CreateMesh(i,100)
  ;Couleurs du cube
  *Adresse.som=Cube\Sommet
  *Coord.cube=@Coord()+i*SizeOf(cube)
  For j=0 To 5 ;nombre de faces
    For k=0 To 3 ;nombre de sommets par face
      *Adresse\col=ReverseRGB(*Coord\above)
      *Adresse+SizeOf(som)
    Next k
    *Coord+4
  Next j
  ;Définition des 24 sommets dans le mesh
  SetMeshData(i,#PB_Mesh_Vertex|#PB_Mesh_Normal|#PB_Mesh_Color|#PB_Mesh_UVCoordinate,Cube\Sommet,24)
  ;Définition des triangles
  SetMeshData(i,#PB_Mesh_Face,Cube\Triangle,12)
  ;Création de l'entité, l'objet qui sera affiché !
  CreateEntity(i,MeshID(i),MaterialID(#Matiere),Coord(i)\x,Coord(i)\y,Coord(i)\z)
Next i

;Libération de la mémoire inutile
FreeMemory(Cube\Sommet)
FreeMemory(Cube\Triangle)

;Création de la caméra, pour voir l'objet !
CreateCamera(#Camera,0,0,100,100)
CameraBackColor(#Camera,#Blanc)

;Lumière ambiante
AmbientColor(RGB(255,255,255))

;******************
;-Boucle principale
;******************
x.f
y.f
z.f=30
a.f
b.f

Repeat
  ;On fait table-rase
  ClearScreen(0)
;   RotateEntity(0,x,y,z)
  ;Placer la caméra au bon endroit !
  CameraLocate(#Camera,x,y,z)
  CameraLookAt(#Camera,EntityX(13),EntityY(13),EntityZ(13))
  ;Affichage du monde 3D
  RenderWorld()
  ;Inverser les tampons
  FlipBuffers()
  ;Examen de la souris
  ExamineMouse()
  a=MouseDeltaX()/100
  b=MouseDeltaY()/100
  x=30*Cos(ACos(x/30)+a)
  y=30*Cos(ACos(y/30)+b)
  If MouseButton(#PB_MouseButton_Left)
    z=-z
    Delay(200)
  EndIf
  ;Examen du clavier
  ExamineKeyboard()
Until KeyboardPushed(#PB_Key_Escape)

;********
;-Données
;********
;{
DataSection

Sommets:

;Dessus 0 à 3
Data.f -1,1,-1 : Data.f 0,1,0 : Data.l 0 : Data.f 0,1
Data.f 1,1,-1 : Data.f 0,1,0 : Data.l 0 : Data.f 1,1
Data.f 1,1,1 : Data.f 0,1,0 : Data.l 0 : Data.f 1,0
Data.f -1,1,1 : Data.f 0,1,0 : Data.l 0 : Data.f 0,0

;Dessous 4 à 7
Data.f -1,-1,-1 : Data.f 0,-1,0 : Data.l 0 : Data.f 0,1
Data.f 1,-1,-1 : Data.f 0,-1,0 : Data.l 0 : Data.f 1,1
Data.f 1,-1,1 : Data.f 0,-1,0 : Data.l 0 : Data.f 1,0
Data.f -1,-1,1 : Data.f 0,-1,0 : Data.l 0 : Data.f 0,0

;Derriere 8 à 11
Data.f -1,-1,-1 : Data.f 0,0,-1 : Data.l 0 : Data.f 0,1
Data.f 1,-1,-1 : Data.f 0,0,-1 : Data.l 0 : Data.f 1,1
Data.f 1,1,-1 : Data.f 0,0,-1 : Data.l 0 : Data.f 1,0
Data.f -1,1,-1 : Data.f 0,0,-1 : Data.l 0 : Data.f 0,0

;Devant 12 à 15
Data.f -1,-1,1 : Data.f 0,0,1 : Data.l 0 : Data.f 0,1
Data.f 1,-1,1 : Data.f 0,0,1 : Data.l 0 : Data.f 1,1
Data.f 1,1,1 : Data.f 0,0,1 : Data.l 0 : Data.f 1,0
Data.f -1,1,1 : Data.f 0,0,1 : Data.l 0 : Data.f 0,0

;Droite 16 à 19
Data.f 1,-1,-1 : Data.f 1,0,0 : Data.l 0 : Data.f 0,1
Data.f 1,-1,1 : Data.f 1,0,0 : Data.l 0 : Data.f 1,1
Data.f 1,1,1 : Data.f 1,0,0 : Data.l 0 : Data.f 1,0
Data.f 1,1,-1 : Data.f 1,0,0 : Data.l 0 : Data.f 0,0

;Gauche 20 à 23
Data.f -1,-1,-1 : Data.f -1,0,0 : Data.l 0 : Data.f 0,1
Data.f -1,-1,1 : Data.f -1,0,0 : Data.l 0 : Data.f 1,1
Data.f -1,1,1 : Data.f -1,0,0 : Data.l 0 : Data.f 1,0
Data.f -1,1,-1 : Data.f -1,0,0 : Data.l 0 : Data.f 0,0

Triangles:

;Dessus
Data.w 3,1,0
Data.w 3,2,1

;Dessous
Data.w 4,5,7
Data.w 5,6,7

;Devant
Data.w 11,5,4
Data.w 11,10,5

;Derrière
Data.w 12,13,14
Data.w 12,14,15

;Gauche
Data.w 18,17,16
Data.w 19,18,16

;Droite
Data.w 20,21,22
Data.w 20,22,23

Coordonnees:

Data.b -2,2,2
Data.l #Jaune,0,0,#Bleu,0,#Orange
Data.b 0,2,2
Data.l #Jaune,0,0,#Bleu,0,0
Data.b 2,2,2
Data.l #Jaune,0,0,#Bleu,#Rouge,0
Data.b -2,2,0
Data.l #Jaune,0,0,0,0,#Orange
Data.b 0,2,0
Data.l #Jaune,0,0,0,0,0
Data.b 2,2,0
Data.l #Jaune,0,0,0,#Rouge,0
Data.b -2,2,-2
Data.l #Jaune,0,#Vert,0,0,#Orange
Data.b 0,2,-2
Data.l #Jaune,0,#Vert,0,0,0
Data.b 2,2,-2
Data.l #Jaune,0,#Vert,0,#Rouge,0
Data.b -2,0,2
Data.l 0,0,0,#Bleu,0,#Orange
Data.b 0,0,2
Data.l 0,0,0,#Bleu,0,0
Data.b 2,0,2
Data.l 0,0,0,#Bleu,#Rouge,0
Data.b -2,0,0
Data.l 0,0,0,0,0,#Orange
Data.b 0,0,0
Data.l 0,0,0,0,0,0
Data.b 2,0,0
Data.l 0,0,0,0,#Rouge,0
Data.b -2,0,-2
Data.l 0,0,#Vert,0,0,#Orange
Data.b 0,0,-2
Data.l 0,0,#Vert,0,0,0
Data.b 2,0,-2
Data.l 0,0,#Vert,0,#Rouge,0
Data.b -2,-2,2
Data.l 0,#Blanc,0,#Bleu,0,#Orange
Data.b 0,-2,2
Data.l 0,#Blanc,0,#Bleu,0,0
Data.b 2,-2,2
Data.l 0,#Blanc,0,#Bleu,#Rouge,0
Data.b -2,-2,0
Data.l 0,#Blanc,0,0,0,#Orange
Data.b 0,-2,0
Data.l 0,#Blanc,0,0,0,0
Data.b 2,-2,0
Data.l 0,#Blanc,0,0,#Rouge,0
Data.b -2,-2,-2
Data.l 0,#Blanc,#Vert,0,0,#Orange
Data.b 0,-2,-2
Data.l 0,#Blanc,#Vert,0,0,0
Data.b 2,-2,-2
Data.l 0,#Blanc,#Vert,0,#Rouge,0

EndDataSection

;}

Publié : dim. 06/avr./2008 23:34
par Ar-S
En PB 4.10 sous xp pro

J'ai un beau message d'erreur en le lançant. (j'utilise JaPBe)

Image

Si je lance le débugger, ça fonctionne.

Bizarre 8O

Publié : dim. 06/avr./2008 23:40
par SPH
Chez moi ca fonctionne nikel (sous pb4.10/XP pro)

Publié : dim. 06/avr./2008 23:46
par Octavius
Bizarre... Je précise j'ai PB 4.10 XP familial

SPH, les faces vertes n'apparaissent pas bizarrement t'es sûr ?

Ar-S, tu croies que mon problème vient du debuggeur ?

Vous voyez rien d'anormal dans le code ?

Publié : lun. 07/avr./2008 0:08
par SPH
Octavius a écrit :Bizarre... Je précise j'ai PB 4.10 XP familial

SPH, les faces vertes n'apparaissent pas bizarrement t'es sûr ?

Ar-S, tu croies que mon problème vient du debuggeur ?

Vous voyez rien d'anormal dans le code ?
Les faces vertes ne sont pas comme les autres. Le vert apparait en un joli dégradé et je croyais que tu l'avais fais exprès !!

Publié : lun. 07/avr./2008 0:19
par Octavius
Non justement je l'ai pas fait exprès! Et j'aimerai bien comprendre d'où ça vient... J'y ai passé toute ma journée et je trouve pas l'erreur... :cry:

Publié : mar. 08/avr./2008 13:52
par Octavius
J'ai trouvé!!! L'un de mes triangles n'était pas formé par les bons sommets... Quelle erreur bête!

J'ai mis à jour mon code, navigation de la caméra intuitive avec la souris, utilisation de la roulette pour zoomer/dézoomer, F1/F2 pour changer de mode de caméra (fil de fer/texturé), F3 pour laisser le cube tourner tout seul :

Code : Tout sélectionner

;Virtual Cube

;***************
;-Initialisation
;***************
;{
If InitEngine3D()=0 Or InitSprite()=0 Or InitKeyboard()=0 Or InitMouse()=0
  MessageRequester("Erreur !","Impossible d'initialiser le programme !")
  End
EndIf

;Constantes
#Texture=0
#Matiere=0
#Camera=0
#Lumiere=0
#Cube=27

#Jaune=65535
#Rouge=255
#Vert=32768
#Bleu=16711680
#Orange=33023
#Blanc=16777215

;Structure d'un sommet, position, normale, couleur, coordonnées u/v
Structure som
  px.f
  py.f
  pz.f
  nx.f
  ny.f
  nz.f
  col.l
  u.f
  v.f
EndStructure

;Les trois points qui forment un triangle
Structure tri
  p1.w
  p2.w
  p3.w
EndStructure

;Structure du cube
Structure mesh
  *Sommet.som
  *Triangle.tri
EndStructure

;Positions du cube et couleurs de ses faces
Structure cube
  x.b
  y.b
  z.b
  above.l
  below.l
  back.l
  front.l
  right.l
  left.l
EndStructure

Cube.mesh
Cube\Sommet=AllocateMemory(SizeOf(som)*24)  ;24 sommets par cube
Cube\Triangle=AllocateMemory(SizeOf(tri)*12)  ;12 triangles par cube
Dim Coord.cube(27)  ;27 positions différentes pour les 27 cubes
CopyMemory(?Sommets,Cube\Sommet,SizeOf(som)*24)
CopyMemory(?Triangles,Cube\Triangle,SizeOf(tri)*12)
CopyMemory(?Coordonnees,@Coord(),SizeOf(cube)*27)

;Variables globales
Global R.f,Rh.f,a.f,b.f,x.f,y.f,z.f,rot.b ;Gestion de la caméra
R=30
a=#PI/2

;Matrice gérant la position des cubes
Dim Matrix.b(27)
For i=0 To 26
  Matrix(i)=i+1
Next i
;}

Procedure.l ReverseRGB(col.l)
  ProcedureReturn RGB(Blue(col),Green(col),Red(col))
EndProcedure

Procedure.b GestionCamera(deltax.f,deltay.f)
  ;Calcul des coordonnées
  a=a+deltax
  b=b+deltay
  y=R*Sin(b)
  Rh=R*Cos(b)
  x=Rh*Cos(a)
  z=Rh*Sin(a)
  ;Placer la caméra au bon endroit !
  CameraLocate(#Camera,x,y,z)
  RotateCamera(#Camera,-deltax*180/#PI,-deltay*180/#PI,0)
  ProcedureReturn 1
EndProcedure

Procedure.b GestionClavier()
  If KeyboardPushed(#PB_Key_Escape)
    End
  EndIf
  If KeyboardReleased(#PB_Key_F1)
    CameraRenderMode(#Camera,#PB_Camera_Wireframe)
  EndIf
  If KeyboardReleased(#PB_Key_F2)
    CameraRenderMode(#Camera,#PB_Camera_Textured)
  EndIf
  If KeyboardReleased(#PB_Key_F3)
    rot=1-rot
  EndIf
EndProcedure

Procedure.f DistanceCamera(wheel.f)
  Protected result.f
  result=R-wheel
  If result<10 : ProcedureReturn 10
  ElseIf result>100 : ProcedureReturn 100
  Else : ProcedureReturn result : EndIf
EndProcedure

;Ouverture d'un écran ayant les dimensions du bureau
ExamineDesktops()
OpenScreen(DesktopWidth(0),DesktopHeight(0),DesktopDepth(0),"Virtual Cube")

;Création de la texture blanche
CreateTexture(#Texture,64,64)
StartDrawing(TextureOutput(#Texture))
  Box(0,0,64,64,0)
  Box(2,2,60,60,#Blanc)
StopDrawing()

;Création de la matière
CreateMaterial(#Matiere,TextureID(#Texture))
MaterialAmbientColor(#Matiere,#PB_Material_AmbientColors)

;Création des 27 cubes numérotés de 0 à 26
For i=0 To #Cube-1
  ;Création d'un mesh avec 100 vertex maximum pour chaque cube
  CreateMesh(i,200)
  ;Couleurs du cube
  *Adresse.som=Cube\Sommet
  *Coord.cube=@Coord()+i*SizeOf(cube)
  For j=0 To 5 ;nombre de faces
    For k=0 To 3 ;nombre de sommets par face
      *Adresse\col=ReverseRGB(*Coord\above)
      *Adresse+SizeOf(som)
    Next k
    *Coord+4
  Next j
  ;Définition des 24 sommets dans le mesh
  SetMeshData(i,#PB_Mesh_Vertex|#PB_Mesh_Normal|#PB_Mesh_Color|#PB_Mesh_UVCoordinate,Cube\Sommet,24)
  ;Définition des triangles
  SetMeshData(i,#PB_Mesh_Face,Cube\Triangle,12)
  ;Création de l'entité, l'objet qui sera affiché !
  CreateEntity(i,MeshID(i),MaterialID(#Matiere),Coord(i)\x,Coord(i)\y,Coord(i)\z)
Next i

;Libération de la mémoire inutile
FreeMemory(Cube\Sommet)
FreeMemory(Cube\Triangle)

;Création de la caméra, pour voir l'objet !
CreateCamera(#Camera,0,0,100,100)
CameraBackColor(#Camera,#Blanc)

;Lumière ambiante
AmbientColor(#Blanc)

;Création de la caméra, pour voir l'objet !
CreateCamera(#Camera,0,0,100,100)
CameraBackColor(#Camera,#Blanc)
CameraLocate(#Camera,0,0,30)
CameraLookAt(#Camera,0,0,0)

;******************
;-Boucle principale
;******************

Repeat
  ;On fait table-rase
  ClearScreen(0)
  ;Examen du clavier
  ExamineKeyboard()
  GestionClavier()
  ;Examen de la souris
  ExamineMouse()
  ;Déplacement et rotation de la caméra autour du cube
  If rot=0 : GestionCamera(MouseDeltaX()/300,MouseDeltaY()/300)
  Else : GestionCamera(0.02,0.01) : EndIf
  ;Distance de la caméra au cube
  R=DistanceCamera(MouseWheel())
  ;Affichage du monde 3D
  RenderWorld()
  ;Dessins
  StartDrawing(ScreenOutput())
    DrawText(10,10,"x="+StrF(x))
    DrawText(10,30,"y="+StrF(y))
    DrawText(10,50,"z="+StrF(z))
    DrawText(10,70,"a="+StrF(a/#PI*180)+"°")
    DrawText(10,90,"b="+StrF(b/#PI*180)+"°")
  StopDrawing()
  ;Inverser les tampons
  FlipBuffers()
ForEver

;********
;-Données
;********
;{
DataSection

Sommets:

;Dessus 0 à 3
Data.f -1,1,-1 : Data.f 0,1,0 : Data.l 0 : Data.f 0,1
Data.f 1,1,-1 : Data.f 0,1,0 : Data.l 0 : Data.f 1,1
Data.f 1,1,1 : Data.f 0,1,0 : Data.l 0 : Data.f 1,0
Data.f -1,1,1 : Data.f 0,1,0 : Data.l 0 : Data.f 0,0

;Dessous 4 à 7
Data.f -1,-1,-1 : Data.f 0,-1,0 : Data.l 0 : Data.f 0,1
Data.f 1,-1,-1 : Data.f 0,-1,0 : Data.l 0 : Data.f 1,1
Data.f 1,-1,1 : Data.f 0,-1,0 : Data.l 0 : Data.f 1,0
Data.f -1,-1,1 : Data.f 0,-1,0 : Data.l 0 : Data.f 0,0

;Derriere 8 à 11
Data.f -1,-1,-1 : Data.f 0,0,-1 : Data.l 0 : Data.f 0,1
Data.f 1,-1,-1 : Data.f 0,0,-1 : Data.l 0 : Data.f 1,1
Data.f 1,1,-1 : Data.f 0,0,-1 : Data.l 0 : Data.f 1,0
Data.f -1,1,-1 : Data.f 0,0,-1 : Data.l 0 : Data.f 0,0

;Devant 12 à 15
Data.f -1,-1,1 : Data.f 0,0,1 : Data.l 0 : Data.f 0,1
Data.f 1,-1,1 : Data.f 0,0,1 : Data.l 0 : Data.f 1,1
Data.f 1,1,1 : Data.f 0,0,1 : Data.l 0 : Data.f 1,0
Data.f -1,1,1 : Data.f 0,0,1 : Data.l 0 : Data.f 0,0

;Droite 16 à 19
Data.f 1,-1,-1 : Data.f 1,0,0 : Data.l 0 : Data.f 0,1
Data.f 1,-1,1 : Data.f 1,0,0 : Data.l 0 : Data.f 1,1
Data.f 1,1,1 : Data.f 1,0,0 : Data.l 0 : Data.f 1,0
Data.f 1,1,-1 : Data.f 1,0,0 : Data.l 0 : Data.f 0,0

;Gauche 20 à 23
Data.f -1,-1,-1 : Data.f -1,0,0 : Data.l 0 : Data.f 0,1
Data.f -1,-1,1 : Data.f -1,0,0 : Data.l 0 : Data.f 1,1
Data.f -1,1,1 : Data.f -1,0,0 : Data.l 0 : Data.f 1,0
Data.f -1,1,-1 : Data.f -1,0,0 : Data.l 0 : Data.f 0,0

Triangles:

;Dessus
Data.w 3,1,0
Data.w 3,2,1

;Dessous
Data.w 4,5,6
Data.w 4,6,7

;Derrière
Data.w 11,9,8
Data.w 11,10,9

;Devant
Data.w 12,13,14
Data.w 12,14,15

;Gauche
Data.w 19,17,16
Data.w 19,18,17

;Droite
Data.w 20,21,22
Data.w 20,22,23

Coordonnees:

;Rangées du haut
Data.b -2,2,2
Data.l #Jaune,0,0,#Bleu,0,#Orange
Data.b 0,2,2
Data.l #Jaune,0,0,#Bleu,0,0
Data.b 2,2,2
Data.l #Jaune,0,0,#Bleu,#Rouge,0
Data.b -2,2,0
Data.l #Jaune,0,0,0,0,#Orange
Data.b 0,2,0
Data.l #Jaune,0,0,0,0,0
Data.b 2,2,0
Data.l #Jaune,0,0,0,#Rouge,0
Data.b -2,2,-2
Data.l #Jaune,0,#Vert,0,0,#Orange
Data.b 0,2,-2
Data.l #Jaune,0,#Vert,0,0,0
Data.b 2,2,-2
Data.l #Jaune,0,#Vert,0,#Rouge,0

;Rangées du milieu
Data.b -2,0,2
Data.l 0,0,0,#Bleu,0,#Orange
Data.b 0,0,2
Data.l 0,0,0,#Bleu,0,0
Data.b 2,0,2
Data.l 0,0,0,#Bleu,#Rouge,0
Data.b -2,0,0
Data.l 0,0,0,0,0,#Orange
Data.b 0,0,0
Data.l 0,0,0,0,0,0
Data.b 2,0,0
Data.l 0,0,0,0,#Rouge,0
Data.b -2,0,-2
Data.l 0,0,#Vert,0,0,#Orange
Data.b 0,0,-2
Data.l 0,0,#Vert,0,0,0
Data.b 2,0,-2
Data.l 0,0,#Vert,0,#Rouge,0

;Rangées du bas
Data.b -2,-2,2
Data.l 0,#Blanc,0,#Bleu,0,#Orange
Data.b 0,-2,2
Data.l 0,#Blanc,0,#Bleu,0,0
Data.b 2,-2,2
Data.l 0,#Blanc,0,#Bleu,#Rouge,0
Data.b -2,-2,0
Data.l 0,#Blanc,0,0,0,#Orange
Data.b 0,-2,0
Data.l 0,#Blanc,0,0,0,0
Data.b 2,-2,0
Data.l 0,#Blanc,0,0,#Rouge,0
Data.b -2,-2,-2
Data.l 0,#Blanc,#Vert,0,0,#Orange
Data.b 0,-2,-2
Data.l 0,#Blanc,#Vert,0,0,0
Data.b 2,-2,-2
Data.l 0,#Blanc,#Vert,0,#Rouge,0

EndDataSection

;}

Publié : mar. 08/avr./2008 17:55
par comtois
Beau boulot , j'attends la suite avec impatience :)

Publié : mar. 08/avr./2008 20:39
par Octavius
La suite ça sera la manipulation du cube! :wink:

Publié : sam. 12/avr./2008 3:15
par Octavius
Du progrès! Maintenant on peut faire tourner la rangée supérieure! Touches F1/F2 pour les modes fil de fer ou texturé, F3 pour que la caméra tourne toute seule autour du cube, les flèches directionnelles pour contrôler les mouvements de la caméra autour du cube, clique-gauche de la souris pour effectuer le mouvement de 90° de la rangée supérieure, le curseur peut se déplacer aussi mais pour l'instant c'est juste pour faire joli. 8)

J'espère progresser encore rapidement et adapter mon code à tous les mouvements possibles. Mais un problème se pose à moi, je voudrais pouvoir reconnaître au-dessus de quel cube se trouve le curseur et je ne trouve pas de commande purebasic pour ça... Une idée ?

Code : Tout sélectionner

;Virtual Cube

;***************
;-Initialisation
;***************
;{
If InitEngine3D()=0 Or InitSprite()=0 Or InitKeyboard()=0 Or InitMouse()=0
  MessageRequester("Erreur !","Impossible d'initialiser le programme !")
  End
EndIf

;Décodeur PNG
UsePNGImageDecoder()

;Identifiants
#Texture=0
#Matiere=0
#Camera=0
#Lumiere=0
#Cube=27
#Souris=0

;Couleurs
#Jaune=65535
#Rouge=255
#Vert=32768
#Bleu=16711680
#Orange=33023
#Blanc=16777215

;Paramètres
#IncMax=20
#Pas=#PI/(#IncMax*2)

;Structure d'un sommet, position, normale, couleur, coordonnées u/v
Structure som
  px.f
  py.f
  pz.f
  nx.f
  ny.f
  nz.f
  col.l
  u.f
  v.f
EndStructure

;Les trois points qui forment un triangle
Structure tri
  p1.w
  p2.w
  p3.w
EndStructure

;Structure du cube
Structure mesh
  *Sommet.som
  *Triangle.tri
EndStructure

;Positions du cube et couleurs de ses faces
Structure cube
  x.b
  y.b
  z.b
  above.l
  below.l
  back.l
  front.l
  right.l
  left.l
EndStructure

;Retenir des informations sur les cubes
Structure matrix
  no.b
  rotx.b
  roty.b
  rotz.b
EndStructure

Souris.POINT
Cube.mesh
Cube\Sommet=AllocateMemory(SizeOf(som)*24)  ;24 sommets par cube
Cube\Triangle=AllocateMemory(SizeOf(tri)*12)  ;12 triangles par cube
Dim Coord.cube(27)  ;27 positions différentes pour les 27 cubes
CopyMemory(?Sommets,Cube\Sommet,SizeOf(som)*24)
CopyMemory(?Triangles,Cube\Triangle,SizeOf(tri)*12)
CopyMemory(?Coordonnees,@Coord(),SizeOf(cube)*27)

;Variables globales
Global R.f,Rh.f,a.f,b.f,x.f,y.f,z.f,rot.b,DeltaX.f,DeltaY.f,GammaX.f,GammaY.f,t.f,inc.b,stop.b ;Gestion de la caméra
R=30
a=#PI/2
stop=1
inc=0

;Matrice gérant la position des cubes
Global Dim Matrix.matrix(27)
For i=0 To 26
  Matrix(i)\no=i+1
  Matrix(i)\rotx=0
  Matrix(i)\roty=0
  Matrix(i)\rotz=0
Next i
;}

Procedure.f R2D(angle.f)
  ProcedureReturn angle*180/#PI
EndProcedure

Procedure.f D2R(angle.f)
  ProcedureReturn angle*#PI/180
EndProcedure

Procedure.l ReverseRGB(col.l)
  ProcedureReturn RGB(Blue(col),Green(col),Red(col))
EndProcedure

Procedure.b GestionCamera(deltax.f,deltay.f)
  ;Calcul des coordonnées
  a=a+deltax
  b=b+deltay
  y=R*Sin(b)
  Rh=R*Cos(b)
  x=Rh*Cos(a)
  z=Rh*Sin(a)
  ;Placer la caméra au bon endroit !
  CameraLocate(#Camera,x,y,z)
  RotateCamera(#Camera,-deltax*180/#PI,-deltay*180/#PI,0)
  ProcedureReturn 1
EndProcedure

Procedure.b GestionClavier()
  ;Quitter le programme
  If KeyboardPushed(#PB_Key_Escape)
    End
  EndIf
  ;Rotation du cube avec les flèches directionnelles
  If KeyboardPushed(#PB_Key_Left) : GammaX=-1
  ElseIf KeyboardPushed(#PB_Key_Right) : GammaX=1
  Else : GammaX=0 : EndIf
  If KeyboardPushed(#PB_Key_Up) : GammaY=-1
  ElseIf KeyboardPushed(#PB_Key_Down) : GammaY=1
  Else : GammaY=0 : EndIf
  ;Modes d'affichage
  If KeyboardReleased(#PB_Key_F1)
    CameraRenderMode(#Camera,#PB_Camera_Wireframe)
  EndIf
  If KeyboardReleased(#PB_Key_F2)
    CameraRenderMode(#Camera,#PB_Camera_Textured)
  EndIf
  If KeyboardReleased(#PB_Key_F3)
    rot=1-rot
  EndIf
EndProcedure

Procedure.f DistanceCamera(wheel.f)
  Protected result.f
  result=R-wheel
  If result<10 : ProcedureReturn 10
  ElseIf result>100 : ProcedureReturn 100
  Else : ProcedureReturn result : EndIf
EndProcedure

Procedure.b MoveCubes(cubes.b,inc.b)
  t.f
  For i=0 To 8
    Xi.f=EntityX(i)
    Zi.f=EntityZ(i)
    Ri.f=Sqr(Xi*Xi+Zi*Zi)
    If Ri<>0 : t=ACos(Xi/Ri) : Else : t=0 : EndIf
    If Zi<0 : t=-t : EndIf
    t+#Pas
    EntityLocate(i,Ri*Cos(t),EntityY(i),Ri*Sin(t))
    RotateEntity(i,R2D(-(inc+#IncMax*Matrix(i)\rotx)*#Pas),0,0)
  Next i
EndProcedure

;Ouverture d'un écran ayant les dimensions du bureau
ExamineDesktops()
OpenScreen(DesktopWidth(0),DesktopHeight(0),DesktopDepth(0),"Virtual Cube")

;Souri centrée
Souris\X=DesktopWidth(0)/2
Souris\Y=DesktopHeight(0)/2

;Le sprite de la souris
LoadSprite(#Souris,"souris.png")

;Création de la texture blanche
CreateTexture(#Texture,64,64)
StartDrawing(TextureOutput(#Texture))
  Box(0,0,64,64,0)
  Box(2,2,60,60,#Blanc)
StopDrawing()

;Création de la matière
CreateMaterial(#Matiere,TextureID(#Texture))
MaterialAmbientColor(#Matiere,#PB_Material_AmbientColors)

;Création des 27 cubes numérotés de 0 à 26
For i=0 To #Cube-1
  ;Création d'un mesh avec 100 vertex maximum pour chaque cube
  CreateMesh(i,100)
  ;Couleurs du cube
  *Adresse.som=Cube\Sommet
  *Coord.cube=@Coord()+i*SizeOf(cube)
  For j=0 To 5 ;nombre de faces
    For k=0 To 3 ;nombre de sommets par face
      *Adresse\col=ReverseRGB(*Coord\above)
      *Adresse+SizeOf(som)
    Next k
    *Coord+4
  Next j
  ;Définition des 24 sommets dans le mesh
  SetMeshData(i,#PB_Mesh_Vertex|#PB_Mesh_Normal|#PB_Mesh_Color|#PB_Mesh_UVCoordinate,Cube\Sommet,24)
  ;Définition des triangles
  SetMeshData(i,#PB_Mesh_Face,Cube\Triangle,12)
  ;Création de l'entité, l'objet qui sera affiché !
  CreateEntity(i,MeshID(i),MaterialID(#Matiere),Coord(i)\x,Coord(i)\y,Coord(i)\z)
Next i

;Libération de la mémoire inutile
FreeMemory(Cube\Sommet)
FreeMemory(Cube\Triangle)

;Création de la caméra, pour voir l'objet !
CreateCamera(#Camera,0,0,100,100)
CameraBackColor(#Camera,#Blanc)

;Lumière ambiante
AmbientColor(#Blanc)

;Création de la caméra, pour voir l'objet !
CreateCamera(#Camera,0,0,100,100)
CameraBackColor(#Camera,#Blanc)
CameraLocate(#Camera,0,0,30)

;******************
;-Boucle principale
;******************

Repeat
  ;On fait table-rase
  ClearScreen(0)
  ;Examen du clavier
  ExamineKeyboard()
  GestionClavier()
  ;Examen de la souris
  ExamineMouse()
  If MouseButton(1)
    stop=0
  EndIf
  DeltaX=MouseDeltaX() : DeltaY=MouseDeltaY()
  Souris\X+DeltaX : Souris\Y+DeltaY
  ;Déplacement et rotation de la caméra autour du cube
  If rot=0 : GestionCamera(GammaX/25,GammaY/25)
  Else : GestionCamera(0.02,0.01) : EndIf
  ;Distance de la caméra au cube
  R=DistanceCamera(MouseWheel())
  If stop=0 : inc+1 : EndIf
  If inc<>0 : MoveCubes(0,inc) : EndIf
  If inc=#IncMax : inc=0 : stop=1 : For i=0 To 8 : Matrix(i)\rotx+1 : Next i : EndIf
  ;Affichage du monde 3D
  RenderWorld()
  ;Dessins
  StartDrawing(ScreenOutput())
    DrawText(10,10,"x="+StrF(x))
    DrawText(10,30,"y="+StrF(y))
    DrawText(10,50,"z="+StrF(z))
    DrawText(10,70,"a="+StrF(R2D(a))+"°")
    DrawText(10,90,"b="+StrF(R2D(b))+"°")
  StopDrawing()
  ;Sprites
  DisplayTransparentSprite(#Souris,Souris\X,Souris\Y)
  ;Inverser les tampons
  FlipBuffers()
ForEver

;********
;-Données
;********
;{
DataSection

Sommets:

;Dessus 0 à 3
Data.f -1,1,-1 : Data.f 0,1,0 : Data.l 0 : Data.f 0,1
Data.f 1,1,-1 : Data.f 0,1,0 : Data.l 0 : Data.f 1,1
Data.f 1,1,1 : Data.f 0,1,0 : Data.l 0 : Data.f 1,0
Data.f -1,1,1 : Data.f 0,1,0 : Data.l 0 : Data.f 0,0

;Dessous 4 à 7
Data.f -1,-1,-1 : Data.f 0,-1,0 : Data.l 0 : Data.f 0,1
Data.f 1,-1,-1 : Data.f 0,-1,0 : Data.l 0 : Data.f 1,1
Data.f 1,-1,1 : Data.f 0,-1,0 : Data.l 0 : Data.f 1,0
Data.f -1,-1,1 : Data.f 0,-1,0 : Data.l 0 : Data.f 0,0

;Derriere 8 à 11
Data.f -1,-1,-1 : Data.f 0,0,-1 : Data.l 0 : Data.f 0,1
Data.f 1,-1,-1 : Data.f 0,0,-1 : Data.l 0 : Data.f 1,1
Data.f 1,1,-1 : Data.f 0,0,-1 : Data.l 0 : Data.f 1,0
Data.f -1,1,-1 : Data.f 0,0,-1 : Data.l 0 : Data.f 0,0

;Devant 12 à 15
Data.f -1,-1,1 : Data.f 0,0,1 : Data.l 0 : Data.f 0,1
Data.f 1,-1,1 : Data.f 0,0,1 : Data.l 0 : Data.f 1,1
Data.f 1,1,1 : Data.f 0,0,1 : Data.l 0 : Data.f 1,0
Data.f -1,1,1 : Data.f 0,0,1 : Data.l 0 : Data.f 0,0

;Droite 16 à 19
Data.f 1,-1,-1 : Data.f 1,0,0 : Data.l 0 : Data.f 0,1
Data.f 1,-1,1 : Data.f 1,0,0 : Data.l 0 : Data.f 1,1
Data.f 1,1,1 : Data.f 1,0,0 : Data.l 0 : Data.f 1,0
Data.f 1,1,-1 : Data.f 1,0,0 : Data.l 0 : Data.f 0,0

;Gauche 20 à 23
Data.f -1,-1,-1 : Data.f -1,0,0 : Data.l 0 : Data.f 0,1
Data.f -1,-1,1 : Data.f -1,0,0 : Data.l 0 : Data.f 1,1
Data.f -1,1,1 : Data.f -1,0,0 : Data.l 0 : Data.f 1,0
Data.f -1,1,-1 : Data.f -1,0,0 : Data.l 0 : Data.f 0,0

Triangles:

;Dessus
Data.w 3,1,0
Data.w 3,2,1

;Dessous
Data.w 4,5,6
Data.w 4,6,7

;Derrière
Data.w 11,9,8
Data.w 11,10,9

;Devant
Data.w 12,13,14
Data.w 12,14,15

;Gauche
Data.w 19,17,16
Data.w 19,18,17

;Droite
Data.w 20,21,22
Data.w 20,22,23

Coordonnees:

;Rangées du haut
Data.b -2,2,2
Data.l #Jaune,0,0,#Bleu,0,#Orange
Data.b 0,2,2
Data.l #Jaune,0,0,#Bleu,0,0
Data.b 2,2,2
Data.l #Jaune,0,0,#Bleu,#Rouge,0
Data.b -2,2,0
Data.l #Jaune,0,0,0,0,#Orange
Data.b 0,2,0
Data.l #Jaune,0,0,0,0,0
Data.b 2,2,0
Data.l #Jaune,0,0,0,#Rouge,0
Data.b -2,2,-2
Data.l #Jaune,0,#Vert,0,0,#Orange
Data.b 0,2,-2
Data.l #Jaune,0,#Vert,0,0,0
Data.b 2,2,-2
Data.l #Jaune,0,#Vert,0,#Rouge,0

;Rangées du milieu
Data.b -2,0,2
Data.l 0,0,0,#Bleu,0,#Orange
Data.b 0,0,2
Data.l 0,0,0,#Bleu,0,0
Data.b 2,0,2
Data.l 0,0,0,#Bleu,#Rouge,0
Data.b -2,0,0
Data.l 0,0,0,0,0,#Orange
Data.b 0,0,0
Data.l 0,0,0,0,0,0
Data.b 2,0,0
Data.l 0,0,0,0,#Rouge,0
Data.b -2,0,-2
Data.l 0,0,#Vert,0,0,#Orange
Data.b 0,0,-2
Data.l 0,0,#Vert,0,0,0
Data.b 2,0,-2
Data.l 0,0,#Vert,0,#Rouge,0

;Rangées du bas
Data.b -2,-2,2
Data.l 0,#Blanc,0,#Bleu,0,#Orange
Data.b 0,-2,2
Data.l 0,#Blanc,0,#Bleu,0,0
Data.b 2,-2,2
Data.l 0,#Blanc,0,#Bleu,#Rouge,0
Data.b -2,-2,0
Data.l 0,#Blanc,0,0,0,#Orange
Data.b 0,-2,0
Data.l 0,#Blanc,0,0,0,0
Data.b 2,-2,0
Data.l 0,#Blanc,0,0,#Rouge,0
Data.b -2,-2,-2
Data.l 0,#Blanc,#Vert,0,0,#Orange
Data.b 0,-2,-2
Data.l 0,#Blanc,#Vert,0,0,0
Data.b 2,-2,-2
Data.l 0,#Blanc,#Vert,0,#Rouge,0

EndDataSection

;}

Publié : mar. 15/avr./2008 8:54
par kelebrindae
Très joli, Octavius!

Pour savoir sur quelle entity se trouve le curseur de ta souris, tu peux aller voir ce code de l'inévitable Comtois:
http://www.purebasic.fr/french/viewtopic.php?t=4932

Et oui, je suis d'accord avec toi, le "mouse pick" en 3D est une des choses qui manquent en 3D sous PureBasic; tu ne trouveras aucune instruction toute faite. :cry:
Espérons que la 4.30, vers laquelle se tournent les espoirs de milliards de codeurs PB de par le monde, comblera cette lacune (la 4.30 est censée apporter un plus grande intégration du moteur Ogre dans PB, et apporter une gestion plus complète de la 3D).
En attendant, tu peux jeter un oeil à Dreammotion 3D: c'est gratuit, pas trop dur à comprendre, rapide, et plus complet; le mouse pick est géré, par exemple. Que du bon!

Sinon, juste une petite question, pour jouer les enquiquineurs:
Pourquoi 27 cubes ? Celui du centre, on ne le voit jamais, non ? => 26 suffiraient.
(ça te fait bien gagner... Houlà, au moins 12 polygones, ça... :roll: )

Publié : mar. 15/avr./2008 12:22
par Anonyme
(la 4.30 est censée apporter un plus grande intégration du moteur Ogre dans PB, et apporter une gestion plus complète de la 3D).
j'y crois pas trop , la 4.0 devais aussi apporté son lot 3D :D

Publié : mar. 15/avr./2008 12:39
par djes
A mon avis, tu peux créer une entité invisible juste sous le curseur et utiliser la détection de collision intégrée d'ogre.

Publié : mar. 15/avr./2008 13:25
par kelebrindae
djes a écrit :A mon avis, tu peux créer une entité invisible juste sous le curseur et utiliser la détection de collision intégrée d'ogre.
...la difficulté étant de transformer les coordonnées 2D de la souris en coordonnées 3D, justement.

Mais c'est le principe de base, oui:
- On calcule un plan imaginaire parallèle à la vue de la camera;
- Sur ce plan, on place la souris;
- On fait une sorte de "lancer de rayon" entre ce point et un autre situé dans le lointain (toujours par rapport à la caméra);
- Et on repère la collision la plus proche entre ce rayon et les entités présentes.

Ce n'est pas si simple...
Le snippet de Comtois le fait très bien, et il me semble avoir vu un truc sur le forum anglais qui le faisait avec le système de collision intégrée à Ogre => cherche avec "Mouse pick" ou "mouse pick 3D".

Publié : mer. 16/avr./2008 2:28
par Octavius
Mmh, je ne pensais pas que ce serait si compliqué la gestion de la souris. En attendant je fais mes tests au clavier. J'y jetterai un oeil plus tard car pour l'instant j'ai des difficultés avec les transformations et les rotations de mes cubes. Facile de faire tourner des faces séparément, le problème c'est de faire tourner plusieurs faces et de dire au programme que tel cube appartient maintenant à une nouvelle face, sans compter le problème de gérer les rotations successives pour qu'elles soient toutes dans le bon sens... Plein de jolis bugs en perspective!
Pourquoi 27 cubes ? Celui du centre, on ne le voit jamais, non ? => 26 suffiraient.
Au départ je m'en servais pour centrer le regard de la caméra, de plus ça facilite la numérotation de mes cubes, c'est plus facile pour que je me repère dans mes schémas.