This commit is contained in:
Daniel Ledda
2025-02-17 14:13:22 +01:00
parent a89ef8ddde
commit 95b781a4b9
14 changed files with 5609 additions and 326 deletions

View File

@@ -2,29 +2,28 @@
out vec4 frag_color;
uniform vec3 light_pos;
uniform vec3 solid_color;
uniform vec4 solid_color;
uniform vec3 camera;
in vec3 normal;
in vec3 frag_position;
void main() {
vec3 light_color = vec3(1, 1, 1);
vec4 light_color = vec4(1, 1, 1, 1);
vec3 normal_norm = normalize(normal);
vec3 light_direction_norm = normalize(light_pos - frag_position);
float ambient_strength = 0.15;
vec3 ambient = ambient_strength * light_color;
vec4 ambient = ambient_strength * light_color;
float diffuse_strength = max(dot(normal_norm, light_direction_norm), 0.0);
vec3 diffuse = diffuse_strength * light_color;
vec4 diffuse = diffuse_strength * light_color;
float specular_strength = 0.9;
vec3 view_direction_norm = normalize(camera - 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;
vec4 specular = specular_strength * spec * light_color;
vec3 phong = specular + (ambient + diffuse) * solid_color;
frag_color = vec4(phong, 1.0);
frag_color = specular + (ambient + diffuse) * solid_color;
}

View File

@@ -6,7 +6,6 @@ layout (location = 2) in vec3 a_normal;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform vec3 light_pos;
out vec3 normal;
out vec3 frag_position;

View File

@@ -296,3 +296,23 @@ int size(uint64 space) {
}
return size;
}
bool spaceValueAt(Space *space, int x, int y, int z) {
uint64 mask = 1 << (space->dim_y * space->dim_z * x + space->dim_z * y + z);
return (space->space & mask) != 0;
}
void spaceToggle(Space *space, int x, int y, int z) {
uint64 mask = 1 << (space->dim_y * space->dim_z * x + space->dim_z * y + z);
space->space ^= mask;
}
void spaceSet(Space *space, bool val, int x, int y, int z) {
uint64 mask = 1 << (space->dim_y * space->dim_z * x + space->dim_z * y + z);
if (val) {
space->space |= mask;
} else {
space->space &= ~mask;
}
}

View File

