#include "Lights.h" #include GLuint Light::count = 0; // количество используемых источников (должно быть <= MAX_LIGHTS) LightData Light::data[MAX_LIGHTS]; // Массив данных по источникам света Light Light::lights[MAX_LIGHTS]; // Массив источников-узлов сцены // возвращает размер буфера в байтах int Light::getUBOsize() { return sizeof(LightData) * MAX_LIGHTS + sizeof(GLuint); } // Загрузка данных в буфер void Light::upload(UBO& lights_data) { GLuint LightDataSize = sizeof(LightData); // Одного экземпляра структуры LightData int first = MAX_LIGHTS, last = -1; // Начало и конец диапазона загрузки источников if (count) { for (int i = 0; i < MAX_LIGHTS; i++) { lights[i].recalcMatrices(); // Пересчитаем матрицы по необходимости (проверка внутри метода) // Если требуется загрузка if (lights[i].uploadReq) { lights[i].toData(); // Перевод ноды в данные для шейдера // Определение диапазона загрузки if (first > lights[i].index) first = lights[i].index; if (last < lights[i].index) last = lights[i].index; lights[i].uploadReq = false; // Сброс флага } } // Если есть что загрузить (определен диапазон) if (last > -1) lights_data.loadSub(data + first, LightDataSize*(last - first +1), LightDataSize*(first)); // Загрузка данных об источниках } // Загружаем кол-во источников lights_data.loadSub(&count, sizeof(count), LightDataSize*MAX_LIGHTS); } // Метод пересчета матрицы трансформации по необходимости, должен сбрасывать флаг changed void Light::recalcMatrices() { // Если были изменения - необходимо загрузить данные if (changed || parent_changed) uploadReq = true; // Выполняем вычисление матриц методом родительского класса Node::recalcMatrices(); } // Константный доступ к цвету const glm::vec3& Light::c_color() const { return color; } // Неконстантная ссылка для изменений цвета glm::vec3& Light::e_color() { uploadReq = true; return color; } // Проверка что не взаимодествуем с пустым источником void Light::check_id() { if (index < 0 || index >= count) throw std::runtime_error("Попытка использовать ссылку на пустой или некорректный источник"); } // Преобразует информацию об источнике в структуру LightData void Light::toData() { check_id(); // Проверка на работу с корректным индексом data[index].position = glm::vec3(result_transform[3]); // Позиция из матрицы трансформации data[index].color = color; // Цвет } // Возвращает ссылку на новый источник света Light& Light::getNew() { Light& refNew = findByIndex(-1); refNew.index = count++; refNew.uploadReq = true; return refNew; } // Уничтожает источник света void Light::destroy() { check_id(); // Проверка на работу с корректным индексом // Если удаляемый элемент не последний if (count-1 != index) { // Найдем элемент для замены Light& replace = findByIndex(--count); replace.uploadReq = true; // Требуется загрузить данные replace.index = index; // Заменяем индекс данных } operator=(Light()); // Обнулим источник путем замены на новый } // Возвращает ссылку на источник с нужным индексом Light& Light::findByIndex(GLuint index) { // Если нет источников - возвращаем нулевой if (!count) return lights[0]; // Цикл по перебору источников for (int i = 0; i < MAX_LIGHTS; i++) if (lights[i].index == index) return lights[i]; throw std::runtime_error("Запрашиваемый источник освещения не найден, либо достигнут лимит"); } // Конструктор без параметров Light::Light() : Node(), index(-1), uploadReq(false), color(1.0f) { } // Оператор присваивания Light& Light::operator=(const Light& other) { // Проверка на самоприсваивание if (this != &other) { index = other.index; // Переносим индекс uploadReq = other.uploadReq; // Необходимость загрузки color = other.color; Node::operator=(other); } return *this; } Light::~Light() { }