scene graph

This commit is contained in:
John Alanbrook 2023-11-30 16:47:59 +00:00
parent 03fb016fbc
commit 6b28e60e3a
20 changed files with 191 additions and 443 deletions

View file

@ -238,6 +238,7 @@ var gameobject = {
this.level?.remove_obj(this); this.level?.remove_obj(this);
this.level = parent; this.level = parent;
cmd(208,parent,this);
function unique_name(list, obj) { function unique_name(list, obj) {
var str = obj.toString().replaceAll('.', '_'); var str = obj.toString().replaceAll('.', '_');
@ -264,7 +265,7 @@ var gameobject = {
delete this.objects[obj.toString()]; delete this.objects[obj.toString()];
delete this[obj.toString()]; delete this[obj.toString()];
}, },
components: {}, components: {},
objects: {}, objects: {},
level: undefined, level: undefined,
@ -525,10 +526,11 @@ var gameobject = {
left() { return [-1,0].rotate(Math.deg2rad(this.angle));}, left() { return [-1,0].rotate(Math.deg2rad(this.angle));},
make(level, data) { make(level, data) {
// level ??= Primum; level ??= Primum;
var obj = Object.create(this); var obj = Object.create(this);
obj.make = undefined; obj.make = undefined;
obj.level = level;
if (this.instances) if (this.instances)
this.instances.push(obj); this.instances.push(obj);
@ -567,6 +569,8 @@ var gameobject = {
}; };
obj.ur = this.toString(); obj.ur = this.toString();
obj.reparent(level);
cmd(113, obj.body, obj); // set the internal obj reference to this obj cmd(113, obj.body, obj); // set the internal obj reference to this obj
@ -582,9 +586,6 @@ var gameobject = {
if (this.objects) if (this.objects)
obj.make_objs(this.objects); obj.make_objs(this.objects);
obj.level = undefined;
obj.reparent(level);
Object.hide(obj, 'ur','body', 'components', 'objects', '_ed', 'level', 'timers'); Object.hide(obj, 'ur','body', 'components', 'objects', '_ed', 'level', 'timers');
Object.dainty_assign(obj, this); Object.dainty_assign(obj, this);

View file

@ -220,8 +220,7 @@ void phys2d_circledel(struct phys2d_circle *c) {
} }
void phys2d_dbgdrawcpcirc(cpCircleShape *c) { void phys2d_dbgdrawcpcirc(cpCircleShape *c) {
HMM_Mat3 rt = mt_rt(go2t(shape2go(c))); HMM_Vec2 pos = mat_t_pos(t_go2world(shape2go(c)), (HMM_Vec2)cpCircleShapeGetOffset(c));
HMM_Vec2 pos = mat_t_pos(rt, (HMM_Vec2)cpCircleShapeGetOffset(c));
float radius = cpCircleShapeGetRadius(c); float radius = cpCircleShapeGetRadius(c);
struct rgba color = shape_color(c); struct rgba color = shape_color(c);
float seglen = cpShapeGetSensor(c) ? 5 : -1; float seglen = cpShapeGetSensor(c) ? 5 : -1;
@ -377,7 +376,7 @@ void phys2d_dbgdrawpoly(struct phys2d_poly *poly) {
if (arrlen(poly->points) >= 3) { if (arrlen(poly->points) >= 3) {
int n = cpPolyShapeGetCount(poly->shape.shape); int n = cpPolyShapeGetCount(poly->shape.shape);
HMM_Vec2 points[n]; 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++) for (int i = 0; i < n; i++)
points[i] = mat_t_pos(rt, (HMM_Vec2)cpPolyShapeGetVert(poly->shape.shape, i)); points[i] = mat_t_pos(rt, (HMM_Vec2)cpPolyShapeGetVert(poly->shape.shape, i));

View file

@ -4,6 +4,7 @@
#include "script.h" #include "script.h"
#include <chipmunk/chipmunk.h> #include <chipmunk/chipmunk.h>
#include "render.h" #include "render.h"
#include "transform.h"
struct gameobject; struct gameobject;
@ -11,7 +12,6 @@ extern float phys2d_gravity;
extern int physOn; extern int physOn;
extern cpSpace *space; extern cpSpace *space;
extern struct rgba color_white; extern struct rgba color_white;
extern struct rgba color_black; extern struct rgba color_black;

View file

@ -48,12 +48,6 @@ struct bone_weights {
char b4; char b4;
}; };
struct bone {
HMM_Vec3 pos;
HMM_Quat rot;
HMM_Vec3 scale;
};
struct mesh_v { struct mesh_v {
HMM_Vec3 pos; HMM_Vec3 pos;
struct uv_n uv; struct uv_n uv;
@ -345,7 +339,7 @@ void draw_drawmodel(struct drawmodel *dm)
{ {
if (!dm->model) return; if (!dm->model) return;
struct gameobject *go = id2go(dm->go); struct gameobject *go = id2go(dm->go);
HMM_Mat4 rst = m4_rst(go2t3(go)); HMM_Mat4 rst = t3d_go2world(go);
draw_model(dm->model, rst); draw_model(dm->model, rst);
} }

View file

@ -2,7 +2,7 @@
#define MODEL_H #define MODEL_H
#include "HandmadeMath.h" #include "HandmadeMath.h"
#include "transform.h"
#include "sokol/sokol_gfx.h" #include "sokol/sokol_gfx.h"
extern HMM_Vec3 eye; extern HMM_Vec3 eye;
@ -26,6 +26,11 @@ struct drawmodel {
int go; 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 */ /* Get the model at a path, or create and return if it doesn't exist */
struct model *GetExistingModel(const char *path); struct model *GetExistingModel(const char *path);

View file

@ -1,6 +1,5 @@
#include "skybox.h" #include "skybox.h"
#include "camera.h"
#include "shader.h" #include "shader.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>

View file

@ -1181,9 +1181,9 @@ static inline HMM_Mat3 HMM_DivM3F(HMM_Mat3 Matrix, float Scalar) {
return Result; 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[0][0] = Scale.X;
Result.Elements[1][1] = Scale.Y; 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]); 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) { static inline HMM_Mat3 HMM_InvGeneralM3(HMM_Mat3 Matrix) {
HMM_Mat3 Cross; HMM_Mat3 Cross;

View file

@ -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);
}

View file

@ -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

View file

@ -9,6 +9,7 @@ struct freelistheader
{ {
unsigned int first; unsigned int first;
unsigned int len; unsigned int len;
unsigned int count;
}; };
#define freelist_header(p) ((struct freelistheader*)p-1) #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 = malloc(elemsize*n*sizeof(struct freelistheader));
list->first = 0; list->first = 0;
list->len = n; list->len = n;
list->count = 0;
return list+1; 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_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_len(p) (freelist_header(p)->len)
#define freelist_first(p) (freelist_header(p)->first) #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_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;}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_free(p) (free(freelist_header(p)))
#define freelist_count(p) (freelist_header(p)->count)
struct link_header struct link_header
{ {

View file

@ -11,20 +11,11 @@
#include <chipmunk/chipmunk.h> #include <chipmunk/chipmunk.h>
#include <string.h> #include <string.h>
#include "debugdraw.h" #include "debugdraw.h"
#include "freelist.h"
#include "stb_ds.h" #include "stb_ds.h"
struct gameobject *gameobjects = NULL; 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) { struct gameobject *id2go(int id) {
if (id < 0) return NULL; if (id < 0) return NULL;
@ -32,9 +23,7 @@ struct gameobject *id2go(int id) {
return &gameobjects[id]; return &gameobjects[id];
} }
int body2id(cpBody *body) { int body2id(cpBody *body) { return (int)cpBodyGetUserData(body); }
return (int)cpBodyGetUserData(body);
}
cpBody *id2body(int id) { cpBody *id2body(int id) {
struct gameobject *go = id2go(id); struct gameobject *go = id2go(id);
@ -61,56 +50,15 @@ HMM_Vec2 go2pos(struct gameobject *go)
return (HMM_Vec2){p.x, p.y}; return (HMM_Vec2){p.x, p.y};
} }
float go2angle(struct gameobject *go) float go2angle(struct gameobject *go) { return cpBodyGetAngle(go->body); }
{
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)
{
}
transform3d go2t3(gameobject *go) transform3d go2t3(gameobject *go)
{ {
transform3d t; transform3d t;
HMM_Vec2 p = go2pos(go); HMM_Vec2 p = go2pos(go);
t.pos.X = p.X;
t.pos.Y = p.Y; t.pos.Y = p.Y;
t.pos.X = p.X; t.pos.Z = go->drawlayer;
t.scale = go->scale; t.scale = go->scale;
t.scale.Z = go->scale.X; t.scale.Z = go->scale.X;
t.rotation = HMM_QFromAxisAngle_RH(vFWD, go2angle(go)); t.rotation = HMM_QFromAxisAngle_RH(vFWD, go2angle(go));
@ -119,105 +67,18 @@ transform3d go2t3(gameobject *go)
return t; return t;
} }
HMM_Mat4 m4_t(transform3d t) HMM_Vec2 go2world(struct gameobject *go, HMM_Vec2 pos) { return mat_t_pos(t_go2world(go), pos); }
{
return HMM_Translate(t.pos);
}
HMM_Mat4 m4_s(transform3d t) HMM_Vec2 world2go(struct gameobject *go, HMM_Vec2 pos) { return mat_t_pos(t_world2go(go), pos); }
{
return HMM_Scale(t.scale);
}
HMM_Mat4 m4_r(transform3d t) HMM_Vec2 goscale(struct gameobject *go, HMM_Vec2 pos) { return HMM_MulV2(go->scale.XY, pos); }
{
return HMM_QToM4(t.rotation);
}
HMM_Mat4 m4_st(transform3d t) HMM_Mat3 t_go2world(struct gameobject *go) { return transform2d2mat(go2t(go)); }
{
return HMM_MulM4(m4_t(t), m4_s(t));
}
HMM_Mat4 m4_rt(transform3d t) HMM_Mat3 t_world2go(struct gameobject *go) { return HMM_InvGeneralM3(t_go2world(go)); }
{
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_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) { int pos2gameobject(HMM_Vec2 pos) {
cpShape *hit = phys2d_query_pos(pos.cp); cpShape *hit = phys2d_query_pos(pos.cp);
@ -237,19 +98,6 @@ int pos2gameobject(HMM_Vec2 pos) {
return -1; 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 go2t(gameobject *go)
{ {
transform2d t; transform2d t;
@ -262,17 +110,10 @@ transform2d go2t(gameobject *go)
} }
int go2id(struct 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 -1;
{
return 0;
}
uint32_t go2mask(struct gameobject *go)
{
return 0;
} }
unsigned int editor_cat = 1<<31; 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) static void velocityFn(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt)
{ {
struct gameobject *go = id2go((int)cpBodyGetUserData(body)); struct gameobject *go = id2go((int)cpBodyGetUserData(body));
@ -367,9 +196,9 @@ int MakeGameobject() {
.maxangularvelocity = INFINITY, .maxangularvelocity = INFINITY,
.mass = 1.f, .mass = 1.f,
.next = -1, .next = -1,
.sensor = 0,
.drawlayer = 0, .drawlayer = 0,
.shape_cbs = NULL, .shape_cbs = NULL,
.children = NULL,
.gravity = 1, .gravity = 1,
.cgravity = (HMM_Vec2){0,0}, .cgravity = (HMM_Vec2){0,0},
.damping = NAN, .damping = NAN,
@ -383,20 +212,22 @@ int MakeGameobject() {
go.body = cpSpaceAddBody(space, cpBodyNew(go.mass, 1.f)); go.body = cpSpaceAddBody(space, cpBodyNew(go.mass, 1.f));
cpBodySetVelocityUpdateFunc(go.body, velocityFn); 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) { void gameobject_traverse(struct gameobject *go, HMM_Mat4 p)
arrput(gameobjects, go); {
retid = arrlast(gameobjects).id = arrlen(gameobjects) - 1; HMM_Mat4 local = transform3d2mat(go2t3(go));
} else { go->world = HMM_MulM4(local, p);
retid = first;
first = id2go(first)->next;
*id2go(retid) = go;
}
cpBodySetUserData(go.body, (void *)retid); for (int i = 0; i < arrlen(go->children); i++)
phys2d_setup_handlers(retid); gameobject_traverse(go->children[i], go->world);
return retid;
} }
void rm_body_shapes(cpBody *body, cpShape *shape, void *data) { 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" ... */ /* Really more of a "mark for deletion" ... */
void gameobject_delete(int id) { void gameobject_delete(int id) {
id2go(id)->next = first; gameobject *go = id2go(id);
JS_FreeValue(js, id2go(id)->ref); JS_FreeValue(js, go->ref);
first = id;
if (cpSpaceIsLocked(space)) if (cpSpaceIsLocked(space))
arrpush(go_toclean, id); arrpush(go_toclean, id);
else else
gameobject_clean(id); gameobject_clean(id);
dag_clip(go);
freelist_kill(gameobjects,id);
} }
void gameobject_free(int id) void gameobject_free(int id)
{ {
YughWarn("FREED A GAMEOBJECT!!!");
if (id >= 0) if (id >= 0)
gameobject_delete(id); gameobject_delete(id);
} }
@ -445,15 +277,6 @@ void gameobjects_cleanup() {
gameobject_clean(go_toclean[i]); gameobject_clean(go_toclean[i]);
arrsetlen(go_toclean, 0); 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) { 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++) for (int i = 0; i < arrlen(gameobjects); i++)
gameobject_draw_debug(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);
}

View file

@ -8,39 +8,35 @@
#include <stdio.h> #include <stdio.h>
#include "quickjs/quickjs.h" #include "quickjs/quickjs.h"
#include "HandmadeMath.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 shader;
struct sprite; struct sprite;
struct component; 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 { typedef struct gameobject {
cpBodyType bodytype; cpBodyType bodytype;
int next; int next;
HMM_Vec3 scale; HMM_Vec3 scale; /* local */
float mass; float mass;
float f; /* friction */ float f; /* friction */
float e; /* elasticity */ float e; /* elasticity */
@ -50,7 +46,6 @@ typedef struct gameobject {
int gravity; int gravity;
HMM_Vec2 cgravity; HMM_Vec2 cgravity;
float damping; float damping;
int sensor;
unsigned int layer; unsigned int layer;
cpShapeFilter filter; cpShapeFilter filter;
cpBody *body; /* NULL if this object is dead */ cpBody *body; /* NULL if this object is dead */
@ -58,10 +53,12 @@ typedef struct gameobject {
struct phys_cbs cbs; struct phys_cbs cbs;
struct shape_cb *shape_cbs; struct shape_cb *shape_cbs;
JSValue ref; JSValue ref;
HMM_Mat3 transform;
struct gameobject *master; struct gameobject *master;
HMM_Mat4 world;
transform2d t; /* The local transformation of this object */ transform2d t; /* The local transformation of this object */
float drawlayer; float drawlayer;
struct gameobject *parent;
struct gameobject **children;
} gameobject; } gameobject;
extern struct gameobject *gameobjects; extern struct gameobject *gameobjects;
@ -72,42 +69,33 @@ void gameobject_delete(int id);
void gameobject_free(int id); void gameobject_free(int id);
void gameobjects_cleanup(); 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); transform2d go2t(gameobject *go);
transform3d go2t3(gameobject *go); transform3d go2t3(gameobject *go);
HMM_Vec2 go2world(struct gameobject *go, HMM_Vec2 pos); HMM_Vec2 go2world(struct gameobject *go, HMM_Vec2 pos);
HMM_Vec2 world2go(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_go2world(struct gameobject *go);
HMM_Mat3 t_world2go(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 goscale(struct gameobject *go, HMM_Vec2 pos);
HMM_Vec2 gotpos(struct gameobject *go, HMM_Vec2 pos); HMM_Vec2 gotpos(struct gameobject *go, HMM_Vec2 pos);
HMM_Mat3 mt_rst(transform2d t); 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); struct gameobject *id2go(int id);
int id_from_gameobject(struct gameobject *go);
int go2id(struct gameobject *go); int go2id(struct gameobject *go);
int body2id(cpBody *body); int body2id(cpBody *body);
cpBody *id2body(int id); cpBody *id2body(int id);
int shape2gameobject(cpShape *shape); int shape2gameobject(cpShape *shape);
struct gameobject *shape2go(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); 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_debugs();
void gameobject_draw_debug(int go); void gameobject_draw_debug(int go);
void object_gui(struct gameobject *go);
void gameobject_saveall();
void gameobject_loadall();
int gameobjects_saved();
#endif #endif

View file

@ -360,7 +360,11 @@ int js_print_exception(JSValue v)
JSValue duk_gui_img(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) { JSValue duk_gui_img(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
const char *img = JS_ToCString(js, argv[0]); 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); JS_FreeCString(js, img);
return JS_UNDEFINED; return JS_UNDEFINED;
} }
@ -684,7 +688,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
case 37: case 37:
if (!id2sprite(js2int(argv[1]))) break; if (!id2sprite(js2int(argv[1]))) break;
id2sprite(js2int(argv[1]))->pos = js2vec2(argv[2]); id2sprite(js2int(argv[1]))->t.pos = js2vec2(argv[2]);
break; break;
case 38: case 38:
@ -821,7 +825,6 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
break; break;
case 69: case 69:
gameobject_set_sensor(js2go(argv[1]), JS_ToBool(js, argv[2]));
break; break;
case 70: case 70:
@ -995,7 +998,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
break; break;
case 111: case 111:
ret = vec2js(js2sprite(argv[1])->pos); ret = vec2js(js2sprite(argv[1])->t.pos);
break; break;
case 112: case 112:
@ -1345,6 +1348,9 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
case 207: case 207:
ret = dsp_node2js(dsp_fwd_delay(js2number(argv[1]), js2number(argv[2]))); ret = dsp_node2js(dsp_fwd_delay(js2number(argv[1]), js2number(argv[2])));
break; break;
case 208:
dag_set(js2go(argv[1]), js2go(argv[2]));
break;
} }
if (str) if (str)

View file

@ -1,6 +1,5 @@
#include "render.h" #include "render.h"
#include "camera.h"
#include "config.h" #include "config.h"
#include "datastream.h" #include "datastream.h"
#include "debugdraw.h" #include "debugdraw.h"

View file

@ -89,7 +89,6 @@ dsp_node *dsp_midi(const char *midi, tsf *sf)
ms->time = 0.0; ms->time = 0.0;
ms->midi = tml_load_memory(raw, rawlen); ms->midi = tml_load_memory(raw, rawlen);
ms->sf = tsf_copy(sf); ms->sf = tsf_copy(sf);
free(midi);
return make_node(ms, dsp_midi_fillbuf, dsp_midi_free); return make_node(ms, dsp_midi_fillbuf, dsp_midi_free);
} }

View file

@ -53,11 +53,10 @@ struct slice9_vert {
}; };
int make_sprite(int go) { int make_sprite(int go) {
YughWarn("Attaching sprite to gameobject %d", go);
struct sprite sprite = { struct sprite sprite = {
.t = t2d_unit,
.color = color_white, .color = color_white,
.emissive = {0,0,0,0}, .emissive = {0,0,0,0},
.size = {1.f, 1.f},
.tex = texture_loadfromfile(NULL), .tex = texture_loadfromfile(NULL),
.go = go, .go = go,
.layer = 0, .layer = 0,
@ -77,9 +76,7 @@ void sprite_delete(int id) {
freelist_kill(sprites,id); freelist_kill(sprites,id);
} }
void sprite_enabled(int id, int e) { void sprite_enabled(int id, int e) { sprites[id].enabled = e; }
sprites[id].enabled = e;
}
struct sprite *id2sprite(int id) { struct sprite *id2sprite(int id) {
if (id < 0) return NULL; 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; 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_append_buffer(bind_sprite.vertex_buffers[0], SG_RANGE_REF(verts));
sg_apply_bindings(&bind_sprite); sg_apply_bindings(&bind_sprite);
@ -259,14 +255,13 @@ void sprite_draw(struct sprite *sprite) {
struct gameobject *go = id2go(sprite->go); struct gameobject *go = id2go(sprite->go);
if (sprite->tex) { if (sprite->tex) {
transform2d t = go2t(id2go(sprite->go)); HMM_Mat3 m = t_go2world(go);
HMM_Mat3 m = transform2d2mat(t);
HMM_Mat3 ss = HMM_M3D(1); HMM_Mat3 ss = HMM_M3D(1);
ss.Columns[0].X = sprite->size.X * sprite->tex->width * st_s_w(sprite->frame); ss.Columns[0].X = sprite->t.scale.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[1].Y = sprite->t.scale.Y * sprite->tex->height * st_s_h(sprite->frame);
HMM_Mat3 ts = HMM_M3D(1); 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); HMM_Mat3 sm = HMM_MulM3(ss, ts);
m = HMM_MulM3(m, sm); 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]; 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_pipeline(pip_sprite);
sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(hudproj)); sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(hudproj));
struct Texture *tex = texture_loadfromfile(img); 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}); 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) { void sprite_setframe(struct sprite *sprite, struct glrect *frame) {
sprite->frame = *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);
*/
}

View file

@ -6,14 +6,13 @@
#include "texture.h" #include "texture.h"
#include "HandmadeMath.h" #include "HandmadeMath.h"
#include "render.h" #include "render.h"
#include "transform.h"
struct datastream; struct datastream;
struct gameobject; struct gameobject;
struct sprite { struct sprite {
HMM_Vec2 pos; transform2d t;
HMM_Vec2 size;
float rotation;
struct rgba color; struct rgba color;
struct rgba emissive; struct rgba emissive;
int go; /* id of gameobject */ 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_setframe(struct sprite *sprite, struct glrect *frame);
void sprite_initialize(); void sprite_initialize();
void sprite_draw(struct sprite *sprite); 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(); void sprite_draw_all();
unsigned int incrementAnimFrame(unsigned int interval, struct sprite *sprite); unsigned int incrementAnimFrame(unsigned int interval, struct sprite *sprite);
void sprite_flush(); 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 #endif

View file

@ -1,42 +1,67 @@
#include "transform.h" #include "transform.h"
#include <string.h> #include <string.h>
struct mTransform MakeTransform(HMM_Vec3 pos, HMM_Quat rotation, float scale) const transform2d t2d_unit = {
{ .pos = {0,0},
struct mTransform newT = { .scale = {1,1},
.pos = pos, .angle = 0
.rotation = rotation, };
.scale = scale
};
return newT;
}
HMM_Vec3 trans_forward(const struct mTransform *const trans) HMM_Vec3 trans_forward(const transform3d *const trans)
{ {
return HMM_QVRot(vFWD, trans->rotation); 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); 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); 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); 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); 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); 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))); }

View file

@ -3,23 +3,36 @@
#include "HandmadeMath.h" #include "HandmadeMath.h"
struct mTransform { typedef struct {
HMM_Vec3 pos; HMM_Vec3 pos;
HMM_Vec3 scale;
HMM_Quat rotation; 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_forward(const transform3d *const trans);
HMM_Vec3 trans_back(const struct mTransform *trans); HMM_Vec3 trans_back(const transform3d *trans);
HMM_Vec3 trans_up(const struct mTransform *trans); HMM_Vec3 trans_up(const transform3d *trans);
HMM_Vec3 trans_down(const struct mTransform *trans); HMM_Vec3 trans_down(const transform3d *trans);
HMM_Vec3 trans_right(const struct mTransform *trans); HMM_Vec3 trans_right(const transform3d *trans);
HMM_Vec3 trans_left(const struct mTransform *trans); HMM_Vec3 trans_left(const transform3d *trans);
void trans_drawgui(struct mTransform *T);
//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 #endif

View file

@ -1,5 +1,4 @@
#include "yugine.h" #include "yugine.h"
#include "camera.h"
#include "font.h" #include "font.h"
#include "gameobject.h" #include "gameobject.h"
#include "input.h" #include "input.h"
@ -169,6 +168,11 @@ static void process_frame()
/* Timers all update every frame - once per monitor refresh */ /* Timers all update every frame - once per monitor refresh */
timer_update(elapsed, timescale); timer_update(elapsed, timescale);
/* Update at a high level::
* Update scene graph
*
*/
if (sim_play == SIM_PLAY || sim_play == SIM_STEP) { if (sim_play == SIM_PLAY || sim_play == SIM_STEP) {
if (stm_sec(stm_diff(frame_t, updatelast)) > updateMS) { if (stm_sec(stm_diff(frame_t, updatelast)) > updateMS) {
double dt = stm_sec(stm_diff(frame_t, updatelast)); double dt = stm_sec(stm_diff(frame_t, updatelast));