Skip to content

spinning_cube

Jan Boon edited this page May 22, 2023 · 8 revisions

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.

Set Up the Camera

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();
 
    // ...
}

Set Up the Lighting

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();
 
    // ...
}

Draw the Cube

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();

    // ...
}

Putting It All Together

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.

Animating the Cube

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.

Clone this wiki locally