3d skeletal animation
This commit is contained in:
parent
5af7d0a2e0
commit
0052a89c41
4
Makefile
4
Makefile
|
@ -66,7 +66,7 @@ else ifeq ($(OPT), 1)
|
||||||
CPPFLAGS += -O3 -flto
|
CPPFLAGS += -O3 -flto
|
||||||
INFO :=$(INFO)_opt
|
INFO :=$(INFO)_opt
|
||||||
else
|
else
|
||||||
CPPFLAGS += -O2
|
CPPFLAGS += -O0
|
||||||
endif
|
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
|
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
|
||||||
|
@ -204,7 +204,7 @@ shaders: $(SHADERS)
|
||||||
|
|
||||||
%.sglsl.h:%.sglsl
|
%.sglsl.h:%.sglsl
|
||||||
@echo Creating shader $^
|
@echo Creating shader $^
|
||||||
./sokol-shdc --ifdef -i $^ --slang=glsl330:hlsl5:metal_macos:metal_ios:metal_sim:glsl300es -o $@
|
./sokol-shdc -r --ifdef -i $^ --slang=glsl330:hlsl5:metal_macos:metal_ios:metal_sim:glsl300es -o $@
|
||||||
|
|
||||||
SCRIPTS := $(shell ls scripts/*.js*)
|
SCRIPTS := $(shell ls scripts/*.js*)
|
||||||
CORE != (ls icons/* fonts/*)
|
CORE != (ls icons/* fonts/*)
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "resources.h"
|
#include "resources.h"
|
||||||
#include "stb_ds.h"
|
#include "stb_ds.h"
|
||||||
#include "font.h"
|
|
||||||
#include "gameobject.h"
|
#include "gameobject.h"
|
||||||
|
|
||||||
//#include "diffuse.sglsl.h"
|
//#include "diffuse.sglsl.h"
|
||||||
|
@ -16,11 +15,12 @@
|
||||||
#include "math.h"
|
#include "math.h"
|
||||||
#include "time.h"
|
#include "time.h"
|
||||||
|
|
||||||
#define CGLTF_IMPLEMENTATION
|
|
||||||
#include <cgltf.h>
|
#include <cgltf.h>
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "yugine.h"
|
||||||
|
|
||||||
#include "texture.h"
|
#include "texture.h"
|
||||||
|
|
||||||
|
@ -32,7 +32,6 @@ static void processtexture();
|
||||||
|
|
||||||
static sg_shader model_shader;
|
static sg_shader model_shader;
|
||||||
static sg_pipeline model_pipe;
|
static sg_pipeline model_pipe;
|
||||||
|
|
||||||
struct bone_weights {
|
struct bone_weights {
|
||||||
char b1;
|
char b1;
|
||||||
char b2;
|
char b2;
|
||||||
|
@ -40,11 +39,11 @@ struct bone_weights {
|
||||||
char b4;
|
char b4;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mesh_v {
|
struct joints {
|
||||||
HMM_Vec3 pos;
|
char j1;
|
||||||
struct uv_n uv;
|
char j2;
|
||||||
uint32_t norm;
|
char j3;
|
||||||
struct bone_weights bones;
|
char j4;
|
||||||
};
|
};
|
||||||
|
|
||||||
void model_init() {
|
void model_init() {
|
||||||
|
@ -57,8 +56,16 @@ void model_init() {
|
||||||
[0].format = SG_VERTEXFORMAT_FLOAT3,
|
[0].format = SG_VERTEXFORMAT_FLOAT3,
|
||||||
[1].format = SG_VERTEXFORMAT_USHORT2N,
|
[1].format = SG_VERTEXFORMAT_USHORT2N,
|
||||||
[1].buffer_index = 1,
|
[1].buffer_index = 1,
|
||||||
[2].format = SG_VERTEXFORMAT_FLOAT3,
|
[2].format = SG_VERTEXFORMAT_UINT10_N2,
|
||||||
[2].buffer_index = 2
|
[2].buffer_index = 2,
|
||||||
|
[3] = {
|
||||||
|
.format = SG_VERTEXFORMAT_UBYTE4N,
|
||||||
|
.buffer_index = 3
|
||||||
|
},
|
||||||
|
[4] = {
|
||||||
|
.format = SG_VERTEXFORMAT_UBYTE4,
|
||||||
|
.buffer_index = 4
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.index_type = SG_INDEXTYPE_UINT16,
|
.index_type = SG_INDEXTYPE_UINT16,
|
||||||
|
@ -90,59 +97,29 @@ unsigned short pack_short_tex(float c) { return c * USHRT_MAX; }
|
||||||
|
|
||||||
uint32_t pack_int10_n2(float *norm)
|
uint32_t pack_int10_n2(float *norm)
|
||||||
{
|
{
|
||||||
/*float x = norm[0];
|
uint32_t ret = 0;
|
||||||
float y = norm[1];
|
for (int i = 0; i < 3; i++) {
|
||||||
float z = norm[2];
|
int n = (norm[i]+1.0)*511;
|
||||||
const uint32_t xs = x < 0;
|
ret |= (n & 0x3ff) << (10*i);
|
||||||
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++) {
|
|
||||||
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];
|
|
||||||
}
|
}
|
||||||
|
return ret;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mesh_add_material(mesh *mesh, cgltf_material *mat)
|
void mesh_add_material(primitive *prim, cgltf_material *mat)
|
||||||
{
|
{
|
||||||
if (!mat) return;
|
if (!mat) return;
|
||||||
|
|
||||||
if (mat && mat->has_pbr_metallic_roughness) {
|
if (mat->has_pbr_metallic_roughness) {
|
||||||
cgltf_image *img = mat->pbr_metallic_roughness.base_color_texture.texture->image;
|
cgltf_image *img = mat->pbr_metallic_roughness.base_color_texture.texture->image;
|
||||||
if (img->buffer_view) {
|
if (img->buffer_view) {
|
||||||
cgltf_buffer_view *buf = img->buffer_view;
|
cgltf_buffer_view *buf = img->buffer_view;
|
||||||
mesh->bind.fs.images[0] = texture_fromdata(buf->buffer->data, buf->size)->id;
|
prim->bind.fs.images[0] = texture_fromdata(buf->buffer->data, buf->size)->id;
|
||||||
} else
|
} else
|
||||||
mesh->bind.fs.images[0] = texture_from_file(img->uri)->id;
|
prim->bind.fs.images[0] = texture_from_file(img->uri)->id;
|
||||||
} else
|
} else
|
||||||
mesh->bind.fs.images[0] = texture_from_file("icons/moon.gif")->id;
|
prim->bind.fs.images[0] = texture_from_file("icons/moon.gif")->id;
|
||||||
|
|
||||||
mesh->bind.fs.samplers[0] = std_sampler;
|
prim->bind.fs.samplers[0] = std_sampler;
|
||||||
}
|
}
|
||||||
|
|
||||||
sg_buffer texcoord_floats(float *f, int verts, int comp)
|
sg_buffer texcoord_floats(float *f, int verts, int comp)
|
||||||
|
@ -160,10 +137,6 @@ sg_buffer texcoord_floats(float *f, int verts, int comp)
|
||||||
|
|
||||||
sg_buffer normal_floats(float *f, int verts, int comp)
|
sg_buffer normal_floats(float *f, int verts, int comp)
|
||||||
{
|
{
|
||||||
return sg_make_buffer(&(sg_buffer_desc){
|
|
||||||
.data.ptr = f,
|
|
||||||
.data.size = sizeof(*f)*verts*comp
|
|
||||||
});
|
|
||||||
uint32_t packed_norms[verts];
|
uint32_t packed_norms[verts];
|
||||||
for (int v = 0, i = 0; v < verts; v++, i+= comp)
|
for (int v = 0, i = 0; v < verts; v++, i+= comp)
|
||||||
packed_norms[v] = pack_int10_n2(f+i);
|
packed_norms[v] = pack_int10_n2(f+i);
|
||||||
|
@ -174,46 +147,70 @@ sg_buffer normal_floats(float *f, int verts, int comp)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sg_buffer joint_buf(float *f, int v, int c)
|
||||||
|
{
|
||||||
|
char joints[v*c];
|
||||||
|
for (int i = 0; i < (v*c); i++)
|
||||||
|
joints[i] = f[i];
|
||||||
|
|
||||||
|
return sg_make_buffer(&(sg_buffer_desc){ .data = SG_RANGE(joints)});
|
||||||
|
}
|
||||||
|
|
||||||
|
sg_buffer weight_buf(float *f, int v, int c)
|
||||||
|
{
|
||||||
|
unsigned char weights[v*c];
|
||||||
|
for (int i = 0; i < (v*c); 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)
|
HMM_Vec3 index_to_vert(uint32_t idx, float *f)
|
||||||
{
|
{
|
||||||
return (HMM_Vec3){f[idx*3], f[idx*3+1], f[idx*3+2]};
|
return (HMM_Vec3){f[idx*3], f[idx*3+1], f[idx*3+2]};
|
||||||
}
|
}
|
||||||
|
|
||||||
void mesh_add_primitive(mesh *mesh, cgltf_primitive *prim)
|
struct primitive mesh_add_primitive(cgltf_primitive *prim)
|
||||||
{
|
{
|
||||||
|
primitive retp = (primitive){0};
|
||||||
|
|
||||||
uint16_t *idxs;
|
uint16_t *idxs;
|
||||||
if (prim->indices) {
|
if (prim->indices) {
|
||||||
int c = prim->indices->count;
|
int n = cgltf_accessor_unpack_floats(prim->indices, NULL, 0);
|
||||||
idxs = malloc(sizeof(*idxs)*c);
|
float fidx[n];
|
||||||
memcpy(idxs, cgltf_buffer_view_data(prim->indices->buffer_view), sizeof(uint16_t) * c);
|
cgltf_accessor_unpack_floats(prim->indices, fidx, n);
|
||||||
|
idxs = malloc(sizeof(*idxs)*n);
|
||||||
|
for (int i = 0; i < n; i++)
|
||||||
|
idxs[i] = fidx[i];
|
||||||
|
|
||||||
mesh->bind.index_buffer = sg_make_buffer(&(sg_buffer_desc){
|
retp.bind.index_buffer = sg_make_buffer(&(sg_buffer_desc){
|
||||||
.data.ptr = idxs,
|
.data.ptr = idxs,
|
||||||
.data.size = sizeof(uint16_t) * c,
|
.data.size = sizeof(*idxs) * n,
|
||||||
.type = SG_BUFFERTYPE_INDEXBUFFER,
|
.type = SG_BUFFERTYPE_INDEXBUFFER,
|
||||||
.label = "mesh index buffer",
|
.label = "mesh index buffer",
|
||||||
});
|
});
|
||||||
|
|
||||||
mesh->idx_count = c;
|
retp.idx_count = n;
|
||||||
} else {
|
} else {
|
||||||
YughWarn("Model does not have indices. Generating them.");
|
YughWarn("Model does not have indices. Generating them.");
|
||||||
int c = prim->attributes[0].data->count;
|
int c = cgltf_accessor_unpack_floats(prim->attributes[0].data, NULL, 0);
|
||||||
|
|
||||||
mesh->idx_count = c;
|
retp.idx_count = c;
|
||||||
idxs = malloc(sizeof(*idxs)*c);
|
idxs = malloc(sizeof(*idxs)*c);
|
||||||
|
|
||||||
for (int z = 0; z < c; z++)
|
for (int z = 0; z < c; z++)
|
||||||
idxs[z] = z;
|
idxs[z] = z;
|
||||||
|
|
||||||
mesh->bind.index_buffer = sg_make_buffer(&(sg_buffer_desc){
|
retp.bind.index_buffer = sg_make_buffer(&(sg_buffer_desc){
|
||||||
.data.ptr = idxs,
|
.data.ptr = idxs,
|
||||||
.data.size = sizeof(uint16_t) * c,
|
.data.size = sizeof(uint16_t) * c,
|
||||||
.type = SG_BUFFERTYPE_INDEXBUFFER});
|
.type = SG_BUFFERTYPE_INDEXBUFFER});
|
||||||
}
|
}
|
||||||
|
|
||||||
free(idxs);
|
free(idxs);
|
||||||
|
|
||||||
printf("adding material\n");
|
printf("adding material\n");
|
||||||
mesh_add_material(mesh, prim->material);
|
mesh_add_material(&retp, prim->material);
|
||||||
int has_norm = 0;
|
int has_norm = 0;
|
||||||
|
|
||||||
for (int k = 0; k < prim->attributes_count; k++) {
|
for (int k = 0; k < prim->attributes_count; k++) {
|
||||||
|
@ -227,7 +224,7 @@ void mesh_add_primitive(mesh *mesh, cgltf_primitive *prim)
|
||||||
|
|
||||||
switch (attribute.type) {
|
switch (attribute.type) {
|
||||||
case cgltf_attribute_type_position:
|
case cgltf_attribute_type_position:
|
||||||
mesh->bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
|
retp.bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
|
||||||
.data.ptr = vs,
|
.data.ptr = vs,
|
||||||
.data.size = sizeof(float) * n,
|
.data.size = sizeof(float) * n,
|
||||||
.label = "mesh vert buffer"
|
.label = "mesh vert buffer"
|
||||||
|
@ -236,8 +233,7 @@ void mesh_add_primitive(mesh *mesh, cgltf_primitive *prim)
|
||||||
|
|
||||||
case cgltf_attribute_type_normal:
|
case cgltf_attribute_type_normal:
|
||||||
has_norm = 1;
|
has_norm = 1;
|
||||||
YughInfo("Found normals.");
|
retp.bind.vertex_buffers[2] = normal_floats(vs, verts, comp);
|
||||||
mesh->bind.vertex_buffers[2] = normal_floats(vs, verts, comp);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case cgltf_attribute_type_tangent:
|
case cgltf_attribute_type_tangent:
|
||||||
|
@ -247,16 +243,15 @@ void mesh_add_primitive(mesh *mesh, cgltf_primitive *prim)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case cgltf_attribute_type_weights:
|
case cgltf_attribute_type_weights:
|
||||||
|
retp.bind.vertex_buffers[3] = weight_buf(vs, verts, comp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case cgltf_attribute_type_joints:
|
case cgltf_attribute_type_joints:
|
||||||
|
retp.bind.vertex_buffers[4] = joint_buf(vs, verts, comp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case cgltf_attribute_type_texcoord:
|
case cgltf_attribute_type_texcoord:
|
||||||
mesh->bind.vertex_buffers[1] = texcoord_floats(vs, verts, comp); /*sg_make_buffer(&(sg_buffer_desc){
|
retp.bind.vertex_buffers[1] = texcoord_floats(vs, verts, comp);
|
||||||
.data.ptr = vs,
|
|
||||||
.data.size=sizeof(*vs)*verts*comp
|
|
||||||
});*/
|
|
||||||
break;
|
break;
|
||||||
case cgltf_attribute_type_invalid:
|
case cgltf_attribute_type_invalid:
|
||||||
YughWarn("Invalid type.");
|
YughWarn("Invalid type.");
|
||||||
|
@ -288,48 +283,135 @@ void mesh_add_primitive(mesh *mesh, cgltf_primitive *prim)
|
||||||
face_norms[i] = face_norms[i+1] = face_norms[i+2] = packed_norm;
|
face_norms[i] = face_norms[i+1] = face_norms[i+2] = packed_norm;
|
||||||
}
|
}
|
||||||
|
|
||||||
mesh->bind.vertex_buffers[2] = sg_make_buffer(&(sg_buffer_desc){
|
retp.bind.vertex_buffers[2] = sg_make_buffer(&(sg_buffer_desc){
|
||||||
.data.ptr = face_norms,
|
.data.ptr = face_norms,
|
||||||
.data.size = sizeof(uint32_t) * verts});
|
.data.size = sizeof(uint32_t) * verts});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return retp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void model_add_cgltf_mesh(model *model, cgltf_mesh *gltf_mesh)
|
static cgltf_data *cdata;
|
||||||
|
|
||||||
|
void model_add_cgltf_mesh(mesh *m, cgltf_mesh *gltf_mesh)
|
||||||
{
|
{
|
||||||
mesh mesh = {0};
|
printf("mesh has %d primitives\n", gltf_mesh->primitives_count);
|
||||||
|
|
||||||
for (int i = 0; i < gltf_mesh->primitives_count; i++)
|
for (int i = 0; i < gltf_mesh->primitives_count; i++)
|
||||||
mesh_add_primitive(&mesh, &gltf_mesh->primitives[i]);
|
arrput(m->primitives, mesh_add_primitive(gltf_mesh->primitives+i));
|
||||||
|
}
|
||||||
|
|
||||||
arrput(model->meshes,mesh);
|
void packFloats(float *src, float *dest, int srcLength) {
|
||||||
|
int i, j;
|
||||||
|
for (i = 0, j = 0; i < srcLength; i += 3, j += 4) {
|
||||||
|
dest[j] = src[i];
|
||||||
|
dest[j + 1] = src[i + 1];
|
||||||
|
dest[j + 2] = src[i + 2];
|
||||||
|
dest[j + 3] = 0.0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void model_add_cgltf_anim(model *model, cgltf_animation *anim)
|
void model_add_cgltf_anim(model *model, cgltf_animation *anim)
|
||||||
{
|
{
|
||||||
|
YughInfo("FOUND ANIM, using %d channels and %d samplers", anim->channels_count, anim->samplers_count);
|
||||||
|
|
||||||
|
struct animation an = (struct animation){0};
|
||||||
|
arrsetlen(an.samplers, anim->samplers_count);
|
||||||
|
|
||||||
|
for (int i = 0; i < anim->samplers_count; i++) {
|
||||||
|
cgltf_animation_sampler s = anim->samplers[i];
|
||||||
|
sampler samp = (sampler){0};
|
||||||
|
int n = cgltf_accessor_unpack_floats(s.input, NULL, 0);
|
||||||
|
arrsetlen(samp.times, n);
|
||||||
|
cgltf_accessor_unpack_floats(s.input, samp.times, n);
|
||||||
|
|
||||||
|
n = cgltf_accessor_unpack_floats(s.output, NULL, 0);
|
||||||
|
int comp = cgltf_num_components(s.output->type);
|
||||||
|
arrsetlen(samp.data, n/comp);
|
||||||
|
if (comp == 4)
|
||||||
|
cgltf_accessor_unpack_floats(s.output, samp.data, n);
|
||||||
|
else {
|
||||||
|
float *out = malloc(sizeof(*out)*n);
|
||||||
|
cgltf_accessor_unpack_floats(s.output, out, n);
|
||||||
|
packFloats(out, samp.data, n);
|
||||||
|
free(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
samp.type = s.interpolation;
|
||||||
|
|
||||||
|
if (samp.type == LINEAR && comp == 4)
|
||||||
|
samp.type = SLERP;
|
||||||
|
|
||||||
|
an.samplers[i] = samp;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
switch(ch.target_path) {
|
||||||
|
case cgltf_animation_path_type_translation:
|
||||||
|
ach.target = &md->pos;
|
||||||
|
break;
|
||||||
|
case cgltf_animation_path_type_rotation:
|
||||||
|
ach.target = &md->rot;
|
||||||
|
break;
|
||||||
|
case cgltf_animation_path_type_scale:
|
||||||
|
ach.target = &md->scale;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ach.sampler = an.samplers+(ch.sampler-anim->samplers);
|
||||||
|
|
||||||
|
arrput(an.channels, ach);
|
||||||
|
}
|
||||||
|
|
||||||
|
model->anim = an;
|
||||||
|
model->anim.time = apptime();
|
||||||
}
|
}
|
||||||
|
|
||||||
void model_add_cgltf_skin(model *model, cgltf_skin *skin)
|
void model_add_cgltf_skin(model *model, 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);
|
||||||
|
|
||||||
|
cgltf_node *root = skin->skeleton;
|
||||||
|
|
||||||
|
arrsetlen(sk.joints, skin->joints_count);
|
||||||
|
sk.root = model->nodes+(skin->skeleton-cdata->nodes);
|
||||||
|
|
||||||
|
for (int i = 0; i < 50; i++)
|
||||||
|
sk.binds[i] = HMM_M4D(1);
|
||||||
|
|
||||||
|
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];
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
j->pos.e[i] = n->translation[i];
|
||||||
|
j->scale.e[i] = n->scale[i];
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
j->rot.e[i] = n->rotation[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
model->skin = sk;
|
||||||
}
|
}
|
||||||
|
|
||||||
void model_process_node(model *model, cgltf_node *node)
|
void model_process_node(model *model, cgltf_node *node)
|
||||||
{
|
{
|
||||||
if (node->has_matrix)
|
int n = node-cdata->nodes;
|
||||||
memcpy(model->matrix.Elements, node->matrix, sizeof(float)*16);
|
cgltf_node_transform_world(node, model->nodes[n].t.e);
|
||||||
|
model->nodes[n].parent = model->nodes+(node->parent-cdata->nodes);
|
||||||
if (node->mesh)
|
|
||||||
model_add_cgltf_mesh(model, node->mesh);
|
if (node->mesh) {
|
||||||
|
int meshn = node->mesh-cdata->meshes;
|
||||||
if (node->skin)
|
arrsetlen(model->meshes, meshn+1);
|
||||||
model_add_cgltf_skin(model, node->skin);
|
model->meshes[meshn].m = &model->nodes[n].t;
|
||||||
}
|
model_add_cgltf_mesh(model->meshes+meshn, node->mesh);
|
||||||
|
}
|
||||||
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]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct model *model_make(const char *path)
|
struct model *model_make(const char *path)
|
||||||
|
@ -338,30 +420,36 @@ struct model *model_make(const char *path)
|
||||||
cgltf_options options = {0};
|
cgltf_options options = {0};
|
||||||
cgltf_data *data = NULL;
|
cgltf_data *data = NULL;
|
||||||
cgltf_result result = cgltf_parse_file(&options, path, &data);
|
cgltf_result result = cgltf_parse_file(&options, path, &data);
|
||||||
|
struct model *model = NULL;
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
YughError("CGLTF could not parse file %s, err %d.", path, result);
|
YughError("CGLTF could not parse file %s, err %d.", path, result);
|
||||||
return NULL;
|
goto CLEAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = cgltf_load_buffers(&options, data, path);
|
result = cgltf_load_buffers(&options, data, path);
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
YughError("CGLTF could not load buffers for file %s, err %d.", path, result);
|
YughError("CGLTF could not load buffers for file %s, err %d.", path, result);
|
||||||
return NULL;
|
goto CLEAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cdata = data;
|
||||||
|
|
||||||
struct model *model = calloc(1, sizeof(*model));
|
model = calloc(1, sizeof(*model));
|
||||||
|
|
||||||
if (data->scenes_count == 0 || data->scenes_count > 1) return NULL;
|
arrsetlen(model->nodes, data->nodes_count);
|
||||||
model_process_scene(model, data->scene);
|
for (int i = 0; i < data->nodes_count; i++)
|
||||||
|
model_process_node(model, data->nodes+i);
|
||||||
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++)
|
for (int i = 0; i < data->animations_count; i++)
|
||||||
model_add_cgltf_anim(model, &data->animations[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;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,20 +460,45 @@ void model_free(model *m)
|
||||||
|
|
||||||
void model_draw_go(model *model, gameobject *go, gameobject *cam)
|
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 view = t3d_go2world(cam);
|
||||||
HMM_Mat4 proj = HMM_Perspective_RH_NO(20, 1, 0.01, 10000);
|
HMM_Mat4 proj = HMM_Perspective_RH_NO(20, 1, 0.01, 10000);
|
||||||
HMM_Mat4 vp = HMM_MulM4(proj, view);
|
HMM_Mat4 vp = HMM_MulM4(proj, view);
|
||||||
|
HMM_Mat4 gom = transform3d2mat(go2t3(go));
|
||||||
vs_p_t vs_p;
|
|
||||||
memcpy(vs_p.vp, vp.Elements, sizeof(float)*16);
|
|
||||||
memcpy(vs_p.model, t3d_go2world(go).Elements, sizeof(float)*16);
|
|
||||||
|
|
||||||
sg_apply_pipeline(model_pipe);
|
sg_apply_pipeline(model_pipe);
|
||||||
sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_vs_p, SG_RANGE_REF(vs_p));
|
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++) {
|
for (int i = 0; i < arrlen(model->meshes); i++) {
|
||||||
sg_apply_bindings(&model->meshes[i].bind);
|
HMM_Mat4 mod = *model->meshes[i].m;
|
||||||
sg_draw(0, model->meshes[i].idx_count, 1);
|
mod = HMM_MulM4(mod, gom);
|
||||||
|
mesh msh = model->meshes[i];
|
||||||
|
for (int j = 0; j < arrlen(msh.primitives); j++) {
|
||||||
|
sg_apply_bindings(&(msh.primitives[j].bind));
|
||||||
|
sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_vmodel, &(sg_range){
|
||||||
|
.ptr = mod.em,
|
||||||
|
.size = sizeof(mod)
|
||||||
|
});
|
||||||
|
sg_draw(0, model->meshes[i].primitives[j].idx_count, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,32 +5,65 @@
|
||||||
#include "transform.h"
|
#include "transform.h"
|
||||||
#include "sokol/sokol_gfx.h"
|
#include "sokol/sokol_gfx.h"
|
||||||
#include "gameobject.h"
|
#include "gameobject.h"
|
||||||
|
#include "anim.h"
|
||||||
|
#include "texture.h"
|
||||||
|
|
||||||
extern HMM_Vec3 eye;
|
extern HMM_Vec3 eye;
|
||||||
|
|
||||||
typedef struct material {
|
typedef struct material {
|
||||||
|
texture *diffuse;
|
||||||
|
texture *metalrough;
|
||||||
|
float metal;
|
||||||
|
float rough;
|
||||||
|
texture *normal;
|
||||||
|
float nrm;
|
||||||
|
texture *occlusion;
|
||||||
|
float occl;
|
||||||
|
texture *emissive;
|
||||||
|
HMM_Vec3 emis;
|
||||||
} material;
|
} material;
|
||||||
|
|
||||||
struct model;
|
struct model;
|
||||||
|
|
||||||
|
typedef struct primitive {
|
||||||
|
sg_bindings bind;
|
||||||
|
uint32_t idx_count;
|
||||||
|
} primitive;
|
||||||
|
|
||||||
/* A single mesh */
|
/* A single mesh */
|
||||||
typedef struct mesh {
|
typedef struct mesh {
|
||||||
sg_bindings bind; /* Encapsulates material, norms, etc */
|
primitive *primitives;
|
||||||
uint32_t idx_count;
|
HMM_Mat4 *m;
|
||||||
} mesh;
|
} mesh;
|
||||||
|
|
||||||
|
typedef struct joint {
|
||||||
|
int me;
|
||||||
|
struct joint *children;
|
||||||
|
} joint_t;
|
||||||
|
|
||||||
|
typedef struct md5joint {
|
||||||
|
struct md5joint *parent;
|
||||||
|
HMM_Vec4 pos;
|
||||||
|
HMM_Quat rot;
|
||||||
|
HMM_Vec4 scale;
|
||||||
|
HMM_Mat4 t;
|
||||||
|
} md5joint;
|
||||||
|
|
||||||
|
typedef struct skin {
|
||||||
|
md5joint **joints;
|
||||||
|
HMM_Mat4 *invbind;
|
||||||
|
HMM_Mat4 binds[50]; /* binds = joint * invbind */
|
||||||
|
md5joint *root;
|
||||||
|
} skin;
|
||||||
|
|
||||||
/* A collection of meshes which create a full figure */
|
/* A collection of meshes which create a full figure */
|
||||||
typedef struct model {
|
typedef struct model {
|
||||||
struct mesh *meshes;
|
struct mesh *meshes;
|
||||||
HMM_Mat4 matrix;
|
md5joint *nodes;
|
||||||
|
skin skin;
|
||||||
|
struct animation anim;
|
||||||
} model;
|
} model;
|
||||||
|
|
||||||
typedef struct bone {
|
|
||||||
transform3d t;
|
|
||||||
struct bone *children;
|
|
||||||
} bone;
|
|
||||||
|
|
||||||
/* Make a Model struct */
|
/* Make a Model struct */
|
||||||
struct model *model_make(const char *path);
|
struct model *model_make(const char *path);
|
||||||
void model_free(model *m);
|
void model_free(model *m);
|
||||||
|
|
|
@ -189,6 +189,12 @@
|
||||||
#define HMM_MOD(a, m) (((a) % (m)) >= 0 ? ((a) % (m)) : (((a) % (m)) + (m)))
|
#define HMM_MOD(a, m) (((a) % (m)) >= 0 ? ((a) % (m)) : (((a) % (m)) + (m)))
|
||||||
#define HMM_SQUARE(x) ((x) * (x))
|
#define HMM_SQUARE(x) ((x) * (x))
|
||||||
|
|
||||||
|
#define HMMFMT_VEC3 "[%g,%g,%g]"
|
||||||
|
#define HMMPRINT_VEC3(vec) vec.x, vec.y, vec.z
|
||||||
|
|
||||||
|
#define FMT_VEC4 "[%g,%g,%g,%g]"
|
||||||
|
#define PRINT_VEC4(vec) vec.x, vec.y, vec.z, vec.w
|
||||||
|
|
||||||
typedef union HMM_Vec2 {
|
typedef union HMM_Vec2 {
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
@ -291,8 +297,11 @@ typedef union HMM_Quat {
|
||||||
|
|
||||||
float W;
|
float W;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct {float x, y, z, w;};
|
||||||
|
|
||||||
float Elements[4];
|
float Elements[4];
|
||||||
|
float e[4];
|
||||||
|
|
||||||
#ifdef HANDMADE_MATH__USE_SSE
|
#ifdef HANDMADE_MATH__USE_SSE
|
||||||
__m128 SSE;
|
__m128 SSE;
|
||||||
|
@ -366,6 +375,7 @@ typedef union HMM_Vec4 {
|
||||||
};
|
};
|
||||||
|
|
||||||
HMM_Quat quat;
|
HMM_Quat quat;
|
||||||
|
struct {float x, y, z, w; };
|
||||||
|
|
||||||
float Elements[4];
|
float Elements[4];
|
||||||
float e[4];
|
float e[4];
|
||||||
|
@ -376,6 +386,8 @@ typedef union HMM_Vec4 {
|
||||||
|
|
||||||
} HMM_Vec4;
|
} HMM_Vec4;
|
||||||
|
|
||||||
|
static const HMM_Vec4 v4zero = {0,0,0,0};
|
||||||
|
|
||||||
typedef union HMM_Mat2 {
|
typedef union HMM_Mat2 {
|
||||||
float Elements[2][2];
|
float Elements[2][2];
|
||||||
HMM_Vec2 Columns[2];
|
HMM_Vec2 Columns[2];
|
||||||
|
@ -392,7 +404,7 @@ typedef union HMM_Mat4 {
|
||||||
float Elements[4][4];
|
float Elements[4][4];
|
||||||
HMM_Vec4 Columns[4];
|
HMM_Vec4 Columns[4];
|
||||||
float e[4][4];
|
float e[4][4];
|
||||||
|
float em[16];
|
||||||
} HMM_Mat4;
|
} HMM_Mat4;
|
||||||
|
|
||||||
|
|
||||||
|
@ -1709,14 +1721,6 @@ static inline HMM_Mat4 HMM_Translate(HMM_Vec3 Translation) {
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline HMM_Mat4 *HMM_Translate_p(HMM_Mat4 *m, HMM_Vec3 t)
|
|
||||||
{
|
|
||||||
m->Elements[3][0] += t.X;
|
|
||||||
m->Elements[3][1] += t.Y;
|
|
||||||
m->Elements[3][2] += t.Z;
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline HMM_Mat4 HMM_InvTranslate(HMM_Mat4 TranslationMatrix) {
|
static inline HMM_Mat4 HMM_InvTranslate(HMM_Mat4 TranslationMatrix) {
|
||||||
|
|
||||||
HMM_Mat4 Result = TranslationMatrix;
|
HMM_Mat4 Result = TranslationMatrix;
|
||||||
|
@ -1771,14 +1775,6 @@ static inline HMM_Mat4 HMM_Scale(HMM_Vec3 Scale) {
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline HMM_Mat4 *HMM_Scale_p(HMM_Mat4 *m, HMM_Vec3 s)
|
|
||||||
{
|
|
||||||
m->Elements[0][0] *= s.X;
|
|
||||||
m->Elements[1][1] *= s.Y;
|
|
||||||
m->Elements[2][2] *= s.Z;
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline HMM_Mat4 HMM_InvScale(HMM_Mat4 ScaleMatrix) {
|
static inline HMM_Mat4 HMM_InvScale(HMM_Mat4 ScaleMatrix) {
|
||||||
|
|
||||||
HMM_Mat4 Result = ScaleMatrix;
|
HMM_Mat4 Result = ScaleMatrix;
|
||||||
|
@ -2148,6 +2144,38 @@ static inline HMM_Mat4 HMM_QToM4(HMM_Quat Left) {
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline HMM_Mat4 HMM_M4TRS(HMM_Vec3 t, HMM_Quat q, HMM_Vec3 s)
|
||||||
|
{
|
||||||
|
HMM_Mat4 T = HMM_Translate(t);
|
||||||
|
HMM_Mat4 R = HMM_QToM4(q);
|
||||||
|
HMM_Mat4 S = HMM_Scale(s);
|
||||||
|
HMM_Mat4 l;
|
||||||
|
float *lm = (float*)&l;
|
||||||
|
|
||||||
|
lm[0] = (1 - 2 * q.y*q.y - 2 * q.z*q.z) * s.x;
|
||||||
|
lm[1] = (2 * q.x*q.y + 2 * q.z*q.w) * s.x;
|
||||||
|
lm[2] = (2 * q.x*q.z - 2 * q.y*q.w) * s.x;
|
||||||
|
lm[3] = 0.f;
|
||||||
|
|
||||||
|
lm[4] = (2 * q.x*q.y - 2 * q.z*q.w) * s.y;
|
||||||
|
lm[5] = (1 - 2 * q.x*q.x - 2 * q.z*q.z) * s.y;
|
||||||
|
lm[6] = (2 * q.y*q.z + 2 * q.x*q.w) * s.y;
|
||||||
|
lm[7] = 0.f;
|
||||||
|
|
||||||
|
lm[8] = (2 * q.x*q.z + 2 * q.y*q.w) * s.z;
|
||||||
|
lm[9] = (2 * q.y*q.z - 2 * q.x*q.w) * s.z;
|
||||||
|
lm[10] = (1 - 2 * q.x*q.x - 2 * q.y*q.y) * s.z;
|
||||||
|
lm[11] = 0.f;
|
||||||
|
|
||||||
|
lm[12] = t.x;
|
||||||
|
lm[13] = t.y;
|
||||||
|
lm[14] = t.z;
|
||||||
|
lm[15] = 1.f;
|
||||||
|
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// This method taken from Mike Day at Insomniac Games.
|
// This method taken from Mike Day at Insomniac Games.
|
||||||
// https://d3cw3dd2w32x2b.cloudfront.net/wp-content/uploads/2015/01/matrix-to-quat.pdf
|
// https://d3cw3dd2w32x2b.cloudfront.net/wp-content/uploads/2015/01/matrix-to-quat.pdf
|
||||||
//
|
//
|
||||||
|
|
|
@ -2,40 +2,39 @@
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "stb_ds.h"
|
#include "stb_ds.h"
|
||||||
|
|
||||||
void sampler_add(sampler *s, float time, HMM_Vec4 val)
|
void animation_run(struct animation *anim, float now)
|
||||||
{
|
{
|
||||||
arrput(s->times,time);
|
float elapsed = now - anim->time;
|
||||||
arrput(s->data,val);
|
elapsed = fmod(elapsed,2);
|
||||||
|
if (!anim->channels) return;
|
||||||
|
|
||||||
|
for (int i = 0; i < arrlen(anim->channels); i++) {
|
||||||
|
struct anim_channel *ch = anim->channels+i;
|
||||||
|
HMM_Vec4 s = sample_sampler(ch->sampler, elapsed);
|
||||||
|
*(ch->target) = s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HMM_Vec4 sample_cubicspline(sampler *sampler, float t, int prev, int next)
|
HMM_Vec4 sample_cubicspline(sampler *sampler, float t, int prev, int next)
|
||||||
{
|
{
|
||||||
float t2 = t*t;
|
return (HMM_Vec4)HMM_SLerp(HMM_QV4(sampler->data[prev]), t, HMM_QV4(sampler->data[next]));
|
||||||
float t3 = t2*t;
|
|
||||||
float td = sampler->times[next]-sampler->times[prev];
|
|
||||||
|
|
||||||
HMM_Vec4 v = HMM_MulV4F(sampler->data[prev*3+1], (2*t3-3*t2+1));
|
|
||||||
v = HMM_AddV4(v, HMM_MulV4F(sampler->data[prev*3+2], td*(t3-2*t2+t)));
|
|
||||||
v = HMM_AddV4(v, HMM_MulV4F(sampler->data[next*3+1], 3*t2-2*t3));
|
|
||||||
v = HMM_AddV4(v, HMM_MulV4F(sampler->data[next*3], td*(t3-t2)));
|
|
||||||
return v;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HMM_Vec4 sample_sampler(sampler *sampler, float time)
|
HMM_Vec4 sample_sampler(sampler *sampler, float time)
|
||||||
{
|
{
|
||||||
if (arrlen(sampler->data) == 0) return (HMM_Vec4){0,0,0,0};
|
if (arrlen(sampler->data) == 0) return v4zero;
|
||||||
if (arrlen(sampler->data) == 1) return sampler->data[0];
|
if (arrlen(sampler->data) == 1) return sampler->data[0];
|
||||||
int previous_time=0;
|
int previous_time=0;
|
||||||
int next_time=0;
|
int next_time=0;
|
||||||
|
|
||||||
for (int i = 1; i < arrlen(sampler->times); i++) {
|
for (int i = 1; i < arrlen(sampler->times); i++) {
|
||||||
if (time < sampler->times[i]) {
|
if (time < sampler->times[i]) {
|
||||||
previous_time = sampler->times[i-1];
|
previous_time = i-1;
|
||||||
next_time = sampler->times[i];
|
next_time = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float td = sampler->times[next_time]-sampler->times[previous_time];
|
float td = sampler->times[next_time]-sampler->times[previous_time];
|
||||||
float t = (time - sampler->times[previous_time])/td;
|
float t = (time - sampler->times[previous_time])/td;
|
||||||
|
|
||||||
|
|
|
@ -13,12 +13,6 @@ struct keyframe {
|
||||||
#define CUBICSPLINE 2
|
#define CUBICSPLINE 2
|
||||||
#define SLERP 3
|
#define SLERP 3
|
||||||
|
|
||||||
typedef struct samplerf {
|
|
||||||
float *times;
|
|
||||||
float *data;
|
|
||||||
int type;
|
|
||||||
} samplerf;
|
|
||||||
|
|
||||||
typedef struct sampler {
|
typedef struct sampler {
|
||||||
float *times;
|
float *times;
|
||||||
HMM_Vec4 *data;
|
HMM_Vec4 *data;
|
||||||
|
@ -26,6 +20,8 @@ typedef struct sampler {
|
||||||
} sampler;
|
} sampler;
|
||||||
|
|
||||||
struct anim_channel {
|
struct anim_channel {
|
||||||
|
HMM_Vec4 *target;
|
||||||
|
int comps;
|
||||||
sampler *sampler;
|
sampler *sampler;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -33,10 +29,10 @@ struct animation {
|
||||||
char *name;
|
char *name;
|
||||||
double time;
|
double time;
|
||||||
struct anim_channel *channels;
|
struct anim_channel *channels;
|
||||||
|
sampler *samplers;
|
||||||
};
|
};
|
||||||
|
|
||||||
void sampler_add(sampler *s, float time, HMM_Vec4 val);
|
void animation_run(struct animation *anim, float now);
|
||||||
HMM_Vec4 sample_sampler(sampler *sampler, float time);
|
HMM_Vec4 sample_sampler(sampler *sampler, float time);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -41,3 +41,6 @@
|
||||||
#define NANOSVGRAST_IMPLEMENTATION
|
#define NANOSVGRAST_IMPLEMENTATION
|
||||||
#include "nanosvg.h"
|
#include "nanosvg.h"
|
||||||
#include "nanosvgrast.h"
|
#include "nanosvgrast.h"
|
||||||
|
|
||||||
|
#define CGLTF_IMPLEMENTATION
|
||||||
|
#include "cgltf.h"
|
||||||
|
|
|
@ -92,7 +92,7 @@ emitter *make_emitter() {
|
||||||
|
|
||||||
e->life = 10;
|
e->life = 10;
|
||||||
e->tte = lerp(e->explosiveness, e->life/e->max, 0);
|
e->tte = lerp(e->explosiveness, e->life/e->max, 0);
|
||||||
sampler_add(&e->color, 0, (HMM_Vec4){1,1,1,1});
|
//sampler_add(&e->color, 0, (HMM_Vec4){1,1,1,1});
|
||||||
e->scale = 1;
|
e->scale = 1;
|
||||||
e->speed = 20;
|
e->speed = 20;
|
||||||
e->texture = NULL;
|
e->texture = NULL;
|
||||||
|
|
|
@ -58,7 +58,11 @@ transform2d mat2transform2d(HMM_Mat3 m)
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
HMM_Mat4 transform3d2mat(transform3d t) { return HMM_MulM4(HMM_Translate(t.pos), HMM_MulM4(HMM_QToM4(t.rotation), HMM_Scale(t.scale))); }
|
HMM_Mat4 transform3d2mat(transform3d t) {
|
||||||
|
return HMM_MulM4(HMM_Translate(t.pos),
|
||||||
|
HMM_MulM4(HMM_QToM4(t.rotation),
|
||||||
|
HMM_Scale(t.scale)));
|
||||||
|
}
|
||||||
|
|
||||||
transform3d mat2transform3d(HMM_Mat4 m)
|
transform3d mat2transform3d(HMM_Mat4 m)
|
||||||
{
|
{
|
||||||
|
|
|
@ -47,8 +47,6 @@ void main()
|
||||||
color = texture(sampler2D(image,smp), texcoords);
|
color = texture(sampler2D(image,smp), texcoords);
|
||||||
color *= fcolor;
|
color *= fcolor;
|
||||||
color.xyz = mix(color.xyz, femissive.xyz, femissive.a);
|
color.xyz = mix(color.xyz, femissive.xyz, femissive.a);
|
||||||
color.a = 1.0;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
|
@ -2,19 +2,26 @@
|
||||||
in vec3 a_pos;
|
in vec3 a_pos;
|
||||||
in vec2 a_tex_coords;
|
in vec2 a_tex_coords;
|
||||||
in vec4 a_norm;
|
in vec4 a_norm;
|
||||||
|
in vec4 a_weight;
|
||||||
|
in vec4 a_joint;
|
||||||
|
|
||||||
out vec2 tex_coords;
|
out vec2 tex_coords;
|
||||||
out vec3 normal;
|
out vec3 normal;
|
||||||
|
|
||||||
uniform vs_p {
|
uniform vs_p { uniform mat4 vp; };
|
||||||
uniform mat4 vp;
|
uniform vmodel { uniform mat4 model; };
|
||||||
uniform mat4 model;
|
|
||||||
};
|
uniform skinv { uniform mat4 bones[50]; };
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_Position = vp * model * vec4(a_pos,1.0);
|
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);
|
||||||
tex_coords = a_tex_coords;
|
tex_coords = a_tex_coords;
|
||||||
normal = a_norm.xyz;
|
normal = (skinm * vec4(a_norm.xyz*2-1,0)).xyz;
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@ -26,10 +33,14 @@ out vec4 color;
|
||||||
uniform texture2D diffuse;
|
uniform texture2D diffuse;
|
||||||
uniform sampler smp;
|
uniform sampler smp;
|
||||||
|
|
||||||
|
uniform lightf {
|
||||||
|
vec4 ambient;
|
||||||
|
};
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec3 lightDir = normalize(vec3(0.5f, 0.5f, 1.0f));
|
vec3 lightDir = normalize(vec3(0.5f, 0.5f, 1.0f));
|
||||||
float diff = max(dot(normal, lightDir), 0.0f);
|
float diff = max(dot(normal, lightDir), 0.0f);
|
||||||
color = texture(sampler2D(diffuse,smp),tex_coords)*diff;
|
color = texture(sampler2D(diffuse,smp),tex_coords) * ambient;
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue