clean up 3d model creation
This commit is contained in:
parent
ceccd032c2
commit
57c2285019
|
@ -209,6 +209,8 @@ debug.api.print_doc = function(name)
|
|||
return mdoc;
|
||||
}
|
||||
|
||||
debug.frozen = false;
|
||||
|
||||
return {
|
||||
debug,
|
||||
Gizmos,
|
||||
|
|
|
@ -44,6 +44,8 @@ function set_model(t)
|
|||
render.setunim4(0, cur.shader.vs.unimap.model.slot, t);
|
||||
}
|
||||
|
||||
render.set_model = set_model;
|
||||
|
||||
var shaderlang = {
|
||||
macos: "metal_macos",
|
||||
windows: "hlsl5",
|
||||
|
|
15
scripts/repl.js
Normal file
15
scripts/repl.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
var repl = {};
|
||||
|
||||
var file = "repl.jj";
|
||||
var last = 0;
|
||||
|
||||
repl.hotreload = function() {
|
||||
if (io.mod(file) > last) {
|
||||
say("REPL:::");
|
||||
last = io.mod(file);
|
||||
var script = io.slurp(file);
|
||||
eval(script);
|
||||
}
|
||||
}
|
||||
|
||||
return {repl:repl};
|
|
@ -25,12 +25,11 @@ struct anim_channel {
|
|||
sampler *sampler;
|
||||
};
|
||||
|
||||
struct animation {
|
||||
char *name;
|
||||
typedef struct animation {
|
||||
double time;
|
||||
struct anim_channel *channels;
|
||||
sampler *samplers;
|
||||
};
|
||||
} animation;
|
||||
|
||||
void animation_run(struct animation *anim, float now);
|
||||
HMM_Vec4 sample_sampler(sampler *sampler, float time);
|
||||
|
|
|
@ -48,8 +48,6 @@ static JSValue globalThis;
|
|||
static JSClassID js_ptr_id;
|
||||
static JSClassDef js_ptr_class = { "POINTER" };
|
||||
|
||||
static JSValue JSUNDEF;
|
||||
|
||||
JSValue str2js(const char *c, ...) {
|
||||
if (!c) return JS_UNDEFINED;
|
||||
char *result = NULL;
|
||||
|
@ -95,6 +93,11 @@ void cpConstraint_free(cpConstraint *c)
|
|||
cpConstraintFree(c);
|
||||
}
|
||||
|
||||
void skin_free(skin *sk) {
|
||||
arrfree(sk->invbind);
|
||||
free(sk);
|
||||
}
|
||||
|
||||
void jsfreestr(const char *s) { JS_FreeCString(js, s); }
|
||||
QJSCLASS(gameobject)
|
||||
QJSCLASS(transform)
|
||||
|
@ -109,6 +112,7 @@ QJSCLASS(datastream)
|
|||
QJSCLASS(cpShape)
|
||||
QJSCLASS(cpConstraint)
|
||||
QJSCLASS(timer)
|
||||
QJSCLASS(skin);
|
||||
|
||||
static JSValue js_circle2d;
|
||||
static JSValue js_poly2d;
|
||||
|
@ -205,6 +209,7 @@ uint64_t js2uint64(JSValue v)
|
|||
JSValue angle2js(double g) {
|
||||
return number2js(g*HMM_RadToTurn);
|
||||
}
|
||||
|
||||
double js2angle(JSValue v) {
|
||||
double n = js2number(v);
|
||||
return n * HMM_TurnToRad;
|
||||
|
@ -532,6 +537,7 @@ int js_print_exception(JSValue v)
|
|||
JS_FreeCString(js, msg);
|
||||
JS_FreeCString(js, stack);
|
||||
JS_FreeValue(js,ex);
|
||||
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
|
@ -864,6 +870,45 @@ sg_shader js2shader(JSValue v)
|
|||
return sh;
|
||||
}
|
||||
|
||||
#define MAT_POS 0
|
||||
#define MAT_UV 1
|
||||
#define MAT_NORM 2
|
||||
#define MAT_BONE 3
|
||||
#define MAT_WEIGHT 4
|
||||
#define MAT_COLOR 5
|
||||
#define MAT_TAN 6
|
||||
#define MAT_ANGLE 7
|
||||
#define MAT_WH 8
|
||||
#define MAT_ST 9
|
||||
#define MAT_PPOS 10
|
||||
#define MAT_SCALE 11
|
||||
|
||||
static int mat2type(int mat)
|
||||
{
|
||||
switch(mat) {
|
||||
case MAT_POS:
|
||||
case MAT_NORM:
|
||||
return SG_VERTEXFORMAT_FLOAT3;
|
||||
case MAT_PPOS:
|
||||
case MAT_WH:
|
||||
case MAT_ST:
|
||||
return SG_VERTEXFORMAT_FLOAT2;
|
||||
case MAT_UV:
|
||||
case MAT_TAN:
|
||||
return SG_VERTEXFORMAT_USHORT2N;
|
||||
return SG_VERTEXFORMAT_UINT10_N2;
|
||||
case MAT_BONE:
|
||||
return SG_VERTEXFORMAT_UBYTE4;
|
||||
case MAT_WEIGHT:
|
||||
case MAT_COLOR:
|
||||
return SG_VERTEXFORMAT_UBYTE4N;
|
||||
case MAT_ANGLE:
|
||||
case MAT_SCALE:
|
||||
return SG_VERTEXFORMAT_FLOAT;
|
||||
};
|
||||
return 0;
|
||||
}
|
||||
|
||||
sg_vertex_layout_state js2layout(JSValue v)
|
||||
{
|
||||
sg_vertex_layout_state st = {0};
|
||||
|
@ -1892,6 +1937,7 @@ JSC_CCALL(transform_rotate,
|
|||
transform *t = js2transform(self);
|
||||
HMM_Quat rot = HMM_QFromAxisAngle_LH(axis, js2angle(argv[1]));
|
||||
t->rotation = HMM_MulQ(t->rotation,rot);
|
||||
printf("rotation is now %g,%g,%g,%g\n", t->rotation.e[0], t->rotation.e[1], t->rotation.e[2], t->rotation.e[3]);
|
||||
t->dirty = true;
|
||||
)
|
||||
|
||||
|
@ -2890,42 +2936,34 @@ JSC_CCALL(os_make_transform, return transform2js(make_transform()))
|
|||
|
||||
JSC_SCALL(os_system, return number2js(system(str)); )
|
||||
|
||||
#define PRIMCHECK(VAR, JS, VAL) \
|
||||
if (VAR->VAL.id) js_setpropstr(JS, #VAL, sg_buffer2js(&VAR->VAL)); \
|
||||
JSC_SCALL(os_gltf_buffer,
|
||||
int buffer_idx = js2number(argv[1]);
|
||||
int type = js2number(argv[2]);
|
||||
cgltf_options options = {0};
|
||||
cgltf_data *data = NULL;
|
||||
cgltf_result result = cgltf_parse_file(&options, str, &data);
|
||||
result = cgltf_load_buffers(&options, data, str);
|
||||
|
||||
JSValue primitive2js(primitive *p)
|
||||
{
|
||||
JSValue v = JS_NewObject(js);
|
||||
PRIMCHECK(p, v, pos)
|
||||
PRIMCHECK(p,v,norm)
|
||||
PRIMCHECK(p,v,uv)
|
||||
PRIMCHECK(p,v,bone)
|
||||
PRIMCHECK(p,v,weight)
|
||||
PRIMCHECK(p,v,color)
|
||||
PRIMCHECK(p,v,index)
|
||||
js_setpropstr(v, "count", number2js(p->idx_count));
|
||||
sg_buffer *b = malloc(sizeof(*b));
|
||||
*b = accessor2buffer(&data->accessors[buffer_idx], type);
|
||||
cgltf_free(data);
|
||||
|
||||
return v;
|
||||
ret = sg_buffer2js(b);
|
||||
)
|
||||
|
||||
JSC_SCALL(os_gltf_skin,
|
||||
cgltf_options options = {0};
|
||||
cgltf_data *data = NULL;
|
||||
cgltf_parse_file(&options,str,&data);
|
||||
cgltf_load_buffers(&options,data,str);
|
||||
|
||||
if (data->skins_count <= 0) {
|
||||
ret = (JS_UNDEFINED);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
JSValue material2js(material *m)
|
||||
{
|
||||
JSValue v = JS_NewObject(js);
|
||||
if (m->diffuse)
|
||||
js_setpropstr(v, "diffuse", texture2js(m->diffuse));
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
JSC_SCALL(os_make_model,
|
||||
model *m = model_make(str);
|
||||
if (arrlen(m->meshes) != 1) return JSUNDEF;
|
||||
mesh *me = m->meshes+0;
|
||||
|
||||
JSValue v = JS_NewObject(js);
|
||||
js_setpropstr(v, "mesh", primitive2js(me->primitives+0));
|
||||
js_setpropstr(v, "material", material2js(me->primitives[0].mat));
|
||||
return v;
|
||||
CLEANUP:
|
||||
cgltf_free(data);
|
||||
)
|
||||
|
||||
JSC_CCALL(os_make_buffer,
|
||||
|
@ -3088,6 +3126,11 @@ JSC_SCALL(os_make_video,
|
|||
js_setpropstr(ret, "texture", texture2js(t));
|
||||
)
|
||||
|
||||
JSC_CCALL(os_skin_calculate,
|
||||
skin *sk = js2skin(argv[0]);
|
||||
skin_calculate(sk);
|
||||
)
|
||||
|
||||
static const JSCFunctionListEntry js_os_funcs[] = {
|
||||
MIST_FUNC_DEF(os, cwd, 0),
|
||||
MIST_FUNC_DEF(os, env, 1),
|
||||
|
@ -3105,7 +3148,6 @@ static const JSCFunctionListEntry js_os_funcs[] = {
|
|||
MIST_FUNC_DEF(os, make_texture, 1),
|
||||
MIST_FUNC_DEF(os, make_tex_data, 3),
|
||||
MIST_FUNC_DEF(os, make_font, 2),
|
||||
MIST_FUNC_DEF(os, make_model, 1),
|
||||
MIST_FUNC_DEF(os, make_transform, 0),
|
||||
MIST_FUNC_DEF(os, make_buffer, 1),
|
||||
MIST_FUNC_DEF(os, make_line_prim, 4),
|
||||
|
@ -3133,7 +3175,10 @@ static const JSCFunctionListEntry js_os_funcs[] = {
|
|||
MIST_FUNC_DEF(os, check_gc, 0),
|
||||
MIST_FUNC_DEF(os, check_cycles, 0),
|
||||
MIST_FUNC_DEF(os, memstate, 0),
|
||||
MIST_FUNC_DEF(os, value_id, 1)
|
||||
MIST_FUNC_DEF(os, value_id, 1),
|
||||
MIST_FUNC_DEF(os, gltf_buffer, 3),
|
||||
MIST_FUNC_DEF(os, gltf_skin, 1),
|
||||
MIST_FUNC_DEF(os, skin_calculate, 1),
|
||||
};
|
||||
|
||||
#include "steam.h"
|
||||
|
@ -3147,7 +3192,6 @@ void ffi_load() {
|
|||
cycles = tmpfile();
|
||||
quickjs_set_cycleout(cycles);
|
||||
|
||||
JSUNDEF = JS_UNDEFINED;
|
||||
globalThis = JS_GetGlobalObject(js);
|
||||
|
||||
QJSCLASSPREP(ptr);
|
||||
|
|
|
@ -23,7 +23,7 @@ extern JSValue cpShape2js(cpShape *s);
|
|||
|
||||
#define JSC_SCALL(NAME, FN) JSC_CCALL(NAME, \
|
||||
const char *str = js2str(argv[0]); \
|
||||
FN ; \
|
||||
{FN;} ; \
|
||||
JS_FreeCString(js,str); \
|
||||
) \
|
||||
|
||||
|
|
|
@ -25,47 +25,10 @@
|
|||
|
||||
#include "sokol/sokol_gfx.h"
|
||||
|
||||
static void processnode();
|
||||
static void processmesh();
|
||||
static void processtexture();
|
||||
|
||||
static cgltf_data *cdata;
|
||||
static char *cpath;
|
||||
|
||||
cgltf_attribute *get_attr_type(cgltf_primitive *p, cgltf_attribute_type t)
|
||||
{
|
||||
for (int i = 0; i < p->attributes_count; i++) {
|
||||
if (p->attributes[i].type == t)
|
||||
return &p->attributes[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#include "jsffi.h"
|
||||
|
||||
unsigned short pack_short_tex(float c) { return c * USHRT_MAX; }
|
||||
|
||||
|
||||
void mesh_add_material(primitive *prim, cgltf_material *mat)
|
||||
{
|
||||
if (!mat) return;
|
||||
|
||||
prim->mat = calloc(sizeof(*prim->mat), 1);
|
||||
material *pmat = prim->mat;
|
||||
|
||||
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;
|
||||
pmat->diffuse = texture_fromdata(buf->buffer->data, buf->size);
|
||||
} else {
|
||||
// char *path = makepath(dirname(cpath), img->uri);
|
||||
// pmat->diffuse = texture_from_file(path);
|
||||
// free(path);
|
||||
}
|
||||
} else
|
||||
pmat->diffuse = texture_from_file("icons/moon.gif");
|
||||
}
|
||||
|
||||
sg_buffer texcoord_floats(float *f, int n)
|
||||
{
|
||||
unsigned short packed[n];
|
||||
|
@ -156,179 +119,41 @@ sg_buffer ubyte_buffer(float *f, int v)
|
|||
return sg_make_buffer(&(sg_buffer_desc){.data=SG_RANGE(b)});
|
||||
}
|
||||
|
||||
sg_buffer joint_buf(float *f, int v)
|
||||
sg_buffer accessor2buffer(cgltf_accessor *a, int type)
|
||||
{
|
||||
char joints[v];
|
||||
for (int i = 0; i < (v); i++)
|
||||
joints[i] = f[i];
|
||||
|
||||
return sg_make_buffer(&(sg_buffer_desc){ .data = SG_RANGE(joints)});
|
||||
}
|
||||
|
||||
sg_buffer weight_buf(float *f, int v)
|
||||
{
|
||||
unsigned char weights[v];
|
||||
for (int i = 0; i < (v); i++)
|
||||
weights[i] = f[i]*255;
|
||||
|
||||
return sg_make_buffer(&(sg_buffer_desc){ .data = SG_RANGE(weights)});
|
||||
}
|
||||
|
||||
HMM_Vec3 index_to_vert(uint32_t idx, float *f)
|
||||
{
|
||||
return (HMM_Vec3){f[idx*3], f[idx*3+1], f[idx*3+2]};
|
||||
}
|
||||
|
||||
void primitive_gen_indices(primitive *prim)
|
||||
{
|
||||
if (prim->idx_count != 0) return;
|
||||
|
||||
uint16_t *idxs = malloc(sizeof(*idxs)*prim->idx_count);
|
||||
|
||||
for (int z = 0; z < prim->idx_count; z++)
|
||||
idxs[z] = z;
|
||||
|
||||
prim->index = sg_make_buffer(&(sg_buffer_desc){
|
||||
.data.ptr = idxs,
|
||||
.data.size = sizeof(uint16_t) * prim->idx_count,
|
||||
.type = SG_BUFFERTYPE_INDEXBUFFER});
|
||||
|
||||
free(idxs);
|
||||
}
|
||||
|
||||
struct primitive mesh_add_primitive(cgltf_primitive *prim)
|
||||
{
|
||||
primitive retp = (primitive){0};
|
||||
|
||||
uint16_t *idxs;
|
||||
if (prim->indices) {
|
||||
int n = cgltf_accessor_unpack_floats(prim->indices, NULL, 0);
|
||||
float fidx[n];
|
||||
cgltf_accessor_unpack_floats(prim->indices, fidx, n);
|
||||
idxs = malloc(sizeof(*idxs)*n);
|
||||
for (int i = 0; i < n; i++)
|
||||
idxs[i] = fidx[i];
|
||||
|
||||
retp.index = sg_make_buffer(&(sg_buffer_desc){
|
||||
.data.ptr = idxs,
|
||||
.data.size = sizeof(*idxs) * n,
|
||||
.type = SG_BUFFERTYPE_INDEXBUFFER,
|
||||
.label = "mesh index buffer",
|
||||
});
|
||||
|
||||
retp.idx_count = n;
|
||||
free(idxs);
|
||||
} else {
|
||||
retp.idx_count = cgltf_accessor_unpack_floats(prim->attributes[0].data, NULL, 0);
|
||||
primitive_gen_indices(&retp);
|
||||
}
|
||||
|
||||
printf("adding material\n");
|
||||
mesh_add_material(&retp, prim->material);
|
||||
|
||||
for (int k = 0; k < prim->attributes_count; k++) {
|
||||
cgltf_attribute attribute = prim->attributes[k];
|
||||
|
||||
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;
|
||||
int n = cgltf_accessor_unpack_floats(a, NULL, 0);
|
||||
float vs[n];
|
||||
cgltf_accessor_unpack_floats(attribute.data, vs, n);
|
||||
cgltf_accessor_unpack_floats(a, vs, n);
|
||||
|
||||
switch (attribute.type) {
|
||||
switch(type) {
|
||||
case cgltf_attribute_type_position:
|
||||
retp.pos = sg_make_buffer(&(sg_buffer_desc){
|
||||
return sg_make_buffer(&(sg_buffer_desc){
|
||||
.data.ptr = vs,
|
||||
.data.size = sizeof(float) * n,
|
||||
.label = "mesh vert buffer"
|
||||
.data.size = sizeof(float)*n
|
||||
});
|
||||
break;
|
||||
|
||||
case cgltf_attribute_type_normal:
|
||||
retp.norm = normal_floats(vs, n);
|
||||
break;
|
||||
|
||||
return normal_floats(vs,n);
|
||||
case cgltf_attribute_type_tangent:
|
||||
return normal_floats(vs,n); // TODO: MAKE A TANGENT READER
|
||||
break;
|
||||
|
||||
case cgltf_attribute_type_color:
|
||||
retp.color = ubyten_buffer(vs,n);
|
||||
break;
|
||||
|
||||
return ubyten_buffer(vs,n);
|
||||
case cgltf_attribute_type_weights:
|
||||
retp.weight = ubyten_buffer(vs, n);
|
||||
break;
|
||||
|
||||
return ubyten_buffer(vs,n);
|
||||
case cgltf_attribute_type_joints:
|
||||
retp.bone = ubyte_buffer(vs, n);
|
||||
break;
|
||||
|
||||
return ubyte_buffer(vs,n);
|
||||
case cgltf_attribute_type_texcoord:
|
||||
retp.uv = texcoord_floats(vs, n);
|
||||
break;
|
||||
return texcoord_floats(vs,n);
|
||||
case cgltf_attribute_type_invalid:
|
||||
YughWarn("Invalid type.");
|
||||
break;
|
||||
|
||||
case cgltf_attribute_type_custom:
|
||||
break;
|
||||
|
||||
case cgltf_attribute_type_max_enum:
|
||||
break;
|
||||
}
|
||||
case 100:
|
||||
return index_buffer(vs,n);
|
||||
}
|
||||
|
||||
if (!retp.bone.id) {
|
||||
char joints[retp.idx_count*4];
|
||||
memset(joints, 0, retp.idx_count*4);
|
||||
retp.bone = sg_make_buffer(&(sg_buffer_desc){ .data = SG_RANGE(joints)});
|
||||
}
|
||||
|
||||
if (!retp.weight.id) {
|
||||
char weights[retp.idx_count*4];
|
||||
memset(weights,0,retp.idx_count*4);
|
||||
retp.weight = sg_make_buffer(&(sg_buffer_desc){ .data = SG_RANGE(weights)});
|
||||
}
|
||||
|
||||
if (!retp.color.id) {
|
||||
char colors[retp.idx_count*4];
|
||||
memset(colors,0,retp.idx_count*4);
|
||||
retp.color = sg_make_buffer(&(sg_buffer_desc) { .data = SG_RANGE(colors) });
|
||||
}
|
||||
|
||||
if (!retp.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);
|
||||
int comp = 3;
|
||||
int verts = n/comp;
|
||||
uint32_t face_norms[verts];
|
||||
float ps[n];
|
||||
cgltf_accessor_unpack_floats(pa->data,ps,n);
|
||||
|
||||
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);
|
||||
HMM_Vec3 norm = HMM_NormV3(HMM_Cross(HMM_SubV3(b,a), HMM_SubV3(c,a)));
|
||||
uint32_t packed_norm = pack_int10_n2(norm.Elements);
|
||||
face_norms[i] = face_norms[i+1] = face_norms[i+2] = packed_norm;
|
||||
}
|
||||
|
||||
retp.norm = sg_make_buffer(&(sg_buffer_desc){
|
||||
.data.ptr = face_norms,
|
||||
.data.size = sizeof(uint32_t) * verts});
|
||||
}
|
||||
|
||||
return retp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void model_add_cgltf_mesh(mesh *m, cgltf_mesh *gltf_mesh)
|
||||
{
|
||||
for (int i = 0; i < gltf_mesh->primitives_count; i++)
|
||||
arrput(m->primitives, mesh_add_primitive(gltf_mesh->primitives+i));
|
||||
return sg_make_buffer(&(sg_buffer_desc) {
|
||||
.data.size = 4,
|
||||
.usage = SG_USAGE_STREAM
|
||||
});
|
||||
}
|
||||
|
||||
void packFloats(float *src, float *dest, int srcLength) {
|
||||
|
@ -341,11 +166,10 @@ void packFloats(float *src, float *dest, int srcLength) {
|
|||
}
|
||||
}
|
||||
|
||||
void model_add_cgltf_anim(model *model, cgltf_animation *anim)
|
||||
animation *gltf_anim(cgltf_animation *anim)
|
||||
{
|
||||
YughInfo("FOUND ANIM, using %d channels and %d samplers", anim->channels_count, anim->samplers_count);
|
||||
|
||||
struct animation an = (struct animation){0};
|
||||
animation *ret = calloc(sizeof(*ret), 1);
|
||||
animation an = *ret;
|
||||
arrsetlen(an.samplers, anim->samplers_count);
|
||||
|
||||
for (int i = 0; i < anim->samplers_count; i++) {
|
||||
|
@ -378,7 +202,7 @@ void model_add_cgltf_anim(model *model, cgltf_animation *anim)
|
|||
for (int i = 0; i < anim->channels_count; i++) {
|
||||
cgltf_animation_channel ch = anim->channels[i];
|
||||
struct anim_channel ach = (struct anim_channel){0};
|
||||
md5joint *md = model->nodes+(ch.target_node-cdata->nodes);
|
||||
md5joint *md = NULL;
|
||||
switch(ch.target_path) {
|
||||
case cgltf_animation_path_type_translation:
|
||||
ach.target = &md->pos;
|
||||
|
@ -396,31 +220,28 @@ void model_add_cgltf_anim(model *model, cgltf_animation *anim)
|
|||
arrput(an.channels, ach);
|
||||
}
|
||||
|
||||
model->anim = an;
|
||||
model->anim.time = apptime();
|
||||
*ret = an;
|
||||
}
|
||||
|
||||
void model_add_cgltf_skin(model *model, cgltf_skin *skin)
|
||||
skin *make_gltf_skin(cgltf_skin *skin)
|
||||
{
|
||||
int n = cgltf_accessor_unpack_floats(skin->inverse_bind_matrices, NULL, 0);
|
||||
struct skin sk = (struct skin){0};
|
||||
arrsetlen(sk.invbind, n/16);
|
||||
cgltf_accessor_unpack_floats(skin->inverse_bind_matrices, sk.invbind, n);
|
||||
YughInfo("FOUND SKIN, of %d bones, and %d vert comps", skin->joints_count, n);
|
||||
struct skin *sk = NULL;
|
||||
sk = calloc(sizeof(*sk),1);
|
||||
arrsetlen(sk->invbind, n/16);
|
||||
cgltf_accessor_unpack_floats(skin->inverse_bind_matrices, sk->invbind, n);
|
||||
|
||||
cgltf_node *root = skin->skeleton;
|
||||
|
||||
arrsetlen(sk.joints, skin->joints_count);
|
||||
sk.root = model->nodes+(skin->skeleton-cdata->nodes);
|
||||
arrsetlen(sk->joints, skin->joints_count);
|
||||
|
||||
for (int i = 0; i < 50; i++)
|
||||
sk.binds[i] = MAT1;
|
||||
sk->binds[i] = MAT1;
|
||||
|
||||
for (int i = 0; i < skin->joints_count; i++) {
|
||||
int offset = skin->joints[i]-cdata->nodes;
|
||||
sk.joints[i] = model->nodes+offset;
|
||||
md5joint *j = sk.joints[i];
|
||||
cgltf_node *n = skin->joints[i];
|
||||
int idx = n-skin->skeleton;
|
||||
int parent_idx = n->parent-skin->skeleton;
|
||||
md5joint *j = sk->joints+idx;
|
||||
j->parent = sk->joints+parent_idx;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
j->pos.e[i] = n->translation[i];
|
||||
j->scale.e[i] = n->scale[i];
|
||||
|
@ -429,196 +250,17 @@ void model_add_cgltf_skin(model *model, cgltf_skin *skin)
|
|||
j->rot.e[i] = n->rotation[i];
|
||||
}
|
||||
|
||||
model->skin = sk;
|
||||
return sk;
|
||||
}
|
||||
|
||||
void model_process_node(model *model, cgltf_node *node)
|
||||
void skin_calculate(skin *sk)
|
||||
{
|
||||
int n = node-cdata->nodes;
|
||||
cgltf_node_transform_world(node, model->nodes[n].t.e);
|
||||
model->nodes[n].parent = model->nodes+(node->parent-cdata->nodes);
|
||||
|
||||
if (node->mesh) {
|
||||
int meshn = node->mesh-cdata->meshes;
|
||||
arrsetlen(model->meshes, meshn+1);
|
||||
model->meshes[meshn].m = &model->nodes[n].t;
|
||||
model_add_cgltf_mesh(model->meshes+meshn, node->mesh);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
struct model *model = NULL;
|
||||
|
||||
if (result) {
|
||||
YughError("CGLTF could not parse file %s, err %d.", path, result);
|
||||
goto CLEAN;
|
||||
}
|
||||
|
||||
result = cgltf_load_buffers(&options, data, path);
|
||||
|
||||
if (result) {
|
||||
YughError("CGLTF could not load buffers for file %s, err %d.", path, result);
|
||||
goto CLEAN;
|
||||
}
|
||||
|
||||
cdata = data;
|
||||
|
||||
model = calloc(1, sizeof(*model));
|
||||
|
||||
arrsetlen(model->nodes, data->nodes_count);
|
||||
for (int i = 0; i < data->nodes_count; i++)
|
||||
model_process_node(model, data->nodes+i);
|
||||
|
||||
for (int i = 0; i < data->animations_count; i++)
|
||||
model_add_cgltf_anim(model, data->animations+i);
|
||||
|
||||
for (int i = 0; i < data->skins_count; i++)
|
||||
model_add_cgltf_skin(model, data->skins+i);
|
||||
|
||||
CLEAN:
|
||||
cgltf_free(data);
|
||||
return model;
|
||||
}
|
||||
|
||||
void model_free(model *m)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
sg_bindings primitive_bind(primitive *p)
|
||||
{
|
||||
sg_bindings b = {0};
|
||||
b.vertex_buffers[MAT_POS] = p->pos;
|
||||
b.vertex_buffers[MAT_UV] = p->uv;
|
||||
b.vertex_buffers[MAT_NORM] = p->norm;
|
||||
b.vertex_buffers[MAT_BONE] = p->bone;
|
||||
b.vertex_buffers[MAT_WEIGHT] = p->weight;
|
||||
b.vertex_buffers[MAT_COLOR] = p->color;
|
||||
b.index_buffer = p->index;
|
||||
b.fs.images[0] = p->mat->diffuse->id;
|
||||
b.fs.samplers[0] = tex_sampler;
|
||||
return b;
|
||||
}
|
||||
|
||||
void model_draw_go(model *model, transform *go)
|
||||
{
|
||||
HMM_Mat4 gom = transform2mat(go);
|
||||
|
||||
animation_run(&model->anim, apptime());
|
||||
|
||||
skin *sk = &model->skin;
|
||||
for (int i = 0; i < arrlen(sk->joints); i++) {
|
||||
md5joint *md = 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
|
||||
});
|
||||
*/
|
||||
|
||||
for (int i = 0; i < arrlen(model->meshes); i++) {
|
||||
HMM_Mat4 mod = *model->meshes[i].m;
|
||||
mod = HMM_MulM4(mod, gom);
|
||||
mesh msh = model->meshes[i];
|
||||
for (int j = 0; j < arrlen(msh.primitives); j++) {
|
||||
sg_bindings b = primitive_bind(msh.primitives+j);
|
||||
sg_apply_bindings(&b);
|
||||
sg_draw(0, msh.primitives[j].idx_count, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int mat2type(int mat)
|
||||
{
|
||||
switch(mat) {
|
||||
case MAT_POS:
|
||||
case MAT_NORM:
|
||||
return SG_VERTEXFORMAT_FLOAT3;
|
||||
case MAT_PPOS:
|
||||
case MAT_WH:
|
||||
case MAT_ST:
|
||||
return SG_VERTEXFORMAT_FLOAT2;
|
||||
case MAT_UV:
|
||||
case MAT_TAN:
|
||||
return SG_VERTEXFORMAT_USHORT2N;
|
||||
return SG_VERTEXFORMAT_UINT10_N2;
|
||||
case MAT_BONE:
|
||||
return SG_VERTEXFORMAT_UBYTE4;
|
||||
case MAT_WEIGHT:
|
||||
case MAT_COLOR:
|
||||
return SG_VERTEXFORMAT_UBYTE4N;
|
||||
case MAT_ANGLE:
|
||||
case MAT_SCALE:
|
||||
return SG_VERTEXFORMAT_FLOAT;
|
||||
};
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mat2step(int mat)
|
||||
{
|
||||
switch(mat) {
|
||||
case MAT_POS:
|
||||
case MAT_UV:
|
||||
case MAT_TAN:
|
||||
case MAT_NORM:
|
||||
case MAT_BONE:
|
||||
case MAT_WEIGHT:
|
||||
return SG_VERTEXSTEP_PER_VERTEX;
|
||||
};
|
||||
return SG_VERTEXSTEP_PER_INSTANCE;
|
||||
}
|
||||
|
||||
sg_buffer mat2buffer(int mat, primitive *p)
|
||||
{
|
||||
switch(mat) {
|
||||
case MAT_POS: return p->pos;
|
||||
case MAT_NORM: return p->norm;
|
||||
case MAT_UV: return p->uv;
|
||||
case MAT_BONE: return p->bone;
|
||||
case MAT_WEIGHT: return p->weight;
|
||||
case MAT_COLOR: return p->color;
|
||||
};
|
||||
|
||||
return p->pos;
|
||||
}
|
||||
|
||||
sg_bindings primitive_bindings(primitive *p, JSValue v)
|
||||
{
|
||||
sg_bindings b = {0};
|
||||
JSValue inputs = js_getpropstr(js_getpropstr(v, "vs"), "inputs");
|
||||
for (int i = 0; i < js_arrlen(inputs); i++) {
|
||||
JSValue attr = js_getpropidx(inputs, i);
|
||||
int mat = js2number(js_getpropstr(attr, "mat"));
|
||||
int slot = js2number(js_getpropstr(attr, "slot"));
|
||||
sg_buffer buf = mat2buffer(mat,p);
|
||||
if (!buf.id) {
|
||||
// ERROR
|
||||
}
|
||||
b.vertex_buffers[slot] = buf;
|
||||
}
|
||||
|
||||
b.index_buffer = p->index;
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
void primitive_free(primitive *prim)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void material_free(material *mat)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
@ -7,57 +7,7 @@
|
|||
#include "gameobject.h"
|
||||
#include "anim.h"
|
||||
#include "texture.h"
|
||||
|
||||
#define MAT_POS 0
|
||||
#define MAT_UV 1
|
||||
#define MAT_NORM 2
|
||||
#define MAT_BONE 3
|
||||
#define MAT_WEIGHT 4
|
||||
#define MAT_COLOR 5
|
||||
#define MAT_TAN 6
|
||||
#define MAT_ANGLE 7
|
||||
#define MAT_WH 8
|
||||
#define MAT_ST 9
|
||||
#define MAT_PPOS 10
|
||||
#define MAT_SCALE 11
|
||||
|
||||
typedef struct material {
|
||||
struct texture *diffuse;
|
||||
struct texture *metalrough;
|
||||
float metal;
|
||||
float rough;
|
||||
struct texture *normal;
|
||||
float nrm;
|
||||
struct texture *occlusion;
|
||||
float occl;
|
||||
struct texture *emissive;
|
||||
HMM_Vec3 emis;
|
||||
} material;
|
||||
|
||||
struct model;
|
||||
|
||||
typedef struct primitive {
|
||||
sg_buffer pos;
|
||||
sg_buffer norm;
|
||||
sg_buffer uv;
|
||||
sg_buffer bone;
|
||||
sg_buffer weight;
|
||||
sg_buffer color;
|
||||
sg_buffer index;
|
||||
material *mat;
|
||||
uint32_t idx_count;
|
||||
} primitive;
|
||||
|
||||
/* A single mesh */
|
||||
typedef struct mesh {
|
||||
primitive *primitives;
|
||||
HMM_Mat4 *m;
|
||||
} mesh;
|
||||
|
||||
typedef struct joint {
|
||||
int me;
|
||||
struct joint *children;
|
||||
} joint_t;
|
||||
#include "cgltf.h"
|
||||
|
||||
typedef struct md5joint {
|
||||
struct md5joint *parent;
|
||||
|
@ -68,29 +18,14 @@ typedef struct md5joint {
|
|||
} md5joint;
|
||||
|
||||
typedef struct skin {
|
||||
md5joint **joints;
|
||||
md5joint *joints;
|
||||
HMM_Mat4 *invbind;
|
||||
HMM_Mat4 binds[50]; /* binds = joint * invbind */
|
||||
md5joint *root;
|
||||
} skin;
|
||||
|
||||
/* A collection of meshes which create a full figure */
|
||||
typedef struct model {
|
||||
struct mesh *meshes;
|
||||
md5joint *nodes;
|
||||
material *mats;
|
||||
skin skin;
|
||||
struct animation anim;
|
||||
} model;
|
||||
|
||||
/* Make a Model struct */
|
||||
struct model *model_make(const char *path);
|
||||
void model_free(model *m);
|
||||
|
||||
void model_draw_go(model *m, transform *go);
|
||||
sg_bindings primitive_bindings(primitive *p, JSValue pipe);
|
||||
void primitive_gen_indices(primitive *prim);
|
||||
int mat2type(int mat);
|
||||
sg_buffer accessor2buffer(cgltf_accessor *a, int type);
|
||||
skin *make_gltf_skin(cgltf_skin *skin);
|
||||
void skin_calculate(skin *sk);
|
||||
|
||||
sg_buffer float_buffer(float *f, int v);
|
||||
sg_buffer index_buffer(float *f, int verts);
|
||||
|
@ -101,9 +36,5 @@ sg_buffer ubyten_buffer(float *f, int v);
|
|||
sg_buffer ubyte_buffer(float *f, int v);
|
||||
sg_buffer joint_buf(float *f, int v);
|
||||
sg_buffer weight_buf(float *f, int v);
|
||||
void primitive_free(primitive *prim);
|
||||
|
||||
material *material_make();
|
||||
void material_free(material *mat);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue