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:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user