Blob Blame Raw
#ifndef MESHTEXTURIZER_H
#define MESHTEXTURIZER_H

#include <memory>

// TnzCore includes
#include "traster.h"
#include "tgl.h" // OpenGL includes

// STL includes
#include <vector>
#include <deque>

#undef DVAPI
#undef DVVAR
#ifdef TNZEXT_EXPORTS
#define DVAPI DV_EXPORT_API
#define DVVAR DV_EXPORT_VAR
#else
#define DVAPI DV_IMPORT_API
#define DVVAR DV_IMPORT_VAR
#endif

//******************************************************************************************
//    MeshTexturizer  declaration
//******************************************************************************************

/*!
  \brief    The MeshTexturizer class acts as a management wrapper to OpenGL texturing
            capabilities, in particular concerning texture virtualization.

  \details  The first step in OpenGL texturing requires copying a texture into the video ram
            (\a VRAM). Now, OpenGL documentation specifies that, although there is no limit
            to the \a number of allowed textures, there \a are limits to the \b size of said
            textures, which can be tested by asking OpenGL whether it can accomodate specific
            texture requests or not.

            Technically, the MeshTexturizer class acts as a virtualization manager that can be
            used to allow texturization with arbitrary texture sizes. The manager accepts raster
            images that are cut up into tiles and bound to VRAM.

            Please, observe that the number of texture objects is typically not an issue, as
            OpenGL is able to swap texture objects between RAM and VRAM, depending on which
            textures have been used most frequently. In other words, since MeshTexturizer ensures
            the granularity required by OpenGL, textures can be used until the process runs out of
            memory - of course, swapping can be a source of slowdowns, though.

  \remark   Subdivision into tiles is designed to work for both premultiplied \a and
            non-premultiplied textures.
  \remark   MeshTexturizer instances are thread-safe.
*/

class DVAPI MeshTexturizer
{
public:
	struct TextureData;

	enum PremultMode //! Premultiplication specifier for texture binding.
	{
		NONPREMULTIPLIED, //!< Texture is not premultiplied.
		PREMULTIPLIED,	//!< Texture is premultiplied.
	};

public:
	MeshTexturizer();
	~MeshTexturizer();

	/*! \details  The bindTexture() function is used to specify a 32-bit fullcolor
                raster as a texture to be used for mesh rendering. The supplied
                geometry rect defines its position with respect to compiled meshes.
      \remark   The premultiplication specifier is used to tell the texturizer how
                to add a proper transparent border surrounding texture tiles.
                This border is essential to draw transparent pixels beyond a texture
                tile's content.
      \returns  The internal id used to reference to the input raster.                        */

	int bindTexture(const TRaster32P &ras, const TRectD &geometry,   //!< Moves a \a copy of the supplied raster image to VRAM,
					PremultMode premultiplyMode = NONPREMULTIPLIED); //!  and assigns an identification number to it.                \param ras  Texture to be copied to VRAM.  \param geometry  The texture's geometry in the world - with respect to compiled meshes.  \param premultiplyMode  Specified whether ras is to be intended premultiplied or not.

	/*! \warning  The pointer returned by getTextureData() is <B>owned by this class</B> -
                it must not be deleted.                                                       */

	TextureData *getTextureData(int textureId); //!< Retrieves the texture data built from a previously
												//!  bound texture image.                                       \param textureId  Identifier of the texture to be retrieved  \returns See summary.

	/*! \details  The texture identifier specified to rebindTexture() is retained,
                and the effect is that of an unbindTexture() - bindTexture() combo.
      \note     Pre-compiled mesh data against the old texture can be retained \b if
                the newly supplied texture size and geometry are the \b same as the old one.  */

	void rebindTexture(int textureId,
					   const TRaster32P &ras, const TRectD &geometry,   //!< Rebinds the image bound to the specified texture
					   PremultMode premultiplyMode = NONPREMULTIPLIED); //!  id to a new image.
	void unbindTexture(int textureId);									//!< Deletes the texture associated to the passed id.           \param textureId  Identifier of the texture to be unbound.

private:
	class Imp;
	std::unique_ptr<Imp> m_imp;

private:
	// Not copyable
	MeshTexturizer(const MeshTexturizer &);
	MeshTexturizer &operator=(const MeshTexturizer &);
};

//******************************************************************************************
//    MeshTexturizer:::CompiledData  definition
//******************************************************************************************

/*!
  \brief    The MeshTexturizer-owned data about a texture.
  
  \details  The purpose of MeshTexturizer is that of storing in VRAM a set of textures
            cut up into tiles. This struture holds the data about the end-product of
            texture loading into a MeshTexturizer instance.
*/

struct MeshTexturizer::TextureData {
	struct TileData //!  Data structure for a texture tile.
	{
		GLuint m_textureId;	//!< OpenGL texture identifier.
		TRectD m_tileGeometry; //!< The tile's world geometry.
	};

public:
	TRectD m_geom;					   //!< The original texture's world geometry.
	std::vector<TileData> m_tileDatas; //!< The texture tiles the original texture was split into.

public:
	TextureData() {}
	TextureData(const TRectD &geom) : m_geom(geom) {}

	~TextureData()
	{
		for (auto const& tile : m_tileDatas) {
			glDeleteTextures(1, &tile.m_textureId);
		}
	}

private:
	// Not copyable
	TextureData(const TextureData &) = delete;
	TextureData &operator=(const TextureData &) = delete;
};

#endif // MESHTEXTURIZER_H