From 6b28e60e3a8d06c532a391d283e74892b6317158 Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Thu, 30 Nov 2023 16:47:59 +0000 Subject: [PATCH] scene graph --- scripts/entity.js | 13 +- source/engine/2dphysics.c | 5 +- source/engine/2dphysics.h | 2 +- source/engine/3d/model.c | 8 +- source/engine/3d/model.h | 7 +- source/engine/3d/skybox.c | 1 - source/engine/HandmadeMath.h | 14 +- source/engine/camera.c | 22 --- source/engine/camera.h | 23 --- source/engine/freelist.h | 7 +- source/engine/gameobject.c | 281 +++++------------------------------ source/engine/gameobject.h | 83 ++++------- source/engine/jsffi.c | 14 +- source/engine/render.c | 1 - source/engine/sound/music.c | 1 - source/engine/sprite.c | 46 +----- source/engine/sprite.h | 8 +- source/engine/transform.c | 55 +++++-- source/engine/transform.h | 37 +++-- source/engine/yugine.c | 6 +- 20 files changed, 191 insertions(+), 443 deletions(-) delete mode 100644 source/engine/camera.c delete mode 100644 source/engine/camera.h diff --git a/scripts/entity.js b/scripts/entity.js index 5a2bf9a..488d60d 100644 --- a/scripts/entity.js +++ b/scripts/entity.js @@ -238,6 +238,7 @@ var gameobject = { this.level?.remove_obj(this); this.level = parent; + cmd(208,parent,this); function unique_name(list, obj) { var str = obj.toString().replaceAll('.', '_'); @@ -264,7 +265,7 @@ var gameobject = { delete this.objects[obj.toString()]; delete this[obj.toString()]; }, - + components: {}, objects: {}, level: undefined, @@ -525,10 +526,11 @@ var gameobject = { left() { return [-1,0].rotate(Math.deg2rad(this.angle));}, make(level, data) { -// level ??= Primum; + level ??= Primum; var obj = Object.create(this); obj.make = undefined; - obj.level = level; + + if (this.instances) this.instances.push(obj); @@ -567,6 +569,8 @@ var gameobject = { }; obj.ur = this.toString(); + + obj.reparent(level); cmd(113, obj.body, obj); // set the internal obj reference to this obj @@ -582,9 +586,6 @@ var gameobject = { if (this.objects) obj.make_objs(this.objects); - obj.level = undefined; - obj.reparent(level); - Object.hide(obj, 'ur','body', 'components', 'objects', '_ed', 'level', 'timers'); Object.dainty_assign(obj, this); diff --git a/source/engine/2dphysics.c b/source/engine/2dphysics.c index 8dd96ad..a7451b9 100644 --- a/source/engine/2dphysics.c +++ b/source/engine/2dphysics.c @@ -220,8 +220,7 @@ void phys2d_circledel(struct phys2d_circle *c) { } void phys2d_dbgdrawcpcirc(cpCircleShape *c) { - HMM_Mat3 rt = mt_rt(go2t(shape2go(c))); - HMM_Vec2 pos = mat_t_pos(rt, (HMM_Vec2)cpCircleShapeGetOffset(c)); + HMM_Vec2 pos = mat_t_pos(t_go2world(shape2go(c)), (HMM_Vec2)cpCircleShapeGetOffset(c)); float radius = cpCircleShapeGetRadius(c); struct rgba color = shape_color(c); float seglen = cpShapeGetSensor(c) ? 5 : -1; @@ -377,7 +376,7 @@ void phys2d_dbgdrawpoly(struct phys2d_poly *poly) { if (arrlen(poly->points) >= 3) { int n = cpPolyShapeGetCount(poly->shape.shape); HMM_Vec2 points[n]; - HMM_Mat3 rt = mt_rt(go2t(shape2go(poly->shape.shape))); + HMM_Mat3 rt = t_go2world(shape2go(poly->shape.shape)); for (int i = 0; i < n; i++) points[i] = mat_t_pos(rt, (HMM_Vec2)cpPolyShapeGetVert(poly->shape.shape, i)); diff --git a/source/engine/2dphysics.h b/source/engine/2dphysics.h index 7f95744..27d145f 100644 --- a/source/engine/2dphysics.h +++ b/source/engine/2dphysics.h @@ -4,6 +4,7 @@ #include "script.h" #include #include "render.h" +#include "transform.h" struct gameobject; @@ -11,7 +12,6 @@ extern float phys2d_gravity; extern int physOn; extern cpSpace *space; - extern struct rgba color_white; extern struct rgba color_black; diff --git a/source/engine/3d/model.c b/source/engine/3d/model.c index 7863e4f..2af1d90 100644 --- a/source/engine/3d/model.c +++ b/source/engine/3d/model.c @@ -48,12 +48,6 @@ struct bone_weights { char b4; }; -struct bone { - HMM_Vec3 pos; - HMM_Quat rot; - HMM_Vec3 scale; -}; - struct mesh_v { HMM_Vec3 pos; struct uv_n uv; @@ -345,7 +339,7 @@ void draw_drawmodel(struct drawmodel *dm) { if (!dm->model) return; struct gameobject *go = id2go(dm->go); - HMM_Mat4 rst = m4_rst(go2t3(go)); + HMM_Mat4 rst = t3d_go2world(go); draw_model(dm->model, rst); } diff --git a/source/engine/3d/model.h b/source/engine/3d/model.h index 11f575c..78fb72e 100644 --- a/source/engine/3d/model.h +++ b/source/engine/3d/model.h @@ -2,7 +2,7 @@ #define MODEL_H #include "HandmadeMath.h" - +#include "transform.h" #include "sokol/sokol_gfx.h" extern HMM_Vec3 eye; @@ -26,6 +26,11 @@ struct drawmodel { int go; }; +typedef struct bone { + transform3d t; + struct bone *children; +} bone; + /* Get the model at a path, or create and return if it doesn't exist */ struct model *GetExistingModel(const char *path); diff --git a/source/engine/3d/skybox.c b/source/engine/3d/skybox.c index 27217d4..8117c62 100644 --- a/source/engine/3d/skybox.c +++ b/source/engine/3d/skybox.c @@ -1,6 +1,5 @@ #include "skybox.h" -#include "camera.h" #include "shader.h" #include #include diff --git a/source/engine/HandmadeMath.h b/source/engine/HandmadeMath.h index 4fd8394..49f418b 100644 --- a/source/engine/HandmadeMath.h +++ b/source/engine/HandmadeMath.h @@ -1181,9 +1181,9 @@ static inline HMM_Mat3 HMM_DivM3F(HMM_Mat3 Matrix, float Scalar) { return Result; } -static inline HMM_Mat3 HMM_ScaleM3(HMM_Vec2 Scale) { +static inline HMM_Mat2 HMM_ScaleM2(HMM_Vec2 Scale) { - HMM_Mat3 Result = HMM_M3D(1.0f); + HMM_Mat2 Result = HMM_M2D(1.0f); Result.Elements[0][0] = Scale.X; Result.Elements[1][1] = Scale.Y; @@ -1200,6 +1200,16 @@ static inline float HMM_DeterminantM3(HMM_Mat3 Matrix) { return HMM_DotV3(Cross.Columns[2], Matrix.Columns[2]); } +static inline HMM_Mat3 HMM_M2BasisPos(HMM_Mat2 basis, HMM_Vec2 pos) +{ + HMM_Mat3 m; + m.Columns[0].XY = basis.Columns[0]; + m.Columns[1].XY = basis.Columns[1]; + m.Columns[2].XY = pos; + m.Columns[2].Z = 1; + return m; +} + static inline HMM_Mat3 HMM_InvGeneralM3(HMM_Mat3 Matrix) { HMM_Mat3 Cross; diff --git a/source/engine/camera.c b/source/engine/camera.c deleted file mode 100644 index 714e24e..0000000 --- a/source/engine/camera.c +++ /dev/null @@ -1,22 +0,0 @@ -#include "camera.h" - -#include "gameobject.h" -#include "input.h" - -const float CAMERA_MINSPEED = 1.f; -const float CAMERA_MAXSPEED = 300.f; -const float CAMERA_ROTATESPEED = 6.f; - -void cam_goto_object(struct mCamera *cam, struct mTransform *transform) { - cam->transform.pos = HMM_SubV3(transform->pos, HMM_MulV3F(trans_forward(transform), 10.0)); -} - -void cam_inverse_goto(struct mCamera *cam, struct mTransform *transform) { - transform->pos = HMM_AddV3(cam->transform.pos, HMM_MulV3F(trans_forward(&cam->transform), 10.0)); -} - -HMM_Mat4 getviewmatrix(const struct mCamera *const camera) -{ - HMM_Vec3 lookvec = HMM_AddV3(camera->transform.pos, trans_forward(&camera->transform.rotation)); - return HMM_LookAt_RH(camera->transform.pos, lookvec, vY); -} diff --git a/source/engine/camera.h b/source/engine/camera.h deleted file mode 100644 index 2f7226e..0000000 --- a/source/engine/camera.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef CAMERA_H -#define CAMERA_H - -#include "transform.h" - -extern const float CAMERA_MINSPEED; -extern const float CAMERA_MAXSPEED; -extern const float CAMERA_ROTATESPEED; - -struct mCamera { - struct mTransform transform; - float speed; - float speedMult; - HMM_Vec3 frame_move; -}; - -void camera_2d_update(struct mCamera *camera, float deltaT); - -HMM_Mat4 getviewmatrix(const struct mCamera *const camera); -void cam_goto_object(struct mCamera *cam, struct mTransform *transform); -void cam_inverse_goto(struct mCamera *cam, struct mTransform *transform); - -#endif diff --git a/source/engine/freelist.h b/source/engine/freelist.h index 3b8a4b6..ac899a7 100644 --- a/source/engine/freelist.h +++ b/source/engine/freelist.h @@ -9,6 +9,7 @@ struct freelistheader { unsigned int first; unsigned int len; + unsigned int count; }; #define freelist_header(p) ((struct freelistheader*)p-1) @@ -17,6 +18,7 @@ static inline void *freelist_make(struct freelistheader *list, size_t elemsize, list = malloc(elemsize*n*sizeof(struct freelistheader)); list->first = 0; list->len = n; + list->count = 0; return list+1; } @@ -30,9 +32,10 @@ static inline unsigned int freelist_check(struct freelistheader *h, void *data, #define freelist_size(p,l) do{p = freelist_make(p,sizeof(*p),l); for(int i = 0; i < l; i++) { p[i].next = i+1; }}while(0) #define freelist_len(p) (freelist_header(p)->len) #define freelist_first(p) (freelist_header(p)->first) -#define freelist_grab(i,p) do{i=freelist_header(p)->first; freelist_header(p)->first = p[i].next; p[i].next = -1;}while(0) -#define freelist_kill(p,i) do{p[i].next = freelist_first(p);freelist_first(p)=i;}while(0) +#define freelist_grab(i,p) do{i=freelist_header(p)->first; freelist_header(p)->first = p[i].next; p[i].next = -1;freelist_header(p)->count++;}while(0) +#define freelist_kill(p,i) do{p[i].next = freelist_first(p);freelist_first(p)=i;freelist_header(p)->count--;}while(0) #define freelist_free(p) (free(freelist_header(p))) +#define freelist_count(p) (freelist_header(p)->count) struct link_header { diff --git a/source/engine/gameobject.c b/source/engine/gameobject.c index 04c721a..e822f08 100644 --- a/source/engine/gameobject.c +++ b/source/engine/gameobject.c @@ -11,20 +11,11 @@ #include #include #include "debugdraw.h" +#include "freelist.h" #include "stb_ds.h" struct gameobject *gameobjects = NULL; -static int first = -1; - -const int nameBuf[MAXNAME] = {0}; -const int prefabNameBuf[MAXNAME] = {0}; - -struct gameobject *get_gameobject_from_id(int id) { - if (id < 0) return NULL; - - return &gameobjects[id]; -} struct gameobject *id2go(int id) { if (id < 0) return NULL; @@ -32,9 +23,7 @@ struct gameobject *id2go(int id) { return &gameobjects[id]; } -int body2id(cpBody *body) { - return (int)cpBodyGetUserData(body); -} +int body2id(cpBody *body) { return (int)cpBodyGetUserData(body); } cpBody *id2body(int id) { struct gameobject *go = id2go(id); @@ -61,56 +50,15 @@ HMM_Vec2 go2pos(struct gameobject *go) return (HMM_Vec2){p.x, p.y}; } -float go2angle(struct gameobject *go) -{ - return cpBodyGetAngle(go->body); -} - -transform2d mat2transform2d(HMM_Mat3 mat) -{ - -} - -HMM_Mat3 mt_t(transform2d t) -{ - HMM_Mat3 p = HMM_M3D(1); - p.Columns[2].X = t.pos.X; - p.Columns[2].Y = t.pos.Y; - return p; -} - -HMM_Mat3 mt_s(transform2d t) -{ - HMM_Mat3 s = HMM_M3D(1); - s.Columns[0].X = t.scale.X; - s.Columns[1].Y = t.scale.Y; - return s; -} - -HMM_Mat3 mt_r(transform2d t) -{ - HMM_Mat3 r = HMM_M3D(1); - r.Columns[0] = (HMM_Vec3){cos(t.angle), sin(t.angle), 0}; - r.Columns[1] = (HMM_Vec3){-sin(t.angle), cos(t.angle), 0}; - return r; -} - -HMM_Mat3 transform2d2mat(transform2d t) -{ - return HMM_MulM3(mt_t(t), HMM_MulM3(mt_r(t), mt_s(t))); -} - -transform3d mat2transform3d(HMM_Mat4 mat) -{ - -} +float go2angle(struct gameobject *go) { return cpBodyGetAngle(go->body); } transform3d go2t3(gameobject *go) { transform3d t; HMM_Vec2 p = go2pos(go); + t.pos.X = p.X; t.pos.Y = p.Y; - t.pos.X = p.X; + t.pos.Z = go->drawlayer; t.scale = go->scale; t.scale.Z = go->scale.X; t.rotation = HMM_QFromAxisAngle_RH(vFWD, go2angle(go)); @@ -119,105 +67,18 @@ transform3d go2t3(gameobject *go) return t; } -HMM_Mat4 m4_t(transform3d t) -{ - return HMM_Translate(t.pos); -} +HMM_Vec2 go2world(struct gameobject *go, HMM_Vec2 pos) { return mat_t_pos(t_go2world(go), pos); } -HMM_Mat4 m4_s(transform3d t) -{ - return HMM_Scale(t.scale); -} +HMM_Vec2 world2go(struct gameobject *go, HMM_Vec2 pos) { return mat_t_pos(t_world2go(go), pos); } -HMM_Mat4 m4_r(transform3d t) -{ - return HMM_QToM4(t.rotation); -} +HMM_Vec2 goscale(struct gameobject *go, HMM_Vec2 pos) { return HMM_MulV2(go->scale.XY, pos); } -HMM_Mat4 m4_st(transform3d t) -{ - return HMM_MulM4(m4_t(t), m4_s(t)); -} +HMM_Mat3 t_go2world(struct gameobject *go) { return transform2d2mat(go2t(go)); } -HMM_Mat4 m4_rt(transform3d t) -{ - return HMM_MulM4(m4_t(t), m4_r(t)); -} - -HMM_Mat4 m4_rst(transform3d t) -{ - return HMM_MulM4(m4_st(t), m4_r(t)); -} - -HMM_Mat4 transform3d2mat(transform3d t) -{ - return m4_rst(t); -} - -HMM_Mat3 mt_rst(transform2d t) -{ - return transform2d2mat(t); -} - -HMM_Mat3 mt_st(transform2d t) -{ - return HMM_MulM3(mt_t(t), mt_s(t)); -} - -HMM_Mat3 mt_rt(transform2d t) -{ - return HMM_MulM3(mt_t(t), mt_r(t)); -} - -HMM_Vec2 go2world(struct gameobject *go, HMM_Vec2 pos) -{ - HMM_Vec2 v = HMM_MulM3V3(t_go2world(go), (HMM_Vec3){pos.X, pos.Y, 1.0}).XY; - return v; -} - -HMM_Vec2 world2go(struct gameobject *go, HMM_Vec2 pos) -{ - return HMM_MulM3V3(t_world2go(go), (HMM_Vec3){pos.X, pos.Y, 1.0}).XY; -} - -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_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[4] = (HMM_Vec4){0,0,0,1}; - return mat3_t_pos(m, dir); -} - - -HMM_Vec2 goscale(struct gameobject *go, HMM_Vec2 pos) -{ - return HMM_MulV2(go->scale.XY, pos); -} - -HMM_Mat3 t_go2world(struct gameobject *go) -{ - return transform2d2mat(go2t(go)); -} - -HMM_Mat3 t_world2go(struct gameobject *go) -{ - return HMM_InvGeneralM3(transform2d2mat(go2t(go))); -} +HMM_Mat3 t_world2go(struct gameobject *go) { return HMM_InvGeneralM3(t_go2world(go)); } +HMM_Mat4 t3d_go2world(struct gameobject *go) { return transform3d2mat(go2t3(go)); } +HMM_Mat4 t3d_world2go(struct gameobject *go) { return HMM_InvGeneralM4(t3d_go2world(go)); } int pos2gameobject(HMM_Vec2 pos) { cpShape *hit = phys2d_query_pos(pos.cp); @@ -237,19 +98,6 @@ int pos2gameobject(HMM_Vec2 pos) { return -1; } -int id_from_gameobject(struct gameobject *go) { - for (int i = 0; i < arrlen(gameobjects); i++) { - if (&gameobjects[i] == go) return i; - } - - return -1; -} - -void gameobject_set_sensor(int id, int sensor) { - id2go(id)->sensor = sensor; - gameobject_apply(id2go(id)); -} - transform2d go2t(gameobject *go) { transform2d t; @@ -262,17 +110,10 @@ transform2d go2t(gameobject *go) } int go2id(struct gameobject *go) { - return id_from_gameobject(go); -} + for (int i = 0; i < arrlen(gameobjects); i++) + if (&gameobjects[i] == go) return i; -uint32_t go2category(struct gameobject *go) -{ - return 0; -} - -uint32_t go2mask(struct gameobject *go) -{ - return 0; + return -1; } unsigned int editor_cat = 1<<31; @@ -324,18 +165,6 @@ void gameobject_apply(struct gameobject *go) { } } -static void gameobject_setpickcolor(struct gameobject *go) { - /* - float r = ((go->editor.id & 0x000000FF) >> 0) / 255.f; - float g = ((go->editor.id & 0x0000FF00) >> 8) / 255.f; - float b = ((go->editor.id & 0x00FF0000) >> 16) / 255.f; - - go->editor.color[0] = r; - go->editor.color[1] = g; - go->editor.color[2] = b; - */ -} - static void velocityFn(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt) { struct gameobject *go = id2go((int)cpBodyGetUserData(body)); @@ -367,9 +196,9 @@ int MakeGameobject() { .maxangularvelocity = INFINITY, .mass = 1.f, .next = -1, - .sensor = 0, .drawlayer = 0, .shape_cbs = NULL, + .children = NULL, .gravity = 1, .cgravity = (HMM_Vec2){0,0}, .damping = NAN, @@ -383,20 +212,22 @@ int MakeGameobject() { go.body = cpSpaceAddBody(space, cpBodyNew(go.mass, 1.f)); cpBodySetVelocityUpdateFunc(go.body, velocityFn); - int retid; + int id; + if (!gameobjects) freelist_size(gameobjects,500); + freelist_grab(id, gameobjects); + cpBodySetUserData(go.body, (void*)id); + phys2d_setup_handlers(id); + gameobjects[id] = go; + return id; +} - if (first < 0) { - arrput(gameobjects, go); - retid = arrlast(gameobjects).id = arrlen(gameobjects) - 1; - } else { - retid = first; - first = id2go(first)->next; - *id2go(retid) = go; - } +void gameobject_traverse(struct gameobject *go, HMM_Mat4 p) +{ + HMM_Mat4 local = transform3d2mat(go2t3(go)); + go->world = HMM_MulM4(local, p); - cpBodySetUserData(go.body, (void *)retid); - phys2d_setup_handlers(retid); - return retid; + for (int i = 0; i < arrlen(go->children); i++) + gameobject_traverse(go->children[i], go->world); } void rm_body_shapes(cpBody *body, cpShape *shape, void *data) { @@ -423,19 +254,20 @@ void gameobject_clean(int id) { /* Really more of a "mark for deletion" ... */ void gameobject_delete(int id) { - id2go(id)->next = first; - JS_FreeValue(js, id2go(id)->ref); - first = id; + gameobject *go = id2go(id); + JS_FreeValue(js, go->ref); if (cpSpaceIsLocked(space)) arrpush(go_toclean, id); else gameobject_clean(id); + + dag_clip(go); + freelist_kill(gameobjects,id); } void gameobject_free(int id) { - YughWarn("FREED A GAMEOBJECT!!!"); if (id >= 0) gameobject_delete(id); } @@ -445,15 +277,6 @@ void gameobjects_cleanup() { gameobject_clean(go_toclean[i]); arrsetlen(go_toclean, 0); - - return; - - int clean = first; - - while (clean >= 0 && id2go(clean)->body) { - gameobject_clean(clean); - clean = id2go(clean)->next; - } } void gameobject_move(struct gameobject *go, HMM_Vec2 vec) { @@ -509,37 +332,3 @@ void gameobject_draw_debugs() { for (int i = 0; i < arrlen(gameobjects); i++) gameobject_draw_debug(i); } - -static struct { - struct gameobject go; - cpVect pos; - float angle; -} *saveobjects = NULL; - -void gameobject_saveall() { - arrfree(saveobjects); - arrsetlen(saveobjects, arrlen(gameobjects)); - - for (int i = 0; i < arrlen(gameobjects); i++) { - saveobjects[i].go = gameobjects[i]; - saveobjects[i].pos = cpBodyGetPosition(gameobjects[i].body); - saveobjects[i].angle = cpBodyGetAngle(gameobjects[i].body); - } -} - -void gameobject_loadall() { - YughInfo("N gameobjects: %d, N saved: %d", arrlen(gameobjects), arrlen(saveobjects)); - for (int i = 0; i < arrlen(saveobjects); i++) { - gameobjects[i] = saveobjects[i].go; - cpBodySetPosition(gameobjects[i].body, saveobjects[i].pos); - cpBodySetAngle(gameobjects[i].body, saveobjects[i].angle); - cpBodySetVelocity(gameobjects[i].body, cpvzero); - cpBodySetAngularVelocity(gameobjects[i].body, 0.f); - } - - arrfree(saveobjects); -} - -int gameobjects_saved() { - return arrlen(saveobjects); -} diff --git a/source/engine/gameobject.h b/source/engine/gameobject.h index c5bc471..987223f 100644 --- a/source/engine/gameobject.h +++ b/source/engine/gameobject.h @@ -8,39 +8,35 @@ #include #include "quickjs/quickjs.h" #include "HandmadeMath.h" +#include "transform.h" + +#define dag_rm(p,c) do{\ + for (int i = arrlen(p->children)-1; i--; i >=0) {\ + if (p->children[i] == c) { \ + arrdelswap(p->children,i);\ + c->parent=NULL;\ + break;\ +}}}while(0) + +#define dag_set(p,c) do{\ + arrpush(p->children,c);\ + if(c->parent) dag_rm(c->parent,c);\ + c->parent=p;\ +}while(0) + +#define dag_clip(p) do{\ + if (p->parent)\ + dag_rm(p->parent,p);\ +}while(0) struct shader; struct sprite; struct component; -typedef struct transform2d { - HMM_Vec2 pos; - HMM_Vec2 scale; - double angle; -} transform2d; - -transform2d mat2transform2d(HMM_Mat3 mat); -HMM_Mat3 transform2d2mat(transform2d t); - -typedef struct transform3d { - HMM_Vec3 pos; - HMM_Vec3 scale; - HMM_Quat rotation; -} transform3d; - -transform3d mat2transform3d(HMM_Mat4 mat); -HMM_Mat4 transform3d2mat(transform3d t); -HMM_Mat4 m4_t(transform3d t); -HMM_Mat4 m4_s(transform3d t); -HMM_Mat4 m4_r(transform3d t); -HMM_Mat4 m4_rt(transform3d t); -HMM_Mat4 m4_st(transform3d t); -HMM_Mat4 m4_rst(transform3d t); - typedef struct gameobject { cpBodyType bodytype; int next; - HMM_Vec3 scale; + HMM_Vec3 scale; /* local */ float mass; float f; /* friction */ float e; /* elasticity */ @@ -50,7 +46,6 @@ typedef struct gameobject { int gravity; HMM_Vec2 cgravity; float damping; - int sensor; unsigned int layer; cpShapeFilter filter; cpBody *body; /* NULL if this object is dead */ @@ -58,10 +53,12 @@ typedef struct gameobject { struct phys_cbs cbs; struct shape_cb *shape_cbs; JSValue ref; - HMM_Mat3 transform; struct gameobject *master; + HMM_Mat4 world; transform2d t; /* The local transformation of this object */ float drawlayer; + struct gameobject *parent; + struct gameobject **children; } gameobject; extern struct gameobject *gameobjects; @@ -72,42 +69,33 @@ void gameobject_delete(int id); void gameobject_free(int id); void gameobjects_cleanup(); -void gameobject_set_sensor(int id, int sensor); +void gameobject_traverse(struct gameobject *start, HMM_Mat4 p); -HMM_Vec2 go2pos(struct gameobject *go); -float go2angle(struct gameobject *go); transform2d go2t(gameobject *go); transform3d go2t3(gameobject *go); + HMM_Vec2 go2world(struct gameobject *go, HMM_Vec2 pos); HMM_Vec2 world2go(struct gameobject *go, HMM_Vec2 pos); HMM_Mat3 t_go2world(struct gameobject *go); HMM_Mat3 t_world2go(struct gameobject *go); +HMM_Mat4 t3d_go2world(struct gameobject *go); +HMM_Mat4 t3d_world2go(struct gameobject *go); + +HMM_Vec2 go2pos(struct gameobject *go); +float go2angle(struct gameobject *go); + HMM_Vec2 goscale(struct gameobject *go, HMM_Vec2 pos); HMM_Vec2 gotpos(struct gameobject *go, HMM_Vec2 pos); HMM_Mat3 mt_rst(transform2d t); -HMM_Mat3 mt_st(transform2d t); -HMM_Mat3 mt_rt(transform2d t); -/* Transform a position via the matrix */ -HMM_Vec2 mat_t_pos(HMM_Mat3 m, HMM_Vec2 pos); -/* Transform a direction via the matrix - does not take into account translation of matrix */ -HMM_Vec2 mat_t_dir(HMM_Mat3 m, HMM_Vec2 dir); - -HMM_Vec3 mat3_t_pos(HMM_Mat4 m, HMM_Vec3 pos); -HMM_Vec3 mat3_t_dir(HMM_Mat4 m, HMM_Vec3 dir); - -struct gameobject *get_gameobject_from_id(int id); struct gameobject *id2go(int id); -int id_from_gameobject(struct gameobject *go); int go2id(struct gameobject *go); int body2id(cpBody *body); cpBody *id2body(int id); int shape2gameobject(cpShape *shape); struct gameobject *shape2go(cpShape *shape); -uint32_t go2category(struct gameobject *go); -uint32_t go2mask(struct gameobject *go); void go_shape_apply(cpBody *body, cpShape *shape, struct gameobject *go); @@ -121,11 +109,4 @@ void gameobject_setpos(struct gameobject *go, cpVect vec); void gameobject_draw_debugs(); void gameobject_draw_debug(int go); - -void object_gui(struct gameobject *go); - -void gameobject_saveall(); -void gameobject_loadall(); -int gameobjects_saved(); - #endif diff --git a/source/engine/jsffi.c b/source/engine/jsffi.c index 2ef1cd4..0d6e460 100644 --- a/source/engine/jsffi.c +++ b/source/engine/jsffi.c @@ -360,7 +360,11 @@ int js_print_exception(JSValue v) JSValue duk_gui_img(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) { const char *img = JS_ToCString(js, argv[0]); - gui_draw_img(img, js2vec2(argv[1]), js2vec2(argv[2]), js2number(argv[3]), js2bool(argv[4]), js2vec2(argv[5]), 1.0, js2color(argv[6])); + transform2d t; + t.pos = js2vec2(argv[1]); + t.scale = js2vec2(argv[2]); + t.angle = js2number(argv[3]); + gui_draw_img(img, t, js2bool(argv[4]), js2vec2(argv[5]), 1.0, js2color(argv[6])); JS_FreeCString(js, img); return JS_UNDEFINED; } @@ -684,7 +688,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) case 37: if (!id2sprite(js2int(argv[1]))) break; - id2sprite(js2int(argv[1]))->pos = js2vec2(argv[2]); + id2sprite(js2int(argv[1]))->t.pos = js2vec2(argv[2]); break; case 38: @@ -821,7 +825,6 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) break; case 69: - gameobject_set_sensor(js2go(argv[1]), JS_ToBool(js, argv[2])); break; case 70: @@ -995,7 +998,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) break; case 111: - ret = vec2js(js2sprite(argv[1])->pos); + ret = vec2js(js2sprite(argv[1])->t.pos); break; case 112: @@ -1345,6 +1348,9 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) case 207: ret = dsp_node2js(dsp_fwd_delay(js2number(argv[1]), js2number(argv[2]))); break; + case 208: + dag_set(js2go(argv[1]), js2go(argv[2])); + break; } if (str) diff --git a/source/engine/render.c b/source/engine/render.c index 8514bd7..8201886 100644 --- a/source/engine/render.c +++ b/source/engine/render.c @@ -1,6 +1,5 @@ #include "render.h" -#include "camera.h" #include "config.h" #include "datastream.h" #include "debugdraw.h" diff --git a/source/engine/sound/music.c b/source/engine/sound/music.c index 9ec0848..c8ed15a 100644 --- a/source/engine/sound/music.c +++ b/source/engine/sound/music.c @@ -89,7 +89,6 @@ dsp_node *dsp_midi(const char *midi, tsf *sf) ms->time = 0.0; ms->midi = tml_load_memory(raw, rawlen); ms->sf = tsf_copy(sf); - free(midi); return make_node(ms, dsp_midi_fillbuf, dsp_midi_free); } diff --git a/source/engine/sprite.c b/source/engine/sprite.c index 9ecbbce..797035b 100644 --- a/source/engine/sprite.c +++ b/source/engine/sprite.c @@ -53,11 +53,10 @@ struct slice9_vert { }; int make_sprite(int go) { - YughWarn("Attaching sprite to gameobject %d", go); struct sprite sprite = { + .t = t2d_unit, .color = color_white, .emissive = {0,0,0,0}, - .size = {1.f, 1.f}, .tex = texture_loadfromfile(NULL), .go = go, .layer = 0, @@ -77,9 +76,7 @@ void sprite_delete(int id) { freelist_kill(sprites,id); } -void sprite_enabled(int id, int e) { - sprites[id].enabled = e; -} +void sprite_enabled(int id, int e) { sprites[id].enabled = e; } struct sprite *id2sprite(int id) { if (id < 0) return NULL; @@ -246,7 +243,6 @@ void tex_draw(struct Texture *tex, HMM_Mat3 m, struct glrect r, struct rgba colo } bind_sprite.fs.images[0] = tex->id; -// YughWarn("Draw sprite %s at %g, %g", tex_get_path(tex), sposes[0].X, sposes[0].Y); sg_append_buffer(bind_sprite.vertex_buffers[0], SG_RANGE_REF(verts)); sg_apply_bindings(&bind_sprite); @@ -259,14 +255,13 @@ void sprite_draw(struct sprite *sprite) { struct gameobject *go = id2go(sprite->go); if (sprite->tex) { - transform2d t = go2t(id2go(sprite->go)); - HMM_Mat3 m = transform2d2mat(t); + HMM_Mat3 m = t_go2world(go); HMM_Mat3 ss = HMM_M3D(1); - ss.Columns[0].X = sprite->size.X * sprite->tex->width * st_s_w(sprite->frame); - ss.Columns[1].Y = sprite->size.Y * sprite->tex->height * st_s_h(sprite->frame); + ss.Columns[0].X = sprite->t.scale.X * sprite->tex->width * st_s_w(sprite->frame); + ss.Columns[1].Y = sprite->t.scale.Y * sprite->tex->height * st_s_h(sprite->frame); HMM_Mat3 ts = HMM_M3D(1); - ts.Columns[2] = (HMM_Vec3){sprite->pos.X, sprite->pos.Y, 1}; + ts.Columns[2] = (HMM_Vec3){sprite->t.pos.X, sprite->t.pos.Y, 1}; HMM_Mat3 sm = HMM_MulM3(ss, ts); m = HMM_MulM3(m, sm); @@ -280,14 +275,10 @@ void sprite_setanim(struct sprite *sprite, struct TexAnim *anim, int frame) { sprite->frame = anim->st_frames[frame]; } -void gui_draw_img(const char *img, HMM_Vec2 pos, HMM_Vec2 scale, float angle, int wrap, HMM_Vec2 wrapoffset, float wrapscale, struct rgba color) { +void gui_draw_img(const char *img, transform2d t, int wrap, HMM_Vec2 wrapoffset, float wrapscale, struct rgba color) { sg_apply_pipeline(pip_sprite); sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(hudproj)); struct Texture *tex = texture_loadfromfile(img); - transform2d t; - t.pos = pos; - t.angle = angle; - t.scale = scale; tex_draw(tex, transform2d2mat(t), tex_get_rect(tex), color, wrap, wrapoffset, wrapscale, (struct rgba){0,0,0,0}); } @@ -335,26 +326,3 @@ void slice9_draw(const char *img, HMM_Vec2 pos, HMM_Vec2 dimensions, struct rgba void sprite_setframe(struct sprite *sprite, struct glrect *frame) { sprite->frame = *frame; } -void video_draw(struct datastream *ds, HMM_Vec2 pos, HMM_Vec2 size, float rotate, struct rgba color) -{ -// shader_use(vid_shader); -/* - static mfloat_t model[16]; - memcpy(model, UNITMAT4, sizeof(UNITMAT4)); - mat4_translate_vec2(model, position); - mat4_scale_vec2(model, size); -*/ -// shader_setmat4(vid_shader, "model", model); -// shader_setvec3(vid_shader, "spriteColor", color); - /* - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, stream->texture_y); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, stream->texture_cb); - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, stream->texture_cr); - - // TODO: video bind VAO - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - */ -} diff --git a/source/engine/sprite.h b/source/engine/sprite.h index 24455b0..c595f2c 100644 --- a/source/engine/sprite.h +++ b/source/engine/sprite.h @@ -6,14 +6,13 @@ #include "texture.h" #include "HandmadeMath.h" #include "render.h" +#include "transform.h" struct datastream; struct gameobject; struct sprite { - HMM_Vec2 pos; - HMM_Vec2 size; - float rotation; + transform2d t; struct rgba color; struct rgba emissive; int go; /* id of gameobject */ @@ -35,11 +34,10 @@ void sprite_setanim(struct sprite *sprite, struct TexAnim *anim, int frame); void sprite_setframe(struct sprite *sprite, struct glrect *frame); void sprite_initialize(); void sprite_draw(struct sprite *sprite); -void video_draw(struct datastream *ds, HMM_Vec2 pos, HMM_Vec2 size, float rotate, struct rgba color); void sprite_draw_all(); unsigned int incrementAnimFrame(unsigned int interval, struct sprite *sprite); void sprite_flush(); -void gui_draw_img(const char *img, HMM_Vec2 pos, HMM_Vec2 scale, float angle, int wrap, HMM_Vec2 wrapoffset, float wrapscale, struct rgba color); +void gui_draw_img(const char *img, transform2d t, int wrap, HMM_Vec2 wrapoffset, float wrapscale, struct rgba color); #endif diff --git a/source/engine/transform.c b/source/engine/transform.c index 4cb9594..47abd1e 100644 --- a/source/engine/transform.c +++ b/source/engine/transform.c @@ -1,42 +1,67 @@ #include "transform.h" #include -struct mTransform MakeTransform(HMM_Vec3 pos, HMM_Quat rotation, float scale) -{ - struct mTransform newT = { - .pos = pos, - .rotation = rotation, - .scale = scale - }; - return newT; -} +const transform2d t2d_unit = { + .pos = {0,0}, + .scale = {1,1}, + .angle = 0 +}; -HMM_Vec3 trans_forward(const struct mTransform *const trans) +HMM_Vec3 trans_forward(const transform3d *const trans) { return HMM_QVRot(vFWD, trans->rotation); } -HMM_Vec3 trans_back(const struct mTransform *trans) +HMM_Vec3 trans_back(const transform3d *trans) { return HMM_QVRot(vBKWD, trans->rotation); } -HMM_Vec3 trans_up(const struct mTransform *trans) +HMM_Vec3 trans_up(const transform3d *trans) { return HMM_QVRot(vUP, trans->rotation); } -HMM_Vec3 trans_down(const struct mTransform *trans) +HMM_Vec3 trans_down(const transform3d *trans) { return HMM_QVRot(vDOWN, trans->rotation); } -HMM_Vec3 trans_right(const struct mTransform *trans) +HMM_Vec3 trans_right(const transform3d *trans) { return HMM_QVRot(vRIGHT, trans->rotation); } -HMM_Vec3 trans_left(const struct mTransform *trans) +HMM_Vec3 trans_left(const transform3d *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, 0}).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_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[4] = (HMM_Vec4){0,0,0,1}; + return mat3_t_pos(m, dir); +} + +HMM_Mat3 transform2d2mat(transform2d t) { + HMM_Mat2 m = HMM_MulM2(HMM_RotateM2(t.angle), HMM_ScaleM2(t.scale)); + return HMM_M2BasisPos(m, t.pos); +} + +HMM_Mat4 transform3d2mat(transform3d t) { return HMM_MulM4(HMM_Translate(t.pos), HMM_MulM4(HMM_QToM4(t.rotation), HMM_Scale(t.scale))); } diff --git a/source/engine/transform.h b/source/engine/transform.h index 0e4ff4a..68b42fd 100644 --- a/source/engine/transform.h +++ b/source/engine/transform.h @@ -3,23 +3,36 @@ #include "HandmadeMath.h" -struct mTransform { +typedef struct { HMM_Vec3 pos; + HMM_Vec3 scale; HMM_Quat rotation; - float scale; -}; +} transform3d; +typedef struct { + HMM_Vec2 pos; + HMM_Vec2 scale; + float angle; +} transform2d; -struct mTransform MakeTransform(HMM_Vec3 pos, HMM_Quat rotation, float scale); +extern const transform2d t2d_unit; -HMM_Vec3 trans_forward(const struct mTransform *const trans); -HMM_Vec3 trans_back(const struct mTransform *trans); -HMM_Vec3 trans_up(const struct mTransform *trans); -HMM_Vec3 trans_down(const struct mTransform *trans); -HMM_Vec3 trans_right(const struct mTransform *trans); -HMM_Vec3 trans_left(const struct mTransform *trans); -void trans_drawgui(struct mTransform *T); +HMM_Vec3 trans_forward(const transform3d *const trans); +HMM_Vec3 trans_back(const transform3d *trans); +HMM_Vec3 trans_up(const transform3d *trans); +HMM_Vec3 trans_down(const transform3d *trans); +HMM_Vec3 trans_right(const transform3d *trans); +HMM_Vec3 trans_left(const transform3d *trans); -//extern Serialize *make_transform(); +/* Transform a position via the matrix */ +HMM_Vec2 mat_t_pos(HMM_Mat3 m, HMM_Vec2 pos); +/* Transform a direction via the matrix - does not take into account translation of matrix */ +HMM_Vec2 mat_t_dir(HMM_Mat3 m, HMM_Vec2 dir); + +HMM_Vec3 mat3_t_pos(HMM_Mat4 m, HMM_Vec3 pos); +HMM_Vec3 mat3_t_dir(HMM_Mat4 m, HMM_Vec3 dir); + +HMM_Mat3 transform2d2mat(transform2d t); +HMM_Mat4 transform3d2mat(transform3d t); #endif diff --git a/source/engine/yugine.c b/source/engine/yugine.c index 8bd7262..01788f9 100644 --- a/source/engine/yugine.c +++ b/source/engine/yugine.c @@ -1,5 +1,4 @@ #include "yugine.h" -#include "camera.h" #include "font.h" #include "gameobject.h" #include "input.h" @@ -169,6 +168,11 @@ static void process_frame() /* Timers all update every frame - once per monitor refresh */ timer_update(elapsed, timescale); + /* Update at a high level:: + * Update scene graph + * + */ + if (sim_play == SIM_PLAY || sim_play == SIM_STEP) { if (stm_sec(stm_diff(frame_t, updatelast)) > updateMS) { double dt = stm_sec(stm_diff(frame_t, updatelast));