diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3b1127c..14c9f32 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,27 +1,49 @@ set(HEADERS ${HEADERS} + ${CMAKE_CURRENT_SOURCE_DIR}/animation_track.h + ${CMAKE_CURRENT_SOURCE_DIR}/camera_node.h ${CMAKE_CURRENT_SOURCE_DIR}/colour.h + ${CMAKE_CURRENT_SOURCE_DIR}/demo_data.h ${CMAKE_CURRENT_SOURCE_DIR}/fbo.h + ${CMAKE_CURRENT_SOURCE_DIR}/light_node.h + ${CMAKE_CURRENT_SOURCE_DIR}/material.h ${CMAKE_CURRENT_SOURCE_DIR}/mesh.h ${CMAKE_CURRENT_SOURCE_DIR}/mesh_generator.h + ${CMAKE_CURRENT_SOURCE_DIR}/mesh_node.h ${CMAKE_CURRENT_SOURCE_DIR}/peripherals.h ${CMAKE_CURRENT_SOURCE_DIR}/peripherals_glfw.h + ${CMAKE_CURRENT_SOURCE_DIR}/scene.h + ${CMAKE_CURRENT_SOURCE_DIR}/scene_node.h + ${CMAKE_CURRENT_SOURCE_DIR}/scene_tree.h ${CMAKE_CURRENT_SOURCE_DIR}/shader.h + ${CMAKE_CURRENT_SOURCE_DIR}/shader_constants.h ${CMAKE_CURRENT_SOURCE_DIR}/texture.h ${CMAKE_CURRENT_SOURCE_DIR}/texture_generator.h + ${CMAKE_CURRENT_SOURCE_DIR}/timeline.h ${CMAKE_CURRENT_SOURCE_DIR}/timer.h PARENT_SCOPE ) set(SOURCE ${SOURCE} + ${CMAKE_CURRENT_SOURCE_DIR}/animation_track.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/camera_node.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/demo_data.cpp ${CMAKE_CURRENT_SOURCE_DIR}/fbo.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/light_node.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/material.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mesh.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mesh_generator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/mesh_node.cpp ${CMAKE_CURRENT_SOURCE_DIR}/peripherals_glfw.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/scene.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/scene_node.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/scene_tree.cpp ${CMAKE_CURRENT_SOURCE_DIR}/shader.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/shader_constants.cpp ${CMAKE_CURRENT_SOURCE_DIR}/texture.cpp ${CMAKE_CURRENT_SOURCE_DIR}/texture_generator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/timeline.cpp ${CMAKE_CURRENT_SOURCE_DIR}/timer.cpp PARENT_SCOPE ) diff --git a/src/animation_track.cpp b/src/animation_track.cpp new file mode 100644 index 0000000..a1af1c0 --- /dev/null +++ b/src/animation_track.cpp @@ -0,0 +1,35 @@ +#include "animation_track.h" + +BEGIN_NAMESPACE + +void animation_track::add_key(animation_key *key) { + keys.push_back(std::shared_ptr(key)); +} + +void animation_track::add_controlled_object(void *controlled_object) { + controlled_objects.push_back(controlled_object); +} + +void animation_track::set_at(float time) { + std::shared_ptr first, second; + + auto i = std::begin(keys); + + while (i != std::end(keys)) { + if ((*i)->time >= time) { + second = *i; + break; + } else { + first = *i; + } + ++i; + } + + float alpha = (time - first->time) / static_cast(second->time - first->time); + animated_value interpolated_value = get_value(first->value, second->value, alpha); + + for (auto o: controlled_objects) + control_object(o, interpolated_value); +} + +END_NAMESPACE \ No newline at end of file diff --git a/src/animation_track.h b/src/animation_track.h new file mode 100644 index 0000000..b5bc4c5 --- /dev/null +++ b/src/animation_track.h @@ -0,0 +1,64 @@ +#pragma once + +#include +#include +#include "defines.h" +#include "glm/glm.hpp" +#include "glm/gtc/quaternion.hpp" + +BEGIN_NAMESPACE + +enum class animated_value_type { + integer, + decimal, + vec3, + vec4, + quaternion +}; + +// sadly we cannot use union here since we have non-POD types +struct animated_value { + int intVal; + float floatVal; + glm::vec3 vec3Val; + glm::vec4 vec4Val; + glm::quat quatVal; +}; + +struct animation_key { + float time; + animated_value value; + + static animation_key *vec3Key(float t, glm::vec3 val) { + auto *result = new animation_key(); + result->time = t; + result->value.vec3Val = val; + return result; + } + + static animation_key *floatKey(float t, float val) { + auto *result = new animation_key(); + result->time = t; + result->value.floatVal = val; + return result; + } +}; + +class animation_track { +public: + void add_key(animation_key *key); + void add_controlled_object(void *controlled_object); + + void set_at(float time); + + virtual animated_value get_value(const animated_value &first, + const animated_value &second, + float alpha) = 0; + virtual void control_object(void *controlled_object, const animated_value &value) = 0; + + std::vector> keys; + std::vector controlled_objects; +}; + + +END_NAMESPACE diff --git a/src/camera_node.cpp b/src/camera_node.cpp new file mode 100644 index 0000000..fb535ac --- /dev/null +++ b/src/camera_node.cpp @@ -0,0 +1,30 @@ +#include "camera_node.h" +#include "demo_data.h" +#include "glm/gtx/quaternion.hpp" +#include "glm/gtx/transform.hpp" +#include "glm/gtc/matrix_transform.hpp" + +BEGIN_NAMESPACE + +camera_node::camera_node() { + type = scene_node_type::camera; +} + +void camera_node::calculate_local_transform() { + scene_node::calculate_local_transform(); + + view_matrix = glm::translate(glm::mat4(1.0f), + glm::vec3(-position.x, -position.y, -position.z)); + view_matrix *= glm::lookAt(glm::vec3(position.x, position.y, position.z), + glm::vec3(target.x, target.y, target.z), + glm::vec3(0, 1, 0) + ); + + projection_matrix = glm::perspective(fov, + demo_data::screen_width / static_cast(demo_data::screen_height), + 0.001f, + 100000.0f + ); +} + +END_NAMESPACE \ No newline at end of file diff --git a/src/camera_node.h b/src/camera_node.h new file mode 100644 index 0000000..a332ce1 --- /dev/null +++ b/src/camera_node.h @@ -0,0 +1,18 @@ +#pragma once + +#include "scene_node.h" + +BEGIN_NAMESPACE + +struct camera_node : scene_node { + camera_node(); + void calculate_local_transform() override; + + glm::vec3 target; + float roll_angle; + float fov; + glm::mat4 view_matrix; + glm::mat4 projection_matrix; +}; + +END_NAMESPACE diff --git a/src/colour.h b/src/colour.h index b68923a..0e08429 100644 --- a/src/colour.h +++ b/src/colour.h @@ -3,12 +3,17 @@ #include #include "glm/vec4.hpp" -typedef glm::vec4 colour; +BEGIN_NAMESPACE + +using colour = glm::vec4; inline uint32_t as_int(const glm::vec4 &col) { - unsigned char rr = static_cast(col.r * 255); - unsigned char gg = static_cast(col.g * 255); - unsigned char bb = static_cast(col.b * 255); - unsigned char aa = static_cast(col.a * 255); - return rr + (gg << 8) + (bb << 16) + (aa << 24); + auto r = static_cast(col.r * 255); + auto g = static_cast(col.g * 255); + auto b = static_cast(col.b * 255); + auto a = static_cast(col.a * 255); + + return r | g << 8 | b << 16 | a << 24; } + +END_NAMESPACE \ No newline at end of file diff --git a/src/defines.h b/src/defines.h index 12ec08d..14f6b7a 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4,5 +4,5 @@ #define BEGIN_NAMESPACE namespace acidrain { #define END_NAMESPACE }; -static int SCREEN_WIDTH = 800; -static int SCREEN_HEIGHT = 600; +//static int SCREEN_WIDTH = 800; +//static int SCREEN_HEIGHT = 600; diff --git a/src/demo_data.cpp b/src/demo_data.cpp new file mode 100644 index 0000000..b740c54 --- /dev/null +++ b/src/demo_data.cpp @@ -0,0 +1,14 @@ +#include "demo_data.h" + +BEGIN_NAMESPACE + +std::vector> demo_data::textures; +std::vector> demo_data::shaders; +std::vector> demo_data::materials; +std::vector> demo_data::meshes; +std::vector> demo_data::fbos; + +int demo_data::screen_width = 1024; +int demo_data::screen_height = 768; + +END_NAMESPACE \ No newline at end of file diff --git a/src/demo_data.h b/src/demo_data.h new file mode 100644 index 0000000..2ae2254 --- /dev/null +++ b/src/demo_data.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include "material.h" +#include "mesh.h" +#include "fbo.h" + +BEGIN_NAMESPACE + +struct demo_data { + + static std::vector> textures; + static std::vector> shaders; + static std::vector> materials; + static std::vector> meshes; + static std::vector> fbos; + + // holds the current viewport size at any point in time + static int screen_width; + static int screen_height; +}; + +END_NAMESPACE \ No newline at end of file diff --git a/src/fbo.cpp b/src/fbo.cpp index 06216f0..92b4184 100644 --- a/src/fbo.cpp +++ b/src/fbo.cpp @@ -1,5 +1,6 @@ #include "fbo.h" +#include "demo_data.h" #include BEGIN_NAMESPACE @@ -48,22 +49,22 @@ GLuint fbo::get_depth_buffer_id() const { } void fbo::use() { - old_width = SCREEN_WIDTH; - old_height = SCREEN_HEIGHT; + old_width = demo_data::screen_width; + old_height = demo_data::screen_height; - SCREEN_WIDTH = width; - SCREEN_HEIGHT = height; + demo_data::screen_height = width; + demo_data::screen_height = height; glBindFramebuffer(GL_FRAMEBUFFER, frame_buffer_id); glViewport(0, 0, width, height); } -void fbo::unuse() { +void fbo::unuse() const { glBindFramebuffer(GL_FRAMEBUFFER, 0); glViewport(0, 0, old_width, old_height); - SCREEN_WIDTH = old_width; - SCREEN_HEIGHT = old_height; + demo_data::screen_width = old_width; + demo_data::screen_height = old_height; } std::shared_ptr fbo::get_texture() { diff --git a/src/fbo.h b/src/fbo.h index 261b3d8..13c381e 100644 --- a/src/fbo.h +++ b/src/fbo.h @@ -11,7 +11,7 @@ public: ~fbo() = default; void use(); - void unuse(); + void unuse() const; int get_width() const; int get_height() const; diff --git a/src/light_node.cpp b/src/light_node.cpp new file mode 100644 index 0000000..9a663bf --- /dev/null +++ b/src/light_node.cpp @@ -0,0 +1,53 @@ +#include "light_node.h" + +//#define GL_COMPARE_REF_TO_TEXTURE 0x884E + +BEGIN_NAMESPACE + +light_node::light_node(light_type type_) { + type = scene_node_type::light; + light_type_ = type_; + + shadow_map_bias_matrix = glm::scale(glm::translate(glm::mat4(1.0f), glm::vec3(0.5f, 0.5f, 0.5f)), + glm::vec3(0.5f, 0.5f, 0.5f)); + + int textures_to_generate = light_type_ == light_type::point ? 6 : 1; + for (int i = 0; i < textures_to_generate; i++) { + GLuint shadow_map_texture_id; + + // setup the shadowmap texture + glGenTextures(1, &shadow_map_texture_id); + glBindTexture(GL_TEXTURE_2D, shadow_map_texture_id); + + // set texture parameters + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); + // TODO: see if we need +// glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, + shadow_map_width, shadow_map_width, + 0, + GL_DEPTH_COMPONENT, + GL_UNSIGNED_BYTE, + nullptr); + + shadow_map[i] = std::make_shared(shadow_map_texture_id, shadow_map_width, shadow_map_width); + } +} + +void light_node::calculate_local_transform() { + if (light_type_ == light_type::spot) { + world_to_light_matrix[0] = glm::lookAt(position, spot_target, glm::vec3(0, 1, 0)); + light_projection_matrix[0] = glm::perspective(90.0f, 1.0f, 0.1f, 100.0f); + glm::mat4 lightProjectionAndBiasMatrix = shadow_map_bias_matrix * light_projection_matrix[0]; + final_shadow_map_matrix[0] = lightProjectionAndBiasMatrix * world_to_light_matrix[0]; + } +} + +END_NAMESPACE \ No newline at end of file diff --git a/src/light_node.h b/src/light_node.h new file mode 100644 index 0000000..243521d --- /dev/null +++ b/src/light_node.h @@ -0,0 +1,42 @@ +#pragma once + +#include "scene_node.h" +#include "texture.h" + +BEGIN_NAMESPACE + +// http://en.wikipedia.org/wiki/Shading#Lighting +enum class light_type { + directional, + point, + spot +}; + +struct light_node : scene_node { + light_node(light_type type); + + void calculate_local_transform() override; + + light_type light_type_; + + glm::vec4 ambient = glm::vec4(0.2, 0.2, 0.2, 1); + glm::vec4 diffuse = glm::vec4(0.5, 0.5, 0.5, 1); + glm::vec4 specular = glm::vec4(1); + + glm::vec3 attenuation; + + glm::vec3 spot_target; + float spot_cutoff; + float spot_exponent; + + bool active = true; + + int shadow_map_width = 1024; + glm::mat4 light_projection_matrix[6]; + glm::mat4 world_to_light_matrix[6]; + glm::mat4 shadow_map_bias_matrix; + glm::mat4 final_shadow_map_matrix[6]; + std::shared_ptr shadow_map[6]; +}; + +END_NAMESPACE \ No newline at end of file diff --git a/src/material.cpp b/src/material.cpp new file mode 100644 index 0000000..57719d6 --- /dev/null +++ b/src/material.cpp @@ -0,0 +1,104 @@ +#include "material.h" +#include "shader_constants.h" + +BEGIN_NAMESPACE + +GLenum to_gl(const blending_constant &c) { + switch (c) { + case blending_constant::src_color: + return GL_SRC_COLOR; + case blending_constant::dst_color: + return GL_DST_COLOR; + case blending_constant::one: + return GL_ONE; + case blending_constant::zero: + return GL_ZERO; + case blending_constant::src_alpha: + return GL_SRC_ALPHA; + case blending_constant::dst_alpha: + return GL_DST_ALPHA; + case blending_constant::one_minus_src_alpha: + return GL_ONE_MINUS_SRC_ALPHA; + case blending_constant::one_minus_dst_alpha: + return GL_ONE_MINUS_DST_ALPHA; + default: + return GL_ZERO; + } +} + +void set_material(std::shared_ptr &mat) { + // glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + mat->shader->use(); + +// if (material->textures[TextureRole::Diffuse]) { +// std::cout << "CAN has diffuse texture!!!!!!!!!11" << std::endl; +// int textureUnit = 0; +// glActiveTexture(GL_TEXTURE0 + textureUnit); +// material->shader->setIntUniform(textureUnit, "diffuseMap"); +// material->textures[TextureRole::Diffuse]->use(); +// } else { +// std::cout << "Cannot has diffuse texture!!!!!!!!!11" << std::endl; +// } + + // int textureUnit = 0; + // for (auto& kv : material->textures) { + // glActiveTexture(GL_TEXTURE0 + textureUnit); + // const char* uniformName = ShaderConstantNameResolver::nameFor(kv.first); + // material->shader->setIntUniform(textureUnit, uniformName); + // kv.second->use(); + // textureUnit++; + // } + + if (mat->transparent) { + glEnable(GL_BLEND); + glBlendFunc(to_gl(mat->blend_src_fact), to_gl(mat->blend_dst_fact)); + } else { + glDisable(GL_BLEND); + } + + if (mat->zbuffer_test) + glEnable(GL_DEPTH_TEST); + else + glDisable(GL_DEPTH_TEST); + + if (mat->zbuffer_write) + glDepthMask(GL_TRUE); + else + glDepthMask(GL_FALSE); + + if (mat->cull_faces) { + glEnable(GL_CULL_FACE); + glFrontFace(GL_CCW); + glCullFace(mat->cull_front_faces ? GL_FRONT : GL_BACK); + } else { + glDisable(GL_CULL_FACE); + } +} + +void unset_material(shared_ptr &mat) { + // int textureUnit = 0; + // for (auto& kv : material->textures) { + // glActiveTexture(GL_TEXTURE0 + textureUnit); + // const char* uniformName = ShaderConstantNameResolver::nameFor(kv.first); + // material->shader->setIntUniform(textureUnit, uniformName); + // kv.second->unuse(); + // textureUnit++; + // } + + mat->shader->unuse(); + + if (mat->transparent) + glDisable(GL_BLEND); + + if (!mat->zbuffer_test) + glEnable(GL_DEPTH_TEST); + + if (!mat->zbuffer_write) + glDepthMask(GL_TRUE); + + if (mat->cull_faces) + glDisable(GL_CULL_FACE); +} + +END_NAMESPACE \ No newline at end of file diff --git a/src/material.h b/src/material.h new file mode 100644 index 0000000..f018515 --- /dev/null +++ b/src/material.h @@ -0,0 +1,62 @@ +#pragma once + +#include +#include +#include "texture.h" +#include "shader.h" +#include "glm/glm.hpp" + +BEGIN_NAMESPACE + +enum class fill_mode_type { + wireframe, + solid +}; + +enum class blending_constant { + src_color, + dst_color, + one, + zero, + src_alpha, + dst_alpha, + one_minus_src_alpha, + one_minus_dst_alpha, +}; + +enum class texture_role { + diffuse, + specular, + normal, + emissive, + environment +}; + +using texture_map = std::map>; + +struct material { + glm::vec4 ambient; + glm::vec4 diffuse; + glm::vec4 specular; + float shininess = 1.f; + + bool flat_shaded = true; + bool zbuffer_write = true; + bool zbuffer_test = true; + bool cull_faces = false; + bool cull_front_faces = false; + bool transparent = false; + bool cast_shadows = true; + + blending_constant blend_src_fact = blending_constant::src_alpha; + blending_constant blend_dst_fact = blending_constant::one_minus_src_alpha; + + fill_mode_type fill_mode = fill_mode_type::solid; + std::shared_ptr shader; + texture_map textures; +}; + +void set_material(std::shared_ptr &material); +void unset_material(std::shared_ptr &material); + +END_NAMESPACE diff --git a/src/mesh_node.cpp b/src/mesh_node.cpp new file mode 100644 index 0000000..5203037 --- /dev/null +++ b/src/mesh_node.cpp @@ -0,0 +1,9 @@ +#include "mesh_node.h" + +BEGIN_NAMESPACE + +mesh_node::mesh_node() { + type = scene_node_type::mesh; +} + +END_NAMESPACE \ No newline at end of file diff --git a/src/mesh_node.h b/src/mesh_node.h new file mode 100644 index 0000000..493bf53 --- /dev/null +++ b/src/mesh_node.h @@ -0,0 +1,16 @@ +#pragma once + +#include "material.h" +#include "mesh.h" +#include "scene_node.h" + +BEGIN_NAMESPACE + +struct mesh_node : scene_node { + mesh_node(); + + std::shared_ptr mesh_; + std::shared_ptr material_; +}; + +END_NAMESPACE \ No newline at end of file diff --git a/src/scene.cpp b/src/scene.cpp new file mode 100644 index 0000000..f604386 --- /dev/null +++ b/src/scene.cpp @@ -0,0 +1,12 @@ +#include "scene.h" + +#include + +BEGIN_NAMESPACE + +scene::scene() { + tree = std::make_shared(); + animation = std::make_shared(); +} + +END_NAMESPACE \ No newline at end of file diff --git a/src/scene.h b/src/scene.h new file mode 100644 index 0000000..eeab128 --- /dev/null +++ b/src/scene.h @@ -0,0 +1,16 @@ +#pragma once + +#include +#include "scene_tree.h" +#include "timeline.h" + +BEGIN_NAMESPACE + +struct scene { + scene(); + + std::shared_ptr tree; + std::shared_ptr animation; +}; + +END_NAMESPACE \ No newline at end of file diff --git a/src/scene_node.cpp b/src/scene_node.cpp new file mode 100644 index 0000000..0a7130a --- /dev/null +++ b/src/scene_node.cpp @@ -0,0 +1,38 @@ +#include "scene_node.h" +#include "mesh_node.h" +#include "camera_node.h" +#include "light_node.h" +#include "glm/gtc/matrix_transform.hpp" +#include "glm/gtx/quaternion.hpp" + +BEGIN_NAMESPACE + +void scene_node::calculate_local_transform() { + local_to_parent_space_matrix = glm::translate(glm::mat4(1.0f), position) + * glm::translate(glm::mat4(1.0f), pivot) + * glm::toMat4(rotation) + * glm::translate(glm::mat4(1.0f), -pivot) + * glm::scale(glm::mat4(1.0f), scale); +} + +void scene_node::apply_parent_transform(const glm::mat4 &parent_transform) { + model_to_world_space_matrix = parent_transform * local_to_parent_space_matrix; + + for (auto &child: children) + child->apply_parent_transform(model_to_world_space_matrix); +} + + +mesh_node &scene_node::as_mesh_node() { + return *static_cast(this); +} + +light_node &scene_node::as_light_node() { + return *static_cast(this); +} + +camera_node &scene_node::as_camera_node() { + return *static_cast(this); +} + +END_NAMESPACE diff --git a/src/scene_node.h b/src/scene_node.h new file mode 100644 index 0000000..077d7b7 --- /dev/null +++ b/src/scene_node.h @@ -0,0 +1,49 @@ +#pragma once + +#include "defines.h" + +#include +#include +#include +#include "glm/glm.hpp" +#include "glm/gtc/quaternion.hpp" + +BEGIN_NAMESPACE + +enum class scene_node_type { + mesh, + camera, + light +}; + +struct mesh_node; +struct light_node; +struct camera_node; + +struct scene_node { + virtual void calculate_local_transform(); + void apply_parent_transform(const glm::mat4 &parent_transform); + + mesh_node &as_mesh_node(); + light_node &as_light_node(); + camera_node &as_camera_node(); + + int id; + std::string name; + scene_node_type type; // We rely on type comparison instead of dynamic casting because comparing types is much faster + + // Helpers to navigate the hierarchy + std::shared_ptr parent; + std::vector> children; + + // Transform + glm::vec3 scale = glm::vec3(1); + glm::vec3 position = glm::vec3(0); + glm::vec3 pivot = glm::vec3(0); + glm::quat rotation; + + glm::mat4 local_to_parent_space_matrix = glm::mat4(1); + glm::mat4 model_to_world_space_matrix = glm::mat4(1); +}; + +END_NAMESPACE \ No newline at end of file diff --git a/src/scene_tree.cpp b/src/scene_tree.cpp new file mode 100644 index 0000000..055e284 --- /dev/null +++ b/src/scene_tree.cpp @@ -0,0 +1,47 @@ +#include "scene_tree.h" + +BEGIN_NAMESPACE + +std::shared_ptr scene_tree::nodeById(int id) const { + for (auto& node : nodes) + if (node->id == id) + return node; + + return std::shared_ptr(nullptr); +} + +std::shared_ptr scene_tree::nodeByNameAndType(std::string name, scene_node_type type) const { + for (auto& node : nodes) + if (node->name == name && node->type == type) + return node; + + return std::shared_ptr(nullptr); +} + + +void scene_tree::add(std::shared_ptr node) { + add(node, std::shared_ptr(nullptr)); +} + +void scene_tree::add(std::shared_ptr node, std::shared_ptr parent) { + nodes.push_back(node); + node->parent = parent; + + if (parent) + parent->children.push_back(node); + else + rootNodes.push_back(node); + + if (node->type == scene_node_type::light) + lights.push_back(node); +} + +void scene_tree::transform() { + for (auto& node : nodes) + node->calculate_local_transform(); + + for (auto& node : rootNodes) + node->apply_parent_transform(glm::mat4(1)); +} + +END_NAMESPACE \ No newline at end of file diff --git a/src/scene_tree.h b/src/scene_tree.h new file mode 100644 index 0000000..14da8c0 --- /dev/null +++ b/src/scene_tree.h @@ -0,0 +1,24 @@ +#pragma once + +#include "scene_node.h" +#include + +BEGIN_NAMESPACE + +class scene_tree { +public: + + std::shared_ptr nodeById(int id) const; + std::shared_ptr nodeByNameAndType(std::string name, scene_node_type type) const; + + void add(std::shared_ptr node); + void add(std::shared_ptr node, std::shared_ptr parent); + + void transform(); + + std::vector> nodes; + std::vector> rootNodes; + std::vector> lights; +}; + +END_NAMESPACE \ No newline at end of file diff --git a/src/shader_constants.cpp b/src/shader_constants.cpp new file mode 100644 index 0000000..243cf4d --- /dev/null +++ b/src/shader_constants.cpp @@ -0,0 +1,160 @@ +#include "shader_constants.h" +#include "glm/gtc/type_ptr.hpp" + +BEGIN_NAMESPACE + +UniformDescriptor Uniforms::ViewMatrix("vmtx"); +UniformDescriptor Uniforms::ProjectionMatrix("pmtx"); +UniformDescriptor Uniforms::ModelToWorldMatrix("mmtx"); +UniformDescriptor Uniforms::NormalMatrix("nmtx"); +UniformDescriptor Uniforms::WorldToLightMatrix("wlmtx"); +UniformDescriptor Uniforms::LightProjectionMatrix("lpmtx"); +UniformDescriptor Uniforms::ShadowBiasMatrix("sbmtx"); +UniformDescriptor Uniforms::ShadowMatrix("smtx"); +UniformDescriptor Uniforms::DemoPartNormalizedTime("dptimen"); +UniformDescriptor Uniforms::LightPositionInEyeSpace("lPosEye"); +UniformDescriptor Uniforms::MaterialAmbientColor("matAmbientCol"); +UniformDescriptor Uniforms::MaterialDiffuseColor("matDiffuseCol"); +UniformDescriptor Uniforms::MaterialSpecularColor("matSpecularCol"); +UniformDescriptor Uniforms::MaterialShininess("matShininess"); +UniformDescriptor Uniforms::DiffuseMap("diffuseMap"); +UniformDescriptor Uniforms::ShadowMap("shadowMap"); +UniformDescriptor Uniforms::ShadowMap1("shadowMap1"); +UniformDescriptor Uniforms::ShadowMap2("shadowMap2"); +UniformDescriptor Uniforms::ShadowMap3("shadowMap3"); +UniformDescriptor Uniforms::ShadowMap4("shadowMap4"); +UniformDescriptor Uniforms::NumberOfLights("numLights"); +UniformDescriptor Uniforms::LightPosition("light", "position"); +UniformDescriptor Uniforms::LightTarget("light", "target"); +UniformDescriptor Uniforms::LightAmbient("light", "ambient"); +UniformDescriptor Uniforms::LightDiffuse("light", "diffuse"); +UniformDescriptor Uniforms::LightSpecular("light", "specular"); +UniformDescriptor Uniforms::LightSpotCutoff("light", "spotCutoff"); +UniformDescriptor Uniforms::LightSpotExponent("light", "spotExponent"); +UniformDescriptor Uniforms::LightAttenuation("light", "attenuation"); + +/* +const char* ShaderConstantNameResolver::nameFor(const ShaderConstantType& type) { + switch (type) { + case ShaderConstantType::ViewMatrix: return "vmtx"; + case ShaderConstantType::ProjectionMatrix: return "pmtx"; + case ShaderConstantType::ModelToWorldMatrix: return "mmtx"; + case ShaderConstantType::NormalMatrix: return "nmtx"; + case ShaderConstantType::DemoPartNormalizedTime: return "dptimen"; + case ShaderConstantType::WorldToLightMatrix: return "wlmtx"; + case ShaderConstantType::LightProjectionMatrix: return "lpmtx"; + case ShaderConstantType::ShadowBiasMatrix: return "sbmtx"; + case ShaderConstantType::ShadowMatrix: return "smtx"; + case ShaderConstantType::LightPositionInEyeSpace: return "lPosEye"; + case ShaderConstantType::MaterialAmbientColor: return "matAmbientCol"; + case ShaderConstantType::MaterialDiffuseColor: return "matDiffuseCol"; + case ShaderConstantType::MaterialSpecularColor: return "matSpecularCol"; + case ShaderConstantType::MaterialShininess: return "matShininess"; + case ShaderConstantType::ShadowMap: return "shadowMap"; + case ShaderConstantType::NumberOfLights: return "numLights"; + default: return ""; + } +} + +const char* ShaderConstantNameResolver::nameFor(const TextureRole& type) { + switch (type) { + case TextureRole::Diffuse: return "mapDiffuse"; + case TextureRole::Specular: return "mapSpecular"; + case TextureRole::Normal: return "mapNormal"; + // TODO: remove Bump since we have normal map + case TextureRole::Bump: return "mapBump"; + default: return ""; + } +} + +void ShaderConstants::add(ShaderConstantType type, float value) { + ShaderConstantValue val; + val.floatVal = value; + constants[type] = val; +} + +void ShaderConstants::add(ShaderConstantType type, int value) { + ShaderConstantValue val; + val.intVal = value; + constants[type] = val; +} + +void ShaderConstants::add(ShaderConstantType type, const glm::vec3& value) { + ShaderConstantValue val; + val.vec3Val = value; + constants[type] = val; +} + +void ShaderConstants::add(ShaderConstantType type, const glm::vec4& value) { + ShaderConstantValue val; + val.vec4Val = value; + constants[type] = val; +} + +void ShaderConstants::add(ShaderConstantType type, const glm::mat3& value) { + ShaderConstantValue val; + val.mat3Val = value; + constants[type] = val; +} + +void ShaderConstants::add(ShaderConstantType type, const glm::mat4& value) { + ShaderConstantValue val; + val.mat4Val = value; + constants[type] = val; +} + + +void ShaderConstants::set(Shader& shader) { + for (auto& kv : constants) { + + const char* uniformName = ShaderConstantNameResolver::nameFor(kv.first); + + switch (kv.first) { + case ShaderConstantType::NormalMatrix: { + shader.setMatrix3Uniform(glm::value_ptr(kv.second.mat3Val), uniformName); + break; + } + + case ShaderConstantType::ViewMatrix: + case ShaderConstantType::ProjectionMatrix: + case ShaderConstantType::ModelToWorldMatrix: + case ShaderConstantType::WorldToLightMatrix: + case ShaderConstantType::LightProjectionMatrix: + case ShaderConstantType::ShadowBiasMatrix: + case ShaderConstantType::ShadowMatrix: { + shader.setMatrix4Uniform(glm::value_ptr(kv.second.mat4Val), uniformName); + break; + } + + case ShaderConstantType::DemoPartNormalizedTime: { + shader.setFloatUniform(kv.second.floatVal, uniformName); + break; + } + + case ShaderConstantType::MaterialShininess: + case ShaderConstantType::ShadowMap: + case ShaderConstantType::NumberOfLights: { + shader.setIntUniform(kv.second.intVal, uniformName); + break; + } + + case ShaderConstantType::LightPositionInEyeSpace: { + shader.setVec3Uniform(glm::value_ptr(kv.second.vec3Val), uniformName); + break; + } + + case ShaderConstantType::MaterialAmbientColor: + case ShaderConstantType::MaterialDiffuseColor: + case ShaderConstantType::MaterialSpecularColor: { + shader.setVec4Uniform(glm::value_ptr(kv.second.vec4Val), uniformName); + break; + } + + default: + break; + } + } +} +*/ + +END_NAMESPACE diff --git a/src/shader_constants.h b/src/shader_constants.h new file mode 100644 index 0000000..3d05b34 --- /dev/null +++ b/src/shader_constants.h @@ -0,0 +1,295 @@ +#pragma once + +#include "defines.h" +#include "shader.h" +#include "texture.h" +#include +#include "material.h" +#include "glm/glm.hpp" +#include "glm/gtc/type_ptr.hpp" +#include + +BEGIN_NAMESPACE + +using namespace std; + +struct UniformDescriptor { + string structureName; + string memberName; + + // TODO: implement memoization of uniform name calculation + + UniformDescriptor(const char *member) { + structureName = ""; + memberName = member; + } + + UniformDescriptor(const char *structure, const char *member) { + structureName = structure; + memberName = member; + } + + std::string getName() { + if (structureName.empty()) + return memberName; + + std::stringstream ss(structureName); + ss << "." << memberName; + return ss.str(); + } + + std::string getName(int index) { + std::stringstream ss; + if (structureName.empty()) { + ss << memberName << "[" << index << "]"; + } else { + ss << structureName << "[" << index << "]." << memberName; + } + return ss.str(); + } +}; + +class Uniforms { +public: + + static UniformDescriptor ViewMatrix; + static UniformDescriptor ProjectionMatrix; + static UniformDescriptor ModelToWorldMatrix; + static UniformDescriptor NormalMatrix; + static UniformDescriptor WorldToLightMatrix; + static UniformDescriptor LightProjectionMatrix; + static UniformDescriptor ShadowBiasMatrix; + static UniformDescriptor ShadowMatrix; + static UniformDescriptor DemoPartNormalizedTime; + static UniformDescriptor LightPositionInEyeSpace; + static UniformDescriptor MaterialAmbientColor; + static UniformDescriptor MaterialDiffuseColor; + static UniformDescriptor MaterialSpecularColor; + static UniformDescriptor MaterialShininess; + static UniformDescriptor DiffuseMap; + static UniformDescriptor ShadowMap; + static UniformDescriptor ShadowMap1; + static UniformDescriptor ShadowMap2; + static UniformDescriptor ShadowMap3; + static UniformDescriptor ShadowMap4; + static UniformDescriptor NumberOfLights; + static UniformDescriptor LightPosition; + static UniformDescriptor LightTarget; + static UniformDescriptor LightAmbient; + static UniformDescriptor LightDiffuse; + static UniformDescriptor LightSpecular; + static UniformDescriptor LightSpotCutoff; + static UniformDescriptor LightSpotExponent; + static UniformDescriptor LightAttenuation; +}; + +enum class ShaderConstantType { + Vec3, + Vec4, + Integer, + Float, + Mat3, + Mat4 +}; + +class ShaderConstantValue { +public: + + ShaderConstantType type; + + glm::vec3 vec3Val; + glm::vec4 vec4Val; + glm::mat3 mat3Val; + glm::mat4 mat4Val; + int intVal; + float floatVal; + + ShaderConstantValue(const ShaderConstantValue &rhs) { + type = rhs.type; + vec3Val = rhs.vec3Val; + vec4Val = rhs.vec4Val; + mat3Val = rhs.mat3Val; + mat4Val = rhs.mat4Val; + intVal = rhs.intVal; + floatVal = rhs.floatVal; + } + + ShaderConstantValue(glm::vec3 &value) { + vec3Val = value; + type = ShaderConstantType::Vec3; + } + + ShaderConstantValue(glm::vec4 &value) { + vec4Val = value; + type = ShaderConstantType::Vec4; + } + + ShaderConstantValue(glm::mat3 &value) { + mat3Val = value; + type = ShaderConstantType::Mat3; + } + + ShaderConstantValue(glm::mat4 &value) { + mat4Val = value; + type = ShaderConstantType::Mat4; + } + + ShaderConstantValue(int value) { + intVal = value; + type = ShaderConstantType::Integer; + } + + ShaderConstantValue(float value) { + floatVal = value; + type = ShaderConstantType::Float; + } + + void applyTo(shader &shader, const char *uniformName) { + switch (type) { + case ShaderConstantType::Vec3: + shader.setVec3Uniform(glm::value_ptr(vec3Val), uniformName); + break; + case ShaderConstantType::Vec4: + shader.setVec4Uniform(glm::value_ptr(vec4Val), uniformName); + break; + case ShaderConstantType::Mat3: + shader.setMatrix3Uniform(glm::value_ptr(mat3Val), uniformName); + break; + case ShaderConstantType::Mat4: + shader.setMatrix4Uniform(glm::value_ptr(mat4Val), uniformName); + break; + case ShaderConstantType::Integer: + shader.setIntUniform(intVal, uniformName); + break; + case ShaderConstantType::Float: + shader.setFloatUniform(floatVal, uniformName); + break; + } + } +}; + + +class ShaderConstants { +public: + + void set(UniformDescriptor descriptor, glm::mat3 value) { + constants[descriptor.getName()] = make_shared(value); + } + + void set(UniformDescriptor descriptor, glm::mat3 value, int index) { + constants[descriptor.getName(index)] = make_shared(value); + } + + void set(UniformDescriptor descriptor, glm::mat4 value) { + constants[descriptor.getName()] = make_shared(value); + } + + void set(UniformDescriptor descriptor, glm::mat4 value, int index) { + constants[descriptor.getName(index)] = make_shared(value); + } + + void set(UniformDescriptor descriptor, glm::vec3 value) { + constants[descriptor.getName()] = make_shared(value); + } + + void set(UniformDescriptor descriptor, glm::vec3 value, int index) { + constants[descriptor.getName(index)] = make_shared(value); + } + + void set(UniformDescriptor descriptor, glm::vec4 value) { + constants[descriptor.getName()] = make_shared(value); + } + + void set(UniformDescriptor descriptor, glm::vec4 value, int index) { + constants[descriptor.getName(index)] = make_shared(value); + } + + void set(UniformDescriptor descriptor, int value) { + constants[descriptor.getName()] = make_shared(value); + } + + void set(UniformDescriptor descriptor, int value, int index) { + constants[descriptor.getName(index)] = make_shared(value); + } + + void set(UniformDescriptor descriptor, float value) { + constants[descriptor.getName()] = make_shared(value); + } + + void set(UniformDescriptor descriptor, float value, int index) { + constants[descriptor.getName(index)] = make_shared(value); + } + + void applyTo(shader &shd) { + for (auto &kv: constants) + kv.second->applyTo(shd, kv.first.c_str()); + } + +private: + std::map> constants; +}; + +/* +enum class ShaderConstantType { + ViewMatrix, + ProjectionMatrix, + ModelToWorldMatrix, + NormalMatrix, + WorldToLightMatrix, + LightProjectionMatrix, + ShadowBiasMatrix, + ShadowMatrix, + DemoPartNormalizedTime, + LightPositionInEyeSpace, + MaterialAmbientColor, + MaterialDiffuseColor, + MaterialSpecularColor, + MaterialShininess, + ShadowMap, + NumberOfLights +}; + +class ShaderConstantNameResolver { +public: + + static const char* nameFor(const ShaderConstantType& type); + static const char* nameFor(const TextureRole& type); +}; + +union ShaderConstantValue { + glm::vec2 vec2Val; + glm::vec3 vec3Val; + glm::vec4 vec4Val; + glm::mat3 mat3Val; + glm::mat4 mat4Val; + bool boolVal; + int intVal; + float floatVal; + + ShaderConstantValue() { + this->floatVal = 0; + }; + + ShaderConstantValue(const ShaderConstantValue& lhs) { + this->mat4Val = lhs.mat4Val; + } + + ShaderConstantValue& operator=(const ShaderConstantValue& lhs) { + this->mat4Val = lhs.mat4Val; + return *this; + }; +}; + +struct ShaderConstants { + std::map constants; + + void add(ShaderConstantType type, float value); + void add(ShaderConstantType type, int value); + void add(ShaderConstantType type, const glm::vec3& value); + void add(ShaderConstantType type, const glm::vec4& value); + void add(ShaderConstantType type, const glm::mat4& value); + void add(ShaderConstantType type, const glm::mat3& value); + void set(Shader& shader); +}; +*/ +END_NAMESPACE \ No newline at end of file diff --git a/src/timeline.cpp b/src/timeline.cpp new file mode 100644 index 0000000..7f1ef03 --- /dev/null +++ b/src/timeline.cpp @@ -0,0 +1,10 @@ +#include "timeline.h" + +BEGIN_NAMESPACE + +void timeline::setAt(float time) { + for (auto &track: tracks) + track->set_at(time); +} + +END_NAMESPACE diff --git a/src/timeline.h b/src/timeline.h new file mode 100644 index 0000000..6a07781 --- /dev/null +++ b/src/timeline.h @@ -0,0 +1,12 @@ +#pragma once + +#include "animation_track.h" + +BEGIN_NAMESPACE + +struct timeline { + void setAt(float time); + std::vector> tracks; +}; + +END_NAMESPACE