Fixed heissenbug caused by quat initialization and added sound server.
This commit is contained in:
+3
-1
@@ -6,6 +6,8 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
|||||||
include(FindPkgConfig)
|
include(FindPkgConfig)
|
||||||
find_package(glfw3 3.3 REQUIRED)
|
find_package(glfw3 3.3 REQUIRED)
|
||||||
find_package(OpenGL REQUIRED)
|
find_package(OpenGL REQUIRED)
|
||||||
|
find_package(SDL2 REQUIRED)
|
||||||
|
include_directories(${SDL2_INCLUDE_DIRS})
|
||||||
|
|
||||||
include_directories("src/")
|
include_directories("src/")
|
||||||
include_directories("gl/include")
|
include_directories("gl/include")
|
||||||
@@ -30,4 +32,4 @@ set(SOURCE
|
|||||||
)
|
)
|
||||||
|
|
||||||
add_executable(demo main.cpp gl/src/glad.c ${SOURCE} lib/easyloggingpp/src/easylogging++.cc)
|
add_executable(demo main.cpp gl/src/glad.c ${SOURCE} lib/easyloggingpp/src/easylogging++.cc)
|
||||||
target_link_libraries(demo glfw OpenGL::GL)
|
target_link_libraries(demo glfw OpenGL::GL ${SDL2_LIBRARIES})
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#include "imgui_impl_glfw.h"
|
#include "imgui_impl_glfw.h"
|
||||||
@@ -7,6 +8,8 @@
|
|||||||
#include "peripherals_glfw.h"
|
#include "peripherals_glfw.h"
|
||||||
#include "demo/demo_engine.h"
|
#include "demo/demo_engine.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
#include "audio/sound_server.h"
|
||||||
|
#include <bitset>
|
||||||
|
|
||||||
using namespace acidrain;
|
using namespace acidrain;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@@ -15,30 +18,30 @@ INITIALIZE_EASYLOGGINGPP
|
|||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
acidrain::peripherals_glfw peripherals;
|
acidrain::peripherals_glfw peripherals;
|
||||||
peripherals.init();
|
peripherals.init(demo_data::screen_width, demo_data::screen_height, "acidrain", false);
|
||||||
LOG(INFO) << "peripherals initialized";
|
LOG(INFO) << "peripherals initialized";
|
||||||
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
const float DEMO_LENGTH_IN_SECONDS = 100;
|
const float DEMO_LENGTH_IN_SECONDS = 1000;
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// Load resources
|
// Load resources
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
acidrain::texture_generator tg(256, 256);
|
acidrain::texture_generator tg(256, 256);
|
||||||
tg.brick(0, 50, 20, 4, glm::vec4(1), glm::vec4(0));
|
// tg.brick(0, 50, 20, 4, glm::vec4(1), glm::vec4(0));
|
||||||
// tg.checker_board(0, 50, glm::vec4(1), glm::vec4(0));
|
tg.checker_board(0, 50, glm::vec4(1), glm::vec4(0));
|
||||||
|
|
||||||
shared_ptr<mesh> affectedSphere = mesh_generator::sphere(50, 50);
|
shared_ptr<mesh> affected_sphere = mesh_generator::sphere(50, 50);
|
||||||
map_transform(affectedSphere, tg, 0, 0, 0.2f);
|
map_transform(affected_sphere, tg, 0, 0, 0.2f);
|
||||||
calculate_normals(*affectedSphere.get());
|
calculate_normals(*affected_sphere);
|
||||||
|
|
||||||
// affectedSphere = mesh_generator::cog(0.2, 0.5, 50, 4, 0.1, 0.2, 0.2, 0.1);
|
// affectedSphere = mesh_generator::cog(0.2, 0.5, 50, 4, 0.1, 0.2, 0.2, 0.1);
|
||||||
|
|
||||||
demo_data::meshes.push_back(affectedSphere);
|
demo_data::meshes.push_back(affected_sphere);
|
||||||
demo_data::meshes.push_back(mesh_generator::sphere(3, 3));
|
demo_data::meshes.push_back(mesh_generator::sphere(3, 3));
|
||||||
demo_data::meshes.push_back(mesh_generator::grid(30, 30));
|
demo_data::meshes.push_back(mesh_generator::grid(1, 1));
|
||||||
demo_data::meshes.push_back(mesh_generator::cube());
|
demo_data::meshes.push_back(mesh_generator::cube());
|
||||||
|
|
||||||
auto mat = std::make_shared<material>();
|
auto mat = std::make_shared<material>();
|
||||||
@@ -49,21 +52,21 @@ int main() {
|
|||||||
mat->shininess = 200;
|
mat->shininess = 200;
|
||||||
mat->cast_shadows = true;
|
mat->cast_shadows = true;
|
||||||
|
|
||||||
auto *textureGenerator1 = new texture_generator(256, 256);
|
auto *texgen = new texture_generator(256, 256);
|
||||||
// mat->textures[texture_role::diffuse] = textureGenerator1->checker_board(0, 20,
|
mat->textures[texture_role::diffuse] = texgen->checker_board(0, 20,
|
||||||
// colour(1, 1, 1, 1),
|
colour(1, 1, 1, 1),
|
||||||
// colour(0, 0.5, 0.2, 1)).get_texture(0);
|
colour(0, 0.5, 0.2, 1)).get_texture(0);
|
||||||
mat->textures[texture_role::diffuse] = textureGenerator1->brick(0,
|
// mat->textures[texture_role::diffuse] = textureGenerator1->brick(0,
|
||||||
50, 20,
|
// 50, 20,
|
||||||
4,
|
// 4,
|
||||||
colour(0.3, 0.1, 0, 1),
|
// colour(0.3, 0.1, 0, 1),
|
||||||
colour(1, 0.3, 0, 1)).get_texture(0);
|
// colour(1, 0.3, 0, 1)).get_texture(0);
|
||||||
|
|
||||||
demo_data::materials.push_back(mat);
|
demo_data::materials.push_back(mat);
|
||||||
|
|
||||||
auto material2 = make_shared<material>();
|
auto material2 = make_shared<material>();
|
||||||
material2->ambient = glm::vec4(0, 0, 0.15, 1);
|
material2->ambient = glm::vec4(0, 0, 0.15, 1);
|
||||||
material2->textures[texture_role::diffuse] = textureGenerator1->get_texture(0);
|
material2->textures[texture_role::diffuse] = texgen->get_texture(0);
|
||||||
// material2->diffuse = glm::vec4(0.2, 1.0, 0.7, 1);
|
// material2->diffuse = glm::vec4(0.2, 1.0, 0.7, 1);
|
||||||
material2->diffuse = glm::vec4(1, 1, 1, 1);
|
material2->diffuse = glm::vec4(1, 1, 1, 1);
|
||||||
material2->specular = glm::vec4(0.3, 0.3, 0.3, 1);
|
material2->specular = glm::vec4(0.3, 0.3, 0.3, 1);
|
||||||
@@ -102,14 +105,14 @@ int main() {
|
|||||||
// Set up demo parts
|
// Set up demo parts
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
DemoPartClear demoPartClear;
|
demo_part_clear demoPartClear;
|
||||||
demoPartClear.startTime = 0;
|
demoPartClear.start_time = 0;
|
||||||
demoPartClear.endTime = DEMO_LENGTH_IN_SECONDS;
|
demoPartClear.end_time = DEMO_LENGTH_IN_SECONDS;
|
||||||
demoPartClear.color = glm::vec4(0.1f, 0.1f, 0.3f, 1.0f);
|
demoPartClear.color = glm::vec4(0.1f, 0.1f, 0.3f, 1.0f);
|
||||||
|
|
||||||
DemoPartScene demoPartScene;
|
demo_part_scene demoPartScene;
|
||||||
demoPartScene.startTime = 0;
|
demoPartScene.start_time = 0;
|
||||||
demoPartScene.endTime = DEMO_LENGTH_IN_SECONDS;
|
demoPartScene.end_time = DEMO_LENGTH_IN_SECONDS;
|
||||||
demoPartScene.cameraName = "cam1";
|
demoPartScene.cameraName = "cam1";
|
||||||
demoPartScene.lightName = "light1";
|
demoPartScene.lightName = "light1";
|
||||||
|
|
||||||
@@ -135,21 +138,21 @@ int main() {
|
|||||||
back_plane->material_ = demo_data::materials[1];
|
back_plane->material_ = demo_data::materials[1];
|
||||||
back_plane->position = glm::vec3(0, 5, -5);
|
back_plane->position = glm::vec3(0, 5, -5);
|
||||||
back_plane->scale = glm::vec3(10);
|
back_plane->scale = glm::vec3(10);
|
||||||
back_plane->rotation = angleAxis(3.141529f, glm::vec3(1.0f, 0.0f, 0.0f));
|
back_plane->rotation = glm::angleAxis(3.141529f, glm::vec3(1.0f, 0.0f, 0.0f));
|
||||||
|
|
||||||
auto left_plane = std::make_shared<mesh_node>("left plane");
|
auto left_plane = std::make_shared<mesh_node>("left plane");
|
||||||
left_plane->mesh_ = demo_data::meshes[2];
|
left_plane->mesh_ = demo_data::meshes[2];
|
||||||
left_plane->material_ = demo_data::materials[1];
|
left_plane->material_ = demo_data::materials[1];
|
||||||
left_plane->position = glm::vec3(-5, 5, 0);
|
left_plane->position = glm::vec3(-5, 5, 0);
|
||||||
left_plane->scale = glm::vec3(10);
|
left_plane->scale = glm::vec3(10);
|
||||||
left_plane->rotation = angleAxis(-3.141529f / 2.0f, glm::vec3(0.0f, 1.0f, 0.0f));
|
left_plane->rotation = glm::angleAxis(-3.141529f / 2.0f, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||||
|
|
||||||
auto right_plane = std::make_shared<mesh_node>("right plane");
|
auto right_plane = std::make_shared<mesh_node>("right plane");
|
||||||
right_plane->mesh_ = demo_data::meshes[2];
|
right_plane->mesh_ = demo_data::meshes[2];
|
||||||
right_plane->material_ = demo_data::materials[1];
|
right_plane->material_ = demo_data::materials[1];
|
||||||
right_plane->position = glm::vec3(5, 5, 0);
|
right_plane->position = glm::vec3(5, 5, 0);
|
||||||
right_plane->scale = glm::vec3(10);
|
right_plane->scale = glm::vec3(10);
|
||||||
right_plane->rotation = angleAxis(3.141529f / 2.0f, glm::vec3(0.0f, 1.0f, 0.0f));
|
right_plane->rotation = glm::angleAxis(3.141529f / 2.0f, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||||
|
|
||||||
auto bigSphere = make_shared<mesh_node>("big sphere");
|
auto bigSphere = make_shared<mesh_node>("big sphere");
|
||||||
bigSphere->mesh_ = demo_data::meshes[0];
|
bigSphere->mesh_ = demo_data::meshes[0];
|
||||||
@@ -178,7 +181,7 @@ int main() {
|
|||||||
lightNode->spot_cutoff = 50.0f;
|
lightNode->spot_cutoff = 50.0f;
|
||||||
lightNode->spot_exponent = 16.0f;
|
lightNode->spot_exponent = 16.0f;
|
||||||
lightNode->ambient = glm::vec4(0.1, 0.1, 0.1, 1.0);
|
lightNode->ambient = glm::vec4(0.1, 0.1, 0.1, 1.0);
|
||||||
lightNode->diffuse = glm::vec4(0.5, 1.0, 1.0, 1.0);
|
lightNode->diffuse = glm::vec4(0.1, 0.3, 1.0, 1.0);
|
||||||
lightNode->specular = glm::vec4(0.0, 0.8, 0.1, 1.0);
|
lightNode->specular = glm::vec4(0.0, 0.8, 0.1, 1.0);
|
||||||
|
|
||||||
auto lightNode2 = make_shared<light_node>(light_type::spot);
|
auto lightNode2 = make_shared<light_node>(light_type::spot);
|
||||||
@@ -188,8 +191,8 @@ int main() {
|
|||||||
lightNode2->spot_cutoff = 50.0f;
|
lightNode2->spot_cutoff = 50.0f;
|
||||||
lightNode2->spot_exponent = 16.0f;
|
lightNode2->spot_exponent = 16.0f;
|
||||||
lightNode2->ambient = glm::vec4(0.1, 0.1, 0.1, 1.0);
|
lightNode2->ambient = glm::vec4(0.1, 0.1, 0.1, 1.0);
|
||||||
lightNode2->diffuse = glm::vec4(1.0, 0.5, 1.0, 1.0);
|
lightNode2->diffuse = glm::vec4(1.0, 0.5, 0.3, 1.0);
|
||||||
lightNode2->specular = glm::vec4(0.0, 0.8, 0.1, 1.0);
|
lightNode2->specular = glm::vec4(1.0, 0.8, 0.1, 1.0);
|
||||||
|
|
||||||
scene1->tree->add(ground_plane);
|
scene1->tree->add(ground_plane);
|
||||||
scene1->tree->add(back_plane);
|
scene1->tree->add(back_plane);
|
||||||
@@ -213,14 +216,15 @@ int main() {
|
|||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
|
|
||||||
IMGUI_CHECKVERSION();
|
// IMGUI_CHECKVERSION();
|
||||||
ImGui::CreateContext();
|
// ImGui::CreateContext();
|
||||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
// ImGuiIO& io = ImGui::GetIO();
|
||||||
ImGui::StyleColorsDark();
|
// (void) io;
|
||||||
|
// ImGui::StyleColorsDark();
|
||||||
// Setup Platform/Renderer backends
|
//
|
||||||
ImGui_ImplGlfw_InitForOpenGL(((peripherals_glfw*)&peripherals)->get_window(), true);
|
// // Setup Platform/Renderer backends
|
||||||
ImGui_ImplOpenGL3_Init("#version 150");
|
// ImGui_ImplGlfw_InitForOpenGL(((peripherals_glfw *) &peripherals)->get_window(), true);
|
||||||
|
// ImGui_ImplOpenGL3_Init("#version 150");
|
||||||
|
|
||||||
timer timer1;
|
timer timer1;
|
||||||
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
||||||
@@ -228,56 +232,57 @@ int main() {
|
|||||||
bool show_another_window = false;
|
bool show_another_window = false;
|
||||||
|
|
||||||
while (!peripherals.should_close() && timer1.seconds_since_start() < DEMO_LENGTH_IN_SECONDS) {
|
while (!peripherals.should_close() && timer1.seconds_since_start() < DEMO_LENGTH_IN_SECONDS) {
|
||||||
ImGui_ImplOpenGL3_NewFrame();
|
// ImGui_ImplOpenGL3_NewFrame();
|
||||||
ImGui_ImplGlfw_NewFrame();
|
// ImGui_ImplGlfw_NewFrame();
|
||||||
ImGui::NewFrame();
|
// ImGui::NewFrame();
|
||||||
|
//
|
||||||
{
|
// {
|
||||||
static float f = 0.0f;
|
// static float f = 0.0f;
|
||||||
static int counter = 0;
|
// static int counter = 0;
|
||||||
|
//
|
||||||
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
|
// ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
|
||||||
|
//
|
||||||
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
|
// ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
|
||||||
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
|
// ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
|
||||||
ImGui::Checkbox("Another Window", &show_another_window);
|
// ImGui::Checkbox("Another Window", &show_another_window);
|
||||||
|
//
|
||||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
|
// ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
|
||||||
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
|
// ImGui::ColorEdit3("clear color", (float *) &clear_color); // Edit 3 floats representing a color
|
||||||
|
//
|
||||||
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
|
// if (ImGui::Button(
|
||||||
counter++;
|
// "Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
|
||||||
ImGui::SameLine();
|
// counter++;
|
||||||
ImGui::Text("counter = %d", counter);
|
// ImGui::SameLine();
|
||||||
|
// ImGui::Text("counter = %d", counter);
|
||||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
|
//
|
||||||
ImGui::End();
|
// ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
|
||||||
}
|
// ImGui::End();
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
double elapsedSeconds = timer1.seconds_since_start();
|
auto elapsed_seconds = timer1.seconds_since_start();
|
||||||
bigSphere->mesh_ = mesh_generator::extrude(mesh_generator::sphere(50, 50), {200, 201, 100, 101, 400, 401}, 0.05,
|
bigSphere->mesh_ = mesh_generator::extrude(mesh_generator::sphere(50, 50), {200, 201, 100, 101, 400, 401}, 0.05,
|
||||||
(int) ((sin(elapsedSeconds) + 0.5) * 40));
|
(int) ((sinf(elapsed_seconds) + 0.5f) * 40));
|
||||||
|
|
||||||
smallSphere->position = glm::vec3(0, sin(2 * M_PI * 0.13 * elapsedSeconds) * 2.0 + 0.5, 0);
|
smallSphere->position = glm::vec3(0, sin(2 * M_PI * 0.13 * elapsed_seconds) * 2.0 + 0.5, 0);
|
||||||
// meshNode->position = glm::vec3(0, 0.001, 0);
|
// meshNode->position = glm::vec3(0, 0.001, 0);
|
||||||
// camNode->target = glm::vec3(0, 0.0001, 0);
|
// camNode->target = glm::vec3(0, 0.0001, 0);
|
||||||
// camNode->position = glm::vec3(0, 5, -10);
|
// camNode->position = glm::vec3(0, 5, -10);
|
||||||
lightNode2->position = glm::vec3(5 * sin(2 * M_PI * 0.05 * elapsedSeconds), 2,
|
lightNode2->position = glm::vec3(5 * sin(2 * M_PI * 0.05 * elapsed_seconds), 2,
|
||||||
5 * cos(2 * M_PI * 0.05 * elapsedSeconds));
|
5 * cos(2 * M_PI * 0.05 * elapsed_seconds));
|
||||||
lightNode->position = glm::vec3(5 * cos(2 * M_PI * 0.75 * elapsedSeconds), 2,
|
lightNode->position = glm::vec3(5 * cos(2 * M_PI * 0.75 * elapsed_seconds), 2,
|
||||||
5 * sin(2 * M_PI * 0.75 * elapsedSeconds));
|
5 * sin(2 * M_PI * 0.75 * elapsed_seconds));
|
||||||
|
|
||||||
lightMeshNode->position = lightNode2->position;
|
lightMeshNode->position = lightNode2->position;
|
||||||
|
|
||||||
bigSphere->rotation *= angleAxis((float) (M_PI / 4.0 * timer1.lap()), normalize(glm::vec3(0.2, 0.5, 0.3)));
|
bigSphere->rotation *= angleAxis((float) (M_PI / 4.0 * timer1.lap()), normalize(glm::vec3(0.2, 0.5, 0.3)));
|
||||||
|
|
||||||
|
|
||||||
demoPartClear.process(demoPartClear.normalizeTime(elapsedSeconds));
|
demoPartClear.process(demoPartClear.normalize_time(elapsed_seconds));
|
||||||
demoPartScene.process(demoPartScene.normalizeTime(elapsedSeconds));
|
demoPartScene.process(demoPartScene.normalize_time(elapsed_seconds));
|
||||||
|
|
||||||
ImGui::Render();
|
// ImGui::Render();
|
||||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
// ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||||
|
|
||||||
peripherals.swap_buffers();
|
peripherals.swap_buffers();
|
||||||
peripherals.poll_events();
|
peripherals.poll_events();
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
Midi events delta time
|
||||||
|
|
||||||
|
https://sites.uci.edu/camp2014/2014/05/19/timing-in-midi-files/
|
||||||
|
http://www.music.mcgill.ca/~ich/classes/mumt306/StandardMIDIfileformat.html#BM2_3
|
||||||
|
|
||||||
|
- Delta-time is in some fraction of a beat (or a second, for recording a track with SMPTE times), as specified in the header chunk.
|
||||||
|
- nardis header track:
|
||||||
|
Format: 1
|
||||||
|
tracks: 10
|
||||||
|
division : 480
|
||||||
|
The third word, <division>, specifies the meaning of the delta-times.
|
||||||
|
It has two formats, one for metrical time, and one for time-code-based time:
|
||||||
|
|
||||||
|
bit 15 bits 14 thru 8 bits 7 thru 0
|
||||||
|
======|===============================|==============
|
||||||
|
0 | ticks per quarter-note
|
||||||
|
1 | negative SMPTE format | ticks per frame
|
||||||
|
|
||||||
|
If bit 15 of <division> is zero, the bits 14 thru 0 represent the number of delta time "ticks" which make up a quarter-note.
|
||||||
|
For instance, if division is 96, then a time interval of an eighth-note between two events in the file would be 48.
|
||||||
|
|
||||||
|
nardis division == 480 => bit 15 is zero, so we have 480 ticks per quarter note.
|
||||||
|
default tempo is 120, if not specified by a meta event
|
||||||
|
default time signature is 4/4 if not specified by a meta event
|
||||||
|
nardis has 4/4 time signature and tempo of 300000 microseconds per quarter note
|
||||||
|
|
||||||
|
|
||||||
|
MIDI header track gives division, which is PPQ (parts per quarter or ticks per quarter note). Nardis = 480 => delta time of 480 means a quarter note.
|
||||||
|
But how long is a quarter note? that is given by the tempo.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
PITCH bending
|
||||||
|
https://sites.uci.edu/camp2014/2014/04/30/managing-midi-pitchbend-messages/
|
||||||
|
- we get a 14bit value, [0..16383]
|
||||||
|
- map this to [-1..1], meaning that 16383/2 means no bend
|
||||||
|
- the float is the relative amount of bending, we should multiply it by a synth setting which says what is the bending range (+/- 2 semitones for example)
|
||||||
|
|
||||||
|
|
||||||
+7
-1
@@ -1,5 +1,6 @@
|
|||||||
set(HEADERS
|
set(HEADERS
|
||||||
${HEADERS}
|
${HEADERS}
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/audio/sound_server.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/animation_track.h
|
${CMAKE_CURRENT_SOURCE_DIR}/animation_track.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/camera_node.h
|
${CMAKE_CURRENT_SOURCE_DIR}/camera_node.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/colour.h
|
${CMAKE_CURRENT_SOURCE_DIR}/colour.h
|
||||||
@@ -10,13 +11,15 @@ set(HEADERS
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/mesh.h
|
${CMAKE_CURRENT_SOURCE_DIR}/mesh.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/mesh_generator.h
|
${CMAKE_CURRENT_SOURCE_DIR}/mesh_generator.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/mesh_node.h
|
${CMAKE_CURRENT_SOURCE_DIR}/mesh_node.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/particles.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/peripherals.h
|
${CMAKE_CURRENT_SOURCE_DIR}/peripherals.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/peripherals_glfw.h
|
${CMAKE_CURRENT_SOURCE_DIR}/peripherals_glfw.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/perlin.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/scene.h
|
${CMAKE_CURRENT_SOURCE_DIR}/scene.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/scene_node.h
|
${CMAKE_CURRENT_SOURCE_DIR}/scene_node.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/scene_renderer.h
|
${CMAKE_CURRENT_SOURCE_DIR}/scene_renderer.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/scene_tree.h
|
${CMAKE_CURRENT_SOURCE_DIR}/scene_tree.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/shader.h
|
${CMAKE_CURRENT_SOURCE_DIR}/shader_program.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/shader_constants.h
|
${CMAKE_CURRENT_SOURCE_DIR}/shader_constants.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/texture.h
|
${CMAKE_CURRENT_SOURCE_DIR}/texture.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/texture_generator.h
|
${CMAKE_CURRENT_SOURCE_DIR}/texture_generator.h
|
||||||
@@ -27,6 +30,7 @@ set(HEADERS
|
|||||||
|
|
||||||
set(SOURCE
|
set(SOURCE
|
||||||
${SOURCE}
|
${SOURCE}
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/audio/sound_server.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/animation_track.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/animation_track.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/camera_node.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/camera_node.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/demo_data.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/demo_data.cpp
|
||||||
@@ -36,7 +40,9 @@ set(SOURCE
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/mesh.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/mesh.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/mesh_generator.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/mesh_generator.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/mesh_node.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/mesh_node.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/particles.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/peripherals_glfw.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/peripherals_glfw.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/perlin.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/scene.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/scene.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/scene_node.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/scene_node.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/scene_renderer.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/scene_renderer.cpp
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
#include "sound_server.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <SDL.h>
|
||||||
|
|
||||||
|
void audio_callback(void *param, uint8_t *stream, int len) {
|
||||||
|
auto producer = reinterpret_cast<sound_producer *>(param);
|
||||||
|
uint16_t samples = len >> 2; // 4 bytes per F32
|
||||||
|
uint16_t frames = samples >> 1; // 2 channels, left and right
|
||||||
|
producer->render(reinterpret_cast<float *>(stream), frames);
|
||||||
|
}
|
||||||
|
|
||||||
|
sound_server::sound_server(uint16_t samplerate, sound_producer& producer) {
|
||||||
|
if (SDL_Init(SDL_INIT_AUDIO) < 0) {
|
||||||
|
std::cerr << "Init failed" << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_AudioSpec spec;
|
||||||
|
spec.freq = samplerate;
|
||||||
|
spec.format = AUDIO_F32;
|
||||||
|
spec.samples = 256;
|
||||||
|
spec.callback = audio_callback;
|
||||||
|
spec.userdata = reinterpret_cast<void *>(&producer);
|
||||||
|
spec.channels = 2;
|
||||||
|
|
||||||
|
if (SDL_OpenAudio(&spec, nullptr) < 0) {
|
||||||
|
std::cerr << "Unable to open audio" << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_PauseAudio(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
sound_server::~sound_server() {
|
||||||
|
SDL_Quit();
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
struct sound_producer {
|
||||||
|
// interleaved samples, LR
|
||||||
|
virtual void render(float *buffer, uint16_t frames) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sound_server {
|
||||||
|
sound_server(uint16_t samplerate, sound_producer& producer);
|
||||||
|
~sound_server();
|
||||||
|
};
|
||||||
@@ -1,9 +1,18 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
#include <easylogging++.h>
|
#include <easylogging++.h>
|
||||||
|
|
||||||
#define BEGIN_NAMESPACE namespace acidrain {
|
#define BEGIN_NAMESPACE namespace acidrain {
|
||||||
#define END_NAMESPACE };
|
#define END_NAMESPACE };
|
||||||
|
|
||||||
|
inline int rand_int(int x, int y) { return rand() % (y - x + 1) + x; }
|
||||||
|
|
||||||
|
inline double rand_float() { return ((rand()) / (RAND_MAX + 1.0)); }
|
||||||
|
|
||||||
|
inline double rand_in_range(double x, double y) {
|
||||||
|
return x + rand_float() * (y - x);
|
||||||
|
}
|
||||||
|
|
||||||
//static int SCREEN_WIDTH = 800;
|
//static int SCREEN_WIDTH = 800;
|
||||||
//static int SCREEN_HEIGHT = 600;
|
//static int SCREEN_HEIGHT = 600;
|
||||||
|
|||||||
@@ -4,12 +4,12 @@
|
|||||||
|
|
||||||
BEGIN_NAMESPACE
|
BEGIN_NAMESPACE
|
||||||
|
|
||||||
struct DemoPart {
|
struct demo_part {
|
||||||
float startTime; // absolute time, since demo starts
|
float start_time; // absolute time, since demo starts
|
||||||
float endTime; // absolute time, since demo starts
|
float end_time; // absolute time, since demo starts
|
||||||
|
|
||||||
float normalizeTime(float absoluteTimeInSeconds) {
|
float normalize_time(float absolute_time_in_seconds) {
|
||||||
return (absoluteTimeInSeconds - startTime) / static_cast<float>(endTime - startTime);
|
return (absolute_time_in_seconds - start_time) / static_cast<float>(end_time - start_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void process(float normalizedTime) = 0;
|
virtual void process(float normalizedTime) = 0;
|
||||||
|
|||||||
@@ -2,18 +2,18 @@
|
|||||||
|
|
||||||
BEGIN_NAMESPACE
|
BEGIN_NAMESPACE
|
||||||
|
|
||||||
void DemoPartClear::process(float normalizedTime) {
|
void demo_part_clear::process(float normalized_time) {
|
||||||
|
|
||||||
glClearColor(color.r, color.g, color.b, color.a);
|
glClearColor(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
GLbitfield mask = 0;
|
GLbitfield mask = 0;
|
||||||
if (clearDepth)
|
if (do_clear_depth)
|
||||||
mask |= GL_DEPTH_BUFFER_BIT;
|
mask |= GL_DEPTH_BUFFER_BIT;
|
||||||
|
|
||||||
if (clearColor)
|
if (do_clear_color)
|
||||||
mask |= GL_COLOR_BUFFER_BIT;
|
mask |= GL_COLOR_BUFFER_BIT;
|
||||||
|
|
||||||
if (clearStencil)
|
if (do_clear_stencil)
|
||||||
mask |= GL_STENCIL_BUFFER_BIT;
|
mask |= GL_STENCIL_BUFFER_BIT;
|
||||||
|
|
||||||
glClear(mask);
|
glClear(mask);
|
||||||
|
|||||||
@@ -5,15 +5,15 @@
|
|||||||
|
|
||||||
BEGIN_NAMESPACE
|
BEGIN_NAMESPACE
|
||||||
|
|
||||||
struct DemoPartClear : DemoPart {
|
struct demo_part_clear : demo_part {
|
||||||
|
|
||||||
glm::vec4 color = glm::vec4(0, 0, 0, 0);
|
glm::vec4 color = glm::vec4(0, 0, 0, 0);
|
||||||
|
|
||||||
bool clearDepth = true;
|
bool do_clear_depth = true;
|
||||||
bool clearColor = true;
|
bool do_clear_color = true;
|
||||||
bool clearStencil = true;
|
bool do_clear_stencil = true;
|
||||||
|
|
||||||
void process(float normalizedTime) override;
|
void process(float normalized_time) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
END_NAMESPACE
|
END_NAMESPACE
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
BEGIN_NAMESPACE
|
BEGIN_NAMESPACE
|
||||||
|
|
||||||
DemoPartMarchingCubes::DemoPartMarchingCubes(std::shared_ptr<mesh> affectedMesh) {
|
demo_part_marching_cubes::demo_part_marching_cubes(std::shared_ptr<mesh> affectedMesh) {
|
||||||
mesh_ = affectedMesh;
|
mesh_ = affectedMesh;
|
||||||
|
|
||||||
field.emitters.push_back(glm::vec4(0, 0.7, 0, 1));
|
field.emitters.push_back(glm::vec4(0, 0.7, 0, 1));
|
||||||
@@ -15,36 +15,36 @@ DemoPartMarchingCubes::DemoPartMarchingCubes(std::shared_ptr<mesh> affectedMesh)
|
|||||||
// field.emitters.push_back(glm::vec4(-0.5, 0.7, -0.3, 1));
|
// field.emitters.push_back(glm::vec4(-0.5, 0.7, -0.3, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DemoPartMarchingCubes::process(float normalizedTime) {
|
void demo_part_marching_cubes::process(float normalized_time) {
|
||||||
|
|
||||||
field.emitters[0].x = sin(normalizedTime * 2 * M_PI * 4);
|
field.emitters[0].x = sin(normalized_time * 2 * M_PI * 4);
|
||||||
field.emitters[0].z = cos(normalizedTime * 2 * M_PI * 4);
|
field.emitters[0].z = cos(normalized_time * 2 * M_PI * 4);
|
||||||
field.emitters[0].y = 0.7 * cos(normalizedTime * 2 * M_PI * 2);
|
field.emitters[0].y = 0.7 * cos(normalized_time * 2 * M_PI * 2);
|
||||||
|
|
||||||
field.emitters[1].x = sin(normalizedTime * 2 * M_PI * 7);
|
field.emitters[1].x = sin(normalized_time * 2 * M_PI * 7);
|
||||||
field.emitters[1].z = cos(normalizedTime * 2 * M_PI * 3.5);
|
field.emitters[1].z = cos(normalized_time * 2 * M_PI * 3.5);
|
||||||
|
|
||||||
field.emitters[2].y = 0.5 * sin(normalizedTime * 2 * M_PI * 4);
|
field.emitters[2].y = 0.5 * sin(normalized_time * 2 * M_PI * 4);
|
||||||
field.emitters[2].z = 0.8 * cos(normalizedTime * 2 * M_PI * 2);
|
field.emitters[2].z = 0.8 * cos(normalized_time * 2 * M_PI * 2);
|
||||||
|
|
||||||
// field.emitters[3].y = 0.8 * cos(normalizedTime * 2 * M_PI * 3);
|
// field.emitters[3].y = 0.8 * cos(normalizedTime * 2 * M_PI * 3);
|
||||||
// field.emitters[3].z = 0.2 * sin(normalizedTime * 2 * M_PI * 8);
|
// field.emitters[3].z = 0.2 * sin(normalizedTime * 2 * M_PI * 8);
|
||||||
|
|
||||||
grid.evaluateForces(field);
|
grid.evaluate_forces(field);
|
||||||
grid.triangulate(*mesh_.get(), minFieldValue);
|
grid.triangulate(*mesh_.get(), min_field_value);
|
||||||
|
|
||||||
for (auto &v: mesh_->vertices)
|
for (auto &v: mesh_->vertices)
|
||||||
v.normal = field.getFieldNormalAt(v.position);
|
v.normal = field.get_field_normal_at(v.position);
|
||||||
|
|
||||||
// calculateNormals(*mesh.get());
|
// calculateNormals(*mesh.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MarchingCubesGrid::evaluateForces(ForceField &field) {
|
void marching_cubes_grid::evaluate_forces(force_field &field) {
|
||||||
|
|
||||||
// Make sure we have enough space preallocated.
|
// Make sure we have enough space preallocated.
|
||||||
// We use resize because we want it also logically allocated with defaults
|
// We use resize because we want it also logically allocated with defaults
|
||||||
// so we can simply access an item at certain index with no issues
|
// so we can simply access an item at certain index with no issues
|
||||||
gridVertices.resize((xCells + 1) * (yCells + 1) * (zCells + 1));
|
grid_vertices.resize((xCells + 1) * (yCells + 1) * (zCells + 1));
|
||||||
|
|
||||||
glm::vec3 stepSize(
|
glm::vec3 stepSize(
|
||||||
(xMax - xMin) / static_cast<float>(xCells),
|
(xMax - xMin) / static_cast<float>(xCells),
|
||||||
@@ -64,11 +64,11 @@ void MarchingCubesGrid::evaluateForces(ForceField &field) {
|
|||||||
|
|
||||||
for (int x = 0; x <= xCells; x++) {
|
for (int x = 0; x <= xCells; x++) {
|
||||||
gridVertex.x = xMin + x * stepSize.x;
|
gridVertex.x = xMin + x * stepSize.x;
|
||||||
gridVertex.w = field.getFieldValueAt(glm::vec3(gridVertex));
|
gridVertex.w = field.get_field_value_at(glm::vec3(gridVertex));
|
||||||
|
|
||||||
// std::cout << std::setprecision(5) << std::fixed << "(x: " << gridVertex.x << ", y: " << gridVertex.y << ", z: " << gridVertex.z << ", val: " << gridVertex.w << ")" << std::endl;
|
// std::cout << std::setprecision(5) << std::fixed << "(x: " << gridVertex.x << ", y: " << gridVertex.y << ", z: " << gridVertex.z << ", val: " << gridVertex.w << ")" << std::endl;
|
||||||
|
|
||||||
gridVertices[cellIndex] = gridVertex;
|
grid_vertices[cellIndex] = gridVertex;
|
||||||
|
|
||||||
cellIndex++;
|
cellIndex++;
|
||||||
}
|
}
|
||||||
@@ -77,7 +77,7 @@ void MarchingCubesGrid::evaluateForces(ForceField &field) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MarchingCubesGrid::triangulate(mesh &m, float minFieldValue) {
|
void marching_cubes_grid::triangulate(mesh &m, float minFieldValue) {
|
||||||
|
|
||||||
m.vertices.clear();
|
m.vertices.clear();
|
||||||
m.facets.clear();
|
m.facets.clear();
|
||||||
@@ -87,20 +87,20 @@ void MarchingCubesGrid::triangulate(mesh &m, float minFieldValue) {
|
|||||||
for (int y = 0; y < yCells; y++) {
|
for (int y = 0; y < yCells; y++) {
|
||||||
for (int x = 0; x < xCells; x++) {
|
for (int x = 0; x < xCells; x++) {
|
||||||
|
|
||||||
calculateCellVertices(x, y, z);
|
calculate_cell_vertices(x, y, z);
|
||||||
|
|
||||||
int cellType = classifyCell(minFieldValue);
|
int cellType = classify_cell(minFieldValue);
|
||||||
if (!edgeTable[cellType]) continue;
|
if (!edgeTable[cellType]) continue;
|
||||||
|
|
||||||
calculateIntersectionVertices(cellType, minFieldValue);
|
calculate_intersection_vertices(cellType, minFieldValue);
|
||||||
addResultingFacets(m, cellType);
|
add_resulting_facets(m, cellType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MarchingCubesGrid::calculateCellVertices(int x, int y, int z) {
|
void marching_cubes_grid::calculate_cell_vertices(int x, int y, int z) {
|
||||||
// TODO: optimize these out. they are constant for a given grid size.
|
// TODO: optimize these out. they are constant for a given grid size.
|
||||||
int xVerts = xCells + 1;
|
int xVerts = xCells + 1;
|
||||||
int yVerts = yCells + 1;
|
int yVerts = yCells + 1;
|
||||||
@@ -109,61 +109,61 @@ void MarchingCubesGrid::calculateCellVertices(int x, int y, int z) {
|
|||||||
int leftTopFarthestIndex = z * vertsInXYPlane + x + y * xCells;
|
int leftTopFarthestIndex = z * vertsInXYPlane + x + y * xCells;
|
||||||
|
|
||||||
// see http://paulbourke.net/geometry/polygonise/polygonise1.gif
|
// see http://paulbourke.net/geometry/polygonise/polygonise1.gif
|
||||||
cubeVertexIndices[0] = leftTopFarthestIndex + xVerts;
|
cube_vertex_indices[0] = leftTopFarthestIndex + xVerts;
|
||||||
cubeVertexIndices[1] = leftTopFarthestIndex + xVerts + 1;
|
cube_vertex_indices[1] = leftTopFarthestIndex + xVerts + 1;
|
||||||
cubeVertexIndices[2] = leftTopFarthestIndex + xVerts + 1 + vertsInXYPlane;
|
cube_vertex_indices[2] = leftTopFarthestIndex + xVerts + 1 + vertsInXYPlane;
|
||||||
cubeVertexIndices[3] = leftTopFarthestIndex + xVerts + vertsInXYPlane;
|
cube_vertex_indices[3] = leftTopFarthestIndex + xVerts + vertsInXYPlane;
|
||||||
|
|
||||||
cubeVertexIndices[4] = leftTopFarthestIndex;
|
cube_vertex_indices[4] = leftTopFarthestIndex;
|
||||||
cubeVertexIndices[5] = leftTopFarthestIndex + 1;
|
cube_vertex_indices[5] = leftTopFarthestIndex + 1;
|
||||||
cubeVertexIndices[6] = leftTopFarthestIndex + 1 + vertsInXYPlane;
|
cube_vertex_indices[6] = leftTopFarthestIndex + 1 + vertsInXYPlane;
|
||||||
cubeVertexIndices[7] = leftTopFarthestIndex + vertsInXYPlane;
|
cube_vertex_indices[7] = leftTopFarthestIndex + vertsInXYPlane;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int MarchingCubesGrid::classifyCell(float minFieldValue) {
|
int marching_cubes_grid::classify_cell(float minFieldValue) {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
if (gridVertices[cubeVertexIndices[i]].w <= minFieldValue)
|
if (grid_vertices[cube_vertex_indices[i]].w <= minFieldValue)
|
||||||
result |= 1 << i;
|
result |= 1 << i;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MarchingCubesGrid::calculateIntersectionVertices(int cellType, float minFieldValue) {
|
void marching_cubes_grid::calculate_intersection_vertices(int cellType, float minFieldValue) {
|
||||||
|
|
||||||
if (edgeTable[cellType] & 1)
|
if (edgeTable[cellType] & 1)
|
||||||
intersectionVertices[0] = intersection(cubeVertexIndices[0], cubeVertexIndices[1], minFieldValue);
|
intersection_vertices[0] = intersection(cube_vertex_indices[0], cube_vertex_indices[1], minFieldValue);
|
||||||
if (edgeTable[cellType] & 2)
|
if (edgeTable[cellType] & 2)
|
||||||
intersectionVertices[1] = intersection(cubeVertexIndices[1], cubeVertexIndices[2], minFieldValue);
|
intersection_vertices[1] = intersection(cube_vertex_indices[1], cube_vertex_indices[2], minFieldValue);
|
||||||
if (edgeTable[cellType] & 4)
|
if (edgeTable[cellType] & 4)
|
||||||
intersectionVertices[2] = intersection(cubeVertexIndices[2], cubeVertexIndices[3], minFieldValue);
|
intersection_vertices[2] = intersection(cube_vertex_indices[2], cube_vertex_indices[3], minFieldValue);
|
||||||
if (edgeTable[cellType] & 8)
|
if (edgeTable[cellType] & 8)
|
||||||
intersectionVertices[3] = intersection(cubeVertexIndices[3], cubeVertexIndices[0], minFieldValue);
|
intersection_vertices[3] = intersection(cube_vertex_indices[3], cube_vertex_indices[0], minFieldValue);
|
||||||
if (edgeTable[cellType] & 16)
|
if (edgeTable[cellType] & 16)
|
||||||
intersectionVertices[4] = intersection(cubeVertexIndices[4], cubeVertexIndices[5], minFieldValue);
|
intersection_vertices[4] = intersection(cube_vertex_indices[4], cube_vertex_indices[5], minFieldValue);
|
||||||
if (edgeTable[cellType] & 32)
|
if (edgeTable[cellType] & 32)
|
||||||
intersectionVertices[5] = intersection(cubeVertexIndices[5], cubeVertexIndices[6], minFieldValue);
|
intersection_vertices[5] = intersection(cube_vertex_indices[5], cube_vertex_indices[6], minFieldValue);
|
||||||
if (edgeTable[cellType] & 64)
|
if (edgeTable[cellType] & 64)
|
||||||
intersectionVertices[6] = intersection(cubeVertexIndices[6], cubeVertexIndices[7], minFieldValue);
|
intersection_vertices[6] = intersection(cube_vertex_indices[6], cube_vertex_indices[7], minFieldValue);
|
||||||
if (edgeTable[cellType] & 128)
|
if (edgeTable[cellType] & 128)
|
||||||
intersectionVertices[7] = intersection(cubeVertexIndices[7], cubeVertexIndices[4], minFieldValue);
|
intersection_vertices[7] = intersection(cube_vertex_indices[7], cube_vertex_indices[4], minFieldValue);
|
||||||
if (edgeTable[cellType] & 256)
|
if (edgeTable[cellType] & 256)
|
||||||
intersectionVertices[8] = intersection(cubeVertexIndices[0], cubeVertexIndices[4], minFieldValue);
|
intersection_vertices[8] = intersection(cube_vertex_indices[0], cube_vertex_indices[4], minFieldValue);
|
||||||
if (edgeTable[cellType] & 512)
|
if (edgeTable[cellType] & 512)
|
||||||
intersectionVertices[9] = intersection(cubeVertexIndices[1], cubeVertexIndices[5], minFieldValue);
|
intersection_vertices[9] = intersection(cube_vertex_indices[1], cube_vertex_indices[5], minFieldValue);
|
||||||
if (edgeTable[cellType] & 1024)
|
if (edgeTable[cellType] & 1024)
|
||||||
intersectionVertices[10] = intersection(cubeVertexIndices[2], cubeVertexIndices[6], minFieldValue);
|
intersection_vertices[10] = intersection(cube_vertex_indices[2], cube_vertex_indices[6], minFieldValue);
|
||||||
if (edgeTable[cellType] & 2048)
|
if (edgeTable[cellType] & 2048)
|
||||||
intersectionVertices[11] = intersection(cubeVertexIndices[3], cubeVertexIndices[7], minFieldValue);
|
intersection_vertices[11] = intersection(cube_vertex_indices[3], cube_vertex_indices[7], minFieldValue);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec3 MarchingCubesGrid::intersection(int v1Index, int v2Index, float minFieldValue) {
|
glm::vec3 marching_cubes_grid::intersection(int v1Index, int v2Index, float minFieldValue) {
|
||||||
glm::vec4 &a = gridVertices[v1Index];
|
glm::vec4 &a = grid_vertices[v1Index];
|
||||||
glm::vec4 &b = gridVertices[v2Index];
|
glm::vec4 &b = grid_vertices[v2Index];
|
||||||
|
|
||||||
if (a.w != b.w) {
|
if (a.w != b.w) {
|
||||||
float alpha = (minFieldValue - a.w) / (b.w - a.w);
|
float alpha = (minFieldValue - a.w) / (b.w - a.w);
|
||||||
@@ -174,7 +174,7 @@ glm::vec3 MarchingCubesGrid::intersection(int v1Index, int v2Index, float minFie
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MarchingCubesGrid::addResultingFacets(mesh &m, int cellType) {
|
void marching_cubes_grid::add_resulting_facets(mesh &m, int cellType) {
|
||||||
facet f{};
|
facet f{};
|
||||||
vertex v{};
|
vertex v{};
|
||||||
int vertexOffset = m.vertices.size();
|
int vertexOffset = m.vertices.size();
|
||||||
@@ -182,7 +182,7 @@ void MarchingCubesGrid::addResultingFacets(mesh &m, int cellType) {
|
|||||||
for (int n = 0; triTable[cellType][n] != -1; n += 3) {
|
for (int n = 0; triTable[cellType][n] != -1; n += 3) {
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
v.position = intersectionVertices[triTable[cellType][n + 2 - i]];
|
v.position = intersection_vertices[triTable[cellType][n + 2 - i]];
|
||||||
m.vertices.push_back(v);
|
m.vertices.push_back(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,7 +194,7 @@ void MarchingCubesGrid::addResultingFacets(mesh &m, int cellType) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
float ForceField::getFieldValueAt(const glm::vec3 &position) const {
|
float force_field::get_field_value_at(const glm::vec3 &position) const {
|
||||||
float result = 0;
|
float result = 0;
|
||||||
|
|
||||||
for (auto &e: emitters) {
|
for (auto &e: emitters) {
|
||||||
@@ -206,7 +206,7 @@ float ForceField::getFieldValueAt(const glm::vec3 &position) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
glm::vec3 ForceField::getFieldNormalAt(const glm::vec3 &position) const {
|
glm::vec3 force_field::get_field_normal_at(const glm::vec3 &position) const {
|
||||||
// Hello blackpawn! http://www.blackpawn.com/texts/metanormals/default.html
|
// Hello blackpawn! http://www.blackpawn.com/texts/metanormals/default.html
|
||||||
glm::vec3 normal = glm::vec3(0);
|
glm::vec3 normal = glm::vec3(0);
|
||||||
|
|
||||||
|
|||||||
@@ -6,14 +6,14 @@
|
|||||||
|
|
||||||
BEGIN_NAMESPACE
|
BEGIN_NAMESPACE
|
||||||
|
|
||||||
struct ForceField {
|
struct force_field {
|
||||||
float getFieldValueAt(const glm::vec3 &position) const;
|
float get_field_value_at(const glm::vec3& position) const;
|
||||||
glm::vec3 getFieldNormalAt(const glm::vec3 &position) const;
|
glm::vec3 get_field_normal_at(const glm::vec3& position) const;
|
||||||
|
|
||||||
std::vector<glm::vec4> emitters; // vec4 = position + strength
|
std::vector<glm::vec4> emitters; // vec4 = position + strength
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MarchingCubesGrid {
|
struct marching_cubes_grid {
|
||||||
int xCells = 60;
|
int xCells = 60;
|
||||||
int yCells = 60;
|
int yCells = 60;
|
||||||
int zCells = 60;
|
int zCells = 60;
|
||||||
@@ -28,31 +28,31 @@ struct MarchingCubesGrid {
|
|||||||
float zMax = 2;
|
float zMax = 2;
|
||||||
|
|
||||||
// .w will hold field value for code size optimisation purposes
|
// .w will hold field value for code size optimisation purposes
|
||||||
std::vector<glm::vec4> gridVertices;
|
std::vector<glm::vec4> grid_vertices;
|
||||||
|
|
||||||
void evaluateForces(ForceField &field);
|
void evaluate_forces(force_field& field);
|
||||||
void triangulate(mesh& m, float minFieldValue);
|
void triangulate(mesh& m, float minFieldValue);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void calculateCellVertices(int x, int y, int z);
|
void calculate_cell_vertices(int x, int y, int z);
|
||||||
int classifyCell(float minFieldValue);
|
int classify_cell(float minFieldValue);
|
||||||
void calculateIntersectionVertices(int cellType, float minFieldValue);
|
void calculate_intersection_vertices(int cellType, float minFieldValue);
|
||||||
void addResultingFacets(mesh &m, int cellType);
|
void add_resulting_facets(mesh& m, int cellType);
|
||||||
glm::vec3 intersection(int v1Index, int v2Index, float minFieldValue);
|
glm::vec3 intersection(int v1Index, int v2Index, float minFieldValue);
|
||||||
|
|
||||||
int cubeVertexIndices[8];
|
int cube_vertex_indices[8];
|
||||||
glm::vec3 intersectionVertices[12];
|
glm::vec3 intersection_vertices[12];
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DemoPartMarchingCubes : DemoPart {
|
struct demo_part_marching_cubes : demo_part {
|
||||||
DemoPartMarchingCubes(std::shared_ptr<mesh> affectedMesh);
|
explicit demo_part_marching_cubes(std::shared_ptr<mesh> affected_mesh);
|
||||||
|
|
||||||
void process(float normalizedTime) override;
|
void process(float normalized_time) override;
|
||||||
|
|
||||||
MarchingCubesGrid grid;
|
marching_cubes_grid grid;
|
||||||
ForceField field;
|
force_field field;
|
||||||
float minFieldValue = 2.6;
|
float min_field_value = 2.6;
|
||||||
std::shared_ptr<mesh> mesh_;
|
std::shared_ptr<mesh> mesh_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -3,12 +3,12 @@
|
|||||||
|
|
||||||
BEGIN_NAMESPACE
|
BEGIN_NAMESPACE
|
||||||
|
|
||||||
DemoPartRenderToTexture::DemoPartRenderToTexture(int s, RenderToTextureAction a)
|
demo_part_render_to_texture::demo_part_render_to_texture(int s, render_to_texture_action a)
|
||||||
: slot(s), action(a) {
|
: slot(s), action(a) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DemoPartRenderToTexture::process(float normalizedTime) {
|
void demo_part_render_to_texture::process(float normalizedTime) {
|
||||||
if (action == RenderToTextureAction::Start)
|
if (action == render_to_texture_action::start)
|
||||||
demo_data::fbos[slot]->use();
|
demo_data::fbos[slot]->use();
|
||||||
else
|
else
|
||||||
demo_data::fbos[slot]->unuse();
|
demo_data::fbos[slot]->unuse();
|
||||||
|
|||||||
@@ -4,19 +4,18 @@
|
|||||||
|
|
||||||
BEGIN_NAMESPACE
|
BEGIN_NAMESPACE
|
||||||
|
|
||||||
enum class RenderToTextureAction {
|
enum class render_to_texture_action {
|
||||||
Start,
|
start,
|
||||||
Stop
|
stop
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DemoPartRenderToTexture : DemoPart {
|
struct demo_part_render_to_texture : demo_part {
|
||||||
|
demo_part_render_to_texture(int slot, render_to_texture_action action);
|
||||||
|
|
||||||
DemoPartRenderToTexture(int slot, RenderToTextureAction action);
|
void process(float normalized_time) override;
|
||||||
|
|
||||||
void process(float normalizedTime) override;
|
|
||||||
|
|
||||||
int slot;
|
int slot;
|
||||||
RenderToTextureAction action;
|
render_to_texture_action action;
|
||||||
};
|
};
|
||||||
|
|
||||||
END_NAMESPACE
|
END_NAMESPACE
|
||||||
@@ -7,16 +7,13 @@
|
|||||||
|
|
||||||
BEGIN_NAMESPACE
|
BEGIN_NAMESPACE
|
||||||
|
|
||||||
DemoPartScene::DemoPartScene() {
|
demo_part_scene::demo_part_scene() {
|
||||||
renderer = std::make_shared<scene_renderer>();
|
renderer = std::make_shared<scene_renderer>();
|
||||||
}
|
}
|
||||||
|
|
||||||
DemoPartScene::~DemoPartScene() {
|
void demo_part_scene::process(float normalized_time) {
|
||||||
}
|
|
||||||
|
|
||||||
void DemoPartScene::process(float normalizedTime) {
|
|
||||||
if (scene_->animation)
|
if (scene_->animation)
|
||||||
scene_->animation->set_at_time(normalizedTime);
|
scene_->animation->set_at_time(normalized_time);
|
||||||
|
|
||||||
if (scene_->tree) {
|
if (scene_->tree) {
|
||||||
scene_->tree->transform();
|
scene_->tree->transform();
|
||||||
|
|||||||
+12
-11
@@ -9,27 +9,28 @@
|
|||||||
|
|
||||||
BEGIN_NAMESPACE
|
BEGIN_NAMESPACE
|
||||||
|
|
||||||
struct DemoPartScene : DemoPart {
|
struct demo_part_scene : demo_part {
|
||||||
|
|
||||||
DemoPartScene();
|
demo_part_scene();
|
||||||
virtual ~DemoPartScene();
|
~demo_part_scene() = default;
|
||||||
|
|
||||||
|
void process(float normalized_time) override;
|
||||||
|
|
||||||
std::shared_ptr<scene_renderer> renderer;
|
std::shared_ptr<scene_renderer> renderer;
|
||||||
std::shared_ptr<scene> scene_;
|
std::shared_ptr<scene> scene_;
|
||||||
std::string cameraName;
|
std::string cameraName;
|
||||||
std::string lightName;
|
std::string lightName;
|
||||||
float animationStartTime; // normalized time, [0-1]
|
float animationStartTime = 0; // normalized time, [0-1]
|
||||||
float animationEndTime; // normalized time, [0-1]
|
|
||||||
|
float animationEndTime = 1.0; // normalized time, [0-1]
|
||||||
|
GLuint fboID = 0;
|
||||||
|
GLuint shadowMapTexID = 0;
|
||||||
|
std::shared_ptr<shader_program> firstPassShadowShader;
|
||||||
|
|
||||||
GLuint fboID;
|
|
||||||
GLuint shadowMapTexID;
|
|
||||||
std::shared_ptr<shader> firstPassShadowShader;
|
|
||||||
std::shared_ptr<material> firstPassShadowMaterial;
|
std::shared_ptr<material> firstPassShadowMaterial;
|
||||||
|
std::shared_ptr<shader_program> secondPassShadowShader;
|
||||||
|
|
||||||
std::shared_ptr<shader> secondPassShadowShader;
|
|
||||||
std::shared_ptr<material> secondPassShadowMaterial;
|
std::shared_ptr<material> secondPassShadowMaterial;
|
||||||
|
|
||||||
void process(float normalizedTime) override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
END_NAMESPACE
|
END_NAMESPACE
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
#include "glm/gtx/transform.hpp"
|
#include "glm/gtx/transform.hpp"
|
||||||
#include "glm/gtc/matrix_transform.hpp"
|
#include "glm/gtc/matrix_transform.hpp"
|
||||||
|
|
||||||
#include "shader.h"
|
#include "shader_program.h"
|
||||||
#include "texture.h"
|
#include "texture.h"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -3,12 +3,12 @@
|
|||||||
BEGIN_NAMESPACE
|
BEGIN_NAMESPACE
|
||||||
|
|
||||||
std::vector<std::shared_ptr<texture>> demo_data::textures;
|
std::vector<std::shared_ptr<texture>> demo_data::textures;
|
||||||
std::vector<std::shared_ptr<shader>> demo_data::shaders;
|
std::vector<std::shared_ptr<shader_program>> demo_data::shaders;
|
||||||
std::vector<std::shared_ptr<material>> demo_data::materials;
|
std::vector<std::shared_ptr<material>> demo_data::materials;
|
||||||
std::vector<std::shared_ptr<mesh>> demo_data::meshes;
|
std::vector<std::shared_ptr<mesh>> demo_data::meshes;
|
||||||
std::vector<std::shared_ptr<fbo>> demo_data::fbos;
|
std::vector<std::shared_ptr<fbo>> demo_data::fbos;
|
||||||
|
|
||||||
int demo_data::screen_width = 1024;
|
int demo_data::screen_width = 1024 * 2;
|
||||||
int demo_data::screen_height = 768;
|
int demo_data::screen_height = 768 * 2;
|
||||||
|
|
||||||
END_NAMESPACE
|
END_NAMESPACE
|
||||||
+1
-1
@@ -10,7 +10,7 @@ BEGIN_NAMESPACE
|
|||||||
struct demo_data {
|
struct demo_data {
|
||||||
|
|
||||||
static std::vector<std::shared_ptr<texture>> textures;
|
static std::vector<std::shared_ptr<texture>> textures;
|
||||||
static std::vector<std::shared_ptr<shader>> shaders;
|
static std::vector<std::shared_ptr<shader_program>> shaders;
|
||||||
static std::vector<std::shared_ptr<material>> materials;
|
static std::vector<std::shared_ptr<material>> materials;
|
||||||
static std::vector<std::shared_ptr<mesh>> meshes;
|
static std::vector<std::shared_ptr<mesh>> meshes;
|
||||||
static std::vector<std::shared_ptr<fbo>> fbos;
|
static std::vector<std::shared_ptr<fbo>> fbos;
|
||||||
|
|||||||
+2
-3
@@ -24,8 +24,7 @@ fbo::fbo(int w, int h)
|
|||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, color_buffer_id,
|
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, color_buffer_id, 0);
|
||||||
0);
|
|
||||||
|
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, depth_buffer_id);
|
glBindRenderbuffer(GL_RENDERBUFFER, depth_buffer_id);
|
||||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
|
||||||
@@ -52,7 +51,7 @@ void fbo::use() {
|
|||||||
old_width = demo_data::screen_width;
|
old_width = demo_data::screen_width;
|
||||||
old_height = demo_data::screen_height;
|
old_height = demo_data::screen_height;
|
||||||
|
|
||||||
demo_data::screen_height = width;
|
demo_data::screen_width = width;
|
||||||
demo_data::screen_height = height;
|
demo_data::screen_height = height;
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, frame_buffer_id);
|
glBindFramebuffer(GL_FRAMEBUFFER, frame_buffer_id);
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@ enum class light_type {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct light_node : scene_node {
|
struct light_node : scene_node {
|
||||||
light_node(light_type type);
|
explicit light_node(light_type type);
|
||||||
|
|
||||||
void calculate_local_transform() override;
|
void calculate_local_transform() override;
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -29,7 +29,7 @@ GLenum to_gl(const blending_constant &c) {
|
|||||||
void set_material(std::shared_ptr<material> &mat) {
|
void set_material(std::shared_ptr<material> &mat) {
|
||||||
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||||
|
|
||||||
mat->shader_->use();
|
mat->shader->bind();
|
||||||
|
|
||||||
// if (material->textures[TextureRole::Diffuse]) {
|
// if (material->textures[TextureRole::Diffuse]) {
|
||||||
// std::cout << "CAN has diffuse texture!!!!!!!!!11" << std::endl;
|
// std::cout << "CAN has diffuse texture!!!!!!!!!11" << std::endl;
|
||||||
@@ -86,7 +86,7 @@ void unset_material(std::shared_ptr<material> &mat) {
|
|||||||
// textureUnit++;
|
// textureUnit++;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
mat->shader_->unuse();
|
mat->shader->unbind();
|
||||||
|
|
||||||
if (mat->transparent)
|
if (mat->transparent)
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
|
|||||||
+2
-2
@@ -3,7 +3,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include "texture.h"
|
#include "texture.h"
|
||||||
#include "shader.h"
|
#include "shader_program.h"
|
||||||
#include "glm/glm.hpp"
|
#include "glm/glm.hpp"
|
||||||
|
|
||||||
BEGIN_NAMESPACE
|
BEGIN_NAMESPACE
|
||||||
@@ -52,7 +52,7 @@ struct material {
|
|||||||
blending_constant blend_dst_fact = blending_constant::one_minus_src_alpha;
|
blending_constant blend_dst_fact = blending_constant::one_minus_src_alpha;
|
||||||
|
|
||||||
fill_mode_type fill_mode = fill_mode_type::solid;
|
fill_mode_type fill_mode = fill_mode_type::solid;
|
||||||
std::shared_ptr<shader> shader_;
|
std::shared_ptr<shader_program> shader;
|
||||||
texture_map textures;
|
texture_map textures;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ BEGIN_NAMESPACE
|
|||||||
|
|
||||||
struct mesh_node : scene_node {
|
struct mesh_node : scene_node {
|
||||||
mesh_node();
|
mesh_node();
|
||||||
mesh_node(std::string name);
|
explicit mesh_node(std::string name);
|
||||||
|
|
||||||
std::shared_ptr<mesh> mesh_;
|
std::shared_ptr<mesh> mesh_;
|
||||||
std::shared_ptr<material> material_;
|
std::shared_ptr<material> material_;
|
||||||
|
|||||||
@@ -0,0 +1,225 @@
|
|||||||
|
#include "particles.h"
|
||||||
|
|
||||||
|
BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
particle_emitter::particle_emitter() {
|
||||||
|
to_spawn = 0;
|
||||||
|
start_size = 1.0f;
|
||||||
|
end_size = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
particle *particle_emitter::new_particle() {
|
||||||
|
particle *p;
|
||||||
|
if (dead_particles.empty()) {
|
||||||
|
p = new particle{};
|
||||||
|
} else {
|
||||||
|
p = dead_particles.back();
|
||||||
|
dead_particles.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
particles.push_back(p);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void particle_emitter::update(float elapsed_ms) {
|
||||||
|
float factor = elapsed_ms / 1000.0f;
|
||||||
|
|
||||||
|
for (auto p : particles) {
|
||||||
|
p->old_pos = p->position;
|
||||||
|
p->position += p->velocity * factor;
|
||||||
|
p->life -= life_decay * factor;
|
||||||
|
p->color = glm::mix(start_colour, end_colour, p->life);
|
||||||
|
p->size = glm::mix(start_size, end_size, p->life);
|
||||||
|
}
|
||||||
|
|
||||||
|
// move dead particles to the dead list
|
||||||
|
auto pit = particles.begin();
|
||||||
|
while (pit != particles.end()) {
|
||||||
|
if ((*pit)->life <= 0.0) {
|
||||||
|
dead_particles.push_back(*pit);
|
||||||
|
pit = particles.erase(pit);
|
||||||
|
} else {
|
||||||
|
++pit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// spawn if needed
|
||||||
|
to_spawn += factor * emission_rate;
|
||||||
|
auto new_particles = static_cast<int>(to_spawn);
|
||||||
|
|
||||||
|
for (auto i = 0; i < new_particles; i++) {
|
||||||
|
particle *p = new_particle();
|
||||||
|
spawn(p);
|
||||||
|
}
|
||||||
|
to_spawn -= static_cast<float>(new_particles);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void particle_system::update(float elapsed_ms) {
|
||||||
|
particles.clear();
|
||||||
|
|
||||||
|
for (auto& emitter: emitters) {
|
||||||
|
emitter->update(elapsed_ms);
|
||||||
|
std::copy(emitter->particles.begin(), emitter->particles.end(), std::back_inserter(particles));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& modifier: modifiers) {
|
||||||
|
for (auto& particle: particles) {
|
||||||
|
modifier->affect_particle(particle, elapsed_ms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void particle_system::render() {
|
||||||
|
|
||||||
|
// draw trail
|
||||||
|
// draw head
|
||||||
|
|
||||||
|
// Matrix mat;
|
||||||
|
// mat.fromGL(GL_MODELVIEW_MATRIX);
|
||||||
|
//
|
||||||
|
// Vector3D a(mat._mat[0], mat._mat[4], mat._mat[8]);
|
||||||
|
// Vector3D b(mat._mat[1], mat._mat[5], mat._mat[9]);
|
||||||
|
//
|
||||||
|
// Vector3D pos[4];
|
||||||
|
// pos[0] = (-a - b);
|
||||||
|
// pos[1] = (a - b);
|
||||||
|
// pos[2] = (a + b);
|
||||||
|
// pos[3] = (-a + b);
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// glEnable(GL_COLOR_MATERIAL);
|
||||||
|
// glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
|
||||||
|
//
|
||||||
|
// glBegin(GL_QUADS);
|
||||||
|
//
|
||||||
|
// for (ParticleList::iterator it = particles.begin(); it != particles.end(); it++) {
|
||||||
|
// Particle *p = (*it);
|
||||||
|
//
|
||||||
|
// glColor4d(p->color.r, p->color.g, p->color.b, p->color.a);
|
||||||
|
//
|
||||||
|
// glTexCoord2f(1.0f, 1.0f);
|
||||||
|
// glVertex3d(pos[0].x * p->size + p->position.x, pos[0].y * p->size + p->position.y, pos[0].z * p->size + p->position.z);
|
||||||
|
//
|
||||||
|
// glTexCoord2f(0.0f, 1.0f);
|
||||||
|
// glVertex3d(pos[1].x * p->size + p->position.x, pos[1].y * p->size + p->position.y, pos[1].z * p->size + p->position.z);
|
||||||
|
//
|
||||||
|
// glTexCoord2f(0.0f, 0.0f);
|
||||||
|
// glVertex3d(pos[2].x * p->size + p->position.x, pos[2].y * p->size + p->position.y, pos[2].z * p->size + p->position.z);
|
||||||
|
//
|
||||||
|
// glTexCoord2f(1.0f, 0.0f);
|
||||||
|
// glVertex3d(pos[3].x * p->size + p->position.x, pos[3].y * p->size + p->position.y, pos[3].z * p->size + p->position.z);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// glEnd();
|
||||||
|
//
|
||||||
|
// //
|
||||||
|
//
|
||||||
|
// glDisable(GL_TEXTURE_2D);
|
||||||
|
// glBegin(GL_LINES);
|
||||||
|
//
|
||||||
|
// for (ParticleList::iterator it = particles.begin(); it != particles.end(); it++) {
|
||||||
|
// Particle *p = (*it);
|
||||||
|
//
|
||||||
|
// glColor4d(p->color.r, p->color.g, p->color.b, p->color.a);
|
||||||
|
//
|
||||||
|
// glVertex3d(p->previousPosition.x, p->previousPosition.y, p->previousPosition.z);
|
||||||
|
// glVertex3d(p->position.x, p->position.y, p->position.z);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// glEnd();
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// glDisable(GL_COLOR_MATERIAL);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
glEnable( GL_COLOR_MATERIAL );
|
||||||
|
glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );
|
||||||
|
|
||||||
|
glEnable( GL_BLEND );
|
||||||
|
glBlendFunc( GL_SRC_ALPHA, GL_ONE );
|
||||||
|
|
||||||
|
|
||||||
|
// This is how will our point sprite's size will be modified by
|
||||||
|
// distance from the viewer
|
||||||
|
float quadratic[] = { 1.0f, 0.0f, 0.01f };
|
||||||
|
glPointParameterfvARB( GL_POINT_DISTANCE_ATTENUATION_ARB, quadratic );
|
||||||
|
|
||||||
|
// Query for the max point size supported by the hardware
|
||||||
|
float maxSize = 0.0f;
|
||||||
|
glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize );
|
||||||
|
|
||||||
|
// Clamp size to 100.0f or the sprites could get a little too big on some
|
||||||
|
// of the newer graphic cards. My ATI card at home supports a max point
|
||||||
|
// size of 1024.0f!
|
||||||
|
maxSize = min( maxSize, 100.0f );
|
||||||
|
glPointSize( maxSize );
|
||||||
|
|
||||||
|
// The alpha of a point is calculated to allow the fading of points
|
||||||
|
// instead of shrinking them past a defined threshold size. The threshold
|
||||||
|
// is defined by GL_POINT_FADE_THRESHOLD_SIZE_ARB and is not clamped to
|
||||||
|
// the minimum and maximum point sizes.
|
||||||
|
glPointParameterfARB( GL_POINT_FADE_THRESHOLD_SIZE_ARB, 60.0f );
|
||||||
|
|
||||||
|
glPointParameterfARB( GL_POINT_SIZE_MIN_ARB, 1.0f );
|
||||||
|
glPointParameterfARB( GL_POINT_SIZE_MAX_ARB, maxSize );
|
||||||
|
|
||||||
|
// Specify point sprite texture coordinate replacement mode for each
|
||||||
|
// texture unit
|
||||||
|
glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE );
|
||||||
|
|
||||||
|
glEnable( GL_POINT_SPRITE_ARB );
|
||||||
|
|
||||||
|
|
||||||
|
glBegin( GL_POINTS );
|
||||||
|
for ( ParticleList::iterator it = particles.begin(); it != particles.end(); it++ ) {
|
||||||
|
Particle *p = (*it);
|
||||||
|
glColor4d( p->color.r, p->color.g, p->color.b, p->color.a );
|
||||||
|
glVertex3d( p->position.x, p->position.y, p->position.z );
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
glDisable( GL_POINT_SPRITE_ARB );
|
||||||
|
glDisable( GL_BLEND );
|
||||||
|
|
||||||
|
glDisable( GL_COLOR_MATERIAL );
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
dot_particle_emitter::dot_particle_emitter() {
|
||||||
|
emission_rate = 30.0f;
|
||||||
|
life_decay = 0.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dot_particle_emitter::spawn(acidrain::particle *p) {
|
||||||
|
if (nullptr == p) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
p->position = {0, 0, 0};
|
||||||
|
p->color = {rand_in_range(0, 1), rand_in_range(0, 1), rand_in_range(0, 1), 1.0};
|
||||||
|
p->velocity = glm::normalize(glm::vec3(rand_in_range(-1, 1), rand_in_range(-1, 1), rand_in_range(-1, 1)));
|
||||||
|
// p->velocity *= 10;
|
||||||
|
|
||||||
|
p->life = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
END_NAMESPACE
|
||||||
|
|
||||||
|
void acidrain::particle_attractor::init(glm::vec3& center, float s) {
|
||||||
|
attractor_center = center;
|
||||||
|
strength = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void acidrain::particle_attractor::affect_particle(acidrain::particle *p, float elapsed_ms) {
|
||||||
|
float factor = elapsed_ms / 1000.0f;
|
||||||
|
|
||||||
|
glm::vec3 attract_direction = attractor_center - p->position;
|
||||||
|
float distance_to_center = glm::length(attract_direction);
|
||||||
|
|
||||||
|
float amount = 1.0f / (distance_to_center * distance_to_center) * strength;
|
||||||
|
p->velocity += attract_direction * amount * factor;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "defines.h"
|
||||||
|
#include "colour.h"
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
struct particle;
|
||||||
|
struct particle_emitter;
|
||||||
|
struct particle_modifier;
|
||||||
|
|
||||||
|
using particle_list = std::vector<particle *>;
|
||||||
|
using particle_emitter_list = std::vector<particle_emitter *>;
|
||||||
|
using particle_modifier_list = std::vector<particle_modifier *>;
|
||||||
|
|
||||||
|
struct particle {
|
||||||
|
glm::vec3 position;
|
||||||
|
glm::vec3 old_pos;
|
||||||
|
glm::vec3 velocity;
|
||||||
|
colour color;
|
||||||
|
float life;
|
||||||
|
float size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct particle_emitter {
|
||||||
|
particle_emitter();
|
||||||
|
virtual ~particle_emitter() = default;
|
||||||
|
|
||||||
|
particle *new_particle();
|
||||||
|
void update(float elapsed_ms);
|
||||||
|
|
||||||
|
virtual void spawn(particle *p) = 0;
|
||||||
|
|
||||||
|
particle_list particles;
|
||||||
|
particle_list dead_particles;
|
||||||
|
|
||||||
|
glm::vec3 position{};
|
||||||
|
float emission_rate{}; // particles per second
|
||||||
|
float to_spawn;
|
||||||
|
float life_decay{};
|
||||||
|
colour start_colour{};
|
||||||
|
colour end_colour{};
|
||||||
|
float start_size;
|
||||||
|
float end_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct particle_modifier {
|
||||||
|
virtual void affect_particle(particle *p, float elapsed_ms) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct particle_system {
|
||||||
|
void update(float elapsed_ms);
|
||||||
|
void render();
|
||||||
|
|
||||||
|
particle_list particles;
|
||||||
|
particle_emitter_list emitters;
|
||||||
|
particle_modifier_list modifiers;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dot_particle_emitter : particle_emitter {
|
||||||
|
dot_particle_emitter();
|
||||||
|
void spawn(particle *p) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct particle_attractor : particle_modifier {
|
||||||
|
void init(glm::vec3& center, float strength_);
|
||||||
|
void affect_particle(particle *p, float elapsed_ms) override;
|
||||||
|
|
||||||
|
glm::vec3 attractor_center;
|
||||||
|
float strength;
|
||||||
|
};
|
||||||
|
|
||||||
|
END_NAMESPACE
|
||||||
+1
-1
@@ -5,7 +5,7 @@ BEGIN_NAMESPACE
|
|||||||
|
|
||||||
class peripherals {
|
class peripherals {
|
||||||
public:
|
public:
|
||||||
virtual bool init() = 0;
|
virtual bool init(uint16_t width, uint16_t height, const char* title, bool fullscreen = false) = 0;
|
||||||
virtual void swap_buffers() = 0;
|
virtual void swap_buffers() = 0;
|
||||||
virtual void poll_events() = 0;
|
virtual void poll_events() = 0;
|
||||||
virtual bool should_close() = 0;
|
virtual bool should_close() = 0;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "peripherals_glfw.h"
|
#include "peripherals_glfw.h"
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "demo_data.h"
|
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
|
|
||||||
BEGIN_NAMESPACE
|
BEGIN_NAMESPACE
|
||||||
@@ -20,7 +19,7 @@ static void key_callback(GLFWwindow *window, int key, int scancode, int action,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool peripherals_glfw::init() {
|
bool peripherals_glfw::init(uint16_t width, uint16_t height, const char *title, bool fullscreen) {
|
||||||
glfwInit();
|
glfwInit();
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
|
||||||
@@ -31,10 +30,9 @@ bool peripherals_glfw::init() {
|
|||||||
glfwSetErrorCallback(error_callback);
|
glfwSetErrorCallback(error_callback);
|
||||||
|
|
||||||
|
|
||||||
bool fullscreen = false;
|
window = glfwCreateWindow(width,
|
||||||
window = glfwCreateWindow(demo_data::screen_width,
|
height,
|
||||||
demo_data::screen_height,
|
title,
|
||||||
"Demo",
|
|
||||||
fullscreen ? glfwGetPrimaryMonitor() : nullptr,
|
fullscreen ? glfwGetPrimaryMonitor() : nullptr,
|
||||||
nullptr);
|
nullptr);
|
||||||
if (window == nullptr) {
|
if (window == nullptr) {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ BEGIN_NAMESPACE
|
|||||||
class peripherals_glfw : public peripherals {
|
class peripherals_glfw : public peripherals {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
bool init() override;
|
bool init(uint16_t width, uint16_t height, const char* title, bool fullscreen = false) override;
|
||||||
void swap_buffers() override;
|
void swap_buffers() override;
|
||||||
void poll_events() override;
|
void poll_events() override;
|
||||||
bool should_close() override;
|
bool should_close() override;
|
||||||
|
|||||||
+263
@@ -0,0 +1,263 @@
|
|||||||
|
#include "perlin.h"
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
// Thank you, Ken Perlin
|
||||||
|
|
||||||
|
BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
namespace perlin {
|
||||||
|
|
||||||
|
#define B 0x100
|
||||||
|
#define BM 0xff
|
||||||
|
#define N 0x1000
|
||||||
|
#define NP 12 /* 2^N */
|
||||||
|
#define NM 0xfff
|
||||||
|
|
||||||
|
#define s_curve(t) ( t * t * (3. - 2. * t) )
|
||||||
|
#define lerp(t, a, b) ( a + t * (b - a) )
|
||||||
|
#define setup(i, b0, b1, r0, r1)\
|
||||||
|
t = vec[i] + N;\
|
||||||
|
b0 = ((int)t) & BM;\
|
||||||
|
b1 = (b0+1) & BM;\
|
||||||
|
r0 = t - (int)t;\
|
||||||
|
r1 = r0 - 1.;
|
||||||
|
#define at2(rx, ry) ( rx * q[0] + ry * q[1] )
|
||||||
|
#define at3(rx, ry, rz) ( rx * q[0] + ry * q[1] + rz * q[2] )
|
||||||
|
|
||||||
|
|
||||||
|
/* Coherent noise function over 1, 2 or 3 dimensions */
|
||||||
|
/* (copyright Ken Perlin) */
|
||||||
|
|
||||||
|
static int p[B + B + 2];
|
||||||
|
static double g3[B + B + 2][3];
|
||||||
|
static double g2[B + B + 2][2];
|
||||||
|
static double g1[B + B + 2];
|
||||||
|
static int start = 1;
|
||||||
|
|
||||||
|
double noise1(double arg) {
|
||||||
|
int bx0, bx1;
|
||||||
|
double rx0, rx1, sx, t, u, v, vec[1];
|
||||||
|
|
||||||
|
vec[0] = arg;
|
||||||
|
if (start) {
|
||||||
|
start = 0;
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
setup(0, bx0, bx1, rx0, rx1);
|
||||||
|
|
||||||
|
sx = s_curve(rx0);
|
||||||
|
u = rx0 * g1[p[bx0]];
|
||||||
|
v = rx1 * g1[p[bx1]];
|
||||||
|
|
||||||
|
return (lerp(sx, u, v));
|
||||||
|
}
|
||||||
|
|
||||||
|
double noise2(double vec[2]) {
|
||||||
|
int bx0, bx1, by0, by1, b00, b10, b01, b11;
|
||||||
|
double rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
if (start) {
|
||||||
|
start = 0;
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
setup(0, bx0, bx1, rx0, rx1);
|
||||||
|
setup(1, by0, by1, ry0, ry1);
|
||||||
|
|
||||||
|
i = p[bx0];
|
||||||
|
j = p[bx1];
|
||||||
|
|
||||||
|
b00 = p[i + by0];
|
||||||
|
b10 = p[j + by0];
|
||||||
|
b01 = p[i + by1];
|
||||||
|
b11 = p[j + by1];
|
||||||
|
|
||||||
|
sx = s_curve(rx0);
|
||||||
|
sy = s_curve(ry0);
|
||||||
|
|
||||||
|
q = g2[b00];
|
||||||
|
u = at2(rx0, ry0);
|
||||||
|
q = g2[b10];
|
||||||
|
v = at2(rx1, ry0);
|
||||||
|
a = lerp(sx, u, v);
|
||||||
|
|
||||||
|
q = g2[b01];
|
||||||
|
u = at2(rx0, ry1);
|
||||||
|
q = g2[b11];
|
||||||
|
v = at2(rx1, ry1);
|
||||||
|
b = lerp(sx, u, v);
|
||||||
|
|
||||||
|
return lerp(sy, a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
double noise3(double vec[3]) {
|
||||||
|
int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
|
||||||
|
double rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
if (start) {
|
||||||
|
start = 0;
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
setup(0, bx0, bx1, rx0, rx1);
|
||||||
|
setup(1, by0, by1, ry0, ry1);
|
||||||
|
setup(2, bz0, bz1, rz0, rz1);
|
||||||
|
|
||||||
|
i = p[bx0];
|
||||||
|
j = p[bx1];
|
||||||
|
|
||||||
|
b00 = p[i + by0];
|
||||||
|
b10 = p[j + by0];
|
||||||
|
b01 = p[i + by1];
|
||||||
|
b11 = p[j + by1];
|
||||||
|
|
||||||
|
t = s_curve(rx0);
|
||||||
|
sy = s_curve(ry0);
|
||||||
|
sz = s_curve(rz0);
|
||||||
|
|
||||||
|
q = g3[b00 + bz0];
|
||||||
|
u = at3(rx0, ry0, rz0);
|
||||||
|
q = g3[b10 + bz0];
|
||||||
|
v = at3(rx1, ry0, rz0);
|
||||||
|
a = lerp(t, u, v);
|
||||||
|
|
||||||
|
q = g3[b01 + bz0];
|
||||||
|
u = at3(rx0, ry1, rz0);
|
||||||
|
q = g3[b11 + bz0];
|
||||||
|
v = at3(rx1, ry1, rz0);
|
||||||
|
b = lerp(t, u, v);
|
||||||
|
|
||||||
|
c = lerp(sy, a, b);
|
||||||
|
|
||||||
|
q = g3[b00 + bz1];
|
||||||
|
u = at3(rx0, ry0, rz1);
|
||||||
|
q = g3[b10 + bz1];
|
||||||
|
v = at3(rx1, ry0, rz1);
|
||||||
|
a = lerp(t, u, v);
|
||||||
|
|
||||||
|
q = g3[b01 + bz1];
|
||||||
|
u = at3(rx0, ry1, rz1);
|
||||||
|
q = g3[b11 + bz1];
|
||||||
|
v = at3(rx1, ry1, rz1);
|
||||||
|
b = lerp(t, u, v);
|
||||||
|
|
||||||
|
d = lerp(sy, a, b);
|
||||||
|
|
||||||
|
return lerp(sz, c, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
void normalize2(double v[2]) {
|
||||||
|
double s;
|
||||||
|
|
||||||
|
s = sqrt(v[0] * v[0] + v[1] * v[1]);
|
||||||
|
v[0] = v[0] / s;
|
||||||
|
v[1] = v[1] / s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void normalize3(double v[3]) {
|
||||||
|
double s;
|
||||||
|
|
||||||
|
s = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
|
||||||
|
v[0] = v[0] / s;
|
||||||
|
v[1] = v[1] / s;
|
||||||
|
v[2] = v[2] / s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- My harmonic summing functions - PDB --------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
In what follows "alpha" is the weight when the sum is formed.
|
||||||
|
Typically it is 2, As this approaches 1 the function is noisier.
|
||||||
|
"beta" is the harmonic scaling/spacing, typically 2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
double noise1D(double x, double alpha, double beta, int n) {
|
||||||
|
int i;
|
||||||
|
double val, sum = 0;
|
||||||
|
double p, scale = 1;
|
||||||
|
|
||||||
|
p = x;
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
val = noise1(p);
|
||||||
|
sum += val / scale;
|
||||||
|
scale *= alpha;
|
||||||
|
p *= beta;
|
||||||
|
}
|
||||||
|
return (sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
double noise2D(double x, double y, double alpha, double beta, int n) {
|
||||||
|
int i;
|
||||||
|
double val, sum = 0;
|
||||||
|
double p[2], scale = 1;
|
||||||
|
|
||||||
|
p[0] = x;
|
||||||
|
p[1] = y;
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
val = noise2(p);
|
||||||
|
sum += val / scale;
|
||||||
|
scale *= alpha;
|
||||||
|
p[0] *= beta;
|
||||||
|
p[1] *= beta;
|
||||||
|
}
|
||||||
|
return (sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
double noise3D(double x, double y, double z, double alpha, double beta, int n) {
|
||||||
|
int i;
|
||||||
|
double val, sum = 0;
|
||||||
|
double p[3], scale = 1;
|
||||||
|
|
||||||
|
p[0] = x;
|
||||||
|
p[1] = y;
|
||||||
|
p[2] = z;
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
val = noise3(p);
|
||||||
|
sum += val / scale;
|
||||||
|
scale *= alpha;
|
||||||
|
p[0] *= beta;
|
||||||
|
p[1] *= beta;
|
||||||
|
p[2] *= beta;
|
||||||
|
}
|
||||||
|
return (sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
void init() {
|
||||||
|
int i, j, k;
|
||||||
|
|
||||||
|
for (i = 0; i < B; i++) {
|
||||||
|
p[i] = i;
|
||||||
|
g1[i] = (double) ((rand() % (B + B)) - B) / B;
|
||||||
|
|
||||||
|
for (j = 0; j < 2; j++)
|
||||||
|
g2[i][j] = (double) ((rand() % (B + B)) - B) / B;
|
||||||
|
normalize2(g2[i]);
|
||||||
|
|
||||||
|
for (j = 0; j < 3; j++)
|
||||||
|
g3[i][j] = (double) ((rand() % (B + B)) - B) / B;
|
||||||
|
normalize3(g3[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (--i) {
|
||||||
|
k = p[i];
|
||||||
|
p[i] = p[j = rand() % B];
|
||||||
|
p[j] = k;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < B + 2; i++) {
|
||||||
|
p[B + i] = p[i];
|
||||||
|
g1[B + i] = g1[i];
|
||||||
|
for (j = 0; j < 2; j++)
|
||||||
|
g2[B + i][j] = g2[i][j];
|
||||||
|
for (j = 0; j < 3; j++)
|
||||||
|
g3[B + i][j] = g3[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
END_NAMESPACE
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "defines.h"
|
||||||
|
|
||||||
|
BEGIN_NAMESPACE
|
||||||
|
namespace perlin {
|
||||||
|
|
||||||
|
void init();
|
||||||
|
|
||||||
|
double noise1D(double x, double alpha, double beta, int n);
|
||||||
|
double noise2D(double x, double y, double alpha, double beta, int n);
|
||||||
|
double noise3D(double x, double y, double z, double alpha, double beta, int n);
|
||||||
|
}
|
||||||
|
END_NAMESPACE
|
||||||
@@ -35,4 +35,11 @@ camera_node &scene_node::as_camera_node() {
|
|||||||
return *static_cast<camera_node *>(this);
|
return *static_cast<camera_node *>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t current_id = 0;
|
||||||
|
|
||||||
|
scene_node::scene_node() {
|
||||||
|
id = current_id++;
|
||||||
|
rotation = glm::angleAxis(0.0f, glm::vec3(1, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
END_NAMESPACE
|
END_NAMESPACE
|
||||||
|
|||||||
+3
-1
@@ -21,6 +21,8 @@ struct light_node;
|
|||||||
struct camera_node;
|
struct camera_node;
|
||||||
|
|
||||||
struct scene_node {
|
struct scene_node {
|
||||||
|
scene_node();
|
||||||
|
|
||||||
virtual void calculate_local_transform();
|
virtual void calculate_local_transform();
|
||||||
void apply_parent_transform(const glm::mat4& parent_transform);
|
void apply_parent_transform(const glm::mat4& parent_transform);
|
||||||
|
|
||||||
@@ -28,7 +30,7 @@ struct scene_node {
|
|||||||
light_node& as_light_node();
|
light_node& as_light_node();
|
||||||
camera_node& as_camera_node();
|
camera_node& as_camera_node();
|
||||||
|
|
||||||
int id;
|
size_t id;
|
||||||
std::string name;
|
std::string name;
|
||||||
scene_node_type type; // We rely on type comparison instead of dynamic casting because comparing types is much faster
|
scene_node_type type; // We rely on type comparison instead of dynamic casting because comparing types is much faster
|
||||||
|
|
||||||
|
|||||||
+73
-54
@@ -1,6 +1,6 @@
|
|||||||
#include "scene_renderer.h"
|
#include "scene_renderer.h"
|
||||||
#include "light_node.h"
|
#include "light_node.h"
|
||||||
#include "shader.h"
|
#include "shader_program.h"
|
||||||
#include "material.h"
|
#include "material.h"
|
||||||
#include "mesh_node.h"
|
#include "mesh_node.h"
|
||||||
#include "demo_data.h"
|
#include "demo_data.h"
|
||||||
@@ -277,20 +277,20 @@ scene_renderer::scene_renderer()
|
|||||||
|
|
||||||
glGenFramebuffers(1, &fbo_id);
|
glGenFramebuffers(1, &fbo_id);
|
||||||
|
|
||||||
first_pass_shadow_shader = std::make_shared<shader>(vs, ps);
|
first_pass_shadow_shader = std::make_shared<shader_program>(vs, ps);
|
||||||
|
|
||||||
first_pass_shadow_material = std::make_shared<material>();
|
first_pass_shadow_material = std::make_shared<material>();
|
||||||
first_pass_shadow_material->shader_ = first_pass_shadow_shader;
|
first_pass_shadow_material->shader = first_pass_shadow_shader;
|
||||||
first_pass_shadow_material->zbuffer_write = true;
|
first_pass_shadow_material->zbuffer_write = true;
|
||||||
first_pass_shadow_material->zbuffer_test = true;
|
first_pass_shadow_material->zbuffer_test = true;
|
||||||
first_pass_shadow_material->transparent = false;
|
first_pass_shadow_material->transparent = false;
|
||||||
first_pass_shadow_material->cull_faces = true;
|
first_pass_shadow_material->cull_faces = true;
|
||||||
first_pass_shadow_material->cull_front_faces = false;
|
first_pass_shadow_material->cull_front_faces = false;
|
||||||
|
|
||||||
second_pass_shadow_shader = std::make_shared<shader>(vs3, ps3);
|
second_pass_shadow_shader = std::make_shared<shader_program>(vs3, ps3);
|
||||||
|
|
||||||
second_pass_shadow_material = std::make_shared<material>();
|
second_pass_shadow_material = std::make_shared<material>();
|
||||||
second_pass_shadow_material->shader_ = second_pass_shadow_shader;
|
second_pass_shadow_material->shader = second_pass_shadow_shader;
|
||||||
second_pass_shadow_material->diffuse = glm::vec4(1, 0, 0, 1);
|
second_pass_shadow_material->diffuse = glm::vec4(1, 0, 0, 1);
|
||||||
second_pass_shadow_material->zbuffer_write = true;
|
second_pass_shadow_material->zbuffer_write = true;
|
||||||
second_pass_shadow_material->zbuffer_test = true;
|
second_pass_shadow_material->zbuffer_test = true;
|
||||||
@@ -305,15 +305,28 @@ void scene_renderer::attach_depth_texture(texture &text) const {
|
|||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void scene_renderer::render(const scene_tree &tree, const std::string &cameraName) {
|
|
||||||
// for (auto &node: scene.lights) {
|
|
||||||
// light_node &light = node->as_light_node();
|
|
||||||
// glActiveTexture(GL_TEXTURE0);
|
|
||||||
// render_shadow_map(scene, light);
|
|
||||||
// }
|
|
||||||
|
|
||||||
std::shared_ptr<scene_node> camNode = tree.node_by_name_and_type(cameraName, scene_node_type::camera);
|
std::string to_string(const glm::vec3& v) {
|
||||||
camera_node &camera = camNode->as_camera_node();
|
std::stringstream ss;
|
||||||
|
ss << "{x:" << v.x << ", y:" << v.y << ", z:" << v.z << "}";
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string to_string(const glm::quat& v) {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "{x:" << v.x << ", y:" << v.y << ", z:" << v.z << ", w:" << v.w << "}";
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void scene_renderer::render(const scene_tree& tree, const std::string& cam_name) {
|
||||||
|
for (auto& node: tree.lights) {
|
||||||
|
light_node& light = node->as_light_node();
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
render_shadow_map(tree, light);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<scene_node> cam_node = tree.node_by_name_and_type(cam_name, scene_node_type::camera);
|
||||||
|
camera_node& camera = cam_node->as_camera_node();
|
||||||
|
|
||||||
shader_consts.set(uniforms::ViewMatrix, camera.view_matrix);
|
shader_consts.set(uniforms::ViewMatrix, camera.view_matrix);
|
||||||
shader_consts.set(uniforms::ProjectionMatrix, camera.projection_matrix);
|
shader_consts.set(uniforms::ProjectionMatrix, camera.projection_matrix);
|
||||||
@@ -323,74 +336,80 @@ std::shared_ptr<scene_node> camNode = tree.node_by_name_and_type(cameraName, sce
|
|||||||
|
|
||||||
set_material(second_pass_shadow_material);
|
set_material(second_pass_shadow_material);
|
||||||
|
|
||||||
int lightIndex = 0;
|
int light_index = 0;
|
||||||
for (auto& node: tree.lights) {
|
for (auto& node: tree.lights) {
|
||||||
light_node& light = node->as_light_node();
|
light_node& light = node->as_light_node();
|
||||||
|
|
||||||
shader_consts.set(uniforms::WorldToLightMatrix, light.world_to_light_matrix[0], lightIndex);
|
shader_consts.set(uniforms::WorldToLightMatrix, light.world_to_light_matrix[0], light_index);
|
||||||
shader_consts.set(uniforms::LightProjectionMatrix, light.light_projection_matrix[0], lightIndex);
|
shader_consts.set(uniforms::LightProjectionMatrix, light.light_projection_matrix[0], light_index);
|
||||||
shader_consts.set(uniforms::ShadowMatrix, light.final_shadow_map_matrix[0], lightIndex);
|
shader_consts.set(uniforms::ShadowMatrix, light.final_shadow_map_matrix[0], light_index);
|
||||||
shader_consts.set(uniforms::ShadowBiasMatrix, light.shadow_map_bias_matrix);
|
shader_consts.set(uniforms::ShadowBiasMatrix, light.shadow_map_bias_matrix);
|
||||||
|
|
||||||
glm::vec3 lightPositionInEyeSpace = light.position - camera.position;
|
glm::vec3 light_pos_in_eye_space = light.position - camera.position;
|
||||||
shader_consts.set(uniforms::LightPosition, lightPositionInEyeSpace, lightIndex);
|
shader_consts.set(uniforms::LightPosition, light_pos_in_eye_space, light_index);
|
||||||
|
|
||||||
glm::vec3 lightTargetInEyeSpace = light.spot_target - camera.position;
|
glm::vec3 light_target_in_eye_space = light.spot_target - camera.position;
|
||||||
shader_consts.set(uniforms::LightTarget, lightTargetInEyeSpace, lightIndex);
|
shader_consts.set(uniforms::LightTarget, light_target_in_eye_space, light_index);
|
||||||
|
|
||||||
shader_consts.set(uniforms::LightAmbient, light.ambient, lightIndex);
|
shader_consts.set(uniforms::LightAmbient, light.ambient, light_index);
|
||||||
shader_consts.set(uniforms::LightDiffuse, light.diffuse, lightIndex);
|
shader_consts.set(uniforms::LightDiffuse, light.diffuse, light_index);
|
||||||
shader_consts.set(uniforms::LightSpecular, light.specular, lightIndex);
|
shader_consts.set(uniforms::LightSpecular, light.specular, light_index);
|
||||||
|
|
||||||
shader_consts.set(uniforms::LightSpotCutoff, light.spot_cutoff, lightIndex);
|
shader_consts.set(uniforms::LightSpotCutoff, light.spot_cutoff, light_index);
|
||||||
shader_consts.set(uniforms::LightSpotExponent, light.spot_exponent, lightIndex);
|
shader_consts.set(uniforms::LightSpotExponent, light.spot_exponent, light_index);
|
||||||
shader_consts.set(uniforms::LightAttenuation, light.attenuation, lightIndex);
|
shader_consts.set(uniforms::LightAttenuation, light.attenuation, light_index);
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0 + 4 + lightIndex);
|
glActiveTexture(GL_TEXTURE0 + 4 + light_index);
|
||||||
glBindTexture(GL_TEXTURE_2D, light.shadow_map[0]->get_id());
|
glBindTexture(GL_TEXTURE_2D, light.shadow_map[0]->get_id());
|
||||||
|
|
||||||
if (lightIndex == 0) {
|
if (light_index == 0) {
|
||||||
shader_consts.set(uniforms::ShadowMap1, lightIndex + 4);
|
shader_consts.set(uniforms::ShadowMap1, light_index + 4);
|
||||||
} else if (lightIndex == 1) {
|
} else if (light_index == 1) {
|
||||||
shader_consts.set(uniforms::ShadowMap2, lightIndex + 4);
|
shader_consts.set(uniforms::ShadowMap2, light_index + 4);
|
||||||
} else if (lightIndex == 2) {
|
} else if (light_index == 2) {
|
||||||
shader_consts.set(uniforms::ShadowMap3, lightIndex + 4);
|
shader_consts.set(uniforms::ShadowMap3, light_index + 4);
|
||||||
} else if (lightIndex == 3) {
|
} else if (light_index == 3) {
|
||||||
shader_consts.set(uniforms::ShadowMap4, lightIndex + 4);
|
shader_consts.set(uniforms::ShadowMap4, light_index + 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
lightIndex++;
|
light_index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw opaque nodes
|
// draw opaque nodes
|
||||||
for (auto& node: tree.nodes) {
|
for (auto& node: tree.nodes) {
|
||||||
if (node->type == scene_node_type::mesh) {
|
if (node->type == scene_node_type::mesh) {
|
||||||
mesh_node &meshNode = node->as_mesh_node();
|
mesh_node& mesh_node = node->as_mesh_node();
|
||||||
|
|
||||||
glm::mat3 normalMatrix = glm::inverseTranspose(
|
// if (node->name == "light mesh") {
|
||||||
glm::mat3(camera.view_matrix * meshNode.model_to_world_space_matrix));
|
// LOG(INFO) << "rendering light mesh. position: " << to_string(mesh_node.position)
|
||||||
|
// << ", scale: " << to_string(mesh_node.scale)
|
||||||
|
// << ", rotation: " << to_string(mesh_node.rotation);
|
||||||
|
// }
|
||||||
|
|
||||||
shader_consts.set(uniforms::ModelToWorldMatrix, meshNode.model_to_world_space_matrix);
|
glm::mat3 normal_mat = glm::inverseTranspose(
|
||||||
shader_consts.set(uniforms::NormalMatrix, normalMatrix);
|
glm::mat3(camera.view_matrix * mesh_node.model_to_world_space_matrix));
|
||||||
shader_consts.set(uniforms::MaterialAmbientColor, meshNode.material_->ambient);
|
|
||||||
shader_consts.set(uniforms::MaterialDiffuseColor, meshNode.material_->diffuse);
|
|
||||||
shader_consts.set(uniforms::MaterialSpecularColor, meshNode.material_->specular);
|
|
||||||
shader_consts.set(uniforms::MaterialShininess, meshNode.material_->shininess);
|
|
||||||
|
|
||||||
shader_consts.apply_to(*second_pass_shadow_material->shader_);
|
shader_consts.set(uniforms::ModelToWorldMatrix, mesh_node.model_to_world_space_matrix);
|
||||||
|
shader_consts.set(uniforms::NormalMatrix, normal_mat);
|
||||||
|
shader_consts.set(uniforms::MaterialAmbientColor, mesh_node.material_->ambient);
|
||||||
|
shader_consts.set(uniforms::MaterialDiffuseColor, mesh_node.material_->diffuse);
|
||||||
|
shader_consts.set(uniforms::MaterialSpecularColor, mesh_node.material_->specular);
|
||||||
|
shader_consts.set(uniforms::MaterialShininess, mesh_node.material_->shininess);
|
||||||
|
|
||||||
if (meshNode.material_->textures[texture_role::diffuse]) {
|
shader_consts.apply_to(*second_pass_shadow_material->shader);
|
||||||
int textureUnit = 0;
|
|
||||||
glActiveTexture(GL_TEXTURE0 + textureUnit);
|
|
||||||
meshNode.material_->textures[texture_role::diffuse]->use();
|
|
||||||
|
|
||||||
second_pass_shadow_material->shader_->setIntUniform(textureUnit, "diffuseMap");
|
if (mesh_node.material_->textures[texture_role::diffuse]) {
|
||||||
|
int texture_unit = 0;
|
||||||
|
glActiveTexture(GL_TEXTURE0 + texture_unit);
|
||||||
|
mesh_node.material_->textures[texture_role::diffuse]->use();
|
||||||
|
|
||||||
|
second_pass_shadow_material->shader->set_int(texture_unit, "diffuseMap");
|
||||||
} else {
|
} else {
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
meshNode.mesh_->render(second_pass_shadow_material->flat_shaded);
|
mesh_node.mesh_->render(second_pass_shadow_material->flat_shaded);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -422,7 +441,7 @@ void scene_renderer::render_shadow_map(const scene_tree &scene, light_node &ligh
|
|||||||
if (!meshNode.material_->transparent && meshNode.material_->cast_shadows) {
|
if (!meshNode.material_->transparent && meshNode.material_->cast_shadows) {
|
||||||
|
|
||||||
shader_consts.set(uniforms::ModelToWorldMatrix, meshNode.model_to_world_space_matrix);
|
shader_consts.set(uniforms::ModelToWorldMatrix, meshNode.model_to_world_space_matrix);
|
||||||
shader_consts.apply_to(*first_pass_shadow_material->shader_);
|
shader_consts.apply_to(*first_pass_shadow_material->shader);
|
||||||
|
|
||||||
meshNode.mesh_->render(first_pass_shadow_material->flat_shaded);
|
meshNode.mesh_->render(first_pass_shadow_material->flat_shaded);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
BEGIN_NAMESPACE
|
BEGIN_NAMESPACE
|
||||||
|
|
||||||
class shader;
|
class shader_program;
|
||||||
|
|
||||||
class material;
|
class material;
|
||||||
|
|
||||||
@@ -17,16 +17,16 @@ public:
|
|||||||
|
|
||||||
scene_renderer();
|
scene_renderer();
|
||||||
|
|
||||||
void render(const scene_tree &tree, const std::string &cameraName);
|
void render(const scene_tree &tree, const std::string &cam_name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void attach_depth_texture(texture &text) const;
|
void attach_depth_texture(texture &text) const;
|
||||||
void render_shadow_map(const scene_tree &scene, light_node &light);
|
void render_shadow_map(const scene_tree &scene, light_node &light);
|
||||||
|
|
||||||
std::shared_ptr<shader> first_pass_shadow_shader;
|
std::shared_ptr<shader_program> first_pass_shadow_shader;
|
||||||
std::shared_ptr<material> first_pass_shadow_material;
|
std::shared_ptr<material> first_pass_shadow_material;
|
||||||
|
|
||||||
std::shared_ptr<shader> second_pass_shadow_shader;
|
std::shared_ptr<shader_program> second_pass_shadow_shader;
|
||||||
std::shared_ptr<material> second_pass_shadow_material;
|
std::shared_ptr<material> second_pass_shadow_material;
|
||||||
|
|
||||||
shader_constants shader_consts;
|
shader_constants shader_consts;
|
||||||
|
|||||||
+8
-6
@@ -1,29 +1,31 @@
|
|||||||
#include "scene_tree.h"
|
#include "scene_tree.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
BEGIN_NAMESPACE
|
BEGIN_NAMESPACE
|
||||||
|
|
||||||
std::shared_ptr<scene_node> scene_tree::nodeById(int id) const {
|
std::shared_ptr<scene_node> scene_tree::node_by_id(size_t id) const {
|
||||||
for (auto& node : nodes)
|
for (auto& node : nodes)
|
||||||
if (node->id == id)
|
if (node->id == id)
|
||||||
return node;
|
return node;
|
||||||
|
|
||||||
return std::shared_ptr<scene_node>(nullptr);
|
return {nullptr};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<scene_node> scene_tree::node_by_name_and_type(std::string name, scene_node_type type) const {
|
std::shared_ptr<scene_node> scene_tree::node_by_name_and_type(const std::string& name, scene_node_type type) const {
|
||||||
for (auto& node : nodes)
|
for (auto& node : nodes)
|
||||||
if (node->name == name && node->type == type)
|
if (node->name == name && node->type == type)
|
||||||
return node;
|
return node;
|
||||||
|
|
||||||
return std::shared_ptr<scene_node>(nullptr);
|
return {nullptr};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void scene_tree::add(std::shared_ptr<scene_node> node) {
|
void scene_tree::add(std::shared_ptr<scene_node> node) {
|
||||||
add(node, std::shared_ptr<scene_node>(nullptr));
|
add(std::move(node), std::shared_ptr<scene_node>(nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
void scene_tree::add(std::shared_ptr<scene_node> node, std::shared_ptr<scene_node> parent) {
|
void scene_tree::add(const std::shared_ptr<scene_node>& node, std::shared_ptr<scene_node> parent) {
|
||||||
nodes.push_back(node);
|
nodes.push_back(node);
|
||||||
node->parent = parent;
|
node->parent = parent;
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -8,11 +8,11 @@ BEGIN_NAMESPACE
|
|||||||
class scene_tree {
|
class scene_tree {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
std::shared_ptr<scene_node> nodeById(int id) const;
|
std::shared_ptr<scene_node> node_by_id(size_t id) const;
|
||||||
std::shared_ptr<scene_node> node_by_name_and_type(std::string name, scene_node_type type) const;
|
std::shared_ptr<scene_node> node_by_name_and_type(const std::string& name, scene_node_type type) const;
|
||||||
|
|
||||||
void add(std::shared_ptr<scene_node> node);
|
void add(std::shared_ptr<scene_node> node);
|
||||||
void add(std::shared_ptr<scene_node> node, std::shared_ptr<scene_node> parent);
|
void add(const std::shared_ptr<scene_node>& node, std::shared_ptr<scene_node> parent);
|
||||||
|
|
||||||
void transform();
|
void transform();
|
||||||
|
|
||||||
|
|||||||
+21
-21
@@ -1,4 +1,4 @@
|
|||||||
#include "shader.h"
|
#include "shader_program.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
BEGIN_NAMESPACE
|
BEGIN_NAMESPACE
|
||||||
@@ -47,7 +47,7 @@ void check_link_error(GLuint program_id) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shader::shader(const char *vs_content, const char *ps_content)
|
shader_program::shader_program(const char *vs_content, const char *ps_content)
|
||||||
: shader_ids{0, 0},
|
: shader_ids{0, 0},
|
||||||
program_id{0} {
|
program_id{0} {
|
||||||
|
|
||||||
@@ -117,7 +117,7 @@ shader::shader(const char *vs_content, const char *ps_content)
|
|||||||
// glUseProgram(program_id);
|
// glUseProgram(program_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
shader::~shader() {
|
shader_program::~shader_program() {
|
||||||
glDetachShader(program_id, shader_ids[0]);
|
glDetachShader(program_id, shader_ids[0]);
|
||||||
glDetachShader(program_id, shader_ids[1]);
|
glDetachShader(program_id, shader_ids[1]);
|
||||||
|
|
||||||
@@ -127,53 +127,53 @@ shader::~shader() {
|
|||||||
glDeleteProgram(program_id);
|
glDeleteProgram(program_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void shader::use() const {
|
void shader_program::bind() const {
|
||||||
glUseProgram(program_id);
|
glUseProgram(program_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void shader::unuse() const {
|
void shader_program::unbind() {
|
||||||
glUseProgram(0);
|
glUseProgram(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int shader::getUniform(const char *uniformName) {
|
int shader_program::get_uniform(const char *name) {
|
||||||
if (uniform_cache.count(uniformName) == 0) {
|
if (uniform_cache.count(name) == 0) {
|
||||||
uniform_cache[uniformName] = glGetUniformLocation(program_id, uniformName);
|
uniform_cache[name] = glGetUniformLocation(program_id, name);
|
||||||
}
|
}
|
||||||
return uniform_cache[uniformName];
|
return uniform_cache[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
void shader::setMatrix3Uniform(float *matrix, const char *uniformName) {
|
void shader_program::set_mat3(float *matrix, const char *uniform_name) {
|
||||||
GLint location = getUniform(uniformName);
|
GLint location = get_uniform(uniform_name);
|
||||||
if (location != -1)
|
if (location != -1)
|
||||||
glUniformMatrix3fv(location, 1, false, matrix);
|
glUniformMatrix3fv(location, 1, false, matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
void shader::setMatrix4Uniform(float *matrix, const char *uniformName) {
|
void shader_program::set_mat4(float *matrix, const char *uniform_name) {
|
||||||
GLint location = getUniform(uniformName);
|
GLint location = get_uniform(uniform_name);
|
||||||
if (location != -1)
|
if (location != -1)
|
||||||
glUniformMatrix4fv(location, 1, false, matrix);
|
glUniformMatrix4fv(location, 1, false, matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
void shader::setVec3Uniform(float *value, const char *uniformName) {
|
void shader_program::set_vec3(float *value, const char *uniform_name) {
|
||||||
GLint location = getUniform(uniformName);
|
GLint location = get_uniform(uniform_name);
|
||||||
if (location != -1)
|
if (location != -1)
|
||||||
glUniform3fv(location, 1, value);
|
glUniform3fv(location, 1, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void shader::setVec4Uniform(float *value, const char *uniformName) {
|
void shader_program::set_vec4(float *value, const char *uniform_name) {
|
||||||
GLint location = getUniform(uniformName);
|
GLint location = get_uniform(uniform_name);
|
||||||
if (location != -1)
|
if (location != -1)
|
||||||
glUniform4fv(location, 1, value);
|
glUniform4fv(location, 1, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void shader::setIntUniform(int value, const char *uniformName) {
|
void shader_program::set_int(int value, const char *uniform_name) {
|
||||||
GLint location = getUniform(uniformName);
|
GLint location = get_uniform(uniform_name);
|
||||||
if (location != -1)
|
if (location != -1)
|
||||||
glUniform1i(location, value);
|
glUniform1i(location, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void shader::setFloatUniform(float value, const char *uniformName) {
|
void shader_program::set_float(float value, const char *uniform_name) {
|
||||||
GLint location = getUniform(uniformName);
|
GLint location = get_uniform(uniform_name);
|
||||||
if (location != -1)
|
if (location != -1)
|
||||||
glUniform1f(location, value);
|
glUniform1f(location, value);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "defines.h"
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
class shader {
|
|
||||||
public:
|
|
||||||
shader(const char *vs_content, const char *ps_content);
|
|
||||||
virtual ~shader();
|
|
||||||
|
|
||||||
void use() const;
|
|
||||||
void unuse() const;
|
|
||||||
|
|
||||||
GLuint getId() const { return program_id; }
|
|
||||||
int getUniform(const char *uniformName);
|
|
||||||
|
|
||||||
void setMatrix3Uniform(float *value, const char *uniformName);
|
|
||||||
void setMatrix4Uniform(float *value, const char *uniformName);
|
|
||||||
void setVec3Uniform(float *value, const char *uniformName);
|
|
||||||
void setVec4Uniform(float *value, const char *uniformName);
|
|
||||||
void setFloatUniform(float value, const char *uniformName);
|
|
||||||
void setIntUniform(int value, const char *uniformName);
|
|
||||||
|
|
||||||
private:
|
|
||||||
GLuint program_id;
|
|
||||||
GLuint shader_ids[2];
|
|
||||||
std::map<const char *, int> uniform_cache;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
END_NAMESPACE
|
|
||||||
+48
-49
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
#include "shader.h"
|
#include "shader_program.h"
|
||||||
#include "texture.h"
|
#include "texture.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
#include "material.h"
|
#include "material.h"
|
||||||
@@ -16,8 +16,7 @@ struct uniform_descriptor {
|
|||||||
std::string member_name;
|
std::string member_name;
|
||||||
|
|
||||||
// TODO: implement memoization of uniform name calculation
|
// TODO: implement memoization of uniform name calculation
|
||||||
|
explicit uniform_descriptor(const char *member) {
|
||||||
uniform_descriptor(const char *member) {
|
|
||||||
structure_name = "";
|
structure_name = "";
|
||||||
member_name = member;
|
member_name = member;
|
||||||
}
|
}
|
||||||
@@ -27,7 +26,7 @@ struct uniform_descriptor {
|
|||||||
member_name = member;
|
member_name = member;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string get_name() {
|
std::string get_name() const {
|
||||||
if (structure_name.empty())
|
if (structure_name.empty())
|
||||||
return member_name;
|
return member_name;
|
||||||
|
|
||||||
@@ -36,7 +35,7 @@ struct uniform_descriptor {
|
|||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string get_name(int index) {
|
std::string get_name(int index) const {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
if (structure_name.empty()) {
|
if (structure_name.empty()) {
|
||||||
ss << member_name << "[" << index << "]";
|
ss << member_name << "[" << index << "]";
|
||||||
@@ -93,72 +92,72 @@ public:
|
|||||||
|
|
||||||
shader_constant_type type;
|
shader_constant_type type;
|
||||||
|
|
||||||
glm::vec3 vec3Val{};
|
glm::vec3 vec3_val{};
|
||||||
glm::vec4 vec4Val{};
|
glm::vec4 vec4_val{};
|
||||||
glm::mat3 mat3Val{};
|
glm::mat3 mat3_val{};
|
||||||
glm::mat4 mat4Val{};
|
glm::mat4 mat4_val{};
|
||||||
int intVal{};
|
int int_val{};
|
||||||
float floatVal{};
|
float float_val{};
|
||||||
|
|
||||||
shader_constant_value(const shader_constant_value& rhs) {
|
shader_constant_value(const shader_constant_value& rhs) {
|
||||||
type = rhs.type;
|
type = rhs.type;
|
||||||
vec3Val = rhs.vec3Val;
|
vec3_val = rhs.vec3_val;
|
||||||
vec4Val = rhs.vec4Val;
|
vec4_val = rhs.vec4_val;
|
||||||
mat3Val = rhs.mat3Val;
|
mat3_val = rhs.mat3_val;
|
||||||
mat4Val = rhs.mat4Val;
|
mat4_val = rhs.mat4_val;
|
||||||
intVal = rhs.intVal;
|
int_val = rhs.int_val;
|
||||||
floatVal = rhs.floatVal;
|
float_val = rhs.float_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
shader_constant_value(glm::vec3 &value) {
|
explicit shader_constant_value(glm::vec3& value) {
|
||||||
vec3Val = value;
|
vec3_val = value;
|
||||||
type = shader_constant_type::vec3;
|
type = shader_constant_type::vec3;
|
||||||
}
|
}
|
||||||
|
|
||||||
shader_constant_value(glm::vec4 &value) {
|
explicit shader_constant_value(glm::vec4& value) {
|
||||||
vec4Val = value;
|
vec4_val = value;
|
||||||
type = shader_constant_type::vec4;
|
type = shader_constant_type::vec4;
|
||||||
}
|
}
|
||||||
|
|
||||||
shader_constant_value(glm::mat3 &value) {
|
explicit shader_constant_value(glm::mat3& value) {
|
||||||
mat3Val = value;
|
mat3_val = value;
|
||||||
type = shader_constant_type::mat3;
|
type = shader_constant_type::mat3;
|
||||||
}
|
}
|
||||||
|
|
||||||
shader_constant_value(glm::mat4 &value) {
|
explicit shader_constant_value(glm::mat4& value) {
|
||||||
mat4Val = value;
|
mat4_val = value;
|
||||||
type = shader_constant_type::mat4;
|
type = shader_constant_type::mat4;
|
||||||
}
|
}
|
||||||
|
|
||||||
shader_constant_value(int value) {
|
explicit shader_constant_value(int value) {
|
||||||
intVal = value;
|
int_val = value;
|
||||||
type = shader_constant_type::integer;
|
type = shader_constant_type::integer;
|
||||||
}
|
}
|
||||||
|
|
||||||
shader_constant_value(float value) {
|
explicit shader_constant_value(float value) {
|
||||||
floatVal = value;
|
float_val = value;
|
||||||
type = shader_constant_type::decimal;
|
type = shader_constant_type::decimal;
|
||||||
}
|
}
|
||||||
|
|
||||||
void apply_to(shader &sh, const char *uniform_name) {
|
void apply_to(shader_program& sh, const char *uniform_name) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case shader_constant_type::vec3:
|
case shader_constant_type::vec3:
|
||||||
sh.setVec3Uniform(glm::value_ptr(vec3Val), uniform_name);
|
sh.set_vec3(glm::value_ptr(vec3_val), uniform_name);
|
||||||
break;
|
break;
|
||||||
case shader_constant_type::vec4:
|
case shader_constant_type::vec4:
|
||||||
sh.setVec4Uniform(glm::value_ptr(vec4Val), uniform_name);
|
sh.set_vec4(glm::value_ptr(vec4_val), uniform_name);
|
||||||
break;
|
break;
|
||||||
case shader_constant_type::mat3:
|
case shader_constant_type::mat3:
|
||||||
sh.setMatrix3Uniform(glm::value_ptr(mat3Val), uniform_name);
|
sh.set_mat3(glm::value_ptr(mat3_val), uniform_name);
|
||||||
break;
|
break;
|
||||||
case shader_constant_type::mat4:
|
case shader_constant_type::mat4:
|
||||||
sh.setMatrix4Uniform(glm::value_ptr(mat4Val), uniform_name);
|
sh.set_mat4(glm::value_ptr(mat4_val), uniform_name);
|
||||||
break;
|
break;
|
||||||
case shader_constant_type::integer:
|
case shader_constant_type::integer:
|
||||||
sh.setIntUniform(intVal, uniform_name);
|
sh.set_int(int_val, uniform_name);
|
||||||
break;
|
break;
|
||||||
case shader_constant_type::decimal:
|
case shader_constant_type::decimal:
|
||||||
sh.setFloatUniform(floatVal, uniform_name);
|
sh.set_float(float_val, uniform_name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -168,55 +167,55 @@ public:
|
|||||||
class shader_constants {
|
class shader_constants {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void set(uniform_descriptor descriptor, glm::mat3 value) {
|
void set(const uniform_descriptor& descriptor, glm::mat3 value) {
|
||||||
constants[descriptor.get_name()] = std::make_shared<shader_constant_value>(value);
|
constants[descriptor.get_name()] = std::make_shared<shader_constant_value>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(uniform_descriptor descriptor, glm::mat3 value, int index) {
|
void set(const uniform_descriptor& descriptor, glm::mat3 value, int index) {
|
||||||
constants[descriptor.get_name(index)] = std::make_shared<shader_constant_value>(value);
|
constants[descriptor.get_name(index)] = std::make_shared<shader_constant_value>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(uniform_descriptor descriptor, glm::mat4 value) {
|
void set(const uniform_descriptor& descriptor, glm::mat4 value) {
|
||||||
constants[descriptor.get_name()] = std::make_shared<shader_constant_value>(value);
|
constants[descriptor.get_name()] = std::make_shared<shader_constant_value>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(uniform_descriptor descriptor, glm::mat4 value, int index) {
|
void set(const uniform_descriptor& descriptor, glm::mat4 value, int index) {
|
||||||
constants[descriptor.get_name(index)] = std::make_shared<shader_constant_value>(value);
|
constants[descriptor.get_name(index)] = std::make_shared<shader_constant_value>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(uniform_descriptor descriptor, glm::vec3 value) {
|
void set(const uniform_descriptor& descriptor, glm::vec3 value) {
|
||||||
constants[descriptor.get_name()] = std::make_shared<shader_constant_value>(value);
|
constants[descriptor.get_name()] = std::make_shared<shader_constant_value>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(uniform_descriptor descriptor, glm::vec3 value, int index) {
|
void set(const uniform_descriptor& descriptor, glm::vec3 value, int index) {
|
||||||
constants[descriptor.get_name(index)] = std::make_shared<shader_constant_value>(value);
|
constants[descriptor.get_name(index)] = std::make_shared<shader_constant_value>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(uniform_descriptor descriptor, glm::vec4 value) {
|
void set(const uniform_descriptor& descriptor, glm::vec4 value) {
|
||||||
constants[descriptor.get_name()] = std::make_shared<shader_constant_value>(value);
|
constants[descriptor.get_name()] = std::make_shared<shader_constant_value>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(uniform_descriptor descriptor, glm::vec4 value, int index) {
|
void set(const uniform_descriptor& descriptor, glm::vec4 value, int index) {
|
||||||
constants[descriptor.get_name(index)] = std::make_shared<shader_constant_value>(value);
|
constants[descriptor.get_name(index)] = std::make_shared<shader_constant_value>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(uniform_descriptor descriptor, int value) {
|
void set(const uniform_descriptor& descriptor, int value) {
|
||||||
constants[descriptor.get_name()] = std::make_shared<shader_constant_value>(value);
|
constants[descriptor.get_name()] = std::make_shared<shader_constant_value>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(uniform_descriptor descriptor, int value, int index) {
|
void set(const uniform_descriptor& descriptor, int value, int index) {
|
||||||
constants[descriptor.get_name(index)] = std::make_shared<shader_constant_value>(value);
|
constants[descriptor.get_name(index)] = std::make_shared<shader_constant_value>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(uniform_descriptor descriptor, float value) {
|
void set(const uniform_descriptor& descriptor, float value) {
|
||||||
constants[descriptor.get_name()] = std::make_shared<shader_constant_value>(value);
|
constants[descriptor.get_name()] = std::make_shared<shader_constant_value>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(uniform_descriptor descriptor, float value, int index) {
|
void set(const uniform_descriptor& descriptor, float value, int index) {
|
||||||
constants[descriptor.get_name(index)] = std::make_shared<shader_constant_value>(value);
|
constants[descriptor.get_name(index)] = std::make_shared<shader_constant_value>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void apply_to(shader &shd) {
|
void apply_to(shader_program& shd) {
|
||||||
for (auto& kv: constants)
|
for (auto& kv: constants)
|
||||||
kv.second->apply_to(shd, kv.first.c_str());
|
kv.second->apply_to(shd, kv.first.c_str());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "defines.h"
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class shader_program {
|
||||||
|
public:
|
||||||
|
shader_program(const char *vs_content, const char *ps_content);
|
||||||
|
virtual ~shader_program();
|
||||||
|
|
||||||
|
void bind() const;
|
||||||
|
static void unbind() ;
|
||||||
|
|
||||||
|
GLuint get_id() const { return program_id; }
|
||||||
|
|
||||||
|
int get_uniform(const char *name);
|
||||||
|
|
||||||
|
void set_mat3(float *value, const char *uniform_name);
|
||||||
|
void set_mat4(float *value, const char *uniform_name);
|
||||||
|
void set_vec3(float *value, const char *uniform_name);
|
||||||
|
void set_vec4(float *value, const char *uniform_name);
|
||||||
|
void set_float(float value, const char *uniform_name);
|
||||||
|
void set_int(int value, const char *uniform_name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
GLuint program_id;
|
||||||
|
GLuint shader_ids[2];
|
||||||
|
std::map<const char *, int> uniform_cache;
|
||||||
|
};
|
||||||
|
|
||||||
|
END_NAMESPACE
|
||||||
+4
-4
@@ -7,15 +7,15 @@ timer::timer() {
|
|||||||
last_lap_time = start_time;
|
last_lap_time = start_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
double timer::seconds_since_start() {
|
float timer::seconds_since_start() {
|
||||||
std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
|
std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
|
||||||
std::chrono::duration<double> elapsed_seconds = now - start_time;
|
std::chrono::duration<float> elapsed_seconds = now - start_time;
|
||||||
return elapsed_seconds.count();
|
return elapsed_seconds.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
double timer::lap() {
|
float timer::lap() {
|
||||||
std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
|
std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
|
||||||
std::chrono::duration<double> elapsed_seconds = now - last_lap_time;
|
std::chrono::duration<float> elapsed_seconds = now - last_lap_time;
|
||||||
last_lap_time = now;
|
last_lap_time = now;
|
||||||
return elapsed_seconds.count();
|
return elapsed_seconds.count();
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -9,8 +9,8 @@ class timer {
|
|||||||
public:
|
public:
|
||||||
timer();
|
timer();
|
||||||
|
|
||||||
double seconds_since_start();
|
float seconds_since_start();
|
||||||
double lap();
|
float lap();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::chrono::time_point<std::chrono::system_clock> start_time;
|
std::chrono::time_point<std::chrono::system_clock> start_time;
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
intro:
|
||||||
|
- benzene elements come together and form the symbol
|
||||||
|
- they slowly come into place and rotate
|
||||||
|
- either explode into particles or fade away
|
||||||
|
|
||||||
|
scenes:
|
||||||
|
- camera flyby trhough a sci-fi tunnel composed of metalic pipe systems and awkward light
|
||||||
|
- walk through a forest made with L-systems
|
||||||
|
- heightmap
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user