wip lightmapper + GUI improvements

main
Dominik Madarász 2023-11-30 14:33:49 +01:00
parent 1e65c7cdcf
commit ab06ce0192
18 changed files with 7698 additions and 136 deletions

View File

@ -31,6 +31,7 @@ if "%1"=="help" (
echo %0 [test] ; check untracked allocators in V4K
echo %0 [todo] ; check for @fixme and @todo
echo %0 [v4web] ; sync v4 website
echo %0 [swap] ; toggle #line directives on/off
echo %0 [split^|join] ; engine/v4k* ^>split^> engine/split/* or engine/split/* ^>join^> engine/v4k*
echo %0 [lua] ; execute lua script with v4k
echo %0 [amalgamation] ; combine engine/v4k* into a single-header file
@ -243,6 +244,13 @@ if "%1"=="join" (
call tools\join
exit /b
)
if "%1"=="swap" (
echo Swapping #line on v4k.h
call tools\linswap engine\v4k.h
echo Swapping #line on v4k.c
call tools\linswap engine\v4k.c
exit /b
)
rem fuse binaries and zipfiles
if "%1"=="fuse" (

View File

@ -1520,17 +1520,23 @@ ffi.cdef([[
//lcpp INF [0000] vec2: macro name but used as C declaration in:vec2 fire;
//lcpp INF [0000] vec4: macro name but used as C declaration in:vec4 pos;
//lcpp INF [0000] vec2: macro name but used as C declaration in:vec2 sca;
//lcpp INF [0000] vec4: macro name but used as C declaration in:void (*drawrect)(void* userdata, const char *skin, vec4 rect);
//lcpp INF [0000] vec2: macro name but used as C declaration in:void (*getskinsize)(void* userdata, const char *skin, vec2 *size);
//lcpp INF [0000] vec4: macro name but used as C declaration in:void (*getscissorrect)(void* userdata, const char *skin, vec4 rect, vec4 *dims);
//lcpp INF [0000] vec4: macro name but used as C declaration in:void (*getscissorrect)(void* userdata, const char *skin, vec4 rect, vec4 *dims);
//lcpp INF [0000] vec4: macro name but used as C declaration in:bool (*ismouseinrect)(void* userdata, const char *skin, vec4 rect);
//lcpp INF [0000] vec2: macro name but used as C declaration in:API vec2 gui_getskinsize(const char *skin);
//lcpp INF [0000] vec2: macro name but used as C declaration in:STATIC vec2 gui_getskinsize(const char *skin);
//lcpp INF [0000] vec2: macro name but used as C declaration in: vec2 gui_getskinsize(const char *skin);
//lcpp INF [0000] vec4: macro name but used as C declaration in:API bool gui_ismouseinrect(const char *skin, vec4 rect);
//lcpp INF [0000] vec4: macro name but used as C declaration in:STATIC bool gui_ismouseinrect(const char *skin, vec4 rect);
//lcpp INF [0000] vec4: macro name but used as C declaration in: bool gui_ismouseinrect(const char *skin, vec4 rect);
//lcpp INF [0000] vec4: macro name but used as C declaration in:void (*drawrect)(void* userdata, const char *skin, const char *fallback, vec4 rect);
//lcpp INF [0000] vec2: macro name but used as C declaration in:void (*getskinsize)(void* userdata, const char *skin, const char *fallback, vec2 *size);
//lcpp INF [0000] vec4: macro name but used as C declaration in:void (*getscissorrect)(void* userdata, const char *skin, const char *fallback, vec4 rect, vec4 *dims);
//lcpp INF [0000] vec4: macro name but used as C declaration in:void (*getscissorrect)(void* userdata, const char *skin, const char *fallback, vec4 rect, vec4 *dims);
//lcpp INF [0000] vec4: macro name but used as C declaration in:bool (*ismouseinrect)(void* userdata, const char *skin, const char *fallback, vec4 rect);
//lcpp INF [0000] vec2: macro name but used as C declaration in:API vec2 gui_getskinsize(const char *skin, const char *fallback);
//lcpp INF [0000] vec2: macro name but used as C declaration in:STATIC vec2 gui_getskinsize(const char *skin, const char *fallback);
//lcpp INF [0000] vec2: macro name but used as C declaration in: vec2 gui_getskinsize(const char *skin, const char *fallback);
//lcpp INF [0000] vec4: macro name but used as C declaration in:API bool gui_ismouseinrect(const char *skin, const char *fallback, vec4 rect);
//lcpp INF [0000] vec4: macro name but used as C declaration in:STATIC bool gui_ismouseinrect(const char *skin, const char *fallback, vec4 rect);
//lcpp INF [0000] vec4: macro name but used as C declaration in: bool gui_ismouseinrect(const char *skin, const char *fallback, vec4 rect);
//lcpp INF [0000] vec4: macro name but used as C declaration in:API vec4 gui_getscissorrect(const char *skin, const char *fallback, vec4 rect);
//lcpp INF [0000] vec4: macro name but used as C declaration in:API vec4 gui_getscissorrect(const char *skin, const char *fallback, vec4 rect);
//lcpp INF [0000] vec4: macro name but used as C declaration in:STATIC vec4 gui_getscissorrect(const char *skin, const char *fallback, vec4 rect);
//lcpp INF [0000] vec4: macro name but used as C declaration in:STATIC vec4 gui_getscissorrect(const char *skin, const char *fallback, vec4 rect);
//lcpp INF [0000] vec4: macro name but used as C declaration in: vec4 gui_getscissorrect(const char *skin, const char *fallback, vec4 rect);
//lcpp INF [0000] vec4: macro name but used as C declaration in: vec4 gui_getscissorrect(const char *skin, const char *fallback, vec4 rect);
//lcpp INF [0000] vec4: macro name but used as C declaration in:API void gui_panel_id(int id, vec4 rect, const char *skin);
//lcpp INF [0000] vec4: macro name but used as C declaration in:STATIC void gui_panel_id(int id, vec4 rect, const char *skin);
//lcpp INF [0000] vec4: macro name but used as C declaration in: void gui_panel_id(int id, vec4 rect, const char *skin);
@ -2991,6 +2997,9 @@ float speed;
anim_t* anims;
} anims_t;
anims_t animations(const char *pathfile, int flags);
typedef struct lightmap_t {
struct lm_context *ctx;
} lightmap_t;
typedef struct skybox_t {
handle program;
mesh_t geometry;
@ -3315,7 +3324,7 @@ unsigned play;
bool paused;
struct atlas_t *a;
} sprite_t;
enum { OBJTYPE_sprite_t = 10 }; typedef struct { unsigned static_assert_on_L__LINE__ : !!(10 <= 255); } static_assert_on_Lconcat(_L,3938)___COUNTER__; typedef struct { unsigned static_assert_on_L__LINE__ : !!(sizeof(sprite_t)); } static_assert_on_Lconcat(_L,3938)___COUNTER__;;
enum { OBJTYPE_sprite_t = 10 }; typedef struct { unsigned static_assert_on_L__LINE__ : !!(10 <= 255); } static_assert_on_Lconcat(_L,3945)___COUNTER__; typedef struct { unsigned static_assert_on_L__LINE__ : !!(sizeof(sprite_t)); } static_assert_on_Lconcat(_L,3945)___COUNTER__;;
void sprite_ctor(sprite_t *s);
void sprite_dtor(sprite_t *s);
void sprite_tick(sprite_t *s);
@ -3325,17 +3334,18 @@ enum { OBJTYPE_sprite_t = 10 }; typedef struct { unsigned static_assert_on
void sprite_del(sprite_t *s);
void sprite_setanim(sprite_t *s, unsigned name);
typedef struct guiskin_t {
void (*drawrect)(void* userdata, const char *skin, vec4 rect);
void (*getskinsize)(void* userdata, const char *skin, vec2 *size);
void (*getscissorrect)(void* userdata, const char *skin, vec4 rect, vec4 *dims);
bool (*ismouseinrect)(void* userdata, const char *skin, vec4 rect);
void (*drawrect)(void* userdata, const char *skin, const char *fallback, vec4 rect);
void (*getskinsize)(void* userdata, const char *skin, const char *fallback, vec2 *size);
void (*getscissorrect)(void* userdata, const char *skin, const char *fallback, vec4 rect, vec4 *dims);
bool (*ismouseinrect)(void* userdata, const char *skin, const char *fallback, vec4 rect);
void (*free)(void* userdata);
void *userdata;
} guiskin_t;
void gui_pushskin(guiskin_t skin);
void* gui_userdata();
vec2 gui_getskinsize(const char *skin);
bool gui_ismouseinrect(const char *skin, vec4 rect);
vec2 gui_getskinsize(const char *skin, const char *fallback);
bool gui_ismouseinrect(const char *skin, const char *fallback, vec4 rect);
vec4 gui_getscissorrect(const char *skin, const char *fallback, vec4 rect);
void gui_panel_id(int id, vec4 rect, const char *skin);
void gui_rect_id(int id, vec4 rect, const char *skin);
void gui_label_id(int id, const char *text, vec4 rect);

File diff suppressed because it is too large Load Diff

View File

@ -45,13 +45,13 @@ int main() {
gui_rect(vec4(40,240, 240, 20*skinned->scale), "vial");
gui_rect(vec4(40,240, 160, 14*skinned->scale), "mp");
vec2 badge_size = gui_getskinsize("badge");
vec2 badge_size = gui_getskinsize("badge", 0);
badge_size.x += 2; // padding
gui_rect(vec4(60+badge_size.x*0,320, 1, 1), "badge");
gui_rect(vec4(60+badge_size.x*1,320, 1, 1), "badge");
gui_rect(vec4(60+badge_size.x*2,320, 1, 1), "badge_empty");
vec2 slider_size = gui_getskinsize("slider");
vec2 slider_size = gui_getskinsize("slider", 0);
gui_slider(vec4(60, 480, 80*skinned->scale, 1), 0, 0.0f, 15.0f, 1.0f, &testval);
gui_slider_label(va(FONT_H1 "%.02f", testval2), vec4(60, 480+slider_size.y+10, 120*skinned->scale, 1), 0, -5.0f, 20.0f, 0.0f, &testval2);
gui_panel_end();

407
demos/99-lmap.c 100644
View File

@ -0,0 +1,407 @@
#include "v4k.h"
#define LIGHTMAPPER_IMPLEMENTATION
// #define LM_DEBUG_INTERPOLATION
#include "3rd_lightmapper.h"
#define scene_t scene_t2
typedef struct {
float p[3];
float t[2];
} vertex_t;
typedef struct
{
GLuint program;
GLint u_lightmap;
GLint u_projection;
GLint u_view;
GLuint lightmap;
int w, h;
GLuint vao, vbo, ibo;
vertex_t *vertices;
unsigned short *indices;
unsigned int vertexCount, indexCount;
} scene_t;
static int initScene(scene_t *scene);
static void drawScene(scene_t *scene, float *view, float *projection);
static void destroyScene(scene_t *scene);
static int bake(scene_t *scene)
{
lm_context *ctx = lmCreate(
64, // hemisphere resolution (power of two, max=512)
0.001f, 100.0f, // zNear, zFar of hemisphere cameras
1.0f, 1.0f, 1.0f, // background color (white for ambient occlusion)
2, 0.01f, // lightmap interpolation threshold (small differences are interpolated rather than sampled)
// check debug_interpolation.tga for an overview of sampled (red) vs interpolated (green) pixels.
0.0f); // modifier for camera-to-surface distance for hemisphere rendering.
// tweak this to trade-off between interpolated normals quality and other artifacts (see declaration).
if (!ctx)
{
fprintf(stderr, "Error: Could not initialize lightmapper.\n");
return 0;
}
int w = scene->w, h = scene->h;
float *data = CALLOC(w * h * 4, sizeof(float));
for (int b = 0; b < 1; b++) {
memset(data, 0, w*h*4);
lmSetTargetLightmap(ctx, data, w, h, 4);
lmSetGeometry(ctx, NULL, // no transformation in this example
LM_FLOAT, (unsigned char*)scene->vertices + offsetof(vertex_t, p), sizeof(vertex_t),
LM_NONE , NULL , 0 , // no interpolated normals in this example
LM_FLOAT, (unsigned char*)scene->vertices + offsetof(vertex_t, t), sizeof(vertex_t),
scene->indexCount, LM_UNSIGNED_SHORT, scene->indices);
glDisable(GL_BLEND);
int vp[4];
float view[16], projection[16];
double lastUpdateTime = 0.0;
while (lmBegin(ctx, vp, view, projection))
{
// render to lightmapper framebuffer
glViewport(vp[0], vp[1], vp[2], vp[3]);
drawScene(scene, view, projection);
// display progress every second (printf is expensive)
double time = time_ms() / 1000.0;
if (time - lastUpdateTime > 1.0)
{
lastUpdateTime = time;
printf("\r%6.2f%%", lmProgress(ctx) * 100.0f);
fflush(stdout);
}
lmEnd(ctx);
// window_swap();
}
printf("\rFinished baking %d triangles.\n", scene->indexCount / 3);
}
lmDestroy(ctx);
// postprocess texture
float *temp = CALLOC(w * h * 4, sizeof(float));
for (int i = 0; i < 16; i++)
{
lmImageDilate(data, temp, w, h, 4);
lmImageDilate(temp, data, w, h, 4);
}
lmImageSmooth(data, temp, w, h, 4);
lmImageDilate(temp, data, w, h, 4);
lmImagePower(data, w, h, 4, 1.0f / 2.2f, 0x7); // gamma correct color channels
FREE(temp);
// save result to a file
if (lmImageSaveTGAf("result.tga", data, w, h, 4, 1.0f))
printf("Saved result.tga\n");
// upload result
glBindTexture(GL_TEXTURE_2D, scene->lightmap);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_FLOAT, data);
FREE(data);
return 1;
}
static void fpsCameraViewMatrix(float *view);
static void mainLoop(scene_t *scene)
{
glViewport(0, 0, window_width(), window_height());
// camera for glfw window
float view[16], projection[16];
fpsCameraViewMatrix(view);
perspective44(projection, 45.0f, window_aspect(), 0.01f, 100.0f);
// draw to screen with a blueish sky
glClearColor(0.6f, 0.8f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
drawScene(scene, view, projection);
}
int main()
{
window_create(0.5, WINDOW_VSYNC_DISABLED);
scene_t scene = {0};
if (!initScene(&scene))
{
fprintf(stderr, "Could not initialize scene.\n");
return EXIT_FAILURE;
}
window_title("AO Baking demo");
while (window_swap())
{
mainLoop(&scene);
if( ui_panel("Lightmapper", PANEL_OPEN) ) {
ui_label2("Freecam", "Mouse + W/A/S/D/E/Q keys");
ui_label("Warning " ICON_MD_WARNING "@This will take a few seconds and bake a lightmap illuminated by: The mesh itself (initially black) + A white sky (1.0f, 1.0f, 1.0f)");
if( ui_button("Bake 1 light bounce") ) {
bake(&scene);
}
ui_panel_end();
}
}
destroyScene(&scene);
}
// helpers ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static int loadSimpleObjFile(const char *filename, vertex_t **vertices, unsigned int *vertexCount, unsigned short **indices, unsigned int *indexCount);
static int initScene(scene_t *scene)
{
// load mesh
if (!loadSimpleObjFile("demos/art/meshes/gazebo.obj", &scene->vertices, &scene->vertexCount, &scene->indices, &scene->indexCount))
{
fprintf(stderr, "Error loading obj file\n");
return 0;
}
glGenVertexArrays(1, &scene->vao);
glBindVertexArray(scene->vao);
glGenBuffers(1, &scene->vbo);
glBindBuffer(GL_ARRAY_BUFFER, scene->vbo);
glBufferData(GL_ARRAY_BUFFER, scene->vertexCount * sizeof(vertex_t), scene->vertices, GL_STATIC_DRAW);
glGenBuffers(1, &scene->ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, scene->ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, scene->indexCount * sizeof(unsigned short), scene->indices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (void*)offsetof(vertex_t, p));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (void*)offsetof(vertex_t, t));
// create lightmap texture
scene->w = 654;
scene->h = 654;
glGenTextures(1, &scene->lightmap);
glBindTexture(GL_TEXTURE_2D, scene->lightmap);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
unsigned char emissive[] = { 0, 0, 0, 255 };
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, emissive);
// load shader
const char *vp =
"in vec3 a_position;\n"
"in vec2 a_texcoord;\n"
"uniform mat4 u_view;\n"
"uniform mat4 u_projection;\n"
"out vec2 v_texcoord;\n"
"void main()\n"
"{\n"
"gl_Position = u_projection * (u_view * vec4(a_position, 1.0));\n"
"v_texcoord = a_texcoord;\n"
"}\n";
const char *fp =
"in vec2 v_texcoord;\n"
"uniform sampler2D u_lightmap;\n"
"out vec4 o_color;\n"
"void main()\n"
"{\n"
"o_color = vec4(texture(u_lightmap, v_texcoord).rgb, gl_FrontFacing ? 1.0 : 0.0);\n"
"}\n";
scene->program = shader(vp, fp, "a_position,a_texcoord", "o_color", NULL);
if (!scene->program)
{
fprintf(stderr, "Error loading shader\n");
return 0;
}
scene->u_view = glGetUniformLocation(scene->program, "u_view");
scene->u_projection = glGetUniformLocation(scene->program, "u_projection");
scene->u_lightmap = glGetUniformLocation(scene->program, "u_lightmap");
return 1;
}
static void drawScene(scene_t *scene, float *view, float *projection)
{
glEnable(GL_DEPTH_TEST);
glUseProgram(scene->program);
glUniform1i(scene->u_lightmap, 0);
glUniformMatrix4fv(scene->u_projection, 1, GL_FALSE, projection);
glUniformMatrix4fv(scene->u_view, 1, GL_FALSE, view);
glBindTexture(GL_TEXTURE_2D, scene->lightmap);
glBindVertexArray(scene->vao);
glDrawElements(GL_TRIANGLES, scene->indexCount, GL_UNSIGNED_SHORT, 0);
}
static void destroyScene(scene_t *scene)
{
FREE(scene->vertices);
FREE(scene->indices);
glDeleteVertexArrays(1, &scene->vao);
glDeleteBuffers(1, &scene->vbo);
glDeleteBuffers(1, &scene->ibo);
glDeleteTextures(1, &scene->lightmap);
glDeleteProgram(scene->program);
}
static int loadSimpleObjFile(const char *filename, vertex_t **vertices, unsigned int *vertexCount, unsigned short **indices, unsigned int *indexCount)
{
FILE *file = fopen(filename, "rt");
if (!file)
return 0;
char line[1024];
// first pass
unsigned int np = 0, nn = 0, nt = 0, nf = 0;
while (!feof(file))
{
fgets(line, 1024, file);
if (line[0] == '#') continue;
if (line[0] == 'v')
{
if (line[1] == ' ') { np++; continue; }
if (line[1] == 'n') { nn++; continue; }
if (line[1] == 't') { nt++; continue; }
assert(!"unknown vertex attribute");
}
if (line[0] == 'f') { nf++; continue; }
assert(!"unknown identifier");
}
assert(np && np == nn && np == nt && nf); // only supports obj files without separately indexed vertex attributes
// allocate memory
*vertexCount = np;
*vertices = CALLOC(np, sizeof(vertex_t));
*indexCount = nf * 3;
*indices = CALLOC(nf * 3, sizeof(unsigned short));
// second pass
fseek(file, 0, SEEK_SET);
unsigned int cp = 0, cn = 0, ct = 0, cf = 0;
while (!feof(file))
{
fgets(line, 1024, file);
if (line[0] == '#') continue;
if (line[0] == 'v')
{
if (line[1] == ' ') { float *p = (*vertices)[cp++].p; char *e1, *e2; p[0] = (float)strtod(line + 2, &e1); p[1] = (float)strtod(e1, &e2); p[2] = (float)strtod(e2, 0); continue; }
if (line[1] == 'n') { /*float *n = (*vertices)[cn++].n; char *e1, *e2; n[0] = (float)strtod(line + 3, &e1); n[1] = (float)strtod(e1, &e2); n[2] = (float)strtod(e2, 0);*/ continue; } // no normals needed
if (line[1] == 't') { float *t = (*vertices)[ct++].t; char *e1; t[0] = (float)strtod(line + 3, &e1); t[1] = (float)strtod(e1, 0); continue; }
assert(!"unknown vertex attribute");
}
if (line[0] == 'f')
{
unsigned short *tri = (*indices) + cf;
cf += 3;
char *e1, *e2, *e3 = line + 1;
for (int i = 0; i < 3; i++)
{
unsigned long pi = strtoul(e3 + 1, &e1, 10);
assert(e1[0] == '/');
unsigned long ti = strtoul(e1 + 1, &e2, 10);
assert(e2[0] == '/');
unsigned long ni = strtoul(e2 + 1, &e3, 10);
assert(pi == ti && pi == ni);
tri[i] = (unsigned short)(pi - 1);
}
continue;
}
assert(!"unknown identifier");
}
fclose(file);
return 1;
}
static void fpsCameraViewMatrix(float *view)
{
// initial camera config
static float position[] = { 0.0f, 0.3f, 1.5f };
static float rotation[] = { 0.0f, 0.0f };
// mouse look
static double lastMouse[] = { 0.0, 0.0 };
double mouse_coord[2];
mouse_coord[0] = input(MOUSE_X);
mouse_coord[1] = input(MOUSE_Y);
if (input(MOUSE_L))
{
rotation[0] += (float)(mouse_coord[1] - lastMouse[1]) * -0.2f;
rotation[1] += (float)(mouse_coord[0] - lastMouse[0]) * -0.2f;
}
lastMouse[0] = mouse_coord[0];
lastMouse[1] = mouse_coord[1];
float rotationY[16], rotationX[16], rotationYX[16];
rotation44(rotationX, rotation[0], 1.0f, 0.0f, 0.0f);
rotation44(rotationY, rotation[1], 0.0f, 1.0f, 0.0f);
multiply44x2(rotationYX, rotationY, rotationX);
// keyboard movement (WSADEQ)
float speed = input(KEY_SHIFT) ? 0.1f : 0.01f;
vec3 movement = {0};
if (input(KEY_W)) movement.z -= speed;
if (input(KEY_S)) movement.z += speed;
if (input(KEY_A)) movement.x -= speed;
if (input(KEY_D)) movement.x += speed;
if (input(KEY_E)) movement.y -= speed;
if (input(KEY_Q)) movement.y += speed;
vec3 worldMovement = transform344(rotationYX, movement);
position[0] += worldMovement.x;
position[1] += worldMovement.y;
position[2] += worldMovement.z;
// construct view matrix
float inverseRotation[16], inverseTranslation[16];
transpose44(inverseRotation, rotationYX);
translation44(inverseTranslation, -position[0], -position[1], -position[2]);
multiply44x2(view, inverseRotation, inverseTranslation); // = inverse(translation(position) * rotationYX);
}
#if 0
#######################################################################
76702 17.93% rendered hemicubes integrated to lightmap texels.
179388 41.94% interpolated lightmap texels.
171626 40.13% wasted lightmap texels.
29.95% of used texels were rendered.
#######################################################################
Finished baking 731 triangles.
Saved result.tga
vs
#######################################################################
124 0.05% rendered hemicubes integrated to lightmap texels.
201 0.08% interpolated lightmap texels.
261947 99.88% wasted lightmap texels.
38.15% of used texels were rendered.
#######################################################################
Finished baking 731 triangles.
Saved result.tga
#endif