@@ -63,4 +63,10 @@ list<uint64> getAllPermutationsInPrism(Arena *arena, Space *space, int prism_dim
int size(uint64 space);
bool spaceValueAt(Space *space, int x, int y, int z);
void spaceToggle(Space *space, int x, int y, int z);
void spaceSet(Space *space, bool val, int x, int y, int z);
#endif

View File

@@ -1,8 +1,7 @@
#include <glm/ext/vector_float3.hpp>
#include <math.h>
#include "../lib/djstdlib/core.h"
#include "Color.h"
real32 hue_to_rgb(real32 p, real32 q, real32 t) {
real32 hueToRGB(real32 p, real32 q, real32 t) {
if (t < 0) {
t += 1;
} else if (t > 1) {
@@ -14,7 +13,7 @@ real32 hue_to_rgb(real32 p, real32 q, real32 t) {
return p;
};
glm::vec3 hsl_to_hex(real32 h, real32 s, real32 l) {
Vector4<real32> hslToHex(real32 h, real32 s, real32 l) {
h /= 360;
s /= 100;
l /= 100;
@@ -24,14 +23,14 @@ glm::vec3 hsl_to_hex(real32 h, real32 s, real32 l) {
} else {
real32 q = l < 0.5f ? l * (1 + s) : l + s - l * s;
real32 p = 2 * l - q;
r = hue_to_rgb(p, q, h + 1.0f / 3);
g = hue_to_rgb(p, q, h);
b = hue_to_rgb(p, q, h - 1.0f / 3);
r = hueToRGB(p, q, h + 1.0f / 3);
g = hueToRGB(p, q, h);
b = hueToRGB(p, q, h - 1.0f / 3);
}
return glm::vec3(r, g, b);
return vec4<real32>(r, g, b, 1);
}
glm::vec3 color_from_index(int index) {
Vector4<real32> colorFromIndex(int index) {
real32 color_wheel_cycle = floorf(index / 6.0f);
real32 darkness_cycle = floorf(index / 12.0f);
real32 spacing = (360.0f / 6.0f);
@@ -39,5 +38,5 @@ glm::vec3 color_from_index(int index) {
real32 hue = spacing * (index % 6) + offset;
real32 saturation = 100.0f;
real32 lightness = 1.0f / (2 + darkness_cycle) * 100;
return hsl_to_hex(hue, saturation, lightness);
return hslToHex(hue, saturation, lightness);
}

View File

@@ -1,3 +1,17 @@
#include <glm/ext/vector_float3.hpp>
#ifndef COLOR_H
#define COLOR_H
glm::vec3 color_from_index(int index);
#include "../lib/djstdlib/core.h"
#define COLOR_BLACK vec4<real32>(0, 0, 0, 1)
#define COLOR_RED vec4<real32>(1, 0, 0, 1)
#define COLOR_GREEN vec4<real32>(0, 1, 0, 1)
#define COLOR_BLUE vec4<real32>(0, 0, 1, 1)
#define COLOR_MAGENTA vec4<real32>(1, 0, 1, 1)
#define COLOR_YELLOW vec4<real32>(1, 1, 0, 1)
#define COLOR_CYAN vec4<real32>(0, 1, 1, 1)
#define COLOR_WHITE vec4<real32>(1, 1, 1, 1)
Vector4<real32> colorFromIndex(int index);
#endif

View File

@@ -38,18 +38,18 @@ Shader createShader(string vertex_path, string fragment_path) {
uint32 vertex_shader = createGlShader(vertex_path, ShaderType::vertex);
uint32 fragment_shader = createGlShader(fragment_path, ShaderType::fragment);
result.prog_id = glCreateProgram();
glAttachShader(result.prog_id, vertex_shader);
glAttachShader(result.prog_id, fragment_shader);
glLinkProgram(result.prog_id);
result.progId = glCreateProgram();
glAttachShader(result.progId, vertex_shader);
glAttachShader(result.progId, fragment_shader);
glLinkProgram(result.progId);
int success;
glGetProgramiv(result.prog_id, GL_LINK_STATUS, &success);
glGetProgramiv(result.progId, GL_LINK_STATUS, &success);
if (!success) {
GLint info_log_length;
glGetShaderiv(result.prog_id, GL_INFO_LOG_LENGTH, &info_log_length);
glGetShaderiv(result.progId, GL_INFO_LOG_LENGTH, &info_log_length);
string info_log_prog = PushString(temp.arena, (size_t)info_log_length + 1);
glGetProgramInfoLog(result.prog_id, info_log_length, NULL, info_log_prog.str);
glGetProgramInfoLog(result.progId, info_log_length, NULL, info_log_prog.str);
print("Shader program link error:\n%S", info_log_prog);
}
@@ -62,38 +62,43 @@ Shader createShader(string vertex_path, string fragment_path) {
void setUniformMat4fv(Shader *s, const char *uniformName, glm::mat4 *matrix) {
glUniformMatrix4fv(
glGetUniformLocation(s->prog_id, uniformName),
glGetUniformLocation(s->progId, uniformName),
1, GL_FALSE, glm::value_ptr(*matrix));
}
void setUniformMat4fv(int uniformLocation, glm::mat4 *matrix) {
glUniformMatrix4fv(uniformLocation, 1, GL_FALSE, glm::value_ptr(*matrix));
}
void setUniform4fv(Shader *s, const char *uniformName, glm::vec4 *vector) {
glUniform4fv(glGetUniformLocation(s->prog_id, uniformName), 1, glm::value_ptr(*vector));
void setUniform4fv(Shader *s, const char *uniformName, Vector4<real32> *vector) {
glUniform4fv(glGetUniformLocation(s->progId, uniformName), 1, vector->vec);
}
void setUniform4fv(Shader *s, const char *uniformName, glm::vec4 *vector) {
glUniform4fv(glGetUniformLocation(s->progId, uniformName), 1, glm::value_ptr(*vector));
}
void setUniform4fv(int uniformLocation, glm::vec4 *vector) {
glUniform4fv(uniformLocation, 1, glm::value_ptr(*vector));
}
void setUniform3fv(Shader *s, const char *uniformName, glm::vec3 *vector) {
glUniform3fv(glGetUniformLocation(s->prog_id, uniformName), 1, glm::value_ptr(*vector));
void setUniform3fv(Shader *s, const char *uniformName, Vector3<real32> *vector) {
glUniform3fv(glGetUniformLocation(s->progId, uniformName), 1, vector->vec);
}
void setUniform3fv(Shader *s, const char *uniformName, glm::vec3 *vector) {
glUniform3fv(glGetUniformLocation(s->progId, uniformName), 1, glm::value_ptr(*vector));
}
void setUniform3fv(int uniformLocation, glm::vec3 *vector) {
glUniform3fv(uniformLocation, 1, glm::value_ptr(*vector));
}
void setUniform2fv(Shader *s, const char *uniformName, glm::vec2 *vector) {
glUniform2fv(glGetUniformLocation(s->prog_id, uniformName), 1, glm::value_ptr(*vector));
void setUniform2fv(Shader *s, const char *uniformName, Vector2<real32> *vector) {
glUniform2fv(glGetUniformLocation(s->progId, uniformName), 1, vector->vec);
}
void setUniform2fv(Shader *s, const char *uniformName, glm::vec2 *vector) {
glUniform2fv(glGetUniformLocation(s->progId, uniformName), 1, glm::value_ptr(*vector));
}
void setUniform2fv(int uniformLocation, glm::vec2 *vector) {
glUniform2fv(uniformLocation, 1, glm::value_ptr(*vector));
}
int getUniformLocation(Shader *s, const char *uniformName) {
return glGetUniformLocation(s->prog_id, uniformName);
return glGetUniformLocation(s->progId, uniformName);
}

View File

@@ -5,7 +5,7 @@
#include "../lib/djstdlib/core.h"
struct Shader {
uint32 prog_id;
uint32 progId;
};
Shader createShader(string vertex_path, string fragment_path);

10
src/gfx/gfx.h Normal file
View File

@@ -0,0 +1,10 @@
#ifndef GFX_H
#define GFX_H
#include "Mesh.h"
#include "Shader.h"
#include "Texture.h"
#include "geometry.h"
#include "Color.h"
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -15,6 +15,7 @@
// Project
#include "SomaSolve.cpp" // errors from iostream also defining the keyword `global`
#include "gfx/gfx.cpp"
#include "world/world.cpp"
#include "VoxelSpace.cpp"
#include "./tests.cpp"
#include "lib/djstdlib/core.cpp"
@@ -27,13 +28,6 @@
#define PI (real32)3.14159265358979323846264338327950288
struct Entity;
struct SceneGraphNode;
uint32 new_entity();
Entity *get_entity(uint32 id);
SceneGraphNode *get_scene_graph_node(int id);
uint32 new_graph_node();
void print(glm::vec3* vector) {
glm::vec3 vec = *vector;
print(
@@ -75,7 +69,7 @@ Camera *createCamera(Arena *arena, real32 aspect_ratio = 800.0f / 600.0f) {
return result;
}
void camera_look_at(Camera *c, float x, float y, float z) {
void cameraLookAt(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);
}
@@ -84,28 +78,6 @@ 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 WindowDims {
uint32 width;
uint32 height;
};
struct Entity {
Mesh *mesh;
Texture *tex;
bool visible;
uint32 scene_graph_node;
};
struct SceneGraphNode {
glm::mat4 local;
glm::mat4 world;
glm::vec3 translation;
glm::quat rotation;
glm::vec3 scale;
std::vector<uint32> children;
uint32 entity;
};
struct Frame {
uint32 width;
uint32 height;
@@ -115,69 +87,108 @@ struct Frame {
};
struct Polycube {
int graph_node;
uint32 entityHandle;
Space repr;
glm::vec3 color;
Vector4<real32> color;
};
struct GlobalAppState {
bool wireframe = false;
uint32 current_polycube;
uint32 last_polycube_visible;
struct RenderObjects_Rectangle {
uint32 vao;
list<Vector2<real32>> p0;
uint32 p0BufferId;
list<Vector2<real32>> p1;
uint32 p1BufferId;
list<Vector4<real32>> color;
uint32 colorBufferId;
uint64 count;
};
struct Input {
struct {
bool escape;
bool enter;
bool space;
bool lshift;
bool x;
bool y;
bool z;
} keyboard;
struct {
union {
struct {
real32 x;
real32 y;
};
Vector2<real32> point;
};
bool btnLeft;
bool btnRight;
bool btnMiddle;
} mouse;
};
struct Renderer {
Scene *scene;
RenderObjects_Rectangle rects;
};
struct PolycubeInput {
Space repr;
Vector4<real32> color;
};
struct SomaState {
bool wireframe;
bool polycubeDirty;
uint32 currentPolycube;
uint32 lastPolycubeVisible;
uint32 light;
Shader *active_shader;
std::vector<Polycube> polycubes;
list<Polycube> polycubes;
Camera* camera;
glm::vec3 rotAxisX;
glm::vec3 rotAxisY;
list<PolycubeInput> polycubeInput;
};
GlobalAppState app_state = {};
struct Soma {
Scene *scene;
Renderer *renderer;
SomaState state;
Input currInput;
Input prevInput;
struct {
GLFWwindow *handle;
uint32 width;
uint32 height;
} window;
};
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(1.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
);
}
void show_polycube(Polycube *p) {
SceneGraphNode *node = get_scene_graph_node(p->graph_node);
void showEntity(Scene *scene, uint32 entityHandle) {
SceneGraphNode *node = getSceneGraphNodeForEntity(scene, entityHandle);
for (uint32 &child : node->children) {
SceneGraphNode *subNode = get_scene_graph_node(child);
if (subNode->entity) {
get_entity(subNode->entity)->visible = true;
SceneGraphNode *subNode = getSceneGraphNode(scene, child);
if (subNode->entityHandle) {
getEntity(scene, subNode->entityHandle)->flags |= EntityFlags_Visible;
}
}
}
void hide_polycube(Polycube *p) {
SceneGraphNode *node = get_scene_graph_node(p->graph_node);
void hideEntity(Scene *scene, uint32 entityHandle) {
SceneGraphNode *node = getSceneGraphNodeForEntity(scene, entityHandle);
for (uint32 &child : node->children) {
SceneGraphNode *subNode = get_scene_graph_node(child);
if (subNode->entity) {
get_entity(subNode->entity)->visible = false;
SceneGraphNode *subNode = getSceneGraphNode(scene, child);
if (subNode->entityHandle) {
getEntity(scene, subNode->entityHandle)->flags &= ~EntityFlags_Visible;
}
}
}
glm::vec3 centreFromPolycube(Polycube *p) {
glm::vec3 centreFromPolycube(Scene *scene, 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;
for (uint32 &child : getSceneGraphNode(scene, p->entityHandle)->children) {
centre += getSceneGraphNode(scene, child)->translation;
}
centre /= get_scene_graph_node(p->graph_node)->children.size();
centre /= getSceneGraphNodeForEntity(scene, p->entityHandle)->children.size();
return centre;
}
@@ -191,67 +202,61 @@ Frame createFrame(Arena *arena, uint32 width, uint32 height, uint32 x, uint32 y)
return result;
}
void framebuffer_size_callback(GLFWwindow *window, int width, int height) {
void framebufferSizeCallback(GLFWwindow *window, int width, int height) {
glViewport(0, 0, width, height);
}
GLFWwindow *init_window_and_gl(WindowDims *window_dims) {
GLFWwindow *initWindowAndGL(uint32 windowWidth, uint32 windowHeight) {
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow *window = glfwCreateWindow(window_dims->width, window_dims->height, "Somaesque", NULL, NULL);
GLFWwindow *window = glfwCreateWindow(windowWidth, windowHeight, "Somaesque", NULL, NULL);
if (window == NULL) {
std::cout << "Failed to create GLFW window" << std::endl;
print("Failed to create GLFW window\n");
glfwTerminate();
return nullptr;
return NULL;
}
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
std::cout << "Failed to initilaize GLAD" << std::endl;
return nullptr;
print("Failed to initilaize GLAD\n");
return NULL;
}
glViewport(0, 0, 800, 600);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwSetFramebufferSizeCallback(window, framebufferSizeCallback);
glfwSetInputMode(window, GLFW_CURSOR | GLFW_RAW_MOUSE_MOTION, GLFW_CURSOR_NORMAL);
glEnable(GL_DEPTH_TEST);
return window;
}
void update_viewport_from_frame(WindowDims* window_dims, Frame* frame) {
glViewport(frame->x, window_dims->height - frame->y - frame->height, frame->width, frame->height);
void updateViewportFromFrame(uint32 windowWidth, uint32 windowHeight, Frame* frame) {
glViewport(frame->x, windowHeight - frame->y - frame->height, frame->width, frame->height);
}
Mesh cube_mesh = {0};
Texture wall_tex = {0};
Shader solid_color_shader;
Shader phong_shader;
std::vector<Entity> entities = std::vector<Entity>();
std::vector<SceneGraphNode> scene_graph_nodes = std::vector<SceneGraphNode>();
struct Input {
struct {
bool escape;
bool enter;
bool space;
bool lshift;
bool x;
bool y;
bool z;
} keyboard;
struct {
real64 x;
real64 y;
bool btnLeft;
bool btnRight;
bool btnMiddle;
} mouse;
struct UI_Context {
Renderer *renderer;
Input *prevInput;
Input *input;
bool cursorIsPointer;
};
struct UI_Rect {
real32 x;
real32 y;
real32 width;
real32 height;
real32 borderRadius;
Vector4<real32> color;
};
Mesh cubeMesh = {0};
Texture wallTex = {0};
Shader solidColorShader;
Shader phongShader;
inline bool glfwMouse(GLFWwindow *window, int mouseBtnCode) {
switch (glfwGetMouseButton(window, mouseBtnCode)) {
case GLFW_RELEASE: return false;
@@ -268,7 +273,7 @@ inline bool glfwKey(GLFWwindow *window, int keyCode) {
}
}
Input get_current_input(GLFWwindow *window) {
Input getCurrentInput(GLFWwindow *window) {
Input input = {0};
input.keyboard.escape = glfwKey(window, GLFW_KEY_ESCAPE);
@@ -283,130 +288,87 @@ Input get_current_input(GLFWwindow *window) {
input.mouse.btnRight = glfwMouse(window, GLFW_MOUSE_BUTTON_RIGHT);
input.mouse.btnMiddle = glfwMouse(window, GLFW_MOUSE_BUTTON_MIDDLE);
glfwGetCursorPos(window, &input.mouse.x, &input.mouse.y);
real64 mouseX;
real64 mouseY;
glfwGetCursorPos(window, &mouseX, &mouseY);
input.mouse.point = vec2<real32>((real32)mouseX, (real32)mouseY);
return input;
}
void process_input(GLFWwindow *window, Input *input, Input *prevInput) {
void processInput(Soma *soma) {
Input *input = &soma->currInput;
Input *prevInput = &soma->prevInput;
if (input->keyboard.escape) {
glfwSetWindowShouldClose(window, true);
glfwSetWindowShouldClose(soma->window.handle, true);
}
if (input->keyboard.space && !prevInput->keyboard.space) {
glPolygonMode(GL_FRONT_AND_BACK, !app_state.wireframe ? GL_LINE : GL_FILL);
app_state.wireframe = !app_state.wireframe;
glPolygonMode(GL_FRONT_AND_BACK, !soma->state.wireframe ? GL_LINE : GL_FILL);
soma->state.wireframe = !soma->state.wireframe;
}
SceneGraphNode *node = get_scene_graph_node(get_entity(app_state.light)->scene_graph_node);
SceneGraphNode *node = getSceneGraphNode(soma->scene, getEntity(soma->scene, soma->state.light)->graphNodeHandle);
int shiftMultiplier = input->keyboard.lshift ? -1 : 1;
node->translation.x += 1.0 * input->keyboard.x * shiftMultiplier;
node->translation.y += 1.0 * input->keyboard.y * shiftMultiplier;
node->translation.z += 1.0 * input->keyboard.z * shiftMultiplier;
if (input->keyboard.enter && !prevInput->keyboard.enter) {
if (app_state.current_polycube == 6) {
app_state.current_polycube = 0;
if (soma->state.currentPolycube == 6) {
soma->state.currentPolycube = 0;
} else {
app_state.current_polycube += 1;
soma->state.currentPolycube += 1;
}
}
bool dragScene = false;
if (input->mouse.btnLeft) {
Polycube *current_polycube = &app_state.polycubes[app_state.current_polycube];
SceneGraphNode *polycube_graph_node = get_scene_graph_node(current_polycube->graph_node);
Polycube *current_polycube = &soma->state.polycubes.data[soma->state.currentPolycube];
SceneGraphNode *polycubeGraphNode = getSceneGraphNodeForEntity(soma->scene, current_polycube->entityHandle);
real64 deltaX = (input->mouse.x - prevInput->mouse.x) * 0.005;
if (deltaX > 0.00000001 || deltaX < -0.00000001) {
polycube_graph_node->rotation *= glm::angleAxis((real32)deltaX, app_state.rotAxisY);
polycubeGraphNode->rotation *= glm::angleAxis((real32)deltaX, soma->state.rotAxisY);
}
real64 deltaY = (input->mouse.y - prevInput->mouse.y) * 0.005;
if (deltaY > 0.00000001 || deltaY < -0.00000001) {
polycube_graph_node->rotation = glm::angleAxis(-(real32)deltaY, app_state.rotAxisX) * polycube_graph_node->rotation;
polycubeGraphNode->rotation = glm::angleAxis(-(real32)deltaY, soma->state.rotAxisX) * polycubeGraphNode->rotation;
}
}
}
uint32 new_entity() {
entities.emplace_back();
scene_graph_nodes.emplace_back();
entities.back().scene_graph_node = (uint32)scene_graph_nodes.size();
scene_graph_nodes.back().entity = (uint32)entities.size();
return (uint32)entities.size();
}
Entity *get_entity(uint32 id) {
return &entities[id - 1];
}
SceneGraphNode *get_scene_graph_node(int id) {
return &scene_graph_nodes[id - 1];
}
uint32 new_graph_node() {
scene_graph_nodes.emplace_back();
return (uint32)scene_graph_nodes.size();
}
Polycube create_polycube_from_repr(Space *repr) {
uint32 polycube_id = new_graph_node();
init_sg_node(get_scene_graph_node(polycube_id));
Polycube createPolycubeFromRepr(Soma *soma, Space *repr, Vector4<real32> color) {
uint32 polycubeMainEntityHandle = createEntity(soma->scene);
Entity *polycubeMainEntity = getEntity(soma->scene, polycubeMainEntityHandle);
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++) {
if (filledAt(repr, x, y, z)) {
Entity *polycube_segment = get_entity(new_entity());
polycube_segment->mesh = &cube_mesh;
polycube_segment->tex = &wall_tex;
SceneGraphNode *graph_node = get_scene_graph_node(polycube_segment->scene_graph_node);
init_sg_node(graph_node);
graph_node->translation = glm::vec3(
uint32 segmentEntityHandle = createEntity(soma->scene);
Entity *polycubeSegment = getEntity(soma->scene, segmentEntityHandle);
polycubeSegment->mesh = &cubeMesh;
polycubeSegment->tex = &wallTex;
SceneGraphNode *graphNode = getSceneGraphNode(soma->scene, polycubeSegment->graphNodeHandle);
graphNode->translation = glm::vec3(
-((repr->dim_z - 1)/2.0f) + z,
((repr->dim_x - 1)/2.0f) - x,
-((repr->dim_y - 1)/2.0f) + y
);
recalculate_sg_node(graph_node);
get_scene_graph_node(polycube_id)->children.push_back(polycube_segment->scene_graph_node);
sceneNodeAddEntity(soma->scene, polycubeMainEntity->graphNodeHandle, segmentEntityHandle);
}
}
}
}
Polycube result = {};
result.graph_node = polycube_id;
result.color = glm::vec3(1.0f);
result.entityHandle = polycubeMainEntityHandle;
result.color = color;
result.repr = *repr;
return result;
}
void recalculate_scene_graph(SceneGraphNode *top) {
if (top->children.size() == 0) {
return;
}
for (uint32 &node_id : top->children) {
SceneGraphNode *graph_node = get_scene_graph_node(node_id);
recalculate_sg_node(graph_node);
graph_node->world = top->world * graph_node->local;
recalculate_scene_graph(graph_node);
}
}
struct RenderObjects_Rectangle {
uint32 vao;
list<Vector2<real32>> p0;
uint32 p0BufferId;
list<Vector2<real32>> p1;
uint32 p1BufferId;
list<Vector4<real32>> color;
uint32 colorBufferId;
uint64 count;
};
struct Renderer {
uint32 scene_root;
RenderObjects_Rectangle rects;
};
RenderObjects_Rectangle createRectangleObjects(Arena *arena, size_t count) {
RenderObjects_Rectangle result = {0};
result.count = count;
@@ -461,11 +423,12 @@ void reinitRectangleObjectBuffers(Renderer *r) {
glBufferSubData(GL_ARRAY_BUFFER, 0, r->rects.color.head * sizeof(Vector4<real32>), r->rects.color.data);
}
Renderer createRenderer(Arena *arena) {
Renderer createRenderer(Arena *arena, Scene *scene) {
Renderer result = {0};
result.scene = scene;
result.scene->sceneRoot = createSceneGraphNode(scene);
result.rects = createRectangleObjects(arena, 100);
result.scene_root = new_graph_node();
init_sg_node(get_scene_graph_node(result.scene_root));
initGraphNode(getSceneGraphNode(scene, scene->sceneRoot));
return result;
}
@@ -475,67 +438,93 @@ void renderBegin(Renderer *r) {
r->rects.color.head = 0;
}
void renderEnd(Renderer *r) {
void renderEnd(Soma *soma, Renderer *renderer) {
// 3D Entities
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
Polycube *current_polycube = &app_state.polycubes[app_state.current_polycube];
glBindVertexArray(cube_mesh.vao);
glUseProgram(phongShader.progId);
setUniformMat4fv(&phongShader, "projection", &soma->state.camera->proj);
setUniformMat4fv(&phongShader, "view", &soma->state.camera->view);
setUniform3fv(app_state.active_shader, "solid_color", &current_polycube->color);
int model_uniform = getUniformLocation(app_state.active_shader, "model");
for (Entity &entity : entities) {
if (entity.visible) {
setUniformMat4fv(model_uniform, &get_scene_graph_node(entity.scene_graph_node)->world);
SceneGraphNode *lightGraphNode = getSceneGraphNode(soma->scene, getEntity(soma->scene, soma->state.light)->graphNodeHandle);
setUniform3fv(&phongShader, "light_pos", &lightGraphNode->translation);
setUniform3fv(&phongShader, "camera", &soma->state.camera->pos);
Polycube *currentPolycube = &soma->state.polycubes.data[soma->state.currentPolycube];
glBindVertexArray(cubeMesh.vao);
setUniform4fv(&phongShader, "solid_color", &currentPolycube->color);
int model_uniform = getUniformLocation(&phongShader, "model");
for (Entity &entity : renderer->scene->entities) {
if (entity.flags & EntityFlags_Render && entity.flags & EntityFlags_Visible) {
setUniformMat4fv(model_uniform, &getSceneGraphNode(renderer->scene, entity.graphNodeHandle)->world);
glBindTexture(GL_TEXTURE_2D, entity.tex->tex_id);
glDrawArrays(GL_TRIANGLES, 0, (GLsizei)entity.mesh->num_indices);
entity.flags &= ~EntityFlags_Render;
}
}
// 2D overlay
Shader *last_shader = app_state.active_shader;
app_state.active_shader = &solid_color_shader;
glUseProgram(solidColorShader.progId);
glUseProgram(app_state.active_shader->prog_id);
reinitRectangleObjectBuffers(r);
reinitRectangleObjectBuffers(renderer);
glm::mat4 ortho = glm::ortho(0.0, 800.0, 600.0, 0.0, -1.0, 1.0);
setUniformMat4fv(app_state.active_shader, "projection", &ortho);
setUniformMat4fv(&solidColorShader, "projection", &ortho);
glBindVertexArray(r->rects.vao);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, r->rects.p0.head);
app_state.active_shader = last_shader;
glBindVertexArray(renderer->rects.vao);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, renderer->rects.p0.head);
}
void placeRectangle(Renderer *r, real32 x, real32 y, real32 width, real32 height, Vector4<real32> color) {
void rendererPlaceRectangle(Renderer *r, real32 x, real32 y, real32 width, real32 height, Vector4<real32> color) {
appendList(&r->rects.p0, vec2<real32>(x, y));
appendList(&r->rects.p1, vec2<real32>(x + width, y + height));
appendList(&r->rects.color, color);
}
void drawUI(Renderer *renderer) {
Polycube currentPolycube = app_state.polycubes[app_state.current_polycube];
Vector4 currPolycubeColor = vec4<real32>(currentPolycube.color.x, currentPolycube.color.y, currentPolycube.color.z, 1);
Vector4 white = vec4<real32>(1, 1, 1, 1);
inline bool pointInRect(Vector2<real32> point, UI_Rect rect) {
return point.x > rect.x && point.y > rect.y && point.x < (rect.x + rect.width) && point.y < (rect.y + rect.height);
}
Space repr = currentPolycube.repr;
int boxSize = 30;
int padding = 20;
int paddingBetween = 5;
int currY = padding;
for (int x = 0; x < repr.dim_x; x++) {
for (int y = 0; y < repr.dim_y; y++) {
int currX = padding;
for (int z = 0; z < repr.dim_z; z++) {
placeRectangle(renderer,
bool ui_checkboxRect(UI_Context *ui, bool *value, UI_Rect rect) {
bool clicked = false;
if (pointInRect(ui->input->mouse.point, rect)) {
ui->cursorIsPointer = true;
if (ui->prevInput->mouse.btnLeft && !ui->input->mouse.btnLeft) {
*value = !*value;
clicked = true;
}
}
rendererPlaceRectangle(ui->renderer, rect.x, rect.y, rect.width, rect.height, *value ? rect.color : vec4<real32>(1, 1, 1, 1));
return clicked;
}
void uiPass(Soma *soma, UI_Context *ui, Renderer *renderer) {
PolycubeInput *currentPolycube = &soma->state.polycubeInput.data[soma->state.currentPolycube];
real32 boxSize = 30;
real32 padding = 20;
real32 paddingBetween = 5;
real32 currY = padding;
for (int x = 0; x < currentPolycube->repr.dim_x; x++) {
for (int y = 0; y < currentPolycube->repr.dim_y; y++) {
real32 currX = padding;
for (int z = 0; z < currentPolycube->repr.dim_z; z++) {
bool cellActive = filledAt(&currentPolycube->repr, x, y, z);
UI_Rect rect = {
currX,
currY,
boxSize,
boxSize,
filledAt(&currentPolycube.repr, x, y, z) ? currPolycubeColor : white);
0,
currentPolycube->color,
};
if (ui_checkboxRect(ui, &cellActive, rect)) {
soma->state.polycubeDirty = true;
spaceSet(&currentPolycube->repr, cellActive, x, y, z);
}
currX += paddingBetween + boxSize;
}
currY += paddingBetween + boxSize;
@@ -549,26 +538,38 @@ int main_cmd() {
return 0;
}
int main_gfx() {
int mainGfx() {
Arena *arena = arenaAlloc(Megabytes(128));
WindowDims window_dims = { 800, 600 };
GLFWwindow *window = init_window_and_gl(&window_dims);
if (!window) {
Scene mainScene = createScene();
Soma soma = {};
soma.window.width = 800;
soma.window.height = 600;
soma.window.handle = initWindowAndGL(soma.window.width, soma.window.height);
soma.scene = &mainScene;
Renderer renderer = createRenderer(arena, &mainScene);
soma.renderer = &renderer;
if (!soma.window.handle) {
return -1;
}
Frame main_frame = createFrame(arena, window_dims.width, window_dims.height, 0, 0);
Frame mainFrame = createFrame(arena, soma.window.width, soma.window.height, 0, 0);
UI_Context ui = {};
app_state.current_polycube = 0;
app_state.last_polycube_visible = 6;
app_state.active_shader = 0;
app_state.polycubes = {};
app_state.light = new_entity();
app_state.camera = main_frame.cam;
GLFWcursor *pointerCursor = glfwCreateStandardCursor(GLFW_HAND_CURSOR);
GLFWcursor *arrowCursor = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
SceneGraphNode *light_graph_node = get_scene_graph_node(get_entity(app_state.light)->scene_graph_node);
light_graph_node->translation = glm::vec3(4.0f, 6.0f, 24.0f);
soma.state.currentPolycube = 0;
soma.state.lastPolycubeVisible = 6;
soma.state.polycubeInput = PushListZero(arena, PolycubeInput, 64);
soma.state.polycubes = PushListZero(arena, Polycube, 64);
soma.state.light = createEntity(&mainScene);
soma.state.camera = mainFrame.cam;
SceneGraphNode *light = getSceneGraphNode(&mainScene, getEntity(&mainScene, soma.state.light)->graphNodeHandle);
light->translation = glm::vec3(4.0f, 6.0f, 24.0f);
/*
Shader solid_texture_shader = createShader(
@@ -576,79 +577,91 @@ int main_gfx() {
"./assets/shaders/2d-tex.fragment.glsl"_s);
*/
solid_color_shader = createShader(
solidColorShader = createShader(
"./assets/shaders/2d-solid.vertex.glsl"_s,
"./assets/shaders/2d-solid.fragment.glsl"_s);
phong_shader = createShader(
phongShader = createShader(
"./assets/shaders/phong-solid.vertex.glsl"_s,
"./assets/shaders/phong-solid.fragment.glsl"_s);
app_state.active_shader = &phong_shader;
cube_mesh = createMesh("./assets/models/cube.obj");
wall_tex = createTexture("./assets/textures/brick-wall.jpg");
Renderer renderer = createRenderer(arena);
cubeMesh = createMesh("./assets/models/cube.obj");
wallTex = createTexture("./assets/textures/brick-wall.jpg");
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);
app_state.polycubes.push_back(polycube);
get_scene_graph_node(renderer.scene_root)->children.push_back(app_state.polycubes.back().graph_node);
Space voxelSpace = { STD_SOMA[i], 3, 3, 3 };
Vector4<real32> color = colorFromIndex(i);
appendList(&soma.state.polycubeInput, PolycubeInput{ voxelSpace, color });
cullEmptySpace(&voxelSpace);
Polycube polycube = createPolycubeFromRepr(&soma, &voxelSpace, color);
polycube.color = color;
appendList(&soma.state.polycubes, polycube);
sceneNodeAddEntity(renderer.scene, renderer.scene->sceneRoot, polycube.entityHandle);
}
app_state.camera->pos = glm::vec3(0.0f, 0.0f, 8.0f);
camera_look_at(app_state.camera, 0.0f, 0.0f, 0.0f);
soma.state.camera->pos = glm::vec3(0.0f, 0.0f, 8.0f);
cameraLookAt(soma.state.camera, 0.0f, 0.0f, 0.0f);
SceneGraphNode *reference_polycube_gn = get_scene_graph_node(app_state.polycubes.back().graph_node);
app_state.rotAxisY = glm::normalize(glm::vec4(0, 1, 0, 0) * glm::inverse(reference_polycube_gn->world));
glm::vec3 eyes = glm::normalize(app_state.camera->pos - reference_polycube_gn->translation);
app_state.rotAxisX = glm::normalize(glm::cross(eyes, app_state.rotAxisY));
SceneGraphNode *reference_polycube_gn = getSceneGraphNodeForEntity(soma.scene, soma.state.polycubes.data[0].entityHandle);
soma.state.rotAxisY = glm::normalize(glm::vec4(0, 1, 0, 0) * glm::inverse(reference_polycube_gn->world));
glm::vec3 eyes = glm::normalize(soma.state.camera->pos - reference_polycube_gn->translation);
soma.state.rotAxisX = glm::normalize(glm::cross(eyes, soma.state.rotAxisY));
for (int i = 0; i < ArrayCount(STD_SOMA); i++) {
auto gn = get_scene_graph_node(app_state.polycubes.at(i).graph_node);
auto gn = getSceneGraphNodeForEntity(soma.scene, soma.state.polycubes.data[i].entityHandle);
gn->rotation *= glm::angleAxis(PI / 4, glm::vec3(1, 0, 0));
gn->rotation *= glm::angleAxis(PI / 4, glm::vec3(0, 1, 0));
}
glUseProgram(app_state.active_shader->prog_id);
setUniformMat4fv(app_state.active_shader, "projection", &main_frame.cam->proj);
setUniformMat4fv(app_state.active_shader, "view", &main_frame.cam->view);
real64 lastFrame = glfwGetTime();
real64 timeDelta = 1.0f/60.0f;
real64 last_frame = glfwGetTime();
real64 time_delta = 1.0f/60.0f;
while (!glfwWindowShouldClose(soma.window.handle)) {
real64 currTime = glfwGetTime();
timeDelta = currTime - lastFrame;
lastFrame = currTime;
//print("%.7f\n", timeDelta);
glm::vec3 lastLightPos = {};
Input prevInput = {};
while (!glfwWindowShouldClose(window)) {
time_delta = glfwGetTime() - last_frame;
glfwPollEvents();
Input input = get_current_input(window);
process_input(window, &input, &prevInput);
soma.currInput = getCurrentInput(soma.window.handle);
processInput(&soma);
glUseProgram(app_state.active_shader->prog_id);
SceneGraphNode *light_graph_node = get_scene_graph_node(get_entity(app_state.light)->scene_graph_node);
setUniform3fv(&phong_shader, "light_pos", &light_graph_node->translation);
setUniform3fv(&phong_shader, "camera", &main_frame.cam->pos);
if (app_state.last_polycube_visible != app_state.current_polycube) {
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;
if (soma.state.lastPolycubeVisible != soma.state.currentPolycube) {
hideEntity(soma.scene, soma.state.polycubes.data[soma.state.lastPolycubeVisible].entityHandle);
showEntity(soma.scene, soma.state.polycubes.data[soma.state.currentPolycube].entityHandle);
soma.state.lastPolycubeVisible = soma.state.currentPolycube;
}
if (soma.state.polycubeDirty) {
PolycubeInput *pinput = &soma.state.polycubeInput.data[soma.state.currentPolycube];
removeEntity(soma.scene, soma.state.polycubes.data[soma.state.currentPolycube].entityHandle);
Space culledRepr = pinput->repr;
cullEmptySpace(&culledRepr);
Polycube polycube = createPolycubeFromRepr(&soma, &culledRepr, pinput->color);
soma.state.polycubes.data[soma.state.currentPolycube] = polycube;
sceneNodeAddEntity(soma.scene, soma.scene->sceneRoot, polycube.entityHandle);
soma.state.polycubeDirty = false;
}
update_viewport_from_frame(&window_dims, &main_frame);
recalculate_scene_graph(get_scene_graph_node(renderer.scene_root));
updateViewportFromFrame(soma.window.width, soma.window.height, &mainFrame);
recalcScene(soma.scene);
renderBegin(&renderer);
drawUI(&renderer);
renderEnd(&renderer);
glfwSwapBuffers(window);
prevInput = input;
ui.cursorIsPointer = false;
ui.prevInput = &soma.prevInput;
ui.input = &soma.currInput;
ui.renderer = &renderer;
uiPass(&soma, &ui, &renderer);
if (ui.cursorIsPointer) {
glfwSetCursor(soma.window.handle, pointerCursor);
} else {
glfwSetCursor(soma.window.handle, arrowCursor);
}
renderEnd(&soma, &renderer);
glfwSwapBuffers(soma.window.handle);
soma.prevInput = soma.currInput;
}
glfwTerminate();
@@ -657,6 +670,6 @@ int main_gfx() {
int main() {
initialiseCore();
return main_gfx();
return mainGfx();
}

91
src/world/scene.cpp Normal file
View File

@@ -0,0 +1,91 @@
#include "scene.h"
Entity *getEntity(Scene *s, uint32 id) {
return &s->entities[id - 1];
}
SceneGraphNode *getSceneGraphNodeForEntity(Scene *s, uint32 entityHandle) {
return &s->graphNodes[s->entities[entityHandle - 1].graphNodeHandle - 1];
}
SceneGraphNode *getSceneGraphNode(Scene *s, uint32 sceneGraphNodeHandle) {
return &s->graphNodes[sceneGraphNodeHandle - 1];
}
uint32 createEntity(Scene *s) {
s->entities.emplace_back();
s->graphNodes.emplace_back();
s->entities.back().graphNodeHandle = (uint32)s->graphNodes.size();
s->graphNodes.back().entityHandle = (uint32)s->entities.size();
uint32 handle = (uint32)s->entities.size();
uint32 graphNodeHandle = (uint32)s->graphNodes.size();
initGraphNode(getSceneGraphNode(s, graphNodeHandle));
return handle;
}
uint32 createSceneGraphNode(Scene *s) {
s->graphNodes.emplace_back();
return (uint32)s->graphNodes.size();
}
void initGraphNode(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(1.0f, 0.0f, 0.0f, 0.0f);
n->local = glm::mat4(1.0f);
n->world = n->local;
}
void recalcGraphNode(SceneGraphNode *n) {
n->local = glm::scale(
glm::translate(
glm::mat4(1.0f),
n->translation
) * glm::toMat4(n->rotation),
n->scale
);
}
Scene createScene() {
Scene result = {};
result.sceneRoot = createSceneGraphNode(&result);
return result;
}
void recalcSceneGraphNode(Scene *s, uint32 parentHandle) {
SceneGraphNode *node = getSceneGraphNode(s, parentHandle);
if (node->entityHandle) {
getEntity(s, node->entityHandle)->flags |= EntityFlags_Render;
}
for (uint32 &nodeId : node->children) {
SceneGraphNode *graphNode = getSceneGraphNode(s, nodeId);
graphNode->parentHandle = parentHandle;
recalcGraphNode(graphNode);
graphNode->world = node->world * graphNode->local;
recalcSceneGraphNode(s, nodeId);
}
}
void recalcScene(Scene *s) {
recalcSceneGraphNode(s, s->sceneRoot);
}
void removeEntity(Scene *s, uint32 entityHandle) {
Entity *entity = getEntity(s, entityHandle);
entity->flags |= EntityFlags_Dead;
SceneGraphNode *graphNode = getSceneGraphNode(s, entity->graphNodeHandle);
if (graphNode->parentHandle) {
SceneGraphNode *parentNode = getSceneGraphNode(s, graphNode->parentHandle);
for (int i = 0; i < parentNode->children.size(); i++) {
if (parentNode->children.at(i) == entityHandle) {
parentNode->children.erase(parentNode->children.begin() + i);
graphNode->parentHandle = 0;
break;
}
}
}
}
void sceneNodeAddEntity(Scene *s, uint32 graphNodeHandle, uint32 entityHandle) {
getSceneGraphNode(s, graphNodeHandle)->children.push_back(getEntity(s, entityHandle)->graphNodeHandle);
}

47
src/world/scene.h Normal file
View File

@@ -0,0 +1,47 @@
#include <vector>
#include "glm/glm.hpp"
#include <glm/gtx/quaternion.hpp>
#include "../gfx/gfx.h"
enum EntityFlags {
EntityFlags_Visible=1<<0,
EntityFlags_Dead=1<<1,
EntityFlags_Render=1<<2,
};
struct Entity {
Mesh *mesh;
Texture *tex;
uint32 graphNodeHandle;
uint64 flags;
};
struct SceneGraphNode {
glm::mat4 local;
glm::mat4 world;
glm::vec3 translation;
glm::quat rotation;
glm::vec3 scale;
std::vector<uint32> children;
uint32 entityHandle;
uint32 parentHandle;
};
struct Scene {
uint32 sceneRoot;
std::vector<Entity> entities;
std::vector<SceneGraphNode> graphNodes;
};
uint32 createEntity(Scene *s);
Entity *getEntity(Scene *s);
SceneGraphNode *getSceneGraphNode(Scene *s, int id);
uint32 createSceneGraphNode(Scene *s);
Scene createScene(Scene *s);
void initGraphNode(SceneGraphNode *n);
void recalcGraphNode(SceneGraphNode *n);
void recalcSceneGraphNode(Scene *s, uint32 parentHandle);
void recalcScene(Scene *s);
void removeEntity(Scene *s, uint32 entityHandle);
void sceneNodeAddEntity(Scene *s, uint32 graphNodeHandle, uint32 entityHandle);
SceneGraphNode *getSceneGraphNodeForEntity(Scene *s, uint32 entityHandle);

1
src/world/world.cpp Normal file
View File

@@ -0,0 +1 @@
#include "scene.cpp"