diff --git a/ecs2.h b/ecs2.h index 4376efb..243374f 100644 --- a/ecs2.h +++ b/ecs2.h @@ -90,7 +90,8 @@ typedef int ecs_eid; // Define the CIDs necessary to access a component (each component MUST // have a unique id and I can't do that inside a macro without requiring -// extensions) +// extensions). Note: can't use enum, because we need the flag value too. +// (unless you have a compiler that supports iterating over macro varargs) #define ECS_CID(type, id) \ const int type##_id = id; \ const ecs_cid type##_fl = (1ULL << id); diff --git a/junk.txt b/junk.txt new file mode 100644 index 0000000..e632dde --- /dev/null +++ b/junk.txt @@ -0,0 +1,15 @@ + // haloo3d_print(&pt, "Thi sis a gaint string. I am disylax, I acn'at type, really \n" + // "And this string will just keep going because i need it to take up tons of\n" + // "your time today. fuck you, eat a cock, thank you. just kidding, i love you\n" + // "please have a nice day, but eat a cock if you like that kind of thing. \n" + // "slurp slurp yummy yummy give me treats. i like fat bellies"); + // haloo3d_print(&pt, "Thi sis a gaint string. I am disylax, I acn'at type, really \n" + // "And this string will just keep going because i need it to take up tons of\n" + // "your time today. fuck you, eat a cock, thank you. just kidding, i love you\n" + // "please have a nice day, but eat a cock if you like that kind of thing. \n" + // "slurp slurp yummy yummy give me treats. i like fat bellies"); + // haloo3d_print(&pt, "Thi sis a gaint string. I am disylax, I acn'at type, really \n" + // "And this string will just keep going because i need it to take up tons of\n" + // "your time today. fuck you, eat a cock, thank you. just kidding, i love you\n" + // "please have a nice day, but eat a cock if you like that kind of thing. \n" + // "slurp slurp yummy yummy give me treats. i like fat bellies"); diff --git a/terrain.c b/terrain.c index 23b8cbb..46f1b85 100644 --- a/terrain.c +++ b/terrain.c @@ -22,6 +22,11 @@ #define AVGWEIGHT 0.85 #define DEFAULTUP \ { .x = 0, .y = 1, .z = 0 } +// Lookvec for objects which all face forward along with the player +#define DEFAULTLOOK \ + { .x = 0, .y = 0, .z = -1 } +#define CHUNKSCALE \ + { .x = 1.0, .y = 1.0, .z = 1.0 } // These are initial values but there may be ways to change it #define CAM_INITPITCH MPI_2 @@ -30,6 +35,9 @@ #define INIT_FOV 90.0 #define INIT_DITHERSTART 10000 #define INIT_DITHEREND 10000 +#define INIT_LIGHTPITCH -MPI / 4.0 +#define INIT_LIGHTYAW 0 +#define INIT_MINLIGHT 0.2 #define INIT_PLAYERSPEED \ { .x = 0, .y = 0, .z = -0.5 } @@ -37,6 +45,8 @@ // Some globals you can mess around with potentially int fps = 30; +#define PALETTEKEY "palette" + // --------------------------------------------------- // The terrain ecs systems // --------------------------------------------------- @@ -91,75 +101,79 @@ void sys_renderobject(ecs_placement *p, ecs_object *o, tecs **ecs) { // Apply scale such that it looks like it was applied first (this prevents // scaling applying skew to a rotated object) haloo3d_mat4_prescalev(modelm, o->scale.v); - mat4_multiply(finalmatrix, o->context->precalc_screen, modelm); - haloo3d_precalc_verts(o->model, finalmatrix, precalc_verts); - // --**-- Next, setup some rendering invariants --**-- - struct vec3 lighting; - // The compiler is complaining about lighting being used unitialized, even - // though it's not. Just shut it up - vec3(lighting.v, 0, 0, 0); - o->context->rendersettings.texture = o->texture; - if (o->lighting) { - if (o->lighting->autolightfix) { - // Lighting doesn't rotate with the model unless you do it yourself. - // In the easy system, you can request the renderer to do it for you - struct vec4 ltmp, lout; - // Lighting is centered at 0 - vec4(ltmp.v, 0, 0, 0, 1); - // Calc the same lookat just without translation. THis should be the same - // rotation matrix used on the model - haloo3d_my_lookat(modelm, ltmp.v, p->lookvec.v, p->up.v); - // We actually want the inverse. Apparently to speed things up, the - // transpose works for rotation matrices(?) but I don't trust that this - // lookat does that - // mat4_inverse(modelm, modelm); - mat4_transpose(modelm, modelm); - // We HAVE to have a vec4 (oof) - vec4(ltmp.v, o->lighting->dir.x, o->lighting->dir.y, o->lighting->dir.z, - 1); - haloo3d_vec4_multmat_into(<mp, modelm, &lout); - // No need to fix W, should all be good (no perspective divide). But we DO - // need to pull out that result - vec3(lighting.v, lout.x, lout.y, lout.z); - vec3_normalize(lighting.v, lighting.v); - } else { - vec3_assign(lighting.v, o->lighting->dir.v); - } - } - // --**-- Finally, actually render faces --**-- - haloo3d_facef face, baseface; - haloo3d_facef outfaces[H3D_FACEF_MAXCLIP]; - for (int facei = 0; facei < o->model->numfaces; facei++) { - // Copy face values out of precalc array and clip them - haloo3d_make_facef(o->model->faces[facei], precalc_verts, - o->model->vtexture, face); - int tris = haloo3d_facef_clip(face, outfaces); - if (tris > 0) { - uint8_t oflags = o->context->rendersettings.flags; - if (o->lighting) { - haloo3d_obj_facef(o->model, o->model->faces[facei], baseface); - o->context->rendersettings.intensity = - haloo3d_calc_light(lighting.v, o->lighting->minlight, baseface); + // We might be rendering into multiple contexts in a multiplayer game (or + // just different angles or something) + for (int ctx = 0; ctx < o->contextcount; ctx++) { + mat4_multiply(finalmatrix, o->context[ctx]->precalc_screen, modelm); + haloo3d_precalc_verts(o->model, finalmatrix, precalc_verts); + // --**-- Next, setup some rendering invariants --**-- + struct vec3 lighting; + // The compiler is complaining about lighting being used unitialized, even + // though it's not. Just shut it up + vec3(lighting.v, 0, 0, 0); + o->context[ctx]->rendersettings.texture = o->texture; + if (o->lighting) { + if (o->lighting->autolightfix) { + // Lighting doesn't rotate with the model unless you do it yourself. + // In the easy system, you can request the renderer to do it for you + struct vec4 ltmp, lout; + // Lighting is centered at 0 + vec4(ltmp.v, 0, 0, 0, 1); + // Calc the same lookat just without translation. THis should be the + // same rotation matrix used on the model + haloo3d_my_lookat(modelm, ltmp.v, p->lookvec.v, p->up.v); + // We actually want the inverse. Apparently to speed things up, the + // transpose works for rotation matrices(?) but I don't trust that this + // lookat does that + // mat4_inverse(modelm, modelm); + mat4_transpose(modelm, modelm); + // We HAVE to have a vec4 (oof) + vec4(ltmp.v, o->lighting->dir.x, o->lighting->dir.y, o->lighting->dir.z, + 1); + haloo3d_vec4_multmat_into(<mp, modelm, &lout); + // No need to fix W, should all be good (no perspective divide). But we + // DO need to pull out that result + vec3(lighting.v, lout.x, lout.y, lout.z); + vec3_normalize(lighting.v, lighting.v); } else { - o->context->rendersettings.intensity = H3DVF(1.0); + vec3_assign(lighting.v, o->lighting->dir.v); } - // if ((r->_objstate[object - r->objects] & H3D_EASYOBJSTATE_NOTRANS)) { - // r->rendersettings.flags &= ~H3DR_TRANSPARENCY; - // } - for (int ti = 0; ti < tris; ti++) { - int backface = !haloo3d_facef_finalize(outfaces[ti]); - if (o->cullbackface && backface) { - continue; + } + // --**-- Finally, actually render faces --**-- + haloo3d_facef face, baseface; + haloo3d_facef outfaces[H3D_FACEF_MAXCLIP]; + for (int facei = 0; facei < o->model->numfaces; facei++) { + // Copy face values out of precalc array and clip them + haloo3d_make_facef(o->model->faces[facei], precalc_verts, + o->model->vtexture, face); + int tris = haloo3d_facef_clip(face, outfaces); + if (tris > 0) { + uint8_t oflags = o->context[ctx]->rendersettings.flags; + if (o->lighting) { + haloo3d_obj_facef(o->model, o->model->faces[facei], baseface); + o->context[ctx]->rendersettings.intensity = + haloo3d_calc_light(lighting.v, o->lighting->minlight, baseface); + } else { + o->context[ctx]->rendersettings.intensity = H3DVF(1.0); } - (*ecs)->totaldrawn++; - // We still have to convert the points into the view - haloo3d_facef_viewport_into_fast(outfaces[ti], - o->context->precalc_halfwidth, - o->context->precalc_halfheight); - haloo3d_triangle(&o->context->window, &o->context->rendersettings, - outfaces[ti]); + // if ((r->_objstate[object - r->objects] & H3D_EASYOBJSTATE_NOTRANS)) { + // r->rendersettings.flags &= ~H3DR_TRANSPARENCY; + // } + for (int ti = 0; ti < tris; ti++) { + int backface = !haloo3d_facef_finalize(outfaces[ti]); + if (o->cullbackface && backface) { + continue; + } + (*ecs)->totaldrawn++; + // We still have to convert the points into the view + haloo3d_facef_viewport_into_fast(outfaces[ti], + o->context[ctx]->precalc_halfwidth, + o->context[ctx]->precalc_halfheight); + haloo3d_triangle(&o->context[ctx]->window, + &o->context[ctx]->rendersettings, outfaces[ti]); + } + o->context[ctx]->rendersettings.flags = oflags; } - o->context->rendersettings.flags = oflags; } } } @@ -186,6 +200,51 @@ void sys_playerinput(ecs_input *in) { } while (event.type != unigi_enum_event_none); } +void sys_playergarbage(ecs_playergarbage *pg, ecs_object *ob, tecs **ecs) { + ecs_eid id = tecs_eid(ecs); + if (ob->contextcount <= 0) { + eprintf("Deleting object %d\n", id); + if (pg->dynmodel[0]) { + haloo3d_easystore_deleteobj(&(*ecs)->storage, pg->dynmodel, + haloo3d_obj_free); + } + tecs_deleteentity(*ecs, id); + } +} + +void gen_chunk(render_context *ctx, tecs *ecs, struct vec2i pos) { + eprintf("Generating chunk %d,%d\n", pos.x, pos.y); + // TODO: don't make the system generate components? Let someone else set + // ourselves up, then we just generate the model or... whatever... or is + // that bad? Maybe that's bad, since we'll suddenly be renderable without a + // model, ugh. + // haloo3d_gen_paletteuv(haloo3d_fb *fb, uint16_t col, struct vec2 *uvout); + ecs_eid id = tecs_newentity(ecs, 0); + ecs_playergarbage garbage; + sprintf(garbage.dynmodel, "e%d", id); + haloo3d_obj *model = + haloo3d_easystore_addobj(&ecs->storage, garbage.dynmodel); + ECS_SETCOMPONENT(ecs, id, ecs_playergarbage) garbage; + ECS_SETCOMPONENT(ecs, id, + ecs_placement){.up = DEFAULTUP, + .lookvec = DEFAULTLOOK, + .pos = {.x = pos.x, .y = 0, .z = pos.y}}; + // TODO: an easy place for optimization (if it's even needed) + ECS_SETCOMPONENT(ecs, id, ecs_object){ + .texture = haloo3d_easystore_gettex(&ecs->storage, PALETTEKEY), + .scale = CHUNKSCALE, + .lighting = &ecs->chunklight, + .model = model, + .cullbackface = 1, + .context = {ctx}, + .contextcount = 1}; +} +// void sys_chunk(ecs_chunk *ch, ecs_object *o, tecs **ecs) { +// // Is it really ok to have this check every single time? Seems kinda +// wasteful if (ch->generation == 1) { +// } +// } + // --------------------------------------------------- // MAIN FUNCTION // --------------------------------------------------- @@ -204,19 +263,13 @@ int main() { // int argc, char **argv) { eprintf("Initialized unigi system\n"); - haloo3d_easystore storage; - haloo3d_easystore_init(&storage); - haloo3d_fb *palettetex = haloo3d_easystore_addtex(&storage, "palette"); - haloo3d_gen_palettetex(palettetex); - - eprintf("Initialized storage and default textures/etc\n"); - haloo3d_fb screen; haloo3d_fb_init(&screen, SWIDTH, SHEIGHT); haloo3d_print_tracker pt; char printbuf[8192]; haloo3d_print_initdefault(&pt, printbuf, sizeof(printbuf)); pt.fb = &screen; + pt.scale = 1; haloo3d_easytimer frametimer, drawtimer, sdltimer; haloo3d_easytimer_init(&frametimer, AVGWEIGHT); @@ -236,6 +289,17 @@ int main() { // int argc, char **argv) { ecs.delta_s = 0; tecs_init(&ecs); int tecs_size = sizeof(tecs); + YAWP2VEC(INIT_LIGHTYAW, INIT_LIGHTPITCH, ecs.globallighting.v); + // An issue? Not a pointer? Eeehhh.... + ecs.chunklight.dir = ecs.globallighting; + ecs.chunklight.minlight = INIT_MINLIGHT; + ecs.chunklight.autolightfix = 0; + + haloo3d_easystore_init(&ecs.storage); + haloo3d_fb *palettetex = haloo3d_easystore_addtex(&ecs.storage, PALETTEKEY); + haloo3d_gen_palettetex(palettetex); + + eprintf("Setup ECS system + obj/tex storage (%d bytes)\n", tecs_size); ecs_eid playerid = tecs_newentity(&ecs, 0); ECS_SETCOMPONENT(&ecs, playerid, ecs_placement){ @@ -247,7 +311,7 @@ int main() { // int argc, char **argv) { ECS_SETCOMPONENT(&ecs, playerid, ecs_input){}; ecs_placement *playerpos = &ECS_GETCOMPONENT(&ecs, playerid, ecs_placement); - eprintf("Setup ECS system (%d bytes)\n", tecs_size); + eprintf("Setup player\n"); // MAIN LOOP while (1) { @@ -261,6 +325,9 @@ int main() { // int argc, char **argv) { ECS_RUNSYSTEM2(&ecs, sys_rotation, ecs_placement, ecs_rotation); ECS_RUNSYSTEM3(&ecs, sys_movement, ecs_placement, ecs_movement, tecs); ECS_RUNSYSTEM2(&ecs, sys_rendercontext, ecs_rendercontext, ecs_placement); + // ECS_RUNSYSTEM3(&ecs, sys_chunk, ecs_chunk, ecs_object, tecs); + ECS_RUNSYSTEM3(&ecs, sys_playergarbage, ecs_playergarbage, ecs_object, + tecs); haloo3d_easytimer_start(&drawtimer); ECS_RUNSYSTEM3(&ecs, sys_renderobject, ecs_placement, ecs_object, tecs); haloo3d_easytimer_end(&drawtimer); @@ -302,6 +369,6 @@ int main() { // int argc, char **argv) { haloo3d_fb_free(&screen); haloo3d_fb_free(&context.window); - haloo3d_easystore_deleteallobj(&storage, haloo3d_obj_free); - haloo3d_easystore_deletealltex(&storage, haloo3d_fb_free); + haloo3d_easystore_deleteallobj(&ecs.storage, haloo3d_obj_free); + haloo3d_easystore_deletealltex(&ecs.storage, haloo3d_fb_free); } diff --git a/terrain_ecstypes.h b/terrain_ecstypes.h index 397f88e..b282430 100644 --- a/terrain_ecstypes.h +++ b/terrain_ecstypes.h @@ -3,16 +3,14 @@ #include "ecs2.h" #include "haloo3d/haloo3d.h" -// #include "haloo3d/haloo3dex_easy.h" +#include "haloo3d/haloo3dex_easy.h" + +#define TERRAIN_MAXPLAYERS 4 // Baseline render context. When a pointer to this is attached as a component, // it becomes a render target, and that entity will perform the precalcs // necessary for later object rendering. typedef struct { - // struct vec4 precalcs[H3D_OBJ_MAXVERTICES]; - // haloo3d_facef outfaces[H3D_FACEF_MAXCLIP]; - // haloo3d_perspective(render.perspective, fov, ASPECT, NEARCLIP, FARCLIP); - // mfloat_t precalc_perspective[MAT4_SIZE]; mfloat_t precalc_screen[MAT4_SIZE]; mfloat_t precalc_halfwidth; // Optimization for reducing calcs per tri mfloat_t precalc_halfheight; // Optimization for reducing calcs per tri @@ -46,12 +44,13 @@ typedef struct { // All values which allow rendering of a 3d object typedef struct { // haloo3d_trirender rendersettings; // baseline settings for THIS object. + render_context *context[TERRAIN_MAXPLAYERS]; // What to render into struct vec3 scale; // how big the thing should be in world object_lighting *lighting; // a pointer to lighting, null for none - render_context *context; // What to render into haloo3d_obj *model; haloo3d_fb *texture; uint8_t cullbackface; // Whether to cull backfaces (you probably should) + uint8_t contextcount; // How many contexts we render into } ecs_object; // Some placement within the world. Doesn't imply anything other than a @@ -81,8 +80,21 @@ typedef struct { int numevents; } ecs_input; -// typedef haloo3d_camera *ecs_camera; -// typedef haloo3d_obj_instance *ecs_object; +// Simple component for some entity that should clean itself up +// when there are no more "references" to it. Whatever that means... +// some fields are for special cleanup +typedef struct { + char dynmodel[8]; // A model we may have to cleanup +} ecs_playergarbage; + +// Represents the singular object that is the entire stationary +// object of terrain. The position is the "chunk position", which +// should be integer aligned. Not necessarily 1:1 with world +// coordinates? +typedef struct { + struct vec2i pos; + // uint8_t generation; // The type(?) of generation (idk honestly) +} ecs_chunk; // // A billboard for OUR system, which does not look up or down at the target. // As @@ -94,29 +106,28 @@ typedef struct { // struct vec3 *lookat; // } ecs_billboard; -// // A component which allows an object instance to die -// // when the maze is initiailized. -// typedef struct { -// haloo3d_obj_instance *obj; -// haloo3d_easyrender *render; -// worldstate *ws; -// void (*diefunc)(haloo3d_obj_instance *); -// } ecs_dieoninit; - // Setup ECS system for our game ECS_START(tecs) -float delta_s; // Store delta time in ecs -int totaldrawn; // A place to store total drawn tris +float delta_s; // Store delta time in ecs +int totaldrawn; // A place to store total drawn tris +struct vec3 globallighting; // the global lighting to apply to terrain +object_lighting chunklight; // lighting to assign to a chunk +// Everyone needs to be able to get and set obj/texture +haloo3d_easystore storage; ECS_COMPONENT(ecs_rendercontext); ECS_COMPONENT(ecs_object); ECS_COMPONENT(ecs_placement); ECS_COMPONENT(ecs_rotation); ECS_COMPONENT(ecs_movement); ECS_COMPONENT(ecs_input); +ECS_COMPONENT(ecs_playergarbage); +ECS_COMPONENT(ecs_chunk); ECS_END(tecs) ECS_FN_INIT(tecs) ECS_FN_NEWENTITY(tecs) +ECS_FN_DELETEENTITY(tecs) +ECS_FN_EID(tecs) // And then a copy of the components here... that sucksssss ECS_CID(ecs_rendercontext, 0); @@ -125,5 +136,7 @@ ECS_CID(ecs_placement, 2); ECS_CID(ecs_rotation, 3); ECS_CID(ecs_movement, 4); ECS_CID(ecs_input, 5); +ECS_CID(ecs_playergarbage, 6); +ECS_CID(ecs_chunk, 7); #endif