View File

@ -1,15 +0,0 @@
#include "v4k.h" // Minimal C sample
__thread int foo=0;
int worker(void *ud) {
printf("thread:%d\n", foo);
return 0;
}
int main() {
foo=1;
printf("main:%d\n", foo);
thread_destroy(thread(worker, NULL));
return 0;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -53,6 +53,7 @@
#define BQ_PLATFORM_IMPLEMENTATION // websocket
#define BQ_WEBSOCKET_IMPLEMENTATION // websocket
#define XML_C // xml
#define LIGHTMAPPER_IMPLEMENTATION // lightmapper
#ifdef __APPLE__
#define MA_NO_RUNTIME_LINKING // miniaudio osx
#define _GLFW_COCOA // glfw osx
@ -217,4 +218,6 @@ static char *ui_filter = 0;
{{FILE:3rd_lite_sys.h}}
{{FILE:3rd_lite.h}}
{{FILE:3rd_lightmapper.h}}
#endif // V4K_3RD

View File

@ -118,17 +118,23 @@ void *gui_userdata() {
return last_skin->userdata;
}
vec2 gui_getskinsize(const char *skin) {
vec2 gui_getskinsize(const char *skin, const char *fallback) {
vec2 size={0};
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, skin, &size);
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, skin, fallback, &size);
return size;
}
bool gui_ismouseinrect(const char *skin, vec4 rect) {
if (last_skin->ismouseinrect) return last_skin->ismouseinrect(last_skin->userdata, skin, rect);
bool gui_ismouseinrect(const char *skin, const char *fallback, vec4 rect) {
if (last_skin->ismouseinrect) return last_skin->ismouseinrect(last_skin->userdata, skin, fallback, rect);
return false;
}
vec4 gui_getscissorrect(const char *skin, const char *fallback, vec4 rect) {
vec4 scissor = rect;
if (last_skin->getscissorrect) last_skin->getscissorrect(last_skin->userdata, skin, fallback, rect, &scissor);
return scissor;
}
static
gui_state_t *gui_getstate(int id) {
if (!ctl_states) map_init(ctl_states, less_int, hash_int);
@ -138,8 +144,8 @@ gui_state_t *gui_getstate(int id) {
void gui_panel_id(int id, vec4 rect, const char *skin) {
(void)id;
vec4 scissor={0, 0, window_width(), window_height()};
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, rect);
if (last_skin->getscissorrect) last_skin->getscissorrect(last_skin->userdata, skin, rect, &scissor);
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, NULL, rect);
scissor = gui_getscissorrect(skin, NULL, rect);
if (!array_count(scissor_rects))
glEnable(GL_SCISSOR_TEST);
@ -164,7 +170,7 @@ bool gui_button_id(int id, vec4 r, const char *skin) {
skin=skin?skin:"button";
char *btn = va("%s%s", skin, entry->held?"_press":entry->hover?"_hover":"");
if (gui_ismouseinrect(btn, r)) {
if (gui_ismouseinrect(btn, skin, r)) {
if (input_up(MOUSE_L) && entry->held) {
was_clicked=1;
}
@ -174,24 +180,27 @@ bool gui_button_id(int id, vec4 r, const char *skin) {
entry->hover = true;
}
}
else if (input_up(MOUSE_L) && entry->held) {
entry->held = false;
any_widget_used = false;
}
else {
entry->hover = false;
}
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, btn, r);
if (input_up(MOUSE_L) && entry->held) {
entry->held = false;
any_widget_used = false;
}
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, btn, skin, r);
return was_clicked;
}
bool gui_button_label_id(int id, const char *text, vec4 rect, const char *skin) {
gui_state_t *entry = gui_getstate(id);
bool state = gui_button_id(id, rect, skin);
vec2 buttonsize={0};
skin=skin?skin:"button";
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, skin, &buttonsize);
char *btn = va("%s%s", skin, entry->held?"_press":entry->hover?"_hover":"");
buttonsize = gui_getskinsize(btn, skin);
vec2 textsize = font_rect(text);
vec2 pos;
@ -224,7 +233,8 @@ bool gui_slider_id(int id, vec4 rect, const char *skin, float min, float max, fl
skin = skin?skin:"slider";
char *cursorskin = va("%s_cursor%s", skin, entry->held?"_press":entry->hover?"_hover":"");
if (gui_ismouseinrect(skin, rect) && !any_widget_used) {
char *fbcursor = va("%s_cursor", skin);
if (gui_ismouseinrect(skin, NULL, rect) && !any_widget_used) {
any_widget_used = entry->held = input_held(MOUSE_L);
entry->hover = true;
}
@ -237,13 +247,12 @@ bool gui_slider_id(int id, vec4 rect, const char *skin, float min, float max, fl
}
float old_value = *value;
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, rect);
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, NULL, rect);
vec2 slidersize={0}, cursorsize={0};
vec4 usablerect=rect;
if (last_skin->getscissorrect) last_skin->getscissorrect(last_skin->userdata, skin, rect, &usablerect);
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, skin, &slidersize);
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, cursorskin, &cursorsize);
vec4 usablerect = gui_getscissorrect(skin, NULL, rect);
slidersize = gui_getskinsize(skin, NULL);
cursorsize = gui_getskinsize(cursorskin, fbcursor);
if (entry->held) {
*value = posx2slider(usablerect, min, max, input(MOUSE_X), step);
}
@ -254,7 +263,7 @@ bool gui_slider_id(int id, vec4 rect, const char *skin, float min, float max, fl
cursorrect.y += cursorpos.y;
cursorrect.z = cursorsize.x;
cursorrect.w = cursorsize.y;
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, cursorskin, cursorrect);
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, cursorskin, fbcursor, cursorrect);
return entry->held && (old_value!=*value);
}
@ -263,7 +272,7 @@ bool gui_slider_label_id(int id, const char *text, vec4 rect, const char *skin,
bool state = gui_slider_id(id, rect, skin, min, max, step, value);
vec2 slidersize={0};
skin=skin?skin:"slider";
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, skin, &slidersize);
slidersize = gui_getskinsize(skin, NULL);
vec2 textsize = font_rect(text);
vec2 pos;
@ -276,7 +285,7 @@ bool gui_slider_label_id(int id, const char *text, vec4 rect, const char *skin,
void gui_rect_id(int id, vec4 r, const char *skin) {
(void)id;
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, r);
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, NULL, r);
}
void gui_label_id(int id, const char *text, vec4 rect) {
@ -300,7 +309,7 @@ atlas_slice_frame_t *skinned_getsliceframe(atlas_t *a, const char *name) {
for (int i = 0; i < array_count(a->slices); i++)
if (!strcmp(quark_string(&a->db, a->slices[i].name), name))
return &a->slice_frames[a->slices[i].frames[0]];
PRINTF("slice name: '%s' is missing in atlas!\n", name);
// PRINTF("slice name: '%s' is missing in atlas!\n", name);
return NULL;
}
@ -311,9 +320,10 @@ void skinned_draw_missing_rect(vec4 r) {
}
static
bool skinned_ismouseinrect(void *userdata, const char *skin, vec4 r) {
bool skinned_ismouseinrect(void *userdata, const char *skin, const char *fallback, vec4 r) {
skinned_t *a = C_CAST(skinned_t*, userdata);
atlas_slice_frame_t *f = skinned_getsliceframe(&a->atlas, skin);
if (!f && fallback) f = skinned_getsliceframe(&a->atlas, fallback);
if (!f) return false;
vec4 outer = f->bounds;
@ -396,18 +406,20 @@ void skinned_draw_sprite(float scale, atlas_t *a, atlas_slice_frame_t *f, vec4 r
}
static
void skinned_draw_rect(void* userdata, const char *skin, vec4 r) {
void skinned_draw_rect(void* userdata, const char *skin, const char *fallback, vec4 r) {
skinned_t *a = C_CAST(skinned_t*, userdata);
atlas_slice_frame_t *f = skinned_getsliceframe(&a->atlas, skin);
if (!f && fallback) f = skinned_getsliceframe(&a->atlas, fallback);
if (!f) skinned_draw_missing_rect(r);
else skinned_draw_sprite(a->scale, &a->atlas, f, r);
}
void skinned_getskinsize(void *userdata, const char *skin, vec2 *size) {
void skinned_getskinsize(void *userdata, const char *skin, const char *fallback, vec2 *size) {
skinned_t *a = C_CAST(skinned_t*, userdata);
atlas_slice_frame_t *f = skinned_getsliceframe(&a->atlas, skin);
if (!f && fallback) f = skinned_getsliceframe(&a->atlas, fallback);
if (f) {
size->x = (f->bounds.z-f->bounds.x)*a->scale;
size->y = (f->bounds.w-f->bounds.y)*a->scale;
@ -415,9 +427,10 @@ void skinned_getskinsize(void *userdata, const char *skin, vec2 *size) {
}
static
void skinned_getscissorrect(void* userdata, const char *skin, vec4 rect, vec4 *dims) {
void skinned_getscissorrect(void* userdata, const char *skin, const char *fallback, vec4 rect, vec4 *dims) {
skinned_t *a = C_CAST(skinned_t*, userdata);
atlas_slice_frame_t *f = skinned_getsliceframe(&a->atlas, skin);
if (!f && fallback) f = skinned_getsliceframe(&a->atlas, fallback);
if (!f) return;
*dims = rect;

View File

@ -2,18 +2,19 @@
// game ui
typedef struct guiskin_t {
void (*drawrect)(void* userdata, const char *skin, vec4 rect);
void (*getskinsize)(void* userdata, const char *skin, vec2 *size);
void (*getscissorrect)(void* userdata, const char *skin, vec4 rect, vec4 *dims);
bool (*ismouseinrect)(void* userdata, const char *skin, vec4 rect);
void (*drawrect)(void* userdata, const char *skin, const char *fallback, vec4 rect);
void (*getskinsize)(void* userdata, const char *skin, const char *fallback, vec2 *size);
void (*getscissorrect)(void* userdata, const char *skin, const char *fallback, vec4 rect, vec4 *dims);
bool (*ismouseinrect)(void* userdata, const char *skin, const char *fallback, vec4 rect);
void (*free)(void* userdata);
void *userdata;
} guiskin_t;
API void gui_pushskin(guiskin_t skin);
API void* gui_userdata();
API vec2 gui_getskinsize(const char *skin);
API bool gui_ismouseinrect(const char *skin, vec4 rect);
API vec2 gui_getskinsize(const char *skin, const char *fallback);
API bool gui_ismouseinrect(const char *skin, const char *fallback, vec4 rect);
API vec4 gui_getscissorrect(const char *skin, const char *fallback, vec4 rect);
// --
API void gui_panel_id(int id, vec4 rect, const char *skin);
API void gui_rect_id(int id, vec4 rect, const char *skin);

View File

@ -577,6 +577,13 @@ typedef struct anims_t {
API anims_t animations(const char *pathfile, int flags);
// -----------------------------------------------------------------------------
// lightmapping utils
typedef struct lightmap_t {
struct lm_context *ctx; // private
} lightmap_t;
// -----------------------------------------------------------------------------
// skyboxes

1765
engine/v4k

File diff suppressed because it is too large Load Diff

View File

@ -11128,17 +11128,23 @@ void *gui_userdata() {
return last_skin->userdata;
}
vec2 gui_getskinsize(const char *skin) {
vec2 gui_getskinsize(const char *skin, const char *fallback) {
vec2 size={0};
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, skin, &size);
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, skin, fallback, &size);
return size;
}
bool gui_ismouseinrect(const char *skin, vec4 rect) {
if (last_skin->ismouseinrect) return last_skin->ismouseinrect(last_skin->userdata, skin, rect);
bool gui_ismouseinrect(const char *skin, const char *fallback, vec4 rect) {
if (last_skin->ismouseinrect) return last_skin->ismouseinrect(last_skin->userdata, skin, fallback, rect);
return false;
}
vec4 gui_getscissorrect(const char *skin, const char *fallback, vec4 rect) {
vec4 scissor = rect;
if (last_skin->getscissorrect) last_skin->getscissorrect(last_skin->userdata, skin, fallback, rect, &scissor);
return scissor;
}
static
gui_state_t *gui_getstate(int id) {
if (!ctl_states) map_init(ctl_states, less_int, hash_int);
@ -11148,8 +11154,8 @@ gui_state_t *gui_getstate(int id) {
void gui_panel_id(int id, vec4 rect, const char *skin) {
(void)id;
vec4 scissor={0, 0, window_width(), window_height()};
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, rect);
if (last_skin->getscissorrect) last_skin->getscissorrect(last_skin->userdata, skin, rect, &scissor);
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, NULL, rect);
scissor = gui_getscissorrect(skin, NULL, rect);
if (!array_count(scissor_rects))
glEnable(GL_SCISSOR_TEST);
@ -11174,7 +11180,7 @@ bool gui_button_id(int id, vec4 r, const char *skin) {
skin=skin?skin:"button";
char *btn = va("%s%s", skin, entry->held?"_press":entry->hover?"_hover":"");
if (gui_ismouseinrect(btn, r)) {
if (gui_ismouseinrect(btn, skin, r)) {
if (input_up(MOUSE_L) && entry->held) {
was_clicked=1;
}
@ -11184,24 +11190,27 @@ bool gui_button_id(int id, vec4 r, const char *skin) {
entry->hover = true;
}
}
else if (input_up(MOUSE_L) && entry->held) {
entry->held = false;
any_widget_used = false;
}
else {
entry->hover = false;
}
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, btn, r);
if (input_up(MOUSE_L) && entry->held) {
entry->held = false;
any_widget_used = false;
}
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, btn, skin, r);
return was_clicked;
}
bool gui_button_label_id(int id, const char *text, vec4 rect, const char *skin) {
gui_state_t *entry = gui_getstate(id);
bool state = gui_button_id(id, rect, skin);
vec2 buttonsize={0};
skin=skin?skin:"button";
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, skin, &buttonsize);
char *btn = va("%s%s", skin, entry->held?"_press":entry->hover?"_hover":"");
buttonsize = gui_getskinsize(btn, skin);
vec2 textsize = font_rect(text);
vec2 pos;
@ -11234,7 +11243,8 @@ bool gui_slider_id(int id, vec4 rect, const char *skin, float min, float max, fl
skin = skin?skin:"slider";
char *cursorskin = va("%s_cursor%s", skin, entry->held?"_press":entry->hover?"_hover":"");
if (gui_ismouseinrect(skin, rect) && !any_widget_used) {
char *fbcursor = va("%s_cursor", skin);
if (gui_ismouseinrect(skin, NULL, rect) && !any_widget_used) {
any_widget_used = entry->held = input_held(MOUSE_L);
entry->hover = true;
}
@ -11247,13 +11257,12 @@ bool gui_slider_id(int id, vec4 rect, const char *skin, float min, float max, fl
}
float old_value = *value;
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, rect);
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, NULL, rect);
vec2 slidersize={0}, cursorsize={0};
vec4 usablerect=rect;
if (last_skin->getscissorrect) last_skin->getscissorrect(last_skin->userdata, skin, rect, &usablerect);
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, skin, &slidersize);
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, cursorskin, &cursorsize);
vec4 usablerect = gui_getscissorrect(skin, NULL, rect);
slidersize = gui_getskinsize(skin, NULL);
cursorsize = gui_getskinsize(cursorskin, fbcursor);
if (entry->held) {
*value = posx2slider(usablerect, min, max, input(MOUSE_X), step);
}
@ -11264,7 +11273,7 @@ bool gui_slider_id(int id, vec4 rect, const char *skin, float min, float max, fl
cursorrect.y += cursorpos.y;
cursorrect.z = cursorsize.x;
cursorrect.w = cursorsize.y;
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, cursorskin, cursorrect);
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, cursorskin, fbcursor, cursorrect);
return entry->held && (old_value!=*value);
}
@ -11273,7 +11282,7 @@ bool gui_slider_label_id(int id, const char *text, vec4 rect, const char *skin,
bool state = gui_slider_id(id, rect, skin, min, max, step, value);
vec2 slidersize={0};
skin=skin?skin:"slider";
if (last_skin->getskinsize) last_skin->getskinsize(last_skin->userdata, skin, &slidersize);
slidersize = gui_getskinsize(skin, NULL);
vec2 textsize = font_rect(text);
vec2 pos;
@ -11286,7 +11295,7 @@ bool gui_slider_label_id(int id, const char *text, vec4 rect, const char *skin,
void gui_rect_id(int id, vec4 r, const char *skin) {
(void)id;
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, r);
if (last_skin->drawrect) last_skin->drawrect(last_skin->userdata, skin, NULL, r);
}
void gui_label_id(int id, const char *text, vec4 rect) {
@ -11310,7 +11319,7 @@ atlas_slice_frame_t *skinned_getsliceframe(atlas_t *a, const char *name) {
for (int i = 0; i < array_count(a->slices); i++)
if (!strcmp(quark_string(&a->db, a->slices[i].name), name))
return &a->slice_frames[a->slices[i].frames[0]];
PRINTF("slice name: '%s' is missing in atlas!\n", name);
// PRINTF("slice name: '%s' is missing in atlas!\n", name);
return NULL;
}
@ -11321,9 +11330,10 @@ void skinned_draw_missing_rect(vec4 r) {
}
static
bool skinned_ismouseinrect(void *userdata, const char *skin, vec4 r) {
bool skinned_ismouseinrect(void *userdata, const char *skin, const char *fallback, vec4 r) {
skinned_t *a = C_CAST(skinned_t*, userdata);
atlas_slice_frame_t *f = skinned_getsliceframe(&a->atlas, skin);
if (!f && fallback) f = skinned_getsliceframe(&a->atlas, fallback);
if (!f) return false;
vec4 outer = f->bounds;
@ -11406,18 +11416,20 @@ void skinned_draw_sprite(float scale, atlas_t *a, atlas_slice_frame_t *f, vec4 r
}
static
void skinned_draw_rect(void* userdata, const char *skin, vec4 r) {
void skinned_draw_rect(void* userdata, const char *skin, const char *fallback, vec4 r) {
skinned_t *a = C_CAST(skinned_t*, userdata);
atlas_slice_frame_t *f = skinned_getsliceframe(&a->atlas, skin);
if (!f && fallback) f = skinned_getsliceframe(&a->atlas, fallback);
if (!f) skinned_draw_missing_rect(r);
else skinned_draw_sprite(a->scale, &a->atlas, f, r);
}
void skinned_getskinsize(void *userdata, const char *skin, vec2 *size) {
void skinned_getskinsize(void *userdata, const char *skin, const char *fallback, vec2 *size) {
skinned_t *a = C_CAST(skinned_t*, userdata);
atlas_slice_frame_t *f = skinned_getsliceframe(&a->atlas, skin);
if (!f && fallback) f = skinned_getsliceframe(&a->atlas, fallback);
if (f) {
size->x = (f->bounds.z-f->bounds.x)*a->scale;
size->y = (f->bounds.w-f->bounds.y)*a->scale;
@ -11425,9 +11437,10 @@ void skinned_getskinsize(void *userdata, const char *skin, vec2 *size) {
}
static
void skinned_getscissorrect(void* userdata, const char *skin, vec4 rect, vec4 *dims) {
void skinned_getscissorrect(void* userdata, const char *skin, const char *fallback, vec4 rect, vec4 *dims) {
skinned_t *a = C_CAST(skinned_t*, userdata);
atlas_slice_frame_t *f = skinned_getsliceframe(&a->atlas, skin);
if (!f && fallback) f = skinned_getsliceframe(&a->atlas, fallback);
if (!f) return;
*dims = rect;

View File

@ -3638,6 +3638,13 @@ typedef struct anims_t {
API anims_t animations(const char *pathfile, int flags);
// -----------------------------------------------------------------------------
// lightmapping utils
typedef struct lightmap_t {
struct lm_context *ctx; // private
} lightmap_t;
// -----------------------------------------------------------------------------
// skyboxes
@ -4184,18 +4191,19 @@ API void sprite_setanim(sprite_t *s, unsigned name);
// game ui
typedef struct guiskin_t {
void (*drawrect)(void* userdata, const char *skin, vec4 rect);
void (*getskinsize)(void* userdata, const char *skin, vec2 *size);
void (*getscissorrect)(void* userdata, const char *skin, vec4 rect, vec4 *dims);
bool (*ismouseinrect)(void* userdata, const char *skin, vec4 rect);
void (*drawrect)(void* userdata, const char *skin, const char *fallback, vec4 rect);
void (*getskinsize)(void* userdata, const char *skin, const char *fallback, vec2 *size);
void (*getscissorrect)(void* userdata, const char *skin, const char *fallback, vec4 rect, vec4 *dims);
bool (*ismouseinrect)(void* userdata, const char *skin, const char *fallback, vec4 rect);
void (*free)(void* userdata);
void *userdata;
} guiskin_t;
API void gui_pushskin(guiskin_t skin);
API void* gui_userdata();
API vec2 gui_getskinsize(const char *skin);
API bool gui_ismouseinrect(const char *skin, vec4 rect);
API vec2 gui_getskinsize(const char *skin, const char *fallback);
API bool gui_ismouseinrect(const char *skin, const char *fallback, vec4 rect);
API vec4 gui_getscissorrect(const char *skin, const char *fallback, vec4 rect);
// --
API void gui_panel_id(int id, vec4 rect, const char *skin);
API void gui_rect_id(int id, vec4 rect, const char *skin);

34
tools/linswap.c 100644
View File

@ -0,0 +1,34 @@
#include "v4k.c"
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "usage: %s [file]\n", argv[0]);
fprintf(stderr, "file: %s\n", "source file to process");
return 1;
}
char *buf = file_read(argv[1]);
if (!buf) {
fprintf(stderr, "error: %s\n", "file does not exist!");
return 2;
}
file_delete(argv[1]);
// determine swap mode
char mode = strstri(buf, "//@#line 1 \"") == NULL;
char **lines = strsplit(buf, "\n");
for (int i = 0; i < array_count(lines); i++) {
char *line = STRDUP(lines[i]);
if (!mode) {
strrepl(&line, "//@#line 1 \"", "#line 1 \"");
} else {
strrepl(&line, "#line 1 \"", "//@#line 1 \"");
}
// printf("%s\n", line);
file_append(argv[1], line, strlen(line));
}
return 0;
}

BIN
tools/linswap.exe 100644

Binary file not shown.

View File

@ -3,8 +3,8 @@
[
{
"path": ".",
"file_exclude_patterns": ["*.exe.manifest", "*.zip", "*.ilk", "*.exp", "_mirror/", "engine/v4k", "engine/joint/", "engine/split/"],
"index_exclude_patterns": ["engine/joint/v4k.h", "engine/split/**", "_mirror/**"]
"file_exclude_patterns": ["*.exe.manifest", "*.zip", "*.ilk", "*.exp", "_mirror/", "engine/v4k", "engine/joint/", "engine/split/v4k_*"],
"index_exclude_patterns": ["engine/joint/v4k.h", "engine/split/v4k_**", "_mirror/**"]
}
],
"settings": {