Merge transforms into single type

This commit is contained in:
John Alanbrook 2024-05-12 18:36:14 -05:00
parent 36505ebf51
commit 2a1ea67cec
21 changed files with 232 additions and 355 deletions

View file

@ -332,7 +332,7 @@ function process()
else
prosperon.window_render(game.camera.transform, game.camera.zoom);
render.set_camera();
//render.set_camera();
/*os.sprite_pipe();
allsprites.forEach(function(x) {
@ -621,7 +621,7 @@ global.mixin("scripts/entity");
function world_start() {
globalThis.world = Object.create(entity);
world.transform = os.make_transform2d();
world.transform = os.make_transform();
world.objects = {};
world.toString = function() { return "world"; };
world.ur = "world";

View file

@ -133,7 +133,7 @@ var entity = {
spawn(text, config, callback) {
var st = profile.now();
var ent = Object.create(entity);
ent.transform = os.make_transform2d();
ent.transform = os.make_transform();
ent.guid = prosperon.guid();

View file

@ -34,15 +34,15 @@ static int cb_idx = 0;
static const unsigned char col_alpha = 40;
static const float sensor_seg = 10;
cpTransform m3_to_cpt(HMM_Mat3 m)
cpTransform m3_to_cpt(HMM_Mat4 m)
{
cpTransform t;
t.a = m.Columns[0].x;
t.b = m.Columns[0].y;
t.tx = m.Columns[2].x;
t.tx = m.Columns[3].x;
t.c = m.Columns[1].x;
t.d = m.Columns[1].y;
t.ty = m.Columns[2].y;
t.ty = m.Columns[3].y;
return t;
}
@ -181,7 +181,7 @@ void phys2d_update(float deltaT) {
void init_phys2dshape(struct phys2d_shape *shape, gameobject *go, void *data) {
shape->go = go;
shape->data = data;
shape->t.scale = (HMM_Vec2){1.0,1.0};
shape->t.scale = (HMM_Vec3){1.0,1.0,1.0};
go_shape_apply(go->body, shape->shape, go);
cpShapeSetCollisionType(shape->shape, (cpCollisionType)go);
cpShapeSetUserData(shape->shape, shape);
@ -201,7 +201,6 @@ struct phys2d_circle *Make2DCircle(gameobject *go) {
new->offset = v2zero;
new->shape.shape = cpSpaceAddShape(space, cpCircleShapeNew(go->body, new->radius, cpvzero));
new->shape.debugdraw = phys2d_dbgdrawcircle;
new->shape.moi = phys2d_circle_moi;
new->shape.apply = phys2d_applycircle;
new->shape.free = NULL;
@ -219,16 +218,6 @@ float phys2d_circle_moi(struct phys2d_circle *c) {
void phys2d_circledel(struct phys2d_circle *c) { phys2d_shape_del(&c->shape); }
void circle2d_free(circle2d *c) { phys2d_circledel(c); }
void phys2d_dbgdrawcpcirc(cpShape *c) {
HMM_Vec2 pos = mat_t_pos(t_go2world(shape2go(c)), (HMM_Vec2)cpCircleShapeGetOffset(c));
float radius = cpCircleShapeGetRadius(c);
struct rgba color = shape_color(c);
float seglen = cpShapeGetSensor(c) ? 5 : -1;
//draw_circle(pos, radius, 1, color, seglen);
color.a = col_alpha;
//draw_circle(pos,radius,radius,color,-1);
}
void phys2d_shape_apply(struct phys2d_shape *s)
{
float moment = cpBodyGetMoment(s->go->body);
@ -242,10 +231,6 @@ void phys2d_shape_apply(struct phys2d_shape *s)
cpBodySetMoment(s->go->body, moment);
}
void phys2d_dbgdrawcircle(struct phys2d_circle *circle) {
phys2d_dbgdrawcpcirc(circle->shape.shape);
}
void phys2d_applycircle(struct phys2d_circle *circle) {
gameobject *go = circle->shape.go;
float radius = circle->radius * HMM_MAX(HMM_ABS(go->scale.X), HMM_ABS(go->scale.Y));
@ -263,7 +248,6 @@ struct phys2d_poly *Make2DPoly(gameobject *go) {
new->radius = 0.f;
new->shape.shape = cpSpaceAddShape(space, cpPolyShapeNewRaw(go->body, 0, (cpVect*)new->points, new->radius));
new->shape.debugdraw = phys2d_dbgdrawpoly;
new->shape.moi = phys2d_poly_moi;
new->shape.free = phys2d_poly_free;
new->shape.apply = phys2d_applypoly;
@ -321,36 +305,15 @@ void phys2d_applypoly(struct phys2d_poly *poly) {
if (arrlen(poly->points) <= 0) return;
assert(sizeof(poly->points[0]) == sizeof(cpVect));
struct gameobject *go = poly->shape.go;
transform2d t = go2t(shape2go(poly->shape.shape));
t.pos.cp = cpvzero;
t.angle = 0;
cpTransform T = m3_to_cpt(transform2d2mat(t));
transform t = go2t(shape2go(poly->shape.shape));
t.pos.xy = v2zero;
t.rotation = QUAT1;
cpTransform T = m3_to_cpt(transform2mat(t));
cpPolyShapeSetVerts(poly->shape.shape, arrlen(poly->points), (cpVect*)poly->points, T);
cpPolyShapeSetRadius(poly->shape.shape, poly->radius);
cpSpaceReindexShapesForBody(space, cpShapeGetBody(poly->shape.shape));
}
void phys2d_dbgdrawpoly(struct phys2d_poly *poly) {
struct rgba color = shape_color(poly->shape.shape);
struct rgba line_color = color;
color.a = col_alpha;
if (arrlen(poly->points) >= 3) {
int n = cpPolyShapeGetCount(poly->shape.shape);
HMM_Vec2 points[n+1];
transform2d t = go2t(shape2go(poly->shape.shape));
t.scale = (HMM_Vec2){1,1};
HMM_Mat3 rt = transform2d2mat(t);
for (int i = 0; i < n; i++)
points[i] = mat_t_pos(rt, (HMM_Vec2)cpPolyShapeGetVert(poly->shape.shape, i));
points[n] = points[0];
//draw_poly(points, n, color);
float seglen = cpShapeGetSensor(poly->shape.shape) ? sensor_seg : 0;
//draw_line(points, n, line_color, seglen, 0);
}
}
/****************** EDGE 2D**************/
struct phys2d_edge *Make2DEdge(gameobject *go) {
@ -362,7 +325,6 @@ struct phys2d_edge *Make2DEdge(gameobject *go) {
arrsetlen(new->shapes, 0);
new->shape.go = go;
new->shape.data = new;
new->shape.debugdraw = phys2d_dbgdrawedge;
new->shape.moi = phys2d_edge_moi;
new->shape.shape = NULL;
new->shape.apply = NULL;
@ -469,32 +431,6 @@ void phys2d_applyedge(struct phys2d_edge *edge) {
cpSpaceReindexShapesForBody(space, edge->shape.go->body);
}
void phys2d_dbgdrawedge(struct phys2d_edge *edge) {
edge->draws++;
if (edge->draws > 1) {
if (edge->draws >= arrlen(edge->shapes))
edge->draws = 0;
return;
}
if (arrlen(edge->shapes) < 1) return;
HMM_Vec2 drawpoints[arrlen(edge->points)];
struct gameobject *go = edge->shape.go;
HMM_Mat3 g2w = t_go2world(go);
for (int i = 0; i < arrlen(edge->points); i++)
drawpoints[i] = mat_t_pos(g2w, edge->points[i]);
float seglen = cpShapeGetSensor(edge->shapes[0]) ? sensor_seg : 0;
struct rgba color = shape_color(edge->shapes[0]);
struct rgba line_color = color;
color.a = col_alpha;
// draw_edge(drawpoints, arrlen(edge->points), color, edge->thickness * 2, 0, line_color, seglen);
//draw_points(drawpoints, arrlen(edge->points), 2, kinematic_color);
}
/************ COLLIDER ****************/
void shape_enabled(struct phys2d_shape *shape, int enabled) {
cpShapeFilter set = enabled ? CP_SHAPE_FILTER_ALL : CP_SHAPE_FILTER_NONE;

View file

@ -30,10 +30,9 @@ void constraint_free(constraint *constraint);
struct phys2d_shape {
cpShape *shape; /* user data is this phys2d_shape */
JSValue ref;
transform2d t;
transform t;
gameobject *go;
void *data; /* The specific subtype; phys2d_circle, etc */
void (*debugdraw)(void *data);
float (*moi)(void *data);
void (*apply)(void *data);
void (*free)(void *data);
@ -53,7 +52,6 @@ typedef struct phys2d_circle circle2d;
/* A convex polygon; defined as the convex hull around the given set of points */
struct phys2d_poly {
HMM_Vec2 *points;
transform2d t;
float radius;
struct phys2d_shape shape;
};

View file

@ -503,12 +503,9 @@ sg_bindings primitive_bind(primitive *p)
return b;
}
void model_draw_go(model *model, gameobject *go, gameobject *cam)
void model_draw_go(model *model, transform *go)
{
HMM_Mat4 view = t3d_go2world(cam);
HMM_Mat4 proj = HMM_Perspective_RH_NO(20, 1, 0.01, 10000);
HMM_Mat4 vp = HMM_MulM4(proj, view);
HMM_Mat4 gom = transform3d2mat(go2t3(go));
HMM_Mat4 gom = transform2mat(*go);
animation_run(&model->anim, apptime());

View file

@ -87,7 +87,7 @@ typedef struct model {
struct model *model_make(const char *path);
void model_free(model *m);
void model_draw_go(model *m, gameobject *go, gameobject *cam);
void model_draw_go(model *m, transform *go);
sg_bindings primitive_bindings(primitive *p, JSValue pipe);
void primitive_gen_indices(primitive *prim);
int mat2type(int mat);

View file

@ -17,6 +17,7 @@ const HMM_Vec3 vLEFT = {-1,0,0};
const HMM_Vec3 vRIGHT = {1,0,0};
const HMM_Mat4 MAT1 = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
const HMM_Quat QUAT1 = {1,0,0,0};
/*
* Angle unit conversion functions
@ -1746,6 +1747,7 @@ HMM_Mat4 HMM_M4TRS(HMM_Vec3 t, HMM_Quat q, HMM_Vec3 s)
HMM_Mat4 T = HMM_Translate(t);
HMM_Mat4 R = HMM_QToM4(q);
HMM_Mat4 S = HMM_Scale(s);
return HMM_MulM4(T,S);
HMM_Mat4 l;
float *lm = (float*)&l;

View file

@ -257,6 +257,10 @@ typedef union HMM_Vec3 {
float _Ignored4;
};
struct {
cpVect cp;
float _Ignored5;
};
struct
{
@ -370,6 +374,12 @@ typedef union HMM_Vec4 {
float _Ignored5;
HMM_Vec2 ZW;
};
struct
{
HMM_Vec2 cp;
HMM_Vec2 wh;
};
HMM_Quat quat;
struct {float x, y, z, w; };
@ -423,6 +433,8 @@ extern const HMM_Vec3 vRIGHT;
extern const HMM_Mat4 MAT1;
extern const HMM_Quat QUAT1;
/*
* Angle unit conversion functions
*/

View file

@ -20,26 +20,25 @@
struct sFont *use_font;
static sg_bindings bind_text;
sg_buffer text_ssbo;
struct text_vert {
struct draw_p pos;
struct draw_p wh;
struct uv_n uv;
struct uv_n st;
struct rgba color;
HMM_Vec2 pos;
HMM_Vec2 wh;
HMM_Vec2 uv;
HMM_Vec2 st;
HMM_Vec4 color;
};
static struct text_vert *text_buffer;
void font_init() {
bind_text.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
.size = sizeof(struct text_vert),
.type = SG_BUFFERTYPE_VERTEXBUFFER,
.usage = SG_USAGE_STREAM,
.label = "text buffer"
});
bind_text.fs.samplers[0] = std_sampler;
text_ssbo = sg_make_buffer(&(sg_buffer_desc){
.size = sizeof(struct text_vert),
.type = SG_BUFFERTYPE_STORAGEBUFFER,
.usage = SG_USAGE_STREAM,
.label = "text buffer"
});
}
void font_free(font *f)
@ -51,7 +50,6 @@ void font_free(font *f)
void font_set(font *f)
{
use_font = f;
bind_text.fs.images[0] = f->texID;
}
struct sFont *MakeSDFFont(const char *fontfile, int height)
@ -114,7 +112,8 @@ struct sFont *MakeFont(const char *fontfile, int height) {
newfont->emscale = stbtt_ScaleForPixelHeight(&fontinfo, height);
newfont->linegap = (newfont->ascent - newfont->descent) * newfont->emscale*1.5;
newfont->texID = sg_make_image(&(sg_image_desc){
newfont->texture = malloc(sizeof(texture));
newfont->texture->id = sg_make_image(&(sg_image_desc){
.type = SG_IMAGETYPE_2D,
.width = packsize,
.height = packsize,
@ -125,6 +124,9 @@ struct sFont *MakeFont(const char *fontfile, int height) {
.size = packsize * packsize
}
});
newfont->texture->width = packsize;
newfont->texture->height = packsize;
for (unsigned char c = 32; c < 127; c++) {
stbtt_packedchar glyph = glyphs[c - 32];
@ -173,25 +175,26 @@ void draw_char_box(struct Character c, HMM_Vec2 cursor, float scale, struct rgba
b.y = cursor.Y + wh.y/2;
}
void text_flush() {
if (arrlen(text_buffer) == 0) return;
int text_flush() {
if (arrlen(text_buffer) == 0) return 0;
sg_range verts;
verts.ptr = text_buffer;
verts.size = sizeof(struct text_vert) * arrlen(text_buffer);
if (sg_query_buffer_will_overflow(bind_text.vertex_buffers[0], verts.size))
bind_text.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
if (sg_query_buffer_will_overflow(text_ssbo, verts.size)) {
sg_destroy_buffer(text_ssbo);
text_ssbo = sg_make_buffer(&(sg_buffer_desc){
.size = verts.size,
.type = SG_BUFFERTYPE_VERTEXBUFFER,
.type = SG_BUFFERTYPE_STORAGEBUFFER,
.usage = SG_USAGE_STREAM,
.label = "text buffer"
});
}
sg_append_buffer(bind_text.vertex_buffers[0], &verts);
sg_apply_bindings(&bind_text);
sg_draw(0, 4, arrlen(text_buffer));
sg_append_buffer(text_ssbo, &verts);
int n = arrlen(text_buffer);
arrsetlen(text_buffer, 0);
return n;
}
void sdrawCharacter(struct Character c, HMM_Vec2 cursor, float scale, struct rgba color) {
@ -208,11 +211,11 @@ void sdrawCharacter(struct Character c, HMM_Vec2 cursor, float scale, struct rgb
// if (vert.pos.x > frame.l || vert.pos.y > frame.t || (vert.pos.y + vert.wh.y) < frame.b || (vert.pos.x + vert.wh.x) < frame.l) return;
vert.uv.u = c.rect.x*USHRT_MAX;
vert.uv.v = c.rect.y*USHRT_MAX;
vert.st.u = c.rect.w*USHRT_MAX;
vert.st.v = c.rect.h*USHRT_MAX;
vert.color = color;
vert.uv.x = c.rect.x;
vert.uv.y = c.rect.y;
vert.st.x = c.rect.w;
vert.st.y = c.rect.h;
rgba2floats(vert.color.e, color);
arrput(text_buffer, vert);
}

View file

@ -8,6 +8,8 @@
struct shader;
struct window;
extern sg_buffer text_ssbo;
/// Holds all state information relevant to a character as loaded using FreeType
struct Character {
float Size[2]; // Size of glyph
@ -26,6 +28,7 @@ struct sFont {
float emscale;
struct Character Characters[256];
sg_image texID;
texture *texture;
};
typedef struct sFont font;
@ -40,6 +43,6 @@ void text_settype(struct sFont *font);
struct boundingbox text_bb(const char *text, float scale, float lw, float tracking);
int renderText(const char *text, HMM_Vec2 pos, float scale, struct rgba color, float lw, int caret, float tracking);
void text_flush();
int text_flush();
#endif

View file

@ -14,39 +14,19 @@ gameobject *shape2go(cpShape *shape) {
return pshape->go;
}
HMM_Vec2 go_pos(gameobject *go)
HMM_Vec3 go_pos(gameobject *go)
{
cpVect p = cpBodyGetPosition(go->body);
return (HMM_Vec2){p.x, p.y};
return (HMM_Vec3){p.x, p.y, 0};
}
float go_angle(gameobject *go) { return cpBodyGetAngle(go->body); }
transform3d go2t3(gameobject *go)
transform go2t(gameobject *go)
{
transform3d t;
HMM_Vec2 p = go_pos(go);
t.pos.X = p.X;
t.pos.Y = p.Y;
t.pos.Z = go->drawlayer;
t.scale = go->scale;
t.scale.Z = go->scale.X;
t.rotation = go->quat;
return t;
}
HMM_Vec2 go2world(gameobject *go, HMM_Vec2 pos) { return mat_t_pos(t_go2world(go), pos); }
HMM_Vec2 world2go(gameobject *go, HMM_Vec2 pos) { return mat_t_pos(t_world2go(go), pos); }
HMM_Mat3 t_go2world(gameobject *go) { return transform2d2mat(go2t(go)); }
HMM_Mat3 t_world2go(gameobject *go) { return HMM_InvGeneralM3(t_go2world(go)); }
HMM_Mat4 t3d_go2world(gameobject *go) { return transform3d2mat(go2t3(go)); }
HMM_Mat4 t3d_world2go(gameobject *go) { return HMM_InvGeneralM4(t3d_go2world(go)); }
transform2d go2t(gameobject *go)
{
transform2d t;
transform t = {0};
t.pos.cp = cpBodyGetPosition(go->body);
t.angle = cpBodyGetAngle(go->body);
t.scale = go->scale.XY;
t.rotation = angle2rotation(cpBodyGetAngle(go->body));
t.scale = go->scale;
if (!isfinite(t.scale.X)) t.scale.X = 1;
if (!isfinite(t.scale.Y)) t.scale.Y = 1;
return t;
@ -130,15 +110,12 @@ gameobject *MakeGameobject() {
.maxvelocity = INFINITY,
.maxangularvelocity = INFINITY,
.mass = 1.f,
.next = -1,
.drawlayer = 0,
.damping = INFINITY,
.timescale = 1.0,
.ref = JS_UNDEFINED,
.mask = ~0,
.categories = 1,
.warp_mask = ~0,
.quat = HMM_QFromAxisAngle_RH((HMM_Vec3){0,1,0}, 0)
};
go.body = cpSpaceAddBody(space, cpBodyNew(go.mass, 1.f));
@ -192,14 +169,3 @@ void gameobject_setpos(gameobject *go, cpVect vec) {
cpBodySetPosition(go->body, vec);
phys2d_reindex_body(go->body);
}
void body_draw_shapes_dbg(cpBody *body, cpShape *shape, void *data) {
struct phys2d_shape *s = cpShapeGetUserData(shape);
s->debugdraw(s->data);
}
HMM_Vec3 go_pos3d(gameobject *go)
{
HMM_Vec2 pos2d = go_pos(go);
return (HMM_Vec3){pos2d.x, pos2d.y, go->drawlayer};
}

View file

@ -29,9 +29,6 @@
struct gameobject {
cpBodyType phys;
cpBody *body; /* NULL if this object is dead; has 2d position and rotation, relative to global 0 */
HMM_Vec3 scale; /* local */
HMM_Quat quat;
int next;
float mass;
float friction;
float elasticity;
@ -43,9 +40,8 @@ struct gameobject {
cpBitmask categories;
cpBitmask mask;
unsigned int warp_mask;
HMM_Vec3 scale;
JSValue ref;
HMM_Mat4 world;
float drawlayer;
};
/*
@ -68,21 +64,9 @@ typedef struct gameobject gameobject;
gameobject *MakeGameobject();
void gameobject_apply(gameobject *go);
void gameobject_free(gameobject *go);
transform go2t(gameobject *go);
transform2d go2t(gameobject *go);
transform3d go2t3(gameobject *go);
HMM_Vec2 go2world(gameobject *go, HMM_Vec2 pos);
HMM_Vec2 world2go(gameobject *go, HMM_Vec2 pos);
HMM_Mat3 t_go2world(gameobject *go);
HMM_Mat3 t_world2go(gameobject *go);
HMM_Mat4 t3d_go2world(gameobject *go);
HMM_Mat4 t3d_world2go(gameobject *go);
HMM_Vec3 go_pos3d(gameobject *go);
HMM_Vec2 go_pos(gameobject *go);
HMM_Vec3 go_pos(gameobject *go);
void gameobject_setpos(gameobject *go, cpVect vec);
float go_angle(gameobject *go);
void gameobject_setangle(gameobject *go, float angle);

View file

@ -64,13 +64,13 @@ const char *js2str(JSValue v) {
void sg_buffer_free(sg_buffer *b)
{
sg_dealloc_buffer(*b);
sg_destroy_buffer(*b);
free(b);
}
void jsfreestr(const char *s) { JS_FreeCString(js, s); }
QJSCLASS(gameobject)
QJSCLASS(transform3d)
QJSCLASS(transform2d)
QJSCLASS(transform)
QJSCLASS(emitter)
QJSCLASS(dsp_node)
QJSCLASS(texture)
@ -135,15 +135,11 @@ JSValue strarr2js(char **c)
return arr;
}
JSValue js2strarr(JSValue v)
{
}
JSValue number2js(double g) { return JS_NewFloat64(js,g); }
double js2number(JSValue v) {
double g;
JS_ToFloat64(js, &g, v);
if (isnan(g)) g = 0;
return g;
}
@ -348,6 +344,16 @@ JSValue vec32js(HMM_Vec3 v)
return array;
}
JSValue quat2js(HMM_Quat q)
{
JSValue arr = JS_NewArray(js);
js_setprop_num(arr, 0, number2js(q.x));
js_setprop_num(arr,1,number2js(q.y));
js_setprop_num(arr,2,number2js(q.z));
js_setprop_num(arr,3,number2js(q.w));
return arr;
}
HMM_Vec4 js2vec4(JSValue v)
{
HMM_Vec4 v4;
@ -356,6 +362,11 @@ HMM_Vec4 js2vec4(JSValue v)
return v4;
}
HMM_Quat js2quat(JSValue v)
{
return js2vec4(v).quat;
}
JSValue vec42js(HMM_Vec4 v)
{
JSValue array = JS_NewArray(js);
@ -633,14 +644,16 @@ JSC_GETSET(emitter, die_after_collision, boolean)
JSC_GETSET(emitter, persist, number)
JSC_GETSET(emitter, persist_var, number)
JSC_GETSET(emitter, warp_mask, bitmask)
JSC_CCALL(emitter_emit, emitter_emit(js2emitter(this), js2number(argv[0]), js2transform2d(argv[1])))
JSC_CCALL(emitter_step, emitter_step(js2emitter(this), js2number(argv[0]), js2transform2d(argv[1])))
JSC_CCALL(emitter_emit, emitter_emit(js2emitter(this), js2number(argv[0]), js2transform(argv[1])))
JSC_CCALL(emitter_step, emitter_step(js2emitter(this), js2number(argv[0]), js2transform(argv[1])))
JSC_CCALL(emitter_draw,
emitter_draw(js2emitter(this));
return number2js(arrlen(js2emitter(this)->verts));
)
JSC_CCALL(render_flushtext, text_flush())
JSC_CCALL(render_flushtext,
return number2js(text_flush());
)
JSC_CCALL(render_end_pass,
sg_end_pass();
@ -688,8 +701,37 @@ JSC_CCALL(render_end_pass,
sg_end_pass();
sg_commit();
)
JSC_SCALL(render_text_size, ret = bb2js(text_bb(str, js2number(argv[1]), js2number(argv[2]), 1)))
JSC_CCALL(render_set_camera, useproj = projection)
JSC_CCALL(render_set_camera,
JSValue cam = argv[0];
int ortho = js2boolean(js_getpropstr(cam, "ortho"));
int near = js2number(js_getpropstr(cam, "near"));
int far = js2number(js_getpropstr(cam, "far"));
float fov = js2number(js_getpropstr(cam, "fov"));
HMM_Vec4 viewport = js2vec4(js_getpropstr(cam, "viewport"));
transform *t = js2transform(js_getpropstr(cam, "transform"));
globalview.v = transform2mat(*t);
HMM_Vec2 size = mainwin.mode == MODE_FULL ? mainwin.size : mainwin.rendersize;
sg_apply_viewportf(viewport.x*size.x, viewport.y*size.y, viewport.z*size.x, viewport.w*size.y,1);
if (ortho)
globalview.p = HMM_Orthographic_RH_NO(
-size.x/2,
size.x/2,
-size.y/2,
size.y/2,
near,
far
);
else
globalview.p = HMM_Perspective_RH_NO(fov, size.y/size.x, near, far);
globalview.vp = HMM_MulM4(globalview.p, globalview.v);
projection = globalview.vp;
)
sg_shader js2shader(JSValue v)
{
@ -839,18 +881,18 @@ JSC_CCALL(render_setunim4,
JSValue arr = argv[2];
int n = js_arrlen(arr);
if (n == 1)
m = transform2d2mat4(js2transform2d(js_getpropidx(arr,0)));
m = transform2mat(*js2transform(js_getpropidx(arr,0)));
else {
for (int i = 0; i < n; i++) {
HMM_Mat4 p = transform2d2mat4(js2transform2d(js_getpropidx(arr, i)));
HMM_Mat4 p = transform2mat(*js2transform(js_getpropidx(arr, i)));
m = HMM_MulM4(p,m);
}
}
} else
m = transform2d2mat4(js2transform2d(argv[2]));
m = transform2mat(*js2transform(argv[2]));
sg_apply_uniforms(js2number(argv[0]), js2number(argv[1]), SG_RANGE_REF(m.e));
);
);
JSC_CCALL(render_spdraw,
sg_bindings bind = js2bind(argv[0]);
@ -866,11 +908,16 @@ JSC_CCALL(render_setpipeline,
sg_apply_pipeline(p);
)
JSC_CCALL(render_text_ssbo,
return sg_buffer2js(&text_ssbo);
)
static const JSCFunctionListEntry js_render_funcs[] = {
MIST_FUNC_DEF(render, flushtext, 0),
MIST_FUNC_DEF(render, end_pass, 0),
MIST_FUNC_DEF(render, text_size, 3),
MIST_FUNC_DEF(render, set_camera, 0),
MIST_FUNC_DEF(render, text_ssbo, 0),
MIST_FUNC_DEF(render, set_camera, 1),
MIST_FUNC_DEF(render, pipeline, 1),
MIST_FUNC_DEF(render, setuniv3, 2),
MIST_FUNC_DEF(render, setuniv, 2),
@ -882,7 +929,7 @@ static const JSCFunctionListEntry js_render_funcs[] = {
MIST_FUNC_DEF(render, setpipeline, 1)
};
JSC_CCALL(gui_flush, text_flush(&useproj));
JSC_CCALL(gui_flush, text_flush());
JSC_CCALL(gui_scissor, sg_apply_scissor_rect(js2number(argv[0]), js2number(argv[1]), js2number(argv[2]), js2number(argv[3]), 0))
JSC_CCALL(gui_text,
const char *s = JS_ToCString(js, argv[0]);
@ -1016,7 +1063,7 @@ static const JSCFunctionListEntry js_input_funcs[] = {
};
JSC_CCALL(prosperon_phys2d_step, phys2d_update(js2number(argv[0])))
JSC_CCALL(prosperon_window_render, openglRender(&mainwin, js2transform2d(argv[0]), js2number(argv[1])))
JSC_CCALL(prosperon_window_render, openglRender(&mainwin))
JSC_CCALL(prosperon_guid,
uint8_t bytes[16];
for (int i = 0; i < 16; i++) bytes[i] = rand()%256;
@ -1303,7 +1350,7 @@ static const JSCFunctionListEntry js_physics_funcs[] = {
};
JSC_CCALL(model_draw_go,
model_draw_go(js2model(this), js2gameobject(argv[0]), js2gameobject(argv[1]))
model_draw_go(js2model(this), js2gameobject(argv[0]))
);
static const JSCFunctionListEntry js_model_funcs[] = {
@ -1333,14 +1380,29 @@ static const JSCFunctionListEntry js_emitter_funcs[] = {
MIST_FUNC_DEF(emitter, draw, 1)
};
JSC_GETSET(transform2d, pos, vec2)
JSC_GETSET(transform2d, scale, vec2)
JSC_GETSET(transform2d, angle, number)
JSC_GETSET(transform, pos, vec3)
JSC_GETSET(transform, scale, vec3)
JSC_GETSET(transform, rotation, quat)
JSC_CCALL(transform_lookat,
HMM_Vec3 point = js2vec3(argv[0]);
transform *go = js2transform(this);
HMM_Mat4 m = HMM_LookAt_RH(go->pos, point, vUP);
go->rotation = HMM_M4ToQ_RH(m);
)
static const JSCFunctionListEntry js_transform2d_funcs[] = {
CGETSET_ADD(transform2d, pos),
CGETSET_ADD(transform2d, scale),
CGETSET_ADD(transform2d, angle)
JSC_CCALL(transform_rotate,
HMM_Vec3 axis = js2vec3(argv[0]);
transform *t = js2transform(this);
HMM_Quat rot = HMM_QFromAxisAngle_RH(axis, js2number(argv[1]));
t->rotation = HMM_MulQ(t->rotation, rot);
)
static const JSCFunctionListEntry js_transform_funcs[] = {
CGETSET_ADD(transform, pos),
CGETSET_ADD(transform, scale),
CGETSET_ADD(transform, rotation),
MIST_FUNC_DEF(transform, rotate, 2),
MIST_FUNC_DEF(transform, lookat, 1)
};
JSC_GETSET(dsp_node, pass, boolean)
@ -1454,32 +1516,9 @@ JSC_GETSET(gameobject, timescale, number)
JSC_GETSET(gameobject, maxvelocity, number)
JSC_GETSET(gameobject, maxangularvelocity, number)
JSC_GETSET(gameobject, warp_mask, bitmask)
JSC_GETSET(gameobject, drawlayer, number)
JSC_GETSET(gameobject, categories, bitmask)
JSC_GETSET(gameobject, mask, bitmask)
JSC_CCALL(gameobject_selfsync, gameobject_apply(js2gameobject(this)))
JSC_CCALL(gameobject_world2this, return vec22js(world2go(js2gameobject(this), js2vec2(argv[0]))))
JSC_CCALL(gameobject_this2world, return vec22js(go2world(js2gameobject(this), js2vec2(argv[0]))))
JSC_CCALL(gameobject_dir_world2this, return vec22js(mat_t_dir(t_world2go(js2gameobject(this)), js2vec2(argv[0]))))
JSC_CCALL(gameobject_dir_this2world, return vec22js(mat_t_dir(t_go2world(js2gameobject(this)), js2vec2(argv[0]))))
JSC_CCALL(gameobject_rotate3d,
HMM_Vec3 rot = js2vec3(argv[0]);
HMM_Quat qrot = HMM_QFromAxisAngle_RH((HMM_Vec3){1,0,0}, rot.x);
qrot = HMM_MulQ(qrot, HMM_QFromAxisAngle_RH((HMM_Vec3){0,1,0}, rot.y));
qrot = HMM_MulQ(qrot, HMM_QFromAxisAngle_RH((HMM_Vec3){0,0,1}, rot.z));
gameobject *go = js2gameobject(this);
go->quat = HMM_MulQ(go->quat, qrot);
return JS_UNDEFINED;
)
JSC_CCALL(gameobject_lookat,
HMM_Vec3 point = js2vec3(argv[0]);
gameobject *go = js2gameobject(this);
HMM_Vec3 pos = go_pos3d(go);
HMM_Mat4 m = HMM_LookAt_RH(pos, point, (HMM_Vec3){0,1,0});
go->quat = HMM_M4ToQ_RH(m);
)
static const JSCFunctionListEntry js_gameobject_funcs[] = {
CGETSET_ADD(gameobject, friction),
@ -1491,12 +1530,8 @@ static const JSCFunctionListEntry js_gameobject_funcs[] = {
CGETSET_ADD(gameobject,maxangularvelocity),
CGETSET_ADD(gameobject,layer),
CGETSET_ADD(gameobject,warp_mask),
CGETSET_ADD(gameobject,drawlayer),
CGETSET_ADD(gameobject, categories),
CGETSET_ADD(gameobject, mask),
CGETSET_ADD_HID(gameobject, rpos),
CGETSET_ADD_HID(gameobject, rangle),
CGETSET_ADD_HID(gameobject, rscale),
CGETSET_ADD(gameobject, velocity),
CGETSET_ADD(gameobject, angularvelocity),
// CGETSET_ADD(gameobject, moi),
@ -1505,13 +1540,7 @@ static const JSCFunctionListEntry js_gameobject_funcs[] = {
MIST_FUNC_DEF(gameobject, impulse, 1),
MIST_FUNC_DEF(gameobject, force, 1),
MIST_FUNC_DEF(gameobject, force_local, 2),
MIST_FUNC_DEF(gameobject, world2this, 1),
MIST_FUNC_DEF(gameobject, this2world, 1),
MIST_FUNC_DEF(gameobject, dir_world2this, 1),
MIST_FUNC_DEF(gameobject, dir_this2world, 1),
MIST_FUNC_DEF(gameobject, selfsync, 0),
MIST_FUNC_DEF(gameobject, rotate3d, 1),
MIST_FUNC_DEF(gameobject, lookat, 1)
};
JSC_CCALL(joint_pin, return constraint2js(constraint_make(cpPinJointNew(js2gameobject(argv[0])->body, js2gameobject(argv[1])->body, cpvzero,cpvzero))))
@ -1811,21 +1840,14 @@ JSC_SCALL(os_make_texture,
JS_SetPropertyStr(js, ret, "path", JS_DupValue(js,argv[0]));
)
JSC_CCALL(os_make_font, return font2js(MakeFont(js2str(argv[0]), js2number(argv[1]))))
JSC_CCALL(os_make_transform2d,
if (JS_IsUndefined(argv[0]))
return transform2d2js(make_transform2d());
int n = js2number(argv[0]);
transform2d *t = calloc(sizeof(transform2d), n);
JSValue arr = JS_NewArray(js);
for (int i = 0; i < n; i++)
js_setprop_num(arr, i, transform2d2js(t+i));
return arr;
JSC_CCALL(os_make_font,
font *f = MakeFont(js2str(argv[0]), js2number(argv[1]));
ret = font2js(f);
js_setpropstr(ret, "texture", texture2js(f->texture));
)
JSC_CCALL(os_make_transform, return transform2js(make_transform()))
JSC_SCALL(os_system, return number2js(system(str)); )
JSC_SCALL(os_make_model, ret = model2js(model_make(str)))
JSC_CCALL(os_make_emitter,
@ -2011,7 +2033,7 @@ static const JSCFunctionListEntry js_os_funcs[] = {
MIST_FUNC_DEF(os, make_texture, 1),
MIST_FUNC_DEF(os, make_font, 2),
MIST_FUNC_DEF(os, make_model, 1),
MIST_FUNC_DEF(os, make_transform2d, 1),
MIST_FUNC_DEF(os, make_transform, 0),
MIST_FUNC_DEF(os, make_emitter, 0),
MIST_FUNC_DEF(os, make_buffer, 1),
MIST_FUNC_DEF(os, make_line_prim, 2),
@ -2033,12 +2055,11 @@ void ffi_load() {
globalThis = JS_GetGlobalObject(js);
QJSCLASSPREP(ptr);
QJSCLASSPREP(transform3d);
QJSGLOBALCLASS(os);
QJSCLASSPREP_FUNCS(gameobject);
QJSCLASSPREP_FUNCS(transform2d);
QJSCLASSPREP_FUNCS(transform);
QJSCLASSPREP_FUNCS(dsp_node);
QJSCLASSPREP_FUNCS(emitter);
QJSCLASSPREP_FUNCS(warp_gravity);

View file

@ -39,22 +39,24 @@ float variate(float val, float variance)
return val + val*(frand(variance)-(variance/2));
}
int emitter_spawn(emitter *e, transform2d *t)
int emitter_spawn(emitter *e, transform *t)
{
if (arrlen(e->particles) == e->max) return 0;
particle p = {0};
p.life = e->life;
p.pos = (HMM_Vec4){t->pos.x,t->pos.y,0,0};
float newan = t->angle + (frand(e->divergence)-(e->divergence/2))*HMM_TurnToRad;
HMM_Vec2 norm = HMM_V2Rotate((HMM_Vec2){0,1}, newan);
p.v = HMM_MulV4F((HMM_Vec4){norm.x,norm.y,0,0}, variate(e->speed, e->variation));
p.pos = (HMM_Vec4){t->pos.x,t->pos.y,t->pos.z,0};
HMM_Vec3 up = trans_forward(t);
float newan = (frand(e->divergence)-(e->divergence/2))*HMM_TurnToRad;
HMM_Vec2 v2n = HMM_V2Rotate((HMM_Vec2){0,1}, newan);
HMM_Vec3 norm = (HMM_Vec3){v2n.x, v2n.y,0};
p.v = HMM_MulV4F((HMM_Vec4){norm.x,norm.y,norm.z,0}, variate(e->speed, e->variation));
p.angle = 0.25;
p.scale = variate(e->scale*t->scale.x, e->scale_var);
arrput(e->particles,p);
return 1;
}
void emitter_emit(emitter *e, int count, transform2d *t)
void emitter_emit(emitter *e, int count, transform *t)
{
for (int i = 0; i < count; i++)
emitter_spawn(e, t);
@ -92,7 +94,7 @@ void emitter_draw(emitter *e)
sg_append_buffer(e->buffer, &verts);
}
void emitter_step(emitter *e, double dt, transform2d *t) {
void emitter_step(emitter *e, double dt, transform *t) {
HMM_Vec4 g_accel = HMM_MulV4F((HMM_Vec4){cpSpaceGetGravity(space).x, cpSpaceGetGravity(space).y, 0, 0}, dt);

View file

@ -68,8 +68,8 @@ typedef struct emitter {
emitter *make_emitter();
void emitter_free(emitter *e);
void emitter_emit(emitter *e, int count, transform2d *t);
void emitter_step(emitter *e, double dt, transform2d *t);
void emitter_emit(emitter *e, int count, transform *t);
void emitter_step(emitter *e, double dt, transform *t);
void emitter_draw(emitter *e);
#endif

View file

@ -23,6 +23,8 @@ static HMM_Vec2 lastuse = {0};
HMM_Vec2 campos = {0,0};
float camzoom = 1;
viewstate globalview = {0};
sg_sampler std_sampler;
sg_sampler nofilter_sampler;
sg_sampler tex_sampler;
@ -185,11 +187,10 @@ HMM_Mat4 projection = {0.f};
HMM_Mat4 hudproj = {0.f};
HMM_Mat4 useproj = {0};
void openglRender(struct window *window, transform2d *cam, float zoom) {
void openglRender(struct window *window) {
HMM_Vec2 usesize = mainwin.rendersize;
if (mainwin.mode == MODE_FULL)
usesize = mainwin.size;
//sg_apply_viewportf(0,0,usesize.x,usesize.y,1);
if (usesize.x != lastuse.x || usesize.y != lastuse.y) {
printf("Redoing to %g,%g\n", usesize.x, usesize.y);
sg_destroy_image(screencolor);
@ -219,16 +220,6 @@ void openglRender(struct window *window, transform2d *cam, float zoom) {
}
lastuse = usesize;
sg_begin_pass(&offscreen);
// 2D projection
campos = cam->pos;
camzoom = zoom;
projection = HMM_Orthographic_RH_NO(
campos.x - camzoom * usesize.x / 2,
campos.x + camzoom * usesize.x / 2,
campos.y - camzoom * usesize.y / 2,
campos.y + camzoom * usesize.y / 2, -10000.f, 10000.f);
}
struct boundingbox cwh2bb(HMM_Vec2 c, HMM_Vec2 wh) {

View file

@ -38,6 +38,14 @@ extern sg_sampler tex_sampler;
extern sg_image screencolor;
extern sg_image screendepth;
typedef struct viewstate {
HMM_Mat4 v;
HMM_Mat4 p;
HMM_Mat4 vp;
} viewstate;
extern viewstate globalview;
struct draw_p {
float x;
float y;
@ -63,7 +71,7 @@ void render_init();
extern HMM_Vec2 campos;
extern float camzoom;
void openglRender(struct window *window, transform2d *cam, float zoom);
void openglRender(struct window *window);
void opengl_rendermode(enum RenderMode r);
void openglInit3d(struct window *window);

View file

@ -131,7 +131,7 @@ struct texture *texture_from_file(const char *path) {
mipw = tex->width;
miph = tex->height;
sg_img_data.subimage[0][0] = (sg_range){ .ptr = data, .size = mipw*miph*4 };
sg_img_data.subimage[0][0] = (sg_range){ .ptr = data, .size = mipw*miph*4 };
unsigned char *mipdata[mips];
mipdata[0] = data;
@ -166,6 +166,7 @@ struct texture *texture_from_file(const char *path) {
void texture_free(texture *tex)
{
if (!tex) return;
if (tex->data)
free(tex->data);
if (tex->delays) arrfree(tex->delays);
sg_destroy_image(tex->id);

View file

@ -2,35 +2,21 @@
#include <string.h>
#include <stdio.h>
const transform2d t2d_unit = {
.pos = {0,0},
.scale = {1,1},
.angle = 0
};
transform3d *make_transform3d()
transform *make_transform()
{
transform3d *t = calloc(sizeof(transform3d),1);
transform *t = calloc(sizeof(transform),1);
t->scale = (HMM_Vec3){1,1,1};
return t;
}
void transform3d_free(transform3d *t) { free(t); }
void transform_free(transform *t) { free(t); }
transform2d *make_transform2d()
{
transform2d *t = calloc(sizeof(transform2d),1);
t->scale = (HMM_Vec2){1,1};
return t;
}
void transform2d_free(transform2d *t) { free(t); }
HMM_Vec3 trans_forward(const transform3d *const trans) { return HMM_QVRot(vFWD, trans->rotation); }
HMM_Vec3 trans_back(const transform3d *trans) { return HMM_QVRot(vBKWD, trans->rotation); }
HMM_Vec3 trans_up(const transform3d *trans) { return HMM_QVRot(vUP, trans->rotation); }
HMM_Vec3 trans_down(const transform3d *trans) { return HMM_QVRot(vDOWN, trans->rotation); }
HMM_Vec3 trans_right(const transform3d *trans) { return HMM_QVRot(vRIGHT, trans->rotation); }
HMM_Vec3 trans_left(const transform3d *trans) { return HMM_QVRot(vLEFT, trans->rotation); }
HMM_Vec3 trans_forward(const transform *const trans) { return HMM_QVRot(vFWD, trans->rotation); }
HMM_Vec3 trans_back(const transform *trans) { return HMM_QVRot(vBKWD, trans->rotation); }
HMM_Vec3 trans_up(const transform *trans) { return HMM_QVRot(vUP, trans->rotation); }
HMM_Vec3 trans_down(const transform *trans) { return HMM_QVRot(vDOWN, trans->rotation); }
HMM_Vec3 trans_right(const transform *trans) { return HMM_QVRot(vRIGHT, trans->rotation); }
HMM_Vec3 trans_left(const transform *trans) { return HMM_QVRot(vLEFT, trans->rotation); }
HMM_Vec2 mat_t_pos(HMM_Mat3 m, HMM_Vec2 pos) { return HMM_MulM3V3(m, (HMM_Vec3){pos.x, pos.y, 1}).xy; }
@ -54,43 +40,23 @@ HMM_Vec3 mat3_t_dir(HMM_Mat4 m, HMM_Vec3 dir)
return mat3_t_pos(m, dir);
}
HMM_Mat3 transform2d2mat(transform2d trn) {
return HMM_MulM3(HMM_Translate2D(trn.pos), HMM_MulM3(HMM_RotateM3(trn.angle), HMM_ScaleM3(trn.scale)));
HMM_Mat4 transform2mat(transform t) {
return HMM_M4TRS(t.pos, t.rotation, t.scale);
}
HMM_Mat4 transform2d2mat4(transform2d *t)
HMM_Quat angle2rotation(float angle)
{
HMM_Mat4 T = {0};
float c = cosf(t->angle);
float s = sinf(t->angle);
T.col[0].x = c*t->scale.x;
T.col[0].y = s*t->scale.y;
T.col[1].x = -s*t->scale.x;
T.col[1].y = c*t->scale.y;
T.col[3].xy = t->pos;
T.col[2].z = 1;
T.col[3].w = 1;
return T;
return HMM_QFromAxisAngle_RH(vUP, angle);
}
transform2d mat2transform2d(HMM_Mat3 m)
float transform2angle(HMM_Vec3 axis)
{
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)));
}
transform3d mat2transform3d(HMM_Mat4 m)
transform mat2transform(HMM_Mat4 m)
{
transform3d t;
transform t;
t.pos = m.Columns[3].xyz;
for (int i = 0; i < 2; i++)
t.scale.Elements[i] = HMM_LenV3(m.Columns[i].xyz);

View file

@ -3,37 +3,24 @@
#include "HandmadeMath.h"
typedef struct transform3d {
typedef struct transform {
HMM_Vec3 pos;
HMM_Vec3 scale;
HMM_Quat rotation;
} transform3d;
} transform;
transform3d *make_transform3d();
void transform3d_free(transform3d *t);
typedef struct {
HMM_Vec2 pos;
HMM_Vec2 scale;
float angle;
} transform2d;
transform2d *make_transform2d();
void transform2d_free(transform2d *t);
extern const transform2d t2d_unit;
transform *make_transform();
void transform_free(transform *t);
#define VEC2_FMT "[%g,%g]"
#define VEC2_MEMS(s) (s).x, (s).y
HMM_Vec3 trans_forward(const transform3d *const trans);
HMM_Vec3 trans_back(const transform3d *trans);
HMM_Vec3 trans_up(const transform3d *trans);
HMM_Vec3 trans_down(const transform3d *trans);
HMM_Vec3 trans_right(const transform3d *trans);
HMM_Vec3 trans_left(const transform3d *trans);
HMM_Mat4 transform2d2mat4(transform2d *t);
HMM_Vec3 trans_forward(const transform *const trans);
HMM_Vec3 trans_back(const transform *trans);
HMM_Vec3 trans_up(const transform *trans);
HMM_Vec3 trans_down(const transform *trans);
HMM_Vec3 trans_right(const transform *trans);
HMM_Vec3 trans_left(const transform *trans);
/* Transform a position via the matrix */
HMM_Vec2 mat_t_pos(HMM_Mat3 m, HMM_Vec2 pos);
@ -48,9 +35,9 @@ float vec_dirangle(HMM_Vec2 a, HMM_Vec2 b);
HMM_Vec3 mat3_t_pos(HMM_Mat4 m, HMM_Vec3 pos);
HMM_Vec3 mat3_t_dir(HMM_Mat4 m, HMM_Vec3 dir);
HMM_Mat3 transform2d2mat(transform2d t);
transform2d mat2transform2d(HMM_Mat3 m);
HMM_Mat4 transform3d2mat(transform3d t);
transform3d mat2transform3d(HMM_Mat4 m);
HMM_Mat4 transform2mat(transform t);
transform mat2transform(HMM_Mat4 m);
HMM_Quat angle2rotation(float angle);
#endif

View file

@ -9,7 +9,7 @@ typedef uint32_t warpmask;
#define gravmask 1U
typedef struct {
transform3d t;
transform t;
float strength;
float decay;
int spherical;
@ -18,7 +18,7 @@ typedef struct {
} warp_gravity;
typedef struct {
transform3d t;
transform t;
int unlimited_range;
HMM_Vec3 range;
HMM_Vec3 falloff;
@ -27,7 +27,7 @@ typedef struct {
} warp_damp;
typedef struct {
transform3d t;
transform t;
float strength;
float decay;
float pulse; /* strength of random variance in the wind effect */