Changed readme and examples encoding to UTF-8

This commit is contained in:
Lynix 2012-08-10 01:41:37 +02:00
parent b442ab0bd2
commit b559932d63
4 changed files with 145 additions and 155 deletions

View File

@ -12,10 +12,10 @@
#include <iostream> #include <iostream>
#include <map> #include <map>
// Une structure pour contenir nos informations (Cette structure est très simpliste) // Une structure pour contenir nos informations (Cette structure est très simpliste)
struct Model struct Model
{ {
NzMatrix4f matrix; // Les transformations subies par le modèle NzMatrix4f matrix; // Les transformations subies par le modèle
NzMesh mesh; // Le mesh NzMesh mesh; // Le mesh
NzTexture texture; // Sa texture NzTexture texture; // Sa texture
}; };
@ -23,10 +23,10 @@ struct Model
struct AnimatedModel : public Model struct AnimatedModel : public Model
{ {
// Quelques variables pour l'animation // Quelques variables pour l'animation
const NzSequence* currentSequence = nullptr; // La séquence en cours const NzSequence* currentSequence = nullptr; // La séquence en cours
float interpolation = 0.f; // La valeur de l'interpolation ([0..1], si dépasse 1, on passe à la frame suivante) float interpolation = 0.f; // La valeur de l'interpolation ([0..1], si dépasse 1, on passe à la frame suivante)
unsigned int currentFrame = 0; // La première frame unsigned int currentFrame = 0; // La première frame
unsigned int nextFrame; // La seconde frame, l'animation est interpollée entre ces deux-là unsigned int nextFrame; // La seconde frame, l'animation est interpollée entre ces deux-là
}; };
void AnimateModel(AnimatedModel& moedel, float elapsed); void AnimateModel(AnimatedModel& moedel, float elapsed);
@ -42,15 +42,15 @@ int main()
std::cout << "Dr. Freak controls: Up, down, left and right" << std::endl; std::cout << "Dr. Freak controls: Up, down, left and right" << std::endl;
std::cout << "Escape to quit" << std::endl; std::cout << "Escape to quit" << std::endl;
// Cette ligne active le mode de compatibilité d'OpenGL lors de l'initialisation de Nazara (Nécessaire pour le shader) // Cette ligne active le mode de compatibilité d'OpenGL lors de l'initialisation de Nazara (Nécessaire pour le shader)
NzContextParameters::defaultCompatibilityProfile = true; NzContextParameters::defaultCompatibilityProfile = true;
// Maintenant nous initialisons le Renderer (Qui initialisera le noyau ainsi que le module utlitaire) // Maintenant nous initialisons le Renderer (Qui initialisera le noyau ainsi que le module utilitaire)
// Cette étape est obligatoire pour beaucoup de classes // Cette étape est obligatoire pour beaucoup de fonctionnalités (Notamment le chargement de ressources et le rendu)
NzInitializer<NzRenderer> renderer; NzInitializer<NzRenderer> renderer;
if (!renderer) if (!renderer)
{ {
// Ça n'a pas fonctionné, le pourquoi se trouve dans le fichier NazaraLog.log // Ça n'a pas fonctionné, le pourquoi se trouve dans le fichier NazaraLog.log
std::cout << "Failed to initialize Nazara, see NazaraLog.log for further informations" << std::endl; std::cout << "Failed to initialize Nazara, see NazaraLog.log for further informations" << std::endl;
std::getchar(); // On laise le temps de voir l'erreur std::getchar(); // On laise le temps de voir l'erreur
return EXIT_FAILURE; return EXIT_FAILURE;
@ -58,35 +58,35 @@ int main()
// Maintenant nous pouvons utiliser le moteur comme bon nous semble, tout d'abord nous allons charger les ressources // Maintenant nous pouvons utiliser le moteur comme bon nous semble, tout d'abord nous allons charger les ressources
// Charger une ressource se fait actuellement manuellement, mais un ResourceManager est à venir // Charger une ressource se fait actuellement manuellement, mais un ResourceManager est à venir
// Vous initialisez une ressource, et la chargez via sa méthode LoadFrom[File|Memory|Stream] // Vous initialisez une ressource, et la chargez via sa méthode LoadFrom[File|Memory|Stream]
// Note: il est possible de donner des instructions au loader (qui va charger le fichier en ressource) via les ResourceParameters // Note: il est possible de donner des instructions au loader (qui va charger le fichier en ressource) via les ResourceParameters
NzMeshParams parameters; NzMeshParams parameters;
// Le loader doit-il automatiquement charger les animations ? // Le loader doit-il automatiquement charger les animations ?
// Attention, ce paramètre possède une signification différente selon le type d'animation du mesh. // Attention, ce paramètre possède une signification différente selon le type d'animation du mesh.
// -Pour les animations keyframe (image-clé), c'est la seule et unique façon de charger les animations, étant donné // -Pour les animations keyframe (image-clé), c'est la seule et unique façon de charger les animations, étant donné
// qu'elles sont fourniees avec le mesh. // qu'elles sont fourniees avec le mesh.
// -Pour les animations squelettiques, le loader ne fera que charger automatiquement l'animation associée au mesh s'il le peut // -Pour les animations squelettiques, le loader ne fera que charger automatiquement l'animation associée au mesh s'il le peut
// Dans les deux cas, les paramètres d'animations (parameters.animation) seront utilisés // Dans les deux cas, les paramètres d'animations (parameters.animation) seront utilisés
parameters.loadAnimations = true; // Vaut true par défaut parameters.loadAnimations = true; // Vaut true par défaut
// Pour qu'un mesh puisse être rendu, il doit être stocké du côté de la carte graphique (Hardware), mais il est parfois utile de // Pour qu'un mesh puisse être rendu, il doit être stocké du côté de la carte graphique (Hardware), mais il est parfois utile de
// le stocker côté RAM, par exemple pour le moteur physique. En sachant qu'il est facile de changer le stockage d'un buffer. // le stocker côté RAM, par exemple pour le moteur physique. En sachant qu'il est facile de changer le stockage d'un buffer.
parameters.storage = nzBufferStorage_Hardware; // Vaut nzBufferStorage_Hardware par défaut parameters.storage = nzBufferStorage_Hardware; // Vaut nzBufferStorage_Hardware par défaut
AnimatedModel drfreak; AnimatedModel drfreak;
if (!drfreak.mesh.LoadFromFile("resources/drfreak.md2", parameters)) // On charge notre bon vieux docteur avec les paramètres de chargement. if (!drfreak.mesh.LoadFromFile("resources/drfreak.md2", parameters)) // On charge notre bon vieux docteur avec les paramètres de chargement.
{ {
// Le chargement n'a pas fonctionné, le modèle est peut-être corrompu/non-supporté, ou alors n'existe pas. // Le chargement n'a pas fonctionné, le modèle est peut-être corrompu/non-supporté, ou alors n'existe pas.
std::cout << "Failed to load mesh" << std::endl; std::cout << "Failed to load mesh" << std::endl;
std::getchar(); // On laise le temps de voir l'erreur std::getchar(); // On laise le temps de voir l'erreur
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (!drfreak.mesh.HasAnimation()) // Le mesh possède-t-il des animations ? if (!drfreak.mesh.HasAnimation()) // Le mesh possède-t-il des animations ?
{ {
// Cette démo n'a aucun intérêt sans animations // Cette démo n'a aucun intérêt sans animations
std::cout << "Mesh has no animation" << std::endl; std::cout << "Mesh has no animation" << std::endl;
std::getchar(); std::getchar();
return EXIT_FAILURE; return EXIT_FAILURE;
@ -94,17 +94,17 @@ int main()
SetSequence(drfreak, "stand"); SetSequence(drfreak, "stand");
// Il est possible que le mesh possède un ou plusieurs skin, nous utiliserons cette information pour charger une texture // Il est possible que le mesh possède un ou plusieurs skin, nous utiliserons cette information pour charger une texture
if (drfreak.mesh.HasSkin()) if (drfreak.mesh.HasSkin())
{ {
// Contrairement aux autres ressources, la texture n'est pas critique // Contrairement aux autres ressources, la texture n'est pas critique
if (drfreak.texture.LoadFromFile("resources/" + drfreak.mesh.GetSkin())) if (drfreak.texture.LoadFromFile("resources/" + drfreak.mesh.GetSkin()))
drfreak.texture.SetFilterMode(nzTextureFilter_Bilinear); // Appliquons-lui un filtrage bilinéaire drfreak.texture.SetFilterMode(nzTextureFilter_Bilinear); // Appliquons-lui un filtrage bilinéaire
else else
std::cout << "Failed to load texture" << std::endl; std::cout << "Failed to load texture" << std::endl;
} }
if (!drfreak.texture.IsValid()) // Les méthodes Resource::IsValid indiquent si la ressource a été correctement créée if (!drfreak.texture.IsValid()) // Les méthodes Resource::IsValid indiquent si la ressource a été correctement créée
{ {
std::cout << "Creating checker texture for mesh" << std::endl; std::cout << "Creating checker texture for mesh" << std::endl;
@ -116,7 +116,7 @@ int main()
} }
} }
// Nous créons maintenant notre sol // Nous créons maintenant notre sol
Model floor; Model floor;
if (!CreateFloorMesh(&floor.mesh)) if (!CreateFloorMesh(&floor.mesh))
{ {
@ -136,11 +136,11 @@ int main()
floor.matrix.MakeIdentity(); floor.matrix.MakeIdentity();
// Pour effectuer un rendu, il faut que la carte graphique sache quoi faire. // Pour effectuer un rendu, il faut que la carte graphique sache quoi faire.
// Les shaders sont de petits programmes qui donnent des instructions à la carte graphique lors du pipeline. // Les shaders sont de petits programmes qui donnent des instructions à la carte graphique lors du pipeline.
// Ils sont aujourd'hui indispensables pour un rendu 3D, mais sont très utiles pour divers effets ! // Ils sont aujourd'hui indispensables pour un rendu 3D, mais sont très utiles pour divers effets !
// Il existe plusieurs langages de shaders, GLSL pour OpenGL, HLSL pour Direct3D et Cg qui peut être utilisé pour les deux. // Il existe plusieurs langages de shaders, GLSL pour OpenGL, HLSL pour Direct3D et Cg qui peut être utilisé pour les deux.
// Le Renderer de Nazara utilise OpenGL, par conséquent nous utiliserons le GLSL // Le Renderer de Nazara utilise OpenGL, par conséquent nous utiliserons le GLSL
// La méthode NzShader::IsLanguageSupported permet de savoir si un langage est supporté. // La méthode NzShader::IsLanguageSupported permet de savoir si un langage est supporté.
NzShader shader; NzShader shader;
if (!shader.Create(nzShaderLanguage_GLSL)) if (!shader.Create(nzShaderLanguage_GLSL))
{ {
@ -149,13 +149,13 @@ int main()
return EXIT_FAILURE; return EXIT_FAILURE;
} }
// Une fois le shader créé, nous devons lui spécifier les codes sources de nos shaders // Une fois le shader créé, nous devons lui spécifier les codes sources de nos shaders
// Pour notre exemple nous prendrons un shader très simple // Pour notre exemple nous prendrons un shader très simple
// Un shader doit obligatoirement posséder au moins deux codes, un pour le fragment shader et un pour le vertex shader // Un shader doit obligatoirement posséder au moins deux codes, un pour le fragment shader et un pour le vertex shader
if (!shader.LoadFromFile(nzShaderType_Fragment, "shaders/basic.frag")) if (!shader.LoadFromFile(nzShaderType_Fragment, "shaders/basic.frag"))
{ {
std::cout << "Failed to load fragment shader from file" << std::endl; std::cout << "Failed to load fragment shader from file" << std::endl;
// À la différence des autres ressources, le shader possède un log qui peut indiquer les erreurs en cas d'échec // À la différence des autres ressources, le shader possède un log qui peut indiquer les erreurs en cas d'échec
std::cout << "Log: " << shader.GetLog() << std::endl; std::cout << "Log: " << shader.GetLog() << std::endl;
std::getchar(); std::getchar();
return EXIT_FAILURE; return EXIT_FAILURE;
@ -170,7 +170,7 @@ int main()
return EXIT_FAILURE; return EXIT_FAILURE;
} }
// Une fois le code source de nos shaders chargé, nous pouvons le compiler, afin de le rendre utilisable // Une fois le code source de nos shaders chargé, nous pouvons le compiler, afin de le rendre utilisable
if (!shader.Compile()) if (!shader.Compile())
{ {
std::cout << "Failed to compile shader" << std::endl; std::cout << "Failed to compile shader" << std::endl;
@ -179,9 +179,9 @@ int main()
return EXIT_FAILURE; return EXIT_FAILURE;
} }
// Nos ressources sont chargées, et c'est bien beau, mais il nous faudrait une fenêtre pour afficher tout ça // Nos ressources sont chargées, et c'est bien beau, mais il nous faudrait une fenêtre pour afficher tout ça
// Window représente une fenêtre singulière, pour y effectuer un rendu il nous faut une RenderWindow // Window représente une fenêtre singulière, pour y effectuer un rendu il nous faut une RenderWindow
// Tout d'abord, sa taille, disons celle du bureau divisé par deux // Tout d'abord, sa taille, disons celle du bureau divisé par deux
NzVideoMode mode = NzVideoMode::GetDesktopMode(); NzVideoMode mode = NzVideoMode::GetDesktopMode();
mode.width /= 2; mode.width /= 2;
mode.height /= 2; mode.height /= 2;
@ -189,11 +189,11 @@ int main()
NzString title = "Nazara Demo - AnimatedMesh"; NzString title = "Nazara Demo - AnimatedMesh";
NzRenderWindow window; NzRenderWindow window;
// Le premier argument définit la taille de rendu de la fenêtre (Si elle possède des bordures elle sera légèrement plus grande) // Le premier argument définit la taille de rendu de la fenêtre (Si elle possède une bordure elle sera légèrement plus grande)
// Le deuxième argument est le titre de la fenêtre lors de sa création, vous pouvez le modifier à tout moment via window.SetTitle // Le deuxième argument est le titre de la fenêtre lors de sa création, vous pouvez le modifier à tout moment via window.SetTitle
// Le troisième argument représente la décoration de la fenêtre, sa bordure, ses boutons. // Le troisième argument représente la décoration de la fenêtre, sa bordure, ses boutons.
// Attention que cela permet à la fenêtre d'envoyer des évènements, et de changer sa taille // Attention que cela permet à la fenêtre d'envoyer des évènements, et de changer sa taille
// Par défaut le troisième argument vaut nzWindowStyle_Default (Bordure + Bouton de fermeture + Redimensionnement) // Par défaut le troisième argument vaut nzWindowStyle_Default (Bordure + Bouton de fermeture + Redimensionnement)
if (!window.Create(mode, title, nzWindowStyle_Default)) if (!window.Create(mode, title, nzWindowStyle_Default))
{ {
std::cout << "Failed to create window" << std::endl; std::cout << "Failed to create window" << std::endl;
@ -204,40 +204,40 @@ int main()
// On cache le curseur // On cache le curseur
window.SetCursor(nzWindowCursor_None); window.SetCursor(nzWindowCursor_None);
// Nous limitons les FPS à 100 // Nous limitons les FPS à 100
window.SetFramerateLimit(100); window.SetFramerateLimit(100);
// La matrice de projection définit la transformation du vertice 3D à un point 2D // La matrice de projection définit la transformation du vertice 3D à un point 2D
NzRenderer::SetMatrix(nzMatrixType_Projection, NzMatrix4f::Perspective(NzDegrees(70.f), static_cast<float>(window.GetWidth())/window.GetHeight(), 1.f, 1000.f)); NzRenderer::SetMatrix(nzMatrixType_Projection, NzMatrix4f::Perspective(NzDegrees(70.f), static_cast<float>(window.GetWidth())/window.GetHeight(), 1.f, 1000.f));
// Notre fenêtre est créée, cependant il faut s'occuper d'elle, pour le rendu et les évènements // Notre fenêtre est créée, cependant il faut s'occuper d'elle, pour le rendu et les évènements
NzClock secondClock, updateClock; // Des horloges pour gérer le temps NzClock secondClock, updateClock; // Des horloges pour gérer le temps
unsigned int fps = 0; // Compteur de FPS unsigned int fps = 0; // Compteur de FPS
// Quelques variables pour notre improvisation de physique // Quelques variables pour notre improvisation de physique
float groundPos = drfreak.mesh.GetAABB().GetMinimum().y; // Pas très exact float groundPos = drfreak.mesh.GetAABB().GetMinimum().y; // Pas très exact
NzVector3f modelPos(0.f, groundPos, -50.f); NzVector3f modelPos(0.f, groundPos, -50.f);
NzVector3f modelVel(0.f, 0.f, 0.f); NzVector3f modelVel(0.f, 0.f, 0.f);
NzQuaternionf modelRot(NzEulerAnglesf(0.f, 0.f, 0.f)); // Les angles d'eulers sont bien plus facile à se représenter NzQuaternionf modelRot(NzEulerAnglesf(0.f, 0.f, 0.f)); // Les angles d'eulers sont bien plus facile à se représenter
float speed = 60.f; float speed = 60.f;
// Nous initialisons la matrice // Nous initialisons la matrice
drfreak.matrix = NzMatrix4f::Rotate(modelRot) * NzMatrix4f::Translate(modelPos); drfreak.matrix = NzMatrix4f::Rotate(modelRot) * NzMatrix4f::Translate(modelPos);
// Notre caméra // Notre caméra
NzVector3f camPos(0.f, 25.f, -20.f); NzVector3f camPos(0.f, 25.f, -20.f);
NzEulerAnglesf camRot(0.f, 0.f, 0.f); NzEulerAnglesf camRot(0.f, 0.f, 0.f);
NzMatrix4f camMatrix = NzMatrix4f::Translate(camPos); NzMatrix4f camMatrix = NzMatrix4f::Translate(camPos);
float camSpeed = 2.f; float camSpeed = 2.f;
float sensitivity = 0.5; float sensitivity = 0.5;
// Dernière étape, nos touches // Dernière étape, nos touches
// Chaque touche fera bouger // Chaque touche fera bouger
struct Movement struct Movement
{ {
NzVector3f direction; // La direction NzVector3f direction; // La direction
NzQuaternionf rotation; // La rotation du modèle NzQuaternionf rotation; // La rotation du modèle
}; };
std::map<NzKeyboard::Key, Movement> movements; std::map<NzKeyboard::Key, Movement> movements;
@ -247,39 +247,41 @@ int main()
movements[NzKeyboard::Right] = Movement{NzVector3f(1.f, 0.f, 0.f), NzQuaternionf(NzEulerAnglesf(0.f, -90.f, 0.f))}; movements[NzKeyboard::Right] = Movement{NzVector3f(1.f, 0.f, 0.f), NzQuaternionf(NzEulerAnglesf(0.f, -90.f, 0.f))};
NzKeyboard::Key currentKey = NzKeyboard::Undefined; NzKeyboard::Key currentKey = NzKeyboard::Undefined;
// Quelques booléens // Quelques booléens
bool camMode = true; bool camMode = true;
bool windowOpen = true; bool windowOpen = true;
// On peut commencer la boucle du programme
while (windowOpen) while (windowOpen)
{ {
// Ici nous gérons les évènements // Ici nous gérons les évènements
NzEvent event; NzEvent event;
while (window.PollEvent(&event)) // Avons-nous un évènement dans la file ? while (window.PollEvent(&event)) // Avons-nous un évènement dans la file ?
{ {
// Nous avons un évènement // Nous avons un évènement
switch (event.type) // De quel type est cet évènement ? switch (event.type) // De quel type est cet évènement ?
{ {
case nzEventType_Quit: // L'utilisateur/L'OS nous a demandé de terminer notre exécution case nzEventType_Quit: // L'utilisateur/L'OS nous a demandé de terminer notre exécution
windowOpen = false; // Nous fermons alors la boucle windowOpen = false; // Nous terminons alors la boucle
break; break;
case nzEventType_MouseMoved: case nzEventType_MouseMoved:
{ {
// Si nous ne sommes pas en mode caméra, on ne traite pas l'évènement // Si nous ne sommes pas en mode caméra, on ne traite pas l'évènement
if (!camMode) if (!camMode)
break; break;
// On modifie l'angle de la caméra grâce au déplacement relatif de la souris // On modifie l'angle de la caméra grâce au déplacement relatif de la souris
camRot.yaw = NzNormalizeAngle(camRot.yaw - event.mouseMove.deltaX*sensitivity); camRot.yaw = NzNormalizeAngle(camRot.yaw - event.mouseMove.deltaX*sensitivity);
// Pour éviter les loopings, on restreint les angles // Pour éviter les loopings, on restreint les angles
camRot.pitch = NzClamp(camRot.pitch + event.mouseMove.deltaY*sensitivity, -90.f, 90.f); camRot.pitch = NzClamp(camRot.pitch + event.mouseMove.deltaY*sensitivity, -90.f, 90.f);
// La matrice vue représente les transformations effectuées par la caméra // La matrice vue représente les transformations effectuées par la caméra
// On recalcule la matrice de la caméra et on l'envoie au renderer // On recalcule la matrice de la caméra et on l'envoie au renderer
NzRenderer::SetMatrix(nzMatrixType_View, NzMatrix4f::Translate(camPos) * NzMatrix4f::Rotate(camRot)); NzRenderer::SetMatrix(nzMatrixType_View, NzMatrix4f::Translate(camPos) * NzMatrix4f::Rotate(camRot));
// Pour éviter que le curseur ne sorte de l'écran, nous le renvoyons au centre de la fenêtre // Pour éviter que le curseur ne sorte de l'écran, nous le renvoyons au centre de la fenêtre
NzMouse::SetPosition(window.GetWidth()/2, window.GetHeight()/2, window); NzMouse::SetPosition(window.GetWidth()/2, window.GetHeight()/2, window);
break; break;
} }
@ -288,7 +290,7 @@ int main()
if (event.mouseButton.button == NzMouse::Left) if (event.mouseButton.button == NzMouse::Left)
{ {
// L'utilisateur vient d'appuyer sur le bouton left de la souris // L'utilisateur vient d'appuyer sur le bouton left de la souris
// Nous allons inverser le mode caméra et montrer/cacher le curseur en conséquence // Nous allons inverser le mode caméra et montrer/cacher le curseur en conséquence
if (camMode) if (camMode)
{ {
camMode = false; camMode = false;
@ -303,25 +305,25 @@ int main()
} }
break; break;
case nzEventType_Resized: // L'utilisateur a changé notre taille, le coquin ! case nzEventType_Resized: // L'utilisateur a changé notre taille, le coquin !
NzRenderer::SetViewport(NzRectui(0, 0, event.size.width, event.size.height)); // Adaptons l'affichage NzRenderer::SetViewport(NzRectui(0, 0, event.size.width, event.size.height)); // Adaptons l'affichage
// Il nous faut aussi mettre à jour notre matrice de projection // Il nous faut aussi mettre à jour notre matrice de projection
NzRenderer::SetMatrix(nzMatrixType_Projection, NzMatrix4f::Perspective(NzDegrees(70.f), static_cast<float>(event.size.width)/event.size.height, 1.f, 1000.f)); NzRenderer::SetMatrix(nzMatrixType_Projection, NzMatrix4f::Perspective(NzDegrees(70.f), static_cast<float>(event.size.width)/event.size.height, 1.f, 1000.f));
break; break;
case nzEventType_KeyPressed: case nzEventType_KeyPressed:
if (!event.key.repeated) // Si la touche n'est pas répétée if (!event.key.repeated) // Si la touche n'est pas répétée
{ {
auto it = movements.find(event.key.code); auto it = movements.find(event.key.code);
if (it != movements.end()) if (it != movements.end())
{ {
// Si la touche est une touche de mouvement // Si la touche est une touche de mouvement
SetSequence(drfreak, "run"); // On anime le personnage pour qu'il ait une animation de déplacement SetSequence(drfreak, "run"); // On anime le personnage pour qu'il ait une animation de déplacement
modelRot = it->second.rotation; // On change la rotation du modèle modelRot = it->second.rotation; // On change la rotation du modèle
drfreak.matrix = NzMatrix4f::Rotate(modelRot) * NzMatrix4f::Translate(modelPos); // On recalcule sa matrice drfreak.matrix = NzMatrix4f::Rotate(modelRot) * NzMatrix4f::Translate(modelPos); // On recalcule sa matrice
modelVel = it->second.direction * speed; // On change la vitesse de déplacement modelVel = it->second.direction * speed; // On change la vitesse de déplacement
currentKey = event.key.code; currentKey = event.key.code;
} }
} }
@ -335,18 +337,18 @@ int main()
if (event.key.code == currentKey) if (event.key.code == currentKey)
{ {
SetSequence(drfreak, "stand"); SetSequence(drfreak, "stand");
modelVel = NzVector3f(0.f); // On arrête le déplacement modelVel = NzVector3f(0.f); // On arrête le déplacement
break; break;
} }
break; break;
default: // Les autres évènements, on s'en fiche default: // Les autres évènements, on s'en fiche
break; break;
} }
} }
// On active le shader et paramètrons le rendu // On active le shader et paramètrons le rendu
NzRenderer::SetShader(&shader); NzRenderer::SetShader(&shader);
NzRenderer::Enable(nzRendererParameter_DepthTest, true); NzRenderer::Enable(nzRendererParameter_DepthTest, true);
@ -355,9 +357,9 @@ int main()
if (updateClock.GetMilliseconds() >= 1000/60) // 60 fois par seconde if (updateClock.GetMilliseconds() >= 1000/60) // 60 fois par seconde
{ {
float elapsedTime = updateClock.GetSeconds(); // Le temps depuis la dernière mise à jour float elapsedTime = updateClock.GetSeconds(); // Le temps depuis la dernière mise à jour
// Déplacement de la caméra // Déplacement de la caméra
static const NzVector3f forward(NzVector3f::UnitZ()); static const NzVector3f forward(NzVector3f::UnitZ());
static const NzVector3f left(NzVector3f::UnitX()); static const NzVector3f left(NzVector3f::UnitX());
static const NzVector3f up(NzVector3f::UnitY()); static const NzVector3f up(NzVector3f::UnitY());
@ -365,7 +367,7 @@ int main()
// Notre rotation sous forme de quaternion nous permet de tourner un vecteur // Notre rotation sous forme de quaternion nous permet de tourner un vecteur
NzQuaternionf quaternion(camRot); NzQuaternionf quaternion(camRot);
// Par exemple ici, quaternion * forward nous permet de récupérer le vecteur de la direction "avant" // Par exemple ici, quaternion * forward nous permet de récupérer le vecteur de la direction "avant"
if (NzKeyboard::IsKeyPressed(NzKeyboard::Z)) if (NzKeyboard::IsKeyPressed(NzKeyboard::Z))
camPos += quaternion * forward * camSpeed; camPos += quaternion * forward * camSpeed;
@ -378,15 +380,15 @@ int main()
if (NzKeyboard::IsKeyPressed(NzKeyboard::D)) if (NzKeyboard::IsKeyPressed(NzKeyboard::D))
camPos -= quaternion * left * camSpeed; camPos -= quaternion * left * camSpeed;
// En revanche, ici la hauteur est toujours la même, peu importe notre orientation // En revanche, ici la hauteur est toujours la même, peu importe notre orientation
if (NzKeyboard::IsKeyPressed(NzKeyboard::Space)) if (NzKeyboard::IsKeyPressed(NzKeyboard::Space))
camPos += up * camSpeed; camPos += up * camSpeed;
if (NzKeyboard::IsKeyPressed(NzKeyboard::LControl)) if (NzKeyboard::IsKeyPressed(NzKeyboard::LControl))
camPos -= up * camSpeed; camPos -= up * camSpeed;
// Oui le quaternion et la matrice sont calculés même si la caméra ne bouge pas // Oui le quaternion et la matrice sont calculés même si la caméra ne bouge pas
// C'est une limitation de mon implémentation, qui ne sera pas présente une fois les NzSceneNode intégrés // C'est une limitation de mon implémentation, qui ne sera pas présente une fois les NzSceneNode intégrés
NzRenderer::SetMatrix(nzMatrixType_View, NzMatrix4f::Translate(camPos) * NzMatrix4f::Rotate(camRot)); NzRenderer::SetMatrix(nzMatrixType_View, NzMatrix4f::Translate(camPos) * NzMatrix4f::Rotate(camRot));
// Animation // Animation
@ -397,20 +399,8 @@ int main()
if (modelVel != NzVector3f::Zero()) if (modelVel != NzVector3f::Zero())
{ {
modelPos += modelVel * elapsedTime; modelPos += modelVel * elapsedTime;
/*if (jumping)
{
velocity.y -= 500.f * elapsedTime; // Un simulacre de gravité
if (modelPos.y <= groundPos)
{
// On stoppe net
modelPos.y = groundPos;
velocity.y = 0.f;
jumping = false;
SetSequence(drfreak, "stand");
}
}*/
// Mise à jour de la matrice // Mise à jour de la matrice
drfreak.matrix = NzMatrix4f::Rotate(modelRot) * NzMatrix4f::Translate(modelPos); drfreak.matrix = NzMatrix4f::Rotate(modelRot) * NzMatrix4f::Translate(modelPos);
} }
} }
@ -418,14 +408,14 @@ int main()
// Affichage des meshs // Affichage des meshs
DrawModel(floor); DrawModel(floor);
// Notre Dr. Freak possède des normales, nous pouvons alors culler les faces qu'on ne voit pas // Notre Dr. Freak possède des normales, nous pouvons alors culler les faces qu'on ne voit pas
NzRenderer::Enable(nzRendererParameter_FaceCulling, true); NzRenderer::Enable(nzRendererParameter_FaceCulling, true);
DrawModel(drfreak); DrawModel(drfreak);
NzRenderer::Enable(nzRendererParameter_FaceCulling, false); NzRenderer::Enable(nzRendererParameter_FaceCulling, false);
window.Display(); // Nous mettons à jour l'écran window.Display(); // Nous mettons à jour l'écran
fps++; fps++;
@ -459,16 +449,16 @@ void AnimateModel(AnimatedModel& model, float elapsed)
bool CreateCheckerTexture(NzTexture* texture) bool CreateCheckerTexture(NzTexture* texture)
{ {
NzImage image; NzImage image;
// Nous crééons une image 2D, au format RGBA8 de dimensions 128*128 (8 blocs de 16 pixels de côté) // Nous crééons une image 2D, au format RGBA8 de dimensions 128*128 (8 blocs de 16 pixels de côté)
if (!image.Create(nzImageType_2D, nzPixelFormat_RGBA8, 8*16, 8*16)) if (!image.Create(nzImageType_2D, nzPixelFormat_RGBA8, 8*16, 8*16))
{ {
// Ne devrait pas arriver (La création d'une image ne peut échouer que si l'un des argument est incorrect) // Ne devrait pas arriver (La création d'une image ne peut échouer que si l'un des argument est incorrect)
std::cout << "Failed to create image, this means a bug has been found in Nazara" << std::endl; std::cout << "Failed to create image, this means a bug has been found in Nazara" << std::endl;
return false; return false;
} }
// Pour modifier les pixels, nous pouvons accéder directement à ces derniers avec GetPixels(), ou bien à un pixel // Pour modifier les pixels, nous pouvons accéder directement à ces derniers avec GetPixels(), ou bien à un pixel
// via [Get|Set]PixelColor, mais pour cette occasion nous utiliserons une méthode bien pratique, Fill. // via [Get|Set]PixelColor, mais pour cette occasion nous utiliserons une méthode bien pratique, Fill.
unsigned int blockCountX = image.GetWidth()/16; unsigned int blockCountX = image.GetWidth()/16;
unsigned int blockCountY = image.GetHeight()/16; unsigned int blockCountY = image.GetHeight()/16;
for (unsigned int x = 0; x < blockCountX; ++x) for (unsigned int x = 0; x < blockCountX; ++x)
@ -482,7 +472,7 @@ bool CreateCheckerTexture(NzTexture* texture)
} }
} }
if (!texture->LoadFromImage(image)) // Nous créons notre texture depuis notre image if (!texture->LoadFromImage(image)) // Nous créons notre texture depuis notre image
{ {
// Nous n'avons vraiment pas beaucoup de chance.. // Nous n'avons vraiment pas beaucoup de chance..
std::cout << "Failed to load image" << std::endl; std::cout << "Failed to load image" << std::endl;
@ -490,37 +480,37 @@ bool CreateCheckerTexture(NzTexture* texture)
} }
texture->SetAnisotropyLevel(NzRenderer::GetMaxAnisotropyLevel()); // Un filtrage anisotropique pour la texture texture->SetAnisotropyLevel(NzRenderer::GetMaxAnisotropyLevel()); // Un filtrage anisotropique pour la texture
texture->SetWrapMode(nzTextureWrap_Repeat); // Si les coordonnées de texture dépassent 1.f, la texture sera répétée texture->SetWrapMode(nzTextureWrap_Repeat); // Si les coordonnées de texture dépassent 1.f, la texture sera répétée
return true; return true;
} }
bool CreateFloorMesh(NzMesh* mesh) bool CreateFloorMesh(NzMesh* mesh)
{ {
// Cette fonction créé un mesh statique simpliste pour servir de sol // Cette fonction créé un mesh statique simpliste pour servir de sol
// Nous créons un mesh statique // Nous créons un mesh statique
if (!mesh->Create(nzAnimationType_Static)) if (!mesh->Create(nzAnimationType_Static))
{ {
// L'échec est techniquement impossible mais le moteur étant en constante évolution ... // L'échec est techniquement impossible mais le moteur étant en constante évolution ...
std::cout << "Failed to create mesh" << std::endl; std::cout << "Failed to create mesh" << std::endl;
return false; return false;
} }
// Les vertex declaration ont pour seul but de décrire l'agencement d'un vertex buffer // Les vertex declaration ont pour seul but de décrire l'agencement d'un vertex buffer
// Elles sont composées de VertexElement, chacun décrivant un élément du buffer // Elles sont composées de VertexElement, chacun décrivant un élément du buffer
NzVertexDeclaration* declaration = new NzVertexDeclaration; NzVertexDeclaration* declaration = new NzVertexDeclaration;
// Il y a cinq paramètres différents (stream, usage, type, offset, usageIndex) // Il y a cinq paramètres différents (stream, usage, type, offset, usageIndex)
// -Stream: À quoi serviront les données ? À définir des sommets (nzElementStream_VertexData) ou à l'instancing (nzElementStream_InstancedData) // -Stream: À quoi serviront les données ? À définir des sommets (nzElementStream_VertexData) ou à l'instancing (nzElementStream_InstancedData)
// -Usage: Comment cette donnée doit-elle être envoyée au shader // -Usage: Comment cette donnée doit-elle être envoyée au shader
// -Type: Comment sont stockées ces données ? (Un triplet de float ? Deux double ? ..) // -Type: Comment sont stockées ces données ? (Un triplet de float ? Deux double ? ..)
// -Offset: La position de la donnée dans le buffer (les données sont entrelacées) // -Offset: La position de la donnée dans le buffer (les données sont entrelacées)
// -UsageIndex: Pour les coordonnées de texture, définit l'indice de texture utilisé. // -UsageIndex: Pour les coordonnées de texture, définit l'indice de texture utilisé.
NzVertexElement elements[2]; NzVertexElement elements[2];
elements[0].usage = nzElementUsage_Position; // Notre premier élément sera la position des vertices elements[0].usage = nzElementUsage_Position; // Notre premier élément sera la position des vertices
elements[0].offset = 0; // Celles-ci sont placées au début elements[0].offset = 0; // Celles-ci sont placées au début
elements[0].type = nzElementType_Float3; // Sont composées de trois flottants elements[0].type = nzElementType_Float3; // Sont composées de trois flottants
elements[1].usage = nzElementUsage_TexCoord; elements[1].usage = nzElementUsage_TexCoord;
elements[1].offset = 3*sizeof(float); elements[1].offset = 3*sizeof(float);
@ -528,12 +518,12 @@ bool CreateFloorMesh(NzMesh* mesh)
if (!declaration->Create(elements, 2)) if (!declaration->Create(elements, 2))
{ {
// Nos éléments sont invalides ! // Nos éléments sont invalides !
std::cout << "Failed to create vertex declaration" << std::endl; std::cout << "Failed to create vertex declaration" << std::endl;
return false; return false;
} }
// Nous créons ensuite un buffer de 4 vertices (le second argument précise l'espace pris par chaque vertex), le stockage // Nous créons ensuite un buffer de 4 vertices (le second argument précise l'espace pris par chaque vertex), le stockage
// Et nous indiquons que nous n'y toucherons plus // Et nous indiquons que nous n'y toucherons plus
NzVertexBuffer* buffer = new NzVertexBuffer(4, declaration->GetStride(nzElementStream_VertexData), nzBufferStorage_Hardware, nzBufferUsage_Static); NzVertexBuffer* buffer = new NzVertexBuffer(4, declaration->GetStride(nzElementStream_VertexData), nzBufferStorage_Hardware, nzBufferUsage_Static);
@ -557,8 +547,8 @@ bool CreateFloorMesh(NzMesh* mesh)
10.f, 10.f // UV 10.f, 10.f // UV
}; };
// Afin de modifier un buffer, il nous faut soit le verrouiller (accès bas-niveau), soit le remplir (accès de plus haut niveau) // Afin de modifier un buffer, il nous faut soit le verrouiller (accès bas-niveau), soit le remplir (accès de plus haut niveau)
if (!buffer->Fill(vertices, 0, 4)) // Nous remplissons à partir de l'index 0, et nous envoyons 4 vertices if (!buffer->Fill(vertices, 0, 4)) // Nous remplissons à partir de l'index 0, et nous envoyons 4 vertices
{ {
std::cout << "Failed to fill buffer" << std::endl; std::cout << "Failed to fill buffer" << std::endl;
return false; return false;
@ -576,31 +566,31 @@ bool CreateFloorMesh(NzMesh* mesh)
// On ajoute le submesh au mesh // On ajoute le submesh au mesh
mesh->AddSubMesh(subMesh); mesh->AddSubMesh(subMesh);
// Nos ressources sont notifiées utilisées par le mesh et le submesh, nous pouvons les rendre éphèmères. // Nos ressources sont notifiées utilisées par le mesh et le submesh, nous pouvons les rendre éphèmères.
// Les ressources seront donc automatiquement libérées lorsque plus aucune classe n'en aura besoin // Les ressources seront donc automatiquement libérées lorsque plus aucune classe n'en aura besoin
buffer->SetPersistent(false); buffer->SetPersistent(false);
declaration->SetPersistent(false); declaration->SetPersistent(false);
subMesh->SetPersistent(false); // Pour le submesh, c'est déjà à false à la base subMesh->SetPersistent(false); // Pour le submesh, c'est déjà à false à la base
return true; return true;
} }
void DrawModel(const Model& model) void DrawModel(const Model& model)
{ {
// La matrice world est celle qui représente les transformations du modèle // La matrice world est celle qui représente les transformations du modèle
NzRenderer::SetMatrix(nzMatrixType_World, model.matrix); NzRenderer::SetMatrix(nzMatrixType_World, model.matrix);
NzShader* shader = NzRenderer::GetShader();// On récupère le shader du rendu NzShader* shader = NzRenderer::GetShader();// On récupère le shader du rendu
shader->SendTexture(shader->GetUniformLocation("texture"), &model.texture); shader->SendTexture(shader->GetUniformLocation("texture"), &model.texture);
// Un mesh est divisé en plusieurs submeshes // Un mesh est divisé en plusieurs submeshes
unsigned int subMeshCount = model.mesh.GetSubMeshCount(); unsigned int subMeshCount = model.mesh.GetSubMeshCount();
for (unsigned int i = 0; i < subMeshCount; ++i) for (unsigned int i = 0; i < subMeshCount; ++i)
{ {
// On récupère le submesh // On récupère le submesh
const NzSubMesh* subMesh = model.mesh.GetSubMesh(i); const NzSubMesh* subMesh = model.mesh.GetSubMesh(i);
// On paramètre le Renderer avec ses données // On paramètre le Renderer avec ses données
NzRenderer::SetIndexBuffer(subMesh->GetIndexBuffer()); NzRenderer::SetIndexBuffer(subMesh->GetIndexBuffer());
NzRenderer::SetVertexBuffer(subMesh->GetVertexBuffer()); NzRenderer::SetVertexBuffer(subMesh->GetVertexBuffer());
NzRenderer::SetVertexDeclaration(subMesh->GetVertexDeclaration()); NzRenderer::SetVertexDeclaration(subMesh->GetVertexDeclaration());
@ -612,12 +602,12 @@ void DrawModel(const Model& model)
void SetSequence(AnimatedModel& model, const NzString& sequenceName) void SetSequence(AnimatedModel& model, const NzString& sequenceName)
{ {
// On récupère l'animation du mesh // On récupère l'animation du mesh
const NzAnimation* animation = model.mesh.GetAnimation(); const NzAnimation* animation = model.mesh.GetAnimation();
// Nous nous basons sur l'assertion que la séquence existe (Chose que nous pouvons tester avec HasSequence()) // Nous nous basons sur l'assertion que la séquence existe (Chose que nous pouvons tester avec HasSequence())
model.currentSequence = animation->GetSequence(sequenceName); model.currentSequence = animation->GetSequence(sequenceName);
// Pour avoir une interpolation entre la séquence précédente et celle-ci, nous n'affectons que nextFrame // Pour avoir une interpolation entre la séquence précédente et celle-ci, nous n'affectons que nextFrame
model.nextFrame = model.currentSequence->firstFrame; model.nextFrame = model.currentSequence->firstFrame;
} }

View File

@ -4,17 +4,17 @@
int main() int main()
{ {
// Pour charger des ressources, il est impératif d'initialiser le module utilitaire // Pour charger des ressources, il est impératif d'initialiser le module utilitaire
NzInitializer<NzUtility> utility; NzInitializer<NzUtility> utility;
if (!utility) if (!utility)
{ {
// Ça n'a pas fonctionné, le pourquoi se trouve dans le fichier NazaraLog.log // Ça n'a pas fonctionné, le pourquoi se trouve dans le fichier NazaraLog.log
std::cout << "Failed to initialize Nazara, see NazaraLog.log for further informations" << std::endl; std::cout << "Failed to initialize Nazara, see NazaraLog.log for further informations" << std::endl;
std::getchar(); // On laise le temps de voir l'erreur std::getchar(); // On laise le temps de voir l'erreur
return EXIT_FAILURE; return EXIT_FAILURE;
} }
// Le Renderer n'étant pas chargé, nous devons indiquer que nous désirons un stockage software de notre mesh // Le Renderer n'étant pas chargé, nous devons indiquer que nous désirons un stockage software de notre mesh
NzMeshParams parameters; NzMeshParams parameters;
parameters.storage = nzBufferStorage_Software; parameters.storage = nzBufferStorage_Software;
@ -26,14 +26,14 @@ int main()
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (drfreak.HasAnimation()) // Si le mesh possède des animations if (drfreak.HasAnimation()) // Si le mesh possède des animations
{ {
std::cout << "Mesh has animation" << std::endl; std::cout << "Mesh has animation" << std::endl;
// Un objet NzAnimation représente un ensemble d'informations sur des animations // Un objet NzAnimation représente un ensemble d'informations sur des animations
const NzAnimation* animation = drfreak.GetAnimation(); const NzAnimation* animation = drfreak.GetAnimation();
// Une séquence définit une "action", chaque séquence possède un nom, une frame de départ, une d'arrivée ainsi qu'un framerate // Une séquence définit une "action", chaque séquence possède un nom, une frame de départ, une d'arrivée ainsi qu'un framerate
unsigned int sequenceCount = animation->GetSequenceCount(); unsigned int sequenceCount = animation->GetSequenceCount();
std::cout << sequenceCount << " sequences:" << std::endl; std::cout << sequenceCount << " sequences:" << std::endl;
for (unsigned int i = 0; i < sequenceCount; ++i) for (unsigned int i = 0; i < sequenceCount; ++i)
@ -44,6 +44,6 @@ int main()
std::getchar(); // Une attente pour avoir le temps de lire :-) std::getchar(); // Une attente pour avoir le temps de lire :-)
// Le module utilitaire et le mesh sont déchargés automatiquement // Le module utilitaire et le mesh sont déchargés automatiquement
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@ -11,8 +11,8 @@ You can use it in any kind of commercial/non-commercial applications.
Authors Authors
------- -------
Jérôme "Lynix" Leclercq - main developper (Lynix680@gmail.com) Jérôme "Lynix" Leclercq - main developper (Lynix680@gmail.com)
Rémi "overdrivr" Bèges - developper & helper - NzNoise Module - (remi.beges@laposte.net) Rémi "overdrivr" Bèges - developper & helper - NzNoise Module - (remi.beges@laposte.net)
Install Install
------- -------

View File

@ -1,38 +1,38 @@
Nazara Engine Nazara Engine
============= =============
Nazara Engine est une API rapide, complète, portable et orientée-objet qui peut vous aider dans votre vie de développeur de tous les jours. Nazara Engine est une API rapide, complète, portable et orientée-objet qui peut vous aider dans votre vie de développeur de tous les jours.
Son objectif est de fournir un ensemble de classes utiles : Son noyau dispose de chaînes de caractères unicode, de gestion du système de fichiers, hashs, threads, ... Son objectif est de fournir un ensemble de classes utiles : Son noyau dispose de chaînes de caractères unicode, de gestion du système de fichiers, hashs, threads, ...
Il proposera aussi un ensemble de bibliothèques, comme audio, réseau, physique, moteur de rendu, moteur 2D et 3D. Il proposera aussi un ensemble de bibliothèques, comme audio, réseau, physique, moteur de rendu, moteur 2D et 3D.
Vous pouvez l'utiliser pour toute application commerciale ou non. Vous pouvez l'utiliser pour toute application commerciale ou non.
Auteurs Auteurs
------- -------
Jérôme "Lynix" Leclercq - développeur principal (Lynix680@gmail.com) Jérôme "Lynix" Leclercq - développeur principal (Lynix680@gmail.com)
Rémi "overdrivr" Bèges - développeur & aide - module NzNoise - (remi.beges@laposte.net) Rémi "overdrivr" Bèges - développeur & aide - module NzNoise - (remi.beges@laposte.net)
Installation Installation
------------ ------------
Utilisez le système premake pour construire le projet du moteur, dans le dossier build, pour ensuite compiler le moteur pour votre plateforme. Utilisez le système premake pour construire le projet du moteur, dans le dossier build, pour ensuite compiler le moteur pour votre plateforme.
Utilisation Utilisation
----------- -----------
Vous pouvez lire des tutoriaux sur l'installation, la compilation et l'utilisation à http://wiki.digitalpulsesoftware.com/index.php?title=Nazara:Tutorials Vous pouvez lire des tutoriaux sur l'installation, la compilation et l'utilisation à http://wiki.digitalpulsesoftware.com/index.php?title=Nazara:Tutorials
Contribution Contribution
---------- ----------
N'hésitez pas à contribuer à Nazara Engine en : N'hésitez pas à contribuer à Nazara Engine en :
-Contribuant au wiki à http://wiki.digitalpulsesoftware.com/index.php?title=Nazara -Contribuant au wiki à http://wiki.digitalpulsesoftware.com/index.php?title=Nazara
-Soumettant un patch à GitHub -Soumettant un patch à GitHub
-Postant des suggestions/bugs sur le forum ou sur le tracker GitHub (https://github.com/DigitalPulseSoftware/NazaraEngine/issues) -Postant des suggestions/bugs sur le forum ou sur le tracker GitHub (https://github.com/DigitalPulseSoftware/NazaraEngine/issues)
-Faisant un fork du projet sur GitHub et en proposant vos changements (https://github.com/DigitalPulseSoftware/NazaraEngine/pulls) -Faisant un fork du projet sur GitHub et en proposant vos changements (https://github.com/DigitalPulseSoftware/NazaraEngine/pulls)
-Parlant du Nazara Engine à d'autres personnes -Parlant du Nazara Engine à d'autres personnes
-Faisant n'importe quoi d'autre qui pourrait nous aider. -Faisant n'importe quoi d'autre qui pourrait nous aider.
Liens Liens
@ -42,5 +42,5 @@ Site web : http://www.digitalpulsesoftware.com
Wiki : http://wiki.digitalpulsesoftware.com/index.php?title=Nazara Wiki : http://wiki.digitalpulsesoftware.com/index.php?title=Nazara
Forum : http://forum.digitalpulsesoftware.com Forum : http://forum.digitalpulsesoftware.com
Merci à Merci à
-RafBill: Recherche de bugs -RafBill: Recherche de bugs