adding gfx and ui stuff
This commit is contained in:
3
app.c
3
app.c
@@ -1,2 +1,3 @@
|
||||
//#include "./examples/server-chat.c"
|
||||
#include "./examples/http1-1.c"
|
||||
//#include "./examples/http1-1.c"
|
||||
#include "./examples/gfx.c"
|
||||
|
||||
2
build
2
build
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
clang -g -g3 -lm -DOS_LINUX=1 -DENABLE_ASSERT=1 ./app.c -o ./target/app
|
||||
clang -g -g3 -lm -lglfw -lGL -DOS_LINUX=1 -DENABLE_ASSERT=1 ./app.c -o ./target/app
|
||||
|
||||
if [[ $1 == "run" ]] then
|
||||
./target/app
|
||||
|
||||
131
examples/gfx.c
Normal file
131
examples/gfx.c
Normal file
@@ -0,0 +1,131 @@
|
||||
#define DJSTD_BASIC_ENTRY
|
||||
|
||||
#include "../core.c"
|
||||
#include "../gfx/gfx.c"
|
||||
|
||||
typedef struct WindowData WindowData;
|
||||
struct WindowData {
|
||||
Renderer *renderer;
|
||||
};
|
||||
|
||||
void windowOnEvent(OS_WindowEvent *e, OS_Window *window) {
|
||||
switch (e->kind) {
|
||||
case OS_WindowEventKind_Resize: {
|
||||
WindowData *data = (WindowData*)window->userData;
|
||||
data->renderer->width = e->resize.width;
|
||||
data->renderer->height = e->resize.height;
|
||||
break;
|
||||
};
|
||||
default: {
|
||||
break;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void ui_GreenBox(UI_Context *ui, int32 width, int32 height) {
|
||||
UI(.width=width, .height=height, .color=COLOR_GREEN, .padding=UI_PadUniform(10)) {
|
||||
UI(.flags=UI_Flag_HeightGrow | UI_Flag_WidthGrow | UI_Flag_Vertical, .childGap=10) {
|
||||
UI_SetTxtAttr(.fontSize=40, .alignment=UI_TxtAlign_Center);
|
||||
UI_Rect box = UI_RectAttr(.flags=UI_Flag_WidthGrow | UI_Flag_HeightGrow, .color=COLOR_RED);
|
||||
UI_Rect boxHover = box;
|
||||
boxHover.color = COLOR_BLUE;
|
||||
UI_AttachTxtAttr(&box, UI_TxtAttr(.color=COLOR_CYAN));
|
||||
UI_AttachTxtAttr(&boxHover, UI_TxtAttr(.color=COLOR_YELLOW));
|
||||
|
||||
UI(.flags=UI_Flag_HeightGrow | UI_Flag_WidthGrow, .childGap=10) {
|
||||
UI_FromRect(ui_HoverRect(ui, box, boxHover)) {
|
||||
UI_Txt(s("A"));
|
||||
}
|
||||
UI_FromRect(ui_HoverRect(ui, box, boxHover)) {
|
||||
UI_Txt(s("B"));
|
||||
}
|
||||
}
|
||||
|
||||
UI(.flags=UI_Flag_HeightGrow | UI_Flag_WidthGrow, .childGap=10) {
|
||||
UI_FromRect(ui_HoverRect(ui, box, boxHover)) {
|
||||
UI_Txt(s("C"));
|
||||
}
|
||||
UI_FromRect(ui_HoverRect(ui, box, boxHover)) {
|
||||
UI_Txt(s("D"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ui_Main(UI_Context *ui, int32 width, int32 height) {
|
||||
UI(.flags=UI_Flag_HeightGrow | UI_Flag_WidthGrow, .padding=UI_PadUniform(10), .childGap=10) {
|
||||
ui_GreenBox(ui, width, height);
|
||||
ui_GreenBox(ui, width, height);
|
||||
ui_GreenBox(ui, width, height);
|
||||
ui_GreenBox(ui, width, height);
|
||||
ui_GreenBox(ui, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
int djstd_entry(Arena *arena, StringList args) {
|
||||
WindowData windowData = {
|
||||
.renderer=NULL,
|
||||
};
|
||||
|
||||
Arena *uiArena = arenaAlloc(Megabytes(128));
|
||||
|
||||
OS_WindowInitResult windowInit = os_windowInit(arena, (OS_WindowInitParams){
|
||||
.name=s("Hello DJ Stdlib Graphics"),
|
||||
.width=800,
|
||||
.height=600,
|
||||
.data=&windowData,
|
||||
.eventHandler=windowOnEvent,
|
||||
});
|
||||
|
||||
if (!windowInit.valid) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
OS_Window *window = windowInit.result;
|
||||
|
||||
Scene mainScene = createScene(arena);
|
||||
Camera cam = createCamera(window->width, window->height);
|
||||
|
||||
Font kodeMono = createFont(arena, s("./gfx/assets/fonts/KodeMono.ttf"), 96);
|
||||
Shader phongShader = createShader(s("./gfx/assets/shaders/phong.vertex.glsl"), s("./gfx/assets/shaders/phong.fragment.glsl"));
|
||||
Shader solidShader = createShader(s("./gfx/assets/shaders/rect.vertex.glsl"), s("./gfx/assets/shaders/rect.fragment.glsl"));
|
||||
Shader textShader = createShader(s("./gfx/assets/shaders/text.vertex.glsl"), s("./gfx/assets/shaders/text.fragment.glsl"));
|
||||
|
||||
Renderer renderer = createRenderer(arena, &mainScene, &cam, createSceneGraphNode(&mainScene));
|
||||
UI_Context ui = ui_initContext(uiArena, &renderer);
|
||||
|
||||
renderer.phongShader = &phongShader;
|
||||
renderer.solidShader = &solidShader;
|
||||
renderer.textShader = &textShader;
|
||||
renderer.activeFont = &kodeMono;
|
||||
windowData.renderer = &renderer;
|
||||
|
||||
OS_Input currInput = {0};
|
||||
OS_Input prevInput = {0};
|
||||
|
||||
while (!os_windowShouldClose(window)) {
|
||||
os_windowFrameBegin(window);
|
||||
|
||||
prevInput = currInput;
|
||||
os_windowGetInput(window, &currInput);
|
||||
ui.input = &currInput;
|
||||
|
||||
Render(&renderer) {
|
||||
// Render graphics shit
|
||||
|
||||
UI_Pass(&ui) {
|
||||
ui_Main(&ui);
|
||||
}
|
||||
}
|
||||
|
||||
if (currInput.keyboard.escape) {
|
||||
break;
|
||||
}
|
||||
|
||||
os_windowSwapBuffers(window);
|
||||
os_windowFrameEnd(window);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -76,7 +76,7 @@ void startServer(Arena *arena, int32 port) {
|
||||
.socket=nextEvent->tClientMessage.client,
|
||||
.nickname=newNick,
|
||||
};
|
||||
AppendList(&chatClients, newChatClient);
|
||||
ListAppend(chatClients, newChatClient);
|
||||
println("Client from %d calls themselves \"%S\"", newChatClient.socket->address, newChatClient.nickname);
|
||||
}
|
||||
} else {
|
||||
|
||||
42
gfx/Color.c
Normal file
42
gfx/Color.c
Normal file
@@ -0,0 +1,42 @@
|
||||
#include "math.h"
|
||||
#include "Color.h"
|
||||
|
||||
real32 hueToRGB(real32 p, real32 q, real32 t) {
|
||||
if (t < 0) {
|
||||
t += 1;
|
||||
} else if (t > 1) {
|
||||
t -= 1;
|
||||
}
|
||||
if (t < 1.0f / 6) return p + (q - p) * 6 * t;
|
||||
if (t < 1.0f / 2) return q;
|
||||
if (t < 2.0f / 3) return p + (q - p) * (2.0f / 3 - t) * 6;
|
||||
return p;
|
||||
};
|
||||
|
||||
Vec4 hslToHex(real32 h, real32 s, real32 l) {
|
||||
h /= 360;
|
||||
s /= 100;
|
||||
l /= 100;
|
||||
real32 r, g, b;
|
||||
if (s == 0) {
|
||||
r = g = b = l;
|
||||
} else {
|
||||
real32 q = l < 0.5f ? l * (1 + s) : l + s - l * s;
|
||||
real32 p = 2 * l - q;
|
||||
r = hueToRGB(p, q, h + 1.0f / 3);
|
||||
g = hueToRGB(p, q, h);
|
||||
b = hueToRGB(p, q, h - 1.0f / 3);
|
||||
}
|
||||
return (Vec4){r, g, b, 1};
|
||||
}
|
||||
|
||||
Vec4 colorFromIndex(int index) {
|
||||
real32 color_wheel_cycle = floorf(index / 6.0f);
|
||||
real32 darkness_cycle = floorf(index / 12.0f);
|
||||
real32 spacing = (360.0f / 6.0f);
|
||||
real32 offset = color_wheel_cycle == 0 ? 0 : spacing / (color_wheel_cycle + 2);
|
||||
real32 hue = spacing * (index % 6) + offset;
|
||||
real32 saturation = 100.0f;
|
||||
real32 lightness = 1.0f / (2 + darkness_cycle) * 100;
|
||||
return hslToHex(hue, saturation, lightness);
|
||||
}
|
||||
17
gfx/Color.h
Normal file
17
gfx/Color.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef COLOR_H
|
||||
#define COLOR_H
|
||||
|
||||
#include "../core.h"
|
||||
|
||||
#define COLOR_BLACK (Vec4){0, 0, 0, 1}
|
||||
#define COLOR_RED (Vec4){1, 0, 0, 1}
|
||||
#define COLOR_GREEN (Vec4){0, 1, 0, 1}
|
||||
#define COLOR_BLUE (Vec4){0, 0, 1, 1}
|
||||
#define COLOR_MAGENTA (Vec4){1, 0, 1, 1}
|
||||
#define COLOR_YELLOW (Vec4){1, 1, 0, 1}
|
||||
#define COLOR_CYAN (Vec4){0, 1, 1, 1}
|
||||
#define COLOR_WHITE (Vec4){1, 1, 1, 1}
|
||||
|
||||
Vec4 colorFromIndex(int index);
|
||||
|
||||
#endif
|
||||
116
gfx/Mesh.c
Normal file
116
gfx/Mesh.c
Normal file
@@ -0,0 +1,116 @@
|
||||
#include "Mesh.h"
|
||||
#include "../vendor/loaders/tinyobj.h"
|
||||
#include "../os.h"
|
||||
|
||||
static void tinyobj_get_filedata(void* ctx, const char* filename, const int is_mtl, const char* obj_filename, char** data, size_t* len) {
|
||||
string file = os_readEntireFile((Arena *)ctx, s("./assets/models/cube.obj"));
|
||||
*data = file.str;
|
||||
*len = file.length;
|
||||
}
|
||||
|
||||
DefineList(uint32, MeshIndex);
|
||||
DefineList(real32, MeshValue);
|
||||
|
||||
Mesh createMesh(const char* obj_file) {
|
||||
Scratch temp = scratchStart(0, 0);
|
||||
|
||||
Mesh result = {0};
|
||||
|
||||
tinyobj_attrib_t attrib;
|
||||
tinyobj_shape_t* shapes = NULL;
|
||||
size_t num_shapes;
|
||||
tinyobj_material_t* materials = NULL;
|
||||
size_t num_materials;
|
||||
|
||||
int success = tinyobj_parse_obj(
|
||||
&attrib,
|
||||
&shapes,
|
||||
&num_shapes,
|
||||
&materials,
|
||||
&num_materials,
|
||||
obj_file,
|
||||
tinyobj_get_filedata,
|
||||
(void *)temp.arena,
|
||||
TINYOBJ_FLAG_TRIANGULATE
|
||||
);
|
||||
|
||||
if (success != TINYOBJ_SUCCESS || num_shapes <= 0) {
|
||||
print("Failed to load obj from '%s'! Success %i\n", obj_file, success);
|
||||
return result;
|
||||
}
|
||||
|
||||
MeshIndexList indices = PushFullList(temp.arena, MeshIndexList, attrib.num_faces);
|
||||
MeshValueList vertices = PushFullList(temp.arena, MeshValueList, 3*attrib.num_faces);
|
||||
MeshValueList normals = PushFullList(temp.arena, MeshValueList, 3*attrib.num_faces);
|
||||
MeshValueList texcoords = PushFullList(temp.arena, MeshValueList, 2*attrib.num_faces);
|
||||
|
||||
for (int i = 0; i < attrib.num_faces; i++) {
|
||||
tinyobj_vertex_index_t vertex_data = attrib.faces[i];
|
||||
|
||||
vertices.data[3*i] = attrib.vertices[3*vertex_data.v_idx];
|
||||
vertices.data[3*i+1] = attrib.vertices[3*vertex_data.v_idx + 1];
|
||||
vertices.data[3*i+2] = attrib.vertices[3*vertex_data.v_idx + 2];
|
||||
|
||||
normals.data[3*i] = attrib.normals[3*vertex_data.vn_idx];
|
||||
normals.data[3*i+1] = attrib.normals[3*vertex_data.vn_idx + 1];
|
||||
normals.data[3*i+2] = attrib.normals[3*vertex_data.vn_idx + 2];
|
||||
|
||||
texcoords.data[2*i] = attrib.texcoords[2*vertex_data.vt_idx];
|
||||
texcoords.data[2*i+1] = attrib.texcoords[2*vertex_data.vt_idx + 1];
|
||||
|
||||
indices.data[i] = i;
|
||||
}
|
||||
|
||||
result.num_indices = attrib.num_faces*3;
|
||||
glGenVertexArrays(1, &result.vao);
|
||||
glGenBuffers(3, result.vbos);
|
||||
|
||||
glBindVertexArray(result.vao);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, result.buffers.xyz);
|
||||
glBufferData(GL_ARRAY_BUFFER, vertices.length * sizeof(real32), vertices.data, GL_STATIC_DRAW);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(real32), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, result.buffers.uv);
|
||||
glBufferData(GL_ARRAY_BUFFER, texcoords.length * sizeof(real32), texcoords.data, GL_STATIC_DRAW);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(real32), (void*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, result.buffers.normals);
|
||||
glBufferData(GL_ARRAY_BUFFER, normals.length * sizeof(real32), normals.data, GL_STATIC_DRAW);
|
||||
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(real32), (void*)0);
|
||||
glEnableVertexAttribArray(2);
|
||||
|
||||
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||
//glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), indices.data(), GL_STATIC_DRAW);
|
||||
|
||||
scratchEnd(temp);
|
||||
return result;
|
||||
}
|
||||
|
||||
Mesh createMeshFromShape(const Shape* shape) {
|
||||
Mesh result = {0};
|
||||
|
||||
result.num_indices = shape->indices.length;
|
||||
glGenVertexArrays(1, &result.vao);
|
||||
glGenBuffers(3, result.vbos);
|
||||
|
||||
glBindVertexArray(result.vao);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, result.buffers.xyz);
|
||||
glBufferData(GL_ARRAY_BUFFER, shape->xyz.length * sizeof(float), shape->xyz.data, GL_STATIC_DRAW);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, result.buffers.uv);
|
||||
glBufferData(GL_ARRAY_BUFFER, shape->uv.length * sizeof(real32), shape->uv.data, GL_STATIC_DRAW);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(real32), (void*)0);
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, result.buffers.elements);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, shape->indices.length * sizeof(uint32), shape->indices.data, GL_STATIC_DRAW);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
25
gfx/Mesh.h
Normal file
25
gfx/Mesh.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef LEDDA_MESH_H
|
||||
#define LEDDA_MESH_H
|
||||
|
||||
#include "../vendor/glad/glad.h"
|
||||
#include "../core.h"
|
||||
#include "geometry.h"
|
||||
|
||||
typedef struct {
|
||||
uint32 vao;
|
||||
union {
|
||||
struct {
|
||||
uint32 xyz;
|
||||
uint32 uv;
|
||||
uint32 normals;
|
||||
uint32 elements;
|
||||
} buffers;
|
||||
uint32 vbos[4];
|
||||
};
|
||||
uint64 num_indices;
|
||||
} Mesh;
|
||||
|
||||
Mesh createMesh(const char* obj_file);
|
||||
Mesh createMeshFromShape(const Shape* shape);
|
||||
|
||||
#endif
|
||||
100
gfx/Shader.c
Normal file
100
gfx/Shader.c
Normal file
@@ -0,0 +1,100 @@
|
||||
#include "Shader.h"
|
||||
#include "../core.h"
|
||||
#include "../os.h"
|
||||
#include "../vendor/glad/glad.h"
|
||||
#include "../vendor/raymath.h"
|
||||
|
||||
typedef enum {
|
||||
ShaderType_fragment=GL_FRAGMENT_SHADER,
|
||||
ShaderType_vertex=GL_VERTEX_SHADER,
|
||||
} ShaderType;
|
||||
|
||||
uint32 createGlShader(string file_path, ShaderType shader_type) {
|
||||
GLuint shader;
|
||||
WithScratch(scratch) {
|
||||
string shader_code = os_readEntireFile(scratch.arena, file_path);
|
||||
shader = glCreateShader(shader_type);
|
||||
const char *shader_code_cstr = cstring(scratch.arena, shader_code);
|
||||
glShaderSource(shader, 1, &shader_code_cstr, NULL);
|
||||
glCompileShader(shader);
|
||||
int success;
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
|
||||
if (!success) {
|
||||
GLint info_log_length;
|
||||
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_log_length);
|
||||
string info_log = PushString(scratch.arena, (size_t)info_log_length + 1);
|
||||
glGetShaderInfoLog(shader, info_log_length, NULL, info_log.str);
|
||||
string shader_type_name = shader_type == ShaderType_fragment ? s("FRAGMENT") : s("VERTEX");
|
||||
print("%S shader compilation error (%S):\n%S", shader_type_name, file_path, info_log);
|
||||
}
|
||||
}
|
||||
return shader;
|
||||
}
|
||||
|
||||
Shader createShader(string vertex_path, string fragment_path) {
|
||||
Shader result = {0};
|
||||
WithScratch(temp) {
|
||||
uint32 vertex_shader = createGlShader(vertex_path, ShaderType_vertex);
|
||||
uint32 fragment_shader = createGlShader(fragment_path, ShaderType_fragment);
|
||||
|
||||
result.progId = glCreateProgram();
|
||||
glAttachShader(result.progId, vertex_shader);
|
||||
glAttachShader(result.progId, fragment_shader);
|
||||
glLinkProgram(result.progId);
|
||||
|
||||
int success;
|
||||
glGetProgramiv(result.progId, GL_LINK_STATUS, &success);
|
||||
if (!success) {
|
||||
GLint info_log_length;
|
||||
glGetShaderiv(result.progId, GL_INFO_LOG_LENGTH, &info_log_length);
|
||||
string info_log_prog = PushString(temp.arena, (size_t)info_log_length + 1);
|
||||
glGetProgramInfoLog(result.progId, info_log_length, NULL, info_log_prog.str);
|
||||
print("Shader program link error:\n%S", info_log_prog);
|
||||
}
|
||||
|
||||
glDeleteShader(vertex_shader);
|
||||
glDeleteShader(fragment_shader);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void setUniformMat4fv(Shader *s, const char *uniformName, Matrix *matrix) {
|
||||
glUniformMatrix4fv(
|
||||
glGetUniformLocation(s->progId, uniformName),
|
||||
1, GL_FALSE, MatrixToFloat(*matrix));
|
||||
}
|
||||
void setUniformMat4fvByLoc(int uniformLocation, Matrix *matrix) {
|
||||
glUniformMatrix4fv(uniformLocation, 1, GL_FALSE, MatrixToFloat(*matrix));
|
||||
}
|
||||
|
||||
void setUniform4fv(Shader *s, const char *uniformName, Vec4 *vector) {
|
||||
glUniform4fv(glGetUniformLocation(s->progId, uniformName), 1, (const GLfloat *)vector);
|
||||
}
|
||||
void setUniform4fvByLoc(int uniformLocation, Vec4 *vector) {
|
||||
glUniform4fv(uniformLocation, 1, (const GLfloat *)vector);
|
||||
}
|
||||
|
||||
void setUniform3fv(Shader *s, const char *uniformName, Vec3 *vector) {
|
||||
glUniform3fv(glGetUniformLocation(s->progId, uniformName), 1, Vector3ToFloat(*vector));
|
||||
}
|
||||
void setUniform3fvByLoc(int uniformLocation, Vec3 *vector) {
|
||||
glUniform3fv(uniformLocation, 1, Vector3ToFloat(*vector));
|
||||
}
|
||||
|
||||
void setUniform1i(Shader *s, const char *uniformName, int32 i) {
|
||||
glUniform1i(glGetUniformLocation(s->progId, uniformName), (GLint)i);
|
||||
}
|
||||
void setUniform1iByLoc(int uniformLocation, int32 i) {
|
||||
glUniform1i(uniformLocation, (GLint)i);
|
||||
}
|
||||
|
||||
void setUniform2fv(Shader *s, const char *uniformName, Vec2 *vector) {
|
||||
glUniform2fv(glGetUniformLocation(s->progId, uniformName), 1, (const GLfloat *)vector);
|
||||
}
|
||||
void setUniform2fvByLoc(int uniformLocation, Vec2 *vector) {
|
||||
glUniform2fv(uniformLocation, 1, (const GLfloat *)vector);
|
||||
}
|
||||
|
||||
int getUniformLocation(Shader *s, const char *uniformName) {
|
||||
return glGetUniformLocation(s->progId, uniformName);
|
||||
}
|
||||
30
gfx/Shader.h
Normal file
30
gfx/Shader.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef DJSTDLIB_GFX_SHADER_H
|
||||
#define DJSTDLIB_GFX_SHADER_H
|
||||
|
||||
#include "../vendor/raymath.h"
|
||||
#include "../core.h"
|
||||
|
||||
typedef struct {
|
||||
uint32 progId;
|
||||
} Shader;
|
||||
|
||||
Shader createShader(string vertex_path, string fragment_path);
|
||||
|
||||
void setUniformMat4fv(Shader *s, const char *uniformName, Matrix *matrix);
|
||||
void setUniformMat4fvByLoc(int uniformLocation, Matrix *matrix);
|
||||
|
||||
void setUniform4fv(Shader *s, const char *uniformName, Vec4 *vector);
|
||||
void setUniform4fvByLoc(int uniformLocation, Vec4 *vector);
|
||||
|
||||
void setUniform3fv(Shader *s, const char *uniformName, Vec3 *vector);
|
||||
void setUniform3fvByLoc(int uniformLocation, Vec3 *vector);
|
||||
|
||||
void setUniform2fv(Shader *s, const char *uniformName, Vec2 *vector);
|
||||
void setUniform2fvByLoc(int uniformLocation, Vec2 *vector);
|
||||
|
||||
void setUniform1i(Shader *s, const char *uniformName, int32 i);
|
||||
void setUniform1iByLoc(int uniformLocation, int32 i);
|
||||
|
||||
int getUniformLocation(Shader *s, const char *uniformName);
|
||||
|
||||
#endif
|
||||
137
gfx/Texture.c
Normal file
137
gfx/Texture.c
Normal file
@@ -0,0 +1,137 @@
|
||||
#include "Texture.h"
|
||||
#include "../os.h"
|
||||
#include <math.h>
|
||||
|
||||
Texture createTexture(const char* bitmap, int32 width, int32 height) {
|
||||
Texture result = {0};
|
||||
result.width = width;
|
||||
result.height = height;
|
||||
glGenTextures(1, &result.tex_id);
|
||||
glBindTexture(GL_TEXTURE_2D, result.tex_id);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, result.width, result.height, 0, GL_RGB, GL_UNSIGNED_BYTE, bitmap);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
DefineList(stbtt_bakedchar, STBBakedChar);
|
||||
|
||||
static void saveGrayscaleTarga(string location, const char *bytes, int width, int height) {
|
||||
char tgaHeader[18] = {
|
||||
// Image ID length
|
||||
0x00,
|
||||
// Color map type
|
||||
0x00,
|
||||
// Image type
|
||||
0x03,
|
||||
// Color map info (unused)
|
||||
0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
// Image spec
|
||||
0x0, 0x0, // x origin
|
||||
0x0, 0x0, // y origin
|
||||
width & 0xFF, (width >> 8) & 0xFF, // width
|
||||
height & 0xFF, (height >> 8) & 0xFF, // width
|
||||
0x8, // bits per px (depth)
|
||||
0b00000000, // image descriptor
|
||||
};
|
||||
os_writeEntireFile(location, tgaHeader, ArrayCount(tgaHeader));
|
||||
os_fileAppend(location, bytes, width * height);
|
||||
}
|
||||
|
||||
Font createFont(Arena *arena, string ttfLocation, real32 lineHeight) {
|
||||
const int CODEPOINT_START = 32;
|
||||
const int CODEPOINT_END = 126;
|
||||
|
||||
int32 atlasWidth = ((int32)lineHeight)*(int32)sqrt(CODEPOINT_END - CODEPOINT_START);
|
||||
int32 atlasHeight = ((int32)lineHeight)*(int32)sqrt(CODEPOINT_END - CODEPOINT_START);
|
||||
|
||||
STBBakedCharList bakedCharlist = PushFullListZero(arena, STBBakedCharList, CODEPOINT_END - CODEPOINT_START);
|
||||
string fontFile = os_readEntireFile(arena, ttfLocation);
|
||||
|
||||
stbtt_fontinfo info;
|
||||
stbtt_InitFont(&info, (unsigned char *)fontFile.str, stbtt_GetFontOffsetForIndex((unsigned char *)fontFile.str, 0));
|
||||
int ascent, descent, lineGap;
|
||||
stbtt_GetFontVMetrics(&info, &ascent, &descent, &lineGap);
|
||||
real32 scale = stbtt_ScaleForPixelHeight(&info, lineHeight);
|
||||
|
||||
char *bakedFontBitmap = PushArrayZero(arena, char, atlasWidth*atlasHeight);
|
||||
int32 bake_result = stbtt_BakeFontBitmap(
|
||||
(unsigned char *)fontFile.str, 0,
|
||||
lineHeight,
|
||||
(unsigned char *)bakedFontBitmap, atlasWidth, atlasHeight,
|
||||
CODEPOINT_START, CODEPOINT_END - CODEPOINT_START,
|
||||
bakedCharlist.data);
|
||||
|
||||
GlyphMetaList glyphMeta = PushFullListZero(arena, GlyphMetaList, bakedCharlist.length);
|
||||
real32 x, y;
|
||||
real32 lastX, lastY;
|
||||
for (EachIn(bakedCharlist, i)) {
|
||||
stbtt_aligned_quad q;
|
||||
stbtt_GetBakedQuad(bakedCharlist.data, atlasWidth, atlasHeight, i, &x, &y, &q, 1);
|
||||
glyphMeta.data[i] = (GlyphMeta){
|
||||
.uv0=(Vec2){q.s0, q.t1},
|
||||
.uv1=(Vec2){q.s1, q.t0},
|
||||
.xOffset=q.x0 - lastX,
|
||||
.yOffset=q.y0 + lineHeight + scale * descent,
|
||||
.width=q.x1-q.x0,
|
||||
.height=q.y1-q.y0,
|
||||
};
|
||||
lastX = x;
|
||||
lastY = y;
|
||||
}
|
||||
|
||||
Font result = {0};
|
||||
result.glyphMeta = glyphMeta;
|
||||
result.lineHeight = lineHeight;
|
||||
result.charWidth = bakedCharlist.data[0].xadvance;
|
||||
|
||||
//saveGrayscaleTarga(s("atlas.tga"), bakedFontBitmap, atlasWidth, atlasHeight);
|
||||
|
||||
glGenTextures(1, &result.texId);
|
||||
glBindTexture(GL_TEXTURE_2D, result.texId);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, atlasWidth, atlasHeight, 0, GL_RED, GL_UNSIGNED_BYTE, bakedFontBitmap);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glGenBuffers(1, &result.glyphTableBufId);
|
||||
glBindBuffer(GL_TEXTURE_BUFFER, result.glyphTableBufId);
|
||||
glBufferData(GL_TEXTURE_BUFFER, sizeof(result.glyphMeta.data[0])*result.glyphMeta.length, result.glyphMeta.data, GL_STATIC_DRAW);
|
||||
|
||||
glGenTextures(1, &result.glyphTableTexId);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, result.glyphTableTexId);
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, result.glyphTableBufId);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Texture createTextureFromFile(const char* source_path) {
|
||||
Texture result = {0};
|
||||
glGenTextures(1, &result.tex_id);
|
||||
glBindTexture(GL_TEXTURE_2D, result.tex_id);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
int nr_channels;
|
||||
stbi_uc *data = stbi_load(source_path, &result.width, &result.height, &nr_channels, 0);
|
||||
if (data) {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, result.width, result.height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
} else {
|
||||
print("Failed to load texture.");
|
||||
}
|
||||
stbi_image_free(data);
|
||||
|
||||
return result;
|
||||
}
|
||||
42
gfx/Texture.h
Normal file
42
gfx/Texture.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#ifndef LEDDA_TEXTURE_H
|
||||
#define LEDDA_TEXTURE_H
|
||||
|
||||
#include "../core.h"
|
||||
#include "../vendor/loaders/stb_truetype.h"
|
||||
#include "../vendor/loaders/stb_image.h"
|
||||
#include "../vendor/glad/glad.h"
|
||||
|
||||
typedef struct Texture Texture;
|
||||
struct Texture {
|
||||
uint32 tex_id;
|
||||
int32 width;
|
||||
int32 height;
|
||||
};
|
||||
|
||||
typedef struct GlyphMeta GlyphMeta;
|
||||
struct GlyphMeta {
|
||||
Vec2 uv0;
|
||||
Vec2 uv1;
|
||||
real32 xOffset;
|
||||
real32 yOffset;
|
||||
real32 width;
|
||||
real32 height;
|
||||
};
|
||||
|
||||
DefineList(GlyphMeta, GlyphMeta);
|
||||
|
||||
typedef struct Font Font;
|
||||
struct Font {
|
||||
GlyphMetaList glyphMeta;
|
||||
real32 lineHeight;
|
||||
real32 charWidth;
|
||||
uint32 texId;
|
||||
uint32 glyphTableTexId;
|
||||
uint32 glyphTableBufId;
|
||||
};
|
||||
|
||||
Texture createTexture(const char* bitmap, int32 width, int32 height);
|
||||
Texture createTextureFromFile(const char* source_path);
|
||||
Font createFont(Arena *arena, string ttfLocation, real32 lineHeight);
|
||||
|
||||
#endif
|
||||
BIN
gfx/assets/fonts/KodeMono.ttf
Normal file
BIN
gfx/assets/fonts/KodeMono.ttf
Normal file
Binary file not shown.
674
gfx/assets/models/cube.obj
Normal file
674
gfx/assets/models/cube.obj
Normal file
@@ -0,0 +1,674 @@
|
||||
# Blender v2.82 (sub 7) OBJ File: ''
|
||||
# www.blender.org
|
||||
o Cube_Cube.001
|
||||
v 0.399961 0.500000 -0.399961
|
||||
v 0.500000 0.399961 -0.399961
|
||||
v 0.399961 0.399961 -0.500000
|
||||
v 0.438244 0.492385 -0.399961
|
||||
v 0.470699 0.470699 -0.399961
|
||||
v 0.399961 0.492385 -0.438244
|
||||
v 0.439203 0.483194 -0.439203
|
||||
v 0.465612 0.465612 -0.437212
|
||||
v 0.457718 0.457718 -0.457718
|
||||
v 0.492385 0.399961 -0.438244
|
||||
v 0.470699 0.399961 -0.470699
|
||||
v 0.492385 0.438244 -0.399961
|
||||
v 0.483194 0.439203 -0.439203
|
||||
v 0.465612 0.437212 -0.465612
|
||||
v 0.399961 0.438244 -0.492385
|
||||
v 0.399961 0.470699 -0.470699
|
||||
v 0.438244 0.399961 -0.492385
|
||||
v 0.439203 0.439203 -0.483194
|
||||
v 0.437212 0.465612 -0.465612
|
||||
v 0.500000 -0.399961 -0.399961
|
||||
v 0.399961 -0.500000 -0.399961
|
||||
v 0.399961 -0.399961 -0.500000
|
||||
v 0.492385 -0.438244 -0.399961
|
||||
v 0.470699 -0.470699 -0.399961
|
||||
v 0.492385 -0.399961 -0.438244
|
||||
v 0.483194 -0.439203 -0.439203
|
||||
v 0.465612 -0.465612 -0.437212
|
||||
v 0.457718 -0.457718 -0.457718
|
||||
v 0.399961 -0.492385 -0.438244
|
||||
v 0.399961 -0.470699 -0.470699
|
||||
v 0.438244 -0.492385 -0.399961
|
||||
v 0.439203 -0.483194 -0.439203
|
||||
v 0.437212 -0.465612 -0.465612
|
||||
v 0.438244 -0.399961 -0.492385
|
||||
v 0.470699 -0.399961 -0.470699
|
||||
v 0.399961 -0.438244 -0.492385
|
||||
v 0.439203 -0.439203 -0.483194
|
||||
v 0.465612 -0.437212 -0.465612
|
||||
v 0.500000 0.399961 0.399961
|
||||
v 0.399961 0.500000 0.399961
|
||||
v 0.399961 0.399961 0.500000
|
||||
v 0.492385 0.438244 0.399961
|
||||
v 0.470699 0.470699 0.399961
|
||||
v 0.492385 0.399961 0.438244
|
||||
v 0.483194 0.439203 0.439203
|
||||
v 0.465612 0.465612 0.437212
|
||||
v 0.457718 0.457718 0.457718
|
||||
v 0.399961 0.492385 0.438244
|
||||
v 0.399961 0.470699 0.470699
|
||||
v 0.438244 0.492385 0.399961
|
||||
v 0.439203 0.483194 0.439203
|
||||
v 0.437212 0.465612 0.465612
|
||||
v 0.438244 0.399961 0.492385
|
||||
v 0.470699 0.399961 0.470699
|
||||
v 0.399961 0.438244 0.492385
|
||||
v 0.439203 0.439203 0.483194
|
||||
v 0.465612 0.437212 0.465612
|
||||
v 0.399961 -0.399961 0.500000
|
||||
v 0.399961 -0.500000 0.399961
|
||||
v 0.500000 -0.399961 0.399961
|
||||
v 0.399961 -0.438244 0.492385
|
||||
v 0.399961 -0.470699 0.470699
|
||||
v 0.438244 -0.399961 0.492385
|
||||
v 0.439203 -0.439203 0.483194
|
||||
v 0.437212 -0.465612 0.465612
|
||||
v 0.457718 -0.457718 0.457718
|
||||
v 0.438244 -0.492385 0.399961
|
||||
v 0.470699 -0.470699 0.399961
|
||||
v 0.399961 -0.492385 0.438244
|
||||
v 0.439203 -0.483194 0.439203
|
||||
v 0.465612 -0.465612 0.437212
|
||||
v 0.492385 -0.399961 0.438244
|
||||
v 0.470699 -0.399961 0.470699
|
||||
v 0.492385 -0.438244 0.399961
|
||||
v 0.483194 -0.439203 0.439203
|
||||
v 0.465612 -0.437212 0.465612
|
||||
v -0.500000 0.399961 -0.399961
|
||||
v -0.399961 0.500000 -0.399961
|
||||
v -0.399961 0.399961 -0.500000
|
||||
v -0.492385 0.438244 -0.399961
|
||||
v -0.470699 0.470699 -0.399961
|
||||
v -0.492385 0.399961 -0.438244
|
||||
v -0.483194 0.439203 -0.439203
|
||||
v -0.465612 0.465612 -0.437212
|
||||
v -0.457718 0.457718 -0.457718
|
||||
v -0.399961 0.492385 -0.438244
|
||||
v -0.399961 0.470699 -0.470699
|
||||
v -0.438244 0.492385 -0.399961
|
||||
v -0.439203 0.483194 -0.439203
|
||||
v -0.437212 0.465612 -0.465612
|
||||
v -0.438244 0.399961 -0.492385
|
||||
v -0.470699 0.399961 -0.470699
|
||||
v -0.399961 0.438244 -0.492385
|
||||
v -0.439203 0.439203 -0.483194
|
||||
v -0.465612 0.437212 -0.465612
|
||||
v -0.399961 -0.399961 -0.500000
|
||||
v -0.399961 -0.500000 -0.399961
|
||||
v -0.500000 -0.399961 -0.399961
|
||||
v -0.399961 -0.438244 -0.492385
|
||||
v -0.399961 -0.470699 -0.470699
|
||||
v -0.438244 -0.399961 -0.492385
|
||||
v -0.439203 -0.439203 -0.483194
|
||||
v -0.437212 -0.465612 -0.465612
|
||||
v -0.457718 -0.457718 -0.457718
|
||||
v -0.438244 -0.492385 -0.399961
|
||||
v -0.470699 -0.470699 -0.399961
|
||||
v -0.399961 -0.492385 -0.438244
|
||||
v -0.439203 -0.483194 -0.439203
|
||||
v -0.465612 -0.465612 -0.437212
|
||||
v -0.492385 -0.399961 -0.438244
|
||||
v -0.470699 -0.399961 -0.470699
|
||||
v -0.492385 -0.438244 -0.399961
|
||||
v -0.483194 -0.439203 -0.439203
|
||||
v -0.465612 -0.437212 -0.465612
|
||||
v -0.500000 0.399961 0.399961
|
||||
v -0.399961 0.399961 0.500000
|
||||
v -0.399961 0.500000 0.399961
|
||||
v -0.492385 0.399961 0.438244
|
||||
v -0.470699 0.399961 0.470699
|
||||
v -0.492385 0.438244 0.399961
|
||||
v -0.483194 0.439203 0.439203
|
||||
v -0.465612 0.437212 0.465612
|
||||
v -0.457718 0.457718 0.457718
|
||||
v -0.399961 0.438244 0.492385
|
||||
v -0.399961 0.470699 0.470699
|
||||
v -0.438244 0.399961 0.492385
|
||||
v -0.439203 0.439203 0.483194
|
||||
v -0.437212 0.465612 0.465612
|
||||
v -0.438244 0.492385 0.399961
|
||||
v -0.470699 0.470699 0.399961
|
||||
v -0.399961 0.492385 0.438244
|
||||
v -0.439203 0.483194 0.439203
|
||||
v -0.465612 0.465612 0.437212
|
||||
v -0.399961 -0.399961 0.500000
|
||||
v -0.500000 -0.399961 0.399961
|
||||
v -0.399961 -0.500000 0.399961
|
||||
v -0.438244 -0.399961 0.492385
|
||||
v -0.470699 -0.399961 0.470699
|
||||
v -0.399961 -0.438244 0.492385
|
||||
v -0.439203 -0.439203 0.483194
|
||||
v -0.465612 -0.437212 0.465612
|
||||
v -0.457718 -0.457718 0.457718
|
||||
v -0.492385 -0.438244 0.399961
|
||||
v -0.470699 -0.470699 0.399961
|
||||
v -0.492385 -0.399961 0.438244
|
||||
v -0.483194 -0.439203 0.439203
|
||||
v -0.465612 -0.465612 0.437212
|
||||
v -0.399961 -0.492385 0.438244
|
||||
v -0.399961 -0.470699 0.470699
|
||||
v -0.438244 -0.492385 0.399961
|
||||
v -0.439203 -0.483194 0.439203
|
||||
v -0.437212 -0.465612 0.465612
|
||||
vt 0.150010 0.525010
|
||||
vt 0.349990 0.525010
|
||||
vt 0.349990 0.724990
|
||||
vt 0.150010 0.724990
|
||||
vt 0.650010 0.525010
|
||||
vt 0.849990 0.525010
|
||||
vt 0.849990 0.724990
|
||||
vt 0.650010 0.724990
|
||||
vt 0.400010 0.275010
|
||||
vt 0.599990 0.275010
|
||||
vt 0.599990 0.474990
|
||||
vt 0.400010 0.474990
|
||||
vt 0.400010 0.775010
|
||||
vt 0.599990 0.775010
|
||||
vt 0.599990 0.974990
|
||||
vt 0.400010 0.974990
|
||||
vt 0.400010 0.025010
|
||||
vt 0.599990 0.025010
|
||||
vt 0.599990 0.224990
|
||||
vt 0.400010 0.224990
|
||||
vt 0.400010 0.525010
|
||||
vt 0.390439 0.525010
|
||||
vt 0.390199 0.515199
|
||||
vt 0.400010 0.515439
|
||||
vt 0.375000 0.525010
|
||||
vt 0.375000 0.515697
|
||||
vt 0.390697 0.500000
|
||||
vt 0.400010 0.500000
|
||||
vt 0.375000 0.510570
|
||||
vt 0.599990 0.265439
|
||||
vt 0.609801 0.265199
|
||||
vt 0.609561 0.275010
|
||||
vt 0.599990 0.250000
|
||||
vt 0.609303 0.250000
|
||||
vt 0.625000 0.265697
|
||||
vt 0.625000 0.275010
|
||||
vt 0.614430 0.250000
|
||||
vt 0.859561 0.724990
|
||||
vt 0.859801 0.734801
|
||||
vt 0.849990 0.734561
|
||||
vt 0.875000 0.724990
|
||||
vt 0.875000 0.734303
|
||||
vt 0.859303 0.750000
|
||||
vt 0.849990 0.750000
|
||||
vt 0.875000 0.739430
|
||||
vt 0.390439 0.275010
|
||||
vt 0.390199 0.265199
|
||||
vt 0.400010 0.265439
|
||||
vt 0.375000 0.275010
|
||||
vt 0.375000 0.265697
|
||||
vt 0.390697 0.250000
|
||||
vt 0.400010 0.250000
|
||||
vt 0.375000 0.260570
|
||||
vt 0.599990 0.015439
|
||||
vt 0.609801 0.015199
|
||||
vt 0.609561 0.025010
|
||||
vt 0.599990 0.000000
|
||||
vt 0.609303 0.000000
|
||||
vt 0.625000 0.015697
|
||||
vt 0.625000 0.025010
|
||||
vt 0.614430 0.000000
|
||||
vt 0.650010 0.734561
|
||||
vt 0.640199 0.734801
|
||||
vt 0.640439 0.724990
|
||||
vt 0.650010 0.750000
|
||||
vt 0.640697 0.750000
|
||||
vt 0.625000 0.734303
|
||||
vt 0.625000 0.724990
|
||||
vt 0.635570 0.750000
|
||||
vt 0.609561 0.474990
|
||||
vt 0.609801 0.484801
|
||||
vt 0.599990 0.484561
|
||||
vt 0.625000 0.474990
|
||||
vt 0.625000 0.484303
|
||||
vt 0.609303 0.500000
|
||||
vt 0.599990 0.500000
|
||||
vt 0.625000 0.489430
|
||||
vt 0.400010 0.724990
|
||||
vt 0.400010 0.734561
|
||||
vt 0.390199 0.734801
|
||||
vt 0.390439 0.724990
|
||||
vt 0.400010 0.750000
|
||||
vt 0.390697 0.750000
|
||||
vt 0.375000 0.734303
|
||||
vt 0.375000 0.724990
|
||||
vt 0.385570 0.750000
|
||||
vt 0.349990 0.515439
|
||||
vt 0.359801 0.515199
|
||||
vt 0.359561 0.525010
|
||||
vt 0.349990 0.500000
|
||||
vt 0.359303 0.500000
|
||||
vt 0.375000 0.515697
|
||||
vt 0.375000 0.525010
|
||||
vt 0.364430 0.500000
|
||||
vt 0.140439 0.525010
|
||||
vt 0.140199 0.515199
|
||||
vt 0.150010 0.515439
|
||||
vt 0.125000 0.525010
|
||||
vt 0.125000 0.515697
|
||||
vt 0.140697 0.500000
|
||||
vt 0.150010 0.500000
|
||||
vt 0.125000 0.510570
|
||||
vt 0.609561 0.224990
|
||||
vt 0.609801 0.234801
|
||||
vt 0.599990 0.234561
|
||||
vt 0.625000 0.224990
|
||||
vt 0.625000 0.234303
|
||||
vt 0.609303 0.250000
|
||||
vt 0.599990 0.250000
|
||||
vt 0.625000 0.239430
|
||||
vt 0.400010 0.484561
|
||||
vt 0.390199 0.484801
|
||||
vt 0.390439 0.474990
|
||||
vt 0.400010 0.500000
|
||||
vt 0.390697 0.500000
|
||||
vt 0.375000 0.484303
|
||||
vt 0.375000 0.474990
|
||||
vt 0.385570 0.500000
|
||||
vt 0.609561 0.974990
|
||||
vt 0.609801 0.984801
|
||||
vt 0.599990 0.984561
|
||||
vt 0.625000 0.974990
|
||||
vt 0.625000 0.984303
|
||||
vt 0.609303 1.000000
|
||||
vt 0.599990 1.000000
|
||||
vt 0.625000 0.989430
|
||||
vt 0.599990 0.525010
|
||||
vt 0.599990 0.515439
|
||||
vt 0.609801 0.515199
|
||||
vt 0.609561 0.525010
|
||||
vt 0.599990 0.500000
|
||||
vt 0.609303 0.500000
|
||||
vt 0.625000 0.515697
|
||||
vt 0.625000 0.525010
|
||||
vt 0.614430 0.500000
|
||||
vt 0.849990 0.515439
|
||||
vt 0.859801 0.515199
|
||||
vt 0.859561 0.525010
|
||||
vt 0.849990 0.500000
|
||||
vt 0.859303 0.500000
|
||||
vt 0.875000 0.515697
|
||||
vt 0.875000 0.525010
|
||||
vt 0.864430 0.500000
|
||||
vt 0.640439 0.525010
|
||||
vt 0.640199 0.515199
|
||||
vt 0.650010 0.515439
|
||||
vt 0.625000 0.525010
|
||||
vt 0.625000 0.515697
|
||||
vt 0.640697 0.500000
|
||||
vt 0.650010 0.500000
|
||||
vt 0.625000 0.510570
|
||||
vt 0.390439 0.025010
|
||||
vt 0.390199 0.015199
|
||||
vt 0.400010 0.015439
|
||||
vt 0.375000 0.025010
|
||||
vt 0.375000 0.015697
|
||||
vt 0.390697 0.000000
|
||||
vt 0.400010 0.000000
|
||||
vt 0.375000 0.010570
|
||||
vt 0.400010 0.984561
|
||||
vt 0.390199 0.984801
|
||||
vt 0.390439 0.974990
|
||||
vt 0.400010 1.000000
|
||||
vt 0.390697 1.000000
|
||||
vt 0.375000 0.984303
|
||||
vt 0.375000 0.974990
|
||||
vt 0.385570 1.000000
|
||||
vt 0.599990 0.765439
|
||||
vt 0.609801 0.765199
|
||||
vt 0.609561 0.775010
|
||||
vt 0.599990 0.750000
|
||||
vt 0.609303 0.750000
|
||||
vt 0.625000 0.765697
|
||||
vt 0.625000 0.775010
|
||||
vt 0.614430 0.750000
|
||||
vt 0.359561 0.724990
|
||||
vt 0.359801 0.734801
|
||||
vt 0.349990 0.734561
|
||||
vt 0.375000 0.724990
|
||||
vt 0.375000 0.734303
|
||||
vt 0.359303 0.750000
|
||||
vt 0.349990 0.750000
|
||||
vt 0.375000 0.739430
|
||||
vt 0.599990 0.724990
|
||||
vt 0.609561 0.724990
|
||||
vt 0.609801 0.734801
|
||||
vt 0.599990 0.734561
|
||||
vt 0.625000 0.724990
|
||||
vt 0.625000 0.734303
|
||||
vt 0.609303 0.750000
|
||||
vt 0.599990 0.750000
|
||||
vt 0.625000 0.739430
|
||||
vt 0.150010 0.734561
|
||||
vt 0.140199 0.734801
|
||||
vt 0.140439 0.724990
|
||||
vt 0.150010 0.750000
|
||||
vt 0.140697 0.750000
|
||||
vt 0.125000 0.734303
|
||||
vt 0.125000 0.724990
|
||||
vt 0.135570 0.750000
|
||||
vt 0.390439 0.775010
|
||||
vt 0.390199 0.765199
|
||||
vt 0.400010 0.765439
|
||||
vt 0.375000 0.775010
|
||||
vt 0.375000 0.765697
|
||||
vt 0.390697 0.750000
|
||||
vt 0.400010 0.750000
|
||||
vt 0.375000 0.760570
|
||||
vt 0.400010 0.234561
|
||||
vt 0.390199 0.234801
|
||||
vt 0.390439 0.224990
|
||||
vt 0.400010 0.250000
|
||||
vt 0.390697 0.250000
|
||||
vt 0.375000 0.234303
|
||||
vt 0.375000 0.224990
|
||||
vt 0.385570 0.250000
|
||||
vn 0.1004 -0.1004 0.9899
|
||||
vn 0.1004 0.1004 0.9899
|
||||
vn -0.1004 0.1004 0.9899
|
||||
vn -0.1004 -0.1004 0.9899
|
||||
vn -0.1004 -0.1004 -0.9899
|
||||
vn -0.1004 0.1004 -0.9899
|
||||
vn 0.1004 0.1004 -0.9899
|
||||
vn 0.1004 -0.1004 -0.9899
|
||||
vn 0.9899 -0.1004 -0.1004
|
||||
vn 0.9899 0.1004 -0.1004
|
||||
vn 0.9899 0.1004 0.1004
|
||||
vn 0.9899 -0.1004 0.1004
|
||||
vn -0.9899 -0.1004 0.1004
|
||||
vn -0.9899 0.1004 0.1004
|
||||
vn -0.9899 0.1004 -0.1004
|
||||
vn -0.9899 -0.1004 -0.1004
|
||||
vn -0.1004 -0.9899 -0.1004
|
||||
vn 0.1004 -0.9899 -0.1004
|
||||
vn 0.1004 -0.9899 0.1004
|
||||
vn -0.1004 -0.9899 0.1004
|
||||
vn 0.1004 0.9899 -0.1004
|
||||
vn 0.3792 0.9201 -0.0981
|
||||
vn 0.3673 0.8545 -0.3673
|
||||
vn 0.0981 0.9201 -0.3792
|
||||
vn 0.7041 0.7041 -0.0919
|
||||
vn 0.6663 0.6663 -0.3347
|
||||
vn 0.3347 0.6663 -0.6663
|
||||
vn 0.0919 0.7041 -0.7041
|
||||
vn 0.5774 0.5774 -0.5774
|
||||
vn 0.9201 0.0981 -0.3792
|
||||
vn 0.8545 0.3673 -0.3673
|
||||
vn 0.9201 0.3792 -0.0981
|
||||
vn 0.7041 0.0919 -0.7041
|
||||
vn 0.6663 0.3347 -0.6663
|
||||
vn 0.0981 0.3792 -0.9201
|
||||
vn 0.3673 0.3673 -0.8545
|
||||
vn 0.3792 0.0981 -0.9201
|
||||
vn 0.9201 -0.3792 -0.0981
|
||||
vn 0.8545 -0.3673 -0.3673
|
||||
vn 0.9201 -0.0981 -0.3792
|
||||
vn 0.7041 -0.7041 -0.0919
|
||||
vn 0.6663 -0.6663 -0.3347
|
||||
vn 0.6663 -0.3347 -0.6663
|
||||
vn 0.7041 -0.0919 -0.7041
|
||||
vn 0.5774 -0.5774 -0.5773
|
||||
vn 0.0981 -0.9201 -0.3792
|
||||
vn 0.3673 -0.8545 -0.3673
|
||||
vn 0.3792 -0.9201 -0.0981
|
||||
vn 0.0919 -0.7041 -0.7041
|
||||
vn 0.3347 -0.6663 -0.6663
|
||||
vn 0.3792 -0.0981 -0.9201
|
||||
vn 0.3673 -0.3673 -0.8545
|
||||
vn 0.0981 -0.3792 -0.9201
|
||||
vn 0.9201 0.3792 0.0981
|
||||
vn 0.8545 0.3673 0.3673
|
||||
vn 0.9201 0.0981 0.3792
|
||||
vn 0.7041 0.7041 0.0919
|
||||
vn 0.6663 0.6663 0.3347
|
||||
vn 0.6663 0.3347 0.6663
|
||||
vn 0.7041 0.0919 0.7041
|
||||
vn 0.5774 0.5774 0.5773
|
||||
vn 0.1004 0.9899 0.1004
|
||||
vn 0.0981 0.9201 0.3792
|
||||
vn 0.3673 0.8545 0.3673
|
||||
vn 0.3792 0.9201 0.0981
|
||||
vn 0.0919 0.7041 0.7041
|
||||
vn 0.3347 0.6663 0.6663
|
||||
vn 0.3792 0.0981 0.9201
|
||||
vn 0.3673 0.3673 0.8545
|
||||
vn 0.0981 0.3792 0.9201
|
||||
vn 0.0981 -0.3792 0.9201
|
||||
vn 0.3673 -0.3673 0.8545
|
||||
vn 0.3792 -0.0981 0.9201
|
||||
vn 0.0919 -0.7041 0.7041
|
||||
vn 0.3347 -0.6663 0.6663
|
||||
vn 0.6663 -0.3347 0.6663
|
||||
vn 0.7041 -0.0919 0.7041
|
||||
vn 0.5773 -0.5774 0.5774
|
||||
vn 0.3792 -0.9201 0.0981
|
||||
vn 0.3673 -0.8545 0.3673
|
||||
vn 0.0981 -0.9201 0.3792
|
||||
vn 0.7041 -0.7041 0.0919
|
||||
vn 0.6663 -0.6663 0.3347
|
||||
vn 0.9201 -0.0981 0.3792
|
||||
vn 0.8545 -0.3673 0.3673
|
||||
vn 0.9201 -0.3792 0.0981
|
||||
vn -0.9201 0.3792 -0.0981
|
||||
vn -0.8545 0.3673 -0.3673
|
||||
vn -0.9201 0.0981 -0.3792
|
||||
vn -0.7041 0.7041 -0.0919
|
||||
vn -0.6663 0.6663 -0.3347
|
||||
vn -0.6663 0.3347 -0.6663
|
||||
vn -0.7041 0.0919 -0.7041
|
||||
vn -0.5774 0.5774 -0.5773
|
||||
vn -0.1004 0.9899 -0.1004
|
||||
vn -0.0981 0.9201 -0.3792
|
||||
vn -0.3673 0.8545 -0.3673
|
||||
vn -0.3792 0.9201 -0.0981
|
||||
vn -0.0919 0.7041 -0.7041
|
||||
vn -0.3347 0.6663 -0.6663
|
||||
vn -0.3792 0.0981 -0.9201
|
||||
vn -0.3673 0.3673 -0.8545
|
||||
vn -0.0981 0.3792 -0.9201
|
||||
vn -0.0981 -0.3792 -0.9201
|
||||
vn -0.3673 -0.3673 -0.8545
|
||||
vn -0.3792 -0.0981 -0.9201
|
||||
vn -0.0919 -0.7041 -0.7041
|
||||
vn -0.3347 -0.6663 -0.6663
|
||||
vn -0.6663 -0.3347 -0.6663
|
||||
vn -0.7041 -0.0919 -0.7041
|
||||
vn -0.5773 -0.5774 -0.5774
|
||||
vn -0.3792 -0.9201 -0.0981
|
||||
vn -0.3673 -0.8545 -0.3673
|
||||
vn -0.0981 -0.9201 -0.3792
|
||||
vn -0.7041 -0.7041 -0.0919
|
||||
vn -0.6663 -0.6663 -0.3347
|
||||
vn -0.9201 -0.0981 -0.3792
|
||||
vn -0.8545 -0.3673 -0.3673
|
||||
vn -0.9201 -0.3792 -0.0981
|
||||
vn -0.9201 0.0981 0.3792
|
||||
vn -0.8545 0.3673 0.3673
|
||||
vn -0.9201 0.3792 0.0981
|
||||
vn -0.7041 0.0919 0.7041
|
||||
vn -0.6663 0.3347 0.6663
|
||||
vn -0.6663 0.6663 0.3347
|
||||
vn -0.7041 0.7041 0.0919
|
||||
vn -0.5774 0.5774 0.5773
|
||||
vn -0.0981 0.3792 0.9201
|
||||
vn -0.3673 0.3673 0.8545
|
||||
vn -0.3792 0.0981 0.9201
|
||||
vn -0.0919 0.7041 0.7041
|
||||
vn -0.3347 0.6663 0.6663
|
||||
vn -0.1004 0.9899 0.1004
|
||||
vn -0.3792 0.9201 0.0981
|
||||
vn -0.3673 0.8545 0.3673
|
||||
vn -0.0981 0.9201 0.3792
|
||||
vn -0.3792 -0.0981 0.9201
|
||||
vn -0.3673 -0.3673 0.8545
|
||||
vn -0.0981 -0.3792 0.9201
|
||||
vn -0.7041 -0.0919 0.7041
|
||||
vn -0.6663 -0.3347 0.6663
|
||||
vn -0.3347 -0.6663 0.6663
|
||||
vn -0.0919 -0.7041 0.7041
|
||||
vn -0.5774 -0.5774 0.5773
|
||||
vn -0.9201 -0.3792 0.0981
|
||||
vn -0.8545 -0.3673 0.3673
|
||||
vn -0.9201 -0.0981 0.3792
|
||||
vn -0.7041 -0.7041 0.0919
|
||||
vn -0.6663 -0.6663 0.3347
|
||||
vn -0.0981 -0.9201 0.3792
|
||||
vn -0.3673 -0.8545 0.3673
|
||||
vn -0.3792 -0.9201 0.0981
|
||||
s 1
|
||||
f 58/1/1 41/2/2 116/3/3 134/4/4
|
||||
f 96/5/5 79/6/6 3/7/7 22/8/8
|
||||
f 20/9/9 2/10/10 39/11/11 60/12/12
|
||||
f 135/13/13 115/14/14 77/15/15 98/16/16
|
||||
f 97/17/17 21/18/18 59/19/19 136/20/20
|
||||
f 1/21/21 4/22/22 7/23/23 6/24/24
|
||||
f 4/22/22 5/25/25 8/26/26 7/23/23
|
||||
f 6/24/24 7/23/23 19/27/27 16/28/28
|
||||
f 7/23/23 8/26/26 9/29/29 19/27/27
|
||||
f 2/10/10 10/30/30 13/31/31 12/32/32
|
||||
f 10/30/30 11/33/33 14/34/34 13/31/31
|
||||
f 12/32/32 13/31/31 8/35/26 5/36/25
|
||||
f 13/31/31 14/34/34 9/37/29 8/35/26
|
||||
f 3/7/7 15/38/35 18/39/36 17/40/37
|
||||
f 15/38/35 16/41/28 19/42/27 18/39/36
|
||||
f 17/40/37 18/39/36 14/43/34 11/44/33
|
||||
f 18/39/36 19/42/27 9/45/29 14/43/34
|
||||
f 20/9/9 23/46/38 26/47/39 25/48/40
|
||||
f 23/46/38 24/49/41 27/50/42 26/47/39
|
||||
f 25/48/40 26/47/39 38/51/43 35/52/44
|
||||
f 26/47/39 27/50/42 28/53/45 38/51/43
|
||||
f 21/18/18 29/54/46 32/55/47 31/56/48
|
||||
f 29/54/46 30/57/49 33/58/50 32/55/47
|
||||
f 31/56/48 32/55/47 27/59/42 24/60/41
|
||||
f 32/55/47 33/58/50 28/61/45 27/59/42
|
||||
f 22/8/8 34/62/51 37/63/52 36/64/53
|
||||
f 34/62/51 35/65/44 38/66/43 37/63/52
|
||||
f 36/64/53 37/63/52 33/67/50 30/68/49
|
||||
f 37/63/52 38/66/43 28/69/45 33/67/50
|
||||
f 39/11/11 42/70/54 45/71/55 44/72/56
|
||||
f 42/70/54 43/73/57 46/74/58 45/71/55
|
||||
f 44/72/56 45/71/55 57/75/59 54/76/60
|
||||
f 45/71/55 46/74/58 47/77/61 57/75/59
|
||||
f 40/78/62 48/79/63 51/80/64 50/81/65
|
||||
f 48/79/63 49/82/66 52/83/67 51/80/64
|
||||
f 50/81/65 51/80/64 46/84/58 43/85/57
|
||||
f 51/80/64 52/83/67 47/86/61 46/84/58
|
||||
f 41/2/2 53/87/68 56/88/69 55/89/70
|
||||
f 53/87/68 54/90/60 57/91/59 56/88/69
|
||||
f 55/89/70 56/88/69 52/92/67 49/93/66
|
||||
f 56/88/69 57/91/59 47/94/61 52/92/67
|
||||
f 58/1/1 61/95/71 64/96/72 63/97/73
|
||||
f 61/95/71 62/98/74 65/99/75 64/96/72
|
||||
f 63/97/73 64/96/72 76/100/76 73/101/77
|
||||
f 64/96/72 65/99/75 66/102/78 76/100/76
|
||||
f 59/19/19 67/103/79 70/104/80 69/105/81
|
||||
f 67/103/79 68/106/82 71/107/83 70/104/80
|
||||
f 69/105/81 70/104/80 65/108/75 62/109/74
|
||||
f 70/104/80 71/107/83 66/110/78 65/108/75
|
||||
f 60/12/12 72/111/84 75/112/85 74/113/86
|
||||
f 72/111/84 73/114/77 76/115/76 75/112/85
|
||||
f 74/113/86 75/112/85 71/116/83 68/117/82
|
||||
f 75/112/85 76/115/76 66/118/78 71/116/83
|
||||
f 77/15/15 80/119/87 83/120/88 82/121/89
|
||||
f 80/119/87 81/122/90 84/123/91 83/120/88
|
||||
f 82/121/89 83/120/88 95/124/92 92/125/93
|
||||
f 83/120/88 84/123/91 85/126/94 95/124/92
|
||||
f 78/127/95 86/128/96 89/129/97 88/130/98
|
||||
f 86/128/96 87/131/99 90/132/100 89/129/97
|
||||
f 88/130/98 89/129/97 84/133/91 81/134/90
|
||||
f 89/129/97 90/132/100 85/135/94 84/133/91
|
||||
f 79/6/6 91/136/101 94/137/102 93/138/103
|
||||
f 91/136/101 92/139/93 95/140/92 94/137/102
|
||||
f 93/138/103 94/137/102 90/141/100 87/142/99
|
||||
f 94/137/102 95/140/92 85/143/94 90/141/100
|
||||
f 96/5/5 99/144/104 102/145/105 101/146/106
|
||||
f 99/144/104 100/147/107 103/148/108 102/145/105
|
||||
f 101/146/106 102/145/105 114/149/109 111/150/110
|
||||
f 102/145/105 103/148/108 104/151/111 114/149/109
|
||||
f 97/17/17 105/152/112 108/153/113 107/154/114
|
||||
f 105/152/112 106/155/115 109/156/116 108/153/113
|
||||
f 107/154/114 108/153/113 103/157/108 100/158/107
|
||||
f 108/153/113 109/156/116 104/159/111 103/157/108
|
||||
f 98/16/16 110/160/117 113/161/118 112/162/119
|
||||
f 110/160/117 111/163/110 114/164/109 113/161/118
|
||||
f 112/162/119 113/161/118 109/165/116 106/166/115
|
||||
f 113/161/118 114/164/109 104/167/111 109/165/116
|
||||
f 115/14/14 118/168/120 121/169/121 120/170/122
|
||||
f 118/168/120 119/171/123 122/172/124 121/169/121
|
||||
f 120/170/122 121/169/121 133/173/125 130/174/126
|
||||
f 121/169/121 122/172/124 123/175/127 133/173/125
|
||||
f 116/3/3 124/176/128 127/177/129 126/178/130
|
||||
f 124/176/128 125/179/131 128/180/132 127/177/129
|
||||
f 126/178/130 127/177/129 122/181/124 119/182/123
|
||||
f 127/177/129 128/180/132 123/183/127 122/181/124
|
||||
f 117/184/133 129/185/134 132/186/135 131/187/136
|
||||
f 129/185/134 130/188/126 133/189/125 132/186/135
|
||||
f 131/187/136 132/186/135 128/190/132 125/191/131
|
||||
f 132/186/135 133/189/125 123/192/127 128/190/132
|
||||
f 134/4/4 137/193/137 140/194/138 139/195/139
|
||||
f 137/193/137 138/196/140 141/197/141 140/194/138
|
||||
f 139/195/139 140/194/138 152/198/142 149/199/143
|
||||
f 140/194/138 141/197/141 142/200/144 152/198/142
|
||||
f 135/13/13 143/201/145 146/202/146 145/203/147
|
||||
f 143/201/145 144/204/148 147/205/149 146/202/146
|
||||
f 145/203/147 146/202/146 141/206/141 138/207/140
|
||||
f 146/202/146 147/205/149 142/208/144 141/206/141
|
||||
f 136/20/20 148/209/150 151/210/151 150/211/152
|
||||
f 148/209/150 149/212/143 152/213/142 151/210/151
|
||||
f 150/211/152 151/210/151 147/214/149 144/215/148
|
||||
f 151/210/151 152/213/142 142/216/144 147/214/149
|
||||
f 136/20/20 59/19/19 69/105/81 148/209/150
|
||||
f 148/209/150 69/105/81 62/109/74 149/212/143
|
||||
f 149/199/143 62/98/74 61/95/71 139/195/139
|
||||
f 139/195/139 61/95/71 58/1/1 134/4/4
|
||||
f 59/19/19 21/18/18 31/56/48 67/103/79
|
||||
f 67/103/79 31/56/48 24/60/41 68/106/82
|
||||
f 68/117/82 24/49/41 23/46/38 74/113/86
|
||||
f 74/113/86 23/46/38 20/9/9 60/12/12
|
||||
f 1/21/21 40/78/62 50/81/65 4/22/22
|
||||
f 4/22/22 50/81/65 43/85/57 5/25/25
|
||||
f 5/36/25 43/73/57 42/70/54 12/32/32
|
||||
f 12/32/32 42/70/54 39/11/11 2/10/10
|
||||
f 21/18/18 97/17/17 107/154/114 29/54/46
|
||||
f 29/54/46 107/154/114 100/158/107 30/57/49
|
||||
f 30/68/49 100/147/107 99/144/104 36/64/53
|
||||
f 36/64/53 99/144/104 96/5/5 22/8/8
|
||||
f 117/184/133 78/127/95 88/130/98 129/185/134
|
||||
f 129/185/134 88/130/98 81/134/90 130/188/126
|
||||
f 130/174/126 81/122/90 80/119/87 120/170/122
|
||||
f 120/170/122 80/119/87 77/15/15 115/14/14
|
||||
f 97/17/17 136/20/20 150/211/152 105/152/112
|
||||
f 105/152/112 150/211/152 144/215/148 106/155/115
|
||||
f 106/166/115 144/204/148 143/201/145 112/162/119
|
||||
f 112/162/119 143/201/145 135/13/13 98/16/16
|
||||
f 40/78/62 117/184/133 131/187/136 48/79/63
|
||||
f 48/79/63 131/187/136 125/191/131 49/82/66
|
||||
f 49/93/66 125/179/131 124/176/128 55/89/70
|
||||
f 55/89/70 124/176/128 116/3/3 41/2/2
|
||||
f 41/2/2 58/1/1 63/97/73 53/87/68
|
||||
f 53/87/68 63/97/73 73/101/77 54/90/60
|
||||
f 54/76/60 73/114/77 72/111/84 44/72/56
|
||||
f 44/72/56 72/111/84 60/12/12 39/11/11
|
||||
f 2/10/10 20/9/9 25/48/40 10/30/30
|
||||
f 10/30/30 25/48/40 35/52/44 11/33/33
|
||||
f 11/44/33 35/65/44 34/62/51 17/40/37
|
||||
f 17/40/37 34/62/51 22/8/8 3/7/7
|
||||
f 134/4/4 116/3/3 126/178/130 137/193/137
|
||||
f 137/193/137 126/178/130 119/182/123 138/196/140
|
||||
f 138/207/140 119/171/123 118/168/120 145/203/147
|
||||
f 145/203/147 118/168/120 115/14/14 135/13/13
|
||||
f 78/127/95 1/21/21 6/24/24 86/128/96
|
||||
f 86/128/96 6/24/24 16/28/28 87/131/99
|
||||
f 87/142/99 16/41/28 15/38/35 93/138/103
|
||||
f 93/138/103 15/38/35 3/7/7 79/6/6
|
||||
f 79/6/6 96/5/5 101/146/106 91/136/101
|
||||
f 91/136/101 101/146/106 111/150/110 92/139/93
|
||||
f 92/125/93 111/163/110 110/160/117 82/121/89
|
||||
f 82/121/89 110/160/117 98/16/16 77/15/15
|
||||
f 1/21/21 78/127/95 117/184/133 40/78/62
|
||||
29
gfx/assets/shaders/phong.fragment.glsl
Normal file
29
gfx/assets/shaders/phong.fragment.glsl
Normal file
@@ -0,0 +1,29 @@
|
||||
#version 330 core
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
|
||||
uniform vec3 light_pos;
|
||||
uniform vec4 solid_color;
|
||||
uniform vec3 camera;
|
||||
|
||||
in vec3 normal;
|
||||
in vec3 frag_position;
|
||||
|
||||
void main() {
|
||||
vec4 light_color = vec4(1, 1, 1, 1);
|
||||
vec3 normal_norm = normalize(normal);
|
||||
vec3 light_direction_norm = normalize(light_pos - frag_position);
|
||||
|
||||
float ambient_strength = 0.15;
|
||||
vec4 ambient = ambient_strength * light_color;
|
||||
|
||||
float diffuse_strength = max(dot(normal_norm, light_direction_norm), 0.0);
|
||||
vec4 diffuse = diffuse_strength * light_color;
|
||||
|
||||
float specular_strength = 0.9;
|
||||
vec3 view_direction_norm = normalize(camera - frag_position);
|
||||
vec3 reflect_dir = reflect(-light_direction_norm, normal_norm);
|
||||
float spec = pow(max(dot(view_direction_norm, reflect_dir), 0.0), 32);
|
||||
vec4 specular = specular_strength * spec * light_color;
|
||||
|
||||
frag_color = specular + (ambient + diffuse) * solid_color;
|
||||
}
|
||||
19
gfx/assets/shaders/phong.vertex.glsl
Normal file
19
gfx/assets/shaders/phong.vertex.glsl
Normal file
@@ -0,0 +1,19 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 a_xyz;
|
||||
layout (location = 1) in vec2 a_uv;
|
||||
layout (location = 2) in vec3 a_normal;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
out vec3 normal;
|
||||
out vec3 frag_position;
|
||||
|
||||
void main() {
|
||||
vec4 a_xyz_vec4 = vec4(a_xyz, 1);
|
||||
|
||||
frag_position = (model * a_xyz_vec4).xyz;
|
||||
normal = mat3(transpose(inverse(model))) * a_normal;
|
||||
gl_Position = projection * view * model * a_xyz_vec4;
|
||||
}
|
||||
61
gfx/assets/shaders/rect.fragment.glsl
Normal file
61
gfx/assets/shaders/rect.fragment.glsl
Normal file
@@ -0,0 +1,61 @@
|
||||
#version 330 core
|
||||
out vec4 pixel_color;
|
||||
|
||||
in vec4 frag_color;
|
||||
in vec2 frag_dest_position;
|
||||
in vec2 frag_dest_center;
|
||||
in vec2 frag_dest_half_size;
|
||||
in float frag_softness;
|
||||
in float frag_border_radius;
|
||||
in float frag_border_thickness;
|
||||
in vec4 frag_border_color;
|
||||
in vec2 uv;
|
||||
|
||||
uniform sampler2D rect_tex;
|
||||
|
||||
float roundedRectSDF(vec2 sample_pos, vec2 rect_center, vec2 rect_half_size, float r) {
|
||||
vec2 d2 = (abs(rect_center - sample_pos) - rect_half_size + vec2(r, r));
|
||||
return min(max(d2.x, d2.y), 0.0) + length(max(d2, 0.0)) - r;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 softness_padding = vec2(
|
||||
max(0, frag_softness*2-1),
|
||||
max(0, frag_softness*2-1));
|
||||
|
||||
float border_factor = 1.0f;
|
||||
if (frag_border_thickness != 0) {
|
||||
vec2 interior_half_size = frag_dest_half_size - vec2(frag_border_thickness);
|
||||
|
||||
float interior_radius_reduce_f = min(
|
||||
interior_half_size.x / frag_dest_half_size.x,
|
||||
interior_half_size.y / frag_dest_half_size.y);
|
||||
|
||||
float interior_corner_radius = frag_border_radius * interior_radius_reduce_f * interior_radius_reduce_f;
|
||||
|
||||
float inside_d = roundedRectSDF(
|
||||
frag_dest_position,
|
||||
frag_dest_center,
|
||||
interior_half_size - softness_padding,
|
||||
interior_corner_radius);
|
||||
|
||||
|
||||
float inside_f = smoothstep(0, 2*frag_softness, inside_d);
|
||||
border_factor = inside_f;
|
||||
}
|
||||
|
||||
float dist = roundedRectSDF(
|
||||
frag_dest_position,
|
||||
frag_dest_center,
|
||||
frag_dest_half_size - softness_padding,
|
||||
frag_border_radius);
|
||||
|
||||
// For texturing later
|
||||
float sample = 1;
|
||||
|
||||
float sdf_factor = 1 - smoothstep(0, 2*frag_softness, dist);
|
||||
|
||||
vec4 out_color = frag_color; //* texture(rect_tex, uv);
|
||||
pixel_color = frag_border_color * sample * sdf_factor * border_factor
|
||||
+ out_color * sample * sdf_factor;
|
||||
};
|
||||
56
gfx/assets/shaders/rect.vertex.glsl
Normal file
56
gfx/assets/shaders/rect.vertex.glsl
Normal file
@@ -0,0 +1,56 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec2 p0;
|
||||
layout (location = 1) in vec2 p1;
|
||||
layout (location = 2) in vec4 color;
|
||||
layout (location = 3) in float border_radius;
|
||||
layout (location = 4) in float border_thickness;
|
||||
layout (location = 5) in vec4 border_color;
|
||||
layout (location = 6) in float edge_softness;
|
||||
|
||||
uniform mat4 projection;
|
||||
|
||||
out vec4 frag_color;
|
||||
out vec2 frag_dest_position;
|
||||
out vec2 frag_dest_center;
|
||||
out vec2 frag_dest_half_size;
|
||||
out float frag_softness;
|
||||
out float frag_border_radius;
|
||||
out float frag_border_thickness;
|
||||
out vec4 frag_border_color;
|
||||
out vec2 uv;
|
||||
|
||||
const vec2 rectangle_uv[4] = vec2[](
|
||||
vec2(0, 1),
|
||||
vec2(0, 0),
|
||||
vec2(1, 1),
|
||||
vec2(1, 0)
|
||||
);
|
||||
|
||||
const vec2 rectangle_vertices[4] = vec2[](
|
||||
vec2(-1, -1),
|
||||
vec2(-1, 1),
|
||||
vec2( 1, -1),
|
||||
vec2( 1, 1)
|
||||
);
|
||||
|
||||
void main() {
|
||||
vec2 dest_half_size = (p1 - p0) / 2;
|
||||
vec2 dest_center = (p1 + p0) / 2;
|
||||
vec2 dest_position = rectangle_vertices[gl_VertexID] * dest_half_size + dest_center;
|
||||
|
||||
gl_Position = projection * vec4(
|
||||
dest_position,
|
||||
0,
|
||||
1
|
||||
);
|
||||
|
||||
frag_color = color;
|
||||
frag_dest_position = dest_position;
|
||||
frag_dest_center = dest_center;
|
||||
frag_dest_half_size = dest_half_size;
|
||||
frag_border_radius = border_radius;
|
||||
frag_border_thickness = border_thickness;
|
||||
frag_border_color = border_color;
|
||||
frag_softness = edge_softness;
|
||||
uv = rectangle_uv[gl_VertexID];
|
||||
}
|
||||
11
gfx/assets/shaders/text.fragment.glsl
Normal file
11
gfx/assets/shaders/text.fragment.glsl
Normal file
@@ -0,0 +1,11 @@
|
||||
#version 330 core
|
||||
out vec4 pixel_color;
|
||||
|
||||
in vec4 frag_color;
|
||||
in vec2 frag_uv_position;
|
||||
|
||||
uniform sampler2D glyph_atlas;
|
||||
|
||||
void main() {
|
||||
pixel_color = vec4(frag_color.xyz,texture(glyph_atlas, frag_uv_position).r);
|
||||
};
|
||||
58
gfx/assets/shaders/text.vertex.glsl
Normal file
58
gfx/assets/shaders/text.vertex.glsl
Normal file
@@ -0,0 +1,58 @@
|
||||
#version 330 core
|
||||
layout (location = 0) in vec2 begin;
|
||||
layout (location = 1) in int glyph;
|
||||
layout (location = 2) in float fontSize;
|
||||
layout (location = 3) in vec4 color;
|
||||
|
||||
uniform samplerBuffer glyph_table;
|
||||
|
||||
uniform mat4 projection;
|
||||
uniform sampler2D font;
|
||||
|
||||
out vec4 frag_color;
|
||||
out vec2 frag_uv_position;
|
||||
|
||||
const vec2 rectangle_vertices[4] = vec2[](
|
||||
vec2(-1, -1), // bl
|
||||
vec2(-1, 1), // tl
|
||||
vec2( 1, -1), // br
|
||||
vec2( 1, 1) // tr
|
||||
);
|
||||
|
||||
const vec2 uv0_vertices[4] = vec2[](
|
||||
vec2(1, 0), // bl
|
||||
vec2(1, 1), // tl
|
||||
vec2(0, 0), // br
|
||||
vec2(0, 1) // tr
|
||||
);
|
||||
|
||||
const vec2 uv1_vertices[4] = vec2[](
|
||||
vec2(0, 1),
|
||||
vec2(0, 0),
|
||||
vec2(1, 1),
|
||||
vec2(1, 0)
|
||||
);
|
||||
|
||||
void main() {
|
||||
vec4 chunk1 = texelFetch(glyph_table, glyph * 2 + 0);
|
||||
vec4 chunk2 = texelFetch(glyph_table, glyph * 2 + 1);
|
||||
|
||||
vec2 uv0 = chunk1.xy;
|
||||
vec2 uv1 = chunk1.zw;
|
||||
vec2 offset = chunk2.xy;
|
||||
vec2 dims = chunk2.zw;
|
||||
|
||||
vec2 p0 = begin + offset*fontSize;
|
||||
vec2 p1 = begin + (offset + dims)*fontSize;
|
||||
|
||||
vec2 dest_half_size = (p1 - p0) / 2;
|
||||
vec2 dest_center = (p1 + p0) / 2;
|
||||
vec2 dest_position = rectangle_vertices[gl_VertexID] * dest_half_size + dest_center;
|
||||
|
||||
vec2 uv_position = uv0 * uv0_vertices[gl_VertexID] + uv1 * uv1_vertices[gl_VertexID];
|
||||
|
||||
gl_Position = projection * vec4(dest_position, 0, 1);
|
||||
|
||||
frag_color = color;
|
||||
frag_uv_position = vec2(uv_position.x, uv_position.y);
|
||||
}
|
||||
24
gfx/debug.c
Normal file
24
gfx/debug.c
Normal file
@@ -0,0 +1,24 @@
|
||||
#include "debug.h"
|
||||
|
||||
void printVec3(Vec3 vec) {
|
||||
print(
|
||||
"┌ ┐\n"
|
||||
"│%7.2f%, %7.2f, %7.2f │\n"
|
||||
"└ ┘\n",
|
||||
vec.x, vec.y, vec.z);
|
||||
}
|
||||
|
||||
void printMatrix(Matrix mat) {
|
||||
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);
|
||||
}
|
||||
|
||||
10
gfx/debug.h
Normal file
10
gfx/debug.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef DEBUG_H
|
||||
#define DEBUG_H
|
||||
|
||||
#include "../core.h"
|
||||
#include "../vendor/raymath.h"
|
||||
|
||||
void printRLVec3(Vec3 vector);
|
||||
void printMatrix(Matrix matrix);
|
||||
|
||||
#endif
|
||||
102
gfx/geometry.c
Normal file
102
gfx/geometry.c
Normal file
@@ -0,0 +1,102 @@
|
||||
#include "geometry.h"
|
||||
#include "gfx-common.h"
|
||||
#include "../core.h"
|
||||
|
||||
// Buffer layout:
|
||||
// X, Y, Z, U, V
|
||||
|
||||
const FloatList triangle_vertices = AsList(FloatList, {
|
||||
-0.5f, -0.5f, 0.0f, 1.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.0f, 0.5f, 0.5f,
|
||||
0.0f, 0.5f, 0.0f, 0.0f, 0.0f,
|
||||
});
|
||||
|
||||
const UInt32List triangle_indices = AsList(UInt32List, {
|
||||
0, 1, 2
|
||||
});
|
||||
|
||||
const FloatList cube_vertices = AsList(FloatList, {
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
|
||||
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
|
||||
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
|
||||
});
|
||||
|
||||
const UInt32List cube_indices = AsList(UInt32List, {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
||||
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
|
||||
});
|
||||
|
||||
const FloatList square_xyz = AsList(FloatList, {
|
||||
200.0f, 200.0f, 0.0f,
|
||||
200.0f, -200.0f, 0.0f,
|
||||
-200.0f, -200.0f, 0.0f,
|
||||
-200.0f, 200.0f, 0.0f,
|
||||
});
|
||||
|
||||
const FloatList square_uv = AsList(FloatList, {
|
||||
1.0f, 1.0f,
|
||||
1.0f, 0.0f,
|
||||
0.0f, 0.0f,
|
||||
0.0f, 1.0f,
|
||||
});
|
||||
|
||||
const UInt32List square_indices = AsList(UInt32List, {
|
||||
0, 1, 3,
|
||||
1, 2, 3,
|
||||
});
|
||||
|
||||
const Shape TRIANGLE = {
|
||||
triangle_indices,
|
||||
triangle_vertices,
|
||||
triangle_vertices,
|
||||
};
|
||||
|
||||
const Shape SQUARE = {
|
||||
square_indices,
|
||||
square_uv,
|
||||
square_xyz,
|
||||
};
|
||||
|
||||
const Shape CUBE = {
|
||||
cube_indices,
|
||||
triangle_vertices,
|
||||
triangle_vertices,
|
||||
};
|
||||
16
gfx/geometry.h
Normal file
16
gfx/geometry.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef DJSTDLIB_GEOMETRY_H
|
||||
#define DJSTDLIB_GEOMETRY_H
|
||||
|
||||
#include "gfx-common.h"
|
||||
|
||||
typedef struct {
|
||||
UInt32List indices;
|
||||
FloatList uv;
|
||||
FloatList xyz;
|
||||
} Shape;
|
||||
|
||||
extern const Shape TRIANGLE;
|
||||
extern const Shape SQUARE;
|
||||
extern const Shape CUBE;
|
||||
|
||||
#endif
|
||||
11
gfx/gfx-common.h
Normal file
11
gfx/gfx-common.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef DJSTDLIB_GFX_COMMON_H
|
||||
#define DJSTDLIB_GFX_COMMON_H
|
||||
|
||||
#include "../core.h"
|
||||
|
||||
DefineList(Vec2, Vec2);
|
||||
DefineList(Vec4, Vec4);
|
||||
DefineList(real32, Float);
|
||||
DefineList(uint32, UInt32);
|
||||
|
||||
#endif
|
||||
15
gfx/gfx.c
Normal file
15
gfx/gfx.c
Normal file
@@ -0,0 +1,15 @@
|
||||
#define RAYMATH_IMPLEMENTATION
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#define STB_TRUETYPE_IMPLEMENTATION
|
||||
#define TINYOBJ_LOADER_C_IMPLEMENTATION
|
||||
|
||||
#include "platform.c"
|
||||
#include "render.c"
|
||||
#include "ui.c"
|
||||
#include "debug.c"
|
||||
#include "geometry.c"
|
||||
#include "Mesh.c"
|
||||
#include "Shader.c"
|
||||
#include "Texture.c"
|
||||
#include "Color.c"
|
||||
#include "world/world.c"
|
||||
14
gfx/gfx.h
Normal file
14
gfx/gfx.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef DJSTDLIB_GFX_H
|
||||
#define DJSTDLIB_GFX_H
|
||||
|
||||
#include "platform.h"
|
||||
#include "render.h"
|
||||
#include "ui.h"
|
||||
#include "debug.h"
|
||||
#include "geometry.h"
|
||||
#include "Mesh.h"
|
||||
#include "Shader.h"
|
||||
#include "Texture.h"
|
||||
#include "Color.h"
|
||||
|
||||
#endif
|
||||
1
gfx/lib_include.txt
Normal file
1
gfx/lib_include.txt
Normal file
@@ -0,0 +1 @@
|
||||
-lglfw -lgl -lm
|
||||
211
gfx/main.c
Normal file
211
gfx/main.c
Normal file
@@ -0,0 +1,211 @@
|
||||
// Library initialisation
|
||||
#define RAYMATH_IMPLEMENTATION
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#define STB_TRUETYPE_IMPLEMENTATION
|
||||
#define TINYOBJ_LOADER_C_IMPLEMENTATION
|
||||
|
||||
// Project
|
||||
#include "lib/djstdlib/core.c"
|
||||
#include "gfx/gfx.c"
|
||||
#include "world/world.c"
|
||||
#include "ui.c"
|
||||
#include "render.c"
|
||||
#include "debug.c"
|
||||
|
||||
// Graphics bindings and libs
|
||||
#include "lib/raymath.h"
|
||||
#include "lib/glad/glad.c"
|
||||
#include "GLFW/glfw3.h"
|
||||
|
||||
|
||||
typedef struct Frame Frame;
|
||||
struct Frame {
|
||||
uint32 width;
|
||||
uint32 height;
|
||||
int32 x;
|
||||
int32 y;
|
||||
Camera cam;
|
||||
};
|
||||
|
||||
typedef struct GlobalState GlobalState;
|
||||
struct GlobalState {
|
||||
struct {
|
||||
GLFWwindow *handle;
|
||||
int32 width;
|
||||
int32 height;
|
||||
struct {
|
||||
GLFWcursor *pointer;
|
||||
GLFWcursor *arrow;
|
||||
GLFWcursor *forbidden;
|
||||
} cursors;
|
||||
} window;
|
||||
|
||||
UI_Context *ui;
|
||||
};
|
||||
|
||||
void framebufferSizeCallback(GLFWwindow *window, int width, int height) {
|
||||
Soma *soma = (Soma *)glfwGetWindowUserPointer(window);
|
||||
soma->renderer->width = width;
|
||||
soma->renderer->height = height;
|
||||
}
|
||||
|
||||
GLFWwindow *initWindowAndGL(uint32 windowWidth, uint32 windowHeight) {
|
||||
if (!glfwInit()) {
|
||||
return NULL;
|
||||
}
|
||||
#ifdef GLFW_WAYLAND_APP_ID
|
||||
glfwWindowHintString(GLFW_WAYLAND_APP_ID, "Somaesque");
|
||||
#endif
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_SAMPLES, 4);
|
||||
|
||||
GLFWwindow *window = glfwCreateWindow(
|
||||
windowWidth,
|
||||
windowHeight,
|
||||
#ifdef DJSTDLIB_DEBUG
|
||||
"Somaesque (djstdlib_debug)",
|
||||
#else
|
||||
"Somaesque",
|
||||
#endif
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (window == NULL) {
|
||||
print("Failed to create GLFW window\n");
|
||||
glfwTerminate();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
|
||||
print("Failed to initilaize GLAD\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
glViewport(0, 0, windowWidth, windowHeight);
|
||||
glfwSwapInterval(1);
|
||||
glfwSetInputMode(window, GLFW_CURSOR | GLFW_RAW_MOUSE_MOTION, GLFW_CURSOR_NORMAL);
|
||||
glfwSetWindowSize(window, windowWidth, windowHeight);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
static void onMouseScroll(GLFWwindow *window, real64 deltaX, real64 deltaY) {
|
||||
Soma *soma = (Soma *)glfwGetWindowUserPointer(window);
|
||||
soma->ui->input->mouse.scroll.dX += deltaX;
|
||||
soma->ui->input->mouse.scroll.dY += deltaY;
|
||||
}
|
||||
|
||||
static void updateWindow(Soma *soma) {
|
||||
glfwGetWindowSize(soma->window.handle, &soma->window.width, &soma->window.height);
|
||||
soma->renderer->width = soma->window.width;
|
||||
soma->renderer->height = soma->window.height;
|
||||
}
|
||||
|
||||
const int32 TARGET_FPS = 144;
|
||||
|
||||
void APIENTRY glDebugCallback(GLenum source, GLenum type, GLuint id,
|
||||
GLenum severity, GLsizei length,
|
||||
const GLchar* message, const void* userParam)
|
||||
{
|
||||
fprintf(stderr, "GL: %s\n", message);
|
||||
}
|
||||
|
||||
int mainGfx() {
|
||||
Arena *arena = arenaAlloc(Megabytes(128));
|
||||
Arena *solutionsArena = arenaAlloc(Megabytes(128));
|
||||
|
||||
int32 winWidth = 800;
|
||||
int32 winHeight = 600;
|
||||
GLFWwindow *windowHandle = initWindowAndGL(winWidth, winHeight);
|
||||
if (!windowHandle) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
glEnable(GL_DEBUG_OUTPUT);
|
||||
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
||||
glDebugMessageCallback(glDebugCallback, NULL);
|
||||
|
||||
Scene mainScene = createScene(arena);
|
||||
Camera cam = createCamera(winWidth, winHeight);
|
||||
Renderer renderer = createRenderer(arena, &mainScene, &cam, createSceneGraphNode(&mainScene));
|
||||
|
||||
renderer.solidShader = &solidColorShader;
|
||||
renderer.phongShader = &phongShader;
|
||||
renderer.cubeMesh = &cubeMesh;
|
||||
|
||||
Arena *uiArena = arenaAlloc(Megabytes(64));
|
||||
UI_Context ui = ui_initContext(uiArena, &renderer);
|
||||
|
||||
glfwSetWindowUserPointer(windowHandle, &soma);
|
||||
glfwSetFramebufferSizeCallback(windowHandle, framebufferSizeCallback);
|
||||
glfwSetScrollCallback(windowHandle, onMouseScroll);
|
||||
|
||||
// Render loop
|
||||
real64 lastFrame = glfwGetTime();
|
||||
real64 timeDelta = 1.0f / TARGET_FPS;
|
||||
real64 frameStart = lastFrame;
|
||||
|
||||
Input lastInput = {0};
|
||||
Input currInput = {0};
|
||||
while (!glfwWindowShouldClose(soma.window.handle)) {
|
||||
glfwPollEvents();
|
||||
|
||||
lastInput = currInput;
|
||||
currInput = getCurrentInput(soma.window.handle);
|
||||
|
||||
ui.prevInput = &lastInput;
|
||||
ui.input = &currInput;
|
||||
|
||||
updateWindow(&soma);
|
||||
|
||||
processInput(&soma);
|
||||
|
||||
Render(&renderer) {
|
||||
UI_Pass(&ui) {
|
||||
ui_Soma(&ui, &soma);
|
||||
}
|
||||
|
||||
switch (ui.cursorType) {
|
||||
case UI_Cursor_Arrow:
|
||||
glfwSetCursor(soma.window.handle, soma.window.cursors.arrow);
|
||||
break;
|
||||
case UI_Cursor_Pointer:
|
||||
glfwSetCursor(soma.window.handle, soma.window.cursors.pointer);
|
||||
break;
|
||||
case UI_Cursor_Forbidden:
|
||||
glfwSetCursor(soma.window.handle, soma.window.cursors.forbidden);
|
||||
break;
|
||||
default:
|
||||
glfwSetCursor(soma.window.handle, soma.window.cursors.arrow);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
updatePolycubeDisplay(&soma);
|
||||
|
||||
recalcScene(soma.scene);
|
||||
|
||||
glfwSwapBuffers(soma.window.handle);
|
||||
|
||||
real64 frameEnd = glfwGetTime();
|
||||
real64 frameTime = frameEnd - frameStart;
|
||||
lastFrame = frameStart;
|
||||
|
||||
//println("FPS: %.7f", 1/(frameTime));
|
||||
|
||||
frameStart = glfwGetTime();
|
||||
|
||||
soma.prevState = soma.state;
|
||||
soma.state.isInitialState = false;
|
||||
}
|
||||
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
}
|
||||
163
gfx/platform.c
Normal file
163
gfx/platform.c
Normal file
@@ -0,0 +1,163 @@
|
||||
#include "platform.h"
|
||||
|
||||
#define RAYMATH_IMPLEMENTATION
|
||||
#include "../vendor/glad/glad.c"
|
||||
#include "GLFW/glfw3.h"
|
||||
|
||||
typedef struct OS_WindowPlatformData OS_WindowPlatformData;
|
||||
struct OS_WindowPlatformData {
|
||||
OS_WindowEventCallback eventHandler;
|
||||
real64 mouseWheelFrameDX;
|
||||
real64 mouseWheelFrameDY;
|
||||
};
|
||||
|
||||
static void os_glfw_onFramebufferResize(GLFWwindow *window, int32 width, int32 height) {
|
||||
OS_Window *osWindow = (OS_Window *)glfwGetWindowUserPointer(window);
|
||||
osWindow->width = width;
|
||||
osWindow->height = height;
|
||||
OS_WindowEvent event = (OS_WindowEvent){.kind=OS_WindowEventKind_Resize, .resize={width, height}};
|
||||
((OS_WindowPlatformData *)osWindow->platformData)->eventHandler(&event, osWindow);
|
||||
}
|
||||
|
||||
static void os_glfw_onMouseScroll(GLFWwindow *window, real64 x, real64 y) {
|
||||
OS_Window *osWindow = (OS_Window *)glfwGetWindowUserPointer(window);
|
||||
}
|
||||
|
||||
OS_WindowInitResult os_windowInit(Arena *arena, OS_WindowInitParams params) {
|
||||
Scratch scratch = scratchStart(NULL, 0);
|
||||
OS_WindowInitResult result = {.result=NULL, .valid=true};
|
||||
|
||||
if (glfwInit()) {
|
||||
const char *windowNameCStr = cstring(scratch.arena, params.name);
|
||||
#ifdef GLFW_WAYLAND_APP_ID
|
||||
glfwWindowHintString(GLFW_WAYLAND_APP_ID, windowNameCStr);
|
||||
#endif
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_SAMPLES, 4);
|
||||
|
||||
GLFWwindow *glfwWindow = glfwCreateWindow(
|
||||
params.width,
|
||||
params.height,
|
||||
#ifdef DJSTDLIB_DEBUG
|
||||
cstring(scratch.arena, print("%s (djstdlib_debug)", windowNameCStr)),
|
||||
#else
|
||||
windowNameCStr,
|
||||
#endif
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (glfwWindow != NULL) {
|
||||
glfwMakeContextCurrent(glfwWindow);
|
||||
|
||||
if (gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
|
||||
glViewport(0, 0, params.width, params.height);
|
||||
glfwSwapInterval(1);
|
||||
glfwSetInputMode(glfwWindow, GLFW_CURSOR | GLFW_RAW_MOUSE_MOTION, GLFW_CURSOR_NORMAL);
|
||||
glfwSetWindowSize(glfwWindow, params.width, params.height);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
|
||||
glEnable(GL_DEBUG_OUTPUT);
|
||||
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
||||
|
||||
//glDebugMessageCallback(glDebugCallback, NULL);
|
||||
|
||||
OS_Window *osWindow = PushStructZero(arena, OS_Window);
|
||||
OS_WindowPlatformData *platformData = PushStructZero(arena, OS_WindowPlatformData);
|
||||
osWindow->platformData = platformData;
|
||||
|
||||
platformData->eventHandler = params.eventHandler;
|
||||
platformData->eventHandler = params.eventHandler;
|
||||
|
||||
osWindow->userData = params.data;
|
||||
osWindow->width = params.width;
|
||||
osWindow->height = params.height;
|
||||
osWindow->handle = glfwWindow;
|
||||
|
||||
glfwSetWindowUserPointer(glfwWindow, osWindow);
|
||||
glfwSetFramebufferSizeCallback(glfwWindow, os_glfw_onFramebufferResize);
|
||||
glfwSetScrollCallback(glfwWindow, os_glfw_onMouseScroll);
|
||||
|
||||
result.result = osWindow;
|
||||
} else {
|
||||
print("os_windowInit::Failed to initilaize GLAD\n");
|
||||
result.valid = false;
|
||||
}
|
||||
} else {
|
||||
print("os_windowInit::Failed to create GLFW window\n");
|
||||
glfwTerminate();
|
||||
result.valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
scratchEnd(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool os_windowShouldClose(OS_Window *window) {
|
||||
return (bool)glfwWindowShouldClose((GLFWwindow*)window->handle);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void os_windowGetInput(OS_Window *window, OS_Input *input) {
|
||||
*input = (OS_Input){0};
|
||||
|
||||
GLFWwindow *handle = (GLFWwindow*)window->handle;
|
||||
|
||||
input->keyboard.escape = glfwKey(handle, GLFW_KEY_ESCAPE);
|
||||
input->keyboard.enter = glfwKey(handle, GLFW_KEY_ENTER);
|
||||
input->keyboard.space = glfwKey(handle, GLFW_KEY_SPACE);
|
||||
input->keyboard.lshift = glfwKey(handle, GLFW_KEY_LEFT_SHIFT);
|
||||
input->keyboard.w = glfwKey(handle, GLFW_KEY_W);
|
||||
input->keyboard.x = glfwKey(handle, GLFW_KEY_X);
|
||||
input->keyboard.y = glfwKey(handle, GLFW_KEY_Y);
|
||||
input->keyboard.z = glfwKey(handle, GLFW_KEY_Z);
|
||||
|
||||
input->mouse.btnLeft = glfwMouse(handle, GLFW_MOUSE_BUTTON_LEFT);
|
||||
input->mouse.btnRight = glfwMouse(handle, GLFW_MOUSE_BUTTON_RIGHT);
|
||||
input->mouse.btnMiddle = glfwMouse(handle, GLFW_MOUSE_BUTTON_MIDDLE);
|
||||
|
||||
real64 mouseX;
|
||||
real64 mouseY;
|
||||
glfwGetCursorPos(handle, &mouseX, &mouseY);
|
||||
input->mouse.point = (Vec2){(real32)mouseX, (real32)mouseY};
|
||||
input->mouse.scroll.dX = ((OS_WindowPlatformData *)window->platformData)->mouseWheelFrameDX;
|
||||
input->mouse.scroll.dY = ((OS_WindowPlatformData *)window->platformData)->mouseWheelFrameDY;
|
||||
}
|
||||
|
||||
void os_windowSwapBuffers(OS_Window *window) {
|
||||
glfwSwapBuffers((GLFWwindow*)window->handle);
|
||||
}
|
||||
|
||||
void os_windowFrameBegin(OS_Window *window) {
|
||||
OS_WindowPlatformData *platformData = (OS_WindowPlatformData*)window->platformData;
|
||||
platformData->mouseWheelFrameDX = 0;
|
||||
platformData->mouseWheelFrameDY = 0;
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
void os_windowFrameEnd(OS_Window *window) {
|
||||
real64 end = glfwGetTime();
|
||||
real64 frameTime = end - window->frame.start;
|
||||
window->frame.fps = 1.0f/frameTime;
|
||||
window->frame.start = glfwGetTime();
|
||||
}
|
||||
|
||||
91
gfx/platform.h
Normal file
91
gfx/platform.h
Normal file
@@ -0,0 +1,91 @@
|
||||
#ifndef PLATFORM_H
|
||||
#define PLATFORM_H
|
||||
|
||||
#include "../core.h"
|
||||
|
||||
typedef struct OS_Input OS_Input;
|
||||
struct OS_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;
|
||||
};
|
||||
Vec2 point;
|
||||
};
|
||||
struct {
|
||||
real64 dX;
|
||||
real64 dY;
|
||||
} scroll;
|
||||
bool btnLeft;
|
||||
bool btnRight;
|
||||
bool btnMiddle;
|
||||
} mouse;
|
||||
};
|
||||
|
||||
enum OS_WindowEventKind {
|
||||
OS_WindowEventKind_Resize,
|
||||
|
||||
// ---
|
||||
OS_WindowEventKind_Count,
|
||||
};
|
||||
|
||||
typedef struct OS_WindowEvent OS_WindowEvent;
|
||||
struct OS_WindowEvent {
|
||||
enum OS_WindowEventKind kind;
|
||||
union {
|
||||
struct {
|
||||
int32 width;
|
||||
int32 height;
|
||||
} resize;
|
||||
};
|
||||
};
|
||||
|
||||
struct OS_Window;
|
||||
typedef void (*OS_WindowEventCallback)(OS_WindowEvent *e, struct OS_Window *userData);
|
||||
|
||||
typedef struct OS_WindowInitParams OS_WindowInitParams;
|
||||
struct OS_WindowInitParams {
|
||||
string name;
|
||||
int32 width;
|
||||
int32 height;
|
||||
void *data;
|
||||
OS_WindowEventCallback eventHandler;
|
||||
};
|
||||
|
||||
typedef struct OS_Window OS_Window;
|
||||
struct OS_Window {
|
||||
void *handle;
|
||||
int32 width;
|
||||
int32 height;
|
||||
real64 fps;
|
||||
void *userData;
|
||||
void *platformData;
|
||||
struct {
|
||||
real64 start;
|
||||
real64 fps;
|
||||
} frame;
|
||||
};
|
||||
|
||||
|
||||
DefineResult(OS_Window*, OS_WindowInit);
|
||||
OS_WindowInitResult os_windowInit(Arena *arena, OS_WindowInitParams params);
|
||||
bool os_windowShouldClose(OS_Window *window);
|
||||
void os_windowProcessEvents(OS_Window *window);
|
||||
void os_windowGetInput(OS_Window *window, OS_Input *input);
|
||||
void os_windowSwapBuffers(OS_Window *window);
|
||||
void os_windowFrameBegin(OS_Window *window);
|
||||
void os_windowFrameEnd(OS_Window *window);
|
||||
void os_windowTerminate(OS_Window *window);
|
||||
|
||||
#endif
|
||||
275
gfx/render.c
Normal file
275
gfx/render.c
Normal file
@@ -0,0 +1,275 @@
|
||||
#include "render.h"
|
||||
|
||||
static RenderObjects_Char createCharObjects(Arena *arena, size_t count) {
|
||||
RenderObjects_Char result = {0};
|
||||
result.count = count;
|
||||
|
||||
result.begin.buf = PushFullList(arena, Vec2List, count);
|
||||
result.glyph.buf = PushFullList(arena, IntList, count);
|
||||
result.fontSize.buf = PushFullList(arena, FloatList, count);
|
||||
result.color.buf = PushFullList(arena, Vec4List, count);
|
||||
|
||||
glGenVertexArrays(1, &result.vao);
|
||||
|
||||
glGenBuffers(1, &result.begin.bufId);
|
||||
glGenBuffers(1, &result.glyph.bufId);
|
||||
glGenBuffers(1, &result.fontSize.bufId);
|
||||
glGenBuffers(1, &result.color.bufId);
|
||||
|
||||
glBindVertexArray(result.vao);
|
||||
|
||||
int32 bufItemSize = sizeof(result.begin.buf.data[0]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, result.begin.bufId);
|
||||
glBufferData(GL_ARRAY_BUFFER, result.begin.buf.length * bufItemSize, 0, GL_STREAM_DRAW);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, bufItemSize, NULL);
|
||||
glVertexAttribDivisor(0, 1);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
bufItemSize = sizeof(result.glyph.buf.data[0]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, result.glyph.bufId);
|
||||
glBufferData(GL_ARRAY_BUFFER, result.glyph.buf.length * bufItemSize, 0, GL_STREAM_DRAW);
|
||||
glVertexAttribIPointer(1, 1, GL_INT, bufItemSize, NULL);
|
||||
glVertexAttribDivisor(1, 1);
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
bufItemSize = sizeof(result.fontSize.buf.data[0]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, result.fontSize.bufId);
|
||||
glBufferData(GL_ARRAY_BUFFER, result.fontSize.buf.length * bufItemSize, 0, GL_STREAM_DRAW);
|
||||
glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, bufItemSize, NULL);
|
||||
glVertexAttribDivisor(2, 1);
|
||||
glEnableVertexAttribArray(2);
|
||||
|
||||
bufItemSize = sizeof(result.color.buf.data[0]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, result.color.bufId);
|
||||
glBufferData(GL_ARRAY_BUFFER, result.color.buf.length * bufItemSize, 0, GL_STREAM_DRAW);
|
||||
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, bufItemSize, NULL);
|
||||
glVertexAttribDivisor(3, 1);
|
||||
glEnableVertexAttribArray(3);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static RenderObjects_Rect createRectangleObjects(Arena *arena, size_t count) {
|
||||
RenderObjects_Rect result = {0};
|
||||
result.count = count;
|
||||
|
||||
result.p0.buf = PushFullList(arena, Vec2List, count);
|
||||
result.p1.buf = PushFullList(arena, Vec2List, count);
|
||||
result.color.buf = PushFullList(arena, Vec4List, count);
|
||||
result.borderRadius.buf = PushFullList(arena, FloatList, count);
|
||||
result.borderThickness.buf = PushFullList(arena, FloatList, count);
|
||||
result.borderColor.buf = PushFullList(arena, Vec4List, count);
|
||||
result.edgeSoftness.buf = PushFullList(arena, FloatList, count);
|
||||
|
||||
glGenVertexArrays(1, &result.vao);
|
||||
|
||||
glGenBuffers(1, &result.p0.bufId);
|
||||
glGenBuffers(1, &result.p1.bufId);
|
||||
glGenBuffers(1, &result.color.bufId);
|
||||
glGenBuffers(1, &result.borderRadius.bufId);
|
||||
glGenBuffers(1, &result.borderThickness.bufId);
|
||||
glGenBuffers(1, &result.borderColor.bufId);
|
||||
glGenBuffers(1, &result.edgeSoftness.bufId);
|
||||
|
||||
glBindVertexArray(result.vao);
|
||||
|
||||
int32 bufItemSize = sizeof(result.p0.buf.data[0]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, result.p0.bufId);
|
||||
glBufferData(GL_ARRAY_BUFFER, result.p0.buf.length * bufItemSize, 0, GL_STREAM_DRAW);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, bufItemSize, NULL);
|
||||
glVertexAttribDivisor(0, 1);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
bufItemSize = sizeof(result.p1.buf.data[0]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, result.p1.bufId);
|
||||
glBufferData(GL_ARRAY_BUFFER, result.p1.buf.length * bufItemSize, 0, GL_STREAM_DRAW);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, bufItemSize, NULL);
|
||||
glVertexAttribDivisor(1, 1);
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
bufItemSize = sizeof(result.color.buf.data[0]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, result.color.bufId);
|
||||
glBufferData(GL_ARRAY_BUFFER, result.color.buf.length * bufItemSize, 0, GL_STREAM_DRAW);
|
||||
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, bufItemSize, NULL);
|
||||
glVertexAttribDivisor(2, 1);
|
||||
glEnableVertexAttribArray(2);
|
||||
|
||||
bufItemSize = sizeof(result.borderRadius.buf.data[0]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, result.borderRadius.bufId);
|
||||
glBufferData(GL_ARRAY_BUFFER, result.borderRadius.buf.length * bufItemSize, 0, GL_STREAM_DRAW);
|
||||
glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, bufItemSize, NULL);
|
||||
glVertexAttribDivisor(3, 1);
|
||||
glEnableVertexAttribArray(3);
|
||||
|
||||
bufItemSize = sizeof(result.borderThickness.buf.data[0]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, result.borderThickness.bufId);
|
||||
glBufferData(GL_ARRAY_BUFFER, result.borderThickness.buf.length * bufItemSize, 0, GL_STREAM_DRAW);
|
||||
glVertexAttribPointer(4, 1, GL_FLOAT, GL_FALSE, bufItemSize, NULL);
|
||||
glVertexAttribDivisor(4, 1);
|
||||
glEnableVertexAttribArray(4);
|
||||
|
||||
bufItemSize = sizeof(result.borderColor.buf.data[0]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, result.borderColor.bufId);
|
||||
glBufferData(GL_ARRAY_BUFFER, result.borderColor.buf.length * bufItemSize, 0, GL_STREAM_DRAW);
|
||||
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, bufItemSize, NULL);
|
||||
glVertexAttribDivisor(5, 1);
|
||||
glEnableVertexAttribArray(5);
|
||||
|
||||
bufItemSize = sizeof(result.edgeSoftness.buf.data[0]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, result.edgeSoftness.bufId);
|
||||
glBufferData(GL_ARRAY_BUFFER, result.edgeSoftness.buf.length * bufItemSize, 0, GL_STREAM_DRAW);
|
||||
glVertexAttribPointer(6, 1, GL_FLOAT, GL_FALSE, bufItemSize, NULL);
|
||||
glVertexAttribDivisor(6, 1);
|
||||
glEnableVertexAttribArray(6);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#define GL_UpdateBuffer(buffer) \
|
||||
glBindBuffer(GL_ARRAY_BUFFER, (buffer).bufId);\
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, (buffer).buf.length * sizeof((buffer).underlying), (buffer).buf.data);
|
||||
|
||||
static void updateCharObjectBuffers(Renderer *r) {
|
||||
glBindVertexArray(r->chars.vao);
|
||||
GL_UpdateBuffer(r->chars.begin);
|
||||
GL_UpdateBuffer(r->chars.glyph);
|
||||
GL_UpdateBuffer(r->chars.fontSize);
|
||||
GL_UpdateBuffer(r->chars.color);
|
||||
}
|
||||
|
||||
static void updateRectangleObjectBuffers(Renderer *r) {
|
||||
glBindVertexArray(r->rects.vao);
|
||||
GL_UpdateBuffer(r->rects.p0);
|
||||
GL_UpdateBuffer(r->rects.p1);
|
||||
GL_UpdateBuffer(r->rects.color);
|
||||
GL_UpdateBuffer(r->rects.borderRadius);
|
||||
GL_UpdateBuffer(r->rects.borderThickness);
|
||||
GL_UpdateBuffer(r->rects.borderColor);
|
||||
GL_UpdateBuffer(r->rects.edgeSoftness);
|
||||
}
|
||||
|
||||
Renderer createRenderer(Arena *arena, Scene *scene, Camera *cam, int32 light) {
|
||||
return (Renderer){
|
||||
.scene = scene,
|
||||
.light = light,
|
||||
.camera = cam,
|
||||
.rects = createRectangleObjects(arena, 1024),
|
||||
.chars = createCharObjects(arena, 10000),
|
||||
};
|
||||
}
|
||||
|
||||
void renderBegin(Renderer *r) {
|
||||
r->rects.p0.buf.length = 0;
|
||||
r->rects.p1.buf.length = 0;
|
||||
r->rects.color.buf.length = 0;
|
||||
r->rects.borderRadius.buf.length = 0;
|
||||
r->rects.borderThickness.buf.length = 0;
|
||||
r->rects.borderColor.buf.length = 0;
|
||||
r->rects.edgeSoftness.buf.length = 0;
|
||||
|
||||
r->chars.begin.buf.length = 0;
|
||||
r->chars.glyph.buf.length = 0;
|
||||
r->chars.fontSize.buf.length = 0;
|
||||
r->chars.color.buf.length = 0;
|
||||
|
||||
r->sceneWidth = 0;
|
||||
r->sceneHeight = 0;
|
||||
r->sceneX = 0;
|
||||
r->sceneY = 0;
|
||||
}
|
||||
|
||||
#define CHECK() do{ GLenum e=glGetError(); if(e) printf("GL err 0x%x at %s:%d\n",e,__FILE__,__LINE__); }while(0)
|
||||
|
||||
void renderEnd(Renderer *r) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
// --- 3D Scene ---
|
||||
|
||||
glViewport(r->sceneX, r->height - r->sceneY - r->sceneHeight, r->sceneWidth, r->sceneHeight);
|
||||
cameraSetAspect(r->camera, r->sceneWidth, r->sceneHeight);
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// --- UI overlay ---
|
||||
glViewport(0, 0, r->width, r->height);
|
||||
glUseProgram(r->solidShader->progId);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
Matrix ortho = MatrixOrtho(0.0, r->width, r->height, 0.0, -1.0, 1.0);
|
||||
|
||||
// - 1. Rects
|
||||
updateRectangleObjectBuffers(r);
|
||||
setUniformMat4fv(r->solidShader, "projection", &ortho);
|
||||
glBindVertexArray(r->rects.vao);
|
||||
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, r->rects.p0.buf.length);
|
||||
|
||||
// - 2. Text
|
||||
updateCharObjectBuffers(r);
|
||||
glUseProgram(r->textShader->progId);
|
||||
setUniformMat4fv(r->textShader, "projection", &ortho);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, r->activeFont->texId);
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, r->activeFont->glyphTableTexId);
|
||||
setUniform1i(r->textShader, "glyph_table", 1);
|
||||
|
||||
glBindVertexArray(r->chars.vao);
|
||||
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, r->chars.begin.buf.length);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
void rendererPlaceRectangle(Renderer *r, real32 x, real32 y, real32 width, real32 height, Vec4 color, real32 borderRadius, real32 borderThickness, Vec4 borderColor) {
|
||||
x = roundf(x);
|
||||
y = roundf(y);
|
||||
width = roundf(width);
|
||||
height = roundf(height);
|
||||
ListAppend(r->rects.p0.buf, ((Vec2){ x, y }));
|
||||
ListAppend(r->rects.p1.buf, ((Vec2){ x + width, y + height }));
|
||||
ListAppend(r->rects.color.buf, color);
|
||||
ListAppend(r->rects.borderRadius.buf, borderRadius);
|
||||
ListAppend(r->rects.borderThickness.buf, borderThickness);
|
||||
ListAppend(r->rects.borderColor.buf, borderColor);
|
||||
ListAppend(r->rects.edgeSoftness.buf, 0.15f);
|
||||
}
|
||||
|
||||
void rendererPlaceString(Renderer *r, string s, real32 x, real32 y, Vec4 color, real32 fontSize) {
|
||||
real32 ratio = fontSize / r->activeFont->lineHeight;
|
||||
real32 charWidth = ratio * r->activeFont->charWidth;
|
||||
for (int i = 0; i < s.length; i++) {
|
||||
ListAppend(r->chars.begin.buf, ((Vec2){ .x=x + i*charWidth, .y=y }));
|
||||
ListAppend(r->chars.glyph.buf, s.str[i] - 32);
|
||||
ListAppend(r->chars.fontSize.buf, ratio);
|
||||
ListAppend(r->chars.color.buf, (color));
|
||||
}
|
||||
}
|
||||
102
gfx/render.h
Normal file
102
gfx/render.h
Normal file
@@ -0,0 +1,102 @@
|
||||
#ifndef DJSTDLIB_GFX_RENDER_H
|
||||
#define DJSTDLIB_GFX_RENDER_H
|
||||
|
||||
#include "gfx-common.h"
|
||||
#include "Shader.h"
|
||||
#include "Texture.h"
|
||||
#include "Mesh.h"
|
||||
#include "world/world.h"
|
||||
|
||||
typedef struct RenderObject_BufferInt32 RenderObject_BufferInt32;
|
||||
struct RenderObject_BufferInt32 {
|
||||
IntList buf;
|
||||
uint32 bufId;
|
||||
IntList_underlying underlying;
|
||||
};
|
||||
typedef struct RenderObject_BufferFloat RenderObject_BufferFloat;
|
||||
struct RenderObject_BufferFloat {
|
||||
FloatList buf;
|
||||
uint32 bufId;
|
||||
FloatList_underlying underlying;
|
||||
};
|
||||
typedef struct RenderObject_BufferVec2 RenderObject_BufferVec2;
|
||||
struct RenderObject_BufferVec2 {
|
||||
Vec2List buf;
|
||||
uint32 bufId;
|
||||
Vec2List_underlying underlying;
|
||||
};
|
||||
typedef struct RenderObject_BufferVec4 RenderObject_BufferVec4;
|
||||
struct RenderObject_BufferVec4 {
|
||||
Vec4List buf;
|
||||
uint32 bufId;
|
||||
Vec4List_underlying underlying;
|
||||
};
|
||||
|
||||
|
||||
typedef struct RenderObjects_Rect RenderObjects_Rect;
|
||||
struct RenderObjects_Rect {
|
||||
uint32 vao;
|
||||
uint64 count;
|
||||
RenderObject_BufferVec2 p0;
|
||||
RenderObject_BufferVec2 p1;
|
||||
RenderObject_BufferVec4 color;
|
||||
RenderObject_BufferFloat borderRadius;
|
||||
RenderObject_BufferFloat borderThickness;
|
||||
RenderObject_BufferVec4 borderColor;
|
||||
RenderObject_BufferFloat edgeSoftness;
|
||||
};
|
||||
|
||||
typedef struct RenderObjects_Char RenderObjects_Char;
|
||||
struct RenderObjects_Char {
|
||||
uint32 vao;
|
||||
uint64 count;
|
||||
RenderObject_BufferVec2 begin;
|
||||
RenderObject_BufferInt32 glyph;
|
||||
RenderObject_BufferFloat fontSize;
|
||||
RenderObject_BufferVec4 color;
|
||||
};
|
||||
|
||||
typedef struct GlyphData GlyphData;
|
||||
struct GlyphData {
|
||||
real32 x0;
|
||||
real32 y0;
|
||||
real32 x1;
|
||||
real32 y1;
|
||||
};
|
||||
|
||||
typedef struct Renderer Renderer;
|
||||
struct Renderer {
|
||||
RenderObjects_Rect rects;
|
||||
RenderObjects_Char chars;
|
||||
|
||||
Shader *phongShader;
|
||||
Shader *solidShader;
|
||||
Shader *textShader;
|
||||
|
||||
Font *activeFont;
|
||||
|
||||
int32 width;
|
||||
int32 height;
|
||||
|
||||
int32 sceneWidth;
|
||||
int32 sceneHeight;
|
||||
int32 sceneX;
|
||||
int32 sceneY;
|
||||
|
||||
Scene *scene;
|
||||
Camera *camera;
|
||||
/** SceneGraphNode handle */
|
||||
int32 light;
|
||||
Mesh *cubeMesh;
|
||||
|
||||
int32 testTexId;
|
||||
};
|
||||
|
||||
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, Vec4 color, real32 borderRadius, real32 borderThickness, Vec4 borderColor);
|
||||
void rendererPlaceString(Renderer *r, string s, real32 x, real32 y, Vec4 color, real32 fontSize);
|
||||
#define Render(r) DeferLoop(renderBegin((r)), renderEnd((r)))
|
||||
|
||||
#endif
|
||||
444
gfx/ui.c
Normal file
444
gfx/ui.c
Normal file
@@ -0,0 +1,444 @@
|
||||
#include "ui.h"
|
||||
#include "Color.h"
|
||||
|
||||
UI_Context *__UI_current_ctx__ = NULL;
|
||||
|
||||
UI_Context ui_initContext(Arena *arena, Renderer *renderer) {
|
||||
UI_RectList prevList = PushListZero(arena, UI_RectList, Thousand(10));
|
||||
UI_RectList list = PushListZero(arena, UI_RectList, Thousand(10));
|
||||
ListAppend(list, ((UI_Rect){0})); // empty item
|
||||
return (UI_Context){
|
||||
.arena=arena,
|
||||
.rects=list,
|
||||
.prevRects=prevList,
|
||||
.hotNode=0,
|
||||
.prevHotNode=0,
|
||||
.cursorType=UI_Cursor_Arrow,
|
||||
.scene3DHandle=0,
|
||||
.input=NULL,
|
||||
.prevInput=NULL,
|
||||
.renderer=renderer,
|
||||
};
|
||||
}
|
||||
|
||||
void ui_attachTextAttr(UI_Context *ui, UI_Rect *rect, UI_RectStr strData) {
|
||||
UI_RectStr *strDataCopy = PushStruct(ui->arena, UI_RectStr);
|
||||
*strDataCopy = strData;
|
||||
if (strDataCopy->fontSize == -1) {
|
||||
strDataCopy->fontSize = rect->inheritedTextAttr->fontSize;
|
||||
if (strDataCopy->fontSize == -1) {
|
||||
strDataCopy->fontSize = ui->renderer->activeFont->lineHeight;
|
||||
}
|
||||
}
|
||||
if (strDataCopy->color.r == -1) {
|
||||
strDataCopy->color = rect->inheritedTextAttr->color;
|
||||
}
|
||||
if (strDataCopy->lineHeight == -1) {
|
||||
strDataCopy->lineHeight = rect->inheritedTextAttr->lineHeight;
|
||||
if (strDataCopy->lineHeight == -1) {
|
||||
strDataCopy->lineHeight = strDataCopy->fontSize;
|
||||
}
|
||||
if (strDataCopy->fontSize > strDataCopy->lineHeight) {
|
||||
strDataCopy->lineHeight = strDataCopy->fontSize;
|
||||
}
|
||||
}
|
||||
if (strDataCopy->alignment == -1) {
|
||||
if (rect->inheritedTextAttr->alignment != -1) {
|
||||
strDataCopy->alignment = rect->inheritedTextAttr->alignment;
|
||||
} else {
|
||||
strDataCopy->alignment = UI_TxtAlign_Left;
|
||||
}
|
||||
}
|
||||
rect->inheritedTextAttr = strDataCopy;
|
||||
if (strData.s.str != NULL) {
|
||||
strDataCopy->s = PushString(ui->arena, strData.s.length);
|
||||
memcpy(strDataCopy->s.str, strData.s.str, strData.s.length);
|
||||
rect->stringData = strDataCopy;
|
||||
} else {
|
||||
// NOTE(djledda): Not real text data if empty string -> just style attributes. Ignore
|
||||
}
|
||||
}
|
||||
|
||||
void ui_placeText(UI_Context *ui, UI_RectStr strData) {
|
||||
ui_attachTextAttr(ui, &ui->rects.data[ui->currRect], strData);
|
||||
}
|
||||
|
||||
void ui_sizingPass(UI_Context *ui, bool isXAxis, int32 rectHandle) {
|
||||
UI_Rect *rect = &ui->rects.data[rectHandle];
|
||||
if (!rect->firstChild) return;
|
||||
|
||||
bool isVertical = rect->flags & UI_Flag_Vertical;
|
||||
|
||||
real32 remainingSpace = (isXAxis
|
||||
? rect->resolvedWidth - rect->padding.left - rect->padding.right
|
||||
: rect->resolvedHeight - rect->padding.top - rect->padding.bottom) + rect->childGap;
|
||||
|
||||
int32 growableChildrenCount = 0;
|
||||
|
||||
UI_Rect *child;
|
||||
|
||||
int32 childHandle = rect->firstChild;
|
||||
if (isVertical != isXAxis) {
|
||||
while (childHandle) {
|
||||
child = &ui->rects.data[childHandle];
|
||||
if (!(child->flags & UI_Flag_Pos_Absolute)) {
|
||||
if (child->flags & UI_Flag_HeightGrow && !isXAxis || child->flags & UI_Flag_WidthGrow && isXAxis) {
|
||||
growableChildrenCount++;
|
||||
}
|
||||
real32 childBreadth = isXAxis ? child->resolvedWidth : child->resolvedHeight;
|
||||
remainingSpace -= childBreadth + rect->childGap;
|
||||
}
|
||||
childHandle = child->nextSibling;
|
||||
}
|
||||
}
|
||||
|
||||
real32 childBreadthInc = growableChildrenCount > 0 ? remainingSpace / (real32)growableChildrenCount : 0;
|
||||
|
||||
childHandle = rect->firstChild;
|
||||
while (childHandle) {
|
||||
child = &ui->rects.data[childHandle];
|
||||
|
||||
if (isXAxis) {
|
||||
if (child->flags & UI_Flag_WidthGrow) {
|
||||
if (isVertical) {
|
||||
child->resolvedWidth = rect->resolvedWidth - rect->padding.left - rect->padding.right;
|
||||
} else {
|
||||
child->resolvedWidth += childBreadthInc;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (child->flags & UI_Flag_HeightGrow) {
|
||||
if (!isVertical) {
|
||||
child->resolvedHeight = rect->resolvedHeight - rect->padding.top - rect->padding.bottom;
|
||||
} else {
|
||||
child->resolvedHeight += childBreadthInc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ui_sizingPass(ui, isXAxis, childHandle);
|
||||
|
||||
childHandle = child->nextSibling;
|
||||
}
|
||||
}
|
||||
|
||||
void ui_calcLayout(UI_Context *ui, bool isXAxis, int32 rectHandle) {
|
||||
UI_Rect *rect = &ui->rects.data[rectHandle];
|
||||
if (!rect->firstChild) return;
|
||||
|
||||
bool isVertical = (rect->flags & UI_Flag_Vertical);
|
||||
|
||||
real32 coord = isXAxis
|
||||
? rect->x + rect->padding.left
|
||||
: rect->y + rect->padding.top;
|
||||
|
||||
real32 parentCoord = coord;
|
||||
|
||||
int32 childHandle = rect->firstChild;
|
||||
UI_Rect *child;
|
||||
while (childHandle) {
|
||||
child = &ui->rects.data[childHandle];
|
||||
|
||||
if (child->flags & UI_Flag_Pos_Absolute) {
|
||||
if (isXAxis) {
|
||||
child->x = rect->x;
|
||||
} else {
|
||||
child->y = rect->y;
|
||||
}
|
||||
} else {
|
||||
if (isXAxis) {
|
||||
child->x = child->flags & UI_Flag_Center && isVertical
|
||||
? coord + (rect->resolvedWidth - rect->padding.left - rect->padding.right)/2 - child->resolvedWidth/2
|
||||
: coord;
|
||||
} else {
|
||||
child->y = child->flags & UI_Flag_Center && !isVertical
|
||||
? coord + (rect->resolvedHeight - rect->padding.top - rect->padding.bottom)/2 - child->resolvedHeight/2
|
||||
: coord;
|
||||
}
|
||||
}
|
||||
|
||||
if (isXAxis) {
|
||||
child->x += child->xOffset;
|
||||
} else {
|
||||
child->y += child->yOffset;
|
||||
}
|
||||
|
||||
ui_calcLayout(ui, isXAxis, childHandle);
|
||||
|
||||
if (!(child->flags & UI_Flag_Pos_Absolute) && !isVertical == isXAxis) {
|
||||
coord += isXAxis ? child->resolvedWidth : child->resolvedHeight;
|
||||
coord += rect->childGap;
|
||||
}
|
||||
|
||||
childHandle = child->nextSibling;
|
||||
}
|
||||
}
|
||||
|
||||
void ui_begin(UI_Context *ui) {
|
||||
__UI_current_ctx__ = ui;
|
||||
arenaFreeFrom(ui->arena, 0);
|
||||
ClearList(ui->prevRects);
|
||||
ListAppendList(ui->prevRects, ui->rects);
|
||||
ui->cursorType = UI_Cursor_Arrow;
|
||||
ui->prevHotNode = ui->hotNode;
|
||||
ui->prevHoveredNode = ui->hoveredNode;
|
||||
ui->hotNode = 0;
|
||||
ui->hoveredNode = 0;
|
||||
ui->scene3DHandle = 0;
|
||||
ui->rootRect = 0;
|
||||
ui->currRect = 0;
|
||||
ClearList(ui->rects);
|
||||
ListAppend(ui->rects, (UI_Rect){0});
|
||||
|
||||
ui_openElement(ui, (UI_Rect){ .width=ui->renderer->width, .height=ui->renderer->height, .color=(Vec4){0,0,0,0}});
|
||||
|
||||
UI_RectStr *inheritedTextAttrInit = PushStruct(ui->arena, UI_RectStr);
|
||||
*inheritedTextAttrInit = UI_TxtAttr();
|
||||
ui->rects.data[ui->currRect].inheritedTextAttr = inheritedTextAttrInit;
|
||||
}
|
||||
|
||||
void ui_end(UI_Context *ui) {
|
||||
ui_closeElement(ui);
|
||||
|
||||
// 1) a. Calculate layout
|
||||
ui_sizingPass(ui, true, ui->rootRect); // x
|
||||
ui_sizingPass(ui, false, ui->rootRect); // y
|
||||
|
||||
// 1) b.
|
||||
ui_calcLayout(ui, true, ui->rootRect); // x
|
||||
ui_calcLayout(ui, false, ui->rootRect); // y
|
||||
|
||||
// 2) Create render commands:
|
||||
|
||||
for (EachEl(ui->rects, UI_Rect, rect)) {
|
||||
rendererPlaceRectangle(
|
||||
ui->renderer,
|
||||
rect->x,
|
||||
rect->y,
|
||||
rect->resolvedWidth,
|
||||
rect->resolvedHeight,
|
||||
rect->color,
|
||||
rect->borderRadius,
|
||||
rect->borderThickness,
|
||||
rect->borderColor
|
||||
);
|
||||
if (rect->stringData) {
|
||||
UI_RectStr *str = rect->stringData;
|
||||
real32 alignmentXOffset = 0;
|
||||
real32 alignmentYOffset = rect->padding.top;
|
||||
real32 textWidth = str->s.length * str->fontSize / ui->renderer->activeFont->lineHeight * ui->renderer->activeFont->charWidth;
|
||||
enum UI_TxtAlign alignment = str->alignment == -1 ? UI_TxtAlign_Left : str->alignment;
|
||||
if (alignment & UI_TxtAlign_Right) {
|
||||
alignmentXOffset = rect->resolvedWidth - rect->padding.right - textWidth;
|
||||
} else if (alignment & UI_TxtAlign_Center) {
|
||||
alignmentXOffset = rect->resolvedWidth/2.0 - textWidth/2.0;
|
||||
} else {
|
||||
alignmentXOffset = rect->padding.left;
|
||||
}
|
||||
rendererPlaceString(
|
||||
ui->renderer,
|
||||
str->s,
|
||||
rect->x + alignmentXOffset + str->xOffset,
|
||||
rect->y + alignmentYOffset + str->yOffset,
|
||||
str->color,
|
||||
str->fontSize
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (ui->scene3DHandle) {
|
||||
UI_Rect *scene3DRect = &ui->rects.data[ui->scene3DHandle];
|
||||
ui->renderer->sceneX = (int32)scene3DRect->x;
|
||||
ui->renderer->sceneY = (int32)scene3DRect->y;
|
||||
ui->renderer->sceneWidth = (int32)scene3DRect->resolvedWidth;
|
||||
ui->renderer->sceneHeight = (int32)scene3DRect->resolvedHeight;
|
||||
}
|
||||
|
||||
__UI_current_ctx__ = NULL;
|
||||
}
|
||||
|
||||
static bool pointInRect(real32 x, real32 y, UI_Rect rect) {
|
||||
return x > rect.x && y > rect.y && x < (rect.x + rect.resolvedWidth) && y < (rect.y + rect.resolvedHeight);
|
||||
}
|
||||
|
||||
void ui_openElement(UI_Context *ui, UI_Rect rect) {
|
||||
ListAppend(ui->rects, (UI_Rect){0});
|
||||
int32 newHandle = ui->rects.length - 1;
|
||||
UI_Rect *newRect = &ui->rects.data[newHandle];
|
||||
UI_Rect *currRect = &ui->rects.data[ui->currRect];
|
||||
|
||||
*newRect = rect;
|
||||
newRect->parent = ui->currRect;
|
||||
if (currRect->lastChild) {
|
||||
ui->rects.data[currRect->lastChild].nextSibling = newHandle;
|
||||
} else {
|
||||
currRect->firstChild = newHandle;
|
||||
}
|
||||
currRect->lastChild = newHandle;
|
||||
|
||||
if (!ui->rootRect) {
|
||||
ui->rootRect = newHandle;
|
||||
}
|
||||
|
||||
ui->currRect = newHandle;
|
||||
|
||||
if (newRect->flags & UI_Flag_3DScene) {
|
||||
ui->scene3DHandle = newHandle;
|
||||
}
|
||||
|
||||
if (currRect->stringData) {
|
||||
UI_RectStr *inheritedTextAttr = PushStructZero(ui->arena, UI_RectStr);
|
||||
*inheritedTextAttr = *currRect->stringData;
|
||||
*newRect->inheritedTextAttr = *currRect->stringData;
|
||||
newRect->inheritedTextAttr->s = (string){ .str=NULL, .length=0 };
|
||||
} else if (newRect->inheritedTextAttr == NULL && currRect) {
|
||||
newRect->inheritedTextAttr = currRect->inheritedTextAttr;
|
||||
}
|
||||
}
|
||||
|
||||
void ui_closeElement(UI_Context *ui) {
|
||||
UI_Rect *currRect = &ui->rects.data[ui->currRect];
|
||||
UI_Rect *parentRect = &ui->rects.data[currRect->parent];
|
||||
|
||||
if (currRect->width != -1) {
|
||||
currRect->resolvedWidth = currRect->width;
|
||||
} else if (currRect->minWidth == -1) {
|
||||
if (currRect->stringData) {
|
||||
real32 charWidth = currRect->stringData->fontSize / ui->renderer->activeFont->lineHeight * ui->renderer->activeFont->charWidth;
|
||||
currRect->minWidth = charWidth*currRect->stringData->s.length;
|
||||
} else {
|
||||
currRect->minWidth = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (currRect->height != -1) {
|
||||
currRect->resolvedHeight = currRect->height;
|
||||
} else if (currRect->minHeight == -1) {
|
||||
if (currRect->stringData) {
|
||||
currRect->minHeight = currRect->stringData->lineHeight;
|
||||
} else {
|
||||
currRect->minHeight = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool vertical = parentRect->flags & UI_Flag_Vertical;
|
||||
|
||||
real32 currBreadth = vertical ? currRect->resolvedHeight : currRect->resolvedWidth;
|
||||
real32 parentBreadth = vertical ? parentRect->height : parentRect->width;
|
||||
real32 gap = parentRect->childGap;
|
||||
|
||||
real32 breadthInc = (parentRect->firstChild == ui->currRect ? 0 : gap) + currBreadth;
|
||||
|
||||
if (parentBreadth == -1) {
|
||||
if (vertical) {
|
||||
parentRect->resolvedHeight += breadthInc;
|
||||
} else {
|
||||
parentRect->resolvedWidth += breadthInc;
|
||||
}
|
||||
}
|
||||
|
||||
real32 currCrossBreadth = vertical ? currRect->resolvedWidth : currRect->resolvedHeight;
|
||||
real32 parentCrossBreadth = vertical ? parentRect->width : parentRect->height;
|
||||
real32 currParentCrossBreadth = vertical ? parentRect->resolvedWidth : parentRect->resolvedHeight;
|
||||
|
||||
if (parentCrossBreadth == -1) {
|
||||
real32 newCrossBreadth = currCrossBreadth > currParentCrossBreadth ? currCrossBreadth : currParentCrossBreadth;
|
||||
if (vertical) {
|
||||
parentRect->resolvedWidth = newCrossBreadth;
|
||||
} else {
|
||||
parentRect->resolvedHeight = newCrossBreadth;
|
||||
}
|
||||
}
|
||||
|
||||
ui->currRect = ui->rects.data[ui->currRect].parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the checkbox was clicked
|
||||
*/
|
||||
bool ui_ButtonWithHover(UI_Context *ui, UI_Rect rect, UI_Rect hovered, UI_RectStr textAttr) {
|
||||
int32 id = UI_NextID();
|
||||
bool clicked = false;
|
||||
|
||||
bool inRect = pointInRect(ui->input->mouse.point.x, ui->input->mouse.point.y, ui->prevRects.data[id]);
|
||||
if (inRect) {
|
||||
ui->cursorType = UI_Cursor_Pointer;
|
||||
if (ui->prevHotNode == id && !ui->input->mouse.btnLeft) {
|
||||
clicked = true;
|
||||
} else if (ui->input->mouse.btnLeft && (!ui->prevInput->mouse.btnLeft || ui->prevHotNode == id)) {
|
||||
ui->hotNode = id;
|
||||
}
|
||||
ui->hoveredNode = id;
|
||||
}
|
||||
|
||||
bool useHover = inRect && !(hovered.flags & UI_Flag_Ignore);
|
||||
UI_Rect *rectToRender = useHover ? &hovered : ▭
|
||||
if (rectToRender->borderRadius == -1) {
|
||||
rectToRender->borderRadius = 5;
|
||||
}
|
||||
|
||||
UI_FromRect(*rectToRender) ui_placeText(ui, textAttr);
|
||||
|
||||
return clicked;
|
||||
}
|
||||
|
||||
UI_Rect ui_HoverRect(UI_Context *ui, UI_Rect rect, UI_Rect hovered) {
|
||||
int32 id = UI_NextID();
|
||||
bool inRect = pointInRect(ui->input->mouse.point.x, ui->input->mouse.point.y, ui->prevRects.data[id]);
|
||||
if (inRect) {
|
||||
ui->hoveredNode = id;
|
||||
}
|
||||
return inRect && !(hovered.flags & UI_Flag_Ignore) ? hovered : rect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the checkbox was clicked
|
||||
*/
|
||||
bool ui_Button(UI_Context *ui, UI_Rect rect, UI_RectStr textAttr) {
|
||||
return ui_ButtonWithHover(ui, rect, UI_RectAttr(.flags=UI_Flag_Ignore), textAttr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the checkbox was clicked
|
||||
*/
|
||||
bool ui_CheckboxRect(UI_Context *ui, bool *value, UI_Rect rect) {
|
||||
int32 id = UI_NextID();
|
||||
bool clicked = false;
|
||||
bool pointerInRect = pointInRect(ui->input->mouse.point.x, ui->input->mouse.point.y, ui->prevRects.data[id]);
|
||||
if (pointerInRect) {
|
||||
ui->cursorType = UI_Cursor_Pointer;
|
||||
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;
|
||||
if (pointerInRect) {
|
||||
rect.color.x += 0.5;
|
||||
rect.color.y += 0.5;
|
||||
rect.color.z += 0.5;
|
||||
rect.color.x = rect.color.x <= 1.0 ? rect.color.x : 1.0;
|
||||
rect.color.y = rect.color.y <= 1.0 ? rect.color.y : 1.0;
|
||||
rect.color.z = rect.color.z <= 1.0 ? rect.color.z : 1.0;
|
||||
}
|
||||
UI_FromRect(rect);
|
||||
} else {
|
||||
rect.borderRadius = 5;
|
||||
rect.borderThickness = 2;
|
||||
rect.borderColor = COLOR_WHITE;
|
||||
if (pointerInRect) {
|
||||
rect.color = COLOR_WHITE;
|
||||
rect.color.w = 0.2;
|
||||
} else {
|
||||
rect.color = (Vec4){0,0,0,0};
|
||||
}
|
||||
UI_FromRect(rect);
|
||||
}
|
||||
|
||||
return clicked;
|
||||
}
|
||||
181
gfx/ui.h
Normal file
181
gfx/ui.h
Normal file
@@ -0,0 +1,181 @@
|
||||
#ifndef UI_H
|
||||
#define UI_H
|
||||
|
||||
#include "platform.h"
|
||||
#include "render.h"
|
||||
#include "../core.h"
|
||||
#include "GLFW/glfw3.h"
|
||||
|
||||
enum UI_Flag {
|
||||
UI_Flag_WidthGrow=1<<0, // Default is fixed
|
||||
UI_Flag_HeightGrow=1<<1, // Default is fixed
|
||||
UI_Flag_Vertical=1<<2, // Default is horizontal
|
||||
UI_Flag_3DScene=1<<3,
|
||||
UI_Flag_Center=1<<4,
|
||||
UI_Flag_Ignore=1<<7, // For optional parameters
|
||||
UI_Flag_Pos_Absolute=1<<8, // Default is relative
|
||||
// ..
|
||||
UI_Flag_COUNT,
|
||||
};
|
||||
|
||||
typedef struct UI_Padding UI_Padding;
|
||||
struct UI_Padding {
|
||||
real32 top;
|
||||
real32 right;
|
||||
real32 bottom;
|
||||
real32 left;
|
||||
};
|
||||
|
||||
enum UI_Cursor {
|
||||
UI_Cursor_Arrow=1<<0,
|
||||
UI_Cursor_Pointer=1<<1,
|
||||
UI_Cursor_Forbidden=1<<2,
|
||||
UI_Cursor_Count=1<<3,
|
||||
};
|
||||
|
||||
enum UI_TxtAlign {
|
||||
UI_TxtAlign_Left=1<<0, // Default
|
||||
UI_TxtAlign_Center=1<<1,
|
||||
UI_TxtAlign_Right=1<<2,
|
||||
};
|
||||
|
||||
typedef struct UI_RectStr UI_RectStr;
|
||||
struct UI_RectStr {
|
||||
string s;
|
||||
real32 xOffset;
|
||||
real32 yOffset;
|
||||
real32 lineHeight;
|
||||
real32 fontSize;
|
||||
Vec4 color;
|
||||
enum UI_TxtAlign alignment;
|
||||
};
|
||||
|
||||
typedef struct UI_Rect UI_Rect;
|
||||
struct UI_Rect {
|
||||
enum UI_Flag flags;
|
||||
|
||||
int32 parent;
|
||||
int32 firstChild;
|
||||
int32 lastChild;
|
||||
int32 nextSibling;
|
||||
|
||||
real32 xOffset;
|
||||
real32 yOffset;
|
||||
|
||||
real32 width;
|
||||
real32 minWidth;
|
||||
real32 maxWidth;
|
||||
|
||||
real32 height;
|
||||
real32 minHeight;
|
||||
real32 maxHeight;
|
||||
|
||||
real32 borderRadius;
|
||||
real32 borderThickness;
|
||||
|
||||
Vec4 color;
|
||||
Vec4 borderColor;
|
||||
|
||||
UI_Padding padding;
|
||||
real32 childGap;
|
||||
|
||||
real32 x;
|
||||
real32 y;
|
||||
real32 resolvedWidth;
|
||||
real32 resolvedHeight;
|
||||
|
||||
UI_RectStr *stringData;
|
||||
/**
|
||||
* Inherited from parent to propagate attributes. Actual string is ignored, only used for filling out defaults in
|
||||
* the next stringData pointer that is set.
|
||||
* This pointer is always set, as the global UI context will set it on the root node if it does not present its own
|
||||
* text data.
|
||||
*/
|
||||
UI_RectStr *inheritedTextAttr;
|
||||
};
|
||||
DefineList(UI_Rect, UI_Rect);
|
||||
|
||||
typedef struct UI_Context UI_Context;
|
||||
struct UI_Context {
|
||||
Arena *arena;
|
||||
UI_RectList prevRects;
|
||||
UI_RectList rects;
|
||||
int32 hotNode;
|
||||
int32 hoveredNode;
|
||||
int32 prevHoveredNode;
|
||||
int32 scene3DHandle;
|
||||
int32 prevHotNode;
|
||||
Renderer *renderer;
|
||||
|
||||
OS_Input *prevInput;
|
||||
OS_Input *input;
|
||||
enum UI_Cursor cursorType;
|
||||
|
||||
int32 rootRect;
|
||||
int32 currRect;
|
||||
};
|
||||
|
||||
void ui_begin(UI_Context *ui);
|
||||
void ui_end(UI_Context *ui);
|
||||
UI_Context ui_initContext(Arena *arena, Renderer *renderer);
|
||||
void ui_resolve();
|
||||
void ui_rect(UI_Context *ui, UI_Rect rect);
|
||||
void ui_placeText(UI_Context *ui, UI_RectStr strData);
|
||||
void ui_attachTextAttr(UI_Context *ui, UI_Rect *rect, UI_RectStr strData);
|
||||
void ui_openElement(UI_Context *ui, UI_Rect rect);
|
||||
void ui_closeElement(UI_Context *ui);
|
||||
|
||||
bool ui_CheckboxRect(UI_Context *ui, bool *value, UI_Rect rect);
|
||||
bool ui_Button(UI_Context *ui, UI_Rect rect, UI_RectStr textAttr);
|
||||
bool ui_ButtonWithHover(UI_Context *ui, UI_Rect rect, UI_Rect hovered, UI_RectStr textAttr);
|
||||
UI_Rect ui_HoverRect(UI_Context *ui, UI_Rect rect, UI_Rect hovered);
|
||||
|
||||
extern UI_Context *__UI_current_ctx__;
|
||||
|
||||
#if 0
|
||||
#define UI_DEBUG_ATTR .borderColor=COLOR_RED, .borderThickness=1,
|
||||
#else
|
||||
#define UI_DEBUG_ATTR
|
||||
#endif
|
||||
|
||||
#define UI_Pass(ui) DeferLoop(ui_begin((ui)), ui_end((ui)))
|
||||
#define UI_PadUniform(padding) ((UI_Padding){ (padding), (padding), (padding), (padding) })
|
||||
#define UI_NextID() ((__UI_current_ctx__)->rects.length)
|
||||
|
||||
#define UI(...)\
|
||||
/** Place a UI_Rect defined in-place in the current position in the UI tree */\
|
||||
DeferLoop(ui_openElement((__UI_current_ctx__), UI_RectAttr(__VA_ARGS__)), ui_closeElement((__UI_current_ctx__)))
|
||||
|
||||
#define UI_RectAttr(...)\
|
||||
/** Generate a UI_Rect to be passed as a value */\
|
||||
((UI_Rect){UI_DEBUG_ATTR .minHeight=-1, .minWidth=-1, .width=-1, .height=-1, .inheritedTextAttr=(__UI_current_ctx__->rects.data[(__UI_current_ctx__)->currRect].inheritedTextAttr), __VA_ARGS__})
|
||||
|
||||
#define UI_FromRect(rect)\
|
||||
/** Place a UI_Rect in the current position in the UI tree, as defined by an existing value */\
|
||||
DeferLoop(ui_openElement((__UI_current_ctx__), (rect)), ui_closeElement((__UI_current_ctx__)))
|
||||
|
||||
#define UI_TxtAttrS(str, ...)\
|
||||
/** Generate UI text to be used as a value */\
|
||||
((UI_RectStr){ .color={-1,-1,-1,-1}, .alignment=-1, .xOffset=0, .yOffset=0, .fontSize=-1, .lineHeight=-1, .s=(str), __VA_ARGS__ })
|
||||
|
||||
#define UI_TxtAttr(...)\
|
||||
/** Generate UI text to be used as a value, attributes only, no string */\
|
||||
((UI_RectStr){ .color={-1,-1,-1,-1}, .alignment=-1, .xOffset=0, .yOffset=0, .fontSize=-1, .lineHeight=-1, .s=((string){.str=NULL,.length=0}), __VA_ARGS__ })
|
||||
|
||||
#define UI_Txt(str, ...)\
|
||||
/** Place UI text in the current position in the UI tree. Attaches to the current UI_Rect */\
|
||||
(ui_placeText((__UI_current_ctx__), (UI_TxtAttrS(str, __VA_ARGS__))))
|
||||
|
||||
#define UI_AttachTxtAttr(rect, txtAttr)\
|
||||
/** Attach "phantom" text to the specified rect in order to set its heritable attributes for subsequent text in the UI subtrees */\
|
||||
(ui_attachTextAttr((__UI_current_ctx__), (rect), (txtAttr)))
|
||||
|
||||
#define UI_SetTxtAttr(...)\
|
||||
/** Attach "phantom" text to the current rect in order to set its heritable attributes for subsequent text in the UI subtrees */\
|
||||
(ui_placeText((__UI_current_ctx__), (UI_TxtAttr(__VA_ARGS__))))
|
||||
|
||||
#define UI_TxtSeg(str, ...)\
|
||||
/** Place a text fragment in its own box (useful for placing many text fragments in a row */\
|
||||
UI() (UI_Txt((str), __VA_ARGS__))
|
||||
|
||||
#endif
|
||||
26
gfx/world/camera.c
Normal file
26
gfx/world/camera.c
Normal file
@@ -0,0 +1,26 @@
|
||||
#include "camera.h"
|
||||
#include "../../vendor/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 = (Vec3){0},
|
||||
.up = (Vec3){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 = (Vec3){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 = (Vec3){up_x, up_y, up_z};
|
||||
}
|
||||
|
||||
21
gfx/world/camera.h
Normal file
21
gfx/world/camera.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef DJSTDLIB_GFX_CAMERA_H
|
||||
#define DJSTDLIB_GFX_CAMERA_H
|
||||
|
||||
#include "../../core.h"
|
||||
#include "../../vendor/raymath.h"
|
||||
|
||||
typedef struct Camera Camera;
|
||||
struct Camera {
|
||||
Matrix view;
|
||||
Matrix proj;
|
||||
Vec3 pos;
|
||||
Vec3 up;
|
||||
Vec3 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
|
||||
196
gfx/world/scene.c
Normal file
196
gfx/world/scene.c
Normal file
@@ -0,0 +1,196 @@
|
||||
#include "../../core.h"
|
||||
#include "scene.h"
|
||||
|
||||
Entity *getEntity(Scene *s, int32 entityHandle) {
|
||||
return &s->entities.data[entityHandle];
|
||||
}
|
||||
|
||||
SceneGraphNode *getSceneGraphNode(Scene *s, int32 sceneGraphNodeHandle) {
|
||||
return &s->graphNodes.data[sceneGraphNodeHandle];
|
||||
}
|
||||
|
||||
SceneGraphNode *getSceneGraphNodeForEntity(Scene *s, int32 entityHandle) {
|
||||
return getSceneGraphNode(s, getEntity(s, entityHandle)->graphNodeHandle);
|
||||
}
|
||||
|
||||
int32 createSceneGraphNode(Scene *s) {
|
||||
SceneGraphNode *newNode;
|
||||
int32 newNodeHandle;
|
||||
if (s->nextFreeNode) {
|
||||
newNodeHandle = s->nextFreeNode;
|
||||
newNode = getSceneGraphNode(s, newNodeHandle);
|
||||
if (newNode->next) {
|
||||
s->nextFreeNode = newNode->next;
|
||||
} else {
|
||||
s->nextFreeNode = 0;
|
||||
}
|
||||
newNode->next = 0;
|
||||
} else {
|
||||
ListAppend(s->graphNodes, (SceneGraphNode){0});
|
||||
newNodeHandle = (int32)s->graphNodes.length - 1;
|
||||
newNode = getSceneGraphNode(s, newNodeHandle);
|
||||
newNode->nextSibling = 0;
|
||||
}
|
||||
initGraphNode(newNode);
|
||||
return newNodeHandle;
|
||||
}
|
||||
|
||||
int32 createEntity(Scene *s) {
|
||||
Entity *newEntity;
|
||||
int32 newEntityHandle;
|
||||
if (s->nextFreeEntity) {
|
||||
newEntityHandle = s->nextFreeEntity;
|
||||
newEntity = getEntity(s, newEntityHandle);
|
||||
if (newEntity->next) {
|
||||
s->nextFreeEntity = newEntity->next;
|
||||
} else {
|
||||
s->nextFreeEntity = 0;
|
||||
}
|
||||
newEntity->next = 0;
|
||||
} else {
|
||||
ListAppend(s->entities, (Entity){0});
|
||||
newEntityHandle = (int32)s->entities.length - 1;
|
||||
newEntity = getEntity(s, newEntityHandle);
|
||||
}
|
||||
newEntity->graphNodeHandle = createSceneGraphNode(s);
|
||||
getSceneGraphNodeForEntity(s, newEntityHandle)->entityHandle = newEntityHandle;
|
||||
return newEntityHandle;
|
||||
}
|
||||
|
||||
void initGraphNode(SceneGraphNode *n) {
|
||||
n->scale = (Vec3){1.0f, 1.0f, 1.0f};
|
||||
n->translation = (Vec3){0.0f, 0.0f, 0.0f};
|
||||
n->rotation = (Quaternion){1.0f, 0.0f, 0.0f, 0.0f};
|
||||
n->local = MatrixIdentity();
|
||||
n->world = n->local;
|
||||
}
|
||||
|
||||
Scene createScene(Arena *arena) {
|
||||
Scene result = {
|
||||
.entities = PushListZero(arena, EntityList, 100000),
|
||||
.nextFreeEntity = 0,
|
||||
.graphNodes = PushListZero(arena, SceneGraphNodeList, 100000),
|
||||
.nextFreeNode = 0,
|
||||
};
|
||||
int32 handle = createEntity(&result); // Intialise the "zero" nodes
|
||||
getEntity(&result, handle)->flags = EntityFlags_None | EntityFlags_Dead;
|
||||
|
||||
result.sceneRoot = createSceneGraphNode(&result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void recalcSceneGraphNode(Scene *s, int32 parentHandle) {
|
||||
if (!parentHandle) return;
|
||||
SceneGraphNode *parentNode = getSceneGraphNode(s, parentHandle);
|
||||
getEntity(s, parentNode->entityHandle)->flags |= EntityFlags_Render;
|
||||
int32 nextChild = parentNode->firstChild;
|
||||
while (nextChild) {
|
||||
SceneGraphNode *childNode = getSceneGraphNode(s, nextChild);
|
||||
childNode->parentHandle = parentHandle;
|
||||
childNode->local = MatrixCompose(childNode->translation, childNode->rotation, childNode->scale);
|
||||
childNode->world = MatrixMultiply(childNode->local, parentNode->world);
|
||||
recalcSceneGraphNode(s, nextChild);
|
||||
nextChild = childNode->nextSibling;
|
||||
}
|
||||
}
|
||||
|
||||
void recalcScene(Scene *s) {
|
||||
recalcSceneGraphNode(s, s->sceneRoot);
|
||||
}
|
||||
|
||||
static void removeSceneGraphNodeRecursive(Scene *s, int32 deletedNodeHandle, bool deletingParent) {
|
||||
if (!deletedNodeHandle) return;
|
||||
SceneGraphNode *deletedNode = getSceneGraphNode(s, deletedNodeHandle);
|
||||
|
||||
int32 nextChild = deletedNode->firstChild;
|
||||
while (nextChild) {
|
||||
int32 sibling = getSceneGraphNode(s, nextChild)->nextSibling;
|
||||
removeSceneGraphNodeRecursive(s, nextChild, true);
|
||||
nextChild = sibling;
|
||||
}
|
||||
|
||||
if (deletedNode->entityHandle) {
|
||||
Entity *entity = getEntity(s, deletedNode->entityHandle);
|
||||
*entity = (Entity){0};
|
||||
if (s->nextFreeEntity) {
|
||||
entity->next = s->nextFreeEntity;
|
||||
}
|
||||
s->nextFreeEntity = deletedNode->entityHandle;
|
||||
}
|
||||
|
||||
if (s->nextFreeNode) {
|
||||
deletedNode->next = s->nextFreeNode;
|
||||
}
|
||||
s->nextFreeNode = deletedNodeHandle;
|
||||
|
||||
if (!deletingParent && deletedNode->parentHandle) {
|
||||
SceneGraphNode *parentNode = getSceneGraphNode(s, deletedNode->parentHandle);
|
||||
if (parentNode->firstChild == deletedNodeHandle) {
|
||||
if (deletedNode->nextSibling) {
|
||||
parentNode->firstChild = deletedNode->nextSibling;
|
||||
} else {
|
||||
parentNode->firstChild = 0;
|
||||
}
|
||||
} else {
|
||||
int32 prevSibling = parentNode->firstChild;
|
||||
int32 nextSibling = getSceneGraphNode(s, parentNode->firstChild)->nextSibling;
|
||||
while (nextSibling) {
|
||||
SceneGraphNode *siblingNode = getSceneGraphNode(s, nextSibling);
|
||||
if (nextSibling == deletedNodeHandle) {
|
||||
SceneGraphNode *prevSiblingNode = getSceneGraphNode(s, prevSibling);
|
||||
prevSiblingNode->nextSibling = deletedNode->nextSibling;
|
||||
break;
|
||||
}
|
||||
prevSibling = nextSibling;
|
||||
nextSibling = siblingNode->nextSibling;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deletedNode->firstChild = 0;
|
||||
deletedNode->parentHandle = 0;
|
||||
deletedNode->entityHandle = 0;
|
||||
deletedNode->nextSibling = 0;
|
||||
}
|
||||
|
||||
void removeSceneGraphNode(Scene *s, int32 graphNodeHandle) {
|
||||
removeSceneGraphNodeRecursive(s, graphNodeHandle, false);
|
||||
}
|
||||
|
||||
void removeEntity(Scene *s, int32 entityHandle) {
|
||||
if (!entityHandle) return;
|
||||
removeSceneGraphNode(s, getEntity(s, entityHandle)->graphNodeHandle);
|
||||
}
|
||||
|
||||
void sceneNodeAddNode(Scene *s, int32 parentHandle, int32 childHandle) {
|
||||
SceneGraphNode *parentNode = getSceneGraphNode(s, parentHandle);
|
||||
SceneGraphNode *childNode = getSceneGraphNode(s, childHandle);
|
||||
childNode->nextSibling = parentNode->firstChild;
|
||||
parentNode->firstChild = childHandle;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
75
gfx/world/scene.h
Normal file
75
gfx/world/scene.h
Normal file
@@ -0,0 +1,75 @@
|
||||
#ifndef DJSTDLIB_GFX_SCENE_H
|
||||
#define DJSTDLIB_GFX_SCENE_H
|
||||
|
||||
#include "../../core.h"
|
||||
#include "../../vendor/raymath.h"
|
||||
#include "../Mesh.h"
|
||||
#include "../Texture.h"
|
||||
|
||||
DefineList(int32, Handle);
|
||||
|
||||
enum EntityFlags {
|
||||
EntityFlags_None=0,
|
||||
EntityFlags_Visible=1<<0,
|
||||
EntityFlags_Dead=1<<1,
|
||||
EntityFlags_Render=1<<2,
|
||||
};
|
||||
|
||||
typedef struct Entity Entity;
|
||||
struct Entity {
|
||||
int32 graphNodeHandle;
|
||||
uint64 flags;
|
||||
Vec4 color;
|
||||
Mesh *mesh;
|
||||
Texture *tex;
|
||||
|
||||
// Free list
|
||||
int32 next;
|
||||
};
|
||||
DefineList(Entity, Entity);
|
||||
|
||||
typedef struct SceneGraphNode SceneGraphNode;
|
||||
struct SceneGraphNode {
|
||||
Matrix local;
|
||||
Matrix world;
|
||||
Vec3 translation;
|
||||
Quaternion rotation;
|
||||
Vec3 scale;
|
||||
int32 entityHandle;
|
||||
int32 parentHandle;
|
||||
|
||||
/** Next free in the free list */
|
||||
int32 next;
|
||||
|
||||
/** Next child in child list in scene hierarchy */
|
||||
int32 nextSibling;
|
||||
int32 firstChild;
|
||||
};
|
||||
DefineList(SceneGraphNode, SceneGraphNode);
|
||||
|
||||
typedef struct Scene Scene;
|
||||
struct Scene {
|
||||
int32 sceneRoot;
|
||||
EntityList entities;
|
||||
int32 nextFreeEntity;
|
||||
/** @internal */
|
||||
SceneGraphNodeList graphNodes;
|
||||
int32 nextFreeNode;
|
||||
};
|
||||
|
||||
int32 createEntity(Scene *s);
|
||||
Entity *getEntity(Scene *s, int32 id);
|
||||
SceneGraphNode *getSceneGraphNode(Scene *s, int32 id);
|
||||
int32 createSceneGraphNode(Scene *s);
|
||||
Scene createScene(Arena *arena);
|
||||
void initGraphNode(SceneGraphNode *n);
|
||||
void recalcSceneGraphNode(Scene *s, int32 parentHandle);
|
||||
void recalcScene(Scene *s);
|
||||
void removeEntity(Scene *s, int32 entityHandle);
|
||||
void removeSceneGraphNode(Scene *s, int32 graphNodeHandle);
|
||||
void sceneNodeAddNode(Scene *s, int32 recipientNodeHandle, int32 graphNodeHandle);
|
||||
SceneGraphNode *getSceneGraphNodeForEntity(Scene *s, int32 entityHandle);
|
||||
void show(Scene *s, uint32 graphNodeHandle);
|
||||
void hide(Scene *s, uint32 graphNodeHandle);
|
||||
|
||||
#endif
|
||||
2
gfx/world/world.c
Normal file
2
gfx/world/world.c
Normal file
@@ -0,0 +1,2 @@
|
||||
#include "scene.c"
|
||||
#include "camera.c"
|
||||
8
gfx/world/world.h
Normal file
8
gfx/world/world.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef DJSTDLIB_GFX_WORLD_H
|
||||
#define DJSTDLIB_GFX_WORLD_H
|
||||
|
||||
#include "scene.h"
|
||||
#include "camera.h"
|
||||
|
||||
#endif
|
||||
|
||||
1833
vendor/glad/glad.c
vendored
Normal file
1833
vendor/glad/glad.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3694
vendor/glad/glad.h
vendored
Normal file
3694
vendor/glad/glad.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
311
vendor/glad/khrplatform.h
vendored
Normal file
311
vendor/glad/khrplatform.h
vendored
Normal file
@@ -0,0 +1,311 @@
|
||||
#ifndef __khrplatform_h_
|
||||
#define __khrplatform_h_
|
||||
|
||||
/*
|
||||
** Copyright (c) 2008-2018 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
/* Khronos platform-specific types and definitions.
|
||||
*
|
||||
* The master copy of khrplatform.h is maintained in the Khronos EGL
|
||||
* Registry repository at https://github.com/KhronosGroup/EGL-Registry
|
||||
* The last semantic modification to khrplatform.h was at commit ID:
|
||||
* 67a3e0864c2d75ea5287b9f3d2eb74a745936692
|
||||
*
|
||||
* Adopters may modify this file to suit their platform. Adopters are
|
||||
* encouraged to submit platform specific modifications to the Khronos
|
||||
* group so that they can be included in future versions of this file.
|
||||
* Please submit changes by filing pull requests or issues on
|
||||
* the EGL Registry repository linked above.
|
||||
*
|
||||
*
|
||||
* See the Implementer's Guidelines for information about where this file
|
||||
* should be located on your system and for more details of its use:
|
||||
* http://www.khronos.org/registry/implementers_guide.pdf
|
||||
*
|
||||
* This file should be included as
|
||||
* #include <KHR/khrplatform.h>
|
||||
* by Khronos client API header files that use its types and defines.
|
||||
*
|
||||
* The types in khrplatform.h should only be used to define API-specific types.
|
||||
*
|
||||
* Types defined in khrplatform.h:
|
||||
* khronos_int8_t signed 8 bit
|
||||
* khronos_uint8_t unsigned 8 bit
|
||||
* khronos_int16_t signed 16 bit
|
||||
* khronos_uint16_t unsigned 16 bit
|
||||
* khronos_int32_t signed 32 bit
|
||||
* khronos_uint32_t unsigned 32 bit
|
||||
* khronos_int64_t signed 64 bit
|
||||
* khronos_uint64_t unsigned 64 bit
|
||||
* khronos_intptr_t signed same number of bits as a pointer
|
||||
* khronos_uintptr_t unsigned same number of bits as a pointer
|
||||
* khronos_ssize_t signed size
|
||||
* khronos_usize_t unsigned size
|
||||
* khronos_float_t signed 32 bit floating point
|
||||
* khronos_time_ns_t unsigned 64 bit time in nanoseconds
|
||||
* khronos_utime_nanoseconds_t unsigned time interval or absolute time in
|
||||
* nanoseconds
|
||||
* khronos_stime_nanoseconds_t signed time interval in nanoseconds
|
||||
* khronos_boolean_enum_t enumerated boolean type. This should
|
||||
* only be used as a base type when a client API's boolean type is
|
||||
* an enum. Client APIs which use an integer or other type for
|
||||
* booleans cannot use this as the base type for their boolean.
|
||||
*
|
||||
* Tokens defined in khrplatform.h:
|
||||
*
|
||||
* KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
|
||||
*
|
||||
* KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
|
||||
* KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
|
||||
*
|
||||
* Calling convention macros defined in this file:
|
||||
* KHRONOS_APICALL
|
||||
* KHRONOS_APIENTRY
|
||||
* KHRONOS_APIATTRIBUTES
|
||||
*
|
||||
* These may be used in function prototypes as:
|
||||
*
|
||||
* KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
|
||||
* int arg1,
|
||||
* int arg2) KHRONOS_APIATTRIBUTES;
|
||||
*/
|
||||
|
||||
#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC)
|
||||
# define KHRONOS_STATIC 1
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Definition of KHRONOS_APICALL
|
||||
*-------------------------------------------------------------------------
|
||||
* This precedes the return type of the function in the function prototype.
|
||||
*/
|
||||
#if defined(KHRONOS_STATIC)
|
||||
/* If the preprocessor constant KHRONOS_STATIC is defined, make the
|
||||
* header compatible with static linking. */
|
||||
# define KHRONOS_APICALL
|
||||
#elif defined(_WIN32)
|
||||
# define KHRONOS_APICALL __declspec(dllimport)
|
||||
#elif defined (__SYMBIAN32__)
|
||||
# define KHRONOS_APICALL IMPORT_C
|
||||
#elif defined(__ANDROID__)
|
||||
# define KHRONOS_APICALL __attribute__((visibility("default")))
|
||||
#else
|
||||
# define KHRONOS_APICALL
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Definition of KHRONOS_APIENTRY
|
||||
*-------------------------------------------------------------------------
|
||||
* This follows the return type of the function and precedes the function
|
||||
* name in the function prototype.
|
||||
*/
|
||||
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
|
||||
/* Win32 but not WinCE */
|
||||
# define KHRONOS_APIENTRY __stdcall
|
||||
#else
|
||||
# define KHRONOS_APIENTRY
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Definition of KHRONOS_APIATTRIBUTES
|
||||
*-------------------------------------------------------------------------
|
||||
* This follows the closing parenthesis of the function prototype arguments.
|
||||
*/
|
||||
#if defined (__ARMCC_2__)
|
||||
#define KHRONOS_APIATTRIBUTES __softfp
|
||||
#else
|
||||
#define KHRONOS_APIATTRIBUTES
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* basic type definitions
|
||||
*-----------------------------------------------------------------------*/
|
||||
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
|
||||
|
||||
|
||||
/*
|
||||
* Using <stdint.h>
|
||||
*/
|
||||
#include <stdint.h>
|
||||
typedef int32_t khronos_int32_t;
|
||||
typedef uint32_t khronos_uint32_t;
|
||||
typedef int64_t khronos_int64_t;
|
||||
typedef uint64_t khronos_uint64_t;
|
||||
#define KHRONOS_SUPPORT_INT64 1
|
||||
#define KHRONOS_SUPPORT_FLOAT 1
|
||||
/*
|
||||
* To support platform where unsigned long cannot be used interchangeably with
|
||||
* inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t.
|
||||
* Ideally, we could just use (u)intptr_t everywhere, but this could result in
|
||||
* ABI breakage if khronos_uintptr_t is changed from unsigned long to
|
||||
* unsigned long long or similar (this results in different C++ name mangling).
|
||||
* To avoid changes for existing platforms, we restrict usage of intptr_t to
|
||||
* platforms where the size of a pointer is larger than the size of long.
|
||||
*/
|
||||
#if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__)
|
||||
#if __SIZEOF_POINTER__ > __SIZEOF_LONG__
|
||||
#define KHRONOS_USE_INTPTR_T
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#elif defined(__VMS ) || defined(__sgi)
|
||||
|
||||
/*
|
||||
* Using <inttypes.h>
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
typedef int32_t khronos_int32_t;
|
||||
typedef uint32_t khronos_uint32_t;
|
||||
typedef int64_t khronos_int64_t;
|
||||
typedef uint64_t khronos_uint64_t;
|
||||
#define KHRONOS_SUPPORT_INT64 1
|
||||
#define KHRONOS_SUPPORT_FLOAT 1
|
||||
|
||||
#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
|
||||
|
||||
/*
|
||||
* Win32
|
||||
*/
|
||||
typedef __int32 khronos_int32_t;
|
||||
typedef unsigned __int32 khronos_uint32_t;
|
||||
typedef __int64 khronos_int64_t;
|
||||
typedef unsigned __int64 khronos_uint64_t;
|
||||
#define KHRONOS_SUPPORT_INT64 1
|
||||
#define KHRONOS_SUPPORT_FLOAT 1
|
||||
|
||||
#elif defined(__sun__) || defined(__digital__)
|
||||
|
||||
/*
|
||||
* Sun or Digital
|
||||
*/
|
||||
typedef int khronos_int32_t;
|
||||
typedef unsigned int khronos_uint32_t;
|
||||
#if defined(__arch64__) || defined(_LP64)
|
||||
typedef long int khronos_int64_t;
|
||||
typedef unsigned long int khronos_uint64_t;
|
||||
#else
|
||||
typedef long long int khronos_int64_t;
|
||||
typedef unsigned long long int khronos_uint64_t;
|
||||
#endif /* __arch64__ */
|
||||
#define KHRONOS_SUPPORT_INT64 1
|
||||
#define KHRONOS_SUPPORT_FLOAT 1
|
||||
|
||||
#elif 0
|
||||
|
||||
/*
|
||||
* Hypothetical platform with no float or int64 support
|
||||
*/
|
||||
typedef int khronos_int32_t;
|
||||
typedef unsigned int khronos_uint32_t;
|
||||
#define KHRONOS_SUPPORT_INT64 0
|
||||
#define KHRONOS_SUPPORT_FLOAT 0
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* Generic fallback
|
||||
*/
|
||||
#include <stdint.h>
|
||||
typedef int32_t khronos_int32_t;
|
||||
typedef uint32_t khronos_uint32_t;
|
||||
typedef int64_t khronos_int64_t;
|
||||
typedef uint64_t khronos_uint64_t;
|
||||
#define KHRONOS_SUPPORT_INT64 1
|
||||
#define KHRONOS_SUPPORT_FLOAT 1
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Types that are (so far) the same on all platforms
|
||||
*/
|
||||
typedef signed char khronos_int8_t;
|
||||
typedef unsigned char khronos_uint8_t;
|
||||
typedef signed short int khronos_int16_t;
|
||||
typedef unsigned short int khronos_uint16_t;
|
||||
|
||||
/*
|
||||
* Types that differ between LLP64 and LP64 architectures - in LLP64,
|
||||
* pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
|
||||
* to be the only LLP64 architecture in current use.
|
||||
*/
|
||||
#ifdef KHRONOS_USE_INTPTR_T
|
||||
typedef intptr_t khronos_intptr_t;
|
||||
typedef uintptr_t khronos_uintptr_t;
|
||||
#elif defined(_WIN64)
|
||||
typedef signed long long int khronos_intptr_t;
|
||||
typedef unsigned long long int khronos_uintptr_t;
|
||||
#else
|
||||
typedef signed long int khronos_intptr_t;
|
||||
typedef unsigned long int khronos_uintptr_t;
|
||||
#endif
|
||||
|
||||
#if defined(_WIN64)
|
||||
typedef signed long long int khronos_ssize_t;
|
||||
typedef unsigned long long int khronos_usize_t;
|
||||
#else
|
||||
typedef signed long int khronos_ssize_t;
|
||||
typedef unsigned long int khronos_usize_t;
|
||||
#endif
|
||||
|
||||
#if KHRONOS_SUPPORT_FLOAT
|
||||
/*
|
||||
* Float type
|
||||
*/
|
||||
typedef float khronos_float_t;
|
||||
#endif
|
||||
|
||||
#if KHRONOS_SUPPORT_INT64
|
||||
/* Time types
|
||||
*
|
||||
* These types can be used to represent a time interval in nanoseconds or
|
||||
* an absolute Unadjusted System Time. Unadjusted System Time is the number
|
||||
* of nanoseconds since some arbitrary system event (e.g. since the last
|
||||
* time the system booted). The Unadjusted System Time is an unsigned
|
||||
* 64 bit value that wraps back to 0 every 584 years. Time intervals
|
||||
* may be either signed or unsigned.
|
||||
*/
|
||||
typedef khronos_uint64_t khronos_utime_nanoseconds_t;
|
||||
typedef khronos_int64_t khronos_stime_nanoseconds_t;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Dummy value used to pad enum types to 32 bits.
|
||||
*/
|
||||
#ifndef KHRONOS_MAX_ENUM
|
||||
#define KHRONOS_MAX_ENUM 0x7FFFFFFF
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Enumerated boolean type
|
||||
*
|
||||
* Values other than zero should be considered to be true. Therefore
|
||||
* comparisons should not be made against KHRONOS_TRUE.
|
||||
*/
|
||||
typedef enum {
|
||||
KHRONOS_FALSE = 0,
|
||||
KHRONOS_TRUE = 1,
|
||||
KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
|
||||
} khronos_boolean_enum_t;
|
||||
|
||||
#endif /* __khrplatform_h_ */
|
||||
7898
vendor/loaders/stb_image.h
vendored
Normal file
7898
vendor/loaders/stb_image.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
5079
vendor/loaders/stb_truetype.h
vendored
Normal file
5079
vendor/loaders/stb_truetype.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1735
vendor/loaders/tinyobj.h
vendored
Normal file
1735
vendor/loaders/tinyobj.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2644
vendor/raymath.h
vendored
Normal file
2644
vendor/raymath.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user