diff --git a/assets/shaders/phong-solid.fragment.glsl b/assets/shaders/phong-solid.fragment.glsl index 559f155..deb9eaf 100644 --- a/assets/shaders/phong-solid.fragment.glsl +++ b/assets/shaders/phong-solid.fragment.glsl @@ -4,32 +4,27 @@ out vec4 frag_color; uniform vec3 light_pos; uniform vec3 solid_color; -in vec3 normal_cameraspace; -in vec3 light_direction_cameraspace; -in vec3 eye_direction_cameraspace; -in vec3 position_worldspace; +in vec3 normal; +in vec3 frag_position; void main() { - vec4 material_diffuse_color = vec4(solid_color, 1); - vec4 material_ambient_color = vec4(0.1, 0.1, 0.1, 1.0) * material_diffuse_color; - vec4 material_specular_color = vec4(1.0, 1.0, 1.0, 1.0); + vec3 light_color = vec3(1, 1, 1); + vec3 light_direction_norm = normalize(light_pos - frag_position); + vec3 normal_norm = normalize(normal); + vec3 eyes = vec3(1, 1, 0); - vec3 normal = normalize(normal_cameraspace); - vec3 light_dir = normalize(light_direction_cameraspace); - float cos_theta = clamp(dot(normal, light_dir), 0, 1); + float ambient_strength = 0.1; + vec3 ambient = ambient_strength * light_color; - vec3 eye = normalize(eye_direction_cameraspace); - vec3 reflected = reflect(-light_dir, normal); - float cos_alpha = clamp(dot(eye, reflected), 0, 1); + float diff = max(dot(normal_norm, light_direction_norm), 0.0); + vec3 diffuse = diff * light_color; - vec4 light_color = vec4(1, 1, 1, 1); - float light_power = 60; + float specular_strength = 0.5; + vec3 view_direction_norm = normalize(eyes - frag_position); + vec3 reflect_dir = reflect(-light_direction_norm, normal_norm); + float spec = pow(max(dot(view_direction_norm, reflect_dir), 0.0), 32); + vec3 specular = specular_strength * spec * light_color; - float distance = length(light_pos - position_worldspace); - float dist_sq = pow(distance, 2); - - vec4 diffuse = material_diffuse_color * light_color * light_power * cos_theta / dist_sq; - vec4 specular = material_specular_color * light_color * light_power * pow(cos_alpha, 10) / dist_sq; - - frag_color = material_ambient_color + diffuse + specular; -}; + vec3 result = (ambient + diffuse + specular) * solid_color; + frag_color = vec4(result, 1.0); +} diff --git a/assets/shaders/phong-solid.vertex.glsl b/assets/shaders/phong-solid.vertex.glsl index e3922dd..e16b006 100644 --- a/assets/shaders/phong-solid.vertex.glsl +++ b/assets/shaders/phong-solid.vertex.glsl @@ -8,19 +8,13 @@ uniform mat4 view; uniform mat4 projection; uniform vec3 light_pos; -out vec3 normal_cameraspace; -out vec3 light_direction_cameraspace; -out vec3 eye_direction_cameraspace; -out vec3 position_worldspace; +out vec3 normal; +out vec3 frag_position; void main() { - vec3 vertex_cameraspace = (view * model * vec4(a_xyz, 1)).xyz; - vec3 light_pos_cameraspace = (view * vec4(light_pos, 1)).xyz; + vec4 a_xyz_vec4 = vec4(a_xyz, 1); - normal_cameraspace = (transpose(inverse(view * model)) * vec4(a_normal, 0)).xyz; - light_direction_cameraspace = light_pos_cameraspace + eye_direction_cameraspace; - eye_direction_cameraspace = vec3(0, 0, 0) - vertex_cameraspace; - position_worldspace = (model * vec4(a_xyz, 1)).xyz; - - gl_Position = projection * view * model * vec4(a_xyz, 1); + frag_position = (model * a_xyz_vec4).xyz; + normal = mat3(transpose(inverse(model))) * a_normal; + gl_Position = projection * view * model * a_xyz_vec4; } diff --git a/build b/build old mode 100644 new mode 100755 index 703d23a..8f3ce76 --- a/build +++ b/build @@ -1,3 +1,4 @@ #!/bin/bash -g++ -I ./ -g -g3 -lglfw -lGLU -lGL -lXrandr -lXxf86vm -lXi -lXinerama -lX11 -lrt -ldl -DOS_LINUX=1 -DENABLE_ASSERT=1 ./app.cpp -o ./target/app +LIB_INCLUDE="-lglfw -lGLU -lGL -lXrandr -lXxf86vm -lXi -lXinerama -lX11 -lrt -ldl" +g++ -g -g3 -DOS_LINUX=1 -DENABLE_ASSERT=1 ./src/main.cpp -o ./target/somaesque $LIB_INCLUDE diff --git a/src/SomaSolve.cpp b/src/SomaSolve.cpp index 77afa30..6bc3d3e 100644 --- a/src/SomaSolve.cpp +++ b/src/SomaSolve.cpp @@ -1,7 +1,9 @@ +#include #include #include #include #include "VoxelSpace.h" +#include "lib/djstdlib/core.h" void get_dims_input(int dims[3]) { std::cout << "Enter dimensions separated by newlines. (x*y*z must not exceed 64)\n"; @@ -43,7 +45,7 @@ std::vector get_reprs_input(int units_required) { uint64 bit_repr = 0; int i = 0; bool good_repr = true; - for (auto it = input.rbegin(); it < input.rend(); it++, i++) { + for (std::reverse_iterator it = input.rbegin(); it < input.rend(); it++, i++) { if (*it == '1') { bit_repr |= 1 << i; total_units++; @@ -63,12 +65,12 @@ std::vector get_reprs_input(int units_required) { typedef std::vector SomaSolution; struct Solver { - std::vector* input; - std::vector* offsets; + list* input; + list* offsets; std::vector* solutions; }; -std::vector STD_SOMA = { 23ul, 30ul, 15ul, 1043ul, 24594ul, 12306ul, 11ul }; +uint64 STD_SOMA[] = { 23ul, 30ul, 15ul, 1043ul, 24594ul, 12306ul, 11ul }; void backtrack_solve_iter(std::vector *polycube_input, std::vector *offsets) { int num_inputs = offsets->size() - 1; @@ -118,18 +120,18 @@ void backtrack_solve_iter(std::vector *polycube_input, std::vector std::cout << "Done. Found " << solns.size() << " solutions." << std::endl; } -void backtrack_solve(Solver *solver, uint64 working_solution = 0, int curr_piece = 0) { - std::vector *input = solver->input; - std::vector *offsets = solver->offsets; +void backtrack_solve(Solver *solver, uint64 working_solution = 0, size_t curr_piece = 0) { + list *input = solver->input; + list *offsets = solver->offsets; std::vector *solutions = solver->solutions; - int start = offsets->at(curr_piece); - int end = offsets->at(curr_piece + 1); - size_t num_pieces = offsets->size() - 1; + int start = offsets->data[curr_piece]; + int end = offsets->data[curr_piece + 1]; + size_t num_pieces = offsets->length - 1; for (int i = start; i < end; i++) { - bool successful_fuse = !collides(working_solution, input->at(i)); + bool successful_fuse = !collides(working_solution, input->data[i]); if (successful_fuse) { - uint64 new_working_solution = working_solution | input->at(i); - solutions->back().at(curr_piece) = input->at(i); + uint64 new_working_solution = working_solution | input->data[i]; + solutions->back().at(curr_piece) = input->data[i]; if (curr_piece == num_pieces - 1) { std::vector last_soln = solutions->back(); solutions->push_back(SomaSolution(last_soln.begin(), last_soln.end())); @@ -144,7 +146,7 @@ void backtrack_solve(Solver *solver, uint64 working_solution = 0, int curr_piece } } -std::vector get_solution_rotations(SomaSolution *solution, int dims[3]) { +std::vector get_solution_rotations(Arena *arena, SomaSolution *solution, int dims[3]) { std::vector result = std::vector(NUM_ROTS_3D); for (int piece_i = 0; piece_i < solution->size(); piece_i++) { Space space = { @@ -153,23 +155,25 @@ std::vector get_solution_rotations(SomaSolution *solution, int dim dims[1], dims[2], }; - std::vector piece_rotations = getAllRotations(&space); - for (int rot_i = 0; rot_i < piece_rotations.size(); rot_i++) { - result[rot_i].push_back(piece_rotations[rot_i].space); + list piece_rotations = getAllRotations(arena, &space); + for (int rot_i = 0; rot_i < piece_rotations.length; rot_i++) { + result[rot_i].push_back(piece_rotations.data[rot_i].space); } } return result; } -std::vector filter_unique(std::vector *solutions, int dims[3]) { +std::vector filter_unique(Arena *arena, std::vector *solutions, int dims[3]) { if (solutions->size() == 0) { return std::vector(); } std::vector unique_solns = std::vector{}; for (std::vector &solution : *solutions) { bool found_match = false; - for (SomaSolution &rotation : get_solution_rotations(&solution, dims)) { - for (auto &unique_soln : unique_solns) { + Scratch temp = scratchStart(&arena, 1); + std::vector rots = get_solution_rotations(temp.arena, &solution, dims); + for (SomaSolution &rotation : rots) { + for (std::vector &unique_soln : unique_solns) { bool is_match = true; for (int piece_i = 0; piece_i < unique_soln.size(); piece_i++) { if (rotation[piece_i] != unique_soln[piece_i]) { @@ -186,6 +190,7 @@ std::vector filter_unique(std::vector *solutions, in break; } } + scratchEnd(temp); if (!found_match) { unique_solns.push_back(SomaSolution(solution)); } @@ -193,11 +198,13 @@ std::vector filter_unique(std::vector *solutions, in return unique_solns; } -std::vector solve(std::vector *reprs_in, int dims[3]) { - std::vector reprs = *reprs_in; - std::vector offsets = std::vector(); - std::vector polycubes = std::vector(); - polycubes.reserve(reprs.size() * 10); +std::vector solve(uint64 *reprs_in, uint32 reprs_in_count, int dims[3]) { + Arena *arena = arenaAlloc(Megabytes(64)); + Arena *permsArena = arenaAlloc(Megabytes(64)); + + list offsets = PushList(arena, size_t, reprs_in_count + 1); + + list polycubes = PushList(arena, uint64, 0); Space model_space = { {}, @@ -206,25 +213,29 @@ std::vector solve(std::vector *reprs_in, int dims[3]) { dims[2], }; - offsets.push_back(0); + appendList(&offsets, 0ul); Space space = model_space; - space.space = reprs[0]; + space.space = reprs_in[0]; cullEmptySpace(&space); - std::vector positions = getAllPositionsInPrism(&space, dims); - polycubes.insert(polycubes.end(), positions.begin(), positions.end()); + list positions = getAllPositionsInPrism(arena, &space, dims); + polycubes.length += positions.length; + polycubes.head += positions.head; + memcpy(polycubes.data, positions.data, positions.length / sizeof(uint64)); - for (int i = 1; i < reprs.size(); i++) { - offsets.push_back(polycubes.size()); + for (int i = 1; i < reprs_in_count; i++) { + appendList(&offsets, polycubes.length); Space space = model_space; - space.space = reprs[i]; + space.space = reprs_in[i]; cullEmptySpace(&space); - std::vector perms = getAllPermutationsInPrism(&space, dims); - polycubes.insert(polycubes.end(), perms.begin(), perms.end()); + list perms = getAllPermutationsInPrism(permsArena, &space, dims); + polycubes.length += positions.length; + polycubes.head += positions.head; + memcpy(polycubes.data + polycubes.length, perms.data, perms.length / sizeof(uint64)); } - offsets.push_back(polycubes.size()); + appendList(&offsets, polycubes.length); - std::vector solutions = {std::vector(reprs.size())}; + std::vector solutions = {std::vector(reprs_in_count)}; Solver solver = { &polycubes, &offsets, @@ -233,7 +244,7 @@ std::vector solve(std::vector *reprs_in, int dims[3]) { backtrack_solve(&solver); - return filter_unique(solver.solutions, dims); + return filter_unique(arena, solver.solutions, dims); } @@ -241,8 +252,8 @@ void interactive_cmd_line_solve_soma() { int dims[3] = { 3, 3, 3 }; //get_dims_input(dims); //std::cout << '\n'; - //auto reprs = get_reprs_input(dims[0]*dims[1]*dims[2]); + //std::vector reprs = get_reprs_input(dims[0]*dims[1]*dims[2]); std::cout << "Great. Calculating solutions...\n"; - std::vector solutions = solve(&STD_SOMA, dims); + std::vector solutions = solve(STD_SOMA, ArrayCount(STD_SOMA), dims); std::cout << solutions.size() << " solutions found." << std::endl; } diff --git a/src/VoxelSpace.cpp b/src/VoxelSpace.cpp index d479259..f9da7b7 100644 --- a/src/VoxelSpace.cpp +++ b/src/VoxelSpace.cpp @@ -1,6 +1,9 @@ -#include +#include #include +#include +#include #include "VoxelSpace.h" +#include "lib/djstdlib/core.h" int index(int dim_y, int dim_z, int x, int y, int z) { return dim_y * dim_z * x + dim_z * y + z; @@ -166,7 +169,7 @@ bool isMatch(Space *a, Space *b) { && a->dim_z == b->dim_z; } -void pushNewUniqueSpins(std::vector *existingSpaces, Space* spaceToSpin) { +void pushNewUniqueSpins(list *existingSpaces, Space* spaceToSpin) { Space spins[4] = {}; spins[0] = *spaceToSpin; for (int i = 0; i < 3; i++) { @@ -175,30 +178,29 @@ void pushNewUniqueSpins(std::vector *existingSpaces, Space* spaceToSpin) } for (int i = 0; i < 4; i++) { bool matchFound = false; - for (Space &existingSpace : *existingSpaces) { - if (isMatch(&existingSpace, &spins[i])) { + for (EachIn(*existingSpaces, i)) { + if (isMatch(&existingSpaces->data[i], &spins[i])) { matchFound = true; break; } } if (!matchFound) { - existingSpaces->push_back(spins[i]); + appendList(existingSpaces, spins[i]); } } } -void pushXAxisSpins(std::vector *existingSpaces, Space* spaceToSpin) { +void pushXAxisSpins(Arena *arena, list *existingSpaces, Space* spaceToSpin) { Space refSpace = *spaceToSpin; for (int i = 0; i < 4; i++) { rotate90X(&refSpace); - existingSpaces->push_back(refSpace); + appendList(existingSpaces, refSpace); } } -std::vector getUniqueRotations(Space *space) { - std::vector rotations = std::vector(); - rotations.reserve(24); - auto refSpace = *space; +list getUniqueRotations(Arena *arena, Space *space) { + list rotations = PushList(arena, Space, 24); + Space refSpace = *space; cullEmptySpace(&refSpace); pushNewUniqueSpins(&rotations, &refSpace); rotate90Y(&refSpace); @@ -212,63 +214,75 @@ std::vector getUniqueRotations(Space *space) { rotate90Z(&refSpace); rotate90Z(&refSpace); pushNewUniqueSpins(&rotations, &refSpace); + rotations.head = rotations.length; + arenaPopTo(arena, rotations.data + rotations.head); return rotations; } -std::vector getAllRotations(Space *space) { - std::vector rotations = {}; - rotations.reserve(24); +list getAllRotations(Arena *arena, Space *space) { + list rotations = PushList(arena, Space, 24); Space refSpace = *space; - pushXAxisSpins(&rotations, &refSpace); + pushXAxisSpins(arena, &rotations, &refSpace); rotate90Y(&refSpace); - pushXAxisSpins(&rotations, &refSpace); + pushXAxisSpins(arena, &rotations, &refSpace); rotate90Y(&refSpace); - pushXAxisSpins(&rotations, &refSpace); + pushXAxisSpins(arena, &rotations, &refSpace); rotate90Y(&refSpace); - pushXAxisSpins(&rotations, &refSpace); + pushXAxisSpins(arena, &rotations, &refSpace); rotate90Z(&refSpace); - pushXAxisSpins(&rotations, &refSpace); + pushXAxisSpins(arena, &rotations, &refSpace); rotate90Z(&refSpace); rotate90Z(&refSpace); - pushXAxisSpins(&rotations, &refSpace); + pushXAxisSpins(arena, &rotations, &refSpace); return rotations; } -std::vector getAllPositionsInPrism(Space *space, int prism_dims[3]) { - std::vector cubePositions = {}; +list getAllPositionsInPrism(Arena *arena, Space *space, int prism_dims[3]) { if (space->dim_x > prism_dims[0] || space->dim_y > prism_dims[1] || space->dim_z > prism_dims[2]) { - return cubePositions; + return list{0}; } + list result = PushList(arena, uint64, 0); + int count = 0; int xPositionCount = prism_dims[0] - space->dim_x + 1; int yPositionCount = prism_dims[1] - space->dim_y + 1; int zPositionCount = prism_dims[2] - space->dim_z + 1; for (int x = 0; x < xPositionCount; x++) { for (int y = 0; y < yPositionCount; y++) { for (int z = 0; z < zPositionCount; z++) { - uint64 new_space = 0; + uint64 *new_space = PushStruct(arena, uint64); + *new_space = 0; + count++; for (int posX = 0; posX < space->dim_x; posX++) { for (int posY = 0; posY < space->dim_y; posY++) { for (int posZ = 0; posZ < space->dim_z; posZ++) { bool set_val = filledAt(space, posX, posY, posZ); int index_to_set = index(prism_dims[1], prism_dims[2], x + posX, y + posY, z + posZ); - new_space = set(new_space, index_to_set, set_val); + *new_space = set(*new_space, index_to_set, set_val); } } } - cubePositions.push_back(new_space); } } } - return cubePositions; + result.length = count; + result.head = count; + return result; } -std::vector getAllPermutationsInPrism(Space *space, int prism_dims[3]) { - std::vector rotations = getUniqueRotations(space); - std::vector result = std::vector(); - for (auto &rotation : rotations) { - auto positions = getAllPositionsInPrism(&rotation, prism_dims); - result.insert(result.end(), positions.begin(), positions.end()); +list getAllPermutationsInPrism(Arena *arena, Space *space, int prism_dims[3]) { + Scratch temp = scratchStart(&arena, 1); + + list rotations = getUniqueRotations(temp.arena, space); + list result = PushList(arena, uint64, 0); + for (EachIn(rotations, i)) { + list positions = getAllPositionsInPrism(temp.arena, &rotations.data[i], prism_dims); + uint64 *listAppend = PushArray(arena, uint64, positions.length); + memcpy(listAppend, positions.data, positions.length / sizeof(uint64)); + result.length += positions.length; + result.head += positions.head; } + + scratchEnd(temp); return result; } diff --git a/src/VoxelSpace.h b/src/VoxelSpace.h index d69775a..1acaa6c 100644 --- a/src/VoxelSpace.h +++ b/src/VoxelSpace.h @@ -53,13 +53,13 @@ void rotate90Z(Space *space); void pushNewUniqueSpins(std::vector *existingSpaces, Space* spaceToSpin); -std::vector getUniqueRotations(Space *space); +list getUniqueRotations(Arena *arena, Space *space); -std::vector getAllRotations(Space *space); +list getAllRotations(Arena *arena, Space *space); -std::vector getAllPositionsInPrism(Space *space, int prism_dims[3]); +list getAllPositionsInPrism(Arena *arena, Space *space, int prism_dims[3]); -std::vector getAllPermutationsInPrism(Space *space, int prism_dims[3]); +list getAllPermutationsInPrism(Arena *arena, Space *space, int prism_dims[3]); int size(uint64 space); diff --git a/src/gfx/Shader.cpp b/src/gfx/Shader.cpp index 8f374ff..dac8433 100644 --- a/src/gfx/Shader.cpp +++ b/src/gfx/Shader.cpp @@ -54,5 +54,7 @@ Shader createShader(const char* vertex_path, const char* fragment_path) { glDeleteShader(vertex_shader); glDeleteShader(fragment_shader); + + return result; } diff --git a/src/gfx/gfx.cpp b/src/gfx/gfx.cpp new file mode 100644 index 0000000..3cab65f --- /dev/null +++ b/src/gfx/gfx.cpp @@ -0,0 +1,5 @@ +#include "Mesh.cpp" +#include "Shader.cpp" +#include "Texture.cpp" +#include "geometry.cpp" +#include "Color.cpp" diff --git a/src/lib/djstdlib/core.cpp b/src/lib/djstdlib/core.cpp index 1d85fc4..e73fb33 100644 --- a/src/lib/djstdlib/core.cpp +++ b/src/lib/djstdlib/core.cpp @@ -1,9 +1,12 @@ +#include +#include #include // TODO(djledda): get outta here #include #include -#define STB_SPRINTF_IMPLEMENTATION #include "core.h" #include "os.cpp" +#define STB_SPRINTF_IMPLEMENTATION +#include "vendor/stb_sprintf.h" void *pushSize(Arena *arena, size_t bytes) { if (arena->capacity - arena->head >= bytes) { @@ -30,6 +33,10 @@ void arenaFreeFrom(Arena *arena, size_t position) { arena->head = position; } +void arenaPopTo(Arena *arena, void *position) { + arena->head = (byte *)position - (byte *)arena->memory; +} + Arena *scratchArenas[2]; void initialiseCore() { diff --git a/src/lib/djstdlib/core.h b/src/lib/djstdlib/core.h index 60e4dde..15a2f28 100644 --- a/src/lib/djstdlib/core.h +++ b/src/lib/djstdlib/core.h @@ -60,6 +60,7 @@ void *pushSize(Arena *arena, size_t bytes); Arena *arenaAlloc(size_t capacity); void arenaFree(Arena *arena); void arenaFreeFrom(Arena *arena, size_t pos); +void arenaPopTo(Arena *arena, void *pos); void initialiseCore(); @@ -209,8 +210,8 @@ void log(const char *fmt, ...); void logError(const char *fmt, ...); // ### Loops ### -#define EachIn(list, it) size_t it = 0; it < list.length; it++ -#define EachInReversed(list, it) size_t it = list.length - 1; it >= 0 && it < list.length; it-- +#define EachIn(list, it) size_t it = 0; it < (list).length; it++ +#define EachInReversed(list, it) size_t it = (list).length - 1; it >= 0 && it < (list).length; it-- #define EachInArray(arr, it) size_t it = 0; it < ArrayCount(arr); ++it // ### Misc ### diff --git a/src/main.cpp b/src/main.cpp index 261c21c..9b528f0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,20 +2,24 @@ #include #include -#include "lib/glad/glad.h" -#include +#include "lib/djstdlib/core.h" +#include "lib/glad/glad.c" #include + +#include #include #include #include #include -#include "lib/loaders/stb_image.h" -#include "gfx/main.cpp" +#include "gfx/gfx.cpp" #include "VoxelSpace.cpp" #include "SomaSolve.cpp" #include "lib/djstdlib/core.cpp" +#define STB_IMAGE_IMPLEMENTATION +#include "lib/loaders/stb_image.h" + struct Entity; struct Polycube; struct SceneGraphNode; @@ -39,42 +43,45 @@ struct Camera { glm::vec3 pos; glm::vec3 up; glm::vec3 target; - - void init(float aspect_ratio = 800.0f / 600.0f) { - view = glm::mat4(); - proj = glm::perspective(glm::radians(45.0f), aspect_ratio, 0.1f, 100.0f); - pos = glm::vec3(0.0f); - up = glm::vec3(0.0f, 1.0f, 0.0f); - } - - void look_at(float x, float y, float z) { - target = glm::vec3(x, y, z); - view = glm::lookAt(pos, target, up); - } - - void set_up(float up_x, float up_y, float up_z) { - up = glm::vec3(up_x, up_y, up_z); - } }; +Camera *createCamera(Arena *arena, real32 aspect_ratio = 800.0f / 600.0f) { + Camera *result = PushStruct(arena, Camera); + result->view = glm::mat4(); + result->proj = glm::perspective(glm::radians(45.0f), aspect_ratio, 0.1f, 100.0f); + result->pos = glm::vec3(0.0f); + result->up = glm::vec3(0.0f, 1.0f, 0.0f); + return result; +} + +void camera_look_at(Camera *c, float x, float y, float z) { + c->target = glm::vec3(x, y, z); + c->view = glm::lookAt(c->pos, c->target, c->up); +} + +void camera_set_up(Camera *c, real32 up_x, real32 up_y, real32 up_z) { + c->up = glm::vec3(up_x, up_y, up_z); +} + struct GlobalAppState { - int current_polycube; - int last_polycube_visible; + uint32 current_polycube; + uint32 last_polycube_visible; Shader *active_shader; std::vector polycubes; }; + GlobalAppState app_state; struct WindowDims { - unsigned int width; - unsigned int height; + uint32 width; + uint32 height; }; struct Entity { Mesh *mesh; Texture *tex; bool visible; - int scene_graph_node; + uint32 scene_graph_node; }; struct SceneGraphNode { @@ -83,79 +90,80 @@ struct SceneGraphNode { glm::vec3 translation; glm::quat rotation; glm::vec3 scale; - std::vector children; - std::optional entity; - - void reset() { - scale = glm::vec3(1.0f, 1.0f, 1.0f); - translation = glm::vec3(0.0f, 0.0f, 0.0f); - rotation = glm::quat(0.0f, 0.0f, 0.0f, 0.0f); - } - - void init() { - reset(); - local = glm::mat4(1.0f); - world = local; - } - - void update_local() { - local = glm::scale( - glm::translate( - glm::mat4(1.0f), - translation - ) * glm::toMat4(rotation), - scale - ); - } + std::vector children; + std::optional entity; }; +void init_sg_node(SceneGraphNode *n) { + n->scale = glm::vec3(1.0f, 1.0f, 1.0f); + n->translation = glm::vec3(0.0f, 0.0f, 0.0f); + n->rotation = glm::quat(0.0f, 0.0f, 0.0f, 0.0f); + n->local = glm::mat4(1.0f); + n->world = n->local; +} + +void recalculate_sg_node(SceneGraphNode *n) { + n->local = glm::scale( + glm::translate( + glm::mat4(1.0f), + n->translation + ) * glm::toMat4(n->rotation), + n->scale + ); +} + struct Polycube { int graph_node; glm::vec3 color; - - void show() { - SceneGraphNode *node = get_scene_graph_node(graph_node); - for (auto &child : node->children) { - auto node = get_scene_graph_node(child); - if (node->entity) { - get_entity(*node->entity)->visible = true; - } - } - } - - void hide() { - SceneGraphNode *node = get_scene_graph_node(graph_node); - for (int &child : node->children) { - SceneGraphNode *node = get_scene_graph_node(child); - if (node->entity) { - get_entity(*node->entity)->visible = false; - } - } - } - - glm::vec3 get_centre() { - glm::vec3 centre = glm::vec3(0.0f); - for (int &child : get_scene_graph_node(graph_node)->children) { - centre += get_scene_graph_node(child)->translation; - } - centre /= get_scene_graph_node(graph_node)->children.size(); - return centre; - } }; +void show_polycube(Polycube *p) { + SceneGraphNode *node = get_scene_graph_node(p->graph_node); + for (uint32 &child : node->children) { + SceneGraphNode *node = get_scene_graph_node(child); + if (node->entity) { + get_entity(*node->entity)->visible = true; + } + } +} + +void hide_polycube(Polycube *p) { + SceneGraphNode *node = get_scene_graph_node(p->graph_node); + for (uint32 &child : node->children) { + SceneGraphNode *node = get_scene_graph_node(child); + if (node->entity) { + get_entity(*node->entity)->visible = false; + } + } +} + +glm::vec3 centreFromPolycube(Polycube *p) { + glm::vec3 centre = glm::vec3(0.0f); + for (uint32 &child : get_scene_graph_node(p->graph_node)->children) { + centre += get_scene_graph_node(child)->translation; + } + centre /= get_scene_graph_node(p->graph_node)->children.size(); + return centre; +} + struct Frame { - unsigned int width; - unsigned int height; - int x; - int y; + uint32 width; + uint32 height; + int32 x; + int32 y; Camera* cam; - - void init(Camera* camera) { - camera->init((float)width / (float)height); - cam = camera; - } }; +Frame createFrame(Arena *arena, uint32 width, uint32 height, real32 x, real32 y) { + Frame result = {0}; + result.width = width; + result.height = height; + result.x = x; + result.y = y; + result.cam = createCamera(arena, (real32)result.width / (real32)result.height); + return result; +} + void framebuffer_size_callback(GLFWwindow *window, int width, int height) { glViewport(0, 0, width, height); } @@ -165,7 +173,7 @@ GLFWwindow *init_window_and_gl(WindowDims *window_dims) { glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - auto window = glfwCreateWindow(window_dims->width, window_dims->height, "Somaesque", NULL, NULL); + GLFWwindow *window = glfwCreateWindow(window_dims->width, window_dims->height, "Somaesque", NULL, NULL); if (window == NULL) { std::cout << "Failed to create GLFW window" << std::endl; glfwTerminate(); @@ -244,18 +252,9 @@ int new_graph_node() { return scene_graph_nodes.size(); } -void draw_entity(Entity *entity) { - GLint modelUniformLoc = glGetUniformLocation(app_state.active_shader->prog_id, "model"); - glUniformMatrix4fv(modelUniformLoc, 1, GL_FALSE, glm::value_ptr(get_scene_graph_node(entity->scene_graph_node)->world)); - glBindTexture(GL_TEXTURE_2D, entity->tex->tex_id); - glBindVertexArray(entity->mesh->vao); - glDrawArrays(GL_TRIANGLES, 0, entity->mesh->num_indices); - //glDrawElements(GL_TRIANGLES, entity->mesh->num_indices, GL_UNSIGNED_INT, 0); -} - Polycube create_polycube_from_repr(Space *repr) { int polycube_id = new_graph_node(); - get_scene_graph_node(polycube_id)->init(); + init_sg_node(get_scene_graph_node(polycube_id)); for (int x = 0; x < repr->dim_x; x++) { for (int y = 0; y < repr->dim_y; y++) { for (int z = 0; z < repr->dim_z; z++) { @@ -264,13 +263,13 @@ Polycube create_polycube_from_repr(Space *repr) { polycube_segment->mesh=&cube_mesh, polycube_segment->tex=&wall_tex; SceneGraphNode *graph_node = get_scene_graph_node(polycube_segment->scene_graph_node); - graph_node->init(); + init_sg_node(graph_node); graph_node->translation = glm::vec3( -((repr->dim_z - 1)/2.0f) + z, ((repr->dim_x - 1)/2.0f) - x, -((repr->dim_y - 1)/2.0f) + y ); - graph_node->update_local(); + recalculate_sg_node(graph_node); get_scene_graph_node(polycube_id)->children.push_back(polycube_segment->scene_graph_node); } } @@ -287,9 +286,9 @@ void recalculate_scene_graph(SceneGraphNode *top) { if (top->children.size() == 0) { return; } - for (int &node_id : top->children) { + for (uint32 &node_id : top->children) { SceneGraphNode *graph_node = get_scene_graph_node(node_id); - graph_node->update_local(); + recalculate_sg_node(graph_node); graph_node->world = top->world * graph_node->local; recalculate_scene_graph(graph_node); } @@ -307,6 +306,8 @@ int main_gfx() { return -1; } + Arena *arena = arenaAlloc(Megabytes(128)); + app_state = { .current_polycube=0, .last_polycube_visible=6, @@ -314,26 +315,21 @@ int main_gfx() { .polycubes={}, }; - Shader phong_shader = {0}; - phong_shader.init("../assets/shaders/phong-solid.vertex.glsl", "../assets/shaders/phong-solid.fragment.glsl"); + Shader phong_shader = createShader("../assets/shaders/phong-solid.vertex.glsl", "../assets/shaders/phong-solid.fragment.glsl"); app_state.active_shader = &phong_shader; - cube_mesh.init("../assets/models/c000000.obj"); - wall_tex.init("../assets/textures/brick-wall.jpg"); + cube_mesh = createMesh("../assets/models/c000000.obj"); + wall_tex = createTexture("../assets/textures/brick-wall.jpg"); - Frame little_frame = { .width=80, .height=60, .x=20, .y=20 }; - Frame big_frame = { .width=800, .height=600, .x=0, .y=0 }; - Camera main_cam = {}; - Camera other_cam = {}; - little_frame.init(&other_cam); - big_frame.init(&main_cam); - std::vector frames = { &big_frame, &little_frame }; + Frame little_frame = createFrame(arena, 80, 60, 20, 20); + Frame big_frame = createFrame(arena, 800, 600, 0, 0); + Frame *frames[] = { &big_frame, &little_frame }; SceneGraphNode root_node = {}; - root_node.init(); + init_sg_node(&root_node); - for (int i = 0; i < STD_SOMA.size(); i++) { - auto voxel_space = Space{ STD_SOMA[i], 3, 3, 3 }; + for (int i = 0; i < ArrayCount(STD_SOMA); i++) { + Space voxel_space = { STD_SOMA[i], 3, 3, 3 }; cullEmptySpace(&voxel_space); Polycube polycube = create_polycube_from_repr(&voxel_space); polycube.color = color_from_index(i); @@ -341,18 +337,21 @@ int main_gfx() { root_node.children.push_back(app_state.polycubes.back().graph_node); } - main_cam.pos = glm::vec3(4.0f, 4.0f, 4.0f); - main_cam.look_at(0.0f, 0.0f, 0.0f); + big_frame.cam->pos = glm::vec3(0.0f, 4.0f, 4.0f); + camera_look_at(big_frame.cam, 0.0f, 0.0f, 0.0f); - glm::vec3 light_pos = glm::vec3(6.0f); + glm::vec3 light_pos = glm::vec3(4.0f, 12.0f, 2.0f); glUseProgram(app_state.active_shader->prog_id); - GLint view_loc = glGetUniformLocation(app_state.active_shader->prog_id, "view"); - GLint proj_loc = glGetUniformLocation(app_state.active_shader->prog_id, "projection"); - GLint light_pos_loc = glGetUniformLocation(app_state.active_shader->prog_id, "light_pos"); - glUniform3fv(light_pos_loc, 1, glm::value_ptr(light_pos)); - glUniformMatrix4fv(proj_loc, 1, GL_FALSE, glm::value_ptr(main_cam.proj)); - glUniformMatrix4fv(view_loc, 1, GL_FALSE, glm::value_ptr(main_cam.view)); + glUniform3fv( + glGetUniformLocation(app_state.active_shader->prog_id, "light_pos"), + 1, glm::value_ptr(light_pos)); + glUniformMatrix4fv( + glGetUniformLocation(app_state.active_shader->prog_id, "projection"), + 1, GL_FALSE, glm::value_ptr(big_frame.cam->proj)); + glUniformMatrix4fv( + glGetUniformLocation(app_state.active_shader->prog_id, "view"), + 1, GL_FALSE, glm::value_ptr(big_frame.cam->view)); real32 last_frame = glfwGetTime(); real32 time_delta = 1.0f/60.0f; @@ -361,8 +360,8 @@ int main_gfx() { process_input(window); if (app_state.last_polycube_visible != app_state.current_polycube) { - app_state.polycubes[app_state.last_polycube_visible].hide(); - app_state.polycubes[app_state.current_polycube].show(); + hide_polycube(&app_state.polycubes[app_state.last_polycube_visible]); + show_polycube(&app_state.polycubes[app_state.current_polycube]); app_state.last_polycube_visible = app_state.current_polycube; } @@ -374,14 +373,16 @@ int main_gfx() { get_scene_graph_node(current_polycube->graph_node)->rotation = glm::quat(glm::vec3(0, glfwGetTime() / 2, 0)); glBindVertexArray(cube_mesh.vao); - //glBindTexture(GL_TEXTURE_2D, entity.tex->tex_id); recalculate_scene_graph(&root_node); GLint model_uniform_loc = glGetUniformLocation(app_state.active_shader->prog_id, "model"); - GLint solid_color_loc = glGetUniformLocation(app_state.active_shader->prog_id, "solid_color"); - glUniform3fv(solid_color_loc, 1, glm::value_ptr(current_polycube->color)); + glUniform3fv( + glGetUniformLocation(app_state.active_shader->prog_id, "solid_color"), + 1, glm::value_ptr(current_polycube->color)); + for (Entity &entity : entities) { if (entity.visible) { glUniformMatrix4fv(model_uniform_loc, 1, GL_FALSE, glm::value_ptr(get_scene_graph_node(entity.scene_graph_node)->world)); + glBindTexture(GL_TEXTURE_2D, entity.tex->tex_id); glDrawArrays(GL_TRIANGLES, 0, entity.mesh->num_indices); //glDrawElements(GL_TRIANGLES, entity->mesh->num_indices, GL_UNSIGNED_INT, 0); } @@ -396,6 +397,7 @@ int main_gfx() { } int main() { + initialiseCore(); return main_cmd(); }