update
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
3
build
Normal file → Executable file
3
build
Normal file → Executable file
@@ -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
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#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<uint64> 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<uint64> get_reprs_input(int units_required) {
|
||||
typedef std::vector<uint64> SomaSolution;
|
||||
|
||||
struct Solver {
|
||||
std::vector<uint64>* input;
|
||||
std::vector<int>* offsets;
|
||||
list<uint64>* input;
|
||||
list<size_t>* offsets;
|
||||
std::vector<SomaSolution>* solutions;
|
||||
};
|
||||
|
||||
std::vector<uint64> 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<uint64> *polycube_input, std::vector<int> *offsets) {
|
||||
int num_inputs = offsets->size() - 1;
|
||||
@@ -118,18 +120,18 @@ void backtrack_solve_iter(std::vector<uint64> *polycube_input, std::vector<int>
|
||||
std::cout << "Done. Found " << solns.size() << " solutions." << std::endl;
|
||||
}
|
||||
|
||||
void backtrack_solve(Solver *solver, uint64 working_solution = 0, int curr_piece = 0) {
|
||||
std::vector<uint64> *input = solver->input;
|
||||
std::vector<int> *offsets = solver->offsets;
|
||||
void backtrack_solve(Solver *solver, uint64 working_solution = 0, size_t curr_piece = 0) {
|
||||
list<uint64> *input = solver->input;
|
||||
list<size_t> *offsets = solver->offsets;
|
||||
std::vector<SomaSolution> *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<uint64> 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<SomaSolution> get_solution_rotations(SomaSolution *solution, int dims[3]) {
|
||||
std::vector<SomaSolution> get_solution_rotations(Arena *arena, SomaSolution *solution, int dims[3]) {
|
||||
std::vector<SomaSolution> result = std::vector<SomaSolution>(NUM_ROTS_3D);
|
||||
for (int piece_i = 0; piece_i < solution->size(); piece_i++) {
|
||||
Space space = {
|
||||
@@ -153,23 +155,25 @@ std::vector<SomaSolution> get_solution_rotations(SomaSolution *solution, int dim
|
||||
dims[1],
|
||||
dims[2],
|
||||
};
|
||||
std::vector<Space> 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<Space> 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<SomaSolution> filter_unique(std::vector<SomaSolution> *solutions, int dims[3]) {
|
||||
std::vector<SomaSolution> filter_unique(Arena *arena, std::vector<SomaSolution> *solutions, int dims[3]) {
|
||||
if (solutions->size() == 0) {
|
||||
return std::vector<SomaSolution>();
|
||||
}
|
||||
std::vector<SomaSolution> unique_solns = std::vector<SomaSolution>{};
|
||||
for (std::vector<uint64> &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<SomaSolution> rots = get_solution_rotations(temp.arena, &solution, dims);
|
||||
for (SomaSolution &rotation : rots) {
|
||||
for (std::vector<uint64> &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<SomaSolution> filter_unique(std::vector<SomaSolution> *solutions, in
|
||||
break;
|
||||
}
|
||||
}
|
||||
scratchEnd(temp);
|
||||
if (!found_match) {
|
||||
unique_solns.push_back(SomaSolution(solution));
|
||||
}
|
||||
@@ -193,11 +198,13 @@ std::vector<SomaSolution> filter_unique(std::vector<SomaSolution> *solutions, in
|
||||
return unique_solns;
|
||||
}
|
||||
|
||||
std::vector<SomaSolution> solve(std::vector<uint64> *reprs_in, int dims[3]) {
|
||||
std::vector<uint64> reprs = *reprs_in;
|
||||
std::vector<int> offsets = std::vector<int>();
|
||||
std::vector<uint64> polycubes = std::vector<uint64>();
|
||||
polycubes.reserve(reprs.size() * 10);
|
||||
std::vector<SomaSolution> solve(uint64 *reprs_in, uint32 reprs_in_count, int dims[3]) {
|
||||
Arena *arena = arenaAlloc(Megabytes(64));
|
||||
Arena *permsArena = arenaAlloc(Megabytes(64));
|
||||
|
||||
list<size_t> offsets = PushList(arena, size_t, reprs_in_count + 1);
|
||||
|
||||
list<uint64> polycubes = PushList(arena, uint64, 0);
|
||||
|
||||
Space model_space = {
|
||||
{},
|
||||
@@ -206,25 +213,29 @@ std::vector<SomaSolution> solve(std::vector<uint64> *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<uint64> positions = getAllPositionsInPrism(&space, dims);
|
||||
polycubes.insert(polycubes.end(), positions.begin(), positions.end());
|
||||
list<uint64> 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<uint64> perms = getAllPermutationsInPrism(&space, dims);
|
||||
polycubes.insert(polycubes.end(), perms.begin(), perms.end());
|
||||
list<uint64> 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<SomaSolution> solutions = {std::vector<uint64>(reprs.size())};
|
||||
std::vector<SomaSolution> solutions = {std::vector<uint64>(reprs_in_count)};
|
||||
Solver solver = {
|
||||
&polycubes,
|
||||
&offsets,
|
||||
@@ -233,7 +244,7 @@ std::vector<SomaSolution> solve(std::vector<uint64> *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<uint64> reprs = get_reprs_input(dims[0]*dims[1]*dims[2]);
|
||||
std::cout << "Great. Calculating solutions...\n";
|
||||
std::vector<SomaSolution> solutions = solve(&STD_SOMA, dims);
|
||||
std::vector<SomaSolution> solutions = solve(STD_SOMA, ArrayCount(STD_SOMA), dims);
|
||||
std::cout << solutions.size() << " solutions found." << std::endl;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
#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<Space> *existingSpaces, Space* spaceToSpin) {
|
||||
void pushNewUniqueSpins(list<Space> *existingSpaces, Space* spaceToSpin) {
|
||||
Space spins[4] = {};
|
||||
spins[0] = *spaceToSpin;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
@@ -175,30 +178,29 @@ void pushNewUniqueSpins(std::vector<Space> *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<Space> *existingSpaces, Space* spaceToSpin) {
|
||||
void pushXAxisSpins(Arena *arena, list<Space> *existingSpaces, Space* spaceToSpin) {
|
||||
Space refSpace = *spaceToSpin;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
rotate90X(&refSpace);
|
||||
existingSpaces->push_back(refSpace);
|
||||
appendList(existingSpaces, refSpace);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Space> getUniqueRotations(Space *space) {
|
||||
std::vector<Space> rotations = std::vector<Space>();
|
||||
rotations.reserve(24);
|
||||
auto refSpace = *space;
|
||||
list<Space> getUniqueRotations(Arena *arena, Space *space) {
|
||||
list<Space> rotations = PushList(arena, Space, 24);
|
||||
Space refSpace = *space;
|
||||
cullEmptySpace(&refSpace);
|
||||
pushNewUniqueSpins(&rotations, &refSpace);
|
||||
rotate90Y(&refSpace);
|
||||
@@ -212,63 +214,75 @@ std::vector<Space> getUniqueRotations(Space *space) {
|
||||
rotate90Z(&refSpace);
|
||||
rotate90Z(&refSpace);
|
||||
pushNewUniqueSpins(&rotations, &refSpace);
|
||||
rotations.head = rotations.length;
|
||||
arenaPopTo(arena, rotations.data + rotations.head);
|
||||
return rotations;
|
||||
}
|
||||
|
||||
std::vector<Space> getAllRotations(Space *space) {
|
||||
std::vector<Space> rotations = {};
|
||||
rotations.reserve(24);
|
||||
list<Space> getAllRotations(Arena *arena, Space *space) {
|
||||
list<Space> 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<uint64> getAllPositionsInPrism(Space *space, int prism_dims[3]) {
|
||||
std::vector<uint64> cubePositions = {};
|
||||
list<uint64> 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<uint64>{0};
|
||||
}
|
||||
list<uint64> 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<uint64> getAllPermutationsInPrism(Space *space, int prism_dims[3]) {
|
||||
std::vector<Space> rotations = getUniqueRotations(space);
|
||||
std::vector<uint64> result = std::vector();
|
||||
for (auto &rotation : rotations) {
|
||||
auto positions = getAllPositionsInPrism(&rotation, prism_dims);
|
||||
result.insert(result.end(), positions.begin(), positions.end());
|
||||
list<uint64> getAllPermutationsInPrism(Arena *arena, Space *space, int prism_dims[3]) {
|
||||
Scratch temp = scratchStart(&arena, 1);
|
||||
|
||||
list<Space> rotations = getUniqueRotations(temp.arena, space);
|
||||
list<uint64> result = PushList(arena, uint64, 0);
|
||||
for (EachIn(rotations, i)) {
|
||||
list<uint64> 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -53,13 +53,13 @@ void rotate90Z(Space *space);
|
||||
|
||||
void pushNewUniqueSpins(std::vector<Space> *existingSpaces, Space* spaceToSpin);
|
||||
|
||||
std::vector<Space> getUniqueRotations(Space *space);
|
||||
list<Space> getUniqueRotations(Arena *arena, Space *space);
|
||||
|
||||
std::vector<Space> getAllRotations(Space *space);
|
||||
list<Space> getAllRotations(Arena *arena, Space *space);
|
||||
|
||||
std::vector<uint64> getAllPositionsInPrism(Space *space, int prism_dims[3]);
|
||||
list<uint64> getAllPositionsInPrism(Arena *arena, Space *space, int prism_dims[3]);
|
||||
|
||||
std::vector<uint64> getAllPermutationsInPrism(Space *space, int prism_dims[3]);
|
||||
list<uint64> getAllPermutationsInPrism(Arena *arena, Space *space, int prism_dims[3]);
|
||||
|
||||
int size(uint64 space);
|
||||
|
||||
|
||||
@@ -54,5 +54,7 @@ Shader createShader(const char* vertex_path, const char* fragment_path) {
|
||||
|
||||
glDeleteShader(vertex_shader);
|
||||
glDeleteShader(fragment_shader);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
5
src/gfx/gfx.cpp
Normal file
5
src/gfx/gfx.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
#include "Mesh.cpp"
|
||||
#include "Shader.cpp"
|
||||
#include "Texture.cpp"
|
||||
#include "geometry.cpp"
|
||||
#include "Color.cpp"
|
||||
@@ -1,9 +1,12 @@
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
#include <unistd.h> // TODO(djledda): get outta here
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#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() {
|
||||
|
||||
@@ -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 ###
|
||||
|
||||
214
src/main.cpp
214
src/main.cpp
@@ -2,20 +2,24 @@
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
|
||||
#include "lib/glad/glad.h"
|
||||
#include <glm/ext/matrix_transform.hpp>
|
||||
#include "lib/djstdlib/core.h"
|
||||
#include "lib/glad/glad.c"
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <glm/ext/matrix_transform.hpp>
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#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<Polycube> 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,49 +90,46 @@ struct SceneGraphNode {
|
||||
glm::vec3 translation;
|
||||
glm::quat rotation;
|
||||
glm::vec3 scale;
|
||||
std::vector<int> children;
|
||||
std::optional<int> entity;
|
||||
std::vector<uint32> children;
|
||||
std::optional<uint32> 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_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 init() {
|
||||
reset();
|
||||
local = glm::mat4(1.0f);
|
||||
world = local;
|
||||
}
|
||||
|
||||
void update_local() {
|
||||
local = glm::scale(
|
||||
void recalculate_sg_node(SceneGraphNode *n) {
|
||||
n->local = glm::scale(
|
||||
glm::translate(
|
||||
glm::mat4(1.0f),
|
||||
translation
|
||||
) * glm::toMat4(rotation),
|
||||
scale
|
||||
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);
|
||||
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() {
|
||||
SceneGraphNode *node = get_scene_graph_node(graph_node);
|
||||
for (int &child : node->children) {
|
||||
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;
|
||||
@@ -133,29 +137,33 @@ struct Polycube {
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec3 get_centre() {
|
||||
glm::vec3 centreFromPolycube(Polycube *p) {
|
||||
glm::vec3 centre = glm::vec3(0.0f);
|
||||
for (int &child : get_scene_graph_node(graph_node)->children) {
|
||||
for (uint32 &child : get_scene_graph_node(p->graph_node)->children) {
|
||||
centre += get_scene_graph_node(child)->translation;
|
||||
}
|
||||
centre /= get_scene_graph_node(graph_node)->children.size();
|
||||
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<Frame> 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();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user