Nazara now use meters as units

Added scale mesh parameter
Added smooth camera to FirstScene demo


Former-commit-id: b3985e10d84512e3b32f2569ac034ba63ace589a
This commit is contained in:
Lynix
2013-06-13 19:29:59 +02:00
parent 3294f18608
commit bb99d044bb
6 changed files with 109 additions and 22 deletions

View File

@@ -4,6 +4,9 @@
#include <Nazara/Utility.hpp> // Module utilitaire
#include <iostream>
// Petite fonction permettant de rendre le déplacement de la caméra moins ridige
NzVector3f DampedString(const NzVector3f& currentPos, const NzVector3f& targetPos, float frametime, float springStrength = 3.f);
int main()
{
// Pour commencer, nous initialisons le module Graphique, celui-ci va provoquer l'initialisation (dans l'ordre),
@@ -24,7 +27,7 @@ int main()
// Une scène représente tout ce qui est visible par une ou plusieurs caméras.
// La plupart du temps vous n'aurez pas besoin de plus d'une scène, mais cela peut se révéler utile pour mieux
// organiser et optimiser le rendu.
// Par exemple, une pièce contenant une télévision, laquelle affichant des images provenant d'une NzCamera
// Par exemple, une pièce contenant une télévision, laquelle affichant des images provenant d'une Camera
// Le rendu sera alors plus efficace en créant deux scènes, une pour la pièce et l'autre pour les images de la télé.
// Cela diminuera le nombre de SceneNode à gérer pour chaque scène, et vous permettra même de ne pas afficher la scène
// affichée dans la télé si cette dernière n'est pas visible dans la première scène.
@@ -70,9 +73,19 @@ int main()
// Nous choisirons ici un vaisseau spatial (Quoi de mieux pour une scène spatiale ?)
NzModel spaceship;
// Une structure permettant de paramétrer le chargement des modèles
NzModelParameters params;
// Le format OBJ ne précise aucune échelle pour ses données, contrairement à Nazara (une unité = un mètre).
// Comme le vaisseau est très grand (Des centaines de mètres de long), nous allons le rendre plus petit
// pour les besoins de la démo.
// Ce paramètre sert à indiquer la mise à l'échelle désirée lors du chargement du modèle.
params.mesh.scale.Set(0.01f); // Un centième de la taille originelle
// On charge ensuite le modèle depuis son fichier
// Le moteur va charger le fichier et essayer de retrouver les fichiers associés (comme les matériaux, textures, ...)
if (!spaceship.LoadFromFile("resources/Spaceship/spaceship.obj"))
if (!spaceship.LoadFromFile("resources/Spaceship/spaceship.obj", params))
{
std::cout << "Failed to load spaceship" << std::endl;
std::getchar();
@@ -84,7 +97,7 @@ int main()
// Pour cela, nous devons accéder au mesh (maillage 3D)
NzMesh* mesh = spaceship.GetMesh();
std::cout << mesh->GetVertexCount() << " vertices" << std::endl;
std::cout << mesh->GetVertexCount() << " sommets" << std::endl;
std::cout << mesh->GetTriangleCount() << " triangles" << std::endl;
// En revanche, le format OBJ ne précise pas l'utilisation d'une normal map, nous devons donc la charger manuellement
@@ -102,7 +115,7 @@ int main()
// Il nous reste à attacher le modèle à la scène, ce qui se fait simplement via cet appel
spaceship.SetParent(scene);
// Et voilà, à partir de maintenant le modèle fait partie de la "hiérarchie de la scène", et sera donc rendu avec la scène
// Et voilà, à partir de maintenant le modèle fait partie de la hiérarchie de la scène, et sera donc rendu avec cette dernière
// Nous avons besoin également d'une caméra, pour des raisons évidentes, celle-ci sera à l'écart du modèle
// regardant dans sa direction.
@@ -111,7 +124,7 @@ int main()
NzEulerAnglesf camAngles(0.f, -20.f, 0.f);
NzCamera camera;
camera.SetPosition(0.f, 25.f, 200.f); // On place la caméra à l'écart
camera.SetPosition(0.f, 0.25f, 2.f); // On place la caméra à l'écart
camera.SetRotation(camAngles);
camera.SetParent(scene); // On l'attache également à la scène
@@ -122,7 +135,7 @@ int main()
camera.SetZFar(5000.f);
// La distance entre l'oeil et le plan rapproché (0 est une valeur interdite car la division par zéro l'est également)
camera.SetZNear(1.f);
camera.SetZNear(0.1f);
// Attention que le ratio entre les deux (zFar/zNear) doit rester raisonnable, dans le cas contraire vous risquez un phénomène
// de "Z-Fighting" (Impossibilité de déduire quelle surface devrait apparaître en premier) sur les surfaces éloignées.
@@ -198,6 +211,10 @@ int main()
// Ainsi qu'un compteur de FPS improvisé
unsigned int fps = 0;
// Quelques variables de plus pour notre caméra
bool smoothMovement = true;
NzVector3f targetPos = camera.GetPosition();
// Début de la boucle de rendu du programme
while (window.IsOpen())
{
@@ -210,7 +227,7 @@ int main()
case nzEventType_MouseMoved: // La souris a bougé
{
// Gestion de la caméra free-fly (Rotation)
float sensitivity = 0.8f; // Sensibilité de la souris
float sensitivity = 0.3f; // Sensibilité de la souris
// On modifie l'angle de la caméra grâce au déplacement relatif sur X de la souris
camAngles.yaw = NzNormalizeAngle(camAngles.yaw - event.mouseMove.deltaX*sensitivity);
@@ -234,6 +251,16 @@ int main()
case nzEventType_KeyPressed: // Une touche a été pressée !
if (event.key.code == NzKeyboard::Key::Escape)
window.Close();
else if (event.key.code == NzKeyboard::F1)
{
if (smoothMovement)
{
targetPos = camera.GetPosition();
smoothMovement = false;
}
else
smoothMovement = true;
}
break;
default:
@@ -244,39 +271,44 @@ int main()
// Mise à jour (Caméra)
if (updateClock.GetMilliseconds() >= 1000/60) // 60 fois par seconde
{
// Gestion de la caméra free-fly (Déplacement)
float cameraSpeed = 300.f; // Unités par seconde
// Le temps écoulé depuis la dernière fois que ce bloc a été exécuté
float elapsedTime = updateClock.GetSeconds();
// Vitesse de déplacement de la caméra
float cameraSpeed = 3.f * elapsedTime; // Trois mètres par seconde
// Si la touche espace est enfoncée, notre vitesse de déplacement est multipliée par deux
if (NzKeyboard::IsKeyPressed(NzKeyboard::Space))
cameraSpeed *= 2.f;
// Move agit par défaut dans l'espace local de la caméra, autrement dit la rotation est prise en compte
// Pour que nos déplacement soient liés à la rotation de la caméra, nous allons utiliser
// les directions locales de la caméra
// Si la flèche du haut ou la touche Z (vive ZQSD) est pressée, on avance
if (NzKeyboard::IsKeyPressed(NzKeyboard::Up) || NzKeyboard::IsKeyPressed(NzKeyboard::Z))
camera.Move(NzVector3f::Forward() * cameraSpeed * elapsedTime);
targetPos += camera.GetForward() * cameraSpeed;
// Si la flèche du bas ou la touche S est pressée, on recule
if (NzKeyboard::IsKeyPressed(NzKeyboard::Down) || NzKeyboard::IsKeyPressed(NzKeyboard::S))
camera.Move(NzVector3f::Backward() * cameraSpeed * elapsedTime);
targetPos += camera.GetBackward() * cameraSpeed;
// Etc...
if (NzKeyboard::IsKeyPressed(NzKeyboard::Left) || NzKeyboard::IsKeyPressed(NzKeyboard::Q))
camera.Move(NzVector3f::Left() * cameraSpeed * elapsedTime);
targetPos += camera.GetLeft() * cameraSpeed;
// Etc...
if (NzKeyboard::IsKeyPressed(NzKeyboard::Right) || NzKeyboard::IsKeyPressed(NzKeyboard::D))
camera.Move(NzVector3f::Right() * cameraSpeed * elapsedTime);
targetPos += camera.GetRight() * cameraSpeed;
// Majuscule pour monter, mais dans l'espace global (Sans tenir compte de la rotation)
// Majuscule pour monter, notez l'utilisation d'une direction globale (Non-affectée par la rotation)
if (NzKeyboard::IsKeyPressed(NzKeyboard::LShift) || NzKeyboard::IsKeyPressed(NzKeyboard::RShift))
camera.Move(NzVector3f::Up() * cameraSpeed * elapsedTime, nzCoordSys_Global);
targetPos += NzVector3f::Up() * cameraSpeed;
// Contrôle (Gauche ou droite) pour descendre dans l'espace global, etc...
if (NzKeyboard::IsKeyPressed(NzKeyboard::LControl) || NzKeyboard::IsKeyPressed(NzKeyboard::RControl))
camera.Move(NzVector3f::Down() * cameraSpeed * elapsedTime, nzCoordSys_Global);
targetPos += NzVector3f::Down() * cameraSpeed;
camera.SetPosition((smoothMovement) ? DampedString(camera.GetPosition(), targetPos, elapsedTime) : targetPos, nzCoordSys_Global);
// On relance l'horloge
updateClock.Restart();
@@ -332,3 +364,36 @@ int main()
return EXIT_SUCCESS;
}
NzVector3f DampedString(const NzVector3f& currentPos, const NzVector3f& targetPos, float frametime, float springStrength)
{
// Je ne suis pas l'auteur de cette fonction
// Je l'ai reprise du programme "Floaty Camera Example" et adaptée au C++
// Trouvé ici: http://nccastaff.bournemouth.ac.uk/jmacey/RobTheBloke/www/opengl_programming.html#4
// Tout le mérite revient à l'auteur (Qui me permettra ainsi d'améliorer les démos, voire même le moteur)
// calculate the displacement between the target and the current position
NzVector3f displacement = targetPos - currentPos;
// whats the distance between them?
float displacementLength = displacement.GetLength();
// Stops small position fluctuations (integration errors probably - since only using euler)
if (displacementLength < 0.0001f)
return currentPos;
float invDisplacementLength = 1.f/displacementLength;
const float dampConstant = 0.000065f; // Something v.small to offset 1/ displacement length
// the strength of the spring increases the further away the camera is from the target.
float springMagitude = springStrength*displacementLength + dampConstant*invDisplacementLength;
// Normalise the displacement and scale by the spring magnitude
// and the amount of time passed
float scalar = invDisplacementLength * springMagitude * frametime;
displacement *= scalar;
// move the camera a bit towards the target
return currentPos + displacement;
}