1
0
Fork 0
2022-untitled-game/code/game/engine/data_loader.c

512 lines
12 KiB
C

static mesh_t
create_mesh(uint16_t index_count, uint16_t* indices, uint16_t vertex_count, vertex_t* vertices);
static mesh_t
load_mesh(SDL_RWops* ops);
static material_t
create_material(uint16_t width, uint16_t height, uint8_t channel_count, uint8_t* data);
static material_t
load_material(SDL_RWops* ops);
static sound_t
load_sound(SDL_RWops* ops);
static audio_source_t
load_audio_source(SDL_RWops* ops);
static transform_t
load_transform(SDL_RWops* ops);
static renderable_t
load_renderable(SDL_RWops* ops);
static box_collider_t
load_collider(SDL_RWops* ops);
static point_light_t
load_light(SDL_RWops* ops);
void
load_data1(const char* path)
{
LOG_DEBUG("Loading %s", path);
SDL_RWops* ops = SDL_RWFromFile(path, "rb");
if (ops == NULL)
{
LOG_ERROR("Error opening data file %s: %s", path, SDL_GetError());
exit(EXIT_FAILURE);
}
{
char magic[4];
SDL_RWread(ops, magic, sizeof(magic), 1);
if (magic[0] != 'A' || magic[1] != 'J' || magic[2] != 'M' || magic[3] != '\0') {
LOG_ERROR("Data file %s has an invalid format", path);
exit(EXIT_FAILURE);
}
}
// NOTE: All printed counts are decremented by 1 to account for the first value being a null item
{
uint16_t count;
SDL_RWread(ops, &count, sizeof(count), 1);
LOG_ASSERT(count < MAX_TRANSFORM_COUNT, "Too many transforms");
LOG_DEBUG("Load %d transforms", count-1);
for (int i = 0; i < count; i++)
{
transform_t transform = load_transform(ops);
insert_transform(transform);
}
}
{
uint16_t count;
SDL_RWread(ops, &count, sizeof(count), 1);
LOG_DEBUG("Load %d meshes", count-1);
LOG_ASSERT(count < MAX_MESH_COUNT, "Too many meshes");
for (int i = 0; i < count; i++)
{
mesh_t mesh = load_mesh(ops);
insert_mesh(mesh);
}
}
{
uint16_t count;
SDL_RWread(ops, &count, sizeof(count), 1);
LOG_DEBUG("Load %d materials", count-1);
LOG_ASSERT(count < MAX_MATERIAL_COUNT, "Too many materials");
for (int i = 0; i < count; i++)
{
material_t material = load_material(ops);
insert_material(material);
}
}
{
uint16_t count;
SDL_RWread(ops, &count, sizeof(count), 1);
LOG_DEBUG("Load %d cameras", count-1);
LOG_ASSERT(count < MAX_CAMERA_COUNT, "Too many cameras");
for (int i = 0; i < count; i++)
{
uint16_t name_length;
SDL_RWread(ops, &name_length, sizeof(name_length), 1);
char* name = scratch_mem_alloc(name_length, sizeof(*name));
SDL_RWread(ops, name, sizeof(*name), name_length);
LOG_ASSERT(name_length < MAX_NAME_LENGTH, "Name of camera is too long: %s", name);
handle_t transform;
SDL_RWread(ops, &transform, sizeof(transform), 1);
camera_t camera = camera_create(transform);
strncpy(camera.name, name, name_length);
insert_camera(camera);
}
}
{
uint16_t count;
SDL_RWread(ops, &count, sizeof(count), 1);
LOG_DEBUG("Load %d renderables", count-1);
LOG_ASSERT(count < MAX_RENDERABLE_COUNT, "Too many renderables");
for (int i = 0; i < count; i++)
{
renderable_t renderable = load_renderable(ops);
insert_renderable(renderable);
}
}
{
uint16_t count;
SDL_RWread(ops, &count, sizeof(count), 1);
LOG_DEBUG("Load %d colliders", count-1);
LOG_ASSERT(count < MAX_COLLIDER_COUNT, "Too many colliders");
for (int i = 0; i < count; i++)
{
box_collider_t collider = load_collider(ops);
insert_collider(collider);
}
}
{
uint16_t count;
SDL_RWread(ops, &count, sizeof(count), 1);
LOG_DEBUG("Load %d lights", count-1);
LOG_ASSERT(count < MAX_LIGHT_COUNT, "Too many lights");
for (int i = 0; i < count; i++)
{
point_light_t light = load_light(ops);
insert_light(light);
}
}
int ret = SDL_RWclose(ops);
if (ret != 0) {
LOG_ERROR("Error closing file %s: %s", path, SDL_GetError());
}
}
void
load_data2(const char* path)
{
LOG_DEBUG("Loading %s", path);
SDL_RWops* ops = SDL_RWFromFile(path, "rb");
if (ops == NULL)
{
LOG_ERROR("Error opening data file %s: %s", path, SDL_GetError());
exit(EXIT_FAILURE);
}
{
char magic[4];
SDL_RWread(ops, magic, sizeof(magic), 1);
if (magic[0] != 'A' || magic[1] != 'J' || magic[2] != 'M' || magic[3] != '\0') {
LOG_ERROR("Data file %s has an invalid format", path);
exit(EXIT_FAILURE);
}
}
{
uint16_t count;
SDL_RWread(ops, &count, sizeof(count), 1);
LOG_DEBUG("Load %d sounds", count-1);
LOG_ASSERT(count < MAX_SOUND_COUNT, "Too many sounds");
for (int i = 0; i < count; i++)
{
sound_t sound = load_sound(ops);
insert_sound(sound);
}
}
{
uint16_t count;
SDL_RWread(ops, &count, sizeof(count), 1);
LOG_DEBUG("Load %d audio sources", count-1);
LOG_ASSERT(count < MAX_AUDIO_SOURCE_COUNT, "Too many audio sources");
for (int i = 0; i < count; i++)
{
audio_source_t source = load_audio_source(ops);
insert_audio_source(source);
}
}
int ret = SDL_RWclose(ops);
if (ret != 0) {
LOG_ERROR("Error closing file %s: %s", path, SDL_GetError());
}
}
static mesh_t
create_mesh(uint16_t index_count, uint16_t* indices, uint16_t vertex_count, vertex_t* vertices)
{
GLuint ebo;
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(
GL_ELEMENT_ARRAY_BUFFER,
index_count * sizeof(*indices),
indices,
GL_STATIC_DRAW);
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(
GL_ARRAY_BUFFER,
vertex_count * sizeof(*vertices),
vertices,
GL_STATIC_DRAW);
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(struct vertex), (void*)offsetof(struct vertex, position));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(struct vertex), (void*)offsetof(struct vertex, normal));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(struct vertex), (void*)offsetof(struct vertex, texcoord));
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
mesh_t result = {
.vao = vao,
.vbo = vbo,
.ebo = ebo,
.index_count = index_count};
return result;
}
static mesh_t
load_mesh(SDL_RWops* ops)
{
uint16_t name_length;
SDL_RWread(ops, &name_length, sizeof(name_length), 1);
char* name = scratch_mem_alloc(name_length, sizeof(*name));
SDL_RWread(ops, name, sizeof(*name), name_length);
LOG_ASSERT(name_length < MAX_NAME_LENGTH, "Name of mesh is too long: %s", name);
uint16_t index_count;
SDL_RWread(ops, &index_count, sizeof(index_count), 1);
uint16_t* indices = scratch_mem_alloc(index_count, sizeof(*indices));
SDL_RWread(ops, indices, sizeof(*indices), index_count);
uint16_t vertex_count;
SDL_RWread(ops, &vertex_count, sizeof(vertex_count), 1);
vertex_t* vertices = scratch_mem_alloc(vertex_count, sizeof(*vertices));
SDL_RWread(ops, vertices, sizeof(*vertices), vertex_count);
mesh_t result = create_mesh(index_count, indices, vertex_count, vertices);
strncpy(result.name, name, name_length);
return result;
}
static material_t
create_material(uint16_t width, uint16_t height, uint8_t channel_count, uint8_t* data)
{
GLuint format = (channel_count == 3) ? GL_RGB : GL_RGBA;
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
material_t result = {
.texture = texture};
return result;
}
static material_t
load_material(SDL_RWops* ops)
{
uint16_t name_length;
SDL_RWread(ops, &name_length, sizeof(name_length), 1);
char* name = scratch_mem_alloc(name_length, sizeof(*name));
SDL_RWread(ops, name, sizeof(*name), name_length);
LOG_ASSERT(name_length < MAX_NAME_LENGTH, "Name of material is too long: %s", name);
uint16_t width;
SDL_RWread(ops, &width, sizeof(width), 1);
uint16_t height;
SDL_RWread(ops, &height, sizeof(height), 1);
uint8_t channel_count;
SDL_RWread(ops, &channel_count, sizeof(channel_count), 1);
uint8_t* data = scratch_mem_alloc(width * height * channel_count, sizeof(*data));
SDL_RWread(ops, data, sizeof(*data), width * height * channel_count);
material_t result = create_material(width, height, channel_count, data);
strncpy(result.name, name, name_length);
return result;
}
static transform_t
load_transform(SDL_RWops* ops)
{
vec3 position;
SDL_RWread(ops, &position, sizeof(position), 1);
vec3 rotation;
SDL_RWread(ops, &rotation, sizeof(rotation), 1);
vec3 scale;
SDL_RWread(ops, &scale, sizeof(scale), 1);
handle_t parent;
SDL_RWread(ops, &parent, sizeof(parent), 1);
uint16_t child_count;
SDL_RWread(ops, &child_count, sizeof(child_count), 1);
LOG_ASSERT(child_count < MAX_CHILDREN_COUNT, "Transform has too many children: %d", child_count);
handle_t* children = scratch_mem_alloc(child_count, sizeof(*children));
SDL_RWread(ops, children, sizeof(*children), child_count);
mat4 matrix = mat4_identity();
transform_t result = {
.position = position,
.rotation = rotation,
.scale = scale,
.child_count = child_count,
.parent = parent,
.matrix = matrix};
memcpy(result.children, children, child_count * sizeof(*children));
return result;
}
static sound_t
load_sound(SDL_RWops* ops)
{
uint16_t name_length;
SDL_RWread(ops, &name_length, sizeof(name_length), 1);
char* name = scratch_mem_alloc(name_length, sizeof(*name));
SDL_RWread(ops, name, sizeof(*name), name_length);
LOG_ASSERT(name_length < MAX_NAME_LENGTH, "Name of sound is too long: %s", name);
uint32_t length;
SDL_RWread(ops, &length, sizeof(length), 1);
uint32_t sample_rate;
SDL_RWread(ops, &sample_rate, sizeof(sample_rate), 1);
uint8_t channel_count;
SDL_RWread(ops, &channel_count, sizeof(channel_count), 1);
size_t size = length * channel_count;
float* wav_data = persistent_mem_alloc(&g_memory->data2, size, sizeof(*wav_data));
SDL_RWread(ops, wav_data, sizeof(*wav_data), size);
int byte_count = length * channel_count * sizeof(*wav_data);
sound_t result = {
.data = wav_data,
.byte_count = byte_count};
strncpy(result.name, name, name_length);
return result;
}
static audio_source_t
load_audio_source(SDL_RWops* ops)
{
uint16_t name_length;
SDL_RWread(ops, &name_length, sizeof(name_length), 1);
char* name = scratch_mem_alloc(name_length, sizeof(*name));
SDL_RWread(ops, name, sizeof(*name), name_length);
LOG_ASSERT(name_length < MAX_NAME_LENGTH, "Name of audio source is too long: %s", name);
handle_t transform;
SDL_RWread(ops, &transform, sizeof(transform), 1);
float volume;
SDL_RWread(ops, &volume, sizeof(volume), 1);
uint32_t type;
SDL_RWread(ops, &type, sizeof(type), 1);
handle_t sound;
SDL_RWread(ops, &sound, sizeof(sound), 1);
audio_source_t result = {
.type = (audio_type_e)type,
.transform = transform,
.volume = volume,
.sound = sound};
strncpy(result.name, name, name_length);
return result;
}
static renderable_t
load_renderable(SDL_RWops* ops)
{
uint16_t name_length;
SDL_RWread(ops, &name_length, sizeof(name_length), 1);
char* name = scratch_mem_alloc(name_length, sizeof(*name));
SDL_RWread(ops, name, sizeof(*name), name_length);
LOG_ASSERT(name_length < MAX_NAME_LENGTH, "Name of mesh is too long: %s", name);
handle_t transform;
SDL_RWread(ops, &transform, sizeof(transform), 1);
handle_t mesh;
SDL_RWread(ops, &mesh, sizeof(mesh), 1);
handle_t material;
SDL_RWread(ops, &material, sizeof(material), 1);
renderable_t result = {
.transform = transform,
.mesh = mesh,
.material = material};
strncpy(result.name, name, name_length);
return result;
}
static box_collider_t
load_collider(SDL_RWops* ops)
{
handle_t transform;
SDL_RWread(ops, &transform, sizeof(transform), 1);
vec3 extents;
SDL_RWread(ops, &extents, sizeof(extents), 1);
box_collider_t result = {
.transform = transform,
.extents = extents};
return result;
}
static point_light_t
load_light(SDL_RWops* ops)
{
handle_t transform;
SDL_RWread(ops, &transform, sizeof(transform), 1);
vec3 color;
SDL_RWread(ops, &color, sizeof(color), 1);
float intensity;
SDL_RWread(ops, &intensity, sizeof(intensity), 1);
float radius;
SDL_RWread(ops, &radius, sizeof(radius), 1);
point_light_t result = {
.transform = transform,
.color = color,
.intensity = intensity,
.radius = radius};
return result;
}