void a2estatic::load_from_memory(unsigned int object_count_, unsigned int vertex_count_, float3* vertices_, float2* tex_coords_, unsigned int* index_count_, uint3** indices_) { filename = "<memory>"; a2estatic::vertex_count = vertex_count_; a2estatic::vertices = vertices_; a2estatic::tex_coord_count = vertex_count_; a2estatic::tex_coords = tex_coords_; a2estatic::index_count = index_count_; a2estatic::indices = indices_; a2estatic::tex_indices = indices_; normals = new float3[vertex_count]; binormals = new float3[vertex_count]; tangents = new float3[vertex_count]; a2estatic::object_count = object_count_; min_index = new unsigned int[object_count]; max_index = new unsigned int[object_count]; memset(min_index, 0xFF, sizeof(unsigned int)*object_count); memset(max_index, 0, sizeof(unsigned int)*object_count); for(unsigned int i = 0; i < object_count; i++) { if(index_count[i] == 0) { min_index[i] = 0; max_index[i] = 0; } for(unsigned int j = 0; j < index_count[i]; j++) { // also get the max/highest and min/lowest index number if(tex_indices[i][j].x > max_index[i]) max_index[i] = tex_indices[i][j].x; if(tex_indices[i][j].y > max_index[i]) max_index[i] = tex_indices[i][j].y; if(tex_indices[i][j].z > max_index[i]) max_index[i] = tex_indices[i][j].z; if(tex_indices[i][j].x < min_index[i]) min_index[i] = tex_indices[i][j].x; if(tex_indices[i][j].y < min_index[i]) min_index[i] = tex_indices[i][j].y; if(tex_indices[i][j].z < min_index[i]) min_index[i] = tex_indices[i][j].z; } } delete_sub_bboxes(); sub_bboxes.resize(object_count); object_names.clear(); object_names.resize(object_count); for(unsigned int i = 0; i < object_count; i++) { object_names[i] = "object #" + to_string(i); } // set this stuff for normal generating model_indices = indices; model_index_count = index_count; generate_normals(); // set the actual model data after everything is computed correctly and its final state model_indices = indices; model_index_count = index_count; model_vertices = new float3*[object_count]; model_vertex_count = new unsigned int[object_count]; for(unsigned int i = 0; i < object_count; i++) { model_vertices[i] = &vertices[min_index[i]]; model_vertex_count[i] = (min_index[i] != 0xFFFFFFFF ? max_index[i] - min_index[i] + 1 : 0); } build_bounding_box(); // vertices vbo glGenBuffers(1, &vbo_vertices_id); glBindBuffer(GL_ARRAY_BUFFER, vbo_vertices_id); glBufferData(GL_ARRAY_BUFFER, vertex_count * 3 * sizeof(float), vertices, GL_STATIC_DRAW); // tex_coords vbo glGenBuffers(1, &vbo_tex_coords_id); glBindBuffer(GL_ARRAY_BUFFER, vbo_tex_coords_id); glBufferData(GL_ARRAY_BUFFER, vertex_count * 2 * sizeof(float), tex_coords, GL_STATIC_DRAW); // normals/binormals/tangents vbo glGenBuffers(1, &vbo_normals_id); glBindBuffer(GL_ARRAY_BUFFER, vbo_normals_id); glBufferData(GL_ARRAY_BUFFER, vertex_count * 3 * sizeof(float), normals, GL_STATIC_DRAW); glGenBuffers(1, &vbo_binormals_id); glBindBuffer(GL_ARRAY_BUFFER, vbo_binormals_id); glBufferData(GL_ARRAY_BUFFER, vertex_count * 3 * sizeof(float), binormals, GL_STATIC_DRAW); glGenBuffers(1, &vbo_tangents_id); glBindBuffer(GL_ARRAY_BUFFER, vbo_tangents_id); glBufferData(GL_ARRAY_BUFFER, vertex_count * 3 * sizeof(float), tangents, GL_STATIC_DRAW); // indices vbos vbo_indices_ids = new GLuint[object_count]; for(unsigned int i = 0; i < object_count; i++) { glGenBuffers(1, &vbo_indices_ids[i]); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo_indices_ids[i]); glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_count[i] * 3 * sizeof(unsigned int), indices[i], GL_STATIC_DRAW); } // reset buffer glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // general model setup model_setup(); }
int unpack(FILE* out,FILE* in) { freq cf; rangecoder rc; struct buffer buffer; struct ari_model model; size_t processed=0; buffer.offset = 0; buffer.len_power = 1+BLOCKSIZE_POWER; buffer.len = 1<<buffer.len_power; buffer.len_mask = buffer.len - 1; buffer.data = malloc(buffer.len); rc.in = in; model_setup(&model); if(!buffer.data) return -2; if (start_decoding(&rc) != 0) { return -1; } while ( (cf = decode_culfreq(&rc,2)) ) { freq i, blocksize; decode_update(&rc,1,1,2); blocksize = decode_short(&rc) | ((size_t)decode_short(&rc)) <<16; for (i=0; i<blocksize; i++) { freq symbol; cf = decode_culfreq(&rc,model.counts[SYMBOLS]); symbol = model_get_symbol(&model, cf); decode_update(&rc, model.counts[symbol+1]-model.counts[symbol],model.counts[symbol],model.counts[SYMBOLS]); model_update_freq(&model,symbol); /*fprintf(stderr,"Decoding:%d(%c),%ld,%ld\n",symbol,symbol,counts[symbol+1]-counts[symbol],counts[symbol]);*/ if(symbol > 0xff) { const uint8_t extra_bits = code_to_length[symbol-0x100].extra_bits; const size_t extra_data = decode_culshift(&rc, extra_bits); const size_t length = code_to_length[symbol-0x100].start + extra_data; size_t distance; size_t distance_hi; decode_update_shift(&rc, 1, extra_data, extra_bits); distance = decode_culshift(&rc,8); decode_update_shift(&rc, 1, distance, 8); distance_hi = decode_culshift(&rc,8); decode_update_shift(&rc, 1, distance_hi, 8); distance |= distance_hi<<8; /* fprintf(stderr,"Retrieved length,distance:%ld,%ld\n",length,distance);*/ buffer.offset = copy_back_bytes(&buffer,buffer.offset,distance,length); } else { buffer.data[buffer.offset++] = symbol; if(buffer.offset >= buffer.len) { buffer.offset = 0; fwrite(buffer.data,1,buffer.len,out); } } } processed += blocksize; if(processed > 1<<19) { done_decoding(&rc); start_decoding(&rc); processed=0; } /*fprintf(stderr,"%ld;;%d\n",blocksize,model.counts[SYMBOLS]);*/ } fwrite(buffer.data,1,buffer.offset,out); done_decoding(&rc); model_done(&model); free(buffer.data); fclose(out); return 0; }
/*! loads a .a2m model file * @param filename the name of the .a2m model file * @param vbo flag that specifies if vertex buffer objects should be used */ void a2estatic::load_model(const string& filename_) { file_io file(filename_, file_io::OPEN_TYPE::READ_BINARY); if(!file.is_open()) { return; } filename = filename_; // get type and name char* file_type = new char[9]; file.get_block(file_type, 8); file_type[8] = 0; if(strcmp(file_type, "A2EMODEL") != 0) { log_error("non supported file type for %s: %s!", filename, file_type); delete [] file_type; file.close(); return; } delete [] file_type; // get model version unsigned int version = file.get_uint(); if(version != A2M_VERSION) { log_error("wrong model file version %u - should be %u!", version, A2M_VERSION); file.close(); return; } // get model type and abort if it's not 0x00 or 0x02 auto mtype = file.get_char(); if(mtype != 0x00 && mtype != 0x02) { log_error("non supported model type: %u!", (unsigned int)(mtype & 0xFF)); file.close(); return; } if(mtype == 0x02) collision_model = true; vertex_count = file.get_uint(); tex_coord_count = file.get_uint(); vertices = new float3[vertex_count]; normals = new float3[vertex_count]; binormals = new float3[vertex_count]; tangents = new float3[vertex_count]; tex_coords = new float2[tex_coord_count]; for(unsigned int i = 0; i < vertex_count; i++) { vertices[i].x = file.get_float(); vertices[i].y = file.get_float(); vertices[i].z = file.get_float(); } for(unsigned int i = 0; i < tex_coord_count; i++) { tex_coords[i].x = file.get_float(); tex_coords[i].y = 1.0f - file.get_float(); } object_count = file.get_uint(); delete_sub_bboxes(); sub_bboxes.resize(object_count); object_names.clear(); object_names.resize(object_count); for(unsigned int i = 0; i < object_count; i++) { file.get_terminated_block(object_names[i], 0xFF); } indices = new uint3*[object_count]; tex_indices = new uint3*[object_count]; index_count = new unsigned int[object_count]; min_index = new unsigned int[object_count]; max_index = new unsigned int[object_count]; memset(min_index, 0xFF, sizeof(unsigned int)*object_count); memset(max_index, 0, sizeof(unsigned int)*object_count); for(unsigned int i = 0; i < object_count; i++) { index_count[i] = file.get_uint(); indices[i] = new uint3[index_count[i]]; tex_indices[i] = new uint3[index_count[i]]; for(unsigned int j = 0; j < index_count[i]; j++) { indices[i][j].x = file.get_uint(); indices[i][j].y = file.get_uint(); indices[i][j].z = file.get_uint(); } for(unsigned int j = 0; j < index_count[i]; j++) { tex_indices[i][j].x = file.get_uint(); tex_indices[i][j].y = file.get_uint(); tex_indices[i][j].z = file.get_uint(); } } if(collision_model) { col_vertex_count = file.get_uint(); col_vertices = new float3[col_vertex_count]; for(unsigned int i = 0; i < col_vertex_count; i++) { col_vertices[i].x = file.get_float(); col_vertices[i].y = file.get_float(); col_vertices[i].z = file.get_float(); } col_index_count = file.get_uint(); col_indices = new uint3[col_index_count]; for(unsigned int i = 0; i < col_index_count; i++) { col_indices[i].x = file.get_uint(); col_indices[i].y = file.get_uint(); col_indices[i].z = file.get_uint(); } } file.close(); // set this stuff for normal generating model_indices = indices; model_index_count = index_count; generate_normals(); reorganize_model_data(); // set the actual model data after everything is computed correctly and its final state model_indices = indices; model_index_count = index_count; model_vertices = new float3*[object_count]; model_tex_coords = new float2*[object_count]; model_vertex_count = new unsigned int[object_count]; for(unsigned int i = 0; i < object_count; i++) { model_vertices[i] = &vertices[min_index[i]]; model_tex_coords[i] = &tex_coords[min_index[i]]; model_vertex_count[i] = max_index[i] - min_index[i] + 1; } build_bounding_box(); // vertices vbo glGenBuffers(1, &vbo_vertices_id); glBindBuffer(GL_ARRAY_BUFFER, vbo_vertices_id); glBufferData(GL_ARRAY_BUFFER, vertex_count * 3 * sizeof(float), vertices, GL_STATIC_DRAW); // tex_coords vbo glGenBuffers(1, &vbo_tex_coords_id); glBindBuffer(GL_ARRAY_BUFFER, vbo_tex_coords_id); glBufferData(GL_ARRAY_BUFFER, vertex_count * 2 * sizeof(float), tex_coords, GL_STATIC_DRAW); // normals/binormals/tangents vbo glGenBuffers(1, &vbo_normals_id); glBindBuffer(GL_ARRAY_BUFFER, vbo_normals_id); glBufferData(GL_ARRAY_BUFFER, vertex_count * 3 * sizeof(float), normals, GL_STATIC_DRAW); glGenBuffers(1, &vbo_binormals_id); glBindBuffer(GL_ARRAY_BUFFER, vbo_binormals_id); glBufferData(GL_ARRAY_BUFFER, vertex_count * 3 * sizeof(float), binormals, GL_STATIC_DRAW); glGenBuffers(1, &vbo_tangents_id); glBindBuffer(GL_ARRAY_BUFFER, vbo_tangents_id); glBufferData(GL_ARRAY_BUFFER, vertex_count * 3 * sizeof(float), tangents, GL_STATIC_DRAW); // indices vbos vbo_indices_ids = new GLuint[object_count]; for(unsigned int i = 0; i < object_count; i++) { glGenBuffers(1, &vbo_indices_ids[i]); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo_indices_ids[i]); glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_count[i] * 3 * sizeof(unsigned int), indices[i], GL_STATIC_DRAW); } // reset buffer glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // general model setup model_setup(); }