From c65787ebfc5f0701bb4366ef22cddc8af2d243ee Mon Sep 17 00:00:00 2001 From: nathan Date: Fri, 25 Jul 2025 01:57:49 -0600 Subject: More tree things --- assets/tree.png | Bin 208938 -> 208723 bytes src/assets.c | 2 +- src/entity.c | 33 +++++++++++++++++---- src/entity.h | 8 ++++-- src/player.c | 26 ++++++++++------- src/world.c | 88 +++++++++++++++++++++++++++++++++++++++----------------- src/world.h | 6 ++-- 7 files changed, 115 insertions(+), 48 deletions(-) diff --git a/assets/tree.png b/assets/tree.png index 5c41e69..af9a24b 100644 Binary files a/assets/tree.png and b/assets/tree.png differ diff --git a/src/assets.c b/src/assets.c index 604b622..6f2ac0c 100644 --- a/src/assets.c +++ b/src/assets.c @@ -17,7 +17,7 @@ void initAssets(Assets* assets) void closeAssets(Assets* assets) { - for (int index = 0; index < TEXTURE_ASSET_COUNT; ++index) + for (int index = 0; index < TEXTURE_ASSET_COUNT; ++index) { UnloadTexture(assets->textures[index]); } diff --git a/src/entity.c b/src/entity.c index d5a0bab..25136c2 100644 --- a/src/entity.c +++ b/src/entity.c @@ -7,13 +7,32 @@ Entity createEntity(EntityId id, Vector3 position) Entity entity; entity.id = id; - // Test box. - float boxSize = 0.4; - entity.box.min = (Vector3){-boxSize, -boxSize, -boxSize}; - entity.box.max = (Vector3){boxSize, boxSize, boxSize}; + switch (id) + { + case OLD_MINT: + case STICKY_NICKEL: + entity.box = (BoundingBox){ + .min = (Vector3){-0.4, -0.4, -0.4}, + .max = (Vector3){0.4, 0.4, 0.4} + }; + + break; + case TREE: + + { + Vector2 size = (Vector2){225.0 / 500.0 * TREE_SCALE, TREE_SCALE}; + size = Vector2Scale(size, 0.5); + + entity.box = (BoundingBox){ + .min = (Vector3){-size.x, -size.y, -size.x}, + .max = (Vector3){size.x, size.y, size.x} + }; + } + + break; + } setEntityPosition(&entity, position); - return entity; } @@ -29,6 +48,10 @@ void updateEntity(Entity* entity, Game* game) DrawBillboard(game->player.camera, game->assets.textures[NICKEL_TEXTURE], entity->position, 1.0, WHITE); break; + case TREE: + DrawBillboard(game->player.camera, game->assets.textures[TREE_TEXTURE], + entity->position, TREE_SCALE, WHITE); + break; default: break; } diff --git a/src/entity.h b/src/entity.h index 11dbde9..38f4092 100644 --- a/src/entity.h +++ b/src/entity.h @@ -7,12 +7,16 @@ typedef int8_t EntityId; -#define ENTITY_COUNT 2 +#define ENTITY_COUNT 3 + +// Constants for entities. +#define TREE_SCALE 32.0 enum { ENTITY_NONE = -1, OLD_MINT, - STICKY_NICKEL + STICKY_NICKEL, + TREE }; typedef struct { diff --git a/src/player.c b/src/player.c index bb63903..136a006 100644 --- a/src/player.c +++ b/src/player.c @@ -83,18 +83,22 @@ void updatePlayer(Player* player, Game* game) camera->position = player->position; camera->target = Vector3Add(player->position, player->direction); - /* Ray ray = (Ray){ */ - /* .position = player->position, */ - /* .direction = player->direction */ - /* }; */ +#ifdef FT_DEBUG_MODE + Ray ray = (Ray){ + .position = player->position, + .direction = player->direction + }; + + DrawRay(ray, YELLOW); - /* int tests; */ - /* WorldUID uid = castRayAtWorld(&game->world, ray, &tests); */ + int tests; + WorldUID uid = castRayAtWorld(&game->world, ray, &tests); - /* printf("%d\n", tests); */ + printf("%d\n", tests); - /* if (uid != -1) */ - /* { */ - /* DrawBoundingBox(game->world.entities[uid].box, RED); */ - /* } */ + if (uid != -1) + { + DrawBoundingBox(game->world.entities[uid].box, RED); + } +#endif } diff --git a/src/world.c b/src/world.c index 52b91b1..17269ec 100644 --- a/src/world.c +++ b/src/world.c @@ -328,7 +328,46 @@ void buildWorldBVH(World* world) world->bvhDebugSelect = 0; } -World createWorld(int seed) +Seed generateWorldTrees(World* world, Seed seed) +{ + for (int index = 0; index < WORLD_TREE_COUNT; ++index) + { + Vector3 position; + position.x = FT_RANDOM16(seed) % (int)world->size.x; + position.z = FT_RANDOM16(seed) % (int)world->size.z; + position.y = getWorldHeightAtLocation( + world, + position.x, position.z) + (TREE_SCALE / 2.0); + Entity entity = createEntity(TREE, position); + + world->entities[index] = entity; + } + + return seed; +} + +Seed generateWorldItems(World* world, Seed seed) +{ + for (int index = WORLD_TREE_COUNT; index < WORLD_ENTITY_MAX; ++index) + { + FT_RANDOM16(seed); + + Vector3 position; + position.x = FT_RANDOM16(seed) % (int)world->size.x; + position.z = FT_RANDOM16(seed) % (int)world->size.z; + position.y = getWorldHeightAtLocation(world, + position.x, position.z) + 1.0; + EntityId items[] = {OLD_MINT, STICKY_NICKEL}; + size_t itemsSize = 2; + Entity entity = createEntity(items[seed % itemsSize], position); + + world->entities[index] = entity; + } + + return seed; +} + +World createWorld(Seed seed) { World world; world.size = WORLD_SIZE; @@ -348,21 +387,8 @@ World createWorld(int seed) UnloadImage(image); - // Entities. - for (int index = 0; index < WORLD_ENTITY_MAX; ++index) - { - FT_RANDOM16(seed); - - Entity entity = createEntity(seed % ENTITY_COUNT, Vector3Zero()); - Vector3 position; - position.x = FT_RANDOM16(seed) % (int)world.size.x; - position.z = FT_RANDOM16(seed) % (int)world.size.z; - position.y = getWorldHeightAtLocation(&world, - position.x, position.z) + 1.0; - setEntityPosition(&entity, position); - - world.entities[index] = entity; - } + seed = generateWorldTrees(&world, seed); + seed = generateWorldItems(&world, seed); double currentTime = GetTime(); buildWorldBVH(&world); @@ -489,11 +515,12 @@ float getWorldHeightAtLocation(const World* world, float x, float y) return 0.0; } -WorldUID castRayBVH(const World* world, BVHNode node, Ray ray, int* tests) +void castRayBVH(const World* world, BVHNode node, Ray ray, int* tests, + WorldUID* closest, float* closestDistance) { if (!GetRayCollisionBox(ray, node.box).hit) { - return -1; + return; } if (tests != NULL) @@ -511,7 +538,15 @@ WorldUID castRayBVH(const World* world, BVHNode node, Ray ray, int* tests) ray, world->entities[node.entities[index]].box).hit) { - return node.entities[index]; + float distance = Vector3Distance( + world->entities[node.entities[index]].position, + ray.position); + + if (distance < *closestDistance) + { + *closest = node.entities[index]; + *closestDistance = distance; + } } } } @@ -519,21 +554,20 @@ WorldUID castRayBVH(const World* world, BVHNode node, Ray ray, int* tests) { for (int index = 0; index < node.branchCount; ++index) { - WorldUID uid = castRayBVH(world, *node.branches[index], ray, tests); - - if (uid != -1) - { - return uid; - } + castRayBVH(world, *node.branches[index], ray, tests, closest, + closestDistance); } } - return -1; + return; } WorldUID castRayAtWorld(const World* world, Ray ray, int* tests) { - return castRayBVH(world, world->bvh, ray, tests); + WorldUID uid = -1; + float distance = Vector3LengthSqr(world->size); + castRayBVH(world, world->bvh, ray, tests, &uid, &distance); + return uid; } // Abortions are good. Get more abortions. diff --git a/src/world.h b/src/world.h index 3c18e9f..c255e17 100644 --- a/src/world.h +++ b/src/world.h @@ -9,14 +9,16 @@ #define BVH_MAX_BRANCH_COUNT 8 #define BVH_BOX_MAX 100.0 -#define WORLD_ENTITY_MAX 1000 +#define WORLD_ENTITY_MAX 1500 #define WORLD_SIZE (Vector3){1000.0, 100.0, 1000.0} #define WORLD_IMAGE_WIDTH 100 #define WORLD_IMAGE_HEIGHT 100 #define WORLD_IMAGE_SCALE 5.0 +#define WORLD_TREE_COUNT 500 // UID for anything in the world. typedef int16_t WorldUID; +typedef int Seed; typedef struct BVHNode { BoundingBox box; @@ -36,7 +38,7 @@ typedef struct { int bvhDebugSelect; } World; -World createWorld(int seed); +World createWorld(Seed seed); void updateWorld(World* world, Game* game); void freeWorld(World world); // Dam, I wanta live in a free world ): -- cgit v1.2.3