transfered from codeberg

This commit is contained in:
2026-03-26 14:46:39 -05:00
parent 630f28bb7e
commit 5ed2173793
136 changed files with 14932 additions and 0 deletions

View File

@@ -0,0 +1,69 @@
#include "private_terrain.h"
#include "perlin.h"
#include <math.h>
#include <stdbool.h>
#define base_noise_scale 0.01f
#define detail_noise_scale 0.05f
#define base_noise_amplitude 12.0f
#define detail_noise_amplitude 4.0f
#define global_ground_level 0.0f
/**
* Calculates the noise-based height value for the terrain surface
* at the given global world coordinates.
*/
float _get_terrain_height_at_coordinates(int32_t world_coordinate_x,
int32_t world_coordinate_z)
{
float noise_input_x = (float)world_coordinate_x;
float noise_input_z = (float)world_coordinate_z;
float base_elevation = stb_perlin_noise3(noise_input_x * base_noise_scale,
0.0f,
noise_input_z * base_noise_scale,
0,
0,
0);
float detail_variation = stb_perlin_noise3(
noise_input_x * detail_noise_scale,
100.0f,
noise_input_z * detail_noise_scale,
0, 0, 0
);
float calculated_final_height =
base_elevation * base_noise_amplitude +
detail_variation * detail_noise_amplitude +
global_ground_level;
return floorf(calculated_final_height);
}
/**
* Determines if a specific 3D coordinate should be empty (air) based
* on 3D noise patterns to create subterranean cave systems.
*/
bool _is_cave_present_at_coordinates(int32_t world_coordinate_x,
int32_t world_coordinate_y,
int32_t world_coordinate_z,
int32_t surface_height_at_location)
{
if (world_coordinate_y >= surface_height_at_location + 5)
{
return false;
}
float cave_noise_scale = 0.06f;
float noise_density_value = stb_perlin_noise3(
(float)world_coordinate_x * cave_noise_scale,
(float)world_coordinate_y * cave_noise_scale,
(float)world_coordinate_z * cave_noise_scale,
0, 0, 0
);
return noise_density_value > 0.3f;
}

View File

@@ -0,0 +1,23 @@
#ifndef private_terrain_h
#define private_terrain_h
#include <stdbool.h>
#include <stdint.h>
/**
* Calculates the noise-based height value for the terrain surface
* at the given global world coordinates.
*/
float _get_terrain_height_at_coordinates(int32_t world_coordinate_x,
int32_t world_coordinate_z);
/**
* Determines if a specific 3D coordinate should be empty (air) based
* on 3D noise patterns to create subterranean cave systems.
*/
bool _is_cave_present_at_coordinates(int32_t world_coordinate_x,
int32_t world_coordinate_y,
int32_t world_coordinate_z,
int32_t surface_height_at_location);
#endif

View File

@@ -0,0 +1,67 @@
#include "terrain.h"
#include "_internal/private_terrain.h"
#include "block.h"
#include "chunk.h"
#include "raylib.h"
#include <math.h>
/**
* Iterates through every coordinate in a chunk, calculating terrain height
* and cave presence to populate the block data array.
*/
void generate_terrain(struct chunk_struct *chunk, struct chunk_position_struct* chunks_world_position)
{
// Align world position to integers once
int32_t base_x = chunks_world_position->x;
int32_t base_y = chunks_world_position->y;
int32_t base_z = chunks_world_position->z;
for (uint8_t x = 0; x < chunk_size; x++)
{
for (uint8_t z = 0; z < chunk_size; z++)
{
int32_t world_coordinate_x = base_x + x;
int32_t world_coordinate_z = base_z + z;
int32_t surface_height =
(int32_t)floorf(
_get_terrain_height_at_coordinates(
world_coordinate_x,
world_coordinate_z));
for (uint8_t y = 0; y < chunk_size; y++)
{
int32_t world_coordinate_y = base_y + y;
uint8_t resulting_block_id = block_air;
if (world_coordinate_y <= surface_height)
{
resulting_block_id = block_dirt;
if (world_coordinate_y < surface_height - 3)
{
resulting_block_id = block_stone;
}
if (world_coordinate_y > surface_height - 1)
{
resulting_block_id = block_grass;
}
if (_is_cave_present_at_coordinates(
world_coordinate_x,
world_coordinate_y,
world_coordinate_z,
surface_height))
{
resulting_block_id = block_air;
}
}
chunk->block_data[index_chunk(x, y, z)] = resulting_block_id;
}
}
}
}

View File

@@ -0,0 +1,16 @@
#ifndef terrain_h
#define terrain_h
struct chunk_struct;
struct chunk_position_struct;
#define grass_height -1
/**
* Iterates through every coordinate in a chunk, calculating terrain height
* and cave presence to populate the block data array.
*/
void generate_terrain(struct chunk_struct *chunk,
struct chunk_position_struct* chunks_world_position);
#endif

View File

@@ -0,0 +1,120 @@
#include "test_terrain.h"
#include "unity.h"
#include "../terrain.h"
#include "../_internal/private_terrain.h"
#include "block.h"
#include "chunk.h"
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//#define terrain_c_test_debug
/* Definition of the missing global the scheduler is looking for */
struct world_struct *world;
/* Checks to see if _get_terrain_hight_at_coordinates is consistant. */
void test_terrain_height_is_consistent(void)
{
float height_one = _get_terrain_height_at_coordinates(10, 10);
float height_two = _get_terrain_height_at_coordinates(10, 10);
TEST_ASSERT_EQUAL_FLOAT(height_one, height_two);
}
void test_cave_probability_at_high_altitude(void)
{
bool has_cave = _is_cave_present_at_coordinates(0, 100, 0, 10);
TEST_ASSERT_FALSE(has_cave);
}
/* Step 1: initialize a chunk with location 0, 0, 0.
* Step 2: run the terrain generator over the chunk.
* Step 3: verify that the surface of the chunk IS NOT made of air.
* Step 4: veridy that blocks 1 unit above the surface (within the same chunk) IS air.
* Step 5: clean up.
*/
void test_generate_terrain_fuzzer(void)
{
/* Step 1: Set up logging and randomness */
unsigned int seed = (unsigned int)time(NULL);
FILE *log = fopen("test_logs/last_test_random_vars.txt", "w");
fprintf(log, "Seed: %u\n", seed);
srand(seed);
for (int i = 0; i < 100; i++)
{
/* Step 2: Generate a random world position aligned to 16x grid */
// We multiply by 16 to ensure the chunk is grid-aligned
chunk_position_struct world_pos = {
.x = (rand() % 2000 - 1000) * chunk_size,
.y = (rand() % 10 - 5) * chunk_size, // Focus near sea level
.z = (rand() % 2000 - 1000) * chunk_size
};
fprintf(log, "Chunk %d: x:%" PRId32 " y:%" PRId32 " z:%" PRId32 "\n",
i,
(int32_t)world_pos.x,
(int32_t)world_pos.y,
(int32_t)world_pos.z);
struct chunk_struct *chunk = initialize_chunk(world_pos);
generate_terrain(chunk, &world_pos);
/* Step 3: Verify the internal data */
for (uint8_t x = 0; x < chunk_size; x++)
{
for (uint8_t z = 0; z < chunk_size; z++)
{
int32_t world_x = (int32_t)world_pos.x + x;
int32_t world_z = (int32_t)world_pos.z + z;
int32_t surface_y =
(int32_t)floorf(
_get_terrain_height_at_coordinates(world_x,
world_z));
// Convert world surface to local chunk space
int32_t local_y = surface_y - (int32_t)world_pos.y;
if (local_y >= 0 && local_y < chunk_size)
{
uint16_t block =
chunk->block_data[index_chunk(x, local_y, z)];
if (block == block_air)
{
bool is_cave =
_is_cave_present_at_coordinates
(world_x,
local_y + (int32_t)world_pos.y,
world_z,
surface_y
);
if (!is_cave)
{
fclose(log);
TEST_FAIL_MESSAGE("Found AIR at s"
"urface where no "
"cave exists!");
}
}
}
}
}
destroy_chunk(chunk);
}
fclose(log);
}
void run_terrain_tests(void)
{
RUN_TEST(test_terrain_height_is_consistent);
RUN_TEST(test_cave_probability_at_high_altitude);
RUN_TEST(test_generate_terrain_fuzzer);
}

View File

@@ -0,0 +1,13 @@
#ifndef test_terrain_h
#define test_terrain_h
void test_terrain_height_is_consistent(void);
void test_cave_probability_at_high_altitude(void);
void test_generate_terrain_fuzzer(void);
void run_terrain_tests(void);
#endif