void generate_texture_atlases(std::vector<TexturePatch::Ptr> * orig_texture_patches, Settings const & settings, std::vector<TextureAtlas::Ptr> * texture_atlases) { std::list<TexturePatch::ConstPtr> texture_patches; while (!orig_texture_patches->empty()) { TexturePatch::Ptr texture_patch = orig_texture_patches->back(); orig_texture_patches->pop_back(); if (settings.tone_mapping != TONE_MAPPING_NONE) { mve::image::gamma_correct(texture_patch->get_image(), 1.0f / 2.2f); } texture_patches.push_back(texture_patch); } std::cout << "\tSorting texture patches... " << std::flush; /* Improve the bin-packing algorithm efficiency by sorting texture patches * in descending order of size. */ texture_patches.sort(comp); std::cout << "done." << std::endl; std::size_t const total_num_patches = texture_patches.size(); std::size_t remaining_patches = texture_patches.size(); std::ofstream tty("/dev/tty", std::ios_base::out); #pragma omp parallel { #pragma omp single { while (!texture_patches.empty()) { unsigned int texture_size = calculate_texture_size(texture_patches); texture_atlases->push_back(TextureAtlas::create(texture_size)); TextureAtlas::Ptr texture_atlas = texture_atlases->back(); /* Try to insert each of the texture patches into the texture atlas. */ std::list<TexturePatch::ConstPtr>::iterator it = texture_patches.begin(); for (; it != texture_patches.end();) { std::size_t done_patches = total_num_patches - remaining_patches; int precent = static_cast<float>(done_patches) / total_num_patches * 100.0f; if (total_num_patches > 100 && done_patches % (total_num_patches / 100) == 0) { tty << "\r\tWorking on atlas " << texture_atlases->size() << " " << precent << "%... " << std::flush; } if (texture_atlas->insert(*it)) { it = texture_patches.erase(it); remaining_patches -= 1; } else { ++it; } } #pragma omp task texture_atlas->finalize(); } std::cout << "\r\tWorking on atlas " << texture_atlases->size() << " 100%... done." << std::endl; util::WallTimer timer; std::cout << "\tFinalizing texture atlases... " << std::flush; #pragma omp taskwait std::cout << "done. (Took: " << timer.get_elapsed_sec() << "s)" << std::endl; /* End of single region */ } /* End of parallel region. */ } }
void BC_Texture::create_texture(int w, int h, int colormodel) { #ifdef HAVE_GL // Get max texture size from the server. // Maximum size was 4096 on the earliest cards that could do video. int max_texture_size = 0; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); // Calculate dimensions of texture int new_w = calculate_texture_size(w, &max_texture_size); int new_h = calculate_texture_size(h, &max_texture_size); int new_components = cmodel_components(colormodel); if(new_w < w || new_h < h) { printf("BC_Texture::create_texture frame size %dx%d bigger than maximum texture %dx%d.\n", w, h, max_texture_size, max_texture_size); } // Delete existing texture if(texture_id >= 0 && (new_h != texture_h || new_w != texture_w || new_components != texture_components || BC_WindowBase::get_synchronous()->current_window->get_id() != window_id)) { // printf("BC_Texture::create_texture released window_id=%d texture_id=%d\n", // BC_WindowBase::get_synchronous()->current_window->get_id(), // texture_id); BC_WindowBase::get_synchronous()->release_texture( window_id, texture_id); texture_id = -1; window_id = -1; } texture_w = new_w; texture_h = new_h; texture_components = new_components; // Get matching texture if(texture_id < 0) { texture_id = BC_WindowBase::get_synchronous()->get_texture( texture_w, texture_h, texture_components); // A new VFrame has no window_id, so it must read it from the matching texture. if(texture_id >= 0) window_id = BC_WindowBase::get_synchronous()->current_window->get_id(); } // No matching texture exists. // Create new texture with the proper dimensions if(texture_id < 0) { glGenTextures(1, (GLuint*)&texture_id); glBindTexture(GL_TEXTURE_2D, (GLuint)texture_id); glEnable(GL_TEXTURE_2D); if(texture_components == 4) glTexImage2D(GL_TEXTURE_2D, 0, 4, texture_w, texture_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); else glTexImage2D(GL_TEXTURE_2D, 0, 3, texture_w, texture_h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); window_id = BC_WindowBase::get_synchronous()->current_window->get_id(); BC_WindowBase::get_synchronous()->put_texture(texture_id, texture_w, texture_h, texture_components); // printf("VFrame::new_texture created texture_id=%d window_id=%d\n", // *texture_id, // *window_id); } else { glBindTexture(GL_TEXTURE_2D, (GLuint)texture_id); glEnable(GL_TEXTURE_2D); } #endif }