From 1db028c814dd13a85d3287b622b3d48fffd9a5c2 Mon Sep 17 00:00:00 2001 From: Carlos Sanchez Date: Fri, 20 Sep 2024 23:37:58 -0400 Subject: [PATCH] Clouds! --- commonobj.c | 83 +++++++++++++++++++++++++++-------------------- terrain.c | 93 ++++++++++++++++++++++++++++++++--------------------- 2 files changed, 106 insertions(+), 70 deletions(-) diff --git a/commonobj.c b/commonobj.c index 350058d..81d15e4 100644 --- a/commonobj.c +++ b/commonobj.c @@ -18,6 +18,10 @@ #define TREETRUNKWIDTH 0.2 #endif +#define COMVERT(m, _x, _y, _z) \ + haloo3d_obj_addvertex(m, (struct vec4){.x = _x, .y = _y, .z = _z, .w = 1}) +#define COMCOL(m, col) haloo3d_obj_addvtexture(m, haloo3d_gen_paletteuv(col)) + // Fill a face with a solid color given by the tex void fastface(haloo3d_facei face, uint16_t tex, uint16_t v0, uint16_t v1, uint16_t v2) { @@ -29,42 +33,53 @@ void fastface(haloo3d_facei face, uint16_t tex, uint16_t v0, uint16_t v1, face[2].posi = v2; } +static inline uint16_t fastface2(haloo3d_obj *model, uint16_t tex, uint16_t v0, + uint16_t v1, uint16_t v2) { + haloo3d_facei face; + fastface(face, tex, v0, v1, v2); + return haloo3d_obj_addface(model, face); +} + // Generate a basic tree model void gen_tree_model(haloo3d_obj *tree) { haloo3d_obj_resetfixed(tree, 12, 24); - struct vec3 treecol = haloo3d_gen_paletteuv(TREECOL); - int treeuv = haloo3d_obj_addvtexture(tree, treecol); - struct vec3 trunkcol = haloo3d_gen_paletteuv(TREETRUNKCOL); - int trunkuv = haloo3d_obj_addvtexture(tree, trunkcol); - // clang-format off - uint16_t top = haloo3d_obj_addvertex(tree, - (struct vec4){.x = 0, .y = 1, .z = 0, .w = 1}); - uint16_t tree1 = haloo3d_obj_addvertex(tree, - (struct vec4){.x = -TREETOPWIDTH, .y = TREEBOTTOM, .z = -TREETOPWIDTH, .w = 1}); - uint16_t tree2 = haloo3d_obj_addvertex(tree, - (struct vec4){.x = TREETOPWIDTH, .y = TREEBOTTOM, .z = -TREETOPWIDTH, .w = 1}); - uint16_t tree3 = haloo3d_obj_addvertex(tree, - (struct vec4){.x = 0, .y = TREEBOTTOM, .z = TREETOPWIDTH, .w = 1}); - uint16_t trunk1 = haloo3d_obj_addvertex(tree, - (struct vec4){ .x = -TREETRUNKWIDTH, .y = -1, .z = -TREETRUNKWIDTH, .w = 1}); - uint16_t trunk2 = haloo3d_obj_addvertex(tree, - (struct vec4){ .x = TREETRUNKWIDTH, .y = -1, .z = -TREETRUNKWIDTH, .w = 1}); - uint16_t trunk3 = haloo3d_obj_addvertex(tree, - (struct vec4){.x = 0, .y = -1, .z = TREETRUNKWIDTH, .w = 1}); - // clang-format on - - haloo3d_facei face; - fastface(face, treeuv, top, tree1, tree3); - haloo3d_obj_addface(tree, face); - fastface(face, treeuv, top, tree3, tree2); - haloo3d_obj_addface(tree, face); - fastface(face, treeuv, top, tree2, tree1); - haloo3d_obj_addface(tree, face); - fastface(face, trunkuv, top, trunk1, trunk3); - haloo3d_obj_addface(tree, face); - fastface(face, trunkuv, top, trunk3, trunk2); - haloo3d_obj_addface(tree, face); - fastface(face, trunkuv, top, trunk2, trunk1); - haloo3d_obj_addface(tree, face); + int treeuv = COMCOL(tree, TREECOL); + int trunkuv = COMCOL(tree, TREETRUNKCOL); + uint16_t top = COMVERT(tree, 0, 1, 0); + uint16_t tree1 = COMVERT(tree, -TREETOPWIDTH, TREEBOTTOM, -TREETOPWIDTH); + uint16_t tree2 = COMVERT(tree, TREETOPWIDTH, TREEBOTTOM, -TREETOPWIDTH); + uint16_t tree3 = COMVERT(tree, 0, TREEBOTTOM, TREETOPWIDTH); + uint16_t trunk1 = COMVERT(tree, -TREETRUNKWIDTH, -1, -TREETRUNKWIDTH); + uint16_t trunk2 = COMVERT(tree, TREETRUNKWIDTH, -1, -TREETRUNKWIDTH); + uint16_t trunk3 = COMVERT(tree, 0, -1, TREETRUNKWIDTH); + fastface2(tree, treeuv, top, tree1, tree3); + fastface2(tree, treeuv, top, tree3, tree2); + fastface2(tree, treeuv, top, tree2, tree1); + fastface2(tree, trunkuv, top, trunk1, trunk3); + fastface2(tree, trunkuv, top, trunk3, trunk2); + fastface2(tree, trunkuv, top, trunk2, trunk1); haloo3d_obj_shrinktofit(tree); } + +void gen_circle_model(haloo3d_obj *model, uint16_t color, int vertices) { + haloo3d_obj_resetfixed(model, vertices, vertices + 1); + int circleuv = COMCOL(model, color); + // Add the center + uint16_t middle = COMVERT(model, 0, 0, 0); + // Go in a circle of course + float angle = 0; + float angle_inc = MPI * 2 / vertices; + uint16_t lastv = 0; + uint16_t firstv = 0; + for (int i = 0; i < vertices; i++) { + uint16_t thisv = COMVERT(model, cos(angle), sin(angle), 0); + if (i == 0) { + firstv = thisv; + } else { + fastface2(model, circleuv, middle, lastv, thisv); + } + angle += angle_inc; + lastv = thisv; + } + fastface2(model, circleuv, middle, lastv, firstv); +} diff --git a/terrain.c b/terrain.c index 6c6800d..a506772 100644 --- a/terrain.c +++ b/terrain.c @@ -39,20 +39,29 @@ #define MAXCHUNKPERFRAME PLBOXEDGE // Generation consts / things for looks +#define LANDHEIGHT 4.0 #define LANDCOL 0xF6D2 // 0xF4E1 #define SEACOL 0xF28D // 0xF26C -#define LANDHEIGHT 4.0 -#define SKYCOL 0xF97F // 0xF77F +#define SKYCOL 0xF97F // 0xF77F +#define CLOUDCOL 0xFFFF #define TREECOL 0xF070 #define TREETRUNKCOL 0xF950 #define TREEBOTTOM -0.333 #define TREETRUNKWIDTH 0.2 #define SEATRANS 0.75 +#define CLOUDTRANSMIN 0.1 +#define CLOUDTRANSMAX 0.2 +#define CLOUDHEIGHT 2 +#define CLOUDSTRETCH 2 +#define CLOUDCHANCE 0.1 #define INIT_LIGHTPITCH MPI_2 * 1.65 #define INIT_LIGHTYAW MPI_2 * 0.65 #define INIT_MINLIGHT 0.2 #define INIT_DITHERSTART 3.5 #define INIT_DITHEREND VIEWDISTANCE - 0.5 +#define MAXTREEPERCELL 9 +#define MAXTREEACROSS 3 +#define MAXTREECLOSENESS 0.2 // Player things #define INIT_FOV 90.0 @@ -68,6 +77,7 @@ int fps = 60; #define PALETTEKEY "palette" #define TREEKEY "tree" +#define CLOUDKEY "cloud" #include "commonobj.c" @@ -78,8 +88,9 @@ void gen_terrain(struct vec3i pos, haloo3d_obj *model, eprintf("Generating terrain at %d,%d\n", pos.x, pos.z); haloo3d_obj *tree = haloo3d_easystore_getobj(storage, TREEKEY); // Don't allow the model to have more than some amount of faces/vertices. - haloo3d_obj_resetfixed(model, CHUNKVSIZE * CHUNKVSIZE * 16, - CHUNKVSIZE * CHUNKVSIZE * 16); + haloo3d_obj_resetfixed(model, H3D_OBJ_MAXFACES, H3D_OBJ_MAXVERTICES); + // CHUNKVSIZE * CHUNKVSIZE * 32, + // CHUNKVSIZE * CHUNKVSIZE * 32); // if (rand() & 3) return; struct vec3 landcol = haloo3d_gen_paletteuv(LANDCOL); // 0xF2C0); int landuv = haloo3d_obj_addvtexture(model, landcol); @@ -122,30 +133,39 @@ void gen_terrain(struct vec3i pos, haloo3d_obj *model, triedge[t][v].z = model->vertices[model->faces[faces[t]][v].posi].y; } } + // Change frequency for trees + // ns.seed = 0; + ns.frequency = 0.02; + ns.fractal_type = FNL_FRACTAL_NONE; // Generate up to 4 trees per cell (usually not) - for (int t = 0; t < 4; t++) { + for (int t = 0; t < MAXTREEPERCELL; t++) { // We know that the first vec in the first triangle is bl, which is our // base to start generating trees struct vec2 treepos = { - .x = triedge[0][0].x + 0.5 * (t & 1) + 0.3 * RANDF(), - .y = triedge[0][0].y - (0.5 * (t >> 1) + 0.3 * RANDF())}; + .x = triedge[0][0].x + + (1.0 / MAXTREEACROSS) * + ((t % MAXTREEACROSS) + (1.0 - MAXTREECLOSENESS) * RANDF()), + .y = triedge[0][0].y - + ((1.0 / MAXTREEACROSS) * ((int)(t / MAXTREEACROSS) + + (1.0 - MAXTREECLOSENESS) * RANDF()))}; mfloat_t we[3]; for (int i = 0; i < 2; i++) { we[0] = haloo3d_edgefunc(triedge[i][1].v, triedge[i][2].v, treepos.v); we[1] = haloo3d_edgefunc(triedge[i][2].v, triedge[i][0].v, treepos.v); we[2] = haloo3d_edgefunc(triedge[i][0].v, triedge[i][1].v, treepos.v); if (we[0] < 0 || we[1] < 0 || we[2] < 0) { - // eprintf("BAD: %f,%f, (%f, %f)\n", treepos.x, treepos.y, - // model->vertices[bl].x, model->vertices[bl].z); continue; } // We know this is the triangle to check. Let's figure out a y. // NOTE: WE SWTICH Y AND Z TO MAKE THE EDGE FUNCTION WORK float y = we[0] * triedge[i][0].z + we[1] * triedge[i][1].z + we[2] * triedge[i][2].z; - // eprintf("TREE Y: %f\n", y); - // For now, only generate trees if they're above a certain height - if (RANDF() < y) { + float pick = RANDF(); // pow(RANDF(), 2); + if (pick < y * + (1 + fnlGetNoise2D(&ns, noisex + treepos.x, + noisey + treepos.y)) * + 0.5) { + // y * (1 + fnlGetNoise2D(&ns, treepos.x, treepos.y)) * 0.5) { float scale = 0.1 + RANDF() * 0.05; float height = 0.5 + RANDF() * 0.5; haloo3d_obj_addobj( @@ -157,34 +177,30 @@ void gen_terrain(struct vec3i pos, haloo3d_obj *model, } } } - - // struct vec4 corn = model->vertices[bl]; - // if (corn.y > 0.1) { - // float scale = 0.1 + RANDF() * 0.05; - // float height = 0.5 + RANDF() * 0.5; - // // for (int b = 1; b <= 4; b++) { - // haloo3d_obj_addobj( - // model, tree, - // (struct vec3){.x = corn.x, .y = corn.y + scale * height, .z = - // corn.z}, (struct vec3)DEFAULTLOOK, (struct vec3)DEFAULTUP, (struct - // vec3){.x = scale, .y = scale * height, .z = scale}); - // //} - // // haloo3d_obj_addobj( - // // model, tree, - // // (struct vec3){ - // // .x = corn.x, .y = corn.y + scale * height * 2, .z = corn.z}, - // // (struct vec3)DEFAULTLOOK, (struct vec3)DEFAULTUP, - // // (struct vec3){.x = scale, .y = scale * height, .z = scale}); - // } } - // haloo3d_obj_addobj( - // model, tree, - // (struct vec3){.x = CHUNKSIZE / 2.0, .y = 1.0, .z = -CHUNKSIZE / 2.0}, - // (struct vec3)DEFAULTLOOK, (struct vec3)DEFAULTUP, - // (struct vec3){.x = 1.0, .y = 1.0, .z = 1.0}); haloo3d_obj_shrinktofit(model); } +void gen_cloud(render_context *ctx, tecs *ecs, struct vec3i pos) { + haloo3d_obj *cloud = haloo3d_easystore_getobj(&ecs->storage, CLOUDKEY); + ecs_eid cloudid = tecs_newentity(ecs, 0); + ECS_SETCOMPONENT(ecs, cloudid, ecs_playergarbage){}; + ECS_SETCOMPONENT(ecs, cloudid, ecs_placement){ + .up = DEFAULTUP, + .lookvec = DEFAULTLOOK, + .pos = { + .x = pos.x + RANDF(), .y = CLOUDHEIGHT + 0.0 * RANDF(), .z = pos.z}}; + ECS_SETCOMPONENT(ecs, cloudid, ecs_object){ + .flatdither = CLOUDTRANSMIN + (CLOUDTRANSMAX - CLOUDTRANSMIN) * RANDF(), + .texture = haloo3d_easystore_gettex(&ecs->storage, PALETTEKEY), + .scale = {.x = 1 + RANDF(), .y = 1.0 / CLOUDSTRETCH, .z = 1}, + .lighting = NULL, //&ecs->chunklight, + .model = cloud, + .cullbackface = 1, + .context = {ctx}, + .contextcount = 1}; +} + // Generate the entity/components/terrain for the chunk at the given // coordinates. // NOTE: chunks are per x/y tile (terrain inside is just scaled @@ -214,6 +230,9 @@ void gen_chunk(render_context *ctx, tecs *ecs, struct vec3i pos) { .cullbackface = 1, .context = {ctx}, .contextcount = 1}; + // Generate a cloud + if (RANDF() < CLOUDCHANCE) + gen_cloud(ctx, ecs, pos); } void player_chunkload(ecs_placement *ppos, render_context *ctx, tecs *ecs) { @@ -594,6 +613,8 @@ int main() { // int argc, char **argv) { haloo3d_gen_palettetex(palettetex); haloo3d_obj *treemodel = haloo3d_easystore_addobj(&ecs.storage, TREEKEY); gen_tree_model(treemodel); + haloo3d_obj *cloudmodel = haloo3d_easystore_addobj(&ecs.storage, CLOUDKEY); + gen_circle_model(cloudmodel, CLOUDCOL, 32); eprintf("Setup ECS system + obj/tex storage (%d bytes)\n", tecs_size);