512 lines
12 KiB
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;
|
||
|
}
|