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; }