Adding lights

This is a follow up on the Boilerplate code tutorial. We are going to extend that piece of code to add lights to our scene. Not just some lights, but 56 lights that rotate around the 125 cubes we were rendering in the previous tutorial. The result will look something like this:

Find the code where we add the cubes to the scene, then add the following lines of code:

    /**
     * Create the lights.
     */
    DreadedPE::Cube* small_cube = new DreadedPE::Cube(0.1f);
    for (int i = -2; i < 5; ++i)
    {
        DiscoballNode* dn = new DiscoballNode(scene_manager, &scene_manager.getRoot(), glm::translate(glm::mat4(1.0f), glm::vec3(0, i, 0)));
        scene_manager.addUpdateableEntity(*dn);
        for (int j = 0; j < 8; ++j)
        {
            DreadedPE::SceneNode* node = new DreadedPE::SceneNode(scene_manager, dn, glm::translate(glm::rotate(glm::mat4(1.0f),  glm::radians360.0f / 8.0f * j), glm::vec3(0, 1, 0)), glm::vec3(0, 0, 10)));
            DreadedPE::PointLight* light = new DreadedPE::PointLight(scene_manager, 30.0f, glm::vec3(0, 0, 0), glm::vec3(1, 1, 1), glm::vec3(0, 0, 0), 1, 0.1, 0.001, 0.1f, 60.0f);
            DreadedPE::SceneLeafLight* light_leaf = new DreadedPE::SceneLeafLight(*node, NULL, *light);

            DreadedPE::SceneNode* cube_node = new DreadedPE::SceneNode(scene_manager, node, glm::translate(glm::mat4(1.0f), glm::vec3(0, 0, 1)));
            DreadedPE::SceneLeafModel* cube_leaf = new DreadedPE::SceneLeafModel(*cube_node, NULL, *small_cube, *wfl_material, DreadedPE::BasicShadowShader::getShader(), false, false);
        }
    }

This adds 7 * 8 = 56 lights to the scene. The lights are evenly spaced in 7 circles and rotate around. The rotating is done by the instance DiscoballNode. This is a custom SceneNode that rotates around. Here is the code for it:

DiscoballNode.h

#ifndef DEMO_MULTIPLE_LIGHTS_DISCOBALLNODE_H
#define DEMO_MULTIPLE_LIGHTS_DISCOBALLNODE_H

#include <glm/glm.hpp>
#include <dpengine/scene/SceneNode.h>

namespace DreadedPE
{
    class SceneManager;
    class SceneNode;
};

class DiscoballNode : public DreadedPE::SceneNode
{
public:
    DiscoballNode(DreadedPE::SceneManager& scene_manager, DreadedPE::SceneNode* parent, const glm::mat4& transformation, const glm::vec3& scaling = glm::vec3(1, 1, 1), bool init_children = true);

    // Spin it!
    void prepare(float dt);
private:

};

#endif

This extends the SceneNode of the engine and overwrites the 'prepare' function. This function is called at fixed time steps and updates the transitions of this node.

DiscoballNode.cpp

#include "DiscoballNode.h"

#include <glm/gtc/matrix_transform.hpp>

DiscoballNode::DiscoballNode(DreadedPE::SceneManager & scene_manager, DreadedPE::SceneNode * parent, const glm::mat4 & transformation, const glm::vec3 & scaling, bool init_children)
    : DreadedPE::SceneNode(scene_manager, parent, transformation, scaling, init_children)
{

}

void DiscoballNode::prepare(float dt)
{
    local_transformation_ = glm::rotate(local_transformation_, dt *  glm::radians(20.0f), glm::vec3(0, 1, 0));
    DreadedPE::SceneNode::prepare(dt);
}

As you can see, the only thing that is different from a normal SceneNode is that we update the local transformation of this node. By calling DreadedPE::SceneNode::prepare(dt); it automatically updates the global transition node.

The result is a cluster of lights illuminating the scene we created before.