new ui stuff
This commit is contained in:
4
build
4
build
@@ -1,13 +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"
|
COMMON_FLAGS="-DOS_LINUX=1 -xc -std=c99"
|
||||||
|
|
||||||
echo [Building target]
|
echo [Building target]
|
||||||
if [ $DEBUG ]; then
|
if [ $DEBUG ]; then
|
||||||
time clang -O0 -g -g2 $COMMON_FLAGS -DDJSTDLIB_DEBUG=1 ./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 $COMMON_FLAGS ./src/main.c -o ./target/somaesque $LIB_INCLUDE
|
time clang -O3 $COMMON_FLAGS ./src/main.c -o ./target/somaesque $LIB_INCLUDE
|
||||||
fi
|
fi
|
||||||
echo [Target built]
|
echo [Target built]
|
||||||
|
|
||||||
|
|||||||
28
src/debug.c
Normal file
28
src/debug.c
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#include "lib/raymath.h"
|
||||||
|
#include "lib/djstdlib/core.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
void printRLVec3(RLVector3* vector) {
|
||||||
|
RLVector3 vec = *vector;
|
||||||
|
print(
|
||||||
|
"┌ ┐\n"
|
||||||
|
"│%7.2f%, %7.2f, %7.2f │\n"
|
||||||
|
"└ ┘\n",
|
||||||
|
vec.x, vec.y, vec.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
void printMatrix(Matrix* matrix) {
|
||||||
|
Matrix mat = *matrix;
|
||||||
|
print(
|
||||||
|
"┌ ┐\n"
|
||||||
|
"│%7.2f%, %7.2f, %7.2f, %7.2f │\n"
|
||||||
|
"│%7.2f%, %7.2f, %7.2f, %7.2f │\n"
|
||||||
|
"│%7.2f%, %7.2f, %7.2f, %7.2f │\n"
|
||||||
|
"│%7.2f%, %7.2f, %7.2f, %7.2f │\n"
|
||||||
|
"└ ┘\n",
|
||||||
|
mat.m0, mat.m1, mat.m2, mat.m3,
|
||||||
|
mat.m4, mat.m5, mat.m6, mat.m7,
|
||||||
|
mat.m8, mat.m9, mat.m10, mat.m11,
|
||||||
|
mat.m12, mat.m13, mat.m14, mat.m15);
|
||||||
|
}
|
||||||
|
|
||||||
9
src/debug.h
Normal file
9
src/debug.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#ifndef DEBUG_H
|
||||||
|
#define DEBUG_H
|
||||||
|
|
||||||
|
#include "lib/raymath.h"
|
||||||
|
|
||||||
|
void printRLVec3(RLVector3* vector);
|
||||||
|
void printMatrix(Matrix* matrix);
|
||||||
|
|
||||||
|
#endif
|
||||||
Submodule src/lib/djstdlib updated: 3f3ef5351f...0fcbb4154b
@@ -51,6 +51,8 @@
|
|||||||
*
|
*
|
||||||
**********************************************************************************************/
|
**********************************************************************************************/
|
||||||
|
|
||||||
|
// NOTE(djledda): this file has been modified from the original to rename types that conflict with other library types (RLVector4, RLVector3, RLVector2)
|
||||||
|
|
||||||
#ifndef RAYMATH_H
|
#ifndef RAYMATH_H
|
||||||
#define RAYMATH_H
|
#define RAYMATH_H
|
||||||
|
|
||||||
|
|||||||
574
src/main.c
574
src/main.c
@@ -1,71 +1,27 @@
|
|||||||
|
#define _POSIX_C_SOURCE 199309L
|
||||||
|
#include "time.h"
|
||||||
|
|
||||||
// Library initialisation
|
// Library initialisation
|
||||||
#define RAYMATH_IMPLEMENTATION
|
#define RAYMATH_IMPLEMENTATION
|
||||||
#define STB_IMAGE_IMPLEMENTATION
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
#define TINYOBJ_LOADER_C_IMPLEMENTATION
|
#define TINYOBJ_LOADER_C_IMPLEMENTATION
|
||||||
|
|
||||||
// Project
|
// Project
|
||||||
#include "SomaSolve.c"
|
#include "lib/djstdlib/core.c"
|
||||||
#include "gfx/gfx.c"
|
#include "gfx/gfx.c"
|
||||||
#include "world/world.c"
|
#include "world/world.c"
|
||||||
|
#include "ui.c"
|
||||||
|
#include "render.c"
|
||||||
|
#include "SomaSolve.c"
|
||||||
#include "VoxelSpace.c"
|
#include "VoxelSpace.c"
|
||||||
#include "./tests.c"
|
#include "./tests.c"
|
||||||
#include "lib/djstdlib/core.c"
|
#include "debug.c"
|
||||||
|
|
||||||
// Graphics bindings and libs
|
// Graphics bindings and libs
|
||||||
#include "lib/raymath.h"
|
#include "lib/raymath.h"
|
||||||
#include "lib/glad/glad.c"
|
#include "lib/glad/glad.c"
|
||||||
#include "GLFW/glfw3.h"
|
#include "GLFW/glfw3.h"
|
||||||
|
|
||||||
void printRLVec3(RLVector3* vector) {
|
|
||||||
RLVector3 vec = *vector;
|
|
||||||
print(
|
|
||||||
"┌ ┐\n"
|
|
||||||
"│%7.2f%, %7.2f, %7.2f │\n"
|
|
||||||
"└ ┘\n",
|
|
||||||
vec.x, vec.y, vec.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
void printMatrix(Matrix* matrix) {
|
|
||||||
Matrix mat = *matrix;
|
|
||||||
print(
|
|
||||||
"┌ ┐\n"
|
|
||||||
"│%7.2f%, %7.2f, %7.2f, %7.2f │\n"
|
|
||||||
"│%7.2f%, %7.2f, %7.2f, %7.2f │\n"
|
|
||||||
"│%7.2f%, %7.2f, %7.2f, %7.2f │\n"
|
|
||||||
"│%7.2f%, %7.2f, %7.2f, %7.2f │\n"
|
|
||||||
"└ ┘\n",
|
|
||||||
mat.m0, mat.m1, mat.m2, mat.m3,
|
|
||||||
mat.m4, mat.m5, mat.m6, mat.m7,
|
|
||||||
mat.m8, mat.m9, mat.m10, mat.m11,
|
|
||||||
mat.m12, mat.m13, mat.m14, mat.m15);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct Camera Camera;
|
|
||||||
struct Camera {
|
|
||||||
Matrix view;
|
|
||||||
Matrix proj;
|
|
||||||
RLVector3 pos;
|
|
||||||
RLVector3 up;
|
|
||||||
RLVector3 target;
|
|
||||||
};
|
|
||||||
|
|
||||||
Camera *createCamera(Arena *arena, real32 aspect_ratio) {
|
|
||||||
Camera *result = PushStruct(arena, Camera);
|
|
||||||
result->view = (Matrix){0};
|
|
||||||
result->proj = MatrixPerspective(DEG2RAD * 45.0f, aspect_ratio, 0.1f, 100.0f);
|
|
||||||
result->pos = (RLVector3){0};
|
|
||||||
result->up = (RLVector3){0,1,0};
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cameraLookAt(Camera *c, float x, float y, float z) {
|
|
||||||
c->target = (RLVector3){x, y, z};
|
|
||||||
c->view = MatrixLookAt(c->pos, c->target, c->up);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cameraSetUp(Camera *c, real32 up_x, real32 up_y, real32 up_z) {
|
|
||||||
c->up = (RLVector3){up_x, up_y, up_z};
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct Frame Frame;
|
typedef struct Frame Frame;
|
||||||
struct Frame {
|
struct Frame {
|
||||||
@@ -73,95 +29,7 @@ struct Frame {
|
|||||||
uint32 height;
|
uint32 height;
|
||||||
int32 x;
|
int32 x;
|
||||||
int32 y;
|
int32 y;
|
||||||
Camera* cam;
|
Camera cam;
|
||||||
};
|
|
||||||
|
|
||||||
DefineList(RLVector2, RLVec2);
|
|
||||||
DefineList(RLVector4, RLVec4);
|
|
||||||
DefineList(real32, Float);
|
|
||||||
|
|
||||||
typedef struct RenderObjects_Rectangle RenderObjects_Rectangle;
|
|
||||||
struct RenderObjects_Rectangle {
|
|
||||||
uint32 vao;
|
|
||||||
uint64 count;
|
|
||||||
|
|
||||||
RLVec2List p0;
|
|
||||||
uint32 p0BufferId;
|
|
||||||
|
|
||||||
RLVec2List p1;
|
|
||||||
uint32 p1BufferId;
|
|
||||||
|
|
||||||
RLVec4List color;
|
|
||||||
uint32 colorBufferId;
|
|
||||||
|
|
||||||
FloatList borderRadius;
|
|
||||||
uint32 borderRadiusBufferId;
|
|
||||||
|
|
||||||
FloatList borderThickness;
|
|
||||||
uint32 borderThicknessBufferId;
|
|
||||||
|
|
||||||
FloatList edgeSoftness;
|
|
||||||
uint32 edgeSoftnessBufferId;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct Input Input;
|
|
||||||
struct Input {
|
|
||||||
struct {
|
|
||||||
bool escape;
|
|
||||||
bool enter;
|
|
||||||
bool space;
|
|
||||||
bool lshift;
|
|
||||||
bool x;
|
|
||||||
bool y;
|
|
||||||
bool z;
|
|
||||||
bool w;
|
|
||||||
} keyboard;
|
|
||||||
struct {
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
real32 x;
|
|
||||||
real32 y;
|
|
||||||
};
|
|
||||||
RLVector2 point;
|
|
||||||
};
|
|
||||||
bool btnLeft;
|
|
||||||
bool btnRight;
|
|
||||||
bool btnMiddle;
|
|
||||||
} mouse;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct Renderer Renderer;
|
|
||||||
struct Renderer {
|
|
||||||
Scene *scene;
|
|
||||||
RenderObjects_Rectangle rects;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct PolycubeInput PolycubeInput;
|
|
||||||
struct PolycubeInput {
|
|
||||||
VoxelSpace repr;
|
|
||||||
RLVector4 color;
|
|
||||||
};
|
|
||||||
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;
|
typedef enum SolveTaskStatus SolveTaskStatus;
|
||||||
@@ -180,19 +48,23 @@ struct SolveTaskCtx {
|
|||||||
SolveTaskStatus taskStatus;
|
SolveTaskStatus taskStatus;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct PolycubeInput PolycubeInput;
|
||||||
|
struct PolycubeInput {
|
||||||
|
VoxelSpace repr;
|
||||||
|
RLVector4 color;
|
||||||
|
};
|
||||||
|
DefineList(PolycubeInput, PolycubeInput);
|
||||||
|
|
||||||
typedef struct SomaState SomaState;
|
typedef struct SomaState SomaState;
|
||||||
struct SomaState {
|
struct SomaState {
|
||||||
bool isInitialState;
|
bool isInitialState;
|
||||||
bool wireframe;
|
bool wireframe;
|
||||||
bool polycubeDirty;
|
bool polycubeDirty;
|
||||||
uint32 displayedPolycube;
|
int32 displayedPolycube;
|
||||||
size_t displayedSolution;
|
size_t displayedSolution;
|
||||||
bool displayingSolutions;
|
bool displayingSolutions;
|
||||||
uint32 light;
|
|
||||||
Camera* camera;
|
|
||||||
RLVector3 rotAxisX;
|
RLVector3 rotAxisX;
|
||||||
RLVector3 rotAxisY;
|
RLVector3 rotAxisY;
|
||||||
Input input;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct Soma Soma;
|
typedef struct Soma Soma;
|
||||||
@@ -201,8 +73,8 @@ struct Soma {
|
|||||||
Renderer *renderer;
|
Renderer *renderer;
|
||||||
struct {
|
struct {
|
||||||
GLFWwindow *handle;
|
GLFWwindow *handle;
|
||||||
uint32 width;
|
int32 width;
|
||||||
uint32 height;
|
int32 height;
|
||||||
struct {
|
struct {
|
||||||
GLFWcursor *pointer;
|
GLFWcursor *pointer;
|
||||||
GLFWcursor *arrow;
|
GLFWcursor *arrow;
|
||||||
@@ -216,7 +88,7 @@ struct Soma {
|
|||||||
HandleList polycubes;
|
HandleList polycubes;
|
||||||
SomaSolutionList solutions;
|
SomaSolutionList solutions;
|
||||||
SolveTaskCtx solveTaskCtx;
|
SolveTaskCtx solveTaskCtx;
|
||||||
uint32 puzzleDims[3];
|
int32 puzzleDims[3];
|
||||||
int32 solutionNode;
|
int32 solutionNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -243,30 +115,6 @@ void scheduleSolve(Soma *soma) {
|
|||||||
os_createThread(&executeSolve, &soma->solveTaskCtx);
|
os_createThread(&executeSolve, &soma->solveTaskCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void show(Scene *s, uint32 graphNodeHandle) {
|
|
||||||
SceneGraphNode *node = getSceneGraphNode(s, graphNodeHandle);
|
|
||||||
if (node->entityHandle) {
|
|
||||||
getEntity(s, node->entityHandle)->flags |= EntityFlags_Visible;
|
|
||||||
}
|
|
||||||
int32 next = node->firstChild;
|
|
||||||
while (next) {
|
|
||||||
show(s, next);
|
|
||||||
next = getSceneGraphNode(s, next)->nextSibling;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void hide(Scene *s, uint32 graphNodeHandle) {
|
|
||||||
SceneGraphNode *node = getSceneGraphNode(s, graphNodeHandle);
|
|
||||||
if (node->entityHandle) {
|
|
||||||
getEntity(s, node->entityHandle)->flags &= ~EntityFlags_Visible;
|
|
||||||
}
|
|
||||||
int32 next = node->firstChild;
|
|
||||||
while (next) {
|
|
||||||
hide(s, next);
|
|
||||||
next = getSceneGraphNode(s, next)->nextSibling;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RLVector3 centreFromPolycube(Scene *scene, uint32 p) {
|
RLVector3 centreFromPolycube(Scene *scene, uint32 p) {
|
||||||
RLVector3 centre = (RLVector3){0,0,0};
|
RLVector3 centre = (RLVector3){0,0,0};
|
||||||
int32 childCount = 0;
|
int32 childCount = 0;
|
||||||
@@ -281,23 +129,13 @@ RLVector3 centreFromPolycube(Scene *scene, uint32 p) {
|
|||||||
return centre;
|
return centre;
|
||||||
}
|
}
|
||||||
|
|
||||||
Frame createFrame(Arena *arena, uint32 width, uint32 height, uint32 x, uint32 y) {
|
|
||||||
return (Frame){
|
|
||||||
.width = width,
|
|
||||||
.height = height,
|
|
||||||
.x = x,
|
|
||||||
.y = y,
|
|
||||||
.cam = createCamera(arena, (real32)width / (real32)height),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
void framebufferSizeCallback(GLFWwindow *window, int width, int height) {
|
void framebufferSizeCallback(GLFWwindow *window, int width, int height) {
|
||||||
glViewport(0, 0, width, height);
|
glViewport(0, 0, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWwindow *initWindowAndGL(uint32 windowWidth, uint32 windowHeight) {
|
GLFWwindow *initWindowAndGL(uint32 windowWidth, uint32 windowHeight) {
|
||||||
#ifdef OS_LINUX
|
#ifdef OS_LINUX
|
||||||
//glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_X11);
|
glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_X11);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
glfwInit();
|
glfwInit();
|
||||||
@@ -329,8 +167,8 @@ GLFWwindow *initWindowAndGL(uint32 windowWidth, uint32 windowHeight) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
glViewport(0, 0, 800, 600);
|
glViewport(0, 0, windowWidth, windowHeight);
|
||||||
glfwSwapInterval(0);
|
glfwSwapInterval(1);
|
||||||
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);
|
glfwSetWindowSize(window, windowWidth, windowHeight);
|
||||||
@@ -339,59 +177,15 @@ GLFWwindow *initWindowAndGL(uint32 windowWidth, uint32 windowHeight) {
|
|||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateViewportFromFrame(uint32 windowWidth, uint32 windowHeight, Frame* frame) {
|
|
||||||
glViewport(frame->x, windowHeight - frame->y - frame->height, frame->width, frame->height);
|
|
||||||
}
|
|
||||||
|
|
||||||
Mesh cubeMesh = {0};
|
Mesh cubeMesh = {0};
|
||||||
Texture wallTex = {0};
|
Texture wallTex = {0};
|
||||||
|
|
||||||
Shader solidColorShader;
|
Shader solidColorShader;
|
||||||
Shader phongShader;
|
Shader phongShader;
|
||||||
|
|
||||||
bool glfwMouse(GLFWwindow *window, int mouseBtnCode) {
|
|
||||||
switch (glfwGetMouseButton(window, mouseBtnCode)) {
|
|
||||||
case GLFW_RELEASE: return false;
|
|
||||||
case GLFW_PRESS: return true;
|
|
||||||
default: return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool glfwKey(GLFWwindow *window, int keyCode) {
|
|
||||||
switch (glfwGetKey(window, keyCode)) {
|
|
||||||
case GLFW_RELEASE: return false;
|
|
||||||
case GLFW_PRESS: return true;
|
|
||||||
default: return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Input getCurrentInput(GLFWwindow *window) {
|
|
||||||
Input input = {0};
|
|
||||||
|
|
||||||
input.keyboard.escape = glfwKey(window, GLFW_KEY_ESCAPE);
|
|
||||||
input.keyboard.enter = glfwKey(window, GLFW_KEY_ENTER);
|
|
||||||
input.keyboard.space = glfwKey(window, GLFW_KEY_SPACE);
|
|
||||||
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.y = glfwKey(window, GLFW_KEY_Y);
|
|
||||||
input.keyboard.z = glfwKey(window, GLFW_KEY_Z);
|
|
||||||
|
|
||||||
input.mouse.btnLeft = glfwMouse(window, GLFW_MOUSE_BUTTON_LEFT);
|
|
||||||
input.mouse.btnRight = glfwMouse(window, GLFW_MOUSE_BUTTON_RIGHT);
|
|
||||||
input.mouse.btnMiddle = glfwMouse(window, GLFW_MOUSE_BUTTON_MIDDLE);
|
|
||||||
|
|
||||||
real64 mouseX;
|
|
||||||
real64 mouseY;
|
|
||||||
glfwGetCursorPos(window, &mouseX, &mouseY);
|
|
||||||
input.mouse.point = (RLVector2){(real32)mouseX, (real32)mouseY};
|
|
||||||
|
|
||||||
return input;
|
|
||||||
}
|
|
||||||
|
|
||||||
void processInput(Soma *soma, UI_Context *ui) {
|
void processInput(Soma *soma, UI_Context *ui) {
|
||||||
Input *input = &soma->state.input;
|
Input *input = ui->input;
|
||||||
Input *prevInput = &soma->prevState.input;
|
Input *prevInput = ui->prevInput;
|
||||||
|
|
||||||
if (input->keyboard.escape) {
|
if (input->keyboard.escape) {
|
||||||
glfwSetWindowShouldClose(soma->window.handle, true);
|
glfwSetWindowShouldClose(soma->window.handle, true);
|
||||||
@@ -402,7 +196,7 @@ void processInput(Soma *soma, UI_Context *ui) {
|
|||||||
soma->state.wireframe = !soma->state.wireframe;
|
soma->state.wireframe = !soma->state.wireframe;
|
||||||
}
|
}
|
||||||
|
|
||||||
SceneGraphNode *node = getSceneGraphNode(soma->scene, soma->state.light);
|
SceneGraphNode *node = getSceneGraphNode(soma->scene, soma->renderer->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;
|
||||||
@@ -479,196 +273,7 @@ uint32 createPolycubeFromRepr(Scene *s, VoxelSpace *repr, RLVector4 color) {
|
|||||||
return mainGraphNode;
|
return mainGraphNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderObjects_Rectangle createRectangleObjects(Arena *arena, size_t count) {
|
static void somaUIPass(Soma *soma, UI_Context *ui) {
|
||||||
RenderObjects_Rectangle result = {0};
|
|
||||||
result.count = count;
|
|
||||||
|
|
||||||
result.p0 = PushFullList(arena, RLVec2List, count);
|
|
||||||
result.p1 = PushFullList(arena, RLVec2List, count);
|
|
||||||
result.color = PushFullList(arena, RLVec4List, count);
|
|
||||||
result.borderRadius = PushFullList(arena, FloatList, count);
|
|
||||||
result.borderThickness = PushFullList(arena, FloatList, count);
|
|
||||||
result.edgeSoftness = PushFullList(arena, FloatList, count);
|
|
||||||
|
|
||||||
glGenVertexArrays(1, &result.vao);
|
|
||||||
|
|
||||||
glGenBuffers(1, &result.p0BufferId);
|
|
||||||
glGenBuffers(1, &result.p1BufferId);
|
|
||||||
glGenBuffers(1, &result.colorBufferId);
|
|
||||||
glGenBuffers(1, &result.borderRadiusBufferId);
|
|
||||||
glGenBuffers(1, &result.borderThicknessBufferId);
|
|
||||||
glGenBuffers(1, &result.edgeSoftnessBufferId);
|
|
||||||
|
|
||||||
glBindVertexArray(result.vao);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, result.p0BufferId);
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, result.p0.length * sizeof(RLVec2List_underlying), 0, GL_DYNAMIC_DRAW);
|
|
||||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(RLVec2List_underlying), NULL);
|
|
||||||
glVertexAttribDivisor(0, 1);
|
|
||||||
glEnableVertexAttribArray(0);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, result.p1BufferId);
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, result.p1.length * sizeof(RLVec2List_underlying), 0, GL_DYNAMIC_DRAW);
|
|
||||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(RLVec2List_underlying), NULL);
|
|
||||||
glVertexAttribDivisor(1, 1);
|
|
||||||
glEnableVertexAttribArray(1);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, result.colorBufferId);
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, result.color.length * sizeof(RLVec4List_underlying), 0, GL_DYNAMIC_DRAW);
|
|
||||||
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(RLVec4List_underlying), NULL);
|
|
||||||
glVertexAttribDivisor(2, 1);
|
|
||||||
glEnableVertexAttribArray(2);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, result.borderRadiusBufferId);
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, result.borderRadius.length * sizeof(FloatList_underlying), 0, GL_DYNAMIC_DRAW);
|
|
||||||
glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, sizeof(FloatList_underlying), NULL);
|
|
||||||
glVertexAttribDivisor(3, 1);
|
|
||||||
glEnableVertexAttribArray(3);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, result.borderThicknessBufferId);
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, result.borderThickness.length * sizeof(FloatList_underlying), 0, GL_DYNAMIC_DRAW);
|
|
||||||
glVertexAttribPointer(4, 1, GL_FLOAT, GL_FALSE, sizeof(FloatList_underlying), NULL);
|
|
||||||
glVertexAttribDivisor(4, 1);
|
|
||||||
glEnableVertexAttribArray(4);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, result.edgeSoftnessBufferId);
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, result.edgeSoftness.length * sizeof(FloatList_underlying), 0, GL_DYNAMIC_DRAW);
|
|
||||||
glVertexAttribPointer(5, 1, GL_FLOAT, GL_FALSE, sizeof(FloatList_underlying), NULL);
|
|
||||||
glVertexAttribDivisor(5, 1);
|
|
||||||
glEnableVertexAttribArray(5);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void updateRectangleObjectBuffers(Renderer *r) {
|
|
||||||
glBindVertexArray(r->rects.vao);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, r->rects.p0BufferId);
|
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, r->rects.p0.length * sizeof(RLVec2List_underlying), r->rects.p0.data);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, r->rects.p1BufferId);
|
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, r->rects.p1.length * sizeof(RLVec2List_underlying), r->rects.p1.data);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, r->rects.colorBufferId);
|
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, r->rects.color.length * sizeof(RLVec4List_underlying), r->rects.color.data);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, r->rects.borderRadiusBufferId);
|
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, r->rects.borderRadius.length * sizeof(FloatList_underlying), r->rects.borderRadius.data);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, r->rects.borderThicknessBufferId);
|
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, r->rects.borderThickness.length * sizeof(FloatList_underlying), r->rects.borderThickness.data);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, r->rects.edgeSoftnessBufferId);
|
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, r->rects.edgeSoftness.length * sizeof(FloatList_underlying), r->rects.edgeSoftness.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
Renderer createRenderer(Arena *arena, Scene *scene) {
|
|
||||||
return (Renderer){
|
|
||||||
.scene = scene,
|
|
||||||
.rects = createRectangleObjects(arena, 1024),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
void renderBegin(Renderer *r) {
|
|
||||||
r->rects.p0.length = 0;
|
|
||||||
r->rects.p1.length = 0;
|
|
||||||
r->rects.color.length = 0;
|
|
||||||
r->rects.borderRadius.length = 0;
|
|
||||||
r->rects.borderThickness.length = 0;
|
|
||||||
r->rects.edgeSoftness.length = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
glUseProgram(phongShader.progId);
|
|
||||||
setUniformMat4fv(&phongShader, "projection", &soma->state.camera->proj);
|
|
||||||
setUniformMat4fv(&phongShader, "view", &soma->state.camera->view);
|
|
||||||
|
|
||||||
SceneGraphNode *lightGraphNode = getSceneGraphNode(soma->scene, soma->state.light);
|
|
||||||
setUniform3fv(&phongShader, "light_pos", &lightGraphNode->translation);
|
|
||||||
setUniform3fv(&phongShader, "camera", &soma->state.camera->pos);
|
|
||||||
|
|
||||||
uint32 currentPolycube = soma->polycubes.data[soma->state.displayedPolycube];
|
|
||||||
glBindVertexArray(cubeMesh.vao);
|
|
||||||
|
|
||||||
int model_uniform = getUniformLocation(&phongShader, "model");
|
|
||||||
int solid_color_uniform = getUniformLocation(&phongShader, "solid_color");
|
|
||||||
for (EachIn(renderer->scene->entities, i)) {
|
|
||||||
Entity *entity = &renderer->scene->entities.data[i];
|
|
||||||
if (entity->flags & EntityFlags_Render && entity->flags & EntityFlags_Visible) {
|
|
||||||
setUniform4fvByLoc(solid_color_uniform, &entity->color);
|
|
||||||
setUniformMat4fvByLoc(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
|
|
||||||
glUseProgram(solidColorShader.progId);
|
|
||||||
|
|
||||||
updateRectangleObjectBuffers(renderer);
|
|
||||||
|
|
||||||
Matrix ortho = MatrixOrtho(0.0, 800.0, 600.0, 0.0, -1.0, 1.0);
|
|
||||||
setUniformMat4fv(&solidColorShader, "projection", &ortho);
|
|
||||||
|
|
||||||
glBindVertexArray(renderer->rects.vao);
|
|
||||||
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, renderer->rects.p0.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rendererPlaceRectangle(Renderer *r, real32 x, real32 y, real32 width, real32 height, RLVector4 color, real32 borderRadius, real32 borderThickness) {
|
|
||||||
ListAppend(r->rects.p0, ((RLVector2){ x, y }));
|
|
||||||
ListAppend(r->rects.p1, ((RLVector2){ x + width, y + height }));
|
|
||||||
ListAppend(r->rects.color, color);
|
|
||||||
ListAppend(r->rects.borderRadius, borderRadius);
|
|
||||||
ListAppend(r->rects.borderThickness, borderThickness);
|
|
||||||
ListAppend(r->rects.edgeSoftness, 0.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool pointInRect(RLVector2 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ui_checkboxRect(UI_Context *ui, bool *value, UI_Rect rect) {
|
|
||||||
uint32 id = ui->nextId++;
|
|
||||||
bool clicked = false;
|
|
||||||
if (pointInRect(ui->input->mouse.point, rect)) {
|
|
||||||
ui->cursorIsPointer = true;
|
|
||||||
if (ui->prevHotNode == id && !ui->input->mouse.btnLeft) {
|
|
||||||
*value = !*value;
|
|
||||||
clicked = true;
|
|
||||||
} else if (ui->input->mouse.btnLeft && (!ui->prevInput->mouse.btnLeft || ui->prevHotNode == id)) {
|
|
||||||
ui->hotNode = id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (*value) {
|
|
||||||
rendererPlaceRectangle(ui->renderer,
|
|
||||||
rect.x, rect.y,
|
|
||||||
rect.width, rect.height,
|
|
||||||
rect.color,
|
|
||||||
5, 0);
|
|
||||||
} else {
|
|
||||||
rendererPlaceRectangle(ui->renderer,
|
|
||||||
rect.x, rect.y,
|
|
||||||
rect.width, rect.height,
|
|
||||||
COLOR_WHITE,
|
|
||||||
5, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
return clicked;
|
|
||||||
}
|
|
||||||
|
|
||||||
void uiPass(Soma *soma, UI_Context *ui) {
|
|
||||||
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;
|
||||||
@@ -733,7 +338,7 @@ void uiPass(Soma *soma, UI_Context *ui) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void updatePolycubeDisplay(Arena *arena, Soma *soma) {
|
static void updatePolycubeDisplay(Soma *soma) {
|
||||||
Scene *s = soma->scene;
|
Scene *s = soma->scene;
|
||||||
|
|
||||||
if (soma->state.displayingSolutions && soma->state.displayedSolution != soma->prevState.displayedSolution) {
|
if (soma->state.displayingSolutions && soma->state.displayedSolution != soma->prevState.displayedSolution) {
|
||||||
@@ -744,7 +349,7 @@ void updatePolycubeDisplay(Arena *arena, Soma *soma) {
|
|||||||
for (EachIn(soln, i)) {
|
for (EachIn(soln, i)) {
|
||||||
uint32 polycubeGraphNodeHandle = createPolycubeFromRepr(
|
uint32 polycubeGraphNodeHandle = createPolycubeFromRepr(
|
||||||
s,
|
s,
|
||||||
&(VoxelSpace){ soln.data[i], 3, 3, 3 },
|
&(VoxelSpace){ soln.data[i], soma->puzzleDims[0], soma->puzzleDims[1], soma->puzzleDims[2] },
|
||||||
colorFromIndex(i)
|
colorFromIndex(i)
|
||||||
);
|
);
|
||||||
sceneNodeAddNode(s, soma->solutionNode, polycubeGraphNodeHandle);
|
sceneNodeAddNode(s, soma->solutionNode, polycubeGraphNodeHandle);
|
||||||
@@ -792,34 +397,52 @@ void updatePolycubeDisplay(Arena *arena, Soma *soma) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void updateWindow(Soma *soma) {
|
||||||
|
glfwGetWindowSize(soma->window.handle, &soma->window.width, &soma->window.height);
|
||||||
|
glViewport(0, 0, soma->window.width, soma->window.height);
|
||||||
|
cameraSetAspect(soma->renderer->camera, soma->window.width, soma->window.height);
|
||||||
|
soma->renderer->width = soma->window.width;
|
||||||
|
soma->renderer->height = soma->window.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int32 MAX_POLYCUBE_INPUT = 64;
|
||||||
|
const int32 TARGET_FPS = 144;
|
||||||
|
|
||||||
int mainGfx() {
|
int mainGfx() {
|
||||||
Arena *arena = arenaAlloc(Megabytes(128));
|
Arena *arena = arenaAlloc(Megabytes(128));
|
||||||
Arena *solutionsArena = arenaAlloc(Megabytes(128));
|
Arena *solutionsArena = arenaAlloc(Megabytes(128));
|
||||||
|
|
||||||
int winWidth = 800;
|
int32 winWidth = 800;
|
||||||
int winHeight = 600;
|
int32 winHeight = 600;
|
||||||
GLFWwindow *windowHandle = initWindowAndGL(winWidth, winHeight);
|
GLFWwindow *windowHandle = initWindowAndGL(winWidth, winHeight);
|
||||||
if (!windowHandle) {
|
if (!windowHandle) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Scene mainScene = createScene(arena);
|
Scene mainScene = createScene(arena);
|
||||||
Renderer renderer = createRenderer(arena, &mainScene);
|
Camera cam = createCamera(winWidth, winHeight);
|
||||||
Frame mainFrame = createFrame(arena, winWidth, winHeight, 0, 0);
|
Renderer renderer = createRenderer(arena, &mainScene, &cam, createSceneGraphNode(&mainScene));
|
||||||
|
|
||||||
UI_Context ui = {
|
solidColorShader = createShader(
|
||||||
.hotNode = 0,
|
s("./assets/shaders/2d-solid.vertex.glsl"),
|
||||||
.nextId = 1,
|
s("./assets/shaders/2d-solid.fragment.glsl"));
|
||||||
.cursorIsPointer = false,
|
|
||||||
.input = NULL,
|
phongShader = createShader(
|
||||||
.prevInput = NULL,
|
s("./assets/shaders/phong-solid.vertex.glsl"),
|
||||||
.renderer = &renderer,
|
s("./assets/shaders/phong-solid.fragment.glsl"));
|
||||||
};
|
|
||||||
|
cubeMesh = createMesh("./assets/models/cube.obj");
|
||||||
|
|
||||||
|
renderer.solidShader = &solidColorShader;
|
||||||
|
renderer.phongShader = &phongShader;
|
||||||
|
renderer.cubeMesh = &cubeMesh;
|
||||||
|
|
||||||
|
UI_Context ui = ui_initContext(arena, &renderer);
|
||||||
|
|
||||||
Soma soma = {
|
Soma soma = {
|
||||||
.window = {
|
.window = {
|
||||||
.width = 800,
|
.width = winWidth,
|
||||||
.height = 600,
|
.height = winHeight,
|
||||||
.handle = windowHandle,
|
.handle = windowHandle,
|
||||||
.cursors = {
|
.cursors = {
|
||||||
.pointer = glfwCreateStandardCursor(GLFW_HAND_CURSOR),
|
.pointer = glfwCreateStandardCursor(GLFW_HAND_CURSOR),
|
||||||
@@ -828,8 +451,8 @@ int mainGfx() {
|
|||||||
},
|
},
|
||||||
.scene = &mainScene,
|
.scene = &mainScene,
|
||||||
.renderer = &renderer,
|
.renderer = &renderer,
|
||||||
.polycubeInput = PushListZero(arena, PolycubeInputList, 64),
|
.polycubeInput = PushListZero(arena, PolycubeInputList, MAX_POLYCUBE_INPUT),
|
||||||
.polycubes = PushListZero(arena, HandleList, 64),
|
.polycubes = PushListZero(arena, HandleList, MAX_POLYCUBE_INPUT),
|
||||||
.puzzleDims = {3, 3, 3},
|
.puzzleDims = {3, 3, 3},
|
||||||
.solveTaskCtx = (SolveTaskCtx){
|
.solveTaskCtx = (SolveTaskCtx){
|
||||||
.arena = arenaAlloc(Megabytes(128)),
|
.arena = arenaAlloc(Megabytes(128)),
|
||||||
@@ -843,33 +466,19 @@ int mainGfx() {
|
|||||||
.displayingSolutions = false,
|
.displayingSolutions = false,
|
||||||
.displayedSolution = -1,
|
.displayedSolution = -1,
|
||||||
.isInitialState = true,
|
.isInitialState = true,
|
||||||
.light = createEntity(&mainScene),
|
|
||||||
.camera = mainFrame.cam,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
Shader solid_texture_shader = createShader(
|
|
||||||
"./assets/shaders/2d.vertex.glsl"_s,
|
|
||||||
"./assets/shaders/2d-tex.fragment.glsl"_s);
|
|
||||||
*/
|
|
||||||
|
|
||||||
solidColorShader = createShader(
|
|
||||||
s("./assets/shaders/2d-solid.vertex.glsl"),
|
|
||||||
s("./assets/shaders/2d-solid.fragment.glsl"));
|
|
||||||
|
|
||||||
phongShader = createShader(
|
|
||||||
s("./assets/shaders/phong-solid.vertex.glsl"),
|
|
||||||
s("./assets/shaders/phong-solid.fragment.glsl"));
|
|
||||||
|
|
||||||
cubeMesh = createMesh("./assets/models/cube.obj");
|
|
||||||
wallTex = createTexture("./assets/textures/brick-wall.jpg");
|
|
||||||
|
|
||||||
VoxelSpaceReprList stdSoma = AsList(VoxelSpaceReprList, STD_SOMA);
|
VoxelSpaceReprList stdSoma = AsList(VoxelSpaceReprList, STD_SOMA);
|
||||||
for (EachIn(stdSoma, i)) {
|
for (EachIn(stdSoma, i)) {
|
||||||
VoxelSpace voxelSpace = { stdSoma.data[i], 3, 3, 3 };
|
VoxelSpace voxelSpace = {
|
||||||
|
.space=stdSoma.data[i],
|
||||||
|
.dim_x=soma.puzzleDims[0],
|
||||||
|
.dim_y=soma.puzzleDims[1],
|
||||||
|
.dim_z=soma.puzzleDims[2],
|
||||||
|
};
|
||||||
RLVector4 color = colorFromIndex(i);
|
RLVector4 color = colorFromIndex(i);
|
||||||
PolycubeInput input = (PolycubeInput){ voxelSpace, color };
|
PolycubeInput input = (PolycubeInput){ .repr=voxelSpace, .color=color };
|
||||||
ListAppend(soma.polycubeInput, input);
|
ListAppend(soma.polycubeInput, input);
|
||||||
cullEmptySpace(&voxelSpace);
|
cullEmptySpace(&voxelSpace);
|
||||||
uint32 polycubeGraphNodeHandle = createPolycubeFromRepr(soma.scene, &voxelSpace, color);
|
uint32 polycubeGraphNodeHandle = createPolycubeFromRepr(soma.scene, &voxelSpace, color);
|
||||||
@@ -877,27 +486,33 @@ int mainGfx() {
|
|||||||
sceneNodeAddNode(renderer.scene, renderer.scene->sceneRoot, polycubeGraphNodeHandle);
|
sceneNodeAddNode(renderer.scene, renderer.scene->sceneRoot, polycubeGraphNodeHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(dledda): only actually create and render one solution/polycube at a time, save lots of space!
|
cam.pos = (RLVector3){0.0f, 0.0f, 8.0f};
|
||||||
|
cameraLookAt(&cam, 0.0f, 0.0f, 0.0f);
|
||||||
soma.state.camera->pos = (RLVector3){0.0f, 0.0f, 8.0f};
|
|
||||||
cameraLookAt(soma.state.camera, 0.0f, 0.0f, 0.0f);
|
|
||||||
|
|
||||||
SceneGraphNode *referencePolycube = getSceneGraphNode(soma.scene, soma.polycubes.data[0]);
|
SceneGraphNode *referencePolycube = getSceneGraphNode(soma.scene, soma.polycubes.data[0]);
|
||||||
Matrix worldInverse = MatrixInvert(referencePolycube->world);
|
Matrix worldInverse = MatrixInvert(referencePolycube->world);
|
||||||
soma.state.rotAxisY = Vector3Normalize((RLVector3){worldInverse.m4, worldInverse.m5, worldInverse.m6});
|
soma.state.rotAxisY = Vector3Normalize((RLVector3){worldInverse.m4, worldInverse.m5, worldInverse.m6});
|
||||||
RLVector3 eyes = Vector3Normalize(Vector3Subtract(soma.state.camera->pos, referencePolycube->translation));
|
RLVector3 eyes = Vector3Normalize(Vector3Subtract(cam.pos, referencePolycube->translation));
|
||||||
soma.state.rotAxisX = Vector3Normalize(Vector3CrossProduct(eyes, soma.state.rotAxisY));
|
soma.state.rotAxisX = Vector3Normalize(Vector3CrossProduct(eyes, soma.state.rotAxisY));
|
||||||
|
|
||||||
getSceneGraphNode(&mainScene, soma.state.light)->translation = (RLVector3){4.0f, 6.0f, 24.0f};
|
getSceneGraphNode(&mainScene, renderer.light)->translation = (RLVector3){4.0f, 6.0f, 24.0f};
|
||||||
|
|
||||||
real64 lastFrame = glfwGetTime();
|
real64 lastFrame = glfwGetTime();
|
||||||
real64 timeDelta = 1.0f/60.0f;
|
real64 timeDelta = 1.0f / TARGET_FPS;
|
||||||
|
real64 frameStart = lastFrame;
|
||||||
|
|
||||||
|
Input lastInput = {0};
|
||||||
|
Input currInput = {0};
|
||||||
while (!glfwWindowShouldClose(soma.window.handle)) {
|
while (!glfwWindowShouldClose(soma.window.handle)) {
|
||||||
real64 frameStart = glfwGetTime();
|
|
||||||
|
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
soma.state.input = getCurrentInput(soma.window.handle);
|
|
||||||
|
lastInput = currInput;
|
||||||
|
currInput = getCurrentInput(soma.window.handle);
|
||||||
|
|
||||||
|
ui.prevInput = &lastInput;
|
||||||
|
ui.input = &currInput;
|
||||||
|
|
||||||
|
updateWindow(&soma);
|
||||||
|
|
||||||
processInput(&soma, &ui);
|
processInput(&soma, &ui);
|
||||||
|
|
||||||
@@ -912,28 +527,33 @@ int mainGfx() {
|
|||||||
arenaFreeFrom(soma.solveTaskCtx.arena, 0);
|
arenaFreeFrom(soma.solveTaskCtx.arena, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePolycubeDisplay(arena, &soma);
|
updatePolycubeDisplay(&soma);
|
||||||
|
|
||||||
updateViewportFromFrame(soma.window.width, soma.window.height, &mainFrame);
|
|
||||||
recalcScene(soma.scene);
|
recalcScene(soma.scene);
|
||||||
|
|
||||||
renderBegin(&renderer);
|
renderBegin(&renderer);
|
||||||
|
|
||||||
uiPass(&soma, &ui);
|
ui_begin(&ui);
|
||||||
|
somaUIPass(&soma, &ui);
|
||||||
|
ui_end(&ui);
|
||||||
|
|
||||||
if (ui.cursorIsPointer) {
|
if (ui.cursorIsPointer) {
|
||||||
glfwSetCursor(soma.window.handle, soma.window.cursors.pointer);
|
glfwSetCursor(soma.window.handle, soma.window.cursors.pointer);
|
||||||
} else {
|
} else {
|
||||||
glfwSetCursor(soma.window.handle, soma.window.cursors.arrow);
|
glfwSetCursor(soma.window.handle, soma.window.cursors.arrow);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderEnd(&soma, &renderer);
|
renderEnd(&renderer);
|
||||||
|
|
||||||
|
glfwSwapBuffers(soma.window.handle);
|
||||||
|
|
||||||
real64 frameEnd = glfwGetTime();
|
real64 frameEnd = glfwGetTime();
|
||||||
real64 frameTime = frameEnd - frameStart;
|
real64 frameTime = frameEnd - frameStart;
|
||||||
lastFrame = frameStart;
|
lastFrame = frameStart;
|
||||||
// print("FPS: %.7f\n", 1 / frameTime);
|
|
||||||
|
|
||||||
glfwSwapBuffers(soma.window.handle);
|
//println("FPS: %.7f", 1/(frameTime));
|
||||||
|
|
||||||
|
frameStart = glfwGetTime();
|
||||||
|
|
||||||
soma.prevState = soma.state;
|
soma.prevState = soma.state;
|
||||||
soma.state.isInitialState = false;
|
soma.state.isInitialState = false;
|
||||||
|
|||||||
155
src/render.c
Normal file
155
src/render.c
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
#include "render.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
RenderObjects_Rectangle createRectangleObjects(Arena *arena, size_t count) {
|
||||||
|
RenderObjects_Rectangle result = {0};
|
||||||
|
result.count = count;
|
||||||
|
|
||||||
|
result.p0 = PushFullList(arena, RLVec2List, count);
|
||||||
|
result.p1 = PushFullList(arena, RLVec2List, count);
|
||||||
|
result.color = PushFullList(arena, RLVec4List, count);
|
||||||
|
result.borderRadius = PushFullList(arena, FloatList, count);
|
||||||
|
result.borderThickness = PushFullList(arena, FloatList, count);
|
||||||
|
result.edgeSoftness = PushFullList(arena, FloatList, count);
|
||||||
|
|
||||||
|
glGenVertexArrays(1, &result.vao);
|
||||||
|
|
||||||
|
glGenBuffers(1, &result.p0BufferId);
|
||||||
|
glGenBuffers(1, &result.p1BufferId);
|
||||||
|
glGenBuffers(1, &result.colorBufferId);
|
||||||
|
glGenBuffers(1, &result.borderRadiusBufferId);
|
||||||
|
glGenBuffers(1, &result.borderThicknessBufferId);
|
||||||
|
glGenBuffers(1, &result.edgeSoftnessBufferId);
|
||||||
|
|
||||||
|
glBindVertexArray(result.vao);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, result.p0BufferId);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, result.p0.length * sizeof(RLVec2List_underlying), 0, GL_DYNAMIC_DRAW);
|
||||||
|
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(RLVec2List_underlying), NULL);
|
||||||
|
glVertexAttribDivisor(0, 1);
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, result.p1BufferId);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, result.p1.length * sizeof(RLVec2List_underlying), 0, GL_DYNAMIC_DRAW);
|
||||||
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(RLVec2List_underlying), NULL);
|
||||||
|
glVertexAttribDivisor(1, 1);
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, result.colorBufferId);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, result.color.length * sizeof(RLVec4List_underlying), 0, GL_DYNAMIC_DRAW);
|
||||||
|
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(RLVec4List_underlying), NULL);
|
||||||
|
glVertexAttribDivisor(2, 1);
|
||||||
|
glEnableVertexAttribArray(2);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, result.borderRadiusBufferId);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, result.borderRadius.length * sizeof(FloatList_underlying), 0, GL_DYNAMIC_DRAW);
|
||||||
|
glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, sizeof(FloatList_underlying), NULL);
|
||||||
|
glVertexAttribDivisor(3, 1);
|
||||||
|
glEnableVertexAttribArray(3);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, result.borderThicknessBufferId);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, result.borderThickness.length * sizeof(FloatList_underlying), 0, GL_DYNAMIC_DRAW);
|
||||||
|
glVertexAttribPointer(4, 1, GL_FLOAT, GL_FALSE, sizeof(FloatList_underlying), NULL);
|
||||||
|
glVertexAttribDivisor(4, 1);
|
||||||
|
glEnableVertexAttribArray(4);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, result.edgeSoftnessBufferId);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, result.edgeSoftness.length * sizeof(FloatList_underlying), 0, GL_DYNAMIC_DRAW);
|
||||||
|
glVertexAttribPointer(5, 1, GL_FLOAT, GL_FALSE, sizeof(FloatList_underlying), NULL);
|
||||||
|
glVertexAttribDivisor(5, 1);
|
||||||
|
glEnableVertexAttribArray(5);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateRectangleObjectBuffers(Renderer *r) {
|
||||||
|
glBindVertexArray(r->rects.vao);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, r->rects.p0BufferId);
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, 0, r->rects.p0.length * sizeof(RLVec2List_underlying), r->rects.p0.data);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, r->rects.p1BufferId);
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, 0, r->rects.p1.length * sizeof(RLVec2List_underlying), r->rects.p1.data);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, r->rects.colorBufferId);
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, 0, r->rects.color.length * sizeof(RLVec4List_underlying), r->rects.color.data);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, r->rects.borderRadiusBufferId);
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, 0, r->rects.borderRadius.length * sizeof(FloatList_underlying), r->rects.borderRadius.data);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, r->rects.borderThicknessBufferId);
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, 0, r->rects.borderThickness.length * sizeof(FloatList_underlying), r->rects.borderThickness.data);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, r->rects.edgeSoftnessBufferId);
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, 0, r->rects.edgeSoftness.length * sizeof(FloatList_underlying), r->rects.edgeSoftness.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
Renderer createRenderer(Arena *arena, Scene *scene, Camera *cam, int32 light) {
|
||||||
|
return (Renderer){
|
||||||
|
.scene = scene,
|
||||||
|
.light = light,
|
||||||
|
.camera = cam,
|
||||||
|
.rects = createRectangleObjects(arena, 1024),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void renderBegin(Renderer *r) {
|
||||||
|
r->rects.p0.length = 0;
|
||||||
|
r->rects.p1.length = 0;
|
||||||
|
r->rects.color.length = 0;
|
||||||
|
r->rects.borderRadius.length = 0;
|
||||||
|
r->rects.borderThickness.length = 0;
|
||||||
|
r->rects.edgeSoftness.length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void renderEnd(Renderer *r) {
|
||||||
|
// 3D Entities
|
||||||
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
glUseProgram(r->phongShader->progId);
|
||||||
|
setUniformMat4fv(r->phongShader, "projection", &r->camera->proj);
|
||||||
|
setUniformMat4fv(r->phongShader, "view", &r->camera->view);
|
||||||
|
|
||||||
|
SceneGraphNode *lightGraphNode = getSceneGraphNode(r->scene, r->light);
|
||||||
|
setUniform3fv(r->phongShader, "light_pos", &lightGraphNode->translation);
|
||||||
|
setUniform3fv(r->phongShader, "camera", &r->camera->pos);
|
||||||
|
|
||||||
|
glBindVertexArray(r->cubeMesh->vao);
|
||||||
|
|
||||||
|
// TODO(djledda): sort by mesh, texture, etc.
|
||||||
|
|
||||||
|
int model_uniform = getUniformLocation(r->phongShader, "model");
|
||||||
|
int solid_color_uniform = getUniformLocation(r->phongShader, "solid_color");
|
||||||
|
for (EachIn(r->scene->entities, i)) {
|
||||||
|
Entity *entity = &r->scene->entities.data[i];
|
||||||
|
if (entity->flags & EntityFlags_Render && entity->flags & EntityFlags_Visible) {
|
||||||
|
setUniform4fvByLoc(solid_color_uniform, &entity->color);
|
||||||
|
setUniformMat4fvByLoc(model_uniform, &getSceneGraphNode(r->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
|
||||||
|
glUseProgram(r->solidShader->progId);
|
||||||
|
|
||||||
|
updateRectangleObjectBuffers(r);
|
||||||
|
|
||||||
|
Matrix ortho = MatrixOrtho(0.0, r->width, r->height, 0.0, -1.0, 1.0);
|
||||||
|
setUniformMat4fv(r->solidShader, "projection", &ortho);
|
||||||
|
|
||||||
|
glBindVertexArray(r->rects.vao);
|
||||||
|
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, r->rects.p0.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rendererPlaceRectangle(Renderer *r, real32 x, real32 y, real32 width, real32 height, RLVector4 color, real32 borderRadius, real32 borderThickness) {
|
||||||
|
ListAppend(r->rects.p0, ((RLVector2){ x, y }));
|
||||||
|
ListAppend(r->rects.p1, ((RLVector2){ x + width, y + height }));
|
||||||
|
ListAppend(r->rects.color, color);
|
||||||
|
ListAppend(r->rects.borderRadius, borderRadius);
|
||||||
|
ListAppend(r->rects.borderThickness, borderThickness);
|
||||||
|
ListAppend(r->rects.edgeSoftness, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
59
src/render.h
Normal file
59
src/render.h
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
#ifndef RENDER_H
|
||||||
|
#define RENDER_H
|
||||||
|
|
||||||
|
#include "gfx/Shader.h"
|
||||||
|
#include "gfx/gfx.h"
|
||||||
|
#include "world/world.h"
|
||||||
|
|
||||||
|
DefineList(RLVector2, RLVec2);
|
||||||
|
DefineList(RLVector4, RLVec4);
|
||||||
|
DefineList(real32, Float);
|
||||||
|
|
||||||
|
typedef struct RenderObjects_Rectangle RenderObjects_Rectangle;
|
||||||
|
struct RenderObjects_Rectangle {
|
||||||
|
uint32 vao;
|
||||||
|
uint64 count;
|
||||||
|
|
||||||
|
RLVec2List p0;
|
||||||
|
uint32 p0BufferId;
|
||||||
|
|
||||||
|
RLVec2List p1;
|
||||||
|
uint32 p1BufferId;
|
||||||
|
|
||||||
|
RLVec4List color;
|
||||||
|
uint32 colorBufferId;
|
||||||
|
|
||||||
|
FloatList borderRadius;
|
||||||
|
uint32 borderRadiusBufferId;
|
||||||
|
|
||||||
|
FloatList borderThickness;
|
||||||
|
uint32 borderThicknessBufferId;
|
||||||
|
|
||||||
|
FloatList edgeSoftness;
|
||||||
|
uint32 edgeSoftnessBufferId;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Renderer Renderer;
|
||||||
|
struct Renderer {
|
||||||
|
RenderObjects_Rectangle rects;
|
||||||
|
|
||||||
|
Shader *phongShader;
|
||||||
|
Shader *solidShader;
|
||||||
|
|
||||||
|
int32 width;
|
||||||
|
int32 height;
|
||||||
|
|
||||||
|
Scene *scene;
|
||||||
|
Camera *camera;
|
||||||
|
/** SceneGraphNode handle */
|
||||||
|
int32 light;
|
||||||
|
Mesh *cubeMesh;
|
||||||
|
};
|
||||||
|
|
||||||
|
Renderer createRenderer(Arena *arena, Scene *scene, Camera *cam, int32 light);
|
||||||
|
void renderBegin(Renderer *r);
|
||||||
|
void renderEnd(Renderer *r);
|
||||||
|
void rendererPlaceRectangle(Renderer *r, real32 x, real32 y, real32 width, real32 height, RLVector4 color, real32 borderRadius, real32 borderThickness);
|
||||||
|
void updateRectangleObjectBuffers(Renderer *r);
|
||||||
|
|
||||||
|
#endif
|
||||||
118
src/ui.c
Normal file
118
src/ui.c
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
#include "ui.h"
|
||||||
|
#include "GLFW/glfw3.h"
|
||||||
|
|
||||||
|
static bool glfwMouse(GLFWwindow *window, int mouseBtnCode) {
|
||||||
|
switch (glfwGetMouseButton(window, mouseBtnCode)) {
|
||||||
|
case GLFW_RELEASE: return false;
|
||||||
|
case GLFW_PRESS: return true;
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool glfwKey(GLFWwindow *window, int keyCode) {
|
||||||
|
switch (glfwGetKey(window, keyCode)) {
|
||||||
|
case GLFW_RELEASE: return false;
|
||||||
|
case GLFW_PRESS: return true;
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Input getCurrentInput(GLFWwindow *window) {
|
||||||
|
Input input = {0};
|
||||||
|
|
||||||
|
input.keyboard.escape = glfwKey(window, GLFW_KEY_ESCAPE);
|
||||||
|
input.keyboard.enter = glfwKey(window, GLFW_KEY_ENTER);
|
||||||
|
input.keyboard.space = glfwKey(window, GLFW_KEY_SPACE);
|
||||||
|
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.y = glfwKey(window, GLFW_KEY_Y);
|
||||||
|
input.keyboard.z = glfwKey(window, GLFW_KEY_Z);
|
||||||
|
|
||||||
|
input.mouse.btnLeft = glfwMouse(window, GLFW_MOUSE_BUTTON_LEFT);
|
||||||
|
input.mouse.btnRight = glfwMouse(window, GLFW_MOUSE_BUTTON_RIGHT);
|
||||||
|
input.mouse.btnMiddle = glfwMouse(window, GLFW_MOUSE_BUTTON_MIDDLE);
|
||||||
|
|
||||||
|
real64 mouseX;
|
||||||
|
real64 mouseY;
|
||||||
|
glfwGetCursorPos(window, &mouseX, &mouseY);
|
||||||
|
input.mouse.point = (RLVector2){(real32)mouseX, (real32)mouseY};
|
||||||
|
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
UI_Context ui_initContext(Arena *arena, Renderer *renderer) {
|
||||||
|
UI_RectList list = PushListZero(arena, UI_RectList, Thousand(10));
|
||||||
|
ListAppend(list, ((UI_Rect){0})); // empty item
|
||||||
|
return (UI_Context){
|
||||||
|
.rects=list,
|
||||||
|
.hotNode = 0,
|
||||||
|
.nextId = 1,
|
||||||
|
.cursorIsPointer = false,
|
||||||
|
.input = NULL,
|
||||||
|
.prevInput = NULL,
|
||||||
|
.renderer = renderer,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void ui_begin(UI_Context *ui) {
|
||||||
|
ui->cursorIsPointer = false;
|
||||||
|
ui->nextId = 1;
|
||||||
|
ui->prevHotNode = ui->hotNode;
|
||||||
|
ui->hotNode = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ui_end(UI_Context *ui) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool pointInRect(real32 x, real32 y, UI_Rect rect) {
|
||||||
|
return x > rect.x && y > rect.y && x < (rect.x + rect.width) && y < (rect.y + rect.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ui_openElement(UI_Context *ui, UI_Rect rect) {
|
||||||
|
ListAppend(ui->rects, rect);
|
||||||
|
int32 nextHandle = ui->rects.length - 1;
|
||||||
|
|
||||||
|
UI_Rect *nextRect = &ui->rects.data[nextHandle];
|
||||||
|
UI_Rect *currRect = &ui->rects.data[ui->currRect];
|
||||||
|
|
||||||
|
nextRect->parent = ui->currRect;
|
||||||
|
nextRect->nextSibling = currRect->firstChild;
|
||||||
|
currRect->firstChild = nextHandle;
|
||||||
|
|
||||||
|
ui->currRect = nextHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ui_closeElement(UI_Context *ui) {
|
||||||
|
ui->currRect = ui->rects.data[ui->currRect].parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the checkbox was clicked
|
||||||
|
*/
|
||||||
|
bool ui_checkboxRect(UI_Context *ui, bool *value, UI_Rect rect) {
|
||||||
|
uint32 id = ui->nextId++;
|
||||||
|
bool clicked = false;
|
||||||
|
if (pointInRect(ui->input->mouse.point.x, ui->input->mouse.point.y, rect)) {
|
||||||
|
ui->cursorIsPointer = true;
|
||||||
|
if (ui->prevHotNode == id && !ui->input->mouse.btnLeft) {
|
||||||
|
*value = !*value;
|
||||||
|
clicked = true;
|
||||||
|
} else if (ui->input->mouse.btnLeft && (!ui->prevInput->mouse.btnLeft || ui->prevHotNode == id)) {
|
||||||
|
ui->hotNode = id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (*value) {
|
||||||
|
rect.borderRadius = 5;
|
||||||
|
rect.borderThickness = 0;
|
||||||
|
DJUI(ui, rect);
|
||||||
|
} else {
|
||||||
|
rect.borderRadius = 5;
|
||||||
|
rect.borderThickness = 2;
|
||||||
|
rect.color = COLOR_WHITE;
|
||||||
|
DJUI(ui, rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
return clicked;
|
||||||
|
}
|
||||||
104
src/ui.h
Normal file
104
src/ui.h
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
#ifndef UI_H
|
||||||
|
#define UI_H
|
||||||
|
|
||||||
|
#include "render.h"
|
||||||
|
#include "lib/djstdlib/core.h"
|
||||||
|
#include "GLFW/glfw3.h"
|
||||||
|
#include "lib/djstdlib/core.h"
|
||||||
|
|
||||||
|
typedef struct Input Input;
|
||||||
|
struct Input {
|
||||||
|
struct {
|
||||||
|
bool escape;
|
||||||
|
bool enter;
|
||||||
|
bool space;
|
||||||
|
bool lshift;
|
||||||
|
bool x;
|
||||||
|
bool y;
|
||||||
|
bool z;
|
||||||
|
bool w;
|
||||||
|
} keyboard;
|
||||||
|
struct {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
real32 x;
|
||||||
|
real32 y;
|
||||||
|
};
|
||||||
|
RLVector2 point;
|
||||||
|
};
|
||||||
|
bool btnLeft;
|
||||||
|
bool btnRight;
|
||||||
|
bool btnMiddle;
|
||||||
|
} mouse;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum UI_Rect_LayoutFlag {
|
||||||
|
UI_Rect_LayoutFlag_Width_Grow=1<<0, // Default is fixed
|
||||||
|
UI_Rect_LayoutFlag_Height_Grow=1<<1,
|
||||||
|
UI_Rect_LayoutFlag_LayoutDirection_Vertical=1<<2, // Default is horizontal
|
||||||
|
// ..
|
||||||
|
UI_Rect_LayoutFlag_COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct UI_Rect UI_Rect;
|
||||||
|
struct UI_Rect {
|
||||||
|
uint64 layoutFlags;
|
||||||
|
|
||||||
|
int32 parent;
|
||||||
|
int32 firstChild;
|
||||||
|
int32 nextSibling;
|
||||||
|
|
||||||
|
real32 xOffset;
|
||||||
|
real32 yOffset;
|
||||||
|
|
||||||
|
real32 width;
|
||||||
|
real32 minWidth;
|
||||||
|
real32 maxWidth;
|
||||||
|
|
||||||
|
real32 height;
|
||||||
|
real32 minHeight;
|
||||||
|
real32 maxHeight;
|
||||||
|
|
||||||
|
real32 borderRadius;
|
||||||
|
real32 borderThickness;
|
||||||
|
|
||||||
|
RLVector4 color;
|
||||||
|
RLVector4 borderColor;
|
||||||
|
|
||||||
|
real32 childGap;
|
||||||
|
|
||||||
|
real32 x;
|
||||||
|
real32 y;
|
||||||
|
real32 resolvedWidth;
|
||||||
|
real32 resolvedHeight;
|
||||||
|
};
|
||||||
|
DefineList(UI_Rect, UI_Rect);
|
||||||
|
|
||||||
|
typedef struct UI_Context UI_Context;
|
||||||
|
struct UI_Context {
|
||||||
|
UI_RectList rects;
|
||||||
|
int32 nextId;
|
||||||
|
int32 hotNode;
|
||||||
|
int32 prevHotNode;
|
||||||
|
Renderer *renderer;
|
||||||
|
|
||||||
|
Input *prevInput;
|
||||||
|
Input *input;
|
||||||
|
bool cursorIsPointer;
|
||||||
|
|
||||||
|
int32 currRect;
|
||||||
|
};
|
||||||
|
|
||||||
|
void ui_begin(UI_Context *ui);
|
||||||
|
void ui_end(UI_Context *ui);
|
||||||
|
UI_Context ui_initContext(Arena *arena, Renderer *renderer);
|
||||||
|
Input getCurrentInput(GLFWwindow *window);
|
||||||
|
void ui_resolve();
|
||||||
|
void ui_rect(UI_Context *ui, UI_Rect rect);
|
||||||
|
bool ui_checkboxRect(UI_Context *ui, bool *value, UI_Rect rect);
|
||||||
|
void ui_openElement(UI_Context *ui, UI_Rect rect);
|
||||||
|
void ui_closeElement(UI_Context *ui);
|
||||||
|
|
||||||
|
#define DJUI(ui, rect) DeferLoop(ui_openElement((ui), (rect)), ui_closeElement((ui)))
|
||||||
|
|
||||||
|
#endif
|
||||||
26
src/world/camera.c
Normal file
26
src/world/camera.c
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#include "camera.h"
|
||||||
|
#include "../lib/raymath.h"
|
||||||
|
|
||||||
|
Camera createCamera(int32 width, int32 height) {
|
||||||
|
return (Camera){
|
||||||
|
.view = (Matrix){0},
|
||||||
|
.proj = MatrixPerspective(DEG2RAD * 45.0f, (real32)width/(real32)height, 0.1f, 100.0f),
|
||||||
|
.pos = (RLVector3){0},
|
||||||
|
.up = (RLVector3){0,1,0},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void cameraSetAspect(Camera *c, int32 width, int32 height) {
|
||||||
|
real32 aspectRatio = (real32)width/(real32)height;
|
||||||
|
c->proj = MatrixPerspective(DEG2RAD * 45.0f, aspectRatio, 0.1f, 100.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cameraLookAt(Camera *c, float x, float y, float z) {
|
||||||
|
c->target = (RLVector3){x, y, z};
|
||||||
|
c->view = MatrixLookAt(c->pos, c->target, c->up);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cameraSetUp(Camera *c, real32 up_x, real32 up_y, real32 up_z) {
|
||||||
|
c->up = (RLVector3){up_x, up_y, up_z};
|
||||||
|
}
|
||||||
|
|
||||||
21
src/world/camera.h
Normal file
21
src/world/camera.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#ifndef CAMERA_H
|
||||||
|
#define CAMERA_H
|
||||||
|
|
||||||
|
#include "../lib/djstdlib/core.h"
|
||||||
|
#include "../lib/raymath.h"
|
||||||
|
|
||||||
|
typedef struct Camera Camera;
|
||||||
|
struct Camera {
|
||||||
|
Matrix view;
|
||||||
|
Matrix proj;
|
||||||
|
RLVector3 pos;
|
||||||
|
RLVector3 up;
|
||||||
|
RLVector3 target;
|
||||||
|
};
|
||||||
|
|
||||||
|
Camera createCamera(int32 width, int32 height);
|
||||||
|
void cameraSetAspect(Camera *c, int32 width, int32 height);
|
||||||
|
void cameraLookAt(Camera *c, float x, float y, float z);
|
||||||
|
void cameraSetUp(Camera *c, real32 up_x, real32 up_y, real32 up_z);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -37,7 +37,6 @@ int32 createSceneGraphNode(Scene *s) {
|
|||||||
int32 createEntity(Scene *s) {
|
int32 createEntity(Scene *s) {
|
||||||
Entity *newEntity;
|
Entity *newEntity;
|
||||||
int32 newEntityHandle;
|
int32 newEntityHandle;
|
||||||
println("%d", s->nextFreeEntity);
|
|
||||||
if (s->nextFreeEntity) {
|
if (s->nextFreeEntity) {
|
||||||
newEntityHandle = s->nextFreeEntity;
|
newEntityHandle = s->nextFreeEntity;
|
||||||
newEntity = getEntity(s, newEntityHandle);
|
newEntity = getEntity(s, newEntityHandle);
|
||||||
@@ -98,36 +97,36 @@ void recalcScene(Scene *s) {
|
|||||||
recalcSceneGraphNode(s, s->sceneRoot);
|
recalcSceneGraphNode(s, s->sceneRoot);
|
||||||
}
|
}
|
||||||
|
|
||||||
function void removeSceneGraphNodeRecursive(Scene *s, int32 graphNodeHandle, bool deletingParent) {
|
static void removeSceneGraphNodeRecursive(Scene *s, int32 deletedNodeHandle, bool deletingParent) {
|
||||||
if (!graphNodeHandle) return;
|
if (!deletedNodeHandle) return;
|
||||||
SceneGraphNode *graphNode = getSceneGraphNode(s, graphNodeHandle);
|
SceneGraphNode *deletedNode = getSceneGraphNode(s, deletedNodeHandle);
|
||||||
|
|
||||||
int32 nextChild = graphNode->firstChild;
|
int32 nextChild = deletedNode->firstChild;
|
||||||
while (nextChild) {
|
while (nextChild) {
|
||||||
int32 sibling = getSceneGraphNode(s, nextChild)->nextSibling;
|
int32 sibling = getSceneGraphNode(s, nextChild)->nextSibling;
|
||||||
removeSceneGraphNodeRecursive(s, nextChild, true);
|
removeSceneGraphNodeRecursive(s, nextChild, true);
|
||||||
nextChild = sibling;
|
nextChild = sibling;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (graphNode->entityHandle) {
|
if (deletedNode->entityHandle) {
|
||||||
Entity *entity = getEntity(s, graphNode->entityHandle);
|
Entity *entity = getEntity(s, deletedNode->entityHandle);
|
||||||
*entity = (Entity){0};
|
*entity = (Entity){0};
|
||||||
if (s->nextFreeEntity) {
|
if (s->nextFreeEntity) {
|
||||||
entity->next = s->nextFreeEntity;
|
entity->next = s->nextFreeEntity;
|
||||||
}
|
}
|
||||||
s->nextFreeEntity = graphNode->entityHandle;
|
s->nextFreeEntity = deletedNode->entityHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->nextFreeNode) {
|
if (s->nextFreeNode) {
|
||||||
graphNode->next = s->nextFreeNode;
|
deletedNode->next = s->nextFreeNode;
|
||||||
}
|
}
|
||||||
s->nextFreeNode = graphNodeHandle;
|
s->nextFreeNode = deletedNodeHandle;
|
||||||
|
|
||||||
if (!deletingParent && graphNode->parentHandle) {
|
if (!deletingParent && deletedNode->parentHandle) {
|
||||||
SceneGraphNode *parentNode = getSceneGraphNode(s, graphNode->parentHandle);
|
SceneGraphNode *parentNode = getSceneGraphNode(s, deletedNode->parentHandle);
|
||||||
if (parentNode->firstChild == graphNodeHandle) {
|
if (parentNode->firstChild == deletedNodeHandle) {
|
||||||
if (graphNode->nextSibling) {
|
if (deletedNode->nextSibling) {
|
||||||
parentNode->firstChild = graphNode->nextSibling;
|
parentNode->firstChild = deletedNode->nextSibling;
|
||||||
} else {
|
} else {
|
||||||
parentNode->firstChild = 0;
|
parentNode->firstChild = 0;
|
||||||
}
|
}
|
||||||
@@ -136,20 +135,21 @@ function void removeSceneGraphNodeRecursive(Scene *s, int32 graphNodeHandle, boo
|
|||||||
int32 nextSibling = getSceneGraphNode(s, parentNode->firstChild)->nextSibling;
|
int32 nextSibling = getSceneGraphNode(s, parentNode->firstChild)->nextSibling;
|
||||||
while (nextSibling) {
|
while (nextSibling) {
|
||||||
SceneGraphNode *siblingNode = getSceneGraphNode(s, nextSibling);
|
SceneGraphNode *siblingNode = getSceneGraphNode(s, nextSibling);
|
||||||
if (nextSibling == graphNodeHandle) {
|
if (nextSibling == deletedNodeHandle) {
|
||||||
SceneGraphNode *prevSiblingNode = getSceneGraphNode(s, prevSibling);
|
SceneGraphNode *prevSiblingNode = getSceneGraphNode(s, prevSibling);
|
||||||
prevSiblingNode->nextSibling = graphNode->nextSibling;
|
prevSiblingNode->nextSibling = deletedNode->nextSibling;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
prevSibling = nextSibling;
|
||||||
nextSibling = siblingNode->nextSibling;
|
nextSibling = siblingNode->nextSibling;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
graphNode->firstChild = 0;
|
deletedNode->firstChild = 0;
|
||||||
graphNode->parentHandle = 0;
|
deletedNode->parentHandle = 0;
|
||||||
graphNode->entityHandle = 0;
|
deletedNode->entityHandle = 0;
|
||||||
graphNode->nextSibling = 0;
|
deletedNode->nextSibling = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeSceneGraphNode(Scene *s, int32 graphNodeHandle) {
|
void removeSceneGraphNode(Scene *s, int32 graphNodeHandle) {
|
||||||
@@ -168,3 +168,28 @@ void sceneNodeAddNode(Scene *s, int32 parentHandle, int32 childHandle) {
|
|||||||
parentNode->firstChild = childHandle;
|
parentNode->firstChild = childHandle;
|
||||||
childNode->parentHandle = parentHandle;
|
childNode->parentHandle = parentHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void show(Scene *s, uint32 graphNodeHandle) {
|
||||||
|
SceneGraphNode *node = getSceneGraphNode(s, graphNodeHandle);
|
||||||
|
if (node->entityHandle) {
|
||||||
|
getEntity(s, node->entityHandle)->flags |= EntityFlags_Visible;
|
||||||
|
}
|
||||||
|
int32 next = node->firstChild;
|
||||||
|
while (next) {
|
||||||
|
show(s, next);
|
||||||
|
next = getSceneGraphNode(s, next)->nextSibling;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void hide(Scene *s, uint32 graphNodeHandle) {
|
||||||
|
SceneGraphNode *node = getSceneGraphNode(s, graphNodeHandle);
|
||||||
|
if (node->entityHandle) {
|
||||||
|
getEntity(s, node->entityHandle)->flags &= ~EntityFlags_Visible;
|
||||||
|
}
|
||||||
|
int32 next = node->firstChild;
|
||||||
|
while (next) {
|
||||||
|
hide(s, next);
|
||||||
|
next = getSceneGraphNode(s, next)->nextSibling;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
#ifndef SCENE_H
|
||||||
|
#define SCENE_H
|
||||||
|
|
||||||
#include "../gfx/gfx.h"
|
#include "../gfx/gfx.h"
|
||||||
#include "../lib/raymath.h"
|
#include "../lib/raymath.h"
|
||||||
|
|
||||||
@@ -33,10 +36,10 @@ struct SceneGraphNode {
|
|||||||
int32 entityHandle;
|
int32 entityHandle;
|
||||||
int32 parentHandle;
|
int32 parentHandle;
|
||||||
|
|
||||||
// Free list
|
/** Next free in the free list */
|
||||||
int32 next;
|
int32 next;
|
||||||
|
|
||||||
// Children
|
/** Next child in child list in scene hierarchy */
|
||||||
int32 nextSibling;
|
int32 nextSibling;
|
||||||
int32 firstChild;
|
int32 firstChild;
|
||||||
};
|
};
|
||||||
@@ -47,6 +50,7 @@ struct Scene {
|
|||||||
int32 sceneRoot;
|
int32 sceneRoot;
|
||||||
EntityList entities;
|
EntityList entities;
|
||||||
int32 nextFreeEntity;
|
int32 nextFreeEntity;
|
||||||
|
/** @internal */
|
||||||
SceneGraphNodeList graphNodes;
|
SceneGraphNodeList graphNodes;
|
||||||
int32 nextFreeNode;
|
int32 nextFreeNode;
|
||||||
};
|
};
|
||||||
@@ -63,3 +67,7 @@ void removeEntity(Scene *s, int32 entityHandle);
|
|||||||
void removeSceneGraphNode(Scene *s, int32 graphNodeHandle);
|
void removeSceneGraphNode(Scene *s, int32 graphNodeHandle);
|
||||||
void sceneNodeAddNode(Scene *s, int32 recipientNodeHandle, int32 graphNodeHandle);
|
void sceneNodeAddNode(Scene *s, int32 recipientNodeHandle, int32 graphNodeHandle);
|
||||||
SceneGraphNode *getSceneGraphNodeForEntity(Scene *s, int32 entityHandle);
|
SceneGraphNode *getSceneGraphNodeForEntity(Scene *s, int32 entityHandle);
|
||||||
|
void show(Scene *s, uint32 graphNodeHandle);
|
||||||
|
void hide(Scene *s, uint32 graphNodeHandle);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
#include "scene.c"
|
#include "scene.c"
|
||||||
|
#include "camera.c"
|
||||||
|
|||||||
8
src/world/world.h
Normal file
8
src/world/world.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef WORLD_H
|
||||||
|
#define WORLD_H
|
||||||
|
|
||||||
|
#include "scene.h"
|
||||||
|
#include "camera.h"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
Reference in New Issue
Block a user