Techneck/code/source-c/meshize.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;
}
}