big progress
This commit is contained in:
2
.clangd
2
.clangd
@@ -4,6 +4,8 @@ CompileFlags:
|
|||||||
- -xc
|
- -xc
|
||||||
# LINUX FLAGS
|
# LINUX FLAGS
|
||||||
- -DOS_LINUX
|
- -DOS_LINUX
|
||||||
|
- -DCOMPOSITOR_WAYLAND
|
||||||
|
- -DDJSTDLIB_DEBUG
|
||||||
# WINDOW FLAGS
|
# WINDOW FLAGS
|
||||||
# - -DOS_WINDOWS
|
# - -DOS_WINDOWS
|
||||||
# - "-IC:\\source\\libs\\include"
|
# - "-IC:\\source\\libs\\include"
|
||||||
|
|||||||
5
build
5
build
@@ -1,12 +1,13 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
LIB_INCLUDE="-lglfw -lGL -lm"
|
LIB_INCLUDE="-lglfw -lGL -lm"
|
||||||
|
COMMON_FLAGS="-DOS_LINUX=1 -DCOMPOSITOR_WAYLAND=1 -xc -std=c99"
|
||||||
|
|
||||||
echo [Building target]
|
echo [Building target]
|
||||||
if [ $DEBUG ]; then
|
if [ $DEBUG ]; then
|
||||||
time clang -O0 -g -g2 -DOS_LINUX=1 -DDJSTDLIB_DEBUG=1 -xc -std=c99 ./src/main.c -o ./target/somaesque $LIB_INCLUDE
|
time clang -O0 -g -g2 $COMMON_FLAGS -DDJSTDLIB_DEBUG=1 ./src/main.c -o ./target/somaesque $LIB_INCLUDE
|
||||||
else
|
else
|
||||||
time clang -O2 -DOS_LINUX=1 -xc -std=c99 ./src/main.c -o ./target/somaesque $LIB_INCLUDE
|
time clang -O2 $COMMON_FLAGS ./src/main.c -o ./target/somaesque $LIB_INCLUDE
|
||||||
fi
|
fi
|
||||||
echo [Target built]
|
echo [Target built]
|
||||||
./target/somaesque
|
./target/somaesque
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "SomaSolve.h"
|
#include "SomaSolve.h"
|
||||||
#include "math.h"
|
#include "math.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
void get_dims_input(int dims[3]) {
|
void get_dims_input(int dims[3]) {
|
||||||
|
|||||||
454
src/main.c
454
src/main.c
@@ -10,6 +10,7 @@
|
|||||||
#include "VoxelSpace.c"
|
#include "VoxelSpace.c"
|
||||||
#include "./tests.c"
|
#include "./tests.c"
|
||||||
#include "lib/djstdlib/core.c"
|
#include "lib/djstdlib/core.c"
|
||||||
|
#include "pthread.h"
|
||||||
|
|
||||||
// Graphics bindings and libs
|
// Graphics bindings and libs
|
||||||
#include "lib/raymath.h"
|
#include "lib/raymath.h"
|
||||||
@@ -114,6 +115,7 @@ struct Input {
|
|||||||
bool x;
|
bool x;
|
||||||
bool y;
|
bool y;
|
||||||
bool z;
|
bool z;
|
||||||
|
bool w;
|
||||||
} keyboard;
|
} keyboard;
|
||||||
struct {
|
struct {
|
||||||
union {
|
union {
|
||||||
@@ -142,8 +144,46 @@ struct PolycubeInput {
|
|||||||
};
|
};
|
||||||
DefineList(PolycubeInput, PolycubeInput);
|
DefineList(PolycubeInput, PolycubeInput);
|
||||||
|
|
||||||
|
typedef struct UI_Context UI_Context;
|
||||||
|
struct UI_Context {
|
||||||
|
uint32 nextId;
|
||||||
|
uint32 hotNode;
|
||||||
|
uint32 prevHotNode;
|
||||||
|
Renderer *renderer;
|
||||||
|
Input *prevInput;
|
||||||
|
Input *input;
|
||||||
|
bool cursorIsPointer;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct UI_Rect UI_Rect;
|
||||||
|
struct UI_Rect {
|
||||||
|
real32 x;
|
||||||
|
real32 y;
|
||||||
|
real32 width;
|
||||||
|
real32 height;
|
||||||
|
real32 borderRadius;
|
||||||
|
RLVector4 color;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum SolveTaskStatus SolveTaskStatus;
|
||||||
|
enum SolveTaskStatus {
|
||||||
|
SolveTaskStatus_Ready,
|
||||||
|
SolveTaskStatus_Solving,
|
||||||
|
SolveTaskStatus_Complete,
|
||||||
|
SolveTaskStatus_Error,
|
||||||
|
};
|
||||||
|
typedef struct SolveTaskCtx SolveTaskCtx;
|
||||||
|
struct SolveTaskCtx {
|
||||||
|
Arena *arena;
|
||||||
|
SomaSolutionList solutions;
|
||||||
|
VoxelSpaceReprList input;
|
||||||
|
int dims[3];
|
||||||
|
SolveTaskStatus taskStatus;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct SomaState SomaState;
|
typedef struct SomaState SomaState;
|
||||||
struct SomaState {
|
struct SomaState {
|
||||||
|
bool isInitialState;
|
||||||
bool wireframe;
|
bool wireframe;
|
||||||
bool polycubeDirty;
|
bool polycubeDirty;
|
||||||
uint32 displayedPolycube;
|
uint32 displayedPolycube;
|
||||||
@@ -164,6 +204,10 @@ struct Soma {
|
|||||||
GLFWwindow *handle;
|
GLFWwindow *handle;
|
||||||
uint32 width;
|
uint32 width;
|
||||||
uint32 height;
|
uint32 height;
|
||||||
|
struct {
|
||||||
|
GLFWcursor *pointer;
|
||||||
|
GLFWcursor *arrow;
|
||||||
|
} cursors;
|
||||||
} window;
|
} window;
|
||||||
|
|
||||||
SomaState prevState;
|
SomaState prevState;
|
||||||
@@ -172,9 +216,42 @@ struct Soma {
|
|||||||
PolycubeInputList polycubeInput;
|
PolycubeInputList polycubeInput;
|
||||||
HandleList polycubes;
|
HandleList polycubes;
|
||||||
SomaSolutionList solutions;
|
SomaSolutionList solutions;
|
||||||
|
Arena *solveArena;
|
||||||
|
SolveTaskCtx *solveTaskCtx;
|
||||||
|
uint32 puzzleDims[3];
|
||||||
HandleList solutionEntities;
|
HandleList solutionEntities;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void *executeSolve(void *ctx) {
|
||||||
|
SolveTaskCtx *solveTaskCtx = (SolveTaskCtx *)ctx;
|
||||||
|
solveTaskCtx->taskStatus = SolveTaskStatus_Solving;
|
||||||
|
solveTaskCtx->solutions = solveSoma(solveTaskCtx->arena, solveTaskCtx->input, solveTaskCtx->dims);
|
||||||
|
solveTaskCtx->taskStatus = SolveTaskStatus_Complete;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SolveTaskCtx *scheduleSolve(Soma *soma) {
|
||||||
|
SolveTaskCtx *threadCtx = PushStructZero(soma->solveArena, SolveTaskCtx);
|
||||||
|
VoxelSpaceReprList mappedInputs = PushList(soma->solveArena, VoxelSpaceReprList, soma->polycubeInput.length);
|
||||||
|
for (EachEl(soma->polycubeInput, PolycubeInput, polycubeInput)) {
|
||||||
|
AppendList(&mappedInputs, polycubeInput->repr.space);
|
||||||
|
}
|
||||||
|
*threadCtx = (SolveTaskCtx){
|
||||||
|
.arena = soma->solveArena,
|
||||||
|
.solutions = EmptyList(),
|
||||||
|
.input = mappedInputs,
|
||||||
|
.taskStatus = SolveTaskStatus_Ready,
|
||||||
|
.dims = { soma->puzzleDims[0], soma->puzzleDims[1], soma->puzzleDims[2] },
|
||||||
|
};
|
||||||
|
soma->solveTaskCtx = threadCtx;
|
||||||
|
pthread_t threadId;
|
||||||
|
pthread_attr_t attr;
|
||||||
|
pthread_attr_init(&attr);
|
||||||
|
pthread_create(&threadId, &attr, &executeSolve, threadCtx);
|
||||||
|
pthread_attr_destroy(&attr);
|
||||||
|
return threadCtx;
|
||||||
|
}
|
||||||
|
|
||||||
void show(Scene *s, uint32 graphNodeHandle) {
|
void show(Scene *s, uint32 graphNodeHandle) {
|
||||||
SceneGraphNode *node = getSceneGraphNode(s, graphNodeHandle);
|
SceneGraphNode *node = getSceneGraphNode(s, graphNodeHandle);
|
||||||
if (node->entityHandle) {
|
if (node->entityHandle) {
|
||||||
@@ -223,10 +300,16 @@ void framebufferSizeCallback(GLFWwindow *window, int width, int height) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GLFWwindow *initWindowAndGL(uint32 windowWidth, uint32 windowHeight) {
|
GLFWwindow *initWindowAndGL(uint32 windowWidth, uint32 windowHeight) {
|
||||||
|
#ifdef OS_LINUX
|
||||||
|
glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_X11);
|
||||||
|
#endif
|
||||||
|
|
||||||
glfwInit();
|
glfwInit();
|
||||||
|
glfwWindowHintString(GLFW_WAYLAND_APP_ID, "Somaesque");
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
|
||||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||||
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||||
GLFWwindow *window = glfwCreateWindow(
|
GLFWwindow *window = glfwCreateWindow(
|
||||||
windowWidth,
|
windowWidth,
|
||||||
windowHeight,
|
windowHeight,
|
||||||
@@ -242,6 +325,7 @@ GLFWwindow *initWindowAndGL(uint32 windowWidth, uint32 windowHeight) {
|
|||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
glfwMakeContextCurrent(window);
|
glfwMakeContextCurrent(window);
|
||||||
|
|
||||||
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
|
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
|
||||||
@@ -253,7 +337,13 @@ GLFWwindow *initWindowAndGL(uint32 windowWidth, uint32 windowHeight) {
|
|||||||
glfwSwapInterval(0);
|
glfwSwapInterval(0);
|
||||||
glfwSetFramebufferSizeCallback(window, framebufferSizeCallback);
|
glfwSetFramebufferSizeCallback(window, framebufferSizeCallback);
|
||||||
glfwSetInputMode(window, GLFW_CURSOR | GLFW_RAW_MOUSE_MOTION, GLFW_CURSOR_NORMAL);
|
glfwSetInputMode(window, GLFW_CURSOR | GLFW_RAW_MOUSE_MOTION, GLFW_CURSOR_NORMAL);
|
||||||
|
glfwSetWindowSize(window, windowWidth, windowHeight);
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
|
glfwSetWindowAttrib(window, GLFW_DECORATED, GLFW_FALSE);
|
||||||
|
glfwSetWindowAttrib(window, GLFW_DECORATED, GLFW_TRUE);
|
||||||
|
glfwSetWindowAttrib(window, GLFW_DECORATED, GLFW_FALSE);
|
||||||
|
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,24 +351,6 @@ void updateViewportFromFrame(uint32 windowWidth, uint32 windowHeight, Frame* fra
|
|||||||
glViewport(frame->x, windowHeight - frame->y - frame->height, frame->width, frame->height);
|
glViewport(frame->x, windowHeight - frame->y - frame->height, frame->width, frame->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct UI_Context UI_Context;
|
|
||||||
struct UI_Context {
|
|
||||||
Renderer *renderer;
|
|
||||||
Input *prevInput;
|
|
||||||
Input *input;
|
|
||||||
bool cursorIsPointer;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct UI_Rect UI_Rect;
|
|
||||||
struct UI_Rect {
|
|
||||||
real32 x;
|
|
||||||
real32 y;
|
|
||||||
real32 width;
|
|
||||||
real32 height;
|
|
||||||
real32 borderRadius;
|
|
||||||
RLVector4 color;
|
|
||||||
};
|
|
||||||
|
|
||||||
Mesh cubeMesh = {0};
|
Mesh cubeMesh = {0};
|
||||||
Texture wallTex = {0};
|
Texture wallTex = {0};
|
||||||
|
|
||||||
@@ -308,6 +380,7 @@ Input getCurrentInput(GLFWwindow *window) {
|
|||||||
input.keyboard.enter = glfwKey(window, GLFW_KEY_ENTER);
|
input.keyboard.enter = glfwKey(window, GLFW_KEY_ENTER);
|
||||||
input.keyboard.space = glfwKey(window, GLFW_KEY_SPACE);
|
input.keyboard.space = glfwKey(window, GLFW_KEY_SPACE);
|
||||||
input.keyboard.lshift = glfwKey(window, GLFW_KEY_LEFT_SHIFT);
|
input.keyboard.lshift = glfwKey(window, GLFW_KEY_LEFT_SHIFT);
|
||||||
|
input.keyboard.w = glfwKey(window, GLFW_KEY_W);
|
||||||
input.keyboard.x = glfwKey(window, GLFW_KEY_X);
|
input.keyboard.x = glfwKey(window, GLFW_KEY_X);
|
||||||
input.keyboard.y = glfwKey(window, GLFW_KEY_Y);
|
input.keyboard.y = glfwKey(window, GLFW_KEY_Y);
|
||||||
input.keyboard.z = glfwKey(window, GLFW_KEY_Z);
|
input.keyboard.z = glfwKey(window, GLFW_KEY_Z);
|
||||||
@@ -324,7 +397,7 @@ Input getCurrentInput(GLFWwindow *window) {
|
|||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
void processInput(Soma *soma) {
|
void processInput(Soma *soma, UI_Context *ui) {
|
||||||
Input *input = &soma->state.input;
|
Input *input = &soma->state.input;
|
||||||
Input *prevInput = &soma->prevState.input;
|
Input *prevInput = &soma->prevState.input;
|
||||||
|
|
||||||
@@ -332,18 +405,18 @@ void processInput(Soma *soma) {
|
|||||||
glfwSetWindowShouldClose(soma->window.handle, true);
|
glfwSetWindowShouldClose(soma->window.handle, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input->keyboard.space && !prevInput->keyboard.space) {
|
if (input->keyboard.w && !prevInput->keyboard.w) {
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, !soma->state.wireframe ? GL_LINE : GL_FILL);
|
glPolygonMode(GL_FRONT_AND_BACK, !soma->state.wireframe ? GL_LINE : GL_FILL);
|
||||||
soma->state.wireframe = !soma->state.wireframe;
|
soma->state.wireframe = !soma->state.wireframe;
|
||||||
}
|
}
|
||||||
|
|
||||||
SceneGraphNode *node = getSceneGraphNode(soma->scene, getEntity(soma->scene, soma->state.light)->graphNodeHandle);
|
SceneGraphNode *node = getSceneGraphNode(soma->scene, soma->state.light);
|
||||||
int shiftMultiplier = input->keyboard.lshift ? -1 : 1;
|
int shiftMultiplier = input->keyboard.lshift ? -1 : 1;
|
||||||
node->translation.x += 1.0 * input->keyboard.x * shiftMultiplier;
|
node->translation.x += 1.0 * input->keyboard.x * shiftMultiplier;
|
||||||
node->translation.y += 1.0 * input->keyboard.y * shiftMultiplier;
|
node->translation.y += 1.0 * input->keyboard.y * shiftMultiplier;
|
||||||
node->translation.z += 1.0 * input->keyboard.z * shiftMultiplier;
|
node->translation.z += 1.0 * input->keyboard.z * shiftMultiplier;
|
||||||
|
|
||||||
if (input->keyboard.enter && !prevInput->keyboard.enter) {
|
if (input->keyboard.space && !prevInput->keyboard.space) {
|
||||||
if (soma->state.displayingSolutions) {
|
if (soma->state.displayingSolutions) {
|
||||||
if (soma->state.displayedSolution == soma->solutions.length - 1) {
|
if (soma->state.displayedSolution == soma->solutions.length - 1) {
|
||||||
soma->state.displayedSolution = 0;
|
soma->state.displayedSolution = 0;
|
||||||
@@ -359,8 +432,15 @@ void processInput(Soma *soma) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dragScene = false;
|
if (input->keyboard.enter && !prevInput->keyboard.enter) {
|
||||||
if (input->mouse.btnLeft) {
|
if (soma->state.displayingSolutions) {
|
||||||
|
soma->state.displayingSolutions = false;
|
||||||
|
} else {
|
||||||
|
scheduleSolve(soma);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input->mouse.btnLeft && ui->hotNode == 0) {
|
||||||
uint32 currentObject = soma->state.displayingSolutions
|
uint32 currentObject = soma->state.displayingSolutions
|
||||||
? soma->solutionEntities.data[soma->state.displayedSolution]
|
? soma->solutionEntities.data[soma->state.displayedSolution]
|
||||||
: soma->polycubes.data[soma->state.displayedPolycube];
|
: soma->polycubes.data[soma->state.displayedPolycube];
|
||||||
@@ -378,13 +458,13 @@ void processInput(Soma *soma) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 createPolycubeFromRepr(Arena *arena, Scene *s, VoxelSpace *repr, RLVector4 color) {
|
uint32 createPolycubeFromRepr(Scene *s, VoxelSpace *repr, RLVector4 color) {
|
||||||
uint32 mainGraphNode = createSceneGraphNode(arena, s);
|
uint32 mainGraphNode = createSceneGraphNode(s);
|
||||||
for (int x = 0; x < repr->dim_x; x++) {
|
for (int x = 0; x < repr->dim_x; x++) {
|
||||||
for (int y = 0; y < repr->dim_y; y++) {
|
for (int y = 0; y < repr->dim_y; y++) {
|
||||||
for (int z = 0; z < repr->dim_z; z++) {
|
for (int z = 0; z < repr->dim_z; z++) {
|
||||||
if (filledAt(repr, x, y, z)) {
|
if (filledAt(repr, x, y, z)) {
|
||||||
uint32 segmentEntityHandle = createEntity(arena, s);
|
uint32 segmentEntityHandle = createEntity(s);
|
||||||
Entity *polycubeSegment = getEntity(s, segmentEntityHandle);
|
Entity *polycubeSegment = getEntity(s, segmentEntityHandle);
|
||||||
polycubeSegment->color = color;
|
polycubeSegment->color = color;
|
||||||
polycubeSegment->mesh = &cubeMesh;
|
polycubeSegment->mesh = &cubeMesh;
|
||||||
@@ -429,72 +509,72 @@ RenderObjects_Rectangle createRectangleObjects(Arena *arena, size_t count) {
|
|||||||
glBindVertexArray(result.vao);
|
glBindVertexArray(result.vao);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, result.p0BufferId);
|
glBindBuffer(GL_ARRAY_BUFFER, result.p0BufferId);
|
||||||
glBufferData(GL_ARRAY_BUFFER, result.p0.length * sizeof(RLVector2), 0, GL_DYNAMIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, result.p0.length * sizeof(RLVec2List_underlying), 0, GL_DYNAMIC_DRAW);
|
||||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(RLVector2), (void*)0);
|
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(RLVec2List_underlying), NULL);
|
||||||
glVertexAttribDivisor(0, 1);
|
glVertexAttribDivisor(0, 1);
|
||||||
glEnableVertexAttribArray(0);
|
glEnableVertexAttribArray(0);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, result.p1BufferId);
|
glBindBuffer(GL_ARRAY_BUFFER, result.p1BufferId);
|
||||||
glBufferData(GL_ARRAY_BUFFER, result.p1.length * sizeof(RLVector2), 0, GL_DYNAMIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, result.p1.length * sizeof(RLVec2List_underlying), 0, GL_DYNAMIC_DRAW);
|
||||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(RLVector2), (void*)0);
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(RLVec2List_underlying), NULL);
|
||||||
glVertexAttribDivisor(1, 1);
|
glVertexAttribDivisor(1, 1);
|
||||||
glEnableVertexAttribArray(1);
|
glEnableVertexAttribArray(1);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, result.colorBufferId);
|
glBindBuffer(GL_ARRAY_BUFFER, result.colorBufferId);
|
||||||
glBufferData(GL_ARRAY_BUFFER, result.color.length * sizeof(RLVector4), 0, GL_DYNAMIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, result.color.length * sizeof(RLVec4List_underlying), 0, GL_DYNAMIC_DRAW);
|
||||||
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(RLVector4), (void*)0);
|
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(RLVec4List_underlying), NULL);
|
||||||
glVertexAttribDivisor(2, 1);
|
glVertexAttribDivisor(2, 1);
|
||||||
glEnableVertexAttribArray(2);
|
glEnableVertexAttribArray(2);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, result.borderRadiusBufferId);
|
glBindBuffer(GL_ARRAY_BUFFER, result.borderRadiusBufferId);
|
||||||
glBufferData(GL_ARRAY_BUFFER, result.borderRadius.length * sizeof(FloatList_underlying), 0, GL_DYNAMIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, result.borderRadius.length * sizeof(FloatList_underlying), 0, GL_DYNAMIC_DRAW);
|
||||||
glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, sizeof(FloatList_underlying), (void*)0);
|
glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, sizeof(FloatList_underlying), NULL);
|
||||||
glVertexAttribDivisor(3, 1);
|
glVertexAttribDivisor(3, 1);
|
||||||
glEnableVertexAttribArray(3);
|
glEnableVertexAttribArray(3);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, result.borderThicknessBufferId);
|
glBindBuffer(GL_ARRAY_BUFFER, result.borderThicknessBufferId);
|
||||||
glBufferData(GL_ARRAY_BUFFER, result.borderThickness.length * sizeof(FloatList_underlying), 0, GL_DYNAMIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, result.borderThickness.length * sizeof(FloatList_underlying), 0, GL_DYNAMIC_DRAW);
|
||||||
glVertexAttribPointer(4, 1, GL_FLOAT, GL_FALSE, sizeof(FloatList_underlying), (void*)0);
|
glVertexAttribPointer(4, 1, GL_FLOAT, GL_FALSE, sizeof(FloatList_underlying), NULL);
|
||||||
glVertexAttribDivisor(4, 1);
|
glVertexAttribDivisor(4, 1);
|
||||||
glEnableVertexAttribArray(4);
|
glEnableVertexAttribArray(4);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, result.edgeSoftnessBufferId);
|
glBindBuffer(GL_ARRAY_BUFFER, result.edgeSoftnessBufferId);
|
||||||
glBufferData(GL_ARRAY_BUFFER, result.edgeSoftness.length * sizeof(FloatList_underlying), 0, GL_DYNAMIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, result.edgeSoftness.length * sizeof(FloatList_underlying), 0, GL_DYNAMIC_DRAW);
|
||||||
glVertexAttribPointer(5, 1, GL_FLOAT, GL_FALSE, sizeof(FloatList_underlying), (void*)0);
|
glVertexAttribPointer(5, 1, GL_FLOAT, GL_FALSE, sizeof(FloatList_underlying), NULL);
|
||||||
glVertexAttribDivisor(5, 1);
|
glVertexAttribDivisor(5, 1);
|
||||||
glEnableVertexAttribArray(5);
|
glEnableVertexAttribArray(5);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reinitRectangleObjectBuffers(Renderer *r) {
|
void updateRectangleObjectBuffers(Renderer *r) {
|
||||||
glBindVertexArray(r->rects.vao);
|
glBindVertexArray(r->rects.vao);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, r->rects.p0BufferId);
|
glBindBuffer(GL_ARRAY_BUFFER, r->rects.p0BufferId);
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, r->rects.p0.length * sizeof(RLVec2List), r->rects.p0.data);
|
glBufferSubData(GL_ARRAY_BUFFER, 0, r->rects.p0.length * sizeof(RLVec2List_underlying), r->rects.p0.data);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, r->rects.p1BufferId);
|
glBindBuffer(GL_ARRAY_BUFFER, r->rects.p1BufferId);
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, r->rects.p1.length * sizeof(RLVec2List), r->rects.p1.data);
|
glBufferSubData(GL_ARRAY_BUFFER, 0, r->rects.p1.length * sizeof(RLVec2List_underlying), r->rects.p1.data);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, r->rects.colorBufferId);
|
glBindBuffer(GL_ARRAY_BUFFER, r->rects.colorBufferId);
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, r->rects.color.length * sizeof(RLVec4List), r->rects.color.data);
|
glBufferSubData(GL_ARRAY_BUFFER, 0, r->rects.color.length * sizeof(RLVec4List_underlying), r->rects.color.data);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, r->rects.borderRadiusBufferId);
|
glBindBuffer(GL_ARRAY_BUFFER, r->rects.borderRadiusBufferId);
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, r->rects.borderRadius.length * sizeof(FloatList), r->rects.borderRadius.data);
|
glBufferSubData(GL_ARRAY_BUFFER, 0, r->rects.borderRadius.length * sizeof(FloatList_underlying), r->rects.borderRadius.data);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, r->rects.borderThicknessBufferId);
|
glBindBuffer(GL_ARRAY_BUFFER, r->rects.borderThicknessBufferId);
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, r->rects.borderThickness.length * sizeof(FloatList), r->rects.borderThickness.data);
|
glBufferSubData(GL_ARRAY_BUFFER, 0, r->rects.borderThickness.length * sizeof(FloatList_underlying), r->rects.borderThickness.data);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, r->rects.edgeSoftnessBufferId);
|
glBindBuffer(GL_ARRAY_BUFFER, r->rects.edgeSoftnessBufferId);
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, r->rects.edgeSoftness.length * sizeof(FloatList), r->rects.edgeSoftness.data);
|
glBufferSubData(GL_ARRAY_BUFFER, 0, r->rects.edgeSoftness.length * sizeof(FloatList_underlying), r->rects.edgeSoftness.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer createRenderer(Arena *arena, Scene *scene) {
|
Renderer createRenderer(Arena *arena, Scene *scene) {
|
||||||
Renderer result = {0};
|
scene->sceneRoot = createSceneGraphNode(scene);
|
||||||
result.scene = scene;
|
return (Renderer){
|
||||||
result.scene->sceneRoot = createSceneGraphNode(arena, scene);
|
.scene = scene,
|
||||||
result.rects = createRectangleObjects(arena, 100);
|
.rects = createRectangleObjects(arena, 100),
|
||||||
return result;
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderBegin(Renderer *r) {
|
void renderBegin(Renderer *r) {
|
||||||
@@ -515,19 +595,19 @@ void renderEnd(Soma *soma, Renderer *renderer) {
|
|||||||
setUniformMat4fv(&phongShader, "projection", &soma->state.camera->proj);
|
setUniformMat4fv(&phongShader, "projection", &soma->state.camera->proj);
|
||||||
setUniformMat4fv(&phongShader, "view", &soma->state.camera->view);
|
setUniformMat4fv(&phongShader, "view", &soma->state.camera->view);
|
||||||
|
|
||||||
SceneGraphNode *lightGraphNode = getSceneGraphNode(soma->scene, getEntity(soma->scene, soma->state.light)->graphNodeHandle);
|
SceneGraphNode *lightGraphNode = getSceneGraphNode(soma->scene, soma->state.light);
|
||||||
setUniform3fv(&phongShader, "light_pos", &lightGraphNode->translation);
|
setUniform3fv(&phongShader, "light_pos", &lightGraphNode->translation);
|
||||||
setUniform3fv(&phongShader, "camera", &soma->state.camera->pos);
|
setUniform3fv(&phongShader, "camera", &soma->state.camera->pos);
|
||||||
|
|
||||||
uint32 currentPolycube = soma->polycubes.data[soma->state.displayedPolycube];
|
uint32 currentPolycube = soma->polycubes.data[soma->state.displayedPolycube];
|
||||||
glBindVertexArray(cubeMesh.vao);
|
glBindVertexArray(cubeMesh.vao);
|
||||||
|
|
||||||
|
|
||||||
int model_uniform = getUniformLocation(&phongShader, "model");
|
int model_uniform = getUniformLocation(&phongShader, "model");
|
||||||
|
int solid_color_uniform = getUniformLocation(&phongShader, "solid_color");
|
||||||
for (EachIn(renderer->scene->entities, i)) {
|
for (EachIn(renderer->scene->entities, i)) {
|
||||||
Entity *entity = &renderer->scene->entities.data[i];
|
Entity *entity = &renderer->scene->entities.data[i];
|
||||||
if (entity->flags & EntityFlags_Render && entity->flags & EntityFlags_Visible) {
|
if (entity->flags & EntityFlags_Render && entity->flags & EntityFlags_Visible) {
|
||||||
setUniform4fv(&phongShader, "solid_color", &entity->color);
|
setUniform4fvByLoc(solid_color_uniform, &entity->color);
|
||||||
setUniformMat4fvByLoc(model_uniform, &getSceneGraphNode(renderer->scene, entity->graphNodeHandle)->world);
|
setUniformMat4fvByLoc(model_uniform, &getSceneGraphNode(renderer->scene, entity->graphNodeHandle)->world);
|
||||||
glBindTexture(GL_TEXTURE_2D, entity->tex->tex_id);
|
glBindTexture(GL_TEXTURE_2D, entity->tex->tex_id);
|
||||||
glDrawArrays(GL_TRIANGLES, 0, (GLsizei)entity->mesh->num_indices);
|
glDrawArrays(GL_TRIANGLES, 0, (GLsizei)entity->mesh->num_indices);
|
||||||
@@ -538,7 +618,7 @@ void renderEnd(Soma *soma, Renderer *renderer) {
|
|||||||
// 2D overlay
|
// 2D overlay
|
||||||
glUseProgram(solidColorShader.progId);
|
glUseProgram(solidColorShader.progId);
|
||||||
|
|
||||||
reinitRectangleObjectBuffers(renderer);
|
updateRectangleObjectBuffers(renderer);
|
||||||
|
|
||||||
Matrix ortho = MatrixOrtho(0.0, 800.0, 600.0, 0.0, -1.0, 1.0);
|
Matrix ortho = MatrixOrtho(0.0, 800.0, 600.0, 0.0, -1.0, 1.0);
|
||||||
setUniformMat4fv(&solidColorShader, "projection", &ortho);
|
setUniformMat4fv(&solidColorShader, "projection", &ortho);
|
||||||
@@ -548,10 +628,8 @@ void renderEnd(Soma *soma, Renderer *renderer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void rendererPlaceRectangle(Renderer *r, real32 x, real32 y, real32 width, real32 height, RLVector4 color, real32 borderRadius, real32 borderThickness) {
|
void rendererPlaceRectangle(Renderer *r, real32 x, real32 y, real32 width, real32 height, RLVector4 color, real32 borderRadius, real32 borderThickness) {
|
||||||
RLVector2 p0 = {x, y};
|
AppendList(&r->rects.p0, ((RLVector2){ x, y }));
|
||||||
AppendList(&r->rects.p0, p0);
|
AppendList(&r->rects.p1, ((RLVector2){ x + width, y + height }));
|
||||||
RLVector2 p1 = {x + width, y + height};
|
|
||||||
AppendList(&r->rects.p1, p1);
|
|
||||||
AppendList(&r->rects.color, color);
|
AppendList(&r->rects.color, color);
|
||||||
AppendList(&r->rects.borderRadius, borderRadius);
|
AppendList(&r->rects.borderRadius, borderRadius);
|
||||||
AppendList(&r->rects.borderThickness, borderThickness);
|
AppendList(&r->rects.borderThickness, borderThickness);
|
||||||
@@ -563,12 +641,15 @@ bool pointInRect(RLVector2 point, UI_Rect rect) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ui_checkboxRect(UI_Context *ui, bool *value, UI_Rect rect) {
|
bool ui_checkboxRect(UI_Context *ui, bool *value, UI_Rect rect) {
|
||||||
|
uint32 id = ui->nextId++;
|
||||||
bool clicked = false;
|
bool clicked = false;
|
||||||
if (pointInRect(ui->input->mouse.point, rect)) {
|
if (pointInRect(ui->input->mouse.point, rect)) {
|
||||||
ui->cursorIsPointer = true;
|
ui->cursorIsPointer = true;
|
||||||
if (ui->prevInput->mouse.btnLeft && !ui->input->mouse.btnLeft) {
|
if (ui->prevHotNode == id && !ui->input->mouse.btnLeft) {
|
||||||
*value = !*value;
|
*value = !*value;
|
||||||
clicked = true;
|
clicked = true;
|
||||||
|
} else if (ui->input->mouse.btnLeft && (!ui->prevInput->mouse.btnLeft || ui->prevHotNode == id)) {
|
||||||
|
ui->hotNode = id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (*value) {
|
if (*value) {
|
||||||
@@ -576,7 +657,7 @@ bool ui_checkboxRect(UI_Context *ui, bool *value, UI_Rect rect) {
|
|||||||
rect.x, rect.y,
|
rect.x, rect.y,
|
||||||
rect.width, rect.height,
|
rect.width, rect.height,
|
||||||
rect.color,
|
rect.color,
|
||||||
5, 2);
|
5, 0);
|
||||||
} else {
|
} else {
|
||||||
rendererPlaceRectangle(ui->renderer,
|
rendererPlaceRectangle(ui->renderer,
|
||||||
rect.x, rect.y,
|
rect.x, rect.y,
|
||||||
@@ -588,13 +669,52 @@ bool ui_checkboxRect(UI_Context *ui, bool *value, UI_Rect rect) {
|
|||||||
return clicked;
|
return clicked;
|
||||||
}
|
}
|
||||||
|
|
||||||
void uiPass(Soma *soma, UI_Context *ui, Renderer *renderer) {
|
void uiPass(Soma *soma, UI_Context *ui) {
|
||||||
PolycubeInput *currentPolycube = &soma->polycubeInput.data[soma->state.displayedPolycube];
|
ui->cursorIsPointer = false;
|
||||||
|
ui->nextId = 1;
|
||||||
|
ui->prevInput = &soma->prevState.input;
|
||||||
|
ui->input = &soma->state.input;
|
||||||
|
ui->prevHotNode = ui->hotNode;
|
||||||
|
ui->hotNode = 0;
|
||||||
|
|
||||||
real32 boxSize = 30;
|
real32 boxSize = 30;
|
||||||
real32 padding = 20;
|
real32 padding = 20;
|
||||||
real32 paddingBetween = 5;
|
real32 paddingBetween = 5;
|
||||||
real32 currY = padding;
|
real32 currY = padding;
|
||||||
|
|
||||||
|
if (soma->state.displayingSolutions) {
|
||||||
|
if (soma->solutions.length > 0) {
|
||||||
|
SomaSolution *currentSolution = &soma->solutions.data[soma->state.displayedSolution];
|
||||||
|
for (EachIn(*currentSolution, i)) {
|
||||||
|
uint64 spaceRepr = currentSolution->data[i];
|
||||||
|
for (int x = 0; x < soma->puzzleDims[0]; x++) {
|
||||||
|
for (int y = 0; y < soma->puzzleDims[1]; y++) {
|
||||||
|
real32 currX = padding;
|
||||||
|
for (int z = 0; z < soma->puzzleDims[2]; z++) {
|
||||||
|
bool cellActive = filledAt(&(VoxelSpace){
|
||||||
|
.space = spaceRepr,
|
||||||
|
.dim_x = soma->puzzleDims[0],
|
||||||
|
.dim_y = soma->puzzleDims[1],
|
||||||
|
.dim_z = soma->puzzleDims[2],
|
||||||
|
}, x, y, z);
|
||||||
|
if (cellActive) {
|
||||||
|
rendererPlaceRectangle(ui->renderer,
|
||||||
|
currX, currY,
|
||||||
|
boxSize, boxSize,
|
||||||
|
soma->polycubeInput.data[i].color,
|
||||||
|
5, 0);
|
||||||
|
}
|
||||||
|
currX += paddingBetween + boxSize;
|
||||||
|
}
|
||||||
|
currY += paddingBetween + boxSize;
|
||||||
|
}
|
||||||
|
currY += padding;
|
||||||
|
}
|
||||||
|
currY = padding;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PolycubeInput *currentPolycube = &soma->polycubeInput.data[soma->state.displayedPolycube];
|
||||||
for (int x = 0; x < currentPolycube->repr.dim_x; x++) {
|
for (int x = 0; x < currentPolycube->repr.dim_x; x++) {
|
||||||
for (int y = 0; y < currentPolycube->repr.dim_y; y++) {
|
for (int y = 0; y < currentPolycube->repr.dim_y; y++) {
|
||||||
real32 currX = padding;
|
real32 currX = padding;
|
||||||
@@ -605,7 +725,7 @@ void uiPass(Soma *soma, UI_Context *ui, Renderer *renderer) {
|
|||||||
.y = currY,
|
.y = currY,
|
||||||
.width = boxSize,
|
.width = boxSize,
|
||||||
.height = boxSize,
|
.height = boxSize,
|
||||||
.borderRadius = 0,
|
.borderRadius = 2,
|
||||||
.color = currentPolycube->color,
|
.color = currentPolycube->color,
|
||||||
};
|
};
|
||||||
if (ui_checkboxRect(ui, &cellActive, rect)) {
|
if (ui_checkboxRect(ui, &cellActive, rect)) {
|
||||||
@@ -619,46 +739,127 @@ void uiPass(Soma *soma, UI_Context *ui, Renderer *renderer) {
|
|||||||
currY += padding;
|
currY += padding;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int mainCmd() {
|
void updatePolycubeDisplay(Arena *arena, Soma *soma) {
|
||||||
interactiveCmdLineSolveSoma();
|
if (soma->prevState.displayingSolutions) {
|
||||||
return 0;
|
if (soma->prevState.displayedPolycube < soma->polycubes.length) {
|
||||||
|
hide(soma->scene, soma->polycubes.data[soma->prevState.displayedPolycube]);
|
||||||
|
show(soma->scene, soma->solutionEntities.data[soma->state.displayedSolution]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (soma->prevState.displayedSolution < soma->solutionEntities.length) {
|
||||||
|
hide(soma->scene, soma->solutionEntities.data[soma->prevState.displayedSolution]);
|
||||||
|
show(soma->scene, soma->polycubes.data[soma->state.displayedPolycube]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (soma->state.displayingSolutions) {
|
||||||
|
if (soma->solutions.length > 0) {
|
||||||
|
if (soma->state.displayedSolution != soma->prevState.displayedSolution) {
|
||||||
|
show(soma->scene, soma->solutionEntities.data[soma->state.displayedSolution]);
|
||||||
|
hide(soma->scene, soma->solutionEntities.data[soma->prevState.displayedSolution]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (soma->state.isInitialState) {
|
||||||
|
show(soma->scene, soma->polycubes.data[soma->state.displayedPolycube]);
|
||||||
|
} else if (soma->state.displayedPolycube != soma->prevState.displayedPolycube) {
|
||||||
|
show(soma->scene, soma->polycubes.data[soma->state.displayedPolycube]);
|
||||||
|
hide(soma->scene, soma->polycubes.data[soma->prevState.displayedPolycube]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (soma->state.polycubeDirty) {
|
||||||
|
if (soma->state.displayedPolycube >= 0 && soma->state.displayedPolycube < soma->polycubes.length) {
|
||||||
|
uint32 currentPolycubeHandle = soma->polycubes.data[soma->state.displayedPolycube];
|
||||||
|
PolycubeInput *pinput = &soma->polycubeInput.data[soma->state.displayedPolycube];
|
||||||
|
VoxelSpace culledRepr = pinput->repr;
|
||||||
|
cullEmptySpace(&culledRepr);
|
||||||
|
uint32 newPolycubeHandle = createPolycubeFromRepr(soma->scene, &culledRepr, pinput->color);
|
||||||
|
SceneGraphNode *newPolycubeGraphNode = getSceneGraphNode(soma->scene, newPolycubeHandle);
|
||||||
|
newPolycubeGraphNode->rotation = getSceneGraphNode(soma->scene, currentPolycubeHandle)->rotation;
|
||||||
|
removeEntity(soma->scene, currentPolycubeHandle);
|
||||||
|
soma->polycubes.data[soma->state.displayedPolycube] = newPolycubeHandle;
|
||||||
|
sceneNodeAddNode(soma->scene, soma->scene->sceneRoot, newPolycubeHandle);
|
||||||
|
soma->state.polycubeDirty = false;
|
||||||
|
hide(soma->scene, currentPolycubeHandle);
|
||||||
|
show(soma->scene, newPolycubeHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void createSolutionEntities(Arena *arena, Soma *soma) {
|
||||||
|
if (soma->solutions.length > 0) {
|
||||||
|
soma->solutionEntities = PushList(arena, HandleList, soma->solutions.length);
|
||||||
|
for (EachEl(soma->solutions, SomaSolution, solution)) {
|
||||||
|
uint32 solutionGraphNodeHandle = createSceneGraphNode(soma->scene);
|
||||||
|
AppendList(&soma->solutionEntities, solutionGraphNodeHandle);
|
||||||
|
sceneNodeAddNode(soma->renderer->scene, soma->renderer->scene->sceneRoot, solutionGraphNodeHandle);
|
||||||
|
for (EachIn(*solution, soln_i)) {
|
||||||
|
uint32 polycubeGraphNodeHandle = createPolycubeFromRepr(
|
||||||
|
soma->scene,
|
||||||
|
&(VoxelSpace){ solution->data[soln_i], 3, 3, 3 },
|
||||||
|
colorFromIndex(soln_i)
|
||||||
|
);
|
||||||
|
sceneNodeAddNode(soma->renderer->scene, solutionGraphNodeHandle, polycubeGraphNodeHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
show(soma->scene, soma->solutionEntities.data[soma->state.displayedSolution]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int mainGfx() {
|
int mainGfx() {
|
||||||
Arena *arena = arenaAlloc(Megabytes(128));
|
Arena *arena = arenaAlloc(Megabytes(128));
|
||||||
|
Arena *solutionsArena = arenaAlloc(Megabytes(128));
|
||||||
|
|
||||||
Scene mainScene = createScene(arena);
|
int winWidth = 800, winHeight = 600;
|
||||||
|
GLFWwindow *windowHandle = initWindowAndGL(winWidth, winHeight);
|
||||||
Soma soma = {};
|
if (!windowHandle) {
|
||||||
soma.window.width = 800;
|
return 1;
|
||||||
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 mainFrame = createFrame(arena, soma.window.width, soma.window.height, 0, 0);
|
Scene mainScene = createScene(arena);
|
||||||
UI_Context ui = {};
|
Renderer renderer = createRenderer(arena, &mainScene);
|
||||||
|
Frame mainFrame = createFrame(arena, winWidth, winHeight, 0, 0);
|
||||||
|
|
||||||
GLFWcursor *pointerCursor = glfwCreateStandardCursor(GLFW_HAND_CURSOR);
|
UI_Context ui = {
|
||||||
GLFWcursor *arrowCursor = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
|
.hotNode = 0,
|
||||||
|
.nextId = 1,
|
||||||
|
.cursorIsPointer = false,
|
||||||
|
.input = NULL,
|
||||||
|
.prevInput = NULL,
|
||||||
|
.renderer = &renderer,
|
||||||
|
};
|
||||||
|
|
||||||
soma.polycubeInput = PushListZero(arena, PolycubeInputList, 64);
|
Soma soma = {
|
||||||
soma.polycubes = PushListZero(arena, HandleList, 64);
|
.window = {
|
||||||
|
.width = 800,
|
||||||
|
.height = 600,
|
||||||
|
.handle = windowHandle,
|
||||||
|
.cursors = {
|
||||||
|
.pointer = glfwCreateStandardCursor(GLFW_HAND_CURSOR),
|
||||||
|
.arrow = glfwCreateStandardCursor(GLFW_ARROW_CURSOR),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.scene = &mainScene,
|
||||||
|
.renderer = &renderer,
|
||||||
|
.polycubeInput = PushListZero(arena, PolycubeInputList, 64),
|
||||||
|
.polycubes = PushListZero(arena, HandleList, 64),
|
||||||
|
.puzzleDims = {3, 3, 3},
|
||||||
|
.solveTaskCtx = NULL,
|
||||||
|
.solveArena = arenaAlloc(Megabytes(128)),
|
||||||
|
.state = {
|
||||||
|
.displayingSolutions = false,
|
||||||
|
.displayedPolycube = 0,
|
||||||
|
.displayedSolution = 0,
|
||||||
|
.isInitialState = true,
|
||||||
|
.light = createEntity(&mainScene),
|
||||||
|
.camera = mainFrame.cam,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
soma.state.displayingSolutions = true;
|
getSceneGraphNode(&mainScene, soma.state.light)->translation = (RLVector3){4.0f, 6.0f, 24.0f};
|
||||||
soma.state.displayedPolycube = 0;
|
|
||||||
soma.state.displayedSolution = 0;
|
|
||||||
soma.state.light = createEntity(arena, &mainScene);
|
|
||||||
soma.state.camera = mainFrame.cam;
|
|
||||||
|
|
||||||
SceneGraphNode *light = getSceneGraphNode(&mainScene, getEntity(&mainScene, soma.state.light)->graphNodeHandle);
|
|
||||||
light->translation = (RLVector3){4.0f, 6.0f, 24.0f};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Shader solid_texture_shader = createShader(
|
Shader solid_texture_shader = createShader(
|
||||||
@@ -684,31 +885,12 @@ int mainGfx() {
|
|||||||
PolycubeInput input = (PolycubeInput){ voxelSpace, color };
|
PolycubeInput input = (PolycubeInput){ voxelSpace, color };
|
||||||
AppendList(&soma.polycubeInput, input);
|
AppendList(&soma.polycubeInput, input);
|
||||||
cullEmptySpace(&voxelSpace);
|
cullEmptySpace(&voxelSpace);
|
||||||
uint32 polycubeGraphNodeHandle = createPolycubeFromRepr(arena, soma.scene, &voxelSpace, color);
|
uint32 polycubeGraphNodeHandle = createPolycubeFromRepr(soma.scene, &voxelSpace, color);
|
||||||
AppendList(&soma.polycubes, polycubeGraphNodeHandle);
|
AppendList(&soma.polycubes, polycubeGraphNodeHandle);
|
||||||
sceneNodeAddNode(renderer.scene, renderer.scene->sceneRoot, polycubeGraphNodeHandle);
|
sceneNodeAddNode(renderer.scene, renderer.scene->sceneRoot, polycubeGraphNodeHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
soma.solutions = solveSoma(arena, AsList(VoxelSpaceReprList, STD_SOMA), (int[]){ 3, 3, 3 });
|
// TODO(dledda): only actually create and render one solution/polycube at a time, save lots of space!
|
||||||
soma.solutionEntities = PushList(arena, HandleList, soma.solutions.length);
|
|
||||||
for (EachEl(soma.solutions, SomaSolution, solution)) {
|
|
||||||
uint32 solutionGraphNodeHandle = createSceneGraphNode(arena, soma.scene);
|
|
||||||
AppendList(&soma.solutionEntities, solutionGraphNodeHandle);
|
|
||||||
sceneNodeAddNode(renderer.scene, renderer.scene->sceneRoot, solutionGraphNodeHandle);
|
|
||||||
for (EachIn(*solution, soln_i)) {
|
|
||||||
uint32 polycubeGraphNodeHandle = createPolycubeFromRepr(
|
|
||||||
arena,
|
|
||||||
soma.scene,
|
|
||||||
&(VoxelSpace){ solution->data[soln_i], 3, 3, 3 },
|
|
||||||
colorFromIndex(soln_i)
|
|
||||||
);
|
|
||||||
sceneNodeAddNode(renderer.scene, solutionGraphNodeHandle, polycubeGraphNodeHandle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
show(soma.scene, soma.solutionEntities.data[soma.state.displayedSolution]);
|
|
||||||
|
|
||||||
print("%zu\n", soma.scene->entities.length);
|
|
||||||
print("%zu\n", soma.scene->graphNodes.length);
|
|
||||||
|
|
||||||
soma.state.camera->pos = (RLVector3){0.0f, 0.0f, 8.0f};
|
soma.state.camera->pos = (RLVector3){0.0f, 0.0f, 8.0f};
|
||||||
cameraLookAt(soma.state.camera, 0.0f, 0.0f, 0.0f);
|
cameraLookAt(soma.state.camera, 0.0f, 0.0f, 0.0f);
|
||||||
@@ -727,34 +909,21 @@ int mainGfx() {
|
|||||||
|
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
soma.state.input = getCurrentInput(soma.window.handle);
|
soma.state.input = getCurrentInput(soma.window.handle);
|
||||||
processInput(&soma);
|
|
||||||
|
|
||||||
/*
|
processInput(&soma, &ui);
|
||||||
if (soma.state.lastPolycubeVisible != soma.state.currentPolycube) {
|
updatePolycubeDisplay(arena, &soma);
|
||||||
hide(soma.scene, soma.state.polycubes.data[soma.state.lastPolycubeVisible].graphNodeHandle);
|
|
||||||
show(soma.scene, soma.state.polycubes.data[soma.state.currentPolycube].graphNodeHandle);
|
if (soma.solveTaskCtx != NULL && soma.solveTaskCtx->taskStatus == SolveTaskStatus_Complete) {
|
||||||
soma.state.lastPolycubeVisible = soma.state.currentPolycube;
|
soma.solutions = PushFullList(solutionsArena, SomaSolutionList, soma.solveTaskCtx->solutions.length);
|
||||||
|
memcpy(soma.solutions.data, soma.solveTaskCtx->solutions.data, soma.solutions.length*sizeof(soma.solutions.data[0]));
|
||||||
|
for (EachIn(soma.solutions, i)) {
|
||||||
|
soma.solutions.data[i] = PushFullList(solutionsArena, SomaSolution, soma.solveTaskCtx->input.length);
|
||||||
|
memcpy(&soma.solutions.data[i], &soma.solveTaskCtx->solutions.data[i], soma.solveTaskCtx->input.length*sizeof(uint64));
|
||||||
}
|
}
|
||||||
*/
|
createSolutionEntities(soma.solveTaskCtx->arena, &soma);
|
||||||
|
soma.solveTaskCtx->taskStatus = SolveTaskStatus_Ready;
|
||||||
if (soma.state.displayedSolution != soma.prevState.displayedSolution) {
|
soma.state.displayingSolutions = true;
|
||||||
show(soma.scene, soma.solutionEntities.data[soma.state.displayedSolution]);
|
arenaFreeFrom(soma.solveTaskCtx->arena, 0);
|
||||||
hide(soma.scene, soma.solutionEntities.data[soma.prevState.displayedSolution]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (soma.state.polycubeDirty) {
|
|
||||||
uint32 currentPolycube = soma.polycubes.data[soma.state.displayedPolycube];
|
|
||||||
PolycubeInput *pinput = &soma.polycubeInput.data[soma.state.displayedPolycube];
|
|
||||||
removeEntity(soma.scene, currentPolycube);
|
|
||||||
VoxelSpace culledRepr = pinput->repr;
|
|
||||||
cullEmptySpace(&culledRepr);
|
|
||||||
uint32 newPolycube = createPolycubeFromRepr(arena, soma.scene, &culledRepr, pinput->color);
|
|
||||||
SceneGraphNode *graphNode = getSceneGraphNode(soma.scene, newPolycube);
|
|
||||||
graphNode->rotation = getSceneGraphNode(soma.scene, currentPolycube)->rotation;
|
|
||||||
soma.polycubes.data[soma.state.displayedPolycube] = newPolycube;
|
|
||||||
sceneNodeAddNode(soma.scene, soma.scene->sceneRoot, newPolycube);
|
|
||||||
soma.state.polycubeDirty = false;
|
|
||||||
show(soma.scene, newPolycube);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateViewportFromFrame(soma.window.width, soma.window.height, &mainFrame);
|
updateViewportFromFrame(soma.window.width, soma.window.height, &mainFrame);
|
||||||
@@ -762,15 +931,11 @@ int mainGfx() {
|
|||||||
|
|
||||||
renderBegin(&renderer);
|
renderBegin(&renderer);
|
||||||
|
|
||||||
ui.cursorIsPointer = false;
|
uiPass(&soma, &ui);
|
||||||
ui.prevInput = &soma.prevState.input;
|
|
||||||
ui.input = &soma.state.input;
|
|
||||||
ui.renderer = &renderer;
|
|
||||||
uiPass(&soma, &ui, &renderer);
|
|
||||||
if (ui.cursorIsPointer) {
|
if (ui.cursorIsPointer) {
|
||||||
glfwSetCursor(soma.window.handle, pointerCursor);
|
glfwSetCursor(soma.window.handle, soma.window.cursors.pointer);
|
||||||
} else {
|
} else {
|
||||||
glfwSetCursor(soma.window.handle, arrowCursor);
|
glfwSetCursor(soma.window.handle, soma.window.cursors.arrow);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderEnd(&soma, &renderer);
|
renderEnd(&soma, &renderer);
|
||||||
@@ -783,6 +948,7 @@ int mainGfx() {
|
|||||||
glfwSwapBuffers(soma.window.handle);
|
glfwSwapBuffers(soma.window.handle);
|
||||||
|
|
||||||
soma.prevState = soma.state;
|
soma.prevState = soma.state;
|
||||||
|
soma.state.isInitialState = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
|
|||||||
@@ -1,29 +1,39 @@
|
|||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "scene.h"
|
#include "scene.h"
|
||||||
|
|
||||||
Entity *getEntity(Scene *s, uint32 id) {
|
Entity *getEntity(Scene *s, uint32 entityHandle) {
|
||||||
return &s->entities.data[id - 1];
|
if (entityHandle) {
|
||||||
|
return &s->entities.data[entityHandle - 1];
|
||||||
}
|
}
|
||||||
|
return NULL;
|
||||||
SceneGraphNode *getSceneGraphNodeForEntity(Scene *s, uint32 entityHandle) {
|
|
||||||
return &s->graphNodes.data[s->entities.data[entityHandle - 1].graphNodeHandle - 1];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SceneGraphNode *getSceneGraphNode(Scene *s, uint32 sceneGraphNodeHandle) {
|
SceneGraphNode *getSceneGraphNode(Scene *s, uint32 sceneGraphNodeHandle) {
|
||||||
|
if (sceneGraphNodeHandle) {
|
||||||
return &s->graphNodes.data[sceneGraphNodeHandle - 1];
|
return &s->graphNodes.data[sceneGraphNodeHandle - 1];
|
||||||
}
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
uint32 createSceneGraphNode(Arena *arena, Scene *s) {
|
SceneGraphNode *getSceneGraphNodeForEntity(Scene *s, uint32 entityHandle) {
|
||||||
|
Entity *e = getEntity(s, entityHandle);
|
||||||
|
if (e) {
|
||||||
|
return getSceneGraphNode(s, e->graphNodeHandle);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 createSceneGraphNode(Scene *s) {
|
||||||
AppendList(&s->graphNodes, (SceneGraphNode){0});
|
AppendList(&s->graphNodes, (SceneGraphNode){0});
|
||||||
SceneGraphNode *node = &s->graphNodes.data[s->graphNodes.length - 1];
|
SceneGraphNode *node = &s->graphNodes.data[s->graphNodes.length - 1];
|
||||||
node->children = PushList(arena, HandleList, 1000);
|
node->children = PushList(s->arena, HandleList, 1000);
|
||||||
initGraphNode(node);
|
initGraphNode(node);
|
||||||
return (uint32)s->graphNodes.length;
|
return (uint32)s->graphNodes.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 createEntity(Arena *arena, Scene *s) {
|
uint32 createEntity(Scene *s) {
|
||||||
AppendList(&s->entities, (Entity){0});
|
AppendList(&s->entities, (Entity){0});
|
||||||
uint32 graphNodeId = createSceneGraphNode(arena, s);
|
uint32 graphNodeId = createSceneGraphNode(s);
|
||||||
s->entities.data[s->entities.length - 1].graphNodeHandle = graphNodeId;
|
s->entities.data[s->entities.length - 1].graphNodeHandle = graphNodeId;
|
||||||
getSceneGraphNode(s, graphNodeId)->entityHandle = (uint32)s->entities.length;
|
getSceneGraphNode(s, graphNodeId)->entityHandle = (uint32)s->entities.length;
|
||||||
uint32 handle = (uint32)s->entities.length;
|
uint32 handle = (uint32)s->entities.length;
|
||||||
@@ -44,10 +54,12 @@ void recalcGraphNode(SceneGraphNode *n) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Scene createScene(Arena *arena) {
|
Scene createScene(Arena *arena) {
|
||||||
Scene result = {};
|
Scene result = {
|
||||||
result.entities = PushList(arena, EntityList, 100000);
|
.arena = arena,
|
||||||
result.graphNodes = PushList(arena, SceneGraphNodeList, 100000);
|
.entities = PushList(arena, EntityList, 100000),
|
||||||
result.sceneRoot = createSceneGraphNode(arena, &result);
|
.graphNodes = PushList(arena, SceneGraphNodeList, 100000),
|
||||||
|
};
|
||||||
|
result.sceneRoot = createSceneGraphNode(&result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,18 +86,19 @@ void removeEntity(Scene *s, uint32 entityHandle) {
|
|||||||
Entity *entity = getEntity(s, entityHandle);
|
Entity *entity = getEntity(s, entityHandle);
|
||||||
entity->flags |= EntityFlags_Dead;
|
entity->flags |= EntityFlags_Dead;
|
||||||
SceneGraphNode *graphNode = getSceneGraphNode(s, entity->graphNodeHandle);
|
SceneGraphNode *graphNode = getSceneGraphNode(s, entity->graphNodeHandle);
|
||||||
if (graphNode->parentHandle) {
|
if (graphNode != NULL && graphNode->parentHandle) {
|
||||||
SceneGraphNode *parentNode = getSceneGraphNode(s, graphNode->parentHandle);
|
SceneGraphNode *parentNode = getSceneGraphNode(s, graphNode->parentHandle);
|
||||||
for (int i = 0; i < parentNode->children.length; i++) {
|
if (parentNode != NULL) {
|
||||||
|
for (EachIn(parentNode->children, i)) {
|
||||||
if (parentNode->children.data[i] == entity->graphNodeHandle) {
|
if (parentNode->children.data[i] == entity->graphNodeHandle) {
|
||||||
memcpy(&parentNode->children.data[i], &parentNode->children.data[i + 1], parentNode->children.length - i);
|
ListRemove(&parentNode->children, i);
|
||||||
parentNode->children.length -= 1;
|
|
||||||
graphNode->parentHandle = 0;
|
graphNode->parentHandle = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void sceneNodeAddEntity(Scene *s, uint32 graphNodeHandle, uint32 entityHandle) {
|
void sceneNodeAddEntity(Scene *s, uint32 graphNodeHandle, uint32 entityHandle) {
|
||||||
HandleList *childList = &getSceneGraphNode(s, graphNodeHandle)->children;
|
HandleList *childList = &getSceneGraphNode(s, graphNodeHandle)->children;
|
||||||
|
|||||||
@@ -37,12 +37,13 @@ struct Scene {
|
|||||||
uint32 sceneRoot;
|
uint32 sceneRoot;
|
||||||
EntityList entities;
|
EntityList entities;
|
||||||
SceneGraphNodeList graphNodes;
|
SceneGraphNodeList graphNodes;
|
||||||
|
Arena *arena;
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32 createEntity(Arena *arena, Scene *s);
|
uint32 createEntity(Scene *s);
|
||||||
Entity *getEntity(Scene *s, uint32 id);
|
Entity *getEntity(Scene *s, uint32 id);
|
||||||
SceneGraphNode *getSceneGraphNode(Scene *s, uint32 id);
|
SceneGraphNode *getSceneGraphNode(Scene *s, uint32 id);
|
||||||
uint32 createSceneGraphNode(Arena *arena, Scene *s);
|
uint32 createSceneGraphNode(Scene *s);
|
||||||
Scene createScene(Arena *arena);
|
Scene createScene(Arena *arena);
|
||||||
void initGraphNode(SceneGraphNode *n);
|
void initGraphNode(SceneGraphNode *n);
|
||||||
void recalcGraphNode(SceneGraphNode *n);
|
void recalcGraphNode(SceneGraphNode *n);
|
||||||
|
|||||||
Reference in New Issue
Block a user