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,66 @@
#include "private_block.h"
#include "texture_atlas_mapper.h"
/**
* The global registry of block properties and rendering data.
* * This array serves as the "Source of Truth" for every block type in the game.
* It defines the physical properties (transparency), the vertex colors,
* and the specific texture indices for each of the six cube faces.
* * The array is indexed using the 'block_id_struct' enum values to ensure
* O(1) look-up time for block data during mesh generation and lighting.
*/
const block_render_data_struct _block_library[] =
{
[block_air] = {
.color = { 0, 0, 0, 0 },
.is_transparent = true,
.texture = {
.top = 0, .bottom = 0,
.front = 0, .back = 0,
.left = 0, .right = 0
}
},
[block_dirt] = {
.color = { 255, 255, 255, 255 },
.is_transparent = false,
.texture = {
.top = dirt_texture, .bottom = dirt_texture,
.front = dirt_texture, .back = dirt_texture,
.left = dirt_texture, .right = dirt_texture
}
},
[block_grass] = {
.color = { 255, 255, 255, 255 },
.is_transparent = false,
.texture = {
.top = grass_top_texture, .bottom = dirt_texture,
.front = grass_side_texture, .back = grass_side_texture,
.left = grass_side_texture, .right = grass_side_texture
}
},
[block_stone] = {
.color = { 255, 255, 255, 255 },
.is_transparent = false,
.texture = {
.top = stone_texture, .bottom = stone_texture,
.front = stone_texture, .back = stone_texture,
.left = stone_texture, .right = stone_texture
}
},
[block_wood] = {
.color = { 255, 255, 255, 255 },
.is_transparent = false,
.texture = {
.top = wood_texture, .bottom = wood_texture,
.front = wood_texture, .back = wood_texture,
.left = wood_texture, .right = wood_texture
}
}
};

View File

@@ -0,0 +1,8 @@
#ifndef private_block_h
#define private_block_h
#include "block.h"
extern const block_render_data_struct _block_library[];
#endif

View File

@@ -0,0 +1,94 @@
#include "block.h"
#include "_internal/private_block.h"
#include "texture_atlas_mapper.h"
/**
* Retrieves the rendering data and metadata for a specific block identifier.
* * This function acts as a safe accessor for the global block library. It
* performs bounds checking on the provided identifier to ensure it exists
* within the library's memory range. If the identifier is invalid or
* out of bounds, it returns the data for 'block_air' as a safe default
* to prevent segmentation faults or undefined rendering behavior.
* * @param id_to_look_up The unique identifier of the block to retrieve.
* @return The rendering data structure corresponding to the block identifier.
*/
block_render_data_struct get_block_data(block_id_struct id_to_look_up)
{
if (id_to_look_up < 0 ||
id_to_look_up >= block_type_count)
{
return _block_library[block_air];
}
return _block_library[id_to_look_up];
}
/**
* Calculates the texture coordinates (UVs) for a specific face of a block.
* This function maps a block's texture index to a 2D position within a 16x16
* texture atlas and handles the V-axis inversion required for OpenGL.
*/
void get_block_face_texture_coordinates(block_id_struct block_id,
int32_t face_direction,
float texture_coordinates[4][2])
{
const int32_t texture_atlas_size = 16;
int32_t texture_index = 0;
/* Retrieve the specific texture index for the requested face */
switch (face_direction)
{
case face_top:
texture_index = get_block_data(block_id).texture.top;
break;
case face_bottom:
texture_index = get_block_data(block_id).texture.bottom;
break;
case face_front:
texture_index = get_block_data(block_id).texture.front;
break;
case face_back:
texture_index = get_block_data(block_id).texture.back;
break;
case face_left:
texture_index = get_block_data(block_id).texture.left;
break;
case face_right:
texture_index = get_block_data(block_id).texture.right;
break;
}
/* Determine the grid position within the atlas */
const int32_t atlas_column = texture_index % texture_atlas_size;
const int32_t atlas_row = texture_index / texture_atlas_size;
/* Calculate the normalized coordinate steps */
const float coordinate_step = 1.0f / (float)texture_atlas_size;
const float horizontal_start = (float)atlas_column * coordinate_step;
const float vertical_start = (float)atlas_row * coordinate_step;
/* Invert the vertical axis to align with OpenGL's bottom-left origin */
const float vertical_minimum = 1.0f - (vertical_start + coordinate_step);
const float vertical_maximum = 1.0f - vertical_start;
const float horizontal_end = horizontal_start + coordinate_step;
/* Assign coordinates to the four vertices of the face quad */
// Top-Left vertex
texture_coordinates[0][0] = horizontal_start;
texture_coordinates[0][1] = vertical_maximum;
// Top-Right vertex
texture_coordinates[1][0] = horizontal_end;
texture_coordinates[1][1] = vertical_maximum;
// Bottom-Right vertex
texture_coordinates[2][0] = horizontal_end;
texture_coordinates[2][1] = vertical_minimum;
// Bottom-Left vertex
texture_coordinates[3][0] = horizontal_start;
texture_coordinates[3][1] = vertical_minimum;
}

View File

