diff --git a/engine/imgui.ini b/engine/imgui.ini deleted file mode 100644 index 63969bb..0000000 --- a/engine/imgui.ini +++ /dev/null @@ -1,8 +0,0 @@ -[Window][Debug##Default] -Pos=60,60 -Size=400,400 - -[Window][Menu] -Pos=60,60 -Size=107,48 - diff --git a/engine/include/Configuration.hpp b/engine/include/Configuration.hpp index e070b8a..b726cfb 100644 --- a/engine/include/Configuration.hpp +++ b/engine/include/Configuration.hpp @@ -14,8 +14,15 @@ class Configuration { Window window; Camera camera; Group group; + std::vector lights; + Configuration() = default; Configuration(const Window &window, const Camera &camera, const Group &group); + Configuration(const Window &window, const Camera &camera, const Group &group, + const std::vector &lights); + + bool addLight(const Light &light); + bool removeLight(int index); // std::string toString(); }; diff --git a/engine/include/light.hpp b/engine/include/light.hpp new file mode 100644 index 0000000..3a9ade1 --- /dev/null +++ b/engine/include/light.hpp @@ -0,0 +1,46 @@ +#ifndef LIGHT_HPP +#define LIGHT_HPP + +extern "C" { +#include +#ifdef __APPLE_CC__ +#include +#else +#include +#endif +} +#include +#include + +enum LightType { DIRECTIONAL, POINT, SPOT }; + +typedef struct { + LightType type; + glm::vec4 position; + glm::vec4 direction; + float cutoff; +} Light; + +Light createDirectionLight(glm::vec4 direction); + +Light createPointLight(glm::vec4 position); + +Light createSpotLight(glm::vec4 position, glm::vec4 direction, float cutoff); + +void setupLights(std::vector lights); + +typedef struct { + glm::vec4 ambient; + glm::vec4 diffuse; + glm::vec4 specular; + glm::vec4 emission; + float shininess; +} Material; + +Material createMaterial(glm::vec4 ambient, glm::vec4 diffuse, + glm::vec4 specular, glm::vec4 emission, + float shininess); + +void setupMaterial(Material m); + +#endif // LIGHT_HPP diff --git a/engine/include/model.hpp b/engine/include/model.hpp index c8d2b18..fc1f55f 100644 --- a/engine/include/model.hpp +++ b/engine/include/model.hpp @@ -15,6 +15,7 @@ extern "C" { #include #include +#include "light.hpp" #include "utils.hpp" #include "vertex.hpp" @@ -30,6 +31,7 @@ class Model { std::vector ibo; int id; bool initialized = false; + Material material; Model(); Model(std::string filename, std::vector points); diff --git a/engine/src/Configuration.cpp b/engine/src/Configuration.cpp index 5bc0e0f..7f85219 100644 --- a/engine/src/Configuration.cpp +++ b/engine/src/Configuration.cpp @@ -8,4 +8,32 @@ Configuration::Configuration(const Window &window, const Camera &camera, this->window = window; this->camera = camera; this->group = group; + this->lights = {}; +} + +Configuration::Configuration(const Window &window, const Camera &camera, + const Group &group, + const std::vector &lights) { + this->window = window; + this->camera = camera; + this->group = group; + this->lights = lights; +} + +bool Configuration::addLight(const Light &light) { + if (this->lights.size() > 8) { + return false; + } + + this->lights.push_back(light); + return true; +} + +bool Configuration::removeLight(int index) { + if (index < 0 || index >= this->lights.size()) { + return false; + } + + this->lights.erase(this->lights.begin() + index); + return true; } diff --git a/engine/src/light.cpp b/engine/src/light.cpp new file mode 100644 index 0000000..fb5b826 --- /dev/null +++ b/engine/src/light.cpp @@ -0,0 +1,63 @@ +#include "light.hpp" + +Light createDirectionLight(glm::vec4 direction) { + Light light; + light.type = DIRECTIONAL; + light.direction = direction; + return light; +} + +Light createPointLight(glm::vec4 position) { + Light light; + light.type = POINT; + light.position = position; + return light; +} + +Light createSpotLight(glm::vec4 position, glm::vec4 direction, float cutoff) { + Light light; + light.type = SPOT; + light.position = position; + light.direction = direction; + light.cutoff = cutoff; + return light; +} + +Material createMaterial(glm::vec4 ambient, glm::vec4 diffuse, + glm::vec4 specular, glm::vec4 emission, + float shininess) { + Material material; + material.ambient = ambient; + material.diffuse = diffuse; + material.specular = specular; + material.emission = emission; + material.shininess = shininess; + return material; +} + +void setupMaterial(Material m) { + glMaterialfv(GL_FRONT, GL_AMBIENT, glm::value_ptr(m.ambient)); + glMaterialfv(GL_FRONT, GL_DIFFUSE, glm::value_ptr(m.diffuse)); + glMaterialfv(GL_FRONT, GL_SPECULAR, glm::value_ptr(m.specular)); + glMaterialfv(GL_FRONT, GL_EMISSION, glm::value_ptr(m.emission)); + glMaterialf(GL_FRONT, GL_SHININESS, m.shininess); +} + +void setupLights(std::vector lights) { + for (int i = 0; i < lights.size() && lights.size() < 8; i++) { + Light light = lights[i]; + switch (light.type) { + case DIRECTIONAL: + glLightfv(GL_LIGHT0 + i, GL_POSITION, glm::value_ptr(light.direction)); + break; + case POINT: + glLightfv(GL_LIGHT0 + i, GL_POSITION, glm::value_ptr(light.position)); + break; + case SPOT: + glLightfv(GL_LIGHT0 + i, GL_POSITION, glm::value_ptr(light.position)); + glLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, glm::value_ptr(light.direction)); + glLightf(GL_LIGHT0 + i, GL_SPOT_CUTOFF, light.cutoff); + break; + } + } +} diff --git a/engine/src/main.cpp b/engine/src/main.cpp index c77f207..6a03d09 100644 --- a/engine/src/main.cpp +++ b/engine/src/main.cpp @@ -24,6 +24,7 @@ float cameraAngleY = 0.0f; float zoom = 1.0f; int axis = 1; +int wireframe = 1; int timebase; float frames; @@ -101,20 +102,10 @@ void renderScene(void) { glRotatef(cameraAngle, 1.0f, 0.0f, 1.0f); glScalef(zoom, zoom, zoom); - drawAxis(); - - // put drawing instructions here - - float pos[4] = {3.0, 3.0, 3.0, 0.0}; - glLightfv(GL_LIGHT0, GL_POSITION, pos); - - float dark[] = {0.2, 0.2, 0.2, 1.0}; - float white[] = {0.8, 0.8, 0.8, 1.0}; - float red[] = {0.8, 0.2, 0.2, 1.0}; + //setup all lights + setupLights(c.lights); - glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, white); - glMaterialfv(GL_FRONT, GL_SPECULAR, white); - glMaterialf(GL_FRONT, GL_SHININESS, 128); + drawAxis(); // glutSolidTeapot(1.0); c.group.drawGroup(); @@ -168,6 +159,14 @@ void processNormalKeys(unsigned char key, int x, int y) { case 'i': zoom += value; break; + case 'c': + if (wireframe) { + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + wireframe = 0; + } else { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + wireframe = 1; + } default: break; } @@ -177,9 +176,11 @@ void setupConfig(char* arg) { filename.assign(arg); if (filename.substr(filename.size() - 4) == ".xml") { + printf("XML\n"); c = parseConfig(filename); } else { - c = parseConfig("../scenes/default.xml"); + std::cout << "Invalid file format\n"; + exit(1); } } @@ -216,17 +217,9 @@ int main(int argc, char** argv) { // some OpenGL settings glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); - glEnable(GL_LIGHTING); - glEnable(GL_LIGHT0); - - float dark[4] = {0.2, 0.2, 0.2, 1.0}; - float white[4] = {1.0, 1.0, 1.0, 1.0}; - float black[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - // light colors - glLightfv(GL_LIGHT0, GL_AMBIENT, dark); - glLightfv(GL_LIGHT0, GL_DIFFUSE, white); - glLightfv(GL_LIGHT0, GL_SPECULAR, white); - glLightModelfv(GL_LIGHT_MODEL_AMBIENT, black); + if(c.lights.size() != 0) { + glEnable(GL_LIGHTING); + } // enter GLUT�s main cycle glutMainLoop(); diff --git a/engine/src/model.cpp b/engine/src/model.cpp index e40c17b..dc3c571 100644 --- a/engine/src/model.cpp +++ b/engine/src/model.cpp @@ -133,6 +133,8 @@ void Model::drawModel() { setupModel(); } + setupMaterial(this->material); + glColor3f(1.0f, 1.0f, 1.0f); glBindBuffer(GL_ARRAY_BUFFER, this->_vbo); glVertexPointer(3, GL_FLOAT, 0, 0); diff --git a/engine/src/parse.cpp b/engine/src/parse.cpp index eee529b..f5d4d5f 100644 --- a/engine/src/parse.cpp +++ b/engine/src/parse.cpp @@ -12,6 +12,8 @@ Configuration parseConfig(std::string filename) { exit(1); } + printf("Parsing file: %s\n", filename.c_str()); + // read the XML file content into a string std::string xmlContent((std::istreambuf_iterator(file)), std::istreambuf_iterator()); @@ -21,15 +23,18 @@ Configuration parseConfig(std::string filename) { rapidxml::xml_document<> doc; doc.parse<0>(&xmlContent[0]); + printf("Parsing XML\n"); // access the root node rapidxml::xml_node<>* root = doc.first_node("world"); + printf("Parsing window\n"); // window information char* width = root->first_node("window")->first_attribute("width")->value(); char* height = root->first_node("window")->first_attribute("height")->value(); Window window_info = Window(std::stoi(width), std::stoi(height)); + printf("Parsing camera\n"); // camera information rapidxml::xml_node<>* camera = root->first_node("camera"); @@ -55,6 +60,48 @@ Configuration parseConfig(std::string filename) { Camera camera_info = Camera(position, lookAt, up, fov, near, far); + // light information + printf("Parsing lights\n"); + std::vector list_lights; + rapidxml::xml_node<>* lights = root->first_node("lights"); + if (lights) { + for (rapidxml::xml_node<>* light = lights->first_node("light"); + light && list_lights.size() < 8; + light = light->next_sibling("light")) { + switch (light->first_attribute("type")->value()[0]) { + case 'p': { + float x = std::stof(light->first_attribute("posX")->value()); + float y = std::stof(light->first_attribute("posY")->value()); + float z = std::stof(light->first_attribute("posZ")->value()); + Light l = createPointLight(glm::vec4(x, y, z, 1)); + list_lights.push_back(l); + } break; + case 'd': { + float x = std::stof(light->first_attribute("dirX")->value()); + float y = std::stof(light->first_attribute("dirY")->value()); + float z = std::stof(light->first_attribute("dirZ")->value()); + Light l = createDirectionLight(glm::vec4(x, y, z, 1)); + list_lights.push_back(l); + } break; + case 's': { + float x = std::stof(light->first_attribute("posX")->value()); + float y = std::stof(light->first_attribute("posY")->value()); + float z = std::stof(light->first_attribute("posZ")->value()); + float dx = std::stof(light->first_attribute("dirX")->value()); + float dy = std::stof(light->first_attribute("dirY")->value()); + float dz = std::stof(light->first_attribute("dirZ")->value()); + float cutoff = std::stof(light->first_attribute("cutoff")->value()); + Light l = createSpotLight(glm::vec4(x, y, z, 1), + glm::vec4(dx, dy, dz, 1), cutoff); + list_lights.push_back(l); + } break; + default: + break; + } + } + } + + std::cout << "Parsing group" << std::endl; // group information rapidxml::xml_node<>* group = root->first_node("group"); @@ -62,7 +109,7 @@ Configuration parseConfig(std::string filename) { Group groupInfo = parseGroup(group); // Return the configuration object - return Configuration(window_info, camera_info, groupInfo); + return Configuration(window_info, camera_info, groupInfo, list_lights); } // Parse a group node recursively @@ -158,13 +205,47 @@ void parseModels(rapidxml::xml_node<>* modelsNode, Group& group) { rapidxml::xml_node<>* modelNode = modelsNode->first_node("model"); while (modelNode) { const std::string& file = modelNode->first_attribute("file")->value(); - const Model& model = readFile(file.data()); + Model model = readFile(file.data()); if (model.id == -1) { std::cerr << "Error reading model file: " << file << std::endl; return; } - group.models.push_back(model); + rapidxml::xml_node<>* color = modelNode->first_node("color"); + if (color) { + rapidxml::xml_node<>* diffuse = color->first_node("diffuse"); + glm::vec4 diffuse_vec = glm::vec4( + std::stof(diffuse->first_attribute("R")->value()) / 255.0f, + std::stof(diffuse->first_attribute("G")->value()) / 255.0f, + std::stof(diffuse->first_attribute("B")->value()) / 255.0f, 1.0f); + rapidxml::xml_node<>* ambient = color->first_node("ambient"); + glm::vec4 ambient_vec = glm::vec4( + std::stof(ambient->first_attribute("R")->value()) / 255.0f, + std::stof(ambient->first_attribute("G")->value()) / 255.0f, + std::stof(ambient->first_attribute("B")->value()) / 255.0f, 1.0f); + rapidxml::xml_node<>* specular = color->first_node("specular"); + glm::vec4 specular_vec = glm::vec4( + std::stof(specular->first_attribute("R")->value()) / 255.0f, + std::stof(specular->first_attribute("G")->value()) / 255.0f, + std::stof(specular->first_attribute("B")->value()) / 255.0f, 1.0f); + rapidxml::xml_node<>* emissive = color->first_node("emissive"); + glm::vec4 emission_vec = glm::vec4( + std::stof(emissive->first_attribute("R")->value()) / 255.0f, + std::stof(emissive->first_attribute("G")->value()) / 255.0f, + std::stof(emissive->first_attribute("B")->value()) / 255.0f, 1.0f); + rapidxml::xml_node<>* shininess = color->first_node("shininess"); + float shininess_val = + std::stof(shininess->first_attribute("value")->value()); + + model.material = createMaterial(diffuse_vec, ambient_vec, specular_vec, + emission_vec, shininess_val); + } else { + model.material = createMaterial(glm::vec4(0.2f, 0.2f, 0.2f, 1.0f), + glm::vec4(0.8f, 0.8f, 0.8f, 1.0f), + glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), + glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), 0.0f); + } + group.models.push_back(model); modelNode = modelNode->next_sibling("model"); } } diff --git a/scenes/advanced/default.xml b/scenes/advanced/default.xml index e951184..9213757 100644 --- a/scenes/advanced/default.xml +++ b/scenes/advanced/default.xml @@ -8,7 +8,7 @@ - + \ No newline at end of file diff --git a/scripts/clean.sh b/scripts/clean.sh index b95182a..de3e2f4 100755 --- a/scripts/clean.sh +++ b/scripts/clean.sh @@ -1,31 +1,12 @@ #!/bin/bash -rm -rf CMakeFiles -rm -f CMakeCache.txt -rm -f Makefile -rm -rf cmake-build-debug -rm -rf build -rm -rf cmake_install.cmake - -# Remove CMakeLists.txt.user if exists -rm -f CMakeLists.txt.user - -rm -rf */CMakeFiles -rm -f */CMakeCache.txt -rm -f */Makefile -rm -rf */cmake-build-debug -rm -rf */cmake_install.cmake -rm -rf */build -rm -rf */engine -rm -rf */generator -rm -rf */common -rm -rf _deps - -rm -rf */libimgui.a -rm -rf */libcommon.a -rm -rf libimgui.a +# Remove all the files that are generated by the build process +rm -rf build +rm -rf */.cmake -rm -rf cg-engine -rm -rf cg-generator +# Remove the CMake cache +rm -rf */cg-generator +rm -rf */cg-engine +rm -rf */imgui.ini -echo "Cleanup complete." +echo "Cleaned complete" \ No newline at end of file