Some checks failed
Build and Deploy / package-dist (push) Has been cancelled
Build and Deploy / deploy-itch (push) Has been cancelled
Build and Deploy / deploy-gitea (push) Has been cancelled
Build and Deploy / build-linux (push) Has been cancelled
Build and Deploy / build-windows (CLANG64) (push) Has been cancelled
157 lines
4.0 KiB
C
157 lines
4.0 KiB
C
#include "transform.h"
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include "stb_ds.h"
|
|
|
|
static transform **dirties;
|
|
|
|
static transform model = {
|
|
.pos = {0,0,0},
|
|
.scale = {1,1,1},
|
|
.rotation = {0,0,0,1},
|
|
.cache = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1},
|
|
.gcache = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1},
|
|
.dirty = 0,
|
|
};
|
|
|
|
transform *make_transform()
|
|
{
|
|
transform *t = malloc(sizeof(transform));
|
|
*t = model;
|
|
t->jsparent = JS_UNDEFINED;
|
|
t->change_hook = JS_UNDEFINED;
|
|
return t;
|
|
}
|
|
|
|
void transform_free(JSRuntime *rt, transform *t) {
|
|
// JS_FreeValueRT(rt,t->self);
|
|
JS_FreeValueRT(rt,t->change_hook);
|
|
JS_FreeValueRT(rt,t->jsparent);
|
|
for (int i = 0; i < arrlen(t->jschildren); i++)
|
|
JS_FreeValueRT(rt,t->jschildren[i]);
|
|
|
|
arrfree(t->jschildren);
|
|
arrfree(t->children);
|
|
free(t);
|
|
|
|
for (int i = arrlen(dirties)-1; i >= 0; i--)
|
|
if (dirties[i] == t) arrdelswap(dirties, i);
|
|
}
|
|
|
|
void transform_clean(JSContext *js, transform *t)
|
|
{
|
|
if (!t->dirty) return;
|
|
t->dirty = 0;
|
|
t->cache = HMM_M4TRS(t->pos,t->rotation,t->scale);
|
|
if (t->parent)
|
|
t->gcache = HMM_MulM4(t->parent->gcache, t->cache);
|
|
else
|
|
t->gcache = t->cache;
|
|
|
|
for (int i = 0; i < arrlen(t->children); i++) {
|
|
t->children[i]->dirty = 1;
|
|
transform_clean(js, t->children[i]);
|
|
}
|
|
|
|
if (!JS_IsUndefined(t->change_hook)) {
|
|
JSValue ret = JS_Call(js, t->change_hook, JS_DupValue(js,t->self), 0, NULL);
|
|
JS_FreeValue(js,ret);
|
|
}
|
|
}
|
|
|
|
void clean_all(JSContext *js)
|
|
{
|
|
for (int i = 0; i < arrlen(dirties); i++)
|
|
transform_clean(js, dirties[i]);
|
|
|
|
arrsetlen(dirties,0);
|
|
}
|
|
|
|
void transform_move(transform *t, HMM_Vec3 v)
|
|
{
|
|
t->pos = HMM_AddV3(t->pos, v);
|
|
transform_apply(t);
|
|
}
|
|
|
|
HMM_Vec3 transform_direction(transform *t, HMM_Vec3 dir)
|
|
{
|
|
return HMM_QVRot(dir, t->rotation);
|
|
}
|
|
|
|
HMM_Vec3 trans_forward(const transform *const trans) { return HMM_QVRot(vFWD, trans->rotation); }
|
|
HMM_Vec3 trans_back(const transform *trans) { return HMM_QVRot(vBKWD, trans->rotation); }
|
|
HMM_Vec3 trans_up(const transform *trans) { return HMM_QVRot(vUP, trans->rotation); }
|
|
HMM_Vec3 trans_down(const transform *trans) { return HMM_QVRot(vDOWN, trans->rotation); }
|
|
HMM_Vec3 trans_right(const transform *trans) { return HMM_QVRot(vRIGHT, trans->rotation); }
|
|
HMM_Vec3 trans_left(const transform *trans) { return HMM_QVRot(vLEFT, trans->rotation); }
|
|
|
|
HMM_Vec2 mat_t_pos(HMM_Mat3 m, HMM_Vec2 pos) { return HMM_MulM3V3(m, (HMM_Vec3){pos.x, pos.y, 1}).xy; }
|
|
|
|
HMM_Vec2 mat_t_dir(HMM_Mat3 m, HMM_Vec2 dir)
|
|
{
|
|
m.Columns[2] = (HMM_Vec3){0,0,1};
|
|
return HMM_MulM3V3(m, (HMM_Vec3){dir.x, dir.y, 1}).XY;
|
|
}
|
|
|
|
HMM_Vec2 mat_up(HMM_Mat3 m) { return HMM_NormV2(m.Columns[1].XY); }
|
|
HMM_Vec2 mat_right(HMM_Mat3 m) { return HMM_NormV2(m.Columns[0].XY); }
|
|
float vec_angle(HMM_Vec2 a, HMM_Vec2 b) { return acos(HMM_DotV2(a,b)/(HMM_LenV2(a)*HMM_LenV2(b))); }
|
|
float vec_dirangle(HMM_Vec2 a, HMM_Vec2 b) { return atan2(b.x, b.y) - atan2(a.x, a.y); }
|
|
|
|
HMM_Vec3 mat3_t_pos(HMM_Mat4 m, HMM_Vec3 pos) { return HMM_MulM4V4(m, (HMM_Vec4){pos.X, pos.Y, pos.Z, 1}).XYZ; }
|
|
|
|
HMM_Vec3 mat3_t_dir(HMM_Mat4 m, HMM_Vec3 dir)
|
|
{
|
|
m.Columns[3] = (HMM_Vec4){0,0,0,1};
|
|
return mat3_t_pos(m, dir);
|
|
}
|
|
|
|
HMM_Mat4 transform2mat(transform *t)
|
|
{
|
|
return t->cache;
|
|
}
|
|
|
|
HMM_Mat3 transform2mat3(transform *t)
|
|
{
|
|
return HMM_M3TRS(t->pos.xy, t->rotation.x, t->scale.xy);
|
|
}
|
|
|
|
HMM_Mat4 transform2mat4_global(transform *t)
|
|
{
|
|
return t->gcache;
|
|
}
|
|
|
|
rect transform2rect(transform *t)
|
|
{
|
|
HMM_Mat4 m = t->gcache;
|
|
rect r = {0};
|
|
r.x = m.Columns[3].x;
|
|
r.y = m.Columns[3].y;
|
|
r.w = m.Columns[0].x;
|
|
r.h = m.Columns[1].y;
|
|
return r;
|
|
}
|
|
|
|
void transform_apply(transform *t)
|
|
{
|
|
t->dirty = 1;
|
|
arrput(dirties,t);
|
|
}
|
|
|
|
HMM_Quat angle2rotation(float angle)
|
|
{
|
|
return HMM_QFromAxisAngle_RH(vBKWD, angle);
|
|
}
|
|
|
|
transform mat2transform(HMM_Mat4 m)
|
|
{
|
|
transform t;
|
|
t.pos = m.Columns[3].xyz;
|
|
for (int i = 0; i < 2; i++)
|
|
t.scale.Elements[i] = HMM_LenV3(m.Columns[i].xyz);
|
|
// for (int i = 0; i < 2; i++)
|
|
// m.Columns[i].xyz = HMM_MulV3(m.Columns[i].xyz, t.scale.Elements[i]);
|
|
t.rotation = HMM_M4ToQ_RH(m);
|
|
return t;
|
|
}
|