@@ -0,0 +1,51 @@
#ifndef block_h
#define block_h
#include <stdint.h>
#include <raylib.h>
typedef enum block_id_struct {
block_air = 0,
block_dirt = 1,
block_grass = 2,
block_stone = 3,
block_wood = 4,
block_type_count
} block_id_struct;
typedef struct block_render_data_struct {
struct Color color;
bool is_transparent;
struct {
uint8_t top;
uint8_t bottom;
uint8_t front;
uint8_t back;
uint8_t left;
uint8_t right;
} texture;
} block_render_data_struct;
/**
* Retrieves the rendering data and metadata for a specific block identifier.
* * This function acts as a safe accessor for the global block library. It
* performs bounds checking on the provided identifier to ensure it exists
* within the library's memory range. If the identifier is invalid or
* out of bounds, it returns the data for 'block_air' as a safe default
* to prevent segmentation faults or undefined rendering behavior.
* * @param id_to_look_up The unique identifier of the block to retrieve.
* @return The rendering data structure corresponding to the block identifier.
*/
block_render_data_struct get_block_data(block_id_struct id_to_look_up);
/**
* Calculates the texture coordinates (UVs) for a specific face of a block.
* This function maps a block's texture index to a 2D position within a 16x16
* texture atlas and handles the V-axis inversion required for OpenGL.
*/
void get_block_face_texture_coordinates(block_id_struct block_id,
int32_t face_direction,
float texture_coordinates[4][2]);
#endif

View File

@@ -0,0 +1,120 @@
#include "test_block.h"
#include "../block.h"
#include "texture_atlas_mapper.h"
#include "unity.h"
void test_get_block_data_bounds_checking(void)
{
// Test way too high
block_render_data_struct data = get_block_data(999);
TEST_ASSERT_TRUE(data.is_transparent);
TEST_ASSERT_EQUAL_INT(0, data.texture.top);
// Test negative
data = get_block_data(-1);
TEST_ASSERT_TRUE(data.is_transparent);
}
/* Verify that Grass has different textures for top and bottom */
void test_grass_block_texture_indices(void)
{
block_render_data_struct grass = get_block_data(block_grass);
// Assert that the top is grass, but the bottom is dirt
TEST_ASSERT_EQUAL_INT(grass_top_texture, grass.texture.top);
TEST_ASSERT_EQUAL_INT(dirt_texture, grass.texture.bottom);
TEST_ASSERT_EQUAL_INT(grass_side_texture, grass.texture.front);
}
void test_get_block_face_texture_coordinates_math(void)
{
float uvs[4][2];
// Let's test Dirt.
// If dirt_texture is index 2 in your texture_atlas_mapper.h:
// atlas_column = 2 % 16 = 2
// horizontal_start = 2 * (1.0/16.0) = 0.125
get_block_face_texture_coordinates(block_dirt, face_front, uvs);
float expected_start_x = (float)(dirt_texture % 16) * (1.0f / 16.0f);
// Top-Left X should be the start of the tile
TEST_ASSERT_FLOAT_WITHIN(0.0001f, expected_start_x, uvs[0][0]);
// Top-Right X should be start + 1/16th
TEST_ASSERT_FLOAT_WITHIN(0.0001f, expected_start_x + 0.0625f, uvs[1][0]);
}
void test_block_library_integrity(void)
{
for (int i = 0; i < block_type_count; i++)
{
block_render_data_struct data = get_block_data(i);
if (i == block_air)
{
TEST_ASSERT_TRUE_MESSAGE(data.is_transparent,
"Air must be transparent");
continue;
}
// Ensure solid blocks have full opacity
if (!data.is_transparent)
{
TEST_ASSERT_EQUAL_UINT8_MESSAGE(255, data.color.a,
"Solid block has invalid alpha");
}
// Ensure texture indices are within a reasonable range (e.g., 256 for a 16x16 atlas)
TEST_ASSERT_LESS_THAN_INT_MESSAGE(256, data.texture.top,
"Texture index out of atlas range");
}
}
void test_get_block_face_uv_winding_and_size(void)
{
float uvs[4][2];
get_block_face_texture_coordinates(block_dirt, face_front, uvs);
// Verify the width of the UV quad is exactly 1/16th (0.0625)
float width = uvs[1][0] - uvs[0][0]; // TopRight.x - TopLeft.x
TEST_ASSERT_FLOAT_WITHIN(0.0001f, 0.0625f, width);
// Verify the height of the UV quad is exactly 1/16th
// Note: vertical_maximum - vertical_minimum
float height = uvs[0][1] - uvs[3][1]; // TopLeft.y - BottomLeft.y
TEST_ASSERT_FLOAT_WITHIN(0.0001f, 0.0625f, height);
// Verify Winding: Top should be Y-greater than Bottom
TEST_ASSERT_MESSAGE(uvs[0][1] > uvs[3][1], "UV mapping is upside down!");
// Verify Winding: Right should be X-greater than Left
TEST_ASSERT_MESSAGE(uvs[1][0] > uvs[0][0], "UV mapping is mirrored horizontally!");
}
void test_stone_faces_are_consistent(void)
{
float top_uvs[4][2];
float front_uvs[4][2];
get_block_face_texture_coordinates(block_stone, face_top, top_uvs);
get_block_face_texture_coordinates(block_stone, face_front, front_uvs);
for(int i = 0; i < 4; i++)
{
TEST_ASSERT_EQUAL_FLOAT(top_uvs[i][0], front_uvs[i][0]);
TEST_ASSERT_EQUAL_FLOAT(top_uvs[i][1], front_uvs[i][1]);
}
}
void run_block_tests(void)
{
RUN_TEST(test_get_block_data_bounds_checking);
RUN_TEST(test_grass_block_texture_indices);
RUN_TEST(test_get_block_face_texture_coordinates_math);
RUN_TEST(test_block_library_integrity);
RUN_TEST(test_get_block_face_uv_winding_and_size);
RUN_TEST(test_stone_faces_are_consistent);
}

View File

@@ -0,0 +1,18 @@
#ifndef test_block_h
#define test_block_h
void test_get_block_data_bounds_checking(void);
void test_grass_block_texture_indices(void);
void test_get_block_face_texture_coordinates_math(void);
void test_block_library_integrity(void);
void test_get_block_face_uv_winding_and_size(void);
void test_stone_faces_are_consistent(void);
void run_block_tests(void);
#endif