ICT290 / src / engine / light.h
light.h
Raw
#pragma once
#include <glm/glm.hpp>

/**
 * @struct SpotLight
 * @brief A struct used to store all the values related to implementing an
 * openGL spotlight. Stored with Light to reduce confusion, instead of having
 * excess members.
 *
 * @author Chase Percy
 *
 */
struct SpotLight {
    float cutoff{90};                    // Angle of the cone light, 0 - 180
    float direction[4] = {0, 0, -1, 1};  // direction the light is traveling
    float exponent{15};                  // The strength of the light
};

/**
 * @class Light
 * @brief Wraps the openGL lighting implementation with simple public members
 * that can be easily updated at runtime. Each Light must be explicitly defined
 * with a constructor and each light has a unique ID.
 *
 * @warning As per the OpenGL spec, only 8 Lights can be active at once. An
 * assert will trip if a light with a invalid ID is enabled.
 *
 * @author Chase Percy
 *
 */
class Light {
   public:
    float m_position[4] = {0, 1, 0, 1};        /// Default starting location
    float m_ambient[4] = {0.f, 0.f, 0.f, 1};   /// Default ambient property
    float m_diffuse[4] = {1.f, 1.f, 1.f, 1};   /// Default diffuse property
    float m_specular[4] = {1.f, 1.f, 1.f, 1};  /// Default specular property
    bool m_isSpotLight{false};  /// True if this light is a spotlight
    SpotLight m_spotLight;  /// A SpotLight member to store all spotlight data

    Light() = default;
    ~Light() = default;
    explicit Light(short id) : m_lightID(id){};
    Light(short id, const glm::vec3& position);
    Light(short id, float x, float y, float z);

    /**
     * Enables a light by calling the appropriate openGL calls, providing the
     * specified values for ambient, diffuse, specular, and position.
     */
    void enable();

    /**
     * Disables a light by calling the appropriate openGL calls.
     */
    void disable();

    /**
     * Returns the current status of a light.
     * @return true if active, false otherwise.
     */
    bool isEnabled() const { return m_enabled; }

    /**
     * Takes a glm::vec3 and updates a GL_LIGHT0 + lightID's location.
     * @param location the location to move the light to.
     */
    void setPosition(const glm::vec3& location);

    /**
     * Sets the position of a light source.
     * @param x the x coordinate.
     * @param y the y coordinate.
     * @param z the z coordinate.
     */
    void setPosition(float x, float y, float z);

    /**
     * Takes a glm::vec3 and updates a GL_LIGHT0 + lightID's direction.
     * @param direction the direction to point the light to.
     */
    void setSpotDirection(const glm::vec3& direction);

    /**
     * Sets a spot light direction.
     * @param x the x coordinate.
     * @param y the y coordinate.
     * @param z the z coordinate.
     */
    void setSpotDirection(float x, float y, float z);

    /**
     * Draws a light at its current location with its current settings.
     */
    void draw() const;

    /**
     * Converts the position float array into a glm vec3 and returns it.
     * @return the position of the light.
     */
    glm::vec3 getPositionVec3();

    /**
     * Disable all lighting that is active and disable lighting. Doesn't alter
     * m_enabled for individual lights.
     */
    static void disableLighting();

    /**
     * Enable lighting and set GL_COLOR_MATERIAL
     */
    static void enableLighting();

    /**
     * Sets the direction of a spot light towards a certain coord.
     * @param rotateTo the location to rotate towards.
     */
    void setSpotDirectionToLocation(const glm::vec3& rotateTo);

   private:
    short m_lightID{0};     /// Default light id, use: GL_LIGHT + light.lightID
    bool m_enabled{false};  /// determines if a light is active or not.
};