PureBasic:3DPremiersPas



PureBasic:3DPremiersPas

<< Précédent | Sommaire | Suivant >>


Sommaire

[modifier] Introduction

Pour débuter nous allons créer un triangle et l'afficher à l'écran.

Copie d'écran de ce fameux triangle
Copie d'écran de ce fameux triangle

Ce premier tutoriel sur la 3D nous permettra d'aborder :

  • La création d'un mesh
  • La création d'une texture
  • La création d'une matière
  • La création d'une entity
  • L'éclairage ambiant
  • La création d'une caméra
  • L'affichage d'une scène 3D

[modifier] Mesh

Ce que dit la doc :

Les Meshs sont des objets 3D composés de triangles qui sont reliés entre eux pour donner la forme finale. Une Mesh peut posséder un squelette si elle est animée, permettant des animations réalistes et de qualité. Une Mesh ne peut pas être affichée directement dans le monde 3D, elle doit être encapsulée dans une entity.

Un triangle est défini par 3 sommets (en anglais : Vertex au singulier, vertices au pluriel)

Un sommet est défini par :

  • Une position en x, y et z (#PB_Mesh_Vertex)
  • Une normale (#PB_Mesh_Normal)
  • Une couleur (#PB_Mesh_Color)
  • Des coordonnées u et v d'une texture. (#PB_Mesh_UVCoordinate)

Seule la position du sommet est obligatoire. La normale, la couleur et les coordonnées UV sont facultatives. Dans ce tutoriel nous allons créer un mesh en définissant la position et la couleur des sommets. Les coordonnées de la position se donnent par rapport aux repères du mesh. Ce repère est indépendant du repère de la scène 3D.

;Création d'un mesh 
#Mesh = 0  
CreateMesh(#Mesh, 200) ; 200 indique la dimension maxi du mesh
   
;Définition des sommets
SetMeshData(#Mesh, #PB_Mesh_Vertex | #PB_Mesh_Color , ?SommetsTriangles, 3) ; Indiquez ici le nombre de sommets

;Définition des triangles
SetMeshData(#Mesh, #PB_Mesh_Face, ?IndexTriangles, 1) ; indiquez ici le nombre de triangles

?SommetsTriangles : Indique l'adresse à laquelle se trouvent les données correspondant à la définition des sommets. Dans le premier exemple on utilise des datas, mais il est aussi possible d'utiliser un tableau , ou d'allouer un bloc mémoire, voir les exemples ci dessous.

?IndexTriangles : Indique l'adresse à laquelle se trouvent les données correspondant à la définition du ou des triangles, dans notre exemple il n'y a qu'un triangle.

IndexTriangles:
Data.w 2,1,0  

Important : Notez le .w pour les datas, vous devez utiliser des word.
Pour former un triangle il faut indiquer l'index des sommets dans un ordre précis, dans le sens inverse des aiguilles d'une montre pour que la face soit visible, l'autre face du triangle sera invisible. Essayez de croiser 0 et 2 :

IndexTriangles:
Data.w 0,1,2  

En changeant l'ordre des sommets, le triangle n'est plus affiché. Faites l'essai !
Pour le voir à nouveau il faudrait placer la caméra derrière.

CameraLocate(#Camera, 0, 0, -500) ; Positionne la caméra 

Si on voulait effectuer des rotations à notre triangle il faudrait donc doubler les faces, pour que notre triangle soit toujours visible quelque soit la position de la caméra.

IndexTriangles:
Data.w 2,1,0  
Data.w 0,1,2  

Et bien sûr, n'oubliez pas de changer le nombre de faces :

;Définition des triangles
SetMeshData(#Mesh, #PB_Mesh_Face, ?IndexTriangles, 2) ; indiquez ici le nombre de triangles

[modifier] Texture

Ce que dit la doc :

Les textures permettent aux objets 3D d'avoir un aspect réaliste. En effet, sans textures les objets 3D seraient d'une seule couleur unie. PureBasic offre la possibilité de créer des textures directement à l'aide des outils 2D de base (bibliothèque 2DDrawing) ou de les charger à partir de fichiers.

Pour charger une texture utilisez la commande LoadTexture().
Dans ce tutoriel nous n'utiliserons pas de média, nous devons donc créer notre texture.

;Création d'une texture
#Texture = 0
CreateTexture(#Texture, 64, 64) 

;Remplissage de la texture en blanc pour visualiser les couleurs des sommets 
StartDrawing(TextureOutput(#Texture))
  Box(0,0, TextureWidth(#Texture), TextureHeight(#Texture), RGB(255, 255, 255))
StopDrawing()

C'est un simple carré blanc. Amusez vous à changer la couleur de la texture et observez les changements à l'affichage.

[modifier] Matière

Ce que dit la doc :

Les matières sont composées de une ou plusieurs textures et parfois de couleurs. Elles sont utilisées par les autres objets 3D tels que les 'Entity', 'Billboards' et les 'Particules' pour leur donner une matière (principalement une texture). Chaque matière regroupe un grand nombre de propriétés tel que l'éclairage, la couleur spéculaire et de réfraction, etc. pour permettre à une matière de ressembler à des revêtements complexes comme le verre, l'eau, le bois...

;Création d'une matière
#Matiere = 0
CreateMaterial(#Matiere, TextureID(#Texture))
MaterialAmbientColor(#Matiere, #PB_Material_AmbientColors)

Pour voir la couleur des sommets définis précédemment, nous devons utiliser la commande MaterialAmbientColor() avec la constante #PB_Material_AmbientColors. Vous pouvez essayer de mettre en commentaire cette commande et observez ce qui se passe. Il est aussi possible de donner une couleur à la matière (par exemple MaterialAmbientColor(#Matiere, $FF00FF)), dans ce cas les couleurs des sommets ne seront plus utilisées.

La gestion des matières est un vaste sujet, surtout depuis que la V4 permet d'utiliser les scripts. On y reviendra peut-être dans un prochain tutoriel. Si vous êtes impatients vous pouvez toujours jeter un oeil sur la doc d'ogre. Pour charger un fichier script reportez vous à la commande Parse3DScripts().

[modifier] Entity

Ce que dit la doc :

Les 'Entity' sont des objets composés d'un mesh et d'une matière pouvant être déplacées et transformées en temps réel. Il est possible de partager la même Mesh entre plusieurs Entities tout en utilisant une matière différente pour chaque Entity, réduisant ainsi la consommation mémoire et l'utilisation du processeur.

;Création entity
#Entity = 0
CreateEntity(#Entity, MeshID(#Mesh), MaterialID(#Matiere))

[modifier] Eclairage ambiant

Si vous trouvez la scène 3D trop sombre, vous pouvez changer la couleur ambiante avec la commande :

AmbientColor(Rgb(255, 255, 255))

On verra dans un prochain tutoriel l'utisation des lumières, sachez dès à présent qu'il faudra réduire la lumière ambiante pour que l'effet des lumières ajoutées soit perceptible. Par exemple une lumière grise foncée.

AmbientColor(Rgb(85, 85, 85))

[modifier] Camera

Ce que dit la doc :

Les caméras sont utilisées pour se déplacer dans le monde en 3D. Il est possible de les utiliser comme des caméras réelles avec lesquelles on peut se déplacer, effectuer des rotations, changer l'angle de vision etc. Au moins une caméra est nécessaire pour effecter un rendu du monde 3D sur un écran, mais plusieurs caméras peuvent être utilisées en même temps pour afficher le monde sous des angles de vue différents (rétroviseurs , split-screen...).

Pour ce tutoriel on se contente d'une seule caméra

;Création d'une caméra, c'est indispensable pour voir quelque chose 
#Camera = 0
CreateCamera(#Camera, 25, 25, 50, 50) ; Création d'une caméra
CameraBackColor(#Camera, $FF0000) ; Couleur de fond bleue
CameraLocate(#Camera,0,0,-500) ; Positionne la caméra 
CameraLookAt(#Camera, EntityX(#Entity), EntityY(#Entity), EntityZ(#Entity)) ; Oriente la caméra vers l'entity  

Pour la démonstration, notre caméra occupe la moitié de l'écran aussi bien en largeur qu'en hauteur et pour la centrer, on la place à 25% à gauche , et 25 % en haut.

Pour une caméra qui occupe tout l'écran recopiez cette ligne :

CreateCamera(#Camera, 0, 0, 100, 100) ; Création d'une caméra

[modifier] Affichage de la scène 3D

Pour afficher la scène 3D utilisez la commande RenderWorld().

Il est possible de mélanger 3D et 2D :

  • Pour que la 3D s'affiche par dessus la 2D utilisez la commande CameraBackColor(#Camera, -1). Cette commande permet de changer la couleur de fond de la scène 3d, ou de rendre le fond transparent si la paramètre vaut -1.
  • Pour que la 2D s'affiche par dessus la 3D placez vos commandes d'affichage 2D après la commande RenderWorld()
RenderWorld()

; Affiche la 2D par dessus la 3D
DisplaySprite(#Sprite, x, y)

StartDrawing(ScreenOutput())
DrawText(0, 0, "Un texte à l'écran")
StopDrawing()

FlipBuffer()

[modifier] Premier programme 3D

Ce programme utilise les datas

;PB 4.0 le 18/08/06

InitEngine3D()
InitSprite()
InitKeyboard()

OpenScreen(800, 600, 32, "Tutoriel 3D")  
 
;Création d'un mesh  
#Mesh = 0  
CreateMesh(#Mesh, 200)
   
;Définition des sommets
SetMeshData(#Mesh, #PB_Mesh_Vertex | #PB_Mesh_Color , ?SommetsTriangles, 3) ; Indiquez ici le nombre de sommets

;Définition des triangles
SetMeshData(#Mesh, #PB_Mesh_Face, ?IndexTriangles, 1) ; indiquez ici le nombre de triangles

;Création d'une texture
#Texture = 0
CreateTexture(#Texture, 64, 64) 

;Remplissage de la texture en blanc pour visualiser les couleurs des sommets 
StartDrawing(TextureOutput(#Texture))
  Box(0,0, TextureWidth(#Texture), TextureHeight(#Texture), RGB(255, 255, 255))
StopDrawing()
   
;Création d'une matière
#Matiere = 0
CreateMaterial(#Matiere, TextureID(#Texture))
MaterialAmbientColor(#Matiere, #PB_Material_AmbientColors)
   
;Création entity
#Entity = 0
CreateEntity(#Entity, MeshID(#Mesh), MaterialID(#Matiere))
   

;Ajoute une caméra , c'est indispensable pour voir quelque chose 
#Camera = 0
CreateCamera(#Camera, 25, 25, 50, 50) ; Création d'une caméra
CameraBackColor(#Camera, $FF0000) ; Couleur de fond bleue
CameraLocate(#Camera,0,0,500) ; Positionne la caméra 
CameraLookAt(#Camera, EntityX(#Entity), EntityY(#Entity), EntityZ(#Entity)) ; Oriente la caméra vers l'entity   
   
Repeat

  ClearScreen(0)
           
  ExamineKeyboard()
 
  RenderWorld() ; Affiche le monde 3D
  
  FlipBuffers()
       
Until KeyboardPushed(#PB_Key_All) 

DataSection

  SommetsTriangles:
   
    Data.f 0.0,100.0,0.0              ; Position sommet 0
    Data.l $FF0000                    ; Couleur  sommet 0 
    Data.f 200.0,-100.0,0.0           ; Position sommet 1
    Data.l $00FF00                    ; Couleur  sommet 1
    Data.f -200.0,-100.0,0.0          ; Position sommet 2
    Data.l $0000FF                    ; Couleur  sommet 2

  IndexTriangles:
    Data.w 2,1,0                      ; Sommets 2, 1 et 0 pour former un triangle

EndDataSection


[modifier] Autre méthode

Il est possible d'obtenir le même résultat en utilisant des tableaux, ou encore en réservant un bloc mémoire.

Exemple avec des tableaux

;PB 4.0 le 18/08/06

InitEngine3D()
InitSprite()
InitKeyboard()

OpenScreen(800, 600, 32, "Tutoriel 3D")  

Structure s_Sommet
  Position.f[3]
  Couleur.l
EndStructure
 
 Structure s_Triangle
  Index.w[3]
 EndStructure
 
Dim Sommets.s_Sommet(2)
Dim Triangles.s_Triangle(0)

;On comprend mieux Sommets(0)\Position[#x] plutôt que Sommets(0)\Position[0]
Enumeration 
  #x
  #y
  #z
EndEnumeration

;Sommet 0 position et couleur 
Sommets(0)\Position[#x] =    0.0 : Sommets(0)\Position[#y] =  100.0 : Sommets(0)\Position[#z] = 0.0 
Sommets(0)\Couleur = $FF0000

;Sommet 1 position et couleur 
Sommets(1)\Position[#x] =  200.0 : Sommets(1)\Position[#y] = -100.0 : Sommets(1)\Position[#z] = 0.0 
Sommets(1)\Couleur = $00FF00 

;Sommet 2 position et couleur 
Sommets(2)\Position[#x] = -200.0 : Sommets(2)\Position[#y] = -100.0 : Sommets(2)\Position[#z] = 0.0 
Sommets(2)\Couleur = $0000FF   

; Définition du triangle
Triangles(0)\Index[0] = 2 : Triangles(0)\Index[1] = 1 : Triangles(0)\Index[2] = 0


;Création d'un mesh  
#Mesh = 0  
CreateMesh(#Mesh, 200)
   
;Définition des sommets
SetMeshData(#Mesh, #PB_Mesh_Vertex | #PB_Mesh_Color , @Sommets(), 3) ; Indiquez ici le nombre de sommets

;Définition des triangles
SetMeshData(#Mesh, #PB_Mesh_Face, @Triangles(), 1) ; indiquez ici le nombre de triangles

;Création d'une texture
#Texture = 0
CreateTexture(#Texture, 64, 64) 

;Remplissage de la texture en blanc pour visualiser les couleurs des sommets 
StartDrawing(TextureOutput(#Texture))
  Box(0,0, TextureWidth(#Texture), TextureHeight(#Texture), RGB(255, 255, 255))
StopDrawing()
   
;Création d'une matière
#Matiere = 0
CreateMaterial(#Matiere, TextureID(#Texture))
MaterialAmbientColor(#Matiere, #PB_Material_AmbientColors)
   
;Création entity
#Entity = 0
CreateEntity(#Entity, MeshID(#Mesh), MaterialID(#Matiere))

;Ajoute une caméra , c'est indispensable pour voir quelque chose 
#Camera = 0
CreateCamera(#Camera, 25, 25, 50, 50) ; Création d'une caméra
CameraBackColor(#Camera, $FF0000) ; Couleur de fond bleue
CameraLocate(#Camera,0,0,500) ; Positionne la caméra 
CameraLookAt(#Camera, EntityX(#Entity), EntityY(#Entity), EntityZ(#Entity)) ; Oriente la caméra vers l'entity  
   
Repeat

  ClearScreen(0)
           
  ExamineKeyboard()
 
  RenderWorld() ; Affiche le monde 3D
  
  FlipBuffers()
       
Until KeyboardPushed(#PB_Key_All) 

On pourrait très bien remplacé les tableaux par des blocs mémoires (c'est la même chose).

Par exemple pour le tableau sommet on pourrait le remplacer de cette façon :

;C'est l'équivalent de notre Tableau Sommets(2)
*Sommets.s_Sommet = AllocateMemory(SizeOf(s_Sommet) * 3)

;Sommet 0 position et couleur 
*Sommets\Position[0] =    0.0 : *Sommets\Position[1] =  100.0 : *Sommets\Position[2] = 0.0 
*Sommets\Couleur = $FF0000
*Sommets + SizeOf(s_Sommet) ; Pointe sur le sommet suivant

;Sommet 1 position et couleur 
*Sommets\Position[0] =  200.0 : *Sommets\Position[1] = -100.0 : *Sommets\Position[2] = 0.0 
*Sommets\Couleur = $00FF00 
*Sommets + SizeOf(s_Sommet) ; Pointe sur le sommet suivant

;Sommet 2 position et couleur 
*Sommets\Position[0] = -200.0 : *Sommets\Position[1] = -100.0 : *Sommets\Position[2] = 0.0 
*Sommets\Couleur = $0000FF   

*Sommets - 2 * SizeOf(s_Sommet) ; Retour à l'adresse initiale 

;Création d'un mesh  
CreateMesh(0, 200)
   
;Définition des sommets
SetMeshData(0, #PB_Mesh_Vertex | #PB_Mesh_Color , *Sommets, 3) ; Indiquez ici le nombre de sommets

;Définition des triangles
SetMeshData(0, #PB_Mesh_Face, @Triangles(), 1) ; indiquez ici le nombre de triangles

Le reste du programme est inchangé, et on obtient le même résultat.

Vous avez donc différentes possibilités pour créer un mesh manuel, à vous de choisir la méthode qui vous convient le mieux.