-
Notifications
You must be signed in to change notification settings - Fork 94
spinning_cube
title: Spinning Cube description: published: true date: 2023-05-22T19:38:21.350Z tags: editor: markdown dateCreated: 2023-05-22T19:38:21.350Z
TODO: This tutorial has been autogenerated and is pending developer review. {.is-danger}
In this tutorial, we will use our previously initialized NeL application context and 3D driver to render a spinning cube on the screen.
First, include the header file needed to use the camera class:
#include <nel/3d/u_camera.h>
Next, in your CMyGame
class, add a member variable for the camera:
class CMyGame : public IEventListener
{
public:
CMyGame();
~CMyGame();
void run();
virtual void operator()(const CEvent &event) NL_OVERRIDE;
private:
// Graphics driver
NL3D::UDriver *m_Driver;
bool m_CloseWindow;
NL3D::UCamera *m_Camera; // The camera
};
Then, initialize the camera in the CMyGame
constructor. The camera will be responsible for rendering the cube on the screen:
CMyGame::CMyGame()
: m_CloseWindow(false)
{
// ...
// Initialize the camera
m_Camera = m_Driver->createCamera();
if (!m_Camera)
{
nlerror("Failed to create camera");
return;
}
// Set the camera to the current viewport
m_Driver->setViewport(*m_Camera);
// ...
}
Remember to release the camera in the destructor to free resources:
CMyGame::~CMyGame()
{
// ...
// Release the camera
m_Camera->release();
// ...
}
Include the header for the light class:
#include <nel/3d/u_light.h>
Add a member variable for the light to your CMyGame
class:
class CMyGame : public IEventListener
{
public:
CMyGame();
~CMyGame();
void run();
virtual void operator()(const CEvent &event) NL_OVERRIDE;
private:
// Graphics driver
NL3D::UDriver *m_Driver;
bool m_CloseWindow;
NL3D::UCamera *m_Camera; // The camera
NL3D::ULight *m_Light; // The light
};
Then, initialize the light in the CMyGame
constructor. Set its position and color:
CMyGame::CMyGame()
: m_CloseWindow(false)
{
// ...
// Create the light
m_Light = m_Driver->createLight();
if (!m_Light)
{
nlerror("Failed to create light");
return;
}
// Set the light's position
m_Light->setPos(NLMISC::CVector(0, 0, 10));
// Set the light's color
m_Light->setAmbient(NLMISC::CRGBA(255, 255, 255));
// ...
}
Don't forget to release the light in the destructor:
CMyGame::~CMyGame()
{
// ...
// Release the light
m_Light->release();
// ...
}
To draw the cube, you'll need to set up its vertices and triangles. Each triangle consists of three vertices, and each face of the cube consists of two triangles. Since a cube has six faces, it will have 12 triangles.
Include the necessary headers:
#include <nel/3d/u_shape_bank.h>
#include <nel/3d/u_material.h>
#include <nel/
3d/u_instance.h>
Then, add member variables for the cube:
class CMyGame : public IEventListener
{
public:
CMyGame();
~CMyGame();
void run();
virtual void operator()(const CEvent &event) NL_OVERRIDE;
private:
// Graphics driver
NL3D::UDriver *m_Driver;
bool m_CloseWindow;
NL3D::UCamera *m_Camera; // The camera
NL3D::ULight *m_Light; // The light
NL3D::UShapeBank *m_ShapeBank; // The shape bank
NL3D::UInstance m_Cube; // The cube
};
Next, initialize the shape bank and the cube:
CMyGame::CMyGame()
: m_CloseWindow(false)
{
// ...
// Initialize the shape bank
m_ShapeBank = m_Driver->createShapeBank();
if (!m_ShapeBank)
{
nlerror("Failed to create shape bank");
return;
}
// Load the cube shape
m_Cube = m_ShapeBank->loadShape("cube.shape");
// ...
}
To draw the cube in the run()
function, use the setModelMatrix()
function to set the position and rotation of the cube. Then call render()
:
void CMyGame::run()
{
// ...
// Update the cube's position and rotation
m_Cube.setModelMatrix(NLMISC::CMatrix::identity);
// Render the cube
m_Cube.render();
// ...
}
Now, if you compile and run your project, you should see a cube rendered on the screen. If you want the cube to rotate, you can update the model matrix with a rotation matrix each frame.
In order to create the illusion of a spinning cube, we'll need to incrementally rotate the cube each frame.
First, include the necessary headers for dealing with time:
#include <nel/misc/time_nl.h>
Add a member variable to keep track of the last frame's time:
class CMyGame : public IEventListener
{
public:
CMyGame();
~CMyGame();
void run();
virtual void operator()(const CEvent &event) NL_OVERRIDE;
private:
// Graphics driver
NL3D::UDriver *m_Driver;
bool m_CloseWindow;
NL3D::UCamera *m_Camera; // The camera
NL3D::ULight *m_Light; // The light
NL3D::UShapeBank *m_ShapeBank; // The shape bank
NL3D::UInstance m_Cube; // The cube
NLMISC::TTime m_LastFrameTime; // Last frame time
};
Initialize m_LastFrameTime
in the constructor:
CMyGame::CMyGame()
: m_CloseWindow(false), m_LastFrameTime(NLMISC::CTime::getLocalTime())
{
// ...
}
Update the cube's position and rotation in the run()
function. You should calculate the time difference between the current frame and the last frame, and use this to determine how much the cube should rotate.
For simplicity, let's make it spin around the Y-axis:
void CMyGame::run()
{
// ...
// Calculate elapsed time since last frame
NLMISC::TTime currentTime = NLMISC::CTime::getLocalTime();
float deltaTime = (float)((currentTime - m_LastFrameTime) * 0.001);
m_LastFrameTime = currentTime;
// Calculate rotation amount
float rotationAmount = deltaTime * 90.0f; // Rotate 90 degrees per second
// Update the cube's position and rotation
NLMISC::CMatrix matrix = m_Cube.getModelMatrix();
matrix.rotateY(rotationAmount * (NLMISC::Pi / 180.0f)); // Pi / 180 converts degrees to radians
m_Cube.setModelMatrix(matrix);
// Render the cube
m_Cube.render();
// ...
}
Now, if you compile and run your project, you should see a cube that continuously spins around its Y-axis.
In the next tutorial, we will introduce how to load and animate complex 3D models.