This commit is contained in:
John Alanbrook 2024-04-28 13:33:37 -05:00
parent 0052a89c41
commit 71fda604ee
14 changed files with 197 additions and 128 deletions

View file

@ -66,7 +66,7 @@ else ifeq ($(OPT), 1)
CPPFLAGS += -O3 -flto
INFO :=$(INFO)_opt
else
CPPFLAGS += -O0
CPPFLAGS += -O2
endif
CPPFLAGS += -DHAVE_CEIL -DCP_USE_CGTYPES=0 -DCP_USE_DOUBLES=0 -DHAVE_FLOOR -DHAVE_FMOD -DHAVE_LRINT -DHAVE_LRINTF $(includeflag) -MD $(WARNING_FLAGS) -I. -DVER=\"$(SEM)\" -DCOM=\"$(COM)\" -DINFO=\"$(INFO)\" #-DENABLE_SINC_MEDIUM_CONVERTER -DENABLE_SINC_FAST_CONVERTER -DCP_COLLISION_TYPE_TYPE=uintptr_t -DCP_BITMASK_TYPE=uintptr_t

View file

@ -476,9 +476,54 @@ Cmdline.register_cmd("l", function(n) {
console.level = n;
}, "Set log level.");
function convertYAMLtoJSON(yamlString) {
const lines = yamlString.split('\n');
const jsonObj = {};
let currentKey = '';
let currentValue = '';
let currentDepth = 0;
for (let i = 0; i < lines.length; i++) {
const line = lines[i].trim();
if (!line || line.startsWith('#')) {
continue;
}
const depth = (line.match(/^\s+/g) || [''])[0].length;
const keyValue = line.split(':');
const key = keyValue[0].trim();
const value = keyValue[1].trim();
if (depth > currentDepth) {
jsonObj[currentKey] = convertYAMLtoJSON(currentValue);
currentKey = key;
currentValue = value;
} else if (depth === currentDepth) {
jsonObj[currentKey] = convertYAMLtoJSON(currentValue);
currentKey = key;
currentValue = value;
} else {
jsonObj[currentKey] = convertYAMLtoJSON(currentValue);
currentKey = '';
currentValue = '';
i--; // To reprocess the current line with updated values
}
currentDepth = depth;
}
if (currentKey) {
jsonObj[currentKey] = convertYAMLtoJSON(currentValue);
}
return jsonObj;
}
return {
Resources,
Cmdline,
cmd_args
cmd_args,
convertYAMLtoJSON
};

View file

@ -26,12 +26,18 @@
#include "sokol/sokol_gfx.h"
#define POS 0
#define UV 1
#define NORM 2
#define WEIGHT 3
#define JOINT 4
static void processnode();
static void processmesh();
static void processtexture();
static sg_shader model_shader;
static sg_pipeline model_pipe;
static sg_pipeline model_st_pipe;
struct bone_weights {
char b1;
char b2;
@ -46,23 +52,27 @@ struct joints {
char j4;
};
void model_init() {
model_shader = sg_make_shader(unlit_shader_desc(sg_query_backend()));
static cgltf_data *cdata;
static char *cpath;
struct joints joint_nul = { 0, 0, 0, 0 };
struct bone_weights weight_nul = {0, 0, 0, 0};
void model_init() {
model_pipe = sg_make_pipeline(&(sg_pipeline_desc){
.shader = model_shader,
.shader = sg_make_shader(unlit_shader_desc(sg_query_backend())),
.layout = {
.attrs = {
[0].format = SG_VERTEXFORMAT_FLOAT3,
[1].format = SG_VERTEXFORMAT_USHORT2N,
[1].buffer_index = 1,
[2].format = SG_VERTEXFORMAT_UINT10_N2,
[2].buffer_index = 2,
[3] = {
[POS].format = SG_VERTEXFORMAT_FLOAT3,
[UV].format = SG_VERTEXFORMAT_USHORT2N,
[UV].buffer_index = 1,
[NORM].format = SG_VERTEXFORMAT_UINT10_N2,
[NORM].buffer_index = 2,
[WEIGHT] = {
.format = SG_VERTEXFORMAT_UBYTE4N,
.buffer_index = 3
},
[4] = {
[JOINT] = {
.format = SG_VERTEXFORMAT_UBYTE4,
.buffer_index = 4
}
@ -73,6 +83,28 @@ void model_init() {
.depth.write_enabled = true,
.depth.compare = SG_COMPAREFUNC_LESS_EQUAL
});
model_st_pipe = sg_make_pipeline(&(sg_pipeline_desc){
.shader = sg_make_shader(unlit_st_shader_desc(sg_query_backend())),
.layout = {
.attrs = {
[ATTR_vs_st_a_pos].format = SG_VERTEXFORMAT_FLOAT3,
[ATTR_vs_st_a_tex_coords] = {
.format = SG_VERTEXFORMAT_USHORT2N,
.buffer_index = 1
},
[ATTR_vs_st_a_norm] = {
.format = SG_VERTEXFORMAT_UINT10_N2,
.buffer_index = 2
}
},
},
.index_type = SG_INDEXTYPE_UINT16,
.cull_mode = SG_CULLMODE_FRONT,
.depth.write_enabled = true,
.depth.compare = SG_COMPAREFUNC_LESS_EQUAL
});
}
cgltf_attribute *get_attr_type(cgltf_primitive *p, cgltf_attribute_type t)
@ -109,17 +141,21 @@ void mesh_add_material(primitive *prim, cgltf_material *mat)
{
if (!mat) return;
if (mat->has_pbr_metallic_roughness) {
if (mat->has_pbr_metallic_roughness && mat->pbr_metallic_roughness.base_color_texture.texture) {
cgltf_image *img = mat->pbr_metallic_roughness.base_color_texture.texture->image;
if (img->buffer_view) {
cgltf_buffer_view *buf = img->buffer_view;
prim->bind.fs.images[0] = texture_fromdata(buf->buffer->data, buf->size)->id;
} else
prim->bind.fs.images[0] = texture_from_file(img->uri)->id;
if (img->buffer_view) {
cgltf_buffer_view *buf = img->buffer_view;
prim->bind.fs.images[0] = texture_fromdata(buf->buffer->data, buf->size)->id;
} else {
char *path = makepath(dirname(cpath), img->uri);
prim->bind.fs.images[0] = texture_from_file(path)->id;
free(path);
}
} else
prim->bind.fs.images[0] = texture_from_file("icons/moon.gif")->id;
prim->bind.fs.samplers[0] = std_sampler;
// TODO: Cache and reuse samplers
prim->bind.fs.samplers[0] = tex_sampler;
}
sg_buffer texcoord_floats(float *f, int verts, int comp)
@ -211,7 +247,6 @@ struct primitive mesh_add_primitive(cgltf_primitive *prim)
printf("adding material\n");
mesh_add_material(&retp, prim->material);
int has_norm = 0;
for (int k = 0; k < prim->attributes_count; k++) {
cgltf_attribute attribute = prim->attributes[k];
@ -232,7 +267,6 @@ struct primitive mesh_add_primitive(cgltf_primitive *prim)
break;
case cgltf_attribute_type_normal:
has_norm = 1;
retp.bind.vertex_buffers[2] = normal_floats(vs, verts, comp);
break;
@ -263,8 +297,25 @@ struct primitive mesh_add_primitive(cgltf_primitive *prim)
break;
}
}
/*
if (!retp.bind.vertex_buffers[JOINT].id) {
struct joints jnts[retp.idx_count];
for (int i = 0; i < retp.idx_count; i++)
jnts[i] = joint_nul;
retp.bind.vertex_buffers[JOINT] = sg_make_buffer(&(sg_buffer_desc){ .data = SG_RANGE(jnts)});
}
if (!retp.bind.vertex_buffers[WEIGHT].id) {
struct bone_weights v[retp.idx_count];
for (int i = 0; i < retp.idx_count; i++)
v[i] = weight_nul;
retp.bind.vertex_buffers[WEIGHT] = sg_make_buffer(&(sg_buffer_desc){ .data = SG_RANGE(v)});
}
*/
if (!has_norm) {
if (retp.bind.vertex_buffers[NORM].id) {
YughInfo("Making normals.");
cgltf_attribute *pa = get_attr_type(prim, cgltf_attribute_type_position);
int n = cgltf_accessor_unpack_floats(pa->data, NULL,0);
@ -291,7 +342,7 @@ struct primitive mesh_add_primitive(cgltf_primitive *prim)
return retp;
}
static cgltf_data *cdata;
void model_add_cgltf_mesh(mesh *m, cgltf_mesh *gltf_mesh)
{
@ -382,7 +433,7 @@ void model_add_cgltf_skin(model *model, cgltf_skin *skin)
sk.root = model->nodes+(skin->skeleton-cdata->nodes);
for (int i = 0; i < 50; i++)
sk.binds[i] = HMM_M4D(1);
sk.binds[i] = MAT1;
for (int i = 0; i < skin->joints_count; i++) {
int offset = skin->joints[i]-cdata->nodes;
@ -417,6 +468,7 @@ void model_process_node(model *model, cgltf_node *node)
struct model *model_make(const char *path)
{
YughInfo("Making the model from %s.", path);
cpath = path;
cgltf_options options = {0};
cgltf_data *data = NULL;
cgltf_result result = cgltf_parse_file(&options, path, &data);
@ -460,31 +512,34 @@ void model_free(model *m)
void model_draw_go(model *model, gameobject *go, gameobject *cam)
{
animation_run(&model->anim, apptime());
skin *sk = &model->skin;
for (int i = 0; i < arrlen(sk->joints); i++) {
md5joint *md = sk->joints[i];
HMM_Mat4 local = HMM_M4TRS(md->pos.xyz, md->rot, md->scale.xyz);
if (md->parent)
local = HMM_MulM4(md->parent->t, local);
md->t = local;
sk->binds[i] = HMM_MulM4(md->t, sk->invbind[i]);
//printf("TRANSLATION OF %d IS " HMMFMT_VEC3 "\n", i, HMMPRINT_VEC3(md->pos));
}
HMM_Mat4 view = t3d_go2world(cam);
HMM_Mat4 proj = HMM_Perspective_RH_NO(20, 1, 0.01, 10000);
HMM_Mat4 vp = HMM_MulM4(proj, view);
HMM_Mat4 gom = transform3d2mat(go2t3(go));
animation_run(&model->anim, apptime());
skin *sk = &model->skin;
if (arrlen(sk->joints) == 0) {
sg_apply_pipeline(model_st_pipe);
} else {
sg_apply_pipeline(model_pipe);
for (int i = 0; i < arrlen(sk->joints); i++) {
md5joint *md = sk->joints[i];
HMM_Mat4 local = HMM_M4TRS(md->pos.xyz, md->rot, md->scale.xyz);
if (md->parent)
local = HMM_MulM4(md->parent->t, local);
md->t = local;
sk->binds[i] = HMM_MulM4(md->t, sk->invbind[i]);
}
sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_skinv, &(sg_range){
.ptr = sk->binds,
.size = sizeof(*sk->binds)*50
});
}
sg_apply_pipeline(model_pipe);
sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_vs_p, SG_RANGE_REF(vp.e));
sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_skinv, &(sg_range){
.ptr = sk->binds,
.size = sizeof(*sk->binds)*50
});
float ambient[4] = {1.0,1.0,1.0,1.0};
sg_apply_uniforms(SG_SHADERSTAGE_FS, SLOT_lightf, SG_RANGE_REF(ambient));
for (int i = 0; i < arrlen(model->meshes); i++) {

View file

@ -421,6 +421,8 @@ static const HMM_Vec3 vBKWD = {0,0,-1};
static const HMM_Vec3 vLEFT = {-1,0,0};
static const HMM_Vec3 vRIGHT = {1,0,0};
static const HMM_Mat4 MAT1 = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
/*
* Angle unit conversion functions
*/

View file

@ -624,7 +624,6 @@ JSC_CCALL(render_clear_color,
)
JSC_CCALL(render_set_sprite_tex, sprite_tex(js2texture(argv[0])))
JSC_CCALL(render_sprite_flush, sprite_flush())
static const JSCFunctionListEntry js_render_funcs[] = {
MIST_FUNC_DEF(render, grid, 3),
@ -641,7 +640,6 @@ static const JSCFunctionListEntry js_render_funcs[] = {
MIST_FUNC_DEF(render, hud_res, 1),
MIST_FUNC_DEF(render, clear_color, 1),
MIST_FUNC_DEF(render, set_sprite_tex, 1),
MIST_FUNC_DEF(render, sprite_flush, 0),
};
JSC_CCALL(gui_flush, text_flush(&useproj));

View file

@ -33,6 +33,7 @@ float camzoom = 1;
sg_buffer sprite_quad;
sg_sampler std_sampler;
sg_sampler tex_sampler;
static struct {
sg_swapchain swap;
@ -242,6 +243,13 @@ void render_init() {
});
std_sampler = sg_make_sampler(&(sg_sampler_desc){});
tex_sampler = sg_make_sampler(&(sg_sampler_desc){
.min_filter = SG_FILTER_LINEAR,
.mag_filter = SG_FILTER_LINEAR,
.mipmap_filter = SG_FILTER_LINEAR,
.wrap_u = SG_WRAP_REPEAT,
.wrap_v = SG_WRAP_REPEAT
});
#ifndef NDEBUG
sg_trace_hooks hh = sg_install_trace_hooks(&hooks);

View file

@ -34,6 +34,7 @@ extern sg_pass_action pass_action;
extern sg_buffer sprite_quad;
extern sg_sampler std_sampler;
extern sg_sampler tex_sampler;
struct draw_p {
float x;

View file

@ -126,6 +126,17 @@ char *dirname(const char *path)
return dir;
}
char *makepath(char *dir, char *file)
{
int d = strlen(dir) + strlen(file) + 2;
char *path = malloc(d);
path[0] = 0;
strncat(path, dir, d);
strncat(path, "/", d);
strncat(path, file, d);
return path;
}
char *seprint(char *fmt, ...)
{
va_list args;

View file

@ -11,7 +11,8 @@ extern int LOADED_GAME;
void resources_init();
char *get_filename_from_path(char *path, int extension);
char *get_directory_from_path(char *path);
char *dirname(const char *path);
char *makepath(char *dir, char *file);
char *str_replace_ext(const char *s, const char *newext);
FILE *res_open(char *path, const char *tag);
char **ls(const char *path);
@ -22,8 +23,6 @@ void pack_start(const char *name);
void pack_add(const char *path);
void pack_end();
char *dirname(const char *path);
void *slurp_file(const char *filename, size_t *size);
char *slurp_text(const char *filename, size_t *size);
int slurp_write(const char *txt, const char *filename, size_t len);

View file

@ -44,31 +44,6 @@ void sprite_free(sprite *sprite) { free(sprite); }
static texture *loadedtex;
static int sprite_count = 0;
void sprite_flush() {
return;
if (!loadedtex) return;
/*
int flushed = arrlen(spverts)/4;
sg_apply_bindings(&bind_sprite);
sg_range data = (sg_range){
.ptr = spverts,
.size = sizeof(sprite_vert)*arrlen(spverts)
};
if (sg_query_buffer_will_overflow(bind_sprite.vertex_buffers[0], data.size))
bind_sprite.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
.size = data.size,
.type = SG_BUFFERTYPE_VERTEXBUFFER,
.usage = SG_USAGE_STREAM,
.label = "sprite vertex buffer"
});
sg_update_buffer(bind_sprite.vertex_buffers[0], &data);
sg_draw(sprite_count * 4, 4, flushed);
sprite_count += flushed;
*/
}
void sprite_initialize() {
shader_sprite = sg_make_shader(sprite_shader_desc(sg_query_backend()));
@ -112,41 +87,6 @@ void sprite_pipe()
sg_apply_bindings(&bind_sprite);
}
void tex_draw(HMM_Mat3 m, struct rect r, struct rgba color, int wrap, HMM_Vec2 wrapoffset, HMM_Vec2 wrapscale, struct rgba emissive) {
/*
struct sprite_vert verts[4];
float w = loadedtex->width*r.w;
float h = loadedtex->height*r.h;
HMM_Vec2 sposes[4] = {
{0,0},
{w,0},
{0,h},
{w,h}
};
for (int i = 0; i < 4; i++)
verts[i].pos = mat_t_pos(m, sposes[i]);
if (wrap) {
r.w *= wrapscale.x;
r.h *= wrapscale.y;
}
verts[0].uv.X = r.x;
verts[0].uv.Y = r.y+r.h;
verts[1].uv.X = r.x+r.w;
verts[1].uv.Y = r.y+r.h;
verts[2].uv.X = r.x;
verts[2].uv.Y = r.y;
verts[3].uv.X = r.x+r.w;
verts[3].uv.Y = r.y;
for (int i = 0; i < 4; i++)
arrput(spverts, verts[i]);
*/
}
transform2d sprite2t(sprite *s)
{
return (transform2d){
@ -179,7 +119,7 @@ void gui_draw_img(texture *tex, transform2d t, int wrap, HMM_Vec2 wrapoffset, fl
sg_apply_pipeline(pip_sprite);
sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_vp, SG_RANGE_REF(useproj));
sprite_tex(tex);
tex_draw(transform2d2mat(t), ST_UNIT, color, wrap, wrapoffset, (HMM_Vec2){wrapscale,wrapscale}, (struct rgba){0,0,0,0});
//tex_draw(transform2d2mat(t), ST_UNIT, color, wrap, wrapoffset, (HMM_Vec2){wrapscale,wrapscale}, (struct rgba){0,0,0,0});
}
void slice9_draw(texture *tex, transform2d *t, HMM_Vec4 border, struct rgba color)

View file

@ -36,7 +36,6 @@ void sprite_initialize();
void sprite_draw(struct sprite *sprite, gameobject *go);
void sprite_pipe();
void sprite_draw_all();
void sprite_flush();
void gui_draw_img(texture *tex, transform2d t, int wrap, HMM_Vec2 wrapoffset, float wrapscale, struct rgba color);

View file

@ -122,11 +122,9 @@ struct texture *texture_from_file(const char *path) {
unsigned int nw = next_pow2(tex->width);
unsigned int nh = next_pow2(tex->height);
int filter = SG_FILTER_NEAREST;
sg_image_data sg_img_data;
sg_img_data.subimage[0][0] = (sg_range){.ptr = data, .size=tex->width*tex->height*4};
/*
int mips = mip_levels(tex->width, tex->height)+1;
YughInfo("Has %d mip levels, from wxh %dx%d, pow2 is %ux%u.", mips, tex->width, tex->height,nw,nh);
@ -151,18 +149,18 @@ struct texture *texture_from_file(const char *path) {
mipw = w;
miph = h;
}
*/
tex->id = sg_make_image(&(sg_image_desc){
.type = SG_IMAGETYPE_2D,
.width = tex->width,
.height = tex->height,
.usage = SG_USAGE_IMMUTABLE,
//.num_mipmaps = mips,
.num_mipmaps = mips,
.data = sg_img_data
});
/*for (int i = 1; i < mips; i++)
free(mipdata[i]);*/
for (int i = 1; i < mips; i++)
free(mipdata[i]);
return tex;
}
@ -191,8 +189,6 @@ struct texture *texture_fromdata(void *raw, long size)
tex->data = data;
int filter = SG_FILTER_NEAREST;
sg_image_data sg_img_data;
int mips = mip_levels(tex->width, tex->height)+1;

View file

@ -25,7 +25,6 @@ uniform sprite {
void main()
{
texcoords = vertex;
texcoords.y = 1 - texcoords.y;
gl_Position = proj * model * vec4(vertex, 0, 1.0);
fcolor = vcolor;
femissive = vemissive;

View file

@ -1,30 +1,45 @@
@vs vs
@block vptr
in vec3 a_pos;
in vec2 a_tex_coords;
in vec4 a_norm;
in vec4 a_weight;
in vec4 a_joint;
out vec2 tex_coords;
out vec3 normal;
uniform vs_p { uniform mat4 vp; };
uniform vmodel { uniform mat4 model; };
@end
@vs vs
@include_block vptr
in vec4 a_weight;
in vec4 a_joint;
uniform skinv { uniform mat4 bones[50]; };
void main() {
mat4 tt = vp;
mat4 mm = model;
mat4 skin = bones[int(a_joint.x)] * a_weight.x;
skin += bones[int(a_joint.y)] * a_weight.y;
skin += bones[int(a_joint.z)] * a_weight.z;
skin += bones[int(a_joint.w)] * a_weight.w;
mat4 skinm = model * skin;
gl_Position = vp * skinm * vec4(a_pos,1.0);
mat4 skinm = mm * skin;
gl_Position = tt * skinm * vec4(a_pos,1.0);
tex_coords = a_tex_coords;
normal = (skinm * vec4(a_norm.xyz*2-1,0)).xyz;
}
@end
@vs vs_st
@include_block vptr
void main() {
gl_Position = vp * model * vec4(a_pos,1.0);
tex_coords = a_tex_coords;
normal = (model * vec4(a_norm.xyz*2-1,0)).xyz;
}
@end
@fs fs
in vec2 tex_coords;
in vec3 normal;
@ -45,3 +60,4 @@ void main() {
@end
@program unlit vs fs
@program unlit_st vs_st fs