catmull-rom spline custom
This commit is contained in:
parent
de8c8c9168
commit
cb0fa34743
|
@ -4,5 +4,14 @@ Entities are defined by creating a .jso script in your game directory. Variants
|
||||||
|
|
||||||
An entity which differs from its ur will have an asterisk * next to its name.
|
An entity which differs from its ur will have an asterisk * next to its name.
|
||||||
|
|
||||||
## Ur types
|
Entities have components. The components all do a thing. Components are placed relative to the entity.
|
||||||
|
|
||||||
|
All entities are child to Primum, once the simulation is running.
|
||||||
|
|
||||||
|
Entites can be static, kinematic, or dynamic. Static entities never move. Kinematic entities move via explicit command. Dynamic ones move under the auspices of the game world.
|
||||||
|
|
||||||
|
Components, if they have a defined transform, are relative to the entity they reside on. Components cannot have components, ensuring that components can be processed and rendered in any order.
|
||||||
|
|
||||||
|
Entities are defined via a typical scene graph system. This allows for easy reuse of components when designing levels.
|
||||||
|
|
||||||
|
When the game is run, the movement relationships are broken, and the physics system takes over. In the physics engine, each entity is a direct child of the world. Objects can still be constrained to other objects via the physics system.
|
||||||
|
|
|
@ -414,10 +414,6 @@ var Game = {
|
||||||
sys_cmd(1);
|
sys_cmd(1);
|
||||||
},
|
},
|
||||||
|
|
||||||
get dt() {
|
|
||||||
return cmd(63);
|
|
||||||
},
|
|
||||||
|
|
||||||
wait_fns: [],
|
wait_fns: [],
|
||||||
|
|
||||||
wait_exec(fn) {
|
wait_exec(fn) {
|
||||||
|
@ -487,4 +483,3 @@ var Asset = {};
|
||||||
Asset.doc = {
|
Asset.doc = {
|
||||||
doc: "Functions to manage the loading and unloading of assets, like sounds and images."
|
doc: "Functions to manage the loading and unloading of assets, like sounds and images."
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -169,7 +169,6 @@ var gameobject = {
|
||||||
set_gravity(x) { cmd(167, this.body, x); },
|
set_gravity(x) { cmd(167, this.body, x); },
|
||||||
set timescale(x) { cmd(168,this.body,x); },
|
set timescale(x) { cmd(168,this.body,x); },
|
||||||
get timescale() { return cmd(169,this.body); },
|
get timescale() { return cmd(169,this.body); },
|
||||||
|
|
||||||
set phys(x) { console.warn(`Setting phys to ${x}`); set_body(1, this.body, x); },
|
set phys(x) { console.warn(`Setting phys to ${x}`); set_body(1, this.body, x); },
|
||||||
get phys() { return q_body(0,this.body); },
|
get phys() { return q_body(0,this.body); },
|
||||||
get velocity() { return q_body(3, this.body); },
|
get velocity() { return q_body(3, this.body); },
|
||||||
|
@ -513,7 +512,6 @@ var gameobject = {
|
||||||
}
|
}
|
||||||
|
|
||||||
delete this.components;
|
delete this.components;
|
||||||
// q_body(8,this.body);
|
|
||||||
|
|
||||||
this.clear();
|
this.clear();
|
||||||
|
|
||||||
|
|
|
@ -76,9 +76,14 @@ var DSP = {
|
||||||
return dsp_node.make(cmd(207,secs,decay));
|
return dsp_node.make(cmd(207,secs,decay));
|
||||||
},
|
},
|
||||||
allpass(secs, decay) {
|
allpass(secs, decay) {
|
||||||
|
var composite = {};
|
||||||
var fwd = DSP.fwd_delay(secs,-decay);
|
var fwd = DSP.fwd_delay(secs,-decay);
|
||||||
var fbk = DSP.delay(secs,decay);
|
var fbk = DSP.delay(secs,decay);
|
||||||
|
composite.id = fwd.id;
|
||||||
|
composite.plugin = composite.plugin.bind(fbk);
|
||||||
|
composite.unplug = dsp_node.unplug.bind(fbk);
|
||||||
fwd.plugin(fbk);
|
fwd.plugin(fbk);
|
||||||
|
return composite;
|
||||||
},
|
},
|
||||||
lpf(f) {
|
lpf(f) {
|
||||||
return dsp_node.make(cmd(186,f));
|
return dsp_node.make(cmd(186,f));
|
||||||
|
|
|
@ -296,6 +296,7 @@ Cmdline.register_cmd("cjson", function(json) {
|
||||||
}, "Clean up a jso file.");
|
}, "Clean up a jso file.");
|
||||||
|
|
||||||
Cmdline.register_cmd("r", function(script) {
|
Cmdline.register_cmd("r", function(script) {
|
||||||
run(script);
|
try { run(script); } catch(e) { STD.exit(0); }
|
||||||
|
|
||||||
STD.exit(0);
|
STD.exit(0);
|
||||||
}, "Run a script.");
|
}, "Run a script.");
|
||||||
|
|
|
@ -12,8 +12,6 @@
|
||||||
|
|
||||||
#include "2dphysics.h"
|
#include "2dphysics.h"
|
||||||
|
|
||||||
#include "tinyspline.h"
|
|
||||||
|
|
||||||
#include "jsffi.h"
|
#include "jsffi.h"
|
||||||
#include "script.h"
|
#include "script.h"
|
||||||
|
|
||||||
|
@ -39,6 +37,18 @@ void set_cat_mask(int cat, unsigned int mask) {
|
||||||
category_masks[cat] = mask;
|
category_masks[cat] = mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cpTransform m3_to_cpt(HMM_Mat3 m)
|
||||||
|
{
|
||||||
|
cpTransform t;
|
||||||
|
t.a = m.Columns[0].x;
|
||||||
|
t.c = m.Columns[0].y;
|
||||||
|
t.tx = m.Columns[0].z;
|
||||||
|
t.b = m.Columns[1].x;
|
||||||
|
t.d = m.Columns[1].y;
|
||||||
|
t.ty = m.Columns[1].z;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
cpShape *phys2d_query_pos(cpVect pos) {
|
cpShape *phys2d_query_pos(cpVect pos) {
|
||||||
cpShapeFilter filter;
|
cpShapeFilter filter;
|
||||||
filter.group = CP_NO_GROUP;
|
filter.group = CP_NO_GROUP;
|
||||||
|
@ -49,62 +59,56 @@ cpShape *phys2d_query_pos(cpVect pos) {
|
||||||
return find;
|
return find;
|
||||||
}
|
}
|
||||||
|
|
||||||
int *qhits;
|
int sort_ids(int *a, int *b)
|
||||||
|
{
|
||||||
void querylist(cpShape *shape, cpContactPointSet *points, void *data) {
|
if (*a == *b) return 0;
|
||||||
int go = shape2gameobject(shape);
|
if (*a < *b) return -1;
|
||||||
int in = 0;
|
return 1;
|
||||||
for (int i = 0; i < arrlen(qhits); i++) {
|
|
||||||
if (qhits[i] == go) {
|
|
||||||
in = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!in) arrput(qhits, go);
|
int *clean_ids(int *ids)
|
||||||
|
{
|
||||||
|
qsort(ids, sizeof(*ids), arrlen(ids), sort_ids);
|
||||||
|
|
||||||
|
int curid = -1;
|
||||||
|
for (int i = arrlen(ids)-1; i >= 0; i--)
|
||||||
|
if (ids[i] == curid)
|
||||||
|
arrdelswap(ids, i);
|
||||||
|
else
|
||||||
|
curid = ids[i];
|
||||||
|
|
||||||
|
return ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
void querylistbodies(cpBody *body, void *data) {
|
void querylist(cpShape *shape, cpContactPointSet *points, int *ids) {
|
||||||
cpBB *bbox = data;
|
arrput(ids,shape2gameobject(shape));
|
||||||
if (cpBBContainsVect(*bbox, cpBodyGetPosition(body))) {
|
|
||||||
int go = body2id(body);
|
|
||||||
if (go < 0) return;
|
|
||||||
|
|
||||||
int in = 0;
|
|
||||||
for (int i = 0; i < arrlen(qhits); i++) {
|
|
||||||
if (qhits[i] == go) {
|
|
||||||
in = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!in) arrput(qhits, go);
|
typedef struct querybox {
|
||||||
}
|
cpBB bb;
|
||||||
|
int *ids;
|
||||||
|
} querybox;
|
||||||
|
|
||||||
|
void querylistbodies(cpBody *body, querybox *qb) {
|
||||||
|
if (cpBBContainsVect(qb->bb, cpBodyGetPosition(body)))
|
||||||
|
arrput(qb->ids,body2id(body));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return all points from a list of points in the given boundingbox */
|
||||||
int *phys2d_query_box_points(HMM_Vec2 pos, HMM_Vec2 wh, HMM_Vec2 *points, int n) {
|
int *phys2d_query_box_points(HMM_Vec2 pos, HMM_Vec2 wh, HMM_Vec2 *points, int n) {
|
||||||
cpShape *box = cpBoxShapeNew(NULL, wh.x, wh.y, 0.f);
|
cpBB bbox;
|
||||||
cpTransform T = {0};
|
bbox = cpBBExpand(bbox, cpvadd(pos.cp, cpvmult(wh.cp,0.5)));
|
||||||
T.a = 1;
|
bbox = cpBBExpand(bbox, cpvsub(pos.cp, cpvmult(wh.cp,0.5)));
|
||||||
T.d = 1;
|
int *hits = NULL;
|
||||||
T.tx = pos.x;
|
|
||||||
T.ty = pos.y;
|
|
||||||
cpShapeUpdate(box, T);
|
|
||||||
|
|
||||||
cpBB bbox = cpShapeGetBB(box);
|
for (int i = 0; i < n; i++)
|
||||||
|
|
||||||
if (qhits) arrfree(qhits);
|
|
||||||
|
|
||||||
for (int i = 0; i < n; i++) {
|
|
||||||
if (cpBBContainsVect(bbox, points[i].cp))
|
if (cpBBContainsVect(bbox, points[i].cp))
|
||||||
arrpush(qhits, i);
|
arrpush(hits, i);
|
||||||
}
|
|
||||||
|
return hits;
|
||||||
cpShapeFree(box);
|
|
||||||
|
|
||||||
return qhits;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return all gameobjects within the given box */
|
||||||
int *phys2d_query_box(HMM_Vec2 pos, HMM_Vec2 wh) {
|
int *phys2d_query_box(HMM_Vec2 pos, HMM_Vec2 wh) {
|
||||||
cpShape *box = cpBoxShapeNew(NULL, wh.x, wh.y, 0.f);
|
cpShape *box = cpBoxShapeNew(NULL, wh.x, wh.y, 0.f);
|
||||||
cpTransform T = {0};
|
cpTransform T = {0};
|
||||||
|
@ -116,22 +120,24 @@ int *phys2d_query_box(HMM_Vec2 pos, HMM_Vec2 wh) {
|
||||||
|
|
||||||
cpBB bbox = cpShapeGetBB(box);
|
cpBB bbox = cpShapeGetBB(box);
|
||||||
|
|
||||||
if (qhits) arrfree(qhits);
|
int *ids = NULL;
|
||||||
|
|
||||||
cpSpaceShapeQuery(space, box, querylist, NULL);
|
querybox qb;
|
||||||
cpSpaceEachBody(space, querylistbodies, &bbox);
|
qb.bb = bbox;
|
||||||
|
qb.ids = ids;
|
||||||
|
|
||||||
|
cpSpaceShapeQuery(space, box, querylist, ids);
|
||||||
|
cpSpaceEachBody(space, querylistbodies, &qb);
|
||||||
|
|
||||||
cpShapeFree(box);
|
cpShapeFree(box);
|
||||||
|
|
||||||
return qhits;
|
return clean_ids(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
int *phys2d_query_shape(struct phys2d_shape *shape) {
|
int *phys2d_query_shape(struct phys2d_shape *shape) {
|
||||||
if (qhits) arrfree(qhits);
|
int *ids = NULL;
|
||||||
|
cpSpaceShapeQuery(space, shape->shape, querylist, ids);
|
||||||
cpSpaceShapeQuery(space, shape->shape, querylist, NULL);
|
return clean_ids(ids);
|
||||||
|
|
||||||
return qhits;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int cpshape_enabled(cpShape *c) {
|
int cpshape_enabled(cpShape *c) {
|
||||||
|
@ -246,11 +252,12 @@ void phys2d_applycircle(struct phys2d_circle *circle) {
|
||||||
|
|
||||||
struct phys2d_box *Make2DBox(int go) {
|
struct phys2d_box *Make2DBox(int go) {
|
||||||
struct phys2d_box *new = malloc(sizeof(struct phys2d_box));
|
struct phys2d_box *new = malloc(sizeof(struct phys2d_box));
|
||||||
|
new->t = (transform2d){
|
||||||
new->w = 50.f;
|
.pos = {0,0},
|
||||||
new->h = 50.f;
|
.angle = 0,
|
||||||
|
.scale = {0,0}
|
||||||
|
};
|
||||||
new->r = 0.f;
|
new->r = 0.f;
|
||||||
new->offset = v2zero;
|
|
||||||
new->shape.go = go;
|
new->shape.go = go;
|
||||||
new->shape.apply = phys2d_applybox;
|
new->shape.apply = phys2d_applybox;
|
||||||
phys2d_applybox(new);
|
phys2d_applybox(new);
|
||||||
|
@ -261,18 +268,7 @@ struct phys2d_box *Make2DBox(int go) {
|
||||||
}
|
}
|
||||||
|
|
||||||
float phys2d_box_moi(struct phys2d_box *box, float m) {
|
float phys2d_box_moi(struct phys2d_box *box, float m) {
|
||||||
return cpMomentForBox(m, box->w, box->h);
|
return cpMomentForBox(m, box->t.scale.x, box->t.scale.y);
|
||||||
}
|
|
||||||
|
|
||||||
cpTransform trs2cpt(HMM_Vec2 t, float r, HMM_Vec2 s) {
|
|
||||||
cpTransform T;
|
|
||||||
T.a = cos(r) * s.X;
|
|
||||||
T.b = -sin(r) * s.X;
|
|
||||||
T.c = sin(r) * s.Y;
|
|
||||||
T.d = cos(r) * s.Y;
|
|
||||||
T.tx = t.X * s.X;
|
|
||||||
T.ty = t.Y * s.Y;
|
|
||||||
return T;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void phys2d_boxdel(struct phys2d_box *box) {
|
void phys2d_boxdel(struct phys2d_box *box) {
|
||||||
|
@ -282,10 +278,8 @@ void phys2d_boxdel(struct phys2d_box *box) {
|
||||||
void phys2d_applybox(struct phys2d_box *box) {
|
void phys2d_applybox(struct phys2d_box *box) {
|
||||||
phys2d_boxdel(box);
|
phys2d_boxdel(box);
|
||||||
struct gameobject *go = id2go(box->shape.go);
|
struct gameobject *go = id2go(box->shape.go);
|
||||||
cpTransform T = trs2cpt(box->offset, box->rotation, id2go(box->shape.go)->scale.XY);
|
cpTransform T = m3_to_cpt(transform2d2mat(box->t));
|
||||||
float hh = box->h / 2.f;
|
cpVect verts[4] = {{-0.5, -0.5}, {0.5, -0.5}, {0.5, 0.5}, {-0.5, 0.5}};
|
||||||
float hw = box->w / 2.f;
|
|
||||||
cpVect verts[4] = {{-hw, -hh}, {hw, -hh}, {hw, hh}, {-hw, hh}};
|
|
||||||
box->shape.shape = cpSpaceAddShape(space, cpPolyShapeNew(go->body, 4, verts, T, box->r));
|
box->shape.shape = cpSpaceAddShape(space, cpPolyShapeNew(go->body, 4, verts, T, box->r));
|
||||||
init_phys2dshape(&box->shape, box->shape.go, box);
|
init_phys2dshape(&box->shape, box->shape.go, box);
|
||||||
}
|
}
|
||||||
|
@ -361,9 +355,7 @@ void phys2d_poly_setverts(struct phys2d_poly *poly, cpVect *verts) {
|
||||||
void phys2d_applypoly(struct phys2d_poly *poly) {
|
void phys2d_applypoly(struct phys2d_poly *poly) {
|
||||||
if (arrlen(poly->points) <= 0) return;
|
if (arrlen(poly->points) <= 0) return;
|
||||||
struct gameobject *go = id2go(poly->shape.go);
|
struct gameobject *go = id2go(poly->shape.go);
|
||||||
|
cpTransform T = m3_to_cpt(transform2d2mat(poly->t));
|
||||||
cpTransform T = trs2cpt((HMM_Vec2){0,0}, 0, go->scale.XY);
|
|
||||||
|
|
||||||
cpPolyShapeSetVerts(poly->shape.shape, arrlen(poly->points), poly->points, T);
|
cpPolyShapeSetVerts(poly->shape.shape, arrlen(poly->points), poly->points, T);
|
||||||
cpPolyShapeSetRadius(poly->shape.shape, poly->radius);
|
cpPolyShapeSetRadius(poly->shape.shape, poly->radius);
|
||||||
cpSpaceReindexShapesForBody(space, cpShapeGetBody(poly->shape.shape));
|
cpSpaceReindexShapesForBody(space, cpShapeGetBody(poly->shape.shape));
|
||||||
|
@ -477,12 +469,13 @@ void phys2d_applyedge(struct phys2d_edge *edge) {
|
||||||
struct gameobject *go = id2go(edge->shape.go);
|
struct gameobject *go = id2go(edge->shape.go);
|
||||||
|
|
||||||
for (int i = 0; i < arrlen(edge->shapes); i++) {
|
for (int i = 0; i < arrlen(edge->shapes); i++) {
|
||||||
HMM_Vec2 a = goscale(go, edge->points[i]);
|
/* Points must be scaled with gameobject, */
|
||||||
HMM_Vec2 b = goscale(go, edge->points[i+1]);
|
HMM_Vec2 a = HMM_MulV2(go->scale.xy, edge->points[i]);
|
||||||
|
HMM_Vec2 b = HMM_MulV2(go->scale.xy, edge->points[i+1]);
|
||||||
cpSegmentShapeSetEndpoints(edge->shapes[i], a.cp, b.cp);
|
cpSegmentShapeSetEndpoints(edge->shapes[i], a.cp, b.cp);
|
||||||
cpSegmentShapeSetRadius(edge->shapes[i], edge->thickness);
|
cpSegmentShapeSetRadius(edge->shapes[i], edge->thickness);
|
||||||
if (i > 0 && i < arrlen(edge->shapes) - 1)
|
if (i > 0 && i < arrlen(edge->shapes) - 1)
|
||||||
cpSegmentShapeSetNeighbors(edge->shapes[i], goscale(go,edge->points[i-1]).cp, goscale(go,edge->points[i+2]).cp);
|
cpSegmentShapeSetNeighbors(edge->shapes[i], HMM_MulV2(go->scale.xy,edge->points[i-1]).cp, HMM_MulV2(go->scale.xy,edge->points[i+2]).cp);
|
||||||
go_shape_apply(NULL, edge->shapes[i], go);
|
go_shape_apply(NULL, edge->shapes[i], go);
|
||||||
cpShapeSetUserData(edge->shapes[i], &edge->shape);
|
cpShapeSetUserData(edge->shapes[i], &edge->shape);
|
||||||
}
|
}
|
||||||
|
@ -504,7 +497,6 @@ void phys2d_dbgdrawedge(struct phys2d_edge *edge) {
|
||||||
HMM_Vec2 drawpoints[arrlen(edge->points)];
|
HMM_Vec2 drawpoints[arrlen(edge->points)];
|
||||||
struct gameobject *go = id2go(edge->shape.go);
|
struct gameobject *go = id2go(edge->shape.go);
|
||||||
|
|
||||||
|
|
||||||
HMM_Mat3 g2w = t_go2world(go);
|
HMM_Mat3 g2w = t_go2world(go);
|
||||||
for (int i = 0; i < arrlen(edge->points); i++)
|
for (int i = 0; i < arrlen(edge->points); i++)
|
||||||
drawpoints[i] = mat_t_pos(g2w, edge->points[i]);
|
drawpoints[i] = mat_t_pos(g2w, edge->points[i]);
|
||||||
|
@ -553,9 +545,7 @@ int shape_get_sensor(struct phys2d_shape *shape) {
|
||||||
return cpShapeGetSensor(shape->shape);
|
return cpShapeGetSensor(shape->shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
void phys2d_reindex_body(cpBody *body) {
|
void phys2d_reindex_body(cpBody *body) { cpSpaceReindexShapesForBody(space, body); }
|
||||||
cpSpaceReindexShapesForBody(space, body);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct postphys_cb {
|
struct postphys_cb {
|
||||||
struct callee c;
|
struct callee c;
|
||||||
|
|
|
@ -23,6 +23,7 @@ extern struct rgba sleep_color;
|
||||||
|
|
||||||
struct phys2d_shape {
|
struct phys2d_shape {
|
||||||
cpShape *shape;
|
cpShape *shape;
|
||||||
|
transform2d t;
|
||||||
int go;
|
int go;
|
||||||
void *data; /* The specific subtype; phys2d_circle, etc */
|
void *data; /* The specific subtype; phys2d_circle, etc */
|
||||||
void (*debugdraw)(void *data);
|
void (*debugdraw)(void *data);
|
||||||
|
@ -48,16 +49,14 @@ struct phys2d_segment {
|
||||||
/* A convex polygon; defined as the convex hull around the given set of points */
|
/* A convex polygon; defined as the convex hull around the given set of points */
|
||||||
struct phys2d_poly {
|
struct phys2d_poly {
|
||||||
HMM_Vec2 *points;
|
HMM_Vec2 *points;
|
||||||
|
transform2d t;
|
||||||
float radius;
|
float radius;
|
||||||
struct phys2d_shape shape;
|
struct phys2d_shape shape;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* A box shape; a type of a polygon collider */
|
/* A box shape; a type of a polygon collider */
|
||||||
struct phys2d_box {
|
struct phys2d_box {
|
||||||
float w;
|
transform2d t; /* Scale here is used as width/height */
|
||||||
float h;
|
|
||||||
HMM_Vec2 offset;
|
|
||||||
float rotation;
|
|
||||||
float r; /* radius */
|
float r; /* radius */
|
||||||
struct phys2d_shape shape;
|
struct phys2d_shape shape;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
#include "3dphysics.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
btDefaultCollisionConfiguration *collisionConfig {
|
|
||||||
NULL};
|
|
||||||
btCollisionDispatcher *dispatcher {
|
|
||||||
NULL};
|
|
||||||
btBroadphaseInterface *overlappingPairCache {
|
|
||||||
NULL};
|
|
||||||
btSequentialImpulseConstraintSolver *solver {
|
|
||||||
NULL};
|
|
||||||
btDiscreteDynamicsWorld *dynamicsWorld {
|
|
||||||
NULL};
|
|
||||||
btRigidBody *worldFloor {
|
|
||||||
NULL};
|
|
||||||
|
|
||||||
void btUpdate()
|
|
||||||
{
|
|
||||||
// dynamicsWorld->stepSimulation(deltaT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void btInit()
|
|
||||||
{
|
|
||||||
// collisionConfig = new btDefaultCollisionConfiguration();
|
|
||||||
// dispatcher = new btCollisionDispatcher(collisionConfig);
|
|
||||||
// overlappingPairCache = new btDbvtBroadphase();
|
|
||||||
// solver = new btSequentialImpulseConstraintSolver;
|
|
||||||
// dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, overlappingPairCache, solver, collisionConfig);
|
|
||||||
// dynamicsWorld->setGravity(btVector3(0.f, -9.8f, 0.f));
|
|
||||||
// btDebugDrawer = new BulletDebugDrawer_OpenGL();
|
|
||||||
// dynamicsWorld->setDebugDrawer(btDebugDrawer);
|
|
||||||
|
|
||||||
|
|
||||||
//btDebugDrawer->setDebugMode(btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb);
|
|
||||||
// Add camera and plane to world
|
|
||||||
// dynamicsWorld->addRigidBody(camera.body);
|
|
||||||
// camera.body->setGravity(btVector3(0.f, 0.f, 0.f));
|
|
||||||
|
|
||||||
// Create and add plane
|
|
||||||
// btStaticPlaneShape* floorShape = new btStaticPlaneShape(btVector3(0.f, 1.f, 0.f), 0.f);
|
|
||||||
// btDefaultMotionState* motionState = new btDefaultMotionState();
|
|
||||||
// btVector3 bodyInertia;
|
|
||||||
// btRigidBody::btRigidBodyConstructionInfo bodyCI = btRigidBody::btRigidBodyConstructionInfo(0.f, motionState, floorShape, bodyInertia);
|
|
||||||
// worldFloor = new btRigidBody(bodyCI);
|
|
||||||
// dynamicsWorld->addRigidBody(worldFloor);
|
|
||||||
}
|
|
||||||
*/
|
|
|
@ -1,4 +0,0 @@
|
||||||
#ifndef THREEDPHYSICS_H
|
|
||||||
#define THREEDPHYSICS_H
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,5 +1,3 @@
|
||||||
// odplot productions is a trademarked name. Project Yugh is a copyrighted property. This code, however, is free to be copy and extended as you see fit.
|
|
||||||
|
|
||||||
#ifndef THIRDPERSONFOLLOW_H
|
#ifndef THIRDPERSONFOLLOW_H
|
||||||
#define THIRDPERSONFOLLOW_H
|
#define THIRDPERSONFOLLOW_H
|
||||||
|
|
||||||
|
@ -8,6 +6,7 @@
|
||||||
|
|
||||||
struct follow {
|
struct follow {
|
||||||
float distance;
|
float distance;
|
||||||
|
HMM_Vec3 offset;
|
||||||
HMM_Quat target_rot;
|
HMM_Quat target_rot;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
|
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
|
|
||||||
// #define HANDMADE_MATH_USE_TURNS
|
|
||||||
#include "HandmadeMath.h"
|
#include "HandmadeMath.h"
|
||||||
|
|
||||||
#include "math.h"
|
#include "math.h"
|
||||||
|
@ -100,11 +99,11 @@ struct model *GetExistingModel(const char *path) {
|
||||||
return MakeModel(path);
|
return MakeModel(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
cgltf_attribute *get_attr_type(cgltf_primitive p, cgltf_attribute_type t)
|
cgltf_attribute *get_attr_type(cgltf_primitive *p, cgltf_attribute_type t)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < p.attributes_count; i++) {
|
for (int i = 0; i < p->attributes_count; i++) {
|
||||||
if (p.attributes[i].type == t)
|
if (p->attributes[i].type == t)
|
||||||
return &p.attributes[i];
|
return &p->attributes[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -128,7 +127,193 @@ uint32_t pack_int10_n2(float *norm)
|
||||||
return (ni[0] & 0x3FF) | ( (ni[1] & 0x3FF) << 10) | ( (ni[2] & 0x3FF) << 20) | ( (0 & 0x3) << 30);
|
return (ni[0] & 0x3FF) | ( (ni[1] & 0x3FF) << 10) | ( (ni[2] & 0x3FF) << 20) | ( (0 & 0x3) << 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct model *MakeModel(const char *path) {
|
void mesh_add_material(mesh *mesh, cgltf_material *mat)
|
||||||
|
{
|
||||||
|
if (!mat) return;
|
||||||
|
|
||||||
|
if (mat && mat->has_pbr_metallic_roughness) {
|
||||||
|
cgltf_image *img = mat->pbr_metallic_roughness.base_color_texture.texture->image;
|
||||||
|
if (img->buffer_view) {
|
||||||
|
cgltf_buffer_view *buf = img->buffer_view;
|
||||||
|
mesh->bind.fs.images[0] = texture_fromdata(buf->buffer->data, buf->size)->id;
|
||||||
|
} else {
|
||||||
|
const char *imp = seprint("%s/%s", dirname(mesh->model->path), img->uri);
|
||||||
|
mesh->bind.fs.images[0] = texture_pullfromfile(imp)->id;
|
||||||
|
free(imp);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
// Get "no texture" tex
|
||||||
|
mesh->bind.fs.images[0] = texture_pullfromfile("k")->id;
|
||||||
|
mesh->bind.fs.samplers[0] = sg_make_sampler(&(sg_sampler_desc){});
|
||||||
|
|
||||||
|
cgltf_texture *tex;
|
||||||
|
if (tex = mat->normal_texture.texture)
|
||||||
|
mesh->bind.fs.images[1] = texture_pullfromfile(tex->image->uri)->id;
|
||||||
|
else
|
||||||
|
mesh->bind.fs.images[1] = texture_pullfromfile("k")->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mesh_add_primitive(mesh *mesh, cgltf_primitive *prim)
|
||||||
|
{
|
||||||
|
uint16_t *idxs;
|
||||||
|
if (prim->indices) {
|
||||||
|
int c = prim->indices->count;
|
||||||
|
idxs = malloc(sizeof(*idxs)*c);
|
||||||
|
memcpy(idxs, cgltf_buffer_view_data(prim->indices->buffer_view), sizeof(uint16_t) * c);
|
||||||
|
|
||||||
|
mesh->bind.index_buffer = sg_make_buffer(&(sg_buffer_desc){
|
||||||
|
.data.ptr = idxs,
|
||||||
|
.data.size = sizeof(uint16_t) * c,
|
||||||
|
.type = SG_BUFFERTYPE_INDEXBUFFER});
|
||||||
|
|
||||||
|
mesh->face_count = c;
|
||||||
|
} else {
|
||||||
|
YughWarn("Model does not have indices. Generating them.");
|
||||||
|
int c = prim->attributes[0].data->count;
|
||||||
|
mesh->face_count = c;
|
||||||
|
idxs = malloc(sizeof(*idxs)*c);
|
||||||
|
|
||||||
|
for (int z = 0; z < c; z++)
|
||||||
|
idxs[z] = z;
|
||||||
|
|
||||||
|
mesh->bind.index_buffer = sg_make_buffer(&(sg_buffer_desc){
|
||||||
|
.data.ptr = idxs,
|
||||||
|
.data.size = sizeof(uint16_t) * c,
|
||||||
|
.type = SG_BUFFERTYPE_INDEXBUFFER});
|
||||||
|
}
|
||||||
|
free(idxs);
|
||||||
|
|
||||||
|
mesh_add_material(mesh, prim->material);
|
||||||
|
int has_norm = 0;
|
||||||
|
|
||||||
|
for (int k = 0; k < prim->attributes_count; k++) {
|
||||||
|
cgltf_attribute attribute = prim->attributes[k];
|
||||||
|
|
||||||
|
int n = cgltf_accessor_unpack_floats(attribute.data, NULL, 0); /* floats per element x num elements */
|
||||||
|
float *vs = malloc(sizeof(float)*n);
|
||||||
|
cgltf_accessor_unpack_floats(attribute.data, vs, n);
|
||||||
|
|
||||||
|
uint32_t *packed_norms;
|
||||||
|
unsigned short *packed_coords;
|
||||||
|
|
||||||
|
|
||||||
|
switch (attribute.type) {
|
||||||
|
case cgltf_attribute_type_position:
|
||||||
|
|
||||||
|
mesh->bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
|
||||||
|
.data.ptr = vs,
|
||||||
|
.data.size = sizeof(float) * n});
|
||||||
|
break;
|
||||||
|
|
||||||
|
case cgltf_attribute_type_normal:
|
||||||
|
has_norm = 1;
|
||||||
|
packed_norms = malloc(mesh->face_count * sizeof(uint32_t));
|
||||||
|
for (int i = 0; i < mesh->face_count; i++)
|
||||||
|
packed_norms[i] = pack_int10_n2(vs + i*3);
|
||||||
|
|
||||||
|
mesh->bind.vertex_buffers[2] = sg_make_buffer(&(sg_buffer_desc){
|
||||||
|
.data.ptr = packed_norms,
|
||||||
|
.data.size = sizeof(uint32_t) * mesh->face_count});
|
||||||
|
|
||||||
|
free (packed_norms);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case cgltf_attribute_type_tangent:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case cgltf_attribute_type_color:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case cgltf_attribute_type_weights:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case cgltf_attribute_type_joints:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case cgltf_attribute_type_texcoord:
|
||||||
|
packed_coords = malloc(mesh->face_count * 2 * sizeof(unsigned short));
|
||||||
|
for (int i = 0; i < mesh->face_count*2; i++)
|
||||||
|
packed_coords[i] = pack_short_texcoord(vs[i]);
|
||||||
|
|
||||||
|
mesh->bind.vertex_buffers[1] = sg_make_buffer(&(sg_buffer_desc){
|
||||||
|
.data.ptr = packed_coords,
|
||||||
|
.data.size = sizeof(unsigned short) * 2 * mesh->face_count});
|
||||||
|
|
||||||
|
free(packed_coords);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
free(vs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!has_norm) {
|
||||||
|
uint32_t norms[mesh->face_count];
|
||||||
|
|
||||||
|
cgltf_attribute *pa = get_attr_type(prim, cgltf_attribute_type_position);
|
||||||
|
int n = cgltf_accessor_unpack_floats(pa->data, NULL,0);
|
||||||
|
float ps[n];
|
||||||
|
cgltf_accessor_unpack_floats(pa->data,ps,n);
|
||||||
|
|
||||||
|
for (int i = 0, face=0; i < mesh->face_count/3; i++, face+=9) {
|
||||||
|
int o = face;
|
||||||
|
HMM_Vec3 a = {ps[o], ps[o+1],ps[o+2]};
|
||||||
|
o += 3;
|
||||||
|
HMM_Vec3 b = {ps[o], ps[o+1],ps[o+2]};
|
||||||
|
o += 3;
|
||||||
|
HMM_Vec3 c = {ps[o], ps[o+1],ps[o+2]};
|
||||||
|
HMM_Vec3 norm = HMM_NormV3(HMM_Cross(HMM_SubV3(b,a), HMM_SubV3(c,a)));
|
||||||
|
|
||||||
|
uint32_t packed_norm = pack_int10_n2(norm.Elements);
|
||||||
|
for (int j = 0; j < 3; j++)
|
||||||
|
norms[i*3+j] = packed_norm;
|
||||||
|
}
|
||||||
|
mesh->bind.vertex_buffers[2] = sg_make_buffer(&(sg_buffer_desc){
|
||||||
|
.data.ptr = norms,
|
||||||
|
.data.size = sizeof(uint32_t) * mesh->face_count
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void model_add_cgltf_mesh(model *model, cgltf_mesh *gltf_mesh)
|
||||||
|
{
|
||||||
|
mesh mesh = {0};
|
||||||
|
mesh.model = model;
|
||||||
|
|
||||||
|
for (int i = 0; i < gltf_mesh->primitives_count; i++)
|
||||||
|
mesh_add_primitive(&mesh, &gltf_mesh->primitives[i]);
|
||||||
|
|
||||||
|
arrput(model->meshes,mesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
void model_add_cgltf_anim(model *model, cgltf_animation *anim)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void model_add_cgltf_skin(model *model, cgltf_skin *skin)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void model_process_node(model *model, cgltf_node *node)
|
||||||
|
{
|
||||||
|
if (node->has_matrix)
|
||||||
|
memcpy(model->matrix.Elements, node->matrix, sizeof(float)*16);
|
||||||
|
|
||||||
|
if (node->mesh)
|
||||||
|
model_add_cgltf_mesh(model, node->mesh);
|
||||||
|
|
||||||
|
if (node->skin)
|
||||||
|
model_add_cgltf_skin(model, node->skin);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 *MakeModel(const char *path)
|
||||||
|
{
|
||||||
YughInfo("Making the model from %s.", path);
|
YughInfo("Making the model from %s.", path);
|
||||||
cgltf_options options = {0};
|
cgltf_options options = {0};
|
||||||
cgltf_data *data = NULL;
|
cgltf_data *data = NULL;
|
||||||
|
@ -147,150 +332,17 @@ struct model *MakeModel(const char *path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct model *model = calloc(1, sizeof(*model));
|
struct model *model = calloc(1, sizeof(*model));
|
||||||
/* TODO: Optimize by grouping by material. One material per draw. */
|
|
||||||
YughInfo("Model has %d materials.", data->materials_count);
|
|
||||||
const char *dir = dirname(path);
|
|
||||||
|
|
||||||
float vs[65535*3];
|
model->path = path;
|
||||||
uint16_t idxs[65535];
|
|
||||||
|
|
||||||
for (int i = 0; i < data->meshes_count; i++) {
|
if (data->scenes_count == 0 || data->scenes_count > 1) return NULL;
|
||||||
cgltf_mesh *mesh = &data->meshes[i];
|
model_process_scene(model, data->scene);
|
||||||
struct mesh newmesh = {0};
|
|
||||||
arrput(model->meshes,newmesh);
|
|
||||||
|
|
||||||
YughInfo("Making mesh %d. It has %d primitives.", i, mesh->primitives_count);
|
for (int i = 0; i < data->meshes_count; i++)
|
||||||
|
model_add_cgltf_mesh(model, &data->meshes[i]);
|
||||||
|
|
||||||
for (int j = 0; j < mesh->primitives_count; j++) {
|
for (int i = 0; i < data->animations_count; i++)
|
||||||
cgltf_primitive primitive = mesh->primitives[j];
|
model_add_cgltf_anim(model, &data->animations[i]);
|
||||||
|
|
||||||
if (primitive.indices) {
|
|
||||||
int c = primitive.indices->count;
|
|
||||||
memcpy(idxs, cgltf_buffer_view_data(primitive.indices->buffer_view), sizeof(uint16_t) * c);
|
|
||||||
|
|
||||||
model->meshes[j].bind.index_buffer = sg_make_buffer(&(sg_buffer_desc){
|
|
||||||
.data.ptr = idxs,
|
|
||||||
.data.size = sizeof(uint16_t) * c,
|
|
||||||
.type = SG_BUFFERTYPE_INDEXBUFFER});
|
|
||||||
|
|
||||||
model->meshes[j].face_count = c;
|
|
||||||
} else {
|
|
||||||
YughWarn("Model does not have indices. Generating them.");
|
|
||||||
int c = primitive.attributes[0].data->count;
|
|
||||||
model->meshes[j].face_count = c;
|
|
||||||
for (int z = 0; z < c; z++)
|
|
||||||
idxs[z] = z;
|
|
||||||
|
|
||||||
model->meshes[j].bind.index_buffer = sg_make_buffer(&(sg_buffer_desc){
|
|
||||||
.data.ptr = idxs,
|
|
||||||
.data.size = sizeof(uint16_t) * c,
|
|
||||||
.type = SG_BUFFERTYPE_INDEXBUFFER});
|
|
||||||
}
|
|
||||||
|
|
||||||
struct cgltf_material *mat = primitive.material;
|
|
||||||
|
|
||||||
if (mat && primitive.material->has_pbr_metallic_roughness) {
|
|
||||||
cgltf_image *img = primitive.material->pbr_metallic_roughness.base_color_texture.texture->image;
|
|
||||||
if (img->buffer_view) {
|
|
||||||
cgltf_buffer_view *buf = img->buffer_view;
|
|
||||||
model->meshes[j].bind.fs.images[0] = texture_fromdata(buf->buffer->data, buf->size)->id;
|
|
||||||
} else {
|
|
||||||
const char *imp = seprint("%s/%s", dir, img->uri);
|
|
||||||
model->meshes[j].bind.fs.images[0] = texture_pullfromfile(imp)->id;
|
|
||||||
free(imp);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
model->meshes[j].bind.fs.images[0] = texture_pullfromfile("k")->id;
|
|
||||||
|
|
||||||
model->meshes[j].bind.fs.samplers[0] = sg_make_sampler(&(sg_sampler_desc){});
|
|
||||||
|
|
||||||
cgltf_texture *tex;
|
|
||||||
// if (tex = primitive.material->normal_texture.texture) {
|
|
||||||
// model->meshes[j].bind.fs.images[1] = texture_pullfromfile(tex->image->uri)->id;
|
|
||||||
// }// else
|
|
||||||
// model->meshes[j].bind.fs.images[1] = texture_pullfromfile("k")->id;
|
|
||||||
|
|
||||||
int has_norm = 0;
|
|
||||||
|
|
||||||
for (int k = 0; k < primitive.attributes_count; k++) {
|
|
||||||
cgltf_attribute attribute = primitive.attributes[k];
|
|
||||||
|
|
||||||
int n = cgltf_accessor_unpack_floats(attribute.data, NULL, 0); /* floats per element x num elements */
|
|
||||||
|
|
||||||
cgltf_accessor_unpack_floats(attribute.data, vs, n);
|
|
||||||
|
|
||||||
uint32_t *packed_norms;
|
|
||||||
unsigned short *packed_coords;
|
|
||||||
|
|
||||||
switch (attribute.type) {
|
|
||||||
case cgltf_attribute_type_position:
|
|
||||||
|
|
||||||
model->meshes[j].bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
|
|
||||||
.data.ptr = vs,
|
|
||||||
.data.size = sizeof(float) * n});
|
|
||||||
break;
|
|
||||||
|
|
||||||
case cgltf_attribute_type_normal:
|
|
||||||
has_norm = 1;
|
|
||||||
packed_norms = malloc(model->meshes[j].face_count * sizeof(uint32_t));;
|
|
||||||
for (int i = 0; i < model->meshes[j].face_count; i++)
|
|
||||||
packed_norms[i] = pack_int10_n2(vs + i*3);
|
|
||||||
|
|
||||||
// model->meshes[j].bind.vertex_buffers[2] = sg_make_buffer(&(sg_buffer_desc){
|
|
||||||
// .data.ptr = packed_norms,
|
|
||||||
// .data.size = sizeof(uint32_t) * model->meshes[j].face_count});
|
|
||||||
|
|
||||||
free (packed_norms);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case cgltf_attribute_type_tangent:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case cgltf_attribute_type_texcoord:
|
|
||||||
packed_coords = malloc(model->meshes[j].face_count * 2 * sizeof(unsigned short));
|
|
||||||
for (int i = 0; i < model->meshes[j].face_count*2; i++)
|
|
||||||
packed_coords[i] = pack_short_texcoord(vs[i]);
|
|
||||||
|
|
||||||
model->meshes[j].bind.vertex_buffers[1] = sg_make_buffer(&(sg_buffer_desc){
|
|
||||||
.data.ptr = packed_coords,
|
|
||||||
.data.size = sizeof(unsigned short) * 2 * model->meshes[j].face_count});
|
|
||||||
|
|
||||||
free(packed_coords);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!has_norm) {
|
|
||||||
YughInfo("Model does not have normals. Generating them.");
|
|
||||||
uint32_t norms[model->meshes[j].face_count];
|
|
||||||
|
|
||||||
|
|
||||||
cgltf_attribute *pa = get_attr_type(primitive, cgltf_attribute_type_position);
|
|
||||||
int n = cgltf_accessor_unpack_floats(pa->data, NULL,0);
|
|
||||||
float ps[n];
|
|
||||||
cgltf_accessor_unpack_floats(pa->data,ps,n);
|
|
||||||
|
|
||||||
for (int i = 0, face=0; i < model->meshes[j].face_count/3; i++, face+=9) {
|
|
||||||
int o = face;
|
|
||||||
HMM_Vec3 a = {ps[o], ps[o+1],ps[o+2]};
|
|
||||||
o += 3;
|
|
||||||
HMM_Vec3 b = {ps[o], ps[o+1],ps[o+2]};
|
|
||||||
o += 3;
|
|
||||||
HMM_Vec3 c = {ps[o], ps[o+1],ps[o+2]};
|
|
||||||
HMM_Vec3 norm = HMM_NormV3(HMM_Cross(HMM_SubV3(b,a), HMM_SubV3(c,a)));
|
|
||||||
|
|
||||||
uint32_t packed_norm = pack_int10_n2(norm.Elements);
|
|
||||||
for (int j = 0; j < 3; j++)
|
|
||||||
norms[i*3+j] = packed_norm;
|
|
||||||
}
|
|
||||||
|
|
||||||
// model->meshes[j].bind.vertex_buffers[2] = sg_make_buffer(&(sg_buffer_desc){
|
|
||||||
// .data.ptr = norms,
|
|
||||||
// .data.size = sizeof(uint32_t) * model->meshes[j].face_count
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
shput(modelhash, path, model);
|
shput(modelhash, path, model);
|
||||||
|
|
||||||
|
|
|
@ -8,16 +8,25 @@
|
||||||
extern HMM_Vec3 eye;
|
extern HMM_Vec3 eye;
|
||||||
struct shader;
|
struct shader;
|
||||||
|
|
||||||
|
typedef struct material {
|
||||||
|
|
||||||
|
} material;
|
||||||
|
|
||||||
|
struct model;
|
||||||
|
|
||||||
/* A single mesh */
|
/* A single mesh */
|
||||||
struct mesh {
|
typedef struct mesh {
|
||||||
sg_bindings bind;
|
sg_bindings bind; /* Encapsulates material, norms, etc */
|
||||||
uint32_t face_count;
|
uint32_t face_count;
|
||||||
};
|
struct model *model;
|
||||||
|
} mesh;
|
||||||
|
|
||||||
/* A collection of meshes which create a full figure */
|
/* A collection of meshes which create a full figure */
|
||||||
struct model {
|
typedef struct model {
|
||||||
struct mesh *meshes;
|
struct mesh *meshes;
|
||||||
};
|
const char *path;
|
||||||
|
HMM_Mat4 matrix;
|
||||||
|
} model;
|
||||||
|
|
||||||
/* A model with draw information */
|
/* A model with draw information */
|
||||||
struct drawmodel {
|
struct drawmodel {
|
||||||
|
|
|
@ -228,6 +228,8 @@ typedef union HMM_Vec3 {
|
||||||
float X, Y, Z;
|
float X, Y, Z;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct { float x, y, z; };
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
float U, V, W;
|
float U, V, W;
|
||||||
|
@ -244,6 +246,13 @@ typedef union HMM_Vec3 {
|
||||||
float _Ignored0;
|
float _Ignored0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
HMM_Vec2 xy;
|
||||||
|
float _Ignored4;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
float _Ignored1;
|
float _Ignored1;
|
||||||
|
@ -268,6 +277,28 @@ typedef union HMM_Vec3 {
|
||||||
|
|
||||||
static const HMM_Vec3 v3zero = {0,0,0};
|
static const HMM_Vec3 v3zero = {0,0,0};
|
||||||
|
|
||||||
|
typedef union HMM_Quat {
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
HMM_Vec3 XYZ;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
float X, Y, Z;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
float W;
|
||||||
|
};
|
||||||
|
|
||||||
|
float Elements[4];
|
||||||
|
|
||||||
|
#ifdef HANDMADE_MATH__USE_SSE
|
||||||
|
__m128 SSE;
|
||||||
|
#endif
|
||||||
|
} HMM_Quat;
|
||||||
|
|
||||||
|
|
||||||
typedef union HMM_Vec4 {
|
typedef union HMM_Vec4 {
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
@ -277,6 +308,7 @@ typedef union HMM_Vec4 {
|
||||||
{
|
{
|
||||||
float X, Y, Z;
|
float X, Y, Z;
|
||||||
};
|
};
|
||||||
|
HMM_Vec3 xyz;
|
||||||
};
|
};
|
||||||
|
|
||||||
float W;
|
float W;
|
||||||
|
@ -301,6 +333,23 @@ typedef union HMM_Vec4 {
|
||||||
float _Ignored1;
|
float _Ignored1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct {
|
||||||
|
HMM_Vec2 xy;
|
||||||
|
float _ig0;
|
||||||
|
float _ig1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct {
|
||||||
|
HMM_Vec2 _2;
|
||||||
|
float _ig2;
|
||||||
|
float _ig3;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct {
|
||||||
|
HMM_Vec3 _3;
|
||||||
|
float _ig4;
|
||||||
|
};
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
float _Ignored2;
|
float _Ignored2;
|
||||||
|
@ -315,6 +364,8 @@ typedef union HMM_Vec4 {
|
||||||
HMM_Vec2 ZW;
|
HMM_Vec2 ZW;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
HMM_Quat quat;
|
||||||
|
|
||||||
float Elements[4];
|
float Elements[4];
|
||||||
|
|
||||||
#ifdef HANDMADE_MATH__USE_SSE
|
#ifdef HANDMADE_MATH__USE_SSE
|
||||||
|
@ -341,26 +392,6 @@ typedef union HMM_Mat4 {
|
||||||
|
|
||||||
} HMM_Mat4;
|
} HMM_Mat4;
|
||||||
|
|
||||||
typedef union HMM_Quat {
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
union {
|
|
||||||
HMM_Vec3 XYZ;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
float X, Y, Z;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
float W;
|
|
||||||
};
|
|
||||||
|
|
||||||
float Elements[4];
|
|
||||||
|
|
||||||
#ifdef HANDMADE_MATH__USE_SSE
|
|
||||||
__m128 SSE;
|
|
||||||
#endif
|
|
||||||
} HMM_Quat;
|
|
||||||
|
|
||||||
typedef signed int HMM_Bool;
|
typedef signed int HMM_Bool;
|
||||||
|
|
||||||
|
@ -552,6 +583,7 @@ static inline HMM_Vec2 HMM_AddV2(HMM_Vec2 Left, HMM_Vec2 Right) {
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline HMM_Vec3 HMM_AddV3(HMM_Vec3 Left, HMM_Vec3 Right) {
|
static inline HMM_Vec3 HMM_AddV3(HMM_Vec3 Left, HMM_Vec3 Right) {
|
||||||
|
|
||||||
HMM_Vec3 Result;
|
HMM_Vec3 Result;
|
||||||
|
@ -776,6 +808,8 @@ static inline float HMM_DotV2(HMM_Vec2 Left, HMM_Vec2 Right) {
|
||||||
return (Left.X * Right.X) + (Left.Y * Right.Y);
|
return (Left.X * Right.X) + (Left.Y * Right.Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static inline HMM_Vec2 HMM_ProjV2(HMM_Vec2 a, HMM_Vec2 b)
|
static inline HMM_Vec2 HMM_ProjV2(HMM_Vec2 a, HMM_Vec2 b)
|
||||||
{
|
{
|
||||||
return HMM_MulV2F(b, HMM_DotV2(a,b)/HMM_DotV2(b,b));
|
return HMM_MulV2F(b, HMM_DotV2(a,b)/HMM_DotV2(b,b));
|
||||||
|
@ -836,6 +870,11 @@ static inline float HMM_LenV2(HMM_Vec2 A) {
|
||||||
return HMM_SqrtF(HMM_LenSqrV2(A));
|
return HMM_SqrtF(HMM_LenSqrV2(A));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline float HMM_AngleV2(HMM_Vec2 a, HMM_Vec2 b)
|
||||||
|
{
|
||||||
|
return acos(HMM_DotV2(a,b)/(HMM_LenV2(a)*HMM_LenV2(b)));
|
||||||
|
}
|
||||||
|
|
||||||
static inline float HMM_DistV2(HMM_Vec2 a, HMM_Vec2 b) {
|
static inline float HMM_DistV2(HMM_Vec2 a, HMM_Vec2 b) {
|
||||||
return HMM_LenV2(HMM_SubV2(a,b));
|
return HMM_LenV2(HMM_SubV2(a,b));
|
||||||
}
|
}
|
||||||
|
@ -844,10 +883,20 @@ static inline float HMM_LenV3(HMM_Vec3 A) {
|
||||||
return HMM_SqrtF(HMM_LenSqrV3(A));
|
return HMM_SqrtF(HMM_LenSqrV3(A));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline float HMM_AngleV3(HMM_Vec3 a, HMM_Vec3 b)
|
||||||
|
{
|
||||||
|
return acos(HMM_DotV3(a,b)/(HMM_LenV3(a)*HMM_LenV3(b)));
|
||||||
|
}
|
||||||
|
|
||||||
static inline float HMM_LenV4(HMM_Vec4 A) {
|
static inline float HMM_LenV4(HMM_Vec4 A) {
|
||||||
return HMM_SqrtF(HMM_LenSqrV4(A));
|
return HMM_SqrtF(HMM_LenSqrV4(A));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline float HMM_AngleV4(HMM_Vec4 a, HMM_Vec4 b)
|
||||||
|
{
|
||||||
|
return acos(HMM_DotV4(a,b)/(HMM_LenV4(a)*HMM_LenV4(b)));
|
||||||
|
}
|
||||||
|
|
||||||
static inline HMM_Vec2 HMM_NormV2(HMM_Vec2 A) {
|
static inline HMM_Vec2 HMM_NormV2(HMM_Vec2 A) {
|
||||||
// HMM_MulV2F(A, 1.0/HMM_LenV2(A)+FLOAT_MIN);
|
// HMM_MulV2F(A, 1.0/HMM_LenV2(A)+FLOAT_MIN);
|
||||||
return HMM_MulV2F(A, HMM_InvSqrtF(HMM_DotV2(A, A)));
|
return HMM_MulV2F(A, HMM_InvSqrtF(HMM_DotV2(A, A)));
|
||||||
|
@ -953,6 +1002,7 @@ static inline HMM_Mat2 HMM_RotateM2(float angle)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline HMM_Mat2 HMM_AddM2(HMM_Mat2 Left, HMM_Mat2 Right) {
|
static inline HMM_Mat2 HMM_AddM2(HMM_Mat2 Left, HMM_Mat2 Right) {
|
||||||
|
|
||||||
HMM_Mat2 Result;
|
HMM_Mat2 Result;
|
||||||
|
@ -1058,6 +1108,29 @@ static inline HMM_Mat3 HMM_M3D(float Diagonal) {
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline HMM_Mat3 HMM_Translate2D(HMM_Vec2 p)
|
||||||
|
{
|
||||||
|
HMM_Mat3 res = HMM_M3D(1);
|
||||||
|
res.Columns[2].XY = p;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline HMM_Mat3 HMM_RotateM3(float angle)
|
||||||
|
{
|
||||||
|
HMM_Mat3 r = HMM_M3D(1);
|
||||||
|
r.Columns[0] = (HMM_Vec3){cos(angle), sin(angle), 0};
|
||||||
|
r.Columns[1] = (HMM_Vec3){-sin(angle), cos(angle), 0};
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline HMM_Mat3 HMM_ScaleM3(HMM_Vec2 s)
|
||||||
|
{
|
||||||
|
HMM_Mat3 sm = HMM_M3D(1);
|
||||||
|
sm.Columns[0].X = s.x;
|
||||||
|
sm.Columns[1].Y = s.y;
|
||||||
|
return sm;
|
||||||
|
}
|
||||||
|
|
||||||
static inline HMM_Mat3 HMM_TransposeM3(HMM_Mat3 Matrix) {
|
static inline HMM_Mat3 HMM_TransposeM3(HMM_Mat3 Matrix) {
|
||||||
|
|
||||||
HMM_Mat3 Result = Matrix;
|
HMM_Mat3 Result = Matrix;
|
||||||
|
@ -1200,12 +1273,11 @@ 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)
|
static inline HMM_Mat3 HMM_M2Basis(HMM_Mat2 basis)
|
||||||
{
|
{
|
||||||
HMM_Mat3 m;
|
HMM_Mat3 m;
|
||||||
m.Columns[0].XY = basis.Columns[0];
|
m.Columns[0].XY = basis.Columns[0];
|
||||||
m.Columns[1].XY = basis.Columns[1];
|
m.Columns[1].XY = basis.Columns[1];
|
||||||
m.Columns[2].XY = pos;
|
|
||||||
m.Columns[2].Z = 1;
|
m.Columns[2].Z = 1;
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,59 +2,53 @@
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "stb_ds.h"
|
#include "stb_ds.h"
|
||||||
|
|
||||||
struct anim make_anim() {
|
HMM_Vec4 sample_linear(sampler *sampler, float time, int prev, int next)
|
||||||
struct anim a = {0};
|
{
|
||||||
a.interp = 1;
|
if (sampler->rotation)
|
||||||
|
return (HMM_Vec4)HMM_SLerp(sampler->data[prev].quat, time, sampler->data[next].quat);
|
||||||
return a;
|
else
|
||||||
|
return HMM_LerpV4(sampler->data[prev], time, sampler->data[next]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_anim(struct anim a) {
|
HMM_Vec4 sample_cubicspline(sampler *sampler, float t, int prev, int next)
|
||||||
arrfree(a.frames);
|
{
|
||||||
|
float t2 = t*t;
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct anim anim_add_keyframe(struct anim a, struct keyframe key) {
|
HMM_Vec4 sample_sampler(sampler *sampler, float time)
|
||||||
arrput(a.frames, key);
|
{
|
||||||
|
int previous_time=0;
|
||||||
|
int next_time=0;
|
||||||
|
|
||||||
return a;
|
for (int i = 1; i < arrlen(sampler->times); i++) {
|
||||||
|
if (time < sampler->times[i]) {
|
||||||
|
previous_time = sampler->times[i-1];
|
||||||
|
next_time = sampler->times[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double interval(struct keyframe a, struct keyframe b, double t) {
|
float td = sampler->times[next_time]-sampler->times[previous_time];
|
||||||
return (t - a.time) / (b.time - a.time);
|
float t = (time - sampler->times[previous_time])/td;
|
||||||
|
|
||||||
|
|
||||||
|
switch(sampler->type) {
|
||||||
|
case LINEAR:
|
||||||
|
return sample_linear(sampler,t,previous_time,next_time);
|
||||||
|
break;
|
||||||
|
case STEP:
|
||||||
|
return sampler->data[previous_time];
|
||||||
|
break;
|
||||||
|
case CUBICSPLINE:
|
||||||
|
return sample_cubicspline(sampler,t, previous_time, next_time);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
double near_val(struct anim anim, double t) {
|
|
||||||
for (int i = 0; i < arrlen(anim.frames) - 1; i++) {
|
|
||||||
|
|
||||||
if (t > anim.frames[i + 1].time)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
return (interval(anim.frames[i], anim.frames[i + 1], t) >= 0.5f ? anim.frames[i + 1].val : anim.frames[i].val);
|
|
||||||
}
|
|
||||||
|
|
||||||
return arrlast(anim.frames).val;
|
|
||||||
}
|
|
||||||
|
|
||||||
double lerp_val(struct anim anim, double t) {
|
|
||||||
|
|
||||||
for (int i = 0; i < arrlen(anim.frames) - 1; i++) {
|
|
||||||
if (t > anim.frames[i + 1].time)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
double intv = interval(anim.frames[i], anim.frames[i + 1], t);
|
|
||||||
return ((1 - intv) * anim.frames[i].val) + (intv * anim.frames[i + 1].val);
|
|
||||||
}
|
|
||||||
|
|
||||||
return arrlast(anim.frames).val;
|
|
||||||
}
|
|
||||||
|
|
||||||
double cubic_val(struct anim anim, double t) {
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
double anim_val(struct anim anim, double t) {
|
|
||||||
if (anim.interp == 0)
|
|
||||||
return near_val(anim, t);
|
|
||||||
|
|
||||||
return lerp_val(anim, t);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,34 @@
|
||||||
#ifndef ANIM_H
|
#ifndef ANIM_H
|
||||||
#define ANIM_H
|
#define ANIM_H
|
||||||
|
|
||||||
|
#include "HandmadeMath.h"
|
||||||
|
|
||||||
struct keyframe {
|
struct keyframe {
|
||||||
double time;
|
double time;
|
||||||
double val;
|
double val;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct anim {
|
#define LINEAR 0
|
||||||
struct keyframe *frames;
|
#define STEP 1
|
||||||
int loop;
|
#define CUBICSPLINE 2
|
||||||
int interp;
|
|
||||||
|
typedef struct sampler {
|
||||||
|
float *times;
|
||||||
|
HMM_Vec4 *data;
|
||||||
|
int type;
|
||||||
|
int rotation;
|
||||||
|
} sampler;
|
||||||
|
|
||||||
|
struct anim_channel {
|
||||||
|
sampler *sampler;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct anim make_anim();
|
struct animation {
|
||||||
struct anim anim_add_keyframe(struct anim a, struct keyframe f);
|
char *name;
|
||||||
double anim_val(struct anim anim, double t);
|
double time;
|
||||||
|
struct anim_channel *channels;
|
||||||
|
};
|
||||||
|
|
||||||
|
HMM_Vec4 sample_sampler(sampler *sampler, float time);
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -1,13 +1,7 @@
|
||||||
#include "gameobject.h"
|
#include "gameobject.h"
|
||||||
|
|
||||||
#include "2dphysics.h"
|
#include "2dphysics.h"
|
||||||
#include "debugdraw.h"
|
|
||||||
#include "input.h"
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "resources.h"
|
|
||||||
#include "script.h"
|
|
||||||
#include "shader.h"
|
|
||||||
#include "sprite.h"
|
|
||||||
#include <chipmunk/chipmunk.h>
|
#include <chipmunk/chipmunk.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "debugdraw.h"
|
#include "debugdraw.h"
|
||||||
|
@ -82,8 +76,6 @@ HMM_Vec2 go2world(struct gameobject *go, HMM_Vec2 pos) { return mat_t_pos(t_go2w
|
||||||
|
|
||||||
HMM_Vec2 world2go(struct gameobject *go, HMM_Vec2 pos) { return mat_t_pos(t_world2go(go), pos); }
|
HMM_Vec2 world2go(struct gameobject *go, HMM_Vec2 pos) { return mat_t_pos(t_world2go(go), pos); }
|
||||||
|
|
||||||
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_go2world(struct gameobject *go) { return transform2d2mat(go2t(go)); }
|
||||||
|
|
||||||
HMM_Mat3 t_world2go(struct gameobject *go) { return HMM_InvGeneralM3(t_go2world(go)); }
|
HMM_Mat3 t_world2go(struct gameobject *go) { return HMM_InvGeneralM3(t_go2world(go)); }
|
||||||
|
@ -94,9 +86,8 @@ HMM_Mat4 t3d_world2go(struct gameobject *go) { return HMM_InvGeneralM4(t3d_go2wo
|
||||||
int pos2gameobject(HMM_Vec2 pos) {
|
int pos2gameobject(HMM_Vec2 pos) {
|
||||||
cpShape *hit = phys2d_query_pos(pos.cp);
|
cpShape *hit = phys2d_query_pos(pos.cp);
|
||||||
|
|
||||||
if (hit) {
|
if (hit)
|
||||||
return shape2gameobject(hit);
|
return shape2gameobject(hit);
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < arrlen(gameobjects); i++) {
|
for (int i = 0; i < arrlen(gameobjects); i++) {
|
||||||
if (!gameobjects[i].body) continue;
|
if (!gameobjects[i].body) continue;
|
||||||
|
@ -290,23 +281,6 @@ void gameobjects_cleanup() {
|
||||||
arrsetlen(go_toclean, 0);
|
arrsetlen(go_toclean, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gameobject_move(struct gameobject *go, HMM_Vec2 vec) {
|
|
||||||
cpVect p = cpBodyGetPosition(go->body);
|
|
||||||
p.x += vec.x;
|
|
||||||
p.y += vec.y;
|
|
||||||
cpBodySetPosition(go->body, p);
|
|
||||||
|
|
||||||
phys2d_reindex_body(go->body);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gameobject_rotate(struct gameobject *go, float as) {
|
|
||||||
cpFloat a = cpBodyGetAngle(go->body);
|
|
||||||
a += as * deltaT;
|
|
||||||
cpBodySetAngle(go->body, a);
|
|
||||||
|
|
||||||
phys2d_reindex_body(go->body);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gameobject_setangle(struct gameobject *go, float angle) {
|
void gameobject_setangle(struct gameobject *go, float angle) {
|
||||||
cpBodySetAngle(go->body, angle);
|
cpBodySetAngle(go->body, angle);
|
||||||
phys2d_reindex_body(go->body);
|
phys2d_reindex_body(go->body);
|
||||||
|
@ -315,7 +289,6 @@ void gameobject_setangle(struct gameobject *go, float angle) {
|
||||||
void gameobject_setpos(struct gameobject *go, cpVect vec) {
|
void gameobject_setpos(struct gameobject *go, cpVect vec) {
|
||||||
if (!go || !go->body) return;
|
if (!go || !go->body) return;
|
||||||
cpBodySetPosition(go->body, vec);
|
cpBodySetPosition(go->body, vec);
|
||||||
|
|
||||||
phys2d_reindex_body(go->body);
|
phys2d_reindex_body(go->body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,13 +302,6 @@ void gameobject_draw_debug(int go) {
|
||||||
if (!g || !g->body) return;
|
if (!g || !g->body) return;
|
||||||
|
|
||||||
cpVect pos = cpBodyGetPosition(g->body);
|
cpVect pos = cpBodyGetPosition(g->body);
|
||||||
struct rgba color = {
|
|
||||||
.r = 0.76*255,
|
|
||||||
.b = 0.38*255,
|
|
||||||
.g = 255,
|
|
||||||
.a = 255
|
|
||||||
};
|
|
||||||
|
|
||||||
cpBodyEachShape(g->body, body_draw_shapes_dbg, NULL);
|
cpBodyEachShape(g->body, body_draw_shapes_dbg, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,7 @@
|
||||||
#define GAMEOBJECT_H
|
#define GAMEOBJECT_H
|
||||||
|
|
||||||
#include "2dphysics.h"
|
#include "2dphysics.h"
|
||||||
#include "config.h"
|
|
||||||
#include <chipmunk/chipmunk.h>
|
#include <chipmunk/chipmunk.h>
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "quickjs/quickjs.h"
|
#include "quickjs/quickjs.h"
|
||||||
#include "HandmadeMath.h"
|
#include "HandmadeMath.h"
|
||||||
#include "transform.h"
|
#include "transform.h"
|
||||||
|
@ -29,10 +26,6 @@
|
||||||
dag_rm(p->parent,p);\
|
dag_rm(p->parent,p);\
|
||||||
}while(0)
|
}while(0)
|
||||||
|
|
||||||
struct shader;
|
|
||||||
struct sprite;
|
|
||||||
struct component;
|
|
||||||
|
|
||||||
typedef struct gameobject {
|
typedef struct gameobject {
|
||||||
cpBodyType bodytype;
|
cpBodyType bodytype;
|
||||||
cpBody *body; /* NULL if this object is dead; has 2d position and rotation, relative to global 0 */
|
cpBody *body; /* NULL if this object is dead; has 2d position and rotation, relative to global 0 */
|
||||||
|
@ -49,7 +42,6 @@ typedef struct gameobject {
|
||||||
float damping;
|
float damping;
|
||||||
unsigned int layer;
|
unsigned int layer;
|
||||||
cpShapeFilter filter;
|
cpShapeFilter filter;
|
||||||
int id;
|
|
||||||
struct phys_cbs cbs;
|
struct phys_cbs cbs;
|
||||||
struct shape_cb *shape_cbs;
|
struct shape_cb *shape_cbs;
|
||||||
JSValue ref;
|
JSValue ref;
|
||||||
|
@ -89,11 +81,6 @@ float go_worldangle(struct gameobject *go);
|
||||||
|
|
||||||
float go2angle(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);
|
|
||||||
|
|
||||||
struct gameobject *id2go(int id);
|
struct gameobject *id2go(int id);
|
||||||
int go2id(struct gameobject *go);
|
int go2id(struct gameobject *go);
|
||||||
int body2id(cpBody *body);
|
int body2id(cpBody *body);
|
||||||
|
|
|
@ -11,8 +11,6 @@
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
#include "resources.h"
|
#include "resources.h"
|
||||||
|
|
||||||
float deltaT = 0;
|
|
||||||
|
|
||||||
static int mouse_states[3] = {INPUT_UP};
|
static int mouse_states[3] = {INPUT_UP};
|
||||||
static int key_states[512] = {INPUT_UP};
|
static int key_states[512] = {INPUT_UP};
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,6 @@ extern HMM_Vec2 mouse_delta;
|
||||||
#define INPUT_UP 1
|
#define INPUT_UP 1
|
||||||
#define INPUT_REPEAT 2
|
#define INPUT_REPEAT 2
|
||||||
|
|
||||||
extern float deltaT;
|
|
||||||
|
|
||||||
void input_init();
|
void input_init();
|
||||||
void input_poll(double wait);
|
void input_poll(double wait);
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,8 @@
|
||||||
#include "sprite.h"
|
#include "sprite.h"
|
||||||
#include "stb_ds.h"
|
#include "stb_ds.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "tinyspline.h"
|
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
#include "spline.h"
|
||||||
#include "yugine.h"
|
#include "yugine.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "resources.h"
|
#include "resources.h"
|
||||||
|
@ -53,8 +53,8 @@ static JSValue TYPE##2js(TYPE *n) { \
|
||||||
|
|
||||||
QJSCLASS(dsp_node)
|
QJSCLASS(dsp_node)
|
||||||
|
|
||||||
// gamobject2js, js2gameobject deals with gameobject*
|
// gameobject2js, js2gameobject deals with gameobject*, converted to ids
|
||||||
// go2js,js2go deals with gameobject ids
|
// go2js,js2go deals with gameobject*
|
||||||
|
|
||||||
QJSCLASS(gameobject)
|
QJSCLASS(gameobject)
|
||||||
|
|
||||||
|
@ -97,7 +97,6 @@ JSValue gos2ref(int *go)
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
JSValue js_getpropstr(JSValue v, const char *str)
|
JSValue js_getpropstr(JSValue v, const char *str)
|
||||||
{
|
{
|
||||||
JSValue p = JS_GetPropertyStr(js,v,str);
|
JSValue p = JS_GetPropertyStr(js,v,str);
|
||||||
|
@ -399,42 +398,23 @@ JSValue bb2js(struct boundingbox bb)
|
||||||
}
|
}
|
||||||
|
|
||||||
JSValue duk_spline_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
|
JSValue duk_spline_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
|
||||||
// static_assert(sizeof(tsReal) * 2 == sizeof(HMM_Vec2));
|
int degrees = js2int(argv[1]); /* not used */
|
||||||
|
int d = js2int(argv[2]); /* dimensions: 1d, 2d, 3d ...*/
|
||||||
tsBSpline spline;
|
/*
|
||||||
|
0: hermite-cubic
|
||||||
int degrees = js2int(argv[1]);
|
1: catmull-rom
|
||||||
int d = js2int(argv[2]); /* dimensions */
|
2: b-spline
|
||||||
|
3: bezier
|
||||||
|
*/
|
||||||
int type = js2int(argv[3]);
|
int type = js2int(argv[3]);
|
||||||
HMM_Vec2 *points = js2cpvec2arr(argv[4]);
|
HMM_Vec2 *points = js2cpvec2arr(argv[4]);
|
||||||
size_t nsamples = js2int(argv[5]);
|
size_t nsamples = js2int(argv[5]);
|
||||||
|
|
||||||
tsStatus status;
|
HMM_Vec2 *samples = catmull_rom_ma_v2(points, nsamples);
|
||||||
ts_bspline_new(arrlen(points), d, degrees, type, &spline, &status);
|
|
||||||
|
|
||||||
if (status.code)
|
|
||||||
YughCritical("Spline creation error %d: %s", status.code, status.message);
|
|
||||||
|
|
||||||
ts_bspline_set_control_points(&spline, (tsReal*)points, &status);
|
|
||||||
|
|
||||||
if (status.code)
|
|
||||||
YughCritical("Spline creation error %d: %s", status.code, status.message);
|
|
||||||
|
|
||||||
HMM_Vec2 *samples = malloc(nsamples*sizeof(HMM_Vec2));
|
|
||||||
|
|
||||||
size_t rsamples;
|
|
||||||
/* TODO: This does not work with Clang/GCC due to UB */
|
|
||||||
ts_bspline_sample(&spline, nsamples, (tsReal **)&samples, &rsamples, &status);
|
|
||||||
|
|
||||||
if (status.code)
|
|
||||||
YughCritical("Spline creation error %d: %s", status.code, status.message);
|
|
||||||
|
|
||||||
JSValue arr = vecarr2js(samples, nsamples);
|
JSValue arr = vecarr2js(samples, nsamples);
|
||||||
|
|
||||||
ts_bspline_free(&spline);
|
|
||||||
free(samples);
|
free(samples);
|
||||||
|
|
||||||
return arr;
|
return JS_UNDEFINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSValue ints2js(int *ints) {
|
JSValue ints2js(int *ints) {
|
||||||
|
@ -523,6 +503,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
const char *str2 = NULL;
|
const char *str2 = NULL;
|
||||||
const void *d1 = NULL;
|
const void *d1 = NULL;
|
||||||
const void *d2 = NULL;
|
const void *d2 = NULL;
|
||||||
|
int *ids = NULL;
|
||||||
JSValue ret = JS_UNDEFINED;
|
JSValue ret = JS_UNDEFINED;
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
|
@ -754,7 +735,9 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 52:
|
case 52:
|
||||||
ret = gos2ref(phys2d_query_box(js2vec2(argv[1]), js2vec2(argv[2])));
|
ids = phys2d_query_box(js2vec2(argv[1]), js2vec2(argv[2]));
|
||||||
|
ret = gos2ref(ids);
|
||||||
|
arrfree(ids);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 53:
|
case 53:
|
||||||
|
@ -799,7 +782,6 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 63:
|
case 63:
|
||||||
ret = JS_NewFloat64(js, deltaT);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 64:
|
case 64:
|
||||||
|
@ -867,7 +849,9 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 80:
|
case 80:
|
||||||
ret = gos2ref(phys2d_query_shape(js2ptr(argv[1])));
|
ids = phys2d_query_shape(js2ptr(argv[1]));
|
||||||
|
ret = gos2ref(ids);
|
||||||
|
arrfree(ids);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 81:
|
case 81:
|
||||||
|
@ -891,7 +875,9 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 86:
|
case 86:
|
||||||
ret = gos2ref(phys2d_query_box_points(js2vec2(argv[1]), js2vec2(argv[2]), js2cpvec2arr(argv[3]), js2int(argv[4])));
|
ids = phys2d_query_box_points(js2vec2(argv[1]), js2vec2(argv[2]), js2cpvec2arr(argv[3]), js2int(argv[4]));
|
||||||
|
ret = gos2ref(ids);
|
||||||
|
arrfree(ids);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 87:
|
case 87:
|
||||||
|
@ -1150,6 +1136,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 147:
|
case 147:
|
||||||
|
YughWarn("EXITING");
|
||||||
exit(js2int(argv[1]));
|
exit(js2int(argv[1]));
|
||||||
break;
|
break;
|
||||||
case 148:
|
case 148:
|
||||||
|
@ -1549,7 +1536,6 @@ JSValue duk_set_body(JSContext *js, JSValueConst this, int argc, JSValueConst *a
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
gameobject_move(go, js2vec2(argv[2]));
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
|
@ -1557,11 +1543,9 @@ JSValue duk_set_body(JSContext *js, JSValueConst this, int argc, JSValueConst *a
|
||||||
return JS_UNDEFINED;
|
return JS_UNDEFINED;
|
||||||
|
|
||||||
case 5:
|
case 5:
|
||||||
// go->flipx = JS_ToBool(js, argv[2]);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 6:
|
case 6:
|
||||||
// go->flipy = JS_ToBool(js, argv[2]);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 7:
|
case 7:
|
||||||
|
@ -1644,7 +1628,7 @@ JSValue duk_q_body(JSContext *js, JSValueConst this, int argc, JSValueConst *arg
|
||||||
|
|
||||||
JSValue duk_make_sprite(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
|
JSValue duk_make_sprite(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
|
||||||
JSValue sprite = JS_NewObject(js);
|
JSValue sprite = JS_NewObject(js);
|
||||||
js_setprop_str(sprite,"id",JS_NewInt64(js, make_sprite(jsgo2id(argv[0]))));
|
js_setprop_str(sprite,"id",JS_NewInt64(js, make_sprite(js2gameobject(argv[0]))));
|
||||||
return sprite;
|
return sprite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1666,9 +1650,8 @@ JSValue duk_make_box2d(JSContext *js, JSValueConst this, int argc, JSValueConst
|
||||||
HMM_Vec2 size = js2vec2(argv[1]);
|
HMM_Vec2 size = js2vec2(argv[1]);
|
||||||
|
|
||||||
struct phys2d_box *box = Make2DBox(go);
|
struct phys2d_box *box = Make2DBox(go);
|
||||||
box->w = size.x;
|
box->t.scale = js2vec2(argv[1]);
|
||||||
box->h = size.y;
|
box->t.pos = js2vec2(argv[2]);
|
||||||
box->offset = js2vec2(argv[2]);
|
|
||||||
|
|
||||||
phys2d_applybox(box);
|
phys2d_applybox(box);
|
||||||
|
|
||||||
|
@ -1687,17 +1670,15 @@ JSValue duk_cmd_box2d(JSContext *js, JSValueConst this, int argc, JSValueConst *
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case 0:
|
case 0:
|
||||||
arg = js2vec2(argv[2]);
|
box->t.scale = js2vec2(argv[2]);
|
||||||
box->w = arg.x;
|
|
||||||
box->h = arg.y;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
box->offset = js2vec2(argv[2]);
|
box->t.pos = js2vec2(argv[2]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
box->rotation = js2number(argv[2]);
|
box->t.angle = js2number(argv[2]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1830,28 +1811,6 @@ JSValue duk_inflate_cpv(JSContext *js, JSValueConst this, int argc, JSValueConst
|
||||||
|
|
||||||
/* These are anims for controlling properties on an object */
|
/* These are anims for controlling properties on an object */
|
||||||
JSValue duk_anim(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
|
JSValue duk_anim(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
|
||||||
JSValue prop = argv[0];
|
|
||||||
int keyframes = js_arrlen(argv[1]);
|
|
||||||
YughInfo("Processing %d keyframes.", keyframes);
|
|
||||||
|
|
||||||
struct anim a = make_anim();
|
|
||||||
|
|
||||||
for (int i = 0; i < keyframes; i++) {
|
|
||||||
struct keyframe k;
|
|
||||||
HMM_Vec2 v = js2vec2(js_getpropidx( argv[1], i));
|
|
||||||
k.time = v.y;
|
|
||||||
k.val = v.x;
|
|
||||||
a = anim_add_keyframe(a, k);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (double i = 0; i < 3.0; i = i + 0.1) {
|
|
||||||
YughInfo("Val is now %f at time %f", anim_val(a, i), i);
|
|
||||||
JSValue vv = num2js(anim_val(a, i));
|
|
||||||
JSValue e = JS_Call(js, prop, globalThis, 1, &vv);
|
|
||||||
JS_FreeValue(js,e);
|
|
||||||
JS_FreeValue(js,vv);
|
|
||||||
}
|
|
||||||
|
|
||||||
return JS_UNDEFINED;
|
return JS_UNDEFINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,263 +0,0 @@
|
||||||
/*
|
|
||||||
SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
Parson 1.4.0 (https://github.com/kgabis/parson)
|
|
||||||
Copyright (c) 2012 - 2022 Krzysztof Gabis
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef parson_parson_h
|
|
||||||
#define parson_parson_h
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
#if 0
|
|
||||||
} /* unconfuse xcode */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define PARSON_VERSION_MAJOR 1
|
|
||||||
#define PARSON_VERSION_MINOR 4
|
|
||||||
#define PARSON_VERSION_PATCH 0
|
|
||||||
|
|
||||||
#define PARSON_VERSION_STRING "1.4.0"
|
|
||||||
|
|
||||||
#include <stddef.h> /* size_t */
|
|
||||||
|
|
||||||
/* Types and enums */
|
|
||||||
typedef struct json_object_t JSON_Object;
|
|
||||||
typedef struct json_array_t JSON_Array;
|
|
||||||
typedef struct json_value_t JSON_Value;
|
|
||||||
|
|
||||||
enum json_value_type {
|
|
||||||
JSONError = -1,
|
|
||||||
JSONNull = 1,
|
|
||||||
JSONString = 2,
|
|
||||||
JSONNumber = 3,
|
|
||||||
JSONObject = 4,
|
|
||||||
JSONArray = 5,
|
|
||||||
JSONBoolean = 6
|
|
||||||
};
|
|
||||||
typedef int JSON_Value_Type;
|
|
||||||
|
|
||||||
enum json_result_t {
|
|
||||||
JSONSuccess = 0,
|
|
||||||
JSONFailure = -1
|
|
||||||
};
|
|
||||||
typedef int JSON_Status;
|
|
||||||
|
|
||||||
typedef void *(*JSON_Malloc_Function)(size_t);
|
|
||||||
typedef void (*JSON_Free_Function)(void *);
|
|
||||||
|
|
||||||
/* Call only once, before calling any other function from parson API. If not called, malloc and free
|
|
||||||
from stdlib will be used for all allocations */
|
|
||||||
void json_set_allocation_functions(JSON_Malloc_Function malloc_fun, JSON_Free_Function free_fun);
|
|
||||||
|
|
||||||
/* Sets if slashes should be escaped or not when serializing JSON. By default slashes are escaped.
|
|
||||||
This function sets a global setting and is not thread safe. */
|
|
||||||
void json_set_escape_slashes(int escape_slashes);
|
|
||||||
|
|
||||||
/* Sets float format used for serialization of numbers.
|
|
||||||
Make sure it can't serialize to a string longer than PARSON_NUM_BUF_SIZE.
|
|
||||||
If format is null then the default format is used. */
|
|
||||||
void json_set_float_serialization_format(const char *format);
|
|
||||||
|
|
||||||
/* Parses first JSON value in a file, returns NULL in case of error */
|
|
||||||
JSON_Value *json_parse_file(const char *filename);
|
|
||||||
|
|
||||||
/* Parses first JSON value in a file and ignores comments (/ * * / and //),
|
|
||||||
returns NULL in case of error */
|
|
||||||
JSON_Value *json_parse_file_with_comments(const char *filename);
|
|
||||||
|
|
||||||
/* Parses first JSON value in a string, returns NULL in case of error */
|
|
||||||
JSON_Value *json_parse_string(const char *string);
|
|
||||||
|
|
||||||
/* Parses first JSON value in a string and ignores comments (/ * * / and //),
|
|
||||||
returns NULL in case of error */
|
|
||||||
JSON_Value *json_parse_string_with_comments(const char *string);
|
|
||||||
|
|
||||||
/* Serialization */
|
|
||||||
size_t json_serialization_size(const JSON_Value *value); /* returns 0 on fail */
|
|
||||||
JSON_Status json_serialize_to_buffer(const JSON_Value *value, char *buf, size_t buf_size_in_bytes);
|
|
||||||
JSON_Status json_serialize_to_file(const JSON_Value *value, const char *filename);
|
|
||||||
char *json_serialize_to_string(const JSON_Value *value);
|
|
||||||
|
|
||||||
/* Pretty serialization */
|
|
||||||
size_t json_serialization_size_pretty(const JSON_Value *value); /* returns 0 on fail */
|
|
||||||
JSON_Status json_serialize_to_buffer_pretty(const JSON_Value *value, char *buf, size_t buf_size_in_bytes);
|
|
||||||
JSON_Status json_serialize_to_file_pretty(const JSON_Value *value, const char *filename);
|
|
||||||
char *json_serialize_to_string_pretty(const JSON_Value *value);
|
|
||||||
|
|
||||||
void json_free_serialized_string(char *string); /* frees string from json_serialize_to_string and json_serialize_to_string_pretty */
|
|
||||||
|
|
||||||
/* Comparing */
|
|
||||||
int json_value_equals(const JSON_Value *a, const JSON_Value *b);
|
|
||||||
|
|
||||||
/* Validation
|
|
||||||
This is *NOT* JSON Schema. It validates json by checking if object have identically
|
|
||||||
named fields with matching types.
|
|
||||||
For example schema {"name":"", "age":0} will validate
|
|
||||||
{"name":"Joe", "age":25} and {"name":"Joe", "age":25, "gender":"m"},
|
|
||||||
but not {"name":"Joe"} or {"name":"Joe", "age":"Cucumber"}.
|
|
||||||
In case of arrays, only first value in schema is checked against all values in tested array.
|
|
||||||
Empty objects ({}) validate all objects, empty arrays ([]) validate all arrays,
|
|
||||||
null validates values of every type.
|
|
||||||
*/
|
|
||||||
JSON_Status json_validate(const JSON_Value *schema, const JSON_Value *value);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* JSON Object
|
|
||||||
*/
|
|
||||||
JSON_Value *json_object_get_value(const JSON_Object *object, const char *name);
|
|
||||||
const char *json_object_get_string(const JSON_Object *object, const char *name);
|
|
||||||
size_t json_object_get_string_len(const JSON_Object *object, const char *name); /* doesn't account for last null character */
|
|
||||||
JSON_Object *json_object_get_object(const JSON_Object *object, const char *name);
|
|
||||||
JSON_Array *json_object_get_array(const JSON_Object *object, const char *name);
|
|
||||||
double json_object_get_number(const JSON_Object *object, const char *name); /* returns 0 on fail */
|
|
||||||
int json_object_get_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */
|
|
||||||
|
|
||||||
/* dotget functions enable addressing values with dot notation in nested objects,
|
|
||||||
just like in structs or c++/java/c# objects (e.g. objectA.objectB.value).
|
|
||||||
Because valid names in JSON can contain dots, some values may be inaccessible
|
|
||||||
this way. */
|
|
||||||
JSON_Value *json_object_dotget_value(const JSON_Object *object, const char *name);
|
|
||||||
const char *json_object_dotget_string(const JSON_Object *object, const char *name);
|
|
||||||
size_t json_object_dotget_string_len(const JSON_Object *object, const char *name); /* doesn't account for last null character */
|
|
||||||
JSON_Object *json_object_dotget_object(const JSON_Object *object, const char *name);
|
|
||||||
JSON_Array *json_object_dotget_array(const JSON_Object *object, const char *name);
|
|
||||||
double json_object_dotget_number(const JSON_Object *object, const char *name); /* returns 0 on fail */
|
|
||||||
int json_object_dotget_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */
|
|
||||||
|
|
||||||
/* Functions to get available names */
|
|
||||||
size_t json_object_get_count(const JSON_Object *object);
|
|
||||||
const char *json_object_get_name(const JSON_Object *object, size_t index);
|
|
||||||
JSON_Value *json_object_get_value_at(const JSON_Object *object, size_t index);
|
|
||||||
JSON_Value *json_object_get_wrapping_value(const JSON_Object *object);
|
|
||||||
|
|
||||||
/* Functions to check if object has a value with a specific name. Returned value is 1 if object has
|
|
||||||
* a value and 0 if it doesn't. dothas functions behave exactly like dotget functions. */
|
|
||||||
int json_object_has_value(const JSON_Object *object, const char *name);
|
|
||||||
int json_object_has_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type);
|
|
||||||
|
|
||||||
int json_object_dothas_value(const JSON_Object *object, const char *name);
|
|
||||||
int json_object_dothas_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type);
|
|
||||||
|
|
||||||
/* Creates new name-value pair or frees and replaces old value with a new one.
|
|
||||||
* json_object_set_value does not copy passed value so it shouldn't be freed afterwards. */
|
|
||||||
JSON_Status json_object_set_value(JSON_Object *object, const char *name, JSON_Value *value);
|
|
||||||
JSON_Status json_object_set_string(JSON_Object *object, const char *name, const char *string);
|
|
||||||
JSON_Status json_object_set_string_with_len(JSON_Object *object, const char *name, const char *string, size_t len); /* length shouldn't include last null character */
|
|
||||||
JSON_Status json_object_set_number(JSON_Object *object, const char *name, double number);
|
|
||||||
JSON_Status json_object_set_boolean(JSON_Object *object, const char *name, int boolean);
|
|
||||||
JSON_Status json_object_set_null(JSON_Object *object, const char *name);
|
|
||||||
|
|
||||||
/* Works like dotget functions, but creates whole hierarchy if necessary.
|
|
||||||
* json_object_dotset_value does not copy passed value so it shouldn't be freed afterwards. */
|
|
||||||
JSON_Status json_object_dotset_value(JSON_Object *object, const char *name, JSON_Value *value);
|
|
||||||
JSON_Status json_object_dotset_string(JSON_Object *object, const char *name, const char *string);
|
|
||||||
JSON_Status json_object_dotset_string_with_len(JSON_Object *object, const char *name, const char *string, size_t len); /* length shouldn't include last null character */
|
|
||||||
JSON_Status json_object_dotset_number(JSON_Object *object, const char *name, double number);
|
|
||||||
JSON_Status json_object_dotset_boolean(JSON_Object *object, const char *name, int boolean);
|
|
||||||
JSON_Status json_object_dotset_null(JSON_Object *object, const char *name);
|
|
||||||
|
|
||||||
/* Frees and removes name-value pair */
|
|
||||||
JSON_Status json_object_remove(JSON_Object *object, const char *name);
|
|
||||||
|
|
||||||
/* Works like dotget function, but removes name-value pair only on exact match. */
|
|
||||||
JSON_Status json_object_dotremove(JSON_Object *object, const char *key);
|
|
||||||
|
|
||||||
/* Removes all name-value pairs in object */
|
|
||||||
JSON_Status json_object_clear(JSON_Object *object);
|
|
||||||
|
|
||||||
/*
|
|
||||||
*JSON Array
|
|
||||||
*/
|
|
||||||
JSON_Value *json_array_get_value(const JSON_Array *array, size_t index);
|
|
||||||
const char *json_array_get_string(const JSON_Array *array, size_t index);
|
|
||||||
size_t json_array_get_string_len(const JSON_Array *array, size_t index); /* doesn't account for last null character */
|
|
||||||
JSON_Object *json_array_get_object(const JSON_Array *array, size_t index);
|
|
||||||
JSON_Array *json_array_get_array(const JSON_Array *array, size_t index);
|
|
||||||
double json_array_get_number(const JSON_Array *array, size_t index); /* returns 0 on fail */
|
|
||||||
int json_array_get_boolean(const JSON_Array *array, size_t index); /* returns -1 on fail */
|
|
||||||
size_t json_array_get_count(const JSON_Array *array);
|
|
||||||
JSON_Value *json_array_get_wrapping_value(const JSON_Array *array);
|
|
||||||
|
|
||||||
/* Frees and removes value at given index, does nothing and returns JSONFailure if index doesn't exist.
|
|
||||||
* Order of values in array may change during execution. */
|
|
||||||
JSON_Status json_array_remove(JSON_Array *array, size_t i);
|
|
||||||
|
|
||||||
/* Frees and removes from array value at given index and replaces it with given one.
|
|
||||||
* Does nothing and returns JSONFailure if index doesn't exist.
|
|
||||||
* json_array_replace_value does not copy passed value so it shouldn't be freed afterwards. */
|
|
||||||
JSON_Status json_array_replace_value(JSON_Array *array, size_t i, JSON_Value *value);
|
|
||||||
JSON_Status json_array_replace_string(JSON_Array *array, size_t i, const char *string);
|
|
||||||
JSON_Status json_array_replace_string_with_len(JSON_Array *array, size_t i, const char *string, size_t len); /* length shouldn't include last null character */
|
|
||||||
JSON_Status json_array_replace_number(JSON_Array *array, size_t i, double number);
|
|
||||||
JSON_Status json_array_replace_boolean(JSON_Array *array, size_t i, int boolean);
|
|
||||||
JSON_Status json_array_replace_null(JSON_Array *array, size_t i);
|
|
||||||
|
|
||||||
/* Frees and removes all values from array */
|
|
||||||
JSON_Status json_array_clear(JSON_Array *array);
|
|
||||||
|
|
||||||
/* Appends new value at the end of array.
|
|
||||||
* json_array_append_value does not copy passed value so it shouldn't be freed afterwards. */
|
|
||||||
JSON_Status json_array_append_value(JSON_Array *array, JSON_Value *value);
|
|
||||||
JSON_Status json_array_append_string(JSON_Array *array, const char *string);
|
|
||||||
JSON_Status json_array_append_string_with_len(JSON_Array *array, const char *string, size_t len); /* length shouldn't include last null character */
|
|
||||||
JSON_Status json_array_append_number(JSON_Array *array, double number);
|
|
||||||
JSON_Status json_array_append_boolean(JSON_Array *array, int boolean);
|
|
||||||
JSON_Status json_array_append_null(JSON_Array *array);
|
|
||||||
|
|
||||||
/*
|
|
||||||
*JSON Value
|
|
||||||
*/
|
|
||||||
JSON_Value *json_value_init_object(void);
|
|
||||||
JSON_Value *json_value_init_array(void);
|
|
||||||
JSON_Value *json_value_init_string(const char *string); /* copies passed string */
|
|
||||||
JSON_Value *json_value_init_string_with_len(const char *string, size_t length); /* copies passed string, length shouldn't include last null character */
|
|
||||||
JSON_Value *json_value_init_number(double number);
|
|
||||||
JSON_Value *json_value_init_boolean(int boolean);
|
|
||||||
JSON_Value *json_value_init_null(void);
|
|
||||||
JSON_Value *json_value_deep_copy(const JSON_Value *value);
|
|
||||||
void json_value_free(JSON_Value *value);
|
|
||||||
|
|
||||||
JSON_Value_Type json_value_get_type(const JSON_Value *value);
|
|
||||||
JSON_Object *json_value_get_object(const JSON_Value *value);
|
|
||||||
JSON_Array *json_value_get_array(const JSON_Value *value);
|
|
||||||
const char *json_value_get_string(const JSON_Value *value);
|
|
||||||
size_t json_value_get_string_len(const JSON_Value *value); /* doesn't account for last null character */
|
|
||||||
double json_value_get_number(const JSON_Value *value);
|
|
||||||
int json_value_get_boolean(const JSON_Value *value);
|
|
||||||
JSON_Value *json_value_get_parent(const JSON_Value *value);
|
|
||||||
|
|
||||||
/* Same as above, but shorter */
|
|
||||||
JSON_Value_Type json_type(const JSON_Value *value);
|
|
||||||
JSON_Object *json_object(const JSON_Value *value);
|
|
||||||
JSON_Array *json_array(const JSON_Value *value);
|
|
||||||
const char *json_string(const JSON_Value *value);
|
|
||||||
size_t json_string_len(const JSON_Value *value); /* doesn't account for last null character */
|
|
||||||
double json_number(const JSON_Value *value);
|
|
||||||
int json_boolean(const JSON_Value *value);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define PARTICLE_H
|
#define PARTICLE_H
|
||||||
|
|
||||||
#include "HandmadeMath.h"
|
#include "HandmadeMath.h"
|
||||||
|
#include "transform.h"
|
||||||
|
|
||||||
struct particle {
|
struct particle {
|
||||||
HMM_Vec3 pos;
|
HMM_Vec3 pos;
|
||||||
|
@ -15,12 +16,13 @@ struct particle {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct emitter {
|
typedef struct emitter {
|
||||||
struct particle *particles;
|
struct particle *particles;
|
||||||
|
transform3d t;
|
||||||
int max;
|
int max;
|
||||||
double life;
|
double life;
|
||||||
void (*seeder)(struct particle *p); /* Called to initialize each particle */
|
void (*seeder)(struct particle *p); /* Called to initialize each particle */
|
||||||
};
|
} emitter;
|
||||||
|
|
||||||
struct emitter make_emitter();
|
struct emitter make_emitter();
|
||||||
void free_emitter(struct emitter e);
|
void free_emitter(struct emitter e);
|
||||||
|
|
|
@ -506,7 +506,7 @@ void full_2d_pass(struct window *window)
|
||||||
//////////// 2D projection
|
//////////// 2D projection
|
||||||
cpVect pos = cam_pos();
|
cpVect pos = cam_pos();
|
||||||
|
|
||||||
projection = HMM_Orthographic_LH_ZO(
|
projection = HMM_Orthographic_LH_NO(
|
||||||
pos.x - zoom * window->rwidth / 2,
|
pos.x - zoom * window->rwidth / 2,
|
||||||
pos.x + zoom * window->rwidth / 2,
|
pos.x + zoom * window->rwidth / 2,
|
||||||
pos.y - zoom * window->rheight / 2,
|
pos.y - zoom * window->rheight / 2,
|
||||||
|
|
|
@ -435,7 +435,6 @@ dsp_node *dsp_fwd_delay(double sec, double decay)
|
||||||
d->ring = NULL;
|
d->ring = NULL;
|
||||||
d->ring = ringnew(d->ring, sec*CHANNELS*SAMPLERATE*2);
|
d->ring = ringnew(d->ring, sec*CHANNELS*SAMPLERATE*2);
|
||||||
ringheader(d->ring)->write += CHANNELS*SAMPLERATE*sec;
|
ringheader(d->ring)->write += CHANNELS*SAMPLERATE*sec;
|
||||||
YughWarn("FWD DELAY");
|
|
||||||
return make_node(d, filter_fwd_delay, delay_free);
|
return make_node(d, filter_fwd_delay, delay_free);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -452,38 +451,31 @@ void dsp_adsr_fillbuf(struct dsp_adsr *adsr, soundbyte *out, int n)
|
||||||
|
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
if (adsr->time > adsr->rls) {
|
if (adsr->time > adsr->rls) {
|
||||||
// Totally decayed
|
|
||||||
adsr->out = 0.f;
|
adsr->out = 0.f;
|
||||||
|
|
||||||
goto fin;
|
goto fin;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (adsr->time > adsr->sus) {
|
if (adsr->time > adsr->sus) {
|
||||||
// Release phase
|
// Release phase
|
||||||
adsr->out = adsr->rls_t * adsr->out;
|
adsr->out = adsr->rls_t * adsr->out;
|
||||||
|
|
||||||
goto fin;
|
goto fin;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (adsr->time > adsr->dec) {
|
if (adsr->time > adsr->dec) {
|
||||||
// Sustain phase
|
// Sustain phase
|
||||||
adsr->out = adsr->sus_pwr;
|
adsr->out = adsr->sus_pwr;
|
||||||
|
|
||||||
goto fin;
|
goto fin;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (adsr->time > adsr->atk) {
|
if (adsr->time > adsr->atk) {
|
||||||
// Decay phase
|
// Decay phase
|
||||||
adsr->out = (1 - adsr->dec_t) * adsr->sus_pwr + adsr->dec_t * adsr->out;
|
adsr->out = (1 - adsr->dec_t) * adsr->sus_pwr + adsr->dec_t * adsr->out;
|
||||||
|
|
||||||
goto fin;
|
goto fin;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attack phase
|
// Attack phase
|
||||||
adsr->out = (1-adsr->atk_t) + adsr->atk_t * adsr->out;
|
adsr->out = (1-adsr->atk_t) + adsr->atk_t * adsr->out;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fin:
|
fin:
|
||||||
|
|
||||||
val = SHRT_MAX * adsr->out;
|
val = SHRT_MAX * adsr->out;
|
||||||
|
|
|
@ -62,7 +62,6 @@ int make_sprite(int go) {
|
||||||
.layer = 0,
|
.layer = 0,
|
||||||
.next = -1,
|
.next = -1,
|
||||||
.enabled = 1};
|
.enabled = 1};
|
||||||
|
|
||||||
int id;
|
int id;
|
||||||
freelist_grab(id, sprites);
|
freelist_grab(id, sprites);
|
||||||
sprites[id] = sprite;
|
sprites[id] = sprite;
|
||||||
|
@ -119,21 +118,24 @@ int sprite_sort(int *a, int *b)
|
||||||
void sprite_draw_all() {
|
void sprite_draw_all() {
|
||||||
sg_apply_pipeline(pip_sprite);
|
sg_apply_pipeline(pip_sprite);
|
||||||
sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(projection));
|
sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(projection));
|
||||||
static int *layers;
|
int *layers = NULL;
|
||||||
if (layers) arrfree(layers);
|
if (layers) arrfree(layers);
|
||||||
|
|
||||||
for (int i = 0; i < freelist_len(sprites); i++)
|
for (int i = 0; i < freelist_len(sprites); i++)
|
||||||
if (sprites[i].next == -1 && sprites[i].go >= 0 && sprites[i].enabled)
|
if (sprites[i].next == -1 && sprites[i].go >= 0 && sprites[i].enabled)
|
||||||
arrpush(layers, i);
|
arrpush(layers, i);
|
||||||
|
|
||||||
if (arrlen(layers) == 0) return;
|
if (!layers || arrlen(layers) == 0) return;
|
||||||
if (arrlen(layers) > 1)
|
if (arrlen(layers) > 1)
|
||||||
qsort(layers, arrlen(layers), sizeof(*layers), sprite_sort);
|
qsort(layers, arrlen(layers), sizeof(*layers), sprite_sort);
|
||||||
|
|
||||||
for (int i = 0; i < arrlen(layers); i++)
|
for (int i = 0; i < arrlen(layers); i++)
|
||||||
sprite_draw(&sprites[layers[i]]);
|
sprite_draw(&sprites[layers[i]]);
|
||||||
|
|
||||||
|
arrfree(layers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void sprite_loadtex(struct sprite *sprite, const char *path, struct glrect frame) {
|
void sprite_loadtex(struct sprite *sprite, const char *path, struct glrect frame) {
|
||||||
if (!sprite) {
|
if (!sprite) {
|
||||||
YughWarn("NO SPRITE!");
|
YughWarn("NO SPRITE!");
|
||||||
|
@ -201,20 +203,16 @@ void sprite_initialize() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/* offset given in texture offset, so -0.5,-0.5 results in it being centered */
|
|
||||||
void tex_draw(struct Texture *tex, HMM_Mat3 m, struct glrect r, struct rgba color, int wrap, HMM_Vec2 wrapoffset, float wrapscale, struct rgba emissive) {
|
void tex_draw(struct Texture *tex, HMM_Mat3 m, struct glrect r, struct rgba color, int wrap, HMM_Vec2 wrapoffset, float wrapscale, struct rgba emissive) {
|
||||||
struct sprite_vert verts[4];
|
struct sprite_vert verts[4];
|
||||||
|
float w = tex->width*st_s_w(r);
|
||||||
|
float h = tex->height*st_s_h(r);
|
||||||
|
|
||||||
HMM_Vec2 sposes[4] = {
|
HMM_Vec2 sposes[4] = {
|
||||||
{0.0,0.0},
|
{0.0,0.0},
|
||||||
{1.0,0.0},
|
{w,0.0},
|
||||||
{0.0,1.0},
|
{0.0,h},
|
||||||
{1.0,1.0},
|
{w,h}
|
||||||
};
|
|
||||||
|
|
||||||
HMM_Vec2 t_scale = {
|
|
||||||
tex->width * st_s_w(r), //*size.X;
|
|
||||||
tex->height * st_s_h(r) // * size.Y
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
|
@ -223,7 +221,6 @@ void tex_draw(struct Texture *tex, HMM_Mat3 m, struct glrect r, struct rgba colo
|
||||||
verts[i].emissive = emissive;
|
verts[i].emissive = emissive;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wrap) {
|
|
||||||
verts[0].uv.X = r.s0;
|
verts[0].uv.X = r.s0;
|
||||||
verts[0].uv.Y = r.t1;
|
verts[0].uv.Y = r.t1;
|
||||||
verts[1].uv.X = r.s1;
|
verts[1].uv.X = r.s1;
|
||||||
|
@ -232,15 +229,6 @@ void tex_draw(struct Texture *tex, HMM_Mat3 m, struct glrect r, struct rgba colo
|
||||||
verts[2].uv.Y = r.t0;
|
verts[2].uv.Y = r.t0;
|
||||||
verts[3].uv.X = r.s1;
|
verts[3].uv.X = r.s1;
|
||||||
verts[3].uv.Y = r.t0;
|
verts[3].uv.Y = r.t0;
|
||||||
} else {
|
|
||||||
// verts[0].uv = HMM_MulV2((HMM_Vec2){0,0}, size);
|
|
||||||
// verts[1].uv = HMM_MulV2((HMM_Vec2){1,0}, size);
|
|
||||||
// verts[2].uv = HMM_MulV2((HMM_Vec2){0,1}, size);
|
|
||||||
// verts[3].uv = HMM_MulV2((HMM_Vec2){1,1}, size);
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
verts[i].uv = HMM_AddV2(verts[i].uv, wrapoffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
bind_sprite.fs.images[0] = tex->id;
|
bind_sprite.fs.images[0] = tex->id;
|
||||||
|
|
||||||
|
@ -256,16 +244,9 @@ void sprite_draw(struct sprite *sprite) {
|
||||||
|
|
||||||
if (sprite->tex) {
|
if (sprite->tex) {
|
||||||
HMM_Mat3 m = t_go2world(go);
|
HMM_Mat3 m = t_go2world(go);
|
||||||
|
HMM_Mat3 sm = transform2d2mat(sprite->t);
|
||||||
|
|
||||||
HMM_Mat3 ss = HMM_M3D(1);
|
tex_draw(sprite->tex, HMM_MulM3(m, sm), sprite->frame, sprite->color, 0, (HMM_Vec2){0,0}, 0, sprite->emissive);
|
||||||
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->t.pos.X, sprite->t.pos.Y, 1};
|
|
||||||
|
|
||||||
HMM_Mat3 sm = HMM_MulM3(ss, ts);
|
|
||||||
m = HMM_MulM3(m, sm);
|
|
||||||
tex_draw(sprite->tex, m, sprite->frame, sprite->color, 0, (HMM_Vec2){0,0}, 0, sprite->emissive);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -36,9 +36,28 @@ HMM_Vec3 mat3_t_dir(HMM_Mat4 m, HMM_Vec3 dir)
|
||||||
return mat3_t_pos(m, dir);
|
return mat3_t_pos(m, dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
HMM_Mat3 transform2d2mat(transform2d t) {
|
HMM_Mat3 transform2d2mat(transform2d trn) {
|
||||||
HMM_Mat2 m = HMM_MulM2(HMM_RotateM2(t.angle), HMM_ScaleM2(t.scale));
|
return HMM_MulM3(HMM_Translate2D(trn.pos), HMM_MulM3(HMM_RotateM3(trn.angle), HMM_ScaleM3(trn.scale)));
|
||||||
return HMM_M2BasisPos(m, t.pos);
|
}
|
||||||
|
|
||||||
|
transform2d mat2transform2d(HMM_Mat3 m)
|
||||||
|
{
|
||||||
|
transform2d t;
|
||||||
|
t.pos = m.Columns[2].xy;
|
||||||
|
t.scale = (HMM_Vec2){HMM_LenV2(m.Columns[0].xy), HMM_LenV2(m.Columns[1].xy)};
|
||||||
|
t.angle = acos(m.Columns[0].x/t.scale.x);
|
||||||
|
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 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);
|
||||||
|
}
|
||||||
|
|
|
@ -17,6 +17,9 @@ typedef struct {
|
||||||
|
|
||||||
extern const transform2d t2d_unit;
|
extern const transform2d t2d_unit;
|
||||||
|
|
||||||
|
#define VEC2_FMT "[%g,%g]"
|
||||||
|
#define VEC2_MEMS(s) (s).x, (s).y
|
||||||
|
|
||||||
HMM_Vec3 trans_forward(const transform3d *const trans);
|
HMM_Vec3 trans_forward(const transform3d *const trans);
|
||||||
HMM_Vec3 trans_back(const transform3d *trans);
|
HMM_Vec3 trans_back(const transform3d *trans);
|
||||||
HMM_Vec3 trans_up(const transform3d *trans);
|
HMM_Vec3 trans_up(const transform3d *trans);
|
||||||
|
@ -38,6 +41,8 @@ HMM_Vec3 mat3_t_pos(HMM_Mat4 m, HMM_Vec3 pos);
|
||||||
HMM_Vec3 mat3_t_dir(HMM_Mat4 m, HMM_Vec3 dir);
|
HMM_Vec3 mat3_t_dir(HMM_Mat4 m, HMM_Vec3 dir);
|
||||||
|
|
||||||
HMM_Mat3 transform2d2mat(transform2d t);
|
HMM_Mat3 transform2d2mat(transform2d t);
|
||||||
|
transform2d mat2transform2d(HMM_Mat3 m);
|
||||||
HMM_Mat4 transform3d2mat(transform3d t);
|
HMM_Mat4 transform3d2mat(transform3d t);
|
||||||
|
transform3d mat2transform3d(HMM_Mat4 m);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
#include "yugine.h"
|
#include "yugine.h"
|
||||||
#include "font.h"
|
#include "font.h"
|
||||||
|
#include "transform.h"
|
||||||
#include "gameobject.h"
|
#include "gameobject.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
#include "resources.h"
|
#include "resources.h"
|
||||||
|
#include "spline.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "datastream.h"
|
#include "datastream.h"
|
||||||
|
|
Loading…
Reference in a new issue