Uint32 get_image_information(el_file_ptr file, image_t* image) { Uint32 dds, result; if (file == 0) { LOG_ERROR("Invalid file!"); return 0; } dds = 0; if (el_get_size(file) >= 4) { if (check_dds(el_get_pointer(file))) { dds = 1; } } if (dds == 1) { result = get_dds_information(file, image); el_seek(file, 0, SEEK_SET); return result; } else { return get_sdl_image_information(file, image); } }
static void* decompress_dds(el_file_ptr file, DdsHeader *header, const Uint32 strip_mipmaps, const Uint32 base_level) { Uint32 width, height, size, format, mipmap_count; Uint32 x, y, i, w, h; Uint32 index; Uint8 *dest; if ((header->m_height % 4) != 0) { LOG_ERROR_OLD("Can`t decompressed DDS file %s because height is" " %d and not a multiple of four.", el_file_name(file), header->m_height); return 0; } if ((header->m_width % 4) != 0) { LOG_ERROR_OLD("Can`t decompressed DDS file %s because width is" " %d and not a multiple of four.", el_file_name(file), header->m_width); return 0; } format = header->m_pixel_format.m_fourcc; if ((format != DDSFMT_DXT1) && (format != DDSFMT_DXT2) && (format != DDSFMT_DXT3) && (format != DDSFMT_DXT4) && (format != DDSFMT_DXT5) && (format != DDSFMT_ATI1) && (format != DDSFMT_ATI2)) { return 0; } index = 0; size = get_dds_size(header, 1, strip_mipmaps, base_level); width = max2u(header->m_width >> base_level, 1); height = max2u(header->m_height >> base_level, 1); mipmap_count = header->m_mipmap_count; if (strip_mipmaps != 0) { if (mipmap_count > (base_level + 1)) { mipmap_count = base_level + 1; } } dest = malloc_aligned(size, 16); el_seek(file, get_dds_offset(header, base_level), SEEK_CUR); for (i = base_level; i < mipmap_count; i++) { w = (width + 3) / 4; h = (height + 3) / 4; assert(index * 4 <= size); // 4x4 blocks in x/y for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { decompress_block(file, format, x * 4, y * 4, width, height, index, dest); } } index += width * height; if (width > 1) { width /= 2; } if (height > 1) { height /= 2; } } assert(index * 4 == size); return dest; }
static e3d_object* do_load_e3d_detail(e3d_object* cur_object) { e3d_header header; e3d_material material; char cur_dir[1024]; int i, idx, l, mem_size, vertex_size, material_size; int file_pos, indices_size, index_size; char text_file_name[1024]; Uint32 tmp; Uint16 tmp_16; Uint8* index_pointer; el_file_ptr file; version_number version; if (cur_object == 0) return 0; memset(cur_dir, 0, sizeof(cur_dir)); //get the current directory l = strlen(cur_object->file_name); //parse the string backwards, until we find a / while (l > 0) { if ((cur_object->file_name[l] == '/') || (cur_object->file_name[l] == '\\')) break; l--; } i = 0; if (l)//prevent invalid dir names { while (l >= 0) { cur_dir[i] = cur_object->file_name[i]; i++; l--; } cur_dir[i+1] = 0; } LOG_DEBUG_OLD("Loading e3d file '%s'.", cur_object->file_name); file = el_open(cur_object->file_name); if (file == 0) { LOG_ERROR_OLD("Can't open file '%s'!", cur_object->file_name); free_e3d_pointer(cur_object); return 0; } if (read_and_check_elc_header(file, EL3D_FILE_MAGIC_NUMBER, &version, cur_object->file_name) != 0) { LOG_ERROR_OLD("File '%s' has wrong header!", cur_object->file_name); free_e3d_pointer(cur_object); el_close(file); return 0; } el_read(file, sizeof(e3d_header), &header); cur_object->vertex_no = SDL_SwapLE32(header.vertex_no); cur_object->index_no = SDL_SwapLE32(header.index_no); cur_object->material_no = SDL_SwapLE32(header.material_no); vertex_size = SDL_SwapLE32(header.vertex_size); material_size = SDL_SwapLE32(header.material_size); index_size = SDL_SwapLE32(header.index_size); LOG_DEBUG_OLD("E3d file vertex count %d and size %d.", cur_object->vertex_no, vertex_size); LOG_DEBUG_OLD("E3d file index count %d and size %d.", cur_object->index_no, index_size); LOG_DEBUG_OLD("E3d file material count %d and size %d.", cur_object->material_no, material_size); LOG_DEBUG_OLD("E3d file version %d.%d.%d.%d.", version[0], version[1], version[2], version[3]); if ((version[0] == 1) && (version[1] == 1)) { if ((header.vertex_options & 0xF0) != 0) { LOG_ERROR_OLD("Unknow options (%d) for file %s.", header.vertex_options, cur_object->file_name); } header.vertex_options &= 0x0F; if ((header.vertex_format & 0xE0) != 0) { LOG_ERROR_OLD("Unknow format (%d) for file %s.", header.vertex_format, cur_object->file_name); } header.vertex_format &= 0x1F; } else { if ((version[0] == 1) && (version[1] == 0)) { header.vertex_format = 0; header.vertex_options ^= 0x01; header.vertex_options &= 0x07; } else { LOG_ERROR_OLD("File '%s' has wrong version number!", cur_object->file_name); free_e3d_pointer(cur_object); el_close(file); return 0; } } idx = 0; if (has_normal(header.vertex_options)) { idx += 1; } if (has_color(header.vertex_options)) { idx += 2; } cur_object->vertex_layout = &(vertex_layout_array[idx]); // They have at least the size we expected if (check_vertex_size(vertex_size, header.vertex_options, header.vertex_format) == 0) { LOG_ERROR_OLD("File '%s' has wrong vertex size!", cur_object->file_name); free_e3d_pointer(cur_object); el_close(file); return 0; } if (material_size != get_material_size(header.vertex_options)) { LOG_ERROR_OLD("File '%s' has wrong material size! Expected size %d, found size %d.", cur_object->file_name, get_material_size(header.vertex_options), material_size); free_e3d_pointer(cur_object); el_close(file); return 0; } if (short_index(header.vertex_format)) { if (index_size != sizeof(Uint16)) { LOG_ERROR_OLD("File '%s' has wrong index size! Expected size %d, found size %d.", cur_object->file_name, sizeof(Uint16), index_size); free_e3d_pointer(cur_object); el_close(file); return 0; } } else { if (index_size != sizeof(Uint32)) { LOG_ERROR_OLD("File '%s' has wrong index size! Expected size %d, found size %d.", cur_object->file_name, sizeof(Uint32), index_size); free_e3d_pointer(cur_object); el_close(file); return 0; } } LOG_DEBUG_OLD("Reading vertices at %d from e3d file '%s'.", SDL_SwapLE32(header.vertex_offset), cur_object->file_name); // Now reading the vertices el_seek(file, SDL_SwapLE32(header.vertex_offset), SEEK_SET); cur_object->vertex_data = malloc(cur_object->vertex_no * cur_object->vertex_layout->size); mem_size = cur_object->vertex_no * cur_object->vertex_layout->size; if (!CHECK_POINTER(cur_object->vertex_data, "vertex data")) return 0; read_vertex_buffer(file, (float*)(cur_object->vertex_data), cur_object->vertex_no, vertex_size, header.vertex_options, header.vertex_format); LOG_DEBUG_OLD("Reading indices at %d from e3d file '%s'.", SDL_SwapLE32(header.index_offset), cur_object->file_name); // Now reading the indices el_seek(file, SDL_SwapLE32(header.index_offset), SEEK_SET); if (cur_object->index_no < 65536) { indices_size = 2; cur_object->index_type = GL_UNSIGNED_SHORT; } else { indices_size = 4; cur_object->index_type = GL_UNSIGNED_INT; } cur_object->indices = malloc(cur_object->index_no * indices_size); index_pointer = 0; for (i = 0; i < cur_object->index_no; i++) { if (index_size == 2) { el_read(file, sizeof(Uint16), &tmp_16); tmp = SDL_SwapLE16(tmp_16); } else { el_read(file, sizeof(Uint32), &tmp); tmp = SDL_SwapLE32(tmp); } if (indices_size == 2) { ((Uint16*)(cur_object->indices))[i] = tmp; } else { ((Uint32*)(cur_object->indices))[i] = tmp; } } // only allocate the materials structure if it doesn't exist (on initial load) if (cur_object->materials == 0) { cur_object->materials = (e3d_draw_list*)malloc(cur_object->material_no*sizeof(e3d_draw_list)); if (!CHECK_POINTER(cur_object->materials, "materials")) return 0; memset(cur_object->materials, 0, cur_object->material_no * sizeof(e3d_draw_list)); } mem_size += cur_object->material_no * sizeof(e3d_draw_list); LOG_DEBUG_OLD("Reading materials at %d from e3d file '%s'.", SDL_SwapLE32(header.material_offset), cur_object->file_name); // Now reading the materials el_seek(file, SDL_SwapLE32(header.material_offset), SEEK_SET); cur_object->min_x = 1e10f; cur_object->min_y = 1e10f; cur_object->min_z = 1e10f; cur_object->max_x = -1e10f; cur_object->max_y = -1e10f; cur_object->max_z = -1e10f; cur_object->max_size = -1e10f; for (i = 0; i < cur_object->material_no; i++) { file_pos = el_tell(file); el_read(file, sizeof(e3d_material), &material); safe_snprintf(text_file_name, sizeof(text_file_name), "%s%s", cur_dir, material.material_name); cur_object->materials[i].options = SDL_SwapLE32(material.options); #ifdef MAP_EDITOR #ifdef NEW_TEXTURES cur_object->materials[i].texture = load_texture_cached(text_file_name, tt_mesh); #else /* NEW_TEXTURES */ cur_object->materials[i].texture = load_texture_cache(text_file_name,0); #endif /* NEW_TEXTURES */ #else //MAP_EDITOR #ifdef NEW_TEXTURES cur_object->materials[i].texture = load_texture_cached(text_file_name, tt_mesh); #else /* NEW_TEXTURES */ #ifdef NEW_ALPHA // prepare to load the textures depending on if it is transparent or not (diff alpha handling) if (material_is_transparent(cur_object->materials[i].options)) { // is this object transparent? cur_object->materials[i].texture= load_texture_cache_deferred(text_file_name, -1); } else { cur_object->materials[i].texture= load_texture_cache_deferred(text_file_name, -1); //255); } #else //NEW_ALPHA // cur_object->materials[i].texture = load_texture_cache_deferred(text_file_name, 255); cur_object->materials[i].texture = load_texture_cache_deferred(text_file_name, 0); #endif //NEW_ALPHA #endif /* NEW_TEXTURES */ #endif //MAP_EDITOR cur_object->materials[i].min_x = SwapLEFloat(material.min_x); cur_object->materials[i].min_y = SwapLEFloat(material.min_y); cur_object->materials[i].min_z = SwapLEFloat(material.min_z); cur_object->materials[i].max_x = SwapLEFloat(material.max_x); cur_object->materials[i].max_y = SwapLEFloat(material.max_y); cur_object->materials[i].max_z = SwapLEFloat(material.max_z); // calculate the max size for cruse LOD processing cur_object->materials[i].max_size= max2f(max2f(cur_object->materials[i].max_x-cur_object->materials[i].min_x, cur_object->materials[i].max_y-cur_object->materials[i].min_y), cur_object->materials[i].max_z-cur_object->materials[i].min_z); cur_object->min_x = min2f(cur_object->min_x, cur_object->materials[i].min_x); cur_object->min_y = min2f(cur_object->min_y, cur_object->materials[i].min_y); cur_object->min_z = min2f(cur_object->min_z, cur_object->materials[i].min_z); cur_object->max_x = max2f(cur_object->max_x, cur_object->materials[i].max_x); cur_object->max_y = max2f(cur_object->max_y, cur_object->materials[i].max_y); cur_object->max_z = max2f(cur_object->max_z, cur_object->materials[i].max_z); cur_object->max_size = max2f(cur_object->max_size, cur_object->materials[i].max_size); cur_object->materials[i].triangles_indices_index = indices_size*SDL_SwapLE32(material.index) + index_pointer; cur_object->materials[i].triangles_indices_count = SDL_SwapLE32(material.count); cur_object->materials[i].triangles_indices_min = SDL_SwapLE32(material.triangles_min_index); cur_object->materials[i].triangles_indices_max = SDL_SwapLE32(material.triangles_max_index); file_pos += SDL_SwapLE32(material_size); el_seek(file, file_pos, SEEK_SET); } el_close(file); LOG_DEBUG_OLD("Building vertex buffers for e3d file '%s'.", cur_object->file_name); //Generate the buffers glGenBuffersARB(1, &cur_object->vertex_vbo); glBindBufferARB(GL_ARRAY_BUFFER_ARB, cur_object->vertex_vbo); glBufferDataARB(GL_ARRAY_BUFFER_ARB, cur_object->vertex_no * cur_object->vertex_layout->size, cur_object->vertex_data, GL_STATIC_DRAW_ARB); #ifndef MAP_EDITOR free(cur_object->vertex_data); cur_object->vertex_data = 0; #endif //MAP_EDITOR glGenBuffersARB(1, &cur_object->indices_vbo); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, cur_object->indices_vbo); glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, cur_object->index_no * indices_size, cur_object->indices, GL_STATIC_DRAW_ARB); #ifndef MAP_EDITOR free(cur_object->indices); cur_object->indices = 0; #endif //MAP_EDITOR glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); #ifndef MAP_EDITOR LOG_DEBUG_OLD("Adding e3d file '%s' to cache.", cur_object->file_name); cache_adj_size(cache_e3d, mem_size, cur_object); #endif //MAP_EDITOR return cur_object; }
static void read_vertex_buffer(el_file_ptr file, float* buffer, const Uint32 vertex_count, const Uint32 vertex_size, const Uint32 options, const Uint32 format) { float temp[3]; Uint16 tmp[3]; Uint32 i, idx, offset; Uint8 color[4]; idx = 0; offset = el_tell(file); for (i = 0; i < vertex_count; i++) { el_seek(file, offset + i * vertex_size, SEEK_SET); if (half_uv(format)) { el_read(file, 2 * sizeof(Uint16), tmp); temp[0] = half_to_float(SDL_SwapLE16(tmp[0])); temp[1] = half_to_float(SDL_SwapLE16(tmp[1])); } else { el_read(file, 2 * sizeof(float), temp); temp[0] = SwapLEFloat(temp[0]); temp[1] = SwapLEFloat(temp[1]); } buffer[idx + 0] = temp[0]; buffer[idx + 1] = temp[1]; idx += 2; if (has_secondary_texture_coordinate(options)) { if (half_extra_uv(format)) { el_seek(file, 2 * sizeof(Uint16), SEEK_CUR); } else { el_seek(file, 2 * sizeof(float), SEEK_CUR); } } if (has_normal(options)) { if (compressed_normal(format)) { el_read(file, sizeof(Uint16), tmp); uncompress_normal(SDL_SwapLE16(tmp[0]), temp); } else { el_read(file, 3 * sizeof(float), temp); temp[0] = SwapLEFloat(temp[0]); temp[1] = SwapLEFloat(temp[1]); temp[2] = SwapLEFloat(temp[2]); } buffer[idx + 0] = temp[0]; buffer[idx + 1] = temp[1]; buffer[idx + 2] = temp[2]; idx += 3; } if (has_tangent(options)) { if (compressed_normal(format)) { el_seek(file, sizeof(Uint16), SEEK_CUR); } else { el_seek(file, 3 * sizeof(float), SEEK_CUR); } } if (half_position(format)) { el_read(file, 3 * sizeof(Uint16), tmp); temp[0] = half_to_float(SDL_SwapLE16(tmp[0])); temp[1] = half_to_float(SDL_SwapLE16(tmp[1])); temp[2] = half_to_float(SDL_SwapLE16(tmp[2])); } else { el_read(file, 3 * sizeof(float), temp); temp[0] = SwapLEFloat(temp[0]); temp[1] = SwapLEFloat(temp[1]); temp[2] = SwapLEFloat(temp[2]); } buffer[idx + 0] = temp[0]; buffer[idx + 1] = temp[1]; buffer[idx + 2] = temp[2]; idx += 3; if (has_color(options)) { el_read(file, 4 * sizeof(Uint8), color); memcpy(&buffer[idx], color, 4 * sizeof(Uint8)); idx += 1; } } }