250 lines
9.1 KiB
C
250 lines
9.1 KiB
C
#include "blocks.h"
|
|
#include "world.h"
|
|
#include "assets.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
bool tc_block_is_opaque_by_id(uint32_t id)
|
|
{
|
|
return !!(id & TC_BLOCK_OPAQUE_BIT);
|
|
}
|
|
|
|
uint32_t tc_count_vertices_of_block(tc_chunk_s *chunk, uint8_t x, uint8_t y, uint8_t z)
|
|
{
|
|
uint32_t num_vertices = 0;
|
|
|
|
uint32_t top_neighbour = 0;
|
|
uint32_t bottom_neighbour = 0;
|
|
uint32_t north_neighbour = 0;
|
|
uint32_t south_neighbour = 0;
|
|
uint32_t east_neighbour = 0;
|
|
uint32_t west_neighbour = 0;
|
|
|
|
if(x < 31) east_neighbour = chunk->blocks[x+1] [y] [z];
|
|
if(x > 0) west_neighbour = chunk->blocks[x-1] [y] [z];
|
|
if(y < 31) top_neighbour = chunk->blocks[x] [y+1] [z];
|
|
if(y > 0) bottom_neighbour = chunk->blocks[x] [y-1] [z];
|
|
if(z < 31) north_neighbour = chunk->blocks[x] [y] [z+1];
|
|
if(z > 0) south_neighbour = chunk->blocks[x] [y] [z-1];
|
|
|
|
if(!tc_block_is_opaque_by_id(top_neighbour)) num_vertices += 6;
|
|
if(!tc_block_is_opaque_by_id(bottom_neighbour)) num_vertices += 6;
|
|
if(!tc_block_is_opaque_by_id(north_neighbour)) num_vertices += 6;
|
|
if(!tc_block_is_opaque_by_id(south_neighbour)) num_vertices += 6;
|
|
if(!tc_block_is_opaque_by_id(east_neighbour)) num_vertices += 6;
|
|
if(!tc_block_is_opaque_by_id(west_neighbour)) num_vertices += 6;
|
|
|
|
return num_vertices;
|
|
}
|
|
|
|
uint32_t tc_count_chunk_vertices(tc_chunk_s *chunk)
|
|
{
|
|
uint32_t num_vertices = 0;
|
|
|
|
uint32_t x_in_chunk = 0;
|
|
uint32_t y_in_chunk = 0;
|
|
uint32_t z_in_chunk = 0;
|
|
while(x_in_chunk < 32)
|
|
{
|
|
y_in_chunk = 0;
|
|
while(y_in_chunk < 32)
|
|
{
|
|
z_in_chunk = 0;
|
|
while(z_in_chunk < 32)
|
|
{
|
|
if(chunk->blocks[x_in_chunk][y_in_chunk][z_in_chunk] != 0)
|
|
{
|
|
num_vertices += tc_count_vertices_of_block(chunk, x_in_chunk, y_in_chunk, z_in_chunk);
|
|
}
|
|
++z_in_chunk;
|
|
}
|
|
++y_in_chunk;
|
|
}
|
|
++x_in_chunk;
|
|
}
|
|
return num_vertices;
|
|
}
|
|
|
|
void printfloatarr(float *arr, uint32_t num)
|
|
{
|
|
for(int i = 0; i < num; ++i)
|
|
printf("%f ", arr[i]);
|
|
}
|
|
|
|
uint32_t tc_meshize_block(tc_chunk_s *chunk,
|
|
uint8_t x, uint8_t y, uint8_t z,
|
|
float *xyz, float *uv)
|
|
{
|
|
tc_block_entry_s *entry =
|
|
tc_resolve_id_to_block_entry(
|
|
chunk->blocks[x][y][z]
|
|
);
|
|
|
|
if(entry == NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
uint32_t num_vertices = 0;
|
|
|
|
uint32_t top_neighbour = 0;
|
|
uint32_t bottom_neighbour = 0;
|
|
uint32_t north_neighbour = 0;
|
|
uint32_t south_neighbour = 0;
|
|
uint32_t east_neighbour = 0;
|
|
uint32_t west_neighbour = 0;
|
|
|
|
if(x < 31) east_neighbour = chunk->blocks[x+1] [y] [z];
|
|
if(x > 0) west_neighbour = chunk->blocks[x-1] [y] [z];
|
|
if(y < 31) top_neighbour = chunk->blocks[x] [y+1] [z];
|
|
if(y > 0) bottom_neighbour = chunk->blocks[x] [y-1] [z];
|
|
if(z < 31) north_neighbour = chunk->blocks[x] [y] [z+1];
|
|
if(z > 0) south_neighbour = chunk->blocks[x] [y] [z-1];
|
|
|
|
if(!tc_block_is_opaque_by_id(top_neighbour))
|
|
{
|
|
tc_cube_side_mesh_s *side_mesh =
|
|
tc_block_resolve_name_to_attribute(entry, "top_mesh")->value.pointer;
|
|
|
|
memcpy(&xyz[num_vertices*3], side_mesh->xyz, sizeof(float) * side_mesh->num_vertices * 3);
|
|
memcpy(&uv[num_vertices*2], side_mesh->uv, sizeof(float) * side_mesh->num_vertices * 2);
|
|
num_vertices += side_mesh->num_vertices;
|
|
}
|
|
|
|
if(!tc_block_is_opaque_by_id(bottom_neighbour))
|
|
{
|
|
tc_cube_side_mesh_s *side_mesh =
|
|
tc_block_resolve_name_to_attribute(entry, "bottom_mesh")->value.pointer;
|
|
|
|
memcpy(&xyz[num_vertices*3], side_mesh->xyz, sizeof(float) * side_mesh->num_vertices * 3);
|
|
memcpy(&uv[num_vertices*2], side_mesh->uv, sizeof(float) * side_mesh->num_vertices * 2);
|
|
num_vertices += side_mesh->num_vertices;
|
|
}
|
|
|
|
if(!tc_block_is_opaque_by_id(south_neighbour))
|
|
{
|
|
tc_cube_side_mesh_s *side_mesh =
|
|
tc_block_resolve_name_to_attribute(entry, "south_mesh")->value.pointer;
|
|
|
|
memcpy(&xyz[num_vertices*3], side_mesh->xyz, sizeof(float) * side_mesh->num_vertices * 3);
|
|
memcpy(&uv[num_vertices*2], side_mesh->uv, sizeof(float) * side_mesh->num_vertices * 2);
|
|
num_vertices += side_mesh->num_vertices;
|
|
}
|
|
|
|
if(!tc_block_is_opaque_by_id(north_neighbour))
|
|
{
|
|
tc_cube_side_mesh_s *side_mesh =
|
|
tc_block_resolve_name_to_attribute(entry, "north_mesh")->value.pointer;
|
|
|
|
memcpy(&xyz[num_vertices*3], side_mesh->xyz, sizeof(float) * side_mesh->num_vertices * 3);
|
|
memcpy(&uv[num_vertices*2], side_mesh->uv, sizeof(float) * side_mesh->num_vertices * 2);
|
|
num_vertices += side_mesh->num_vertices;
|
|
}
|
|
|
|
if(!tc_block_is_opaque_by_id(east_neighbour))
|
|
{
|
|
tc_cube_side_mesh_s *side_mesh =
|
|
tc_block_resolve_name_to_attribute(entry, "east_mesh")->value.pointer;
|
|
|
|
memcpy(&xyz[num_vertices*3], side_mesh->xyz, sizeof(float) * side_mesh->num_vertices * 3);
|
|
memcpy(&uv[num_vertices*2], side_mesh->uv, sizeof(float) * side_mesh->num_vertices * 2);
|
|
num_vertices += side_mesh->num_vertices;
|
|
}
|
|
|
|
if(!tc_block_is_opaque_by_id(west_neighbour))
|
|
{
|
|
tc_cube_side_mesh_s *side_mesh =
|
|
tc_block_resolve_name_to_attribute(entry, "west_mesh")->value.pointer;
|
|
|
|
memcpy(&xyz[num_vertices*3], side_mesh->xyz, sizeof(float) * side_mesh->num_vertices * 3);
|
|
memcpy(&uv[num_vertices*2], side_mesh->uv, sizeof(float) * side_mesh->num_vertices * 2);
|
|
num_vertices += side_mesh->num_vertices;
|
|
}
|
|
|
|
|
|
uint32_t vertex_of_block = 0;
|
|
|
|
vertex_of_block = 0;
|
|
while(vertex_of_block < num_vertices)
|
|
{
|
|
xyz[vertex_of_block*3 + 0] += (float) x;
|
|
xyz[vertex_of_block*3 + 1] += (float) y;
|
|
xyz[vertex_of_block*3 + 2] += (float) z;
|
|
++vertex_of_block;
|
|
}
|
|
|
|
return num_vertices;
|
|
}
|
|
|
|
void tc_meshize_chunk(tc_chunk_s *chunk)
|
|
{
|
|
if(chunk->vertex_positions != NULL) free(chunk->vertex_positions);
|
|
if(chunk->vertex_uvs != NULL) free(chunk->vertex_uvs);
|
|
|
|
chunk->num_vertices = tc_count_chunk_vertices(chunk);
|
|
chunk->vertex_positions = calloc(sizeof(float), 3 * chunk->num_vertices);
|
|
chunk->vertex_uvs = calloc(sizeof(float), 2 * chunk->num_vertices);
|
|
|
|
uint32_t vertex_index = 0;
|
|
float block_positions[1024];
|
|
float block_uvs[1024];
|
|
|
|
uint32_t x_in_chunk = 0;
|
|
uint32_t y_in_chunk = 0;
|
|
uint32_t z_in_chunk = 0;
|
|
while(x_in_chunk < 32)
|
|
{
|
|
y_in_chunk = 0;
|
|
while(y_in_chunk < 32)
|
|
{
|
|
z_in_chunk = 0;
|
|
while(z_in_chunk < 32)
|
|
{
|
|
tc_block_entry_s *entry =
|
|
tc_resolve_id_to_block_entry(
|
|
chunk->blocks[x_in_chunk][y_in_chunk][z_in_chunk]
|
|
);
|
|
if(entry == NULL)
|
|
{
|
|
++z_in_chunk;
|
|
continue;
|
|
}
|
|
|
|
tc_block_attribute_s *block =
|
|
tc_block_resolve_name_to_attribute(entry, "block_type");
|
|
|
|
if(block == NULL)
|
|
{
|
|
++z_in_chunk;
|
|
continue;
|
|
}
|
|
|
|
if(!strcmp(block->value.string, "basic_cube"))
|
|
{
|
|
memset(block_positions, 0x00, sizeof(float) * 1024);
|
|
memset(block_uvs, 0x00, sizeof(float) * 1024);
|
|
uint32_t made_vertices = tc_meshize_block(chunk, x_in_chunk, y_in_chunk, z_in_chunk, block_positions, block_uvs);
|
|
|
|
memcpy(
|
|
&chunk->vertex_positions[vertex_index*3],
|
|
block_positions,
|
|
sizeof(float) * made_vertices * 3
|
|
);
|
|
memcpy(
|
|
&chunk->vertex_uvs[vertex_index*2],
|
|
block_uvs,
|
|
sizeof(float) * made_vertices * 2
|
|
);
|
|
|
|
vertex_index += made_vertices;
|
|
}
|
|
++z_in_chunk;
|
|
}
|
|
++y_in_chunk;
|
|
}
|
|
++x_in_chunk;
|
|
}
|
|
}
|
|
|