Tutoriel 1 - Créer une scène avec Ogre
Date de publication : 15/06/2006 , Date de mise à jour : 05/07/2006
Par
Nicolas Bauland (Autres articles)
Cet article est, pour une grande partie, la traduction d'un tutoriel anglais disponible sur le site d'
Ogre. Il est le premier d'une
série de tutoriaux consacrés à la découverte du moteur Ogre. Si vous avez des questions,
corrections ou suggestions, postez un message sur le forum dans la section
moteur 3D
en précisant [Tutoriel Ogre] dans le titre.
I. Prérequis
II. Introduction
III. C'est parti !
IV. Comment Ogre fonctionne ?
IV-A. Les bases du gestionnaire de scène
IV-B. Les bases des entités
IV-C. Les bases des noeuds de scène
V. Première application Ogre
VI. Coordonnées et vecteurs
VII. Ajouter un autre objet
VIII. Les entités en profondeur
IX. Les noeuds de scène en profondeur
X. Choses à tester
X-A. Echelle
X-B. Rotation
XI. Conclusion
Téléchargements
Remerciements
I. Prérequis
Ce tutoriel présume que vous ayez des connaissances de programmation en
C++ et que vous êtes capable de configurer et compiler une application
Ogre (si vous avez des difficultés à configurer votre application, voir
ce guide pour les configurations
spécifiques au compilateur). Aucune connaissances sur Ogre n'est nécessaire,
en dehors de celles concernant l'installation, pour aborder ce tutoriel.
Bien que je détaille la procédure pour les compilateurs Microsoft Visual Studio 2005 et Microsoft Visual C++ Express 2005 (nommé dans la suite VS), tout le code présenté fonctionne quelque soit le compilateur et l'environnement (Windows ou linux), vous aurez juste à taper le code et à créer les fichiers à la main si vous utilisez un autre environnement de programmation.
II. Introduction
Dans ce tutoriel, on introduira les bases d'Ogre : les noeuds de scène,
les gestionnaires de scène et les entités d'objets. Nous ne verrons pas
beaucoup de code; en fait, nous nous focaliserons sur les concepts généraux
pour commencer à apprendre et à utiliser Ogre.
En même temps que vous parcourerez ce tutoriel, vous devriez ajouter
tranquillement le code dans votre propre projet et observer les résultats
au fur et à mesure que nous le construirons. Il n'y a pas vraiment d'autres
solutions pour vous familiariser avec ces concepts ! Résistez à l'envie
de simplement lire ce texte en diagonale .
Dans ce premier tutoriel, je ne m'interesserai qu'à vous faire découvrir
quelques possibilités d'Ogre, principalement l'affichage d'objet 3D. On utilisera
pour tout ce premier tutoriel, une classe ExampleApplication qui existe
déjà (Répertoire:(OgreSDK)\samples\include) et qui nous fera
l'essentiel du travail. Nous n'étudierons pas en détail cette classe,
ce sera l'objet du prochain tutoriel.
III. C'est parti !
On va utiliser du code de base préconstruit pour ce tutoriel. Vous ne
devez pas, pour l'instant, vous préoccuper du code autre que celui de
la fonction createScene() que nous allons ajouter. Dans un
prochain tutoriel, nous étudierons plus en profondeur comment fonctionne
une application Ogre, mais pour l'instant nous nous focaliserons sur
des choses plus simples. Créez un projet nommé Tutoriel1 à l'aide de l'assistant (voir
ici pour l'installation avec
VS),
sélectionnez les options suivantes:
- Application minimale,
- à partir de l'application exemple
- copie après la compilation (l'exécutable sera ainsi directement copié
dans le répertoire bin de la librairie Ogre pour pouvoir accéder aux DLLs).
Vous devriez obtenir le code suivant dans un fichier nommé Tutoriel1.cpp:
| Tutoriel1.cpp |
#include <Ogre.h>
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
int main(int argc, char *argv[])
#endif
{
SET_TERM_HANDLER;
try {
} catch( Ogre::Exception& e ) {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else
std::cerr << "An exception has occured: " <<
e.getFullDescription().c_str() << std::endl;
#endif
}
return 0;
}
#ifdef __cplusplus
}
#endif |
Vous remarquerez qu'un objet app correspondant à la classe Tutoriel1App est
déclaré (Tutoriel1App app;) puis la méthode go de cet objet est appelé
(app.go();). Ces deux lignes sont commentées ce qui les rends inactives.
De plus la classe Tutoriel1App n'existe pas encore, nous allons la créer de
façon propre, c'est-à-dire dans des fichiers séparés.
Commençons par créer une nouvelle classe que vous nommerez Tutoriel1App.
Cette classe sera dérivée d'une classe ExampleApplication fournie dans les
exemples du SDK d'Ogre. Nous étudierons la conception (plus ou moins bien faite)
de cette classe, et verrons comment créer la notre dans un prochain tutoriel.
Dans VS, vous pouvez le faire en sélectionnant le projet et en cliquant sur
ajouter une classe dans le menu contextuel puis sélectionnez Classe C++.
Nommez votre classe Tutoriel1App, définissez le chemin du fichier
.h dans le répertoire include, et celui du .cpp dans
src. N'oubliez pas de spécifier la classe de base, à savoir
ExampleApplication (Ne tenez pas compte de la fenêtre d'avertissement),
vous devriez obtenir la fenêtre suivante:
Cliquer sur Terminer. Vous obtiendrez donc deux fichiers:
| Tutoriel1App.h | #pragma once
class Tutoriel1App :
public ExampleApplication
{
public:
Tutoriel1App(void);
public:
~Tutoriel1App(void);
}; |
| Tutoriel1App.cpp | #include "..\include\Tutoriel1App.h"
Tutoriel1App::Tutoriel1App(void)
{
}
Tutoriel1App::~Tutoriel1App(void)
{
} |
Il faut faire appel à cette classe dans notre fichier de départ:
Tutoriel1.cpp. Pour cela rajouter la ligne suivante:
| Tutoriel1.cpp | #include "..\include\Tutoriel1App.h" |
Décommentez les deux lignes où apparait Tutoriel1App. Dorénavant,
nous ne manipulerons plus que la classe Tutoriel1App. Pour cela
revenons au fichier Tutoriel1App.h, juste après la ligne qui permet
d'éviter les appels mutiples à ce fichier, rajoutez:
| Tutoriel1App.h | #include "ExampleApplication.h" |
Cette classe ExampleApplication, contient le canevas par défaut
d'une classe d'application pour le moteur Ogre. Cette classe est une classe
abstraite. Nous devons donc définir la fonction virtuelle afin de pouvoir
instancier notre nouvelle classe. Cette fonction virtuelle est createScene
(en réalité, nous ne ferons que modifier son contenu dans ce premier tutoriel).
L'étude de l'architecture de la classe ExampleApplication sera l'objet
du deuxième tutoriel.
Rajouter la déclaration de cette fonction dans le fichier d'entête:
| Tutoriel1App.h | void createScene(void); |
Rajouter la définition dans le fichier de code. Pour l'instant, ce sera simple, cette fonction ne fera absolument rien:
| Tutoriel1App.h | void Tutoriel1App::createScene(void){
} |
IV. Comment Ogre fonctionne ?
Nous allons commencer par étudier le gestionnaire de Scène puis nous
aborderons les entités et, enfin, les noeuds de scène.
Ces trois classes sont les structures fondamentales des applications Ogre.
IV-A. Les bases du gestionnaire de scène
Tout ce qui apparaît à l'écran est géré par le gestionnaire de scène
(original, non ?). Lorsque l'on place un objet sur la scène, le
gestionnaire de scène est la classe qui garde la trace de sa localisation.
Lorsque l'on crée des caméras sur la scène (chose que l'on abordera
dans un prochain tutoriel), le gestionnaire de scène garde leur
trace. Il en va de même pour les plans, les lumières ... et ainsi
de suite.
Il existe plusieurs types de gestionnaires de scène. Certains gèrent
le rendu de terrain, d'autres de texture BSP ... Vous pouvez avoir
une liste de ces gestionnaires ici.
On abordera ces différents gestionnaires au fur et à mesure des tutoriels.
IV-B. Les bases des entités
Une entité est un objet dont on peut avoir un rendu à l'écran.
On peut voir comme entité tout ce qui peut être représenté par un
maillage en 3D. Un robot peut être une entité, un poisson est une
entité, le terrain sur lequel se déplace un personnage est un objet
très vaste. Les choses comme les lumières, les particules, les
cameras ... ne sont pas des entités.
Une chose à noter à propos d'Ogre est qu''il sépare les objets, dont
on peut faire un rendu, et, leur localisation et leur orientation.
Cela signifie que l'on ne peut pas placer directement un objet sur
la scène. En fait, il faut attacher un objet à un noeud de scène,
ce noeud de scène contiendra les informations concernant la
position et de l'orientation de l'entité.
IV-C. Les bases des noeuds de scène
Comme déjà dit, les noeuds de scène contiennent les informations
de position et d'orientation de tous les objets qui y sont rattachés.
Lorsque l'on crée une entité, elle ne sera pas affichée à l'écran tant
qu''elle ne sera pas rattachée à un noeud de scène. De la même façon,
un noeud de scène n'est pas un objet visible à l'écran. Il n'y a
qu''en créant un noeud de scène ET en lui rattachant un objet que
quelque chose sera visible à l'écran.
Un noeud de scène peut avoir un nombre quelconque d'objets attachés.
Par exemple, si l'on souhaite avoir un personnage se déplaçant à l'écran
avec une lumière autour de lui. Il suffit donc de créer en
premier un noeud de scène, créer une entité pour le personnage et
l'attacher au noeud de scène. On crée ensuite une lumière que l'on attache
au même noeud de scène. Les noeuds de scène peuvent eux-mêmes être
attachés à d'autres noeuds de scène, permettant ainsi de créer une
hiérarchie complète de noeuds. Nous utiliserons cela plus tard dans
ce tutoriel.
Un point fondamental à propos des noeuds de scène est
que la position d'un noeud de scène est TOUJOURS relative à son
noeud de scène parent, et chaque gestionnaire de scène contient
un noeud racine auquel sont attachés tous les noeuds de scène.
V. Première application Ogre
Revenons maintenant au code précédent. Cherchons la fonction membre
Tutoriel1App::createScene. Nous ne manipulerons que le contenu de cette fonction
dans ce tutoriel. La première chose que nous allons faire est de définir
la lumière ambiante pour la scène afin que nous puissions voir ce que
nous ferons. Nous ferons cela en appelant la fonction
SetAmbientLight et spécifier la couleur que nous souhaitons. On
notera que le constructeur de ColourValue attend une valeur pour le rouge,
le vert et le bleu chacune étant dans un intervalle compris entre 0 et 1.
Ajouter cette ligne à createScene:
| Tutoriel1App.cpp | mSceneMgr->setAmbientLight(ColourValue(1.0f,1.0f,1.0f)); |
La chose suivante que nous devons faire est d'ajouter une entité. Nous
le faisons en appelant la fonction membre createEntity de SceneManager:
| Tutoriel1App.cpp | Entity* ent1=mSceneMgr->createEntity("Robot 1","robot.mesh"); |
Bien. Plusieurs questions doivent se poser. Premièrement, d'où provient
mSceneMgr et quels sont les paramètres que nous devons passer à cette
fonction ? La variable mSceneMgr contient l'objet SceneManager actuel
(cela est réalisé par la classe ExampleApplication). Le premier paramètre
de createEntity est le nom de l'entité que nous créons. Toutes les
entités doivent avoir un nom unique. Vous obtiendrez une erreur à
l'exécution si vous essayez de créer deux entités avec le même nom. Le
second paramètre indique l'objet maillé que nous souhaitons utilisé pour
cette entité. Celui-ci se trouve dans le dossier (OgreSDK)\media\models.
Comment Ogre a-t-il trouvé cet objet ? Il existe dans le répertoire (OgreSDK)\bin,
un fichier nommé resources.cfg qui contient une liste de répertoires et de packages
(fichiers compressés) dans lequel Ogre pourra aller chercher les différents objets,
textures ... que l'on appellera dans le programme. Pour plus d'informations,
consultez le document intitulé "Gestion des ressources avec Ogre". Encore une fois,
cette initialisation a été effectuée pour nous par la classe ExampleApplication.
Maintenant que nous avons créé notre entité, nous devons créer un noeud de
scène qui la contiendra. Puisque chaque gestionnaire de scène a un noeud de
scène racine, nous allons créer un enfant à ce noeud:
| Tutoriel1App.cpp | SceneNode* node1 = mSceneMgr->getRootSceneNode()->createChildSceneNode("Noeud Robot 1"); |
Cette longue instruction appelle pour commencer la fonction getRootScene
du gestionnaire de scène actuel. Puis elle appelle la fonction createChildSceneNode
du noeud de scène racine. Le paramètre de cette fonction est le nom du noeud de
scène que nous créons. De même que pour les noms d'entités, deux noeuds de scène
ne peuvent pas porter le même nom.
Pour finir, nous devons attacher l'entité au noeud de scène de manière à
ce que le robot puisse être dessiné à une position particulière:
| Tutoriel1App.cpp | node1->attachObject(ent1); |
C'est fini ! Compilez et lancer l'application. Vous devriez voir un
robot sur l'écran.
Vous pouvez utilisez la souris pour faire pivoter la vue, les flèches pour
vous déplacer, et enfin, un appui sur ESC termine l'application. Qu'est-ce
qui permet cette interacitivité ? La classe ExampleApplication fait appel
à un "FrameListener" ou écouteurs d'image. Cet objet est appelé pour chaque
image lorsqu'un événement se déclenche: appui sur une touche, déplacement
de la souris, clic de souris ... Il permettra aussi de réaliser l'animation
des scènes, mais chaque chose en son temps, gardons cela pour les deuxième
et troisième tutoriaux.
VI. Coordonnées et vecteurs
Avant que nous n'allions plus loin, nous devons parler des coordonnées
d'écran et objets vecteurs d'Ogre. Ogre (comme la plupart des moteurs
graphiques) utilise les axes z et x pour définir le plan horizontal, et
l'axe y comme axe vertical. Tel que vous regardez votre écran en ce moment,
l'axe x va du coté gauche au coté droit de votre écran, le coté droit étant
la direction positive de x. L'axe y va du bas en haut de l'écran, le haut
étant la direction positive de y. L'axe z va du "fond" de l'écran vers l'"avant"
de l'écran, l'avant étant la direction positive de z.
Avez-vous noter comme le robot fait face à la direction positive de l'axe x ?
C'est une propriété intrinsèque à l'objet maillé et la façon dont il a été
conçu. Ogre ne fait aucune présomption quant à l'orientation de vos modèles.
Chaque objet maillé que vous chargez peut avoir une orientation de départ
différente.
Ogre utilise la classe Vector pour représenter, et la position, et la direction
(il n'y a pas de classe Point). Il y a des vecteurs pour 2 (Vector2), 3 (Vector3)
et 4(Vector4) dimensions, bien que Vector3 soit le plus utilisé. Si vous n'êtes
pas familiarisé avec les vecteurs, je vous conseille de vous plonger dans leur
étude, car sans, vous ne pourrez rien faire de bien sérieux avec Ogre. Les
mathématiques qui se cachent derrière les vecteurs va devenir rapidement
utile dans les programmes un peu plus complexes.
VII. Ajouter un autre objet
Maintenant que vous avez compris comment fonctionne le système de coordonnées,
nous pouvons revenir à notre code. Dans les trois lignes que nous avons écrites,
nous n'avons spécifié nulle part la position à laquelle nous voulons apparaitre
notre Robot. Une grande partie des fonctions dans Ogre utilisent des paramètres
par défaut. Par exemple, la fonction membre
createChildSceneNode dans Ogre a 3 paramètres: le nom du noeud
de scène, la position du noeud de scène, et la rotation initiale (l'orientation)
à laquelle on fait face. La position, comme vous pouvez le voir, a été définie
pour nous aux coordonnées (0,0,0). Créons un autre noeud de scène, mais cette
fois, nous allons spécifier la position initiale de telle sorte que ce ne soit
pas l'origine:
| Tutoriel1App.cpp | Entity* ent2=mSceneMgr->createEntity("Robot 2","robot.mesh");
SceneNode* node2=mSceneMgr->getRootSceneNode()->createChildSceneNode("Noeud Robot 2",Vector3(50,0,0));
node2->attachObject(ent2); |
Ce code devrait vous sembler familier. Nous avons fait exactement la
même chose qu'avant, à deux exceptions. Premièrement, nous avons nommer
l'entité et le noeud de scène de façon légèrement différente. La deuxième
chose est que nous avons spécifier que la position de départ devait être
de 50 unités selon l'axe x par rapport au noeud de scène (Rappelez-vous
que toutes les positions des noeuds de scène sont relatives à celles de
leurs parents). Compilez et lancer. Maintenant il devrait y avoir deux
robots cote à cote.
VIII. Les entités en profondeur
La classe des entités - Entity - est très fournie, et on ne
va pas passer en revue chaque fonctionnalité. On verra uniquement ce
qui permettra de débuter. Il y a juste quelques fonctions vraiment
très importantes à étudier.
La première est Entity::setVisible et Entity::isVisible.
Vous pouvez définir n'importe quel object comme étant visible ou non.
Si l'on souhaite cacher un objet, mais l'afficher de nouveau plus tard,
il vaut mieux appeler cette fonction plutôt que de détruire l'objet et
de le recréer plus tard. Remarquez que vous n'avez pas à essayer "regrouper"
vos entités. Une seule copie de chaque maillage et chaque texture sont
chargée en mémoire, vous n'avez donc pas à vous préoccuper de sauvegarder
la mémoire en chargeant les modèles. La seule chose que vous économiserez
sera la construction et la destruction des entités, ce qui a un coût
relativement bas en terme d'utilisation processeur.
La fonction getName retourne le nom de l'entité et la fonction
getParentSceneNode retourne le noeud de scène auquel est rattaché
l'objet.
IX. Les noeuds de scène en profondeur
La classe SceneNode est très complexe. Il y a beaucoup de
choses qui peuvent être faites avec les noeuds de scène, aussi, on se
contentera de passer en revue les fonctions que l'on utilisera le plus.
Vous pouvez obtenir et définir la position d'un noeud de scène par les
fonctions getPosition et setPosition (la position est toujours définie
par rapport au noeud de scène parent). Vous pouvez déplacer un objet
par rapport à sa position initiale en utilisant la fonction translate.
Les noeuds de scène ne définissent pas que la position d'un objet,
ils contrôlent également le facteur d'échelle et la rotation des objets.
Vous pouvez modifier le facteur d'échelle par la méthode scale.
Vous pouvez utiliser les méthodes yaw, roll et pitch
pour faire une rotation de l'objet. Vous utiliserez resetOrientation
pour annuler toutes les rotations sur un objet. Vous pouvez également
utiliser les fonctions setOrientation, getOrientation et rotate
pour utiliser des rotations plus avancées. Nous n'étudierons pas les
quaternions avant plusieurs tutoriaux.
Vous avez déjà vu la fonction attachObject. Les fonctions similaires
sont aussi très utiles si vous comptez manipuler les objets attachés à
un noeud de scène: numAttachedObjects, getAttachedObject
(il y a plusieurs versions de cette fonction) et detachAllObjects
(également plusieurs versions). Il y a également une multitude de
fonction permettant de manipuler les noeuds enfants ou parents.
Puisque toutes les positions/translations qui sont faites sont relatives
au noeud parent, nous pouvons faire que deux noeuds de scène se déplacent
en même temps très facilement. Nous avons actuellement ce code dans notre
application:
| Tutoriel1App.cpp | Entity* ent1=mSceneMgr->createEntity("Robot 1","robot.mesh");
SceneNode* node1=mSceneMgr->getRootSceneNode()->createChildSceneNode("Robot noeud 1",Vector3(50,0,0));
node1->attachObject(ent1);
Entity* ent2=mSceneMgr->createEntity("Robot2","robot.mesh");
SceneNode* node2=mSceneMgr->getRootSceneNode()->createChildSceneNode("Robot noeud 2",Vector3(50,0,0));
node2->attachObject(ent2); |
Si nous changeons la cinquième ligne de cela :
| Tutoriel1App.cpp | SceneNode* node2=mSceneMgr->getRootSceneNode()->createChildSceneNode("Robot noeud 2",Vector3(50,0,0)); |
En cela :
| Tutoriel1App.cpp | SceneNode* node2=node1->createChildSceneNode("Robot noeud 2",Vector3(50,0,0));
< |
Alors RobotNode2 est devenu un noeud enfant de RobotNode.
Le fait de déplacer le noeud 1 va déplacer le noeud 2 avec lui, mais
déplacer le noeud 2 n'aura aucun effet sur le noeud 1. Par exemple,
ce code ne déplacera que le noeud 2:
| Tutoriel1App.cpp | node2->translate(Vector3(10,0,10)); |
Le code suivant va déplacer Noeud Robot, et puisque Noeud Robot 2 est
l'enfant de Noeud Robot, Noeud Robot 2 va se déplacer également:
| Tutoriel1App.cpp | node1->translate(Vector3(25,0,0)); |
Si vous avez des difficultés avec ce que l'on vient de voir, la
chose la plus simple que vous ayez à faire est de partir de la racine
des noeuds de scène et de descendre en parcourant chaque noeud.
Dans ce cas, on commence par le noeud 1 de coordonnées (0,0,0)
qui est translaté de (25,0,0), donc la position du noeud 1 devient
(vis à vis du noeud parent) (25,0,0). Le noeud 2 est initialisé
avec (50,0,0) et on le translate de (10,0,10) donc sa nouvelle
position est (60,0,10) relativement à son noeud parent.
Ceci dit il est assez rare d'avoir besoin de connaitre les positions
absolues des noeuds. Si tel était toutefois le cas, vous pouvez utiliser
les fonctions qui appellent les noeuds et les entités par leur nom :
getSceneNode et getEntity. Ceci vous permet également de ne pas garder
des pointeurs sur chaque objet que vous gardez, seuls les objets
fréquemment utilisés pourront faire l'objet de pointeurs afin d'assurer
la rapidité des accès.
X. Choses à tester
Maintenant vous devez avoir les connaissances de bases nécessaires
sur les entités, les noeuds de scène et les gestionnaires de scène.
Je vous suggère de reprendre le code ci-dessus, d'ajouter des robots
et de les enlever de la scène. Ensuite effacez tout et essayer les
concepts suivants:
X-A. Echelle
Vous pouvez modifier le facteur d'échelle d'un objet maillé en
appelant la méthode scale dans le noeud de scène correspondant.
Essayez le code suivant:
| Tutoriel1App.cpp | Entity* ent=mSceneMgr->createEntity("Robot 1","robot.mesh");
SceneNode* node=mSceneMgr->getRootSceneNode()->createChildSceneNode("Robot noeud 1",Vector3(50,0,0));
node->attachObject(ent);
node->scale(0.5,1.0,2.0);
ent=mSceneMgr->createEntity("Robot 2","robot.mesh");
node=mSceneMgr->getRootSceneNode()->createChildSceneNode("Robot noeud 2",Vector3(50,0,0));
node->attachObject(ent);
node->scale(1.0,2.0,1.0); |
X-B. Rotation
Vous pouvez faire pivoter les objets maillés en utilisant les méthodes
yaw, pitch et roll et en spécifiant la valeur de l'angle
en radians (par défaut) ou en degrés (en utilisant la fonction Degree).
Essayez le code suivant:
| Tutoriel1App.cpp | Entity* ent=mSceneMgr->createEntity("Robot 1","robot.mesh");
SceneNode* node=mSceneMgr->getRootSceneNode()->createChildSceneNode("Robot noeud 1",Vector3(50,0,0));
node->attachObject(ent);
node->yaw(Degree(-90));
ent=mSceneMgr->createEntity("Robot 2","robot.mesh");
node=mSceneMgr->getRootSceneNode()->createChildSceneNode("Robot noeud 2",Vector3(50,0,0));
node->attachObject(ent);
node->pitch(Degree(90));
ent=mSceneMgr->createEntity("Robot 3","robot.mesh");
node=mSceneMgr->getRootSceneNode()->createChildSceneNode("Robot noeud 3",Vector3(50,0,0));
node->attachObject(ent);
node->pitch(Degree(-90)); |
XI. Conclusion
Nous voilà arriver au terme de ce premier tutoriel. Vous devriez avoir
les bases vous permettant de manipuler les objets entités, noeuds de
scène et gestionnaire de scène. Ne vous inquiétez pas si vous ne retenez
pas toutes les fonctions utilisées ici, vous finirez par les utiliser si
souvent quelles finiront par devenir naturelles.
Pour la suite, c'est par ici.
Téléchargements
Voici les fichiers relatifs à ce tutoriel:
Remerciements
Je remercie Laurent Gomila (loulou) pour pour son aide. Je remercie également tous les correcteurs de cet article : Khayyam90, Ovh et Loka.
 
|