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. */
    }
}
Ejemplo n.º 2
0
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
}