prosperon/source/engine/3d/model.c

396 lines
10 KiB
C
Raw Normal View History

2021-11-30 21:29:18 -06:00
#include "model.h"
#include "log.h"
2021-11-30 21:29:18 -06:00
#include "resources.h"
#include "stb_ds.h"
2023-05-12 13:22:05 -05:00
#include "font.h"
2023-11-03 08:31:06 -05:00
#include "gameobject.h"
2023-05-12 13:22:05 -05:00
2023-11-03 08:31:06 -05:00
//#include "diffuse.sglsl.h"
#include "unlit.sglsl.h"
#include "render.h"
2023-05-12 13:22:05 -05:00
#include "HandmadeMath.h"
#include "math.h"
#include "time.h"
#define CGLTF_IMPLEMENTATION
2021-11-30 21:29:18 -06:00
#include <cgltf.h>
2023-12-20 17:20:29 -06:00
2022-02-06 10:14:57 -06:00
#include <stdlib.h>
#include <string.h>
2021-11-30 21:29:18 -06:00
2023-05-12 13:22:05 -05:00
#include "texture.h"
#include "sokol/sokol_gfx.h"
2021-11-30 21:29:18 -06:00
static void processnode();
static void processmesh();
static void processtexture();
2023-05-12 13:22:05 -05:00
static sg_shader model_shader;
static sg_pipeline model_pipe;
2023-11-29 07:32:32 -06:00
struct bone_weights {
char b1;
char b2;
char b3;
char b4;
};
struct mesh_v {
HMM_Vec3 pos;
struct uv_n uv;
uint32_t norm;
struct bone_weights bones;
};
2023-05-12 13:22:05 -05:00
void model_init() {
2023-11-03 08:31:06 -05:00
model_shader = sg_make_shader(unlit_shader_desc(sg_query_backend()));
model_pipe = sg_make_pipeline(&(sg_pipeline_desc){
.shader = model_shader,
.layout = {
.attrs = {
[0].format = SG_VERTEXFORMAT_FLOAT3,
2024-04-20 12:55:20 -05:00
[1].format = SG_VERTEXFORMAT_USHORT2N,
[1].buffer_index = 1,
2024-04-23 15:58:08 -05:00
[2].format = SG_VERTEXFORMAT_FLOAT3,
[2].buffer_index = 2
2023-11-03 08:31:06 -05:00
},
},
.index_type = SG_INDEXTYPE_UINT16,
.cull_mode = SG_CULLMODE_FRONT,
.depth.write_enabled = true,
.depth.compare = SG_COMPAREFUNC_LESS_EQUAL
});
2023-05-12 13:22:05 -05:00
}
2023-12-04 13:38:37 -06:00
cgltf_attribute *get_attr_type(cgltf_primitive *p, cgltf_attribute_type t)
2023-05-12 13:22:05 -05:00
{
2023-12-04 13:38:37 -06:00
for (int i = 0; i < p->attributes_count; i++) {
if (p->attributes[i].type == t)
return &p->attributes[i];
2023-05-12 13:22:05 -05:00
}
return NULL;
}
2023-12-19 15:34:36 -06:00
unsigned short pack_short_texcoord(float x, float y)
2023-05-19 09:55:57 -05:00
{
2023-12-19 15:34:36 -06:00
unsigned short s;
char xc = x*255;
char yc = y*255;
return (((unsigned short)yc) << 8) | xc;
2023-05-19 09:55:57 -05:00
}
2023-12-20 17:20:29 -06:00
unsigned short pack_short_tex(float c) { return c * USHRT_MAX; }
2023-05-19 09:55:57 -05:00
uint32_t pack_int10_n2(float *norm)
{
2024-04-23 18:12:45 -05:00
/*float x = norm[0];
float y = norm[1];
float z = norm[2];
const uint32_t xs = x < 0;
const uint32_t ys = y < 0;
const uint32_t zs = z < 0;
uint32_t vi =
zs << 29 | ((uint32_t)(z * 511 + (zs << 9)) & 511) << 20 |
ys << 19 | ((uint32_t)(y * 511 + (ys << 9)) & 511) << 10 |
xs << 9 | ((uint32_t)(x * 511 + (xs << 9)) & 511);
return vi;
int16_t ni[3];
printf("accessing norm %g,%g,%g\n", norm[0], norm[1], norm[2]);
for (int i = 0; i < 3; i++)
ni[i] = (int16_t)(norm[i]*512.0f);
uint32_t combined = (((uint32_t)ni[2]) << 20) | (((uint32_t)ni[1]) << 10) | ((uint32_t)ni[0]);
return combined;
uint32_t ni[3];
for (int i = 0; i < 3; i++) {
2023-05-19 09:55:57 -05:00
ni[i] = fabs(norm[i]) * 511.0 + 0.5;
ni[i] = (ni[i] > 511) ? 511 : ni[i];
ni[i] = ( norm[i] < 0.0 ) ? -ni[i] : ni[i];
}
2024-04-23 18:12:45 -05:00
return (ni[0] | ( (ni[1]) << 10) | ( (ni[2] << 20) | ( (0 & 0x3) << 30)));*/
// Pack the floats into a 32-bit unsigned integer
uint32_t packedValue = 0;
packedValue |= (uint32_t)((int32_t)(norm[0] * 0x1ff) & 0x3ff) << 20;
packedValue |= (uint32_t)((int32_t)(norm[1] * 0x1ff) & 0x3ff) << 10;
packedValue |= (uint32_t)((int32_t)(norm[2] * 0x1ff) & 0x3ff);
//packedValue |= (uint32_t)((int32_t)(0 * 0x1ff) & 0x3ff) >> 8;
return packedValue;
2023-05-19 09:55:57 -05:00
}
2023-12-04 13:38:37 -06:00
void mesh_add_material(mesh *mesh, cgltf_material *mat)
{
if (!mat) return;
if (mat && mat->has_pbr_metallic_roughness) {
cgltf_image *img = mat->pbr_metallic_roughness.base_color_texture.texture->image;
if (img->buffer_view) {
cgltf_buffer_view *buf = img->buffer_view;
mesh->bind.fs.images[0] = texture_fromdata(buf->buffer->data, buf->size)->id;
2024-04-20 12:55:20 -05:00
} else
mesh->bind.fs.images[0] = texture_from_file(img->uri)->id;
2023-12-04 13:38:37 -06:00
} else
2024-04-20 12:55:20 -05:00
mesh->bind.fs.images[0] = texture_from_file("icons/moon.gif")->id;
2024-04-23 15:58:08 -05:00
mesh->bind.fs.samplers[0] = std_sampler;
2023-12-19 15:34:36 -06:00
}
sg_buffer texcoord_floats(float *f, int verts, int comp)
{
2023-12-20 17:20:29 -06:00
int n = verts*comp;
unsigned short packed[n];
2024-04-23 18:12:45 -05:00
for (int i = 0; i < n; i++)
2023-12-20 17:20:29 -06:00
packed[i] = pack_short_tex(f[i]);
2023-12-19 15:34:36 -06:00
return sg_make_buffer(&(sg_buffer_desc){
2024-04-23 18:12:45 -05:00
.data = SG_RANGE(packed),
2024-04-09 16:48:15 -05:00
.label = "tex coord vert buffer",
});
2023-12-19 15:34:36 -06:00
}
sg_buffer normal_floats(float *f, int verts, int comp)
{
2024-04-23 18:12:45 -05:00
return sg_make_buffer(&(sg_buffer_desc){
.data.ptr = f,
.data.size = sizeof(*f)*verts*comp
});
2023-12-19 15:34:36 -06:00
uint32_t packed_norms[verts];
for (int v = 0, i = 0; v < verts; v++, i+= comp)
2023-12-19 17:28:45 -06:00
packed_norms[v] = pack_int10_n2(f+i);
2023-12-19 15:34:36 -06:00
return sg_make_buffer(&(sg_buffer_desc){
2024-04-23 18:12:45 -05:00
.data = SG_RANGE(packed_norms),
2024-04-09 16:48:15 -05:00
.label = "normal vert buffer",
});
2023-12-19 15:34:36 -06:00
}
HMM_Vec3 index_to_vert(uint32_t idx, float *f)
{
return (HMM_Vec3){f[idx*3], f[idx*3+1], f[idx*3+2]};
2023-12-04 13:38:37 -06:00
}
void mesh_add_primitive(mesh *mesh, cgltf_primitive *prim)
{
uint16_t *idxs;
if (prim->indices) {
int c = prim->indices->count;
idxs = malloc(sizeof(*idxs)*c);
memcpy(idxs, cgltf_buffer_view_data(prim->indices->buffer_view), sizeof(uint16_t) * c);
mesh->bind.index_buffer = sg_make_buffer(&(sg_buffer_desc){
2024-04-09 16:48:15 -05:00
.data.ptr = idxs,
.data.size = sizeof(uint16_t) * c,
.type = SG_BUFFERTYPE_INDEXBUFFER,
.label = "mesh index buffer",
});
2023-12-04 13:38:37 -06:00
2023-12-19 15:34:36 -06:00
mesh->idx_count = c;
2023-12-04 13:38:37 -06:00
} else {
YughWarn("Model does not have indices. Generating them.");
int c = prim->attributes[0].data->count;
2023-12-19 15:34:36 -06:00
mesh->idx_count = c;
2023-12-04 13:38:37 -06:00
idxs = malloc(sizeof(*idxs)*c);
for (int z = 0; z < c; z++)
idxs[z] = z;
mesh->bind.index_buffer = sg_make_buffer(&(sg_buffer_desc){
.data.ptr = idxs,
.data.size = sizeof(uint16_t) * c,
.type = SG_BUFFERTYPE_INDEXBUFFER});
}
free(idxs);
2024-04-23 15:58:08 -05:00
printf("adding material\n");
2023-12-04 13:38:37 -06:00
mesh_add_material(mesh, prim->material);
int has_norm = 0;
for (int k = 0; k < prim->attributes_count; k++) {
cgltf_attribute attribute = prim->attributes[k];
2023-12-19 15:34:36 -06:00
int n = cgltf_accessor_unpack_floats(attribute.data, NULL, 0); /* floats per vertex x num elements. In other words, total floats pulled */
int comp = cgltf_num_components(attribute.data->type);
int verts = n/comp;
float vs[n];
2023-12-04 13:38:37 -06:00
cgltf_accessor_unpack_floats(attribute.data, vs, n);
switch (attribute.type) {
case cgltf_attribute_type_position:
mesh->bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
2024-04-09 16:48:15 -05:00
.data.ptr = vs,
.data.size = sizeof(float) * n,
.label = "mesh vert buffer"
});
2023-12-04 13:38:37 -06:00
break;
case cgltf_attribute_type_normal:
2024-04-23 15:58:08 -05:00
has_norm = 1;
2024-04-23 18:12:45 -05:00
YughInfo("Found normals.");
2024-04-23 15:58:08 -05:00
mesh->bind.vertex_buffers[2] = normal_floats(vs, verts, comp);
2023-12-04 13:38:37 -06:00
break;
case cgltf_attribute_type_tangent:
break;
case cgltf_attribute_type_color:
break;
case cgltf_attribute_type_weights:
break;
case cgltf_attribute_type_joints:
break;
case cgltf_attribute_type_texcoord:
2024-04-23 18:12:45 -05:00
mesh->bind.vertex_buffers[1] = texcoord_floats(vs, verts, comp); /*sg_make_buffer(&(sg_buffer_desc){
.data.ptr = vs,
.data.size=sizeof(*vs)*verts*comp
});*/
2023-12-04 13:38:37 -06:00
break;
case cgltf_attribute_type_invalid:
YughWarn("Invalid type.");
break;
2024-03-11 22:23:02 -05:00
case cgltf_attribute_type_custom:
break;
case cgltf_attribute_type_max_enum:
break;
2023-12-04 13:38:37 -06:00
}
}
2024-04-23 15:58:08 -05:00
2023-12-04 13:38:37 -06:00
if (!has_norm) {
2024-04-23 18:12:45 -05:00
YughInfo("Making normals.");
2023-12-04 13:38:37 -06:00
cgltf_attribute *pa = get_attr_type(prim, cgltf_attribute_type_position);
int n = cgltf_accessor_unpack_floats(pa->data, NULL,0);
2023-12-19 15:34:36 -06:00
int comp = 3;
int verts = n/comp;
uint32_t face_norms[verts];
2023-12-04 13:38:37 -06:00
float ps[n];
cgltf_accessor_unpack_floats(pa->data,ps,n);
2023-12-19 15:34:36 -06:00
for (int i = 0; i < verts; i+=3) {
HMM_Vec3 a = index_to_vert(i,ps);
HMM_Vec3 b = index_to_vert(i+1,ps);
HMM_Vec3 c = index_to_vert(i+2,ps);
2023-12-04 13:38:37 -06:00
HMM_Vec3 norm = HMM_NormV3(HMM_Cross(HMM_SubV3(b,a), HMM_SubV3(c,a)));
uint32_t packed_norm = pack_int10_n2(norm.Elements);
2023-12-19 15:34:36 -06:00
face_norms[i] = face_norms[i+1] = face_norms[i+2] = packed_norm;
2023-12-04 13:38:37 -06:00
}
2023-12-19 15:34:36 -06:00
2023-12-04 13:38:37 -06:00
mesh->bind.vertex_buffers[2] = sg_make_buffer(&(sg_buffer_desc){
2023-12-19 15:34:36 -06:00
.data.ptr = face_norms,
.data.size = sizeof(uint32_t) * verts});
2024-04-23 15:58:08 -05:00
}
2023-12-04 13:38:37 -06:00
}
void model_add_cgltf_mesh(model *model, cgltf_mesh *gltf_mesh)
{
mesh mesh = {0};
for (int i = 0; i < gltf_mesh->primitives_count; i++)
mesh_add_primitive(&mesh, &gltf_mesh->primitives[i]);
arrput(model->meshes,mesh);
}
void model_add_cgltf_anim(model *model, cgltf_animation *anim)
{
}
void model_add_cgltf_skin(model *model, cgltf_skin *skin)
{
}
void model_process_node(model *model, cgltf_node *node)
{
if (node->has_matrix)
memcpy(model->matrix.Elements, node->matrix, sizeof(float)*16);
if (node->mesh)
model_add_cgltf_mesh(model, node->mesh);
if (node->skin)
model_add_cgltf_skin(model, node->skin);
}
void model_process_scene(model *model, cgltf_scene *scene)
{
for (int i = 0; i < scene->nodes_count; i++)
model_process_node(model, scene->nodes[i]);
}
2024-04-20 12:55:20 -05:00
struct model *model_make(const char *path)
2023-12-04 13:38:37 -06:00
{
2023-11-03 22:01:30 -05:00
YughInfo("Making the model from %s.", path);
cgltf_options options = {0};
cgltf_data *data = NULL;
cgltf_result result = cgltf_parse_file(&options, path, &data);
if (result) {
YughError("CGLTF could not parse file %s, err %d.", path, result);
2023-04-28 12:49:18 -05:00
return NULL;
}
result = cgltf_load_buffers(&options, data, path);
if (result) {
YughError("CGLTF could not load buffers for file %s, err %d.", path, result);
2023-04-28 12:49:18 -05:00
return NULL;
}
2023-05-12 13:22:05 -05:00
struct model *model = calloc(1, sizeof(*model));
2023-12-04 13:38:37 -06:00
if (data->scenes_count == 0 || data->scenes_count > 1) return NULL;
model_process_scene(model, data->scene);
for (int i = 0; i < data->meshes_count; i++)
model_add_cgltf_mesh(model, &data->meshes[i]);
for (int i = 0; i < data->animations_count; i++)
model_add_cgltf_anim(model, &data->animations[i]);
2023-05-12 13:22:05 -05:00
return model;
2021-11-30 21:29:18 -06:00
}
2024-04-20 12:55:20 -05:00
void model_free(model *m)
{
2024-04-20 12:55:20 -05:00
}
2024-04-20 12:55:20 -05:00
void model_draw_go(model *model, gameobject *go, gameobject *cam)
{
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);
2023-11-03 08:31:06 -05:00
vs_p_t vs_p;
2023-12-21 10:49:44 -06:00
memcpy(vs_p.vp, vp.Elements, sizeof(float)*16);
2024-04-20 12:55:20 -05:00
memcpy(vs_p.model, t3d_go2world(go).Elements, sizeof(float)*16);
2023-05-12 13:22:05 -05:00
sg_apply_pipeline(model_pipe);
2023-11-03 08:31:06 -05:00
sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_vs_p, SG_RANGE_REF(vs_p));
2024-04-20 12:55:20 -05:00
2023-05-12 13:22:05 -05:00
for (int i = 0; i < arrlen(model->meshes); i++) {
sg_apply_bindings(&model->meshes[i].bind);
2023-12-19 15:34:36 -06:00
sg_draw(0, model->meshes[i].idx_count, 1);
2023-05-12 13:22:05 -05:00
}
2021-11-30 21:29:18 -06:00
}
2023-05-12 13:22:05 -05:00
2024-02-25 17:31:48 -06:00
void material_free(material *mat)
{
}