Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "ext/meshtexturizer.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "tgl.h" // OpenGL includes
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Qt includes
Toshihiro Shimizu 890ddd
#include <qreadwritelock></qreadwritelock>
Toshihiro Shimizu 890ddd
#include <qreadlocker></qreadlocker>
Toshihiro Shimizu 890ddd
#include <qwritelocker></qwritelocker>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// tcg includes
Toshihiro Shimizu 890ddd
#include "tcg/tcg_macros.h"
Toshihiro Shimizu 890ddd
#include "tcg/tcg_list.h"
Toshihiro Shimizu 890ddd
#include "tcg/tcg_misc.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Boost includes
Toshihiro Shimizu 890ddd
#include <boost shared_ptr.hpp=""></boost>
Toshihiro Shimizu 890ddd
#include <boost make_shared.hpp=""></boost>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define COPIED_BORDER 1								 // Amount of tile border from the original image
Toshihiro Shimizu 890ddd
#define TRANSP_BORDER 1								 // Amount of transparent tile border
Toshihiro Shimizu 890ddd
#define NONPREM_BORDER 1							 // Amount of nonpremultiplied copied transparent border
Toshihiro Shimizu 890ddd
#define TOTAL_BORDER (COPIED_BORDER + TRANSP_BORDER) // Overall border to texture tiles above
Toshihiro Shimizu 890ddd
#define TOTAL_BORDER_2 (2 * TOTAL_BORDER)			 // Twice the above
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TCG_STATIC_ASSERT(COPIED_BORDER > 0);				// Due to GL_LINEAR alpha blending on tile seams
Toshihiro Shimizu 890ddd
TCG_STATIC_ASSERT(TRANSP_BORDER > 0);				// Due to GL_CLAMP beyond tile limits
Toshihiro Shimizu 890ddd
TCG_STATIC_ASSERT(NONPREM_BORDER <= TRANSP_BORDER); // The nonpremultiplied border is transparent
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//******************************************************************************************
Toshihiro Shimizu 890ddd
//    MeshTexturizer::Imp  definition
Toshihiro Shimizu 890ddd
//******************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class MeshTexturizer::Imp
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	typedef MeshTexturizer::TextureData TextureData;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	QReadWriteLock m_lock;									  //!< Lock for synchronized access
Toshihiro Shimizu 890ddd
	tcg::list<boost::shared_ptr<texturedata>> m_textureDatas; //!< Pool of texture datas</boost::shared_ptr<texturedata>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	Imp() : m_lock(QReadWriteLock::Recursive) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool testTextureAlloc(int lx, int ly);
Toshihiro Shimizu 890ddd
	GLuint textureAlloc(const TRaster32P &ras, const TRaster32P &aux,
Toshihiro Shimizu 890ddd
						int x, int y, int textureLx, int textureLy,
Toshihiro Shimizu 890ddd
						bool premultiplied);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void allocateTextures(int groupIdx, const TRaster32P &ras, const TRaster32P &aux,
Toshihiro Shimizu 890ddd
						  int x, int y, int textureLx, int textureLy,
Toshihiro Shimizu 890ddd
						  bool premultiplied);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TextureData *getTextureData(int groupIdx);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool MeshTexturizer::Imp::testTextureAlloc(int lx, int ly)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	lx += TOTAL_BORDER_2, ly += TOTAL_BORDER_2; // Add border
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glTexImage2D(GL_PROXY_TEXTURE_2D,
Toshihiro Shimizu 890ddd
				 0,				   // one level only
Toshihiro Shimizu 890ddd
				 GL_RGBA,		   // number of pixel channels
Toshihiro Shimizu 890ddd
				 lx,			   // width
Toshihiro Shimizu 890ddd
				 ly,			   // height
Toshihiro Shimizu 890ddd
				 0,				   // border size
Toshihiro Shimizu 890ddd
				 TGL_FMT,		   // pixel format
Toshihiro Shimizu 890ddd
				 GL_UNSIGNED_BYTE, // pixel data type
Toshihiro Shimizu 890ddd
				 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int outLx;
Toshihiro Shimizu 890ddd
	glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &outLx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return (lx == outLx);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
GLuint MeshTexturizer::Imp::textureAlloc(const TRaster32P &ras, const TRaster32P &aux,
Toshihiro Shimizu 890ddd
										 int x, int y, int textureLx, int textureLy,
Toshihiro Shimizu 890ddd
										 bool premultiplied)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	struct locals {
Toshihiro Shimizu 890ddd
		static void clearMatte(const TRaster32P &ras, int xBegin, int yBegin, int xEnd, int yEnd)
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			for (int y = yBegin; y != yEnd; ++y) {
Toshihiro Shimizu 890ddd
				TPixel32 *line = ras->pixels(y), *pixEnd = line + xEnd;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				for (TPixel32 *pix = line + xBegin; pix != pixEnd; ++pix)
Toshihiro Shimizu 890ddd
					pix->m = 0;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		static void clearMatte_border(const TRaster32P &ras, int border0, int border1)
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			assert(border0 < border1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// Horizontal
Toshihiro Shimizu 890ddd
			clearMatte(ras, border0, border0, ras->getLx() - border0, border1);
Toshihiro Shimizu 890ddd
			clearMatte(ras, border0, ras->getLy() - border1, ras->getLx() - border0, ras->getLy() - border0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// Vertical
Toshihiro Shimizu 890ddd
			clearMatte(ras, border0, border1, border1, ras->getLy() - border1);
Toshihiro Shimizu 890ddd
			clearMatte(ras, ras->getLx() - border1, border1, ras->getLx() - border0, ras->getLy() - border1);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}; // locals
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Prepare the texture tile
Toshihiro Shimizu 890ddd
	assert(aux->getLx() >= textureLx + TOTAL_BORDER_2 && aux->getLy() >= textureLy + TOTAL_BORDER_2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRect rasRect(x, y, x + textureLx - 1, y + textureLy - 1);
Toshihiro Shimizu 890ddd
	rasRect = rasRect.enlarge(premultiplied ? COPIED_BORDER : COPIED_BORDER + NONPREM_BORDER);
Toshihiro Shimizu 890ddd
	rasRect = rasRect * ras->getBounds();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRect auxRect(rasRect - TPoint(x - TOTAL_BORDER, y - TOTAL_BORDER));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// An auxiliary raster must be used to supply the transparent border
Toshihiro Shimizu 890ddd
	TRaster32P tex(aux->extract(0, 0, textureLx + TOTAL_BORDER_2 - 1, textureLy + TOTAL_BORDER_2 - 1));
Toshihiro Shimizu 890ddd
	tex->clear();
Toshihiro Shimizu 890ddd
	aux->extract(auxRect)->copy(ras->extract(rasRect));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!premultiplied && NONPREM_BORDER > 0)
Toshihiro Shimizu 890ddd
		locals::clearMatte_border(aux, TRANSP_BORDER - NONPREM_BORDER, TRANSP_BORDER);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Pass the raster into VRAM
Toshihiro Shimizu 890ddd
	GLuint texId;
Toshihiro Shimizu 890ddd
	glGenTextures(1, &texId);
Toshihiro Shimizu 890ddd
	glBindTexture(GL_TEXTURE_2D, texId);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);	  // These must be used on a bound texture,
Toshihiro Shimizu 890ddd
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);	  // and are remembered in the OpenGL context.
Toshihiro Shimizu 890ddd
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // They can be set here, no need for
Toshihiro Shimizu 890ddd
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // the user to do it.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glPixelStorei(GL_UNPACK_ROW_LENGTH, tex->getWrap());
Toshihiro Shimizu 890ddd
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	glTexImage2D(GL_TEXTURE_2D,
Toshihiro Shimizu 890ddd
				 0,				   // one level only
Toshihiro Shimizu 890ddd
				 GL_RGBA,		   // pixel channels count
Toshihiro Shimizu 890ddd
				 tex->getLx(),	 // width
Toshihiro Shimizu 890ddd
				 tex->getLy(),	 // height
Toshihiro Shimizu 890ddd
				 0,				   // border size
Toshihiro Shimizu 890ddd
				 TGL_FMT,		   // pixel format
Toshihiro Shimizu 890ddd
				 GL_UNSIGNED_BYTE, // pixel data type
Toshihiro Shimizu 890ddd
				 (GLvoid *)tex->getRawData());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return texId;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void MeshTexturizer::Imp::allocateTextures(int groupIdx, const TRaster32P &ras, const TRaster32P &aux,
Toshihiro Shimizu 890ddd
										   int x, int y, int textureLx, int textureLy,
Toshihiro Shimizu 890ddd
										   bool premultiplied)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TextureData *data = m_textureDatas[groupIdx].get();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Test the specified texture allocation
Toshihiro Shimizu 890ddd
	if (testTextureAlloc(textureLx, textureLy)) {
Toshihiro Shimizu 890ddd
		TPointD scale(data->m_geom.getLx() / (double)ras->getLx(),
Toshihiro Shimizu 890ddd
					  data->m_geom.getLy() / (double)ras->getLy());
Toshihiro Shimizu 890ddd
		TRectD tileGeom(
Toshihiro Shimizu 890ddd
			TRectD(
Toshihiro Shimizu 890ddd
				scale.x * (x - TOTAL_BORDER), scale.y * (y - TOTAL_BORDER),
Toshihiro Shimizu 890ddd
				scale.x * (x + textureLx + TOTAL_BORDER), scale.y * (y + textureLy + TOTAL_BORDER)) +
Toshihiro Shimizu 890ddd
			data->m_geom.getP00());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		GLuint texId = textureAlloc(ras, aux, x, y, textureLx, textureLy, premultiplied);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TextureData::TileData td = {texId, tileGeom};
Toshihiro Shimizu 890ddd
		data->m_tileDatas.push_back(td);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (textureLx <= 1 && textureLy <= 1)
Toshihiro Shimizu 890ddd
		return; // No texture can be allocated
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// The texture could not be allocated. Then, bisecate and branch.
Toshihiro Shimizu 890ddd
	if (textureLx > textureLy) {
Toshihiro Shimizu 890ddd
		int textureLx_2 = textureLx >> 1;
Toshihiro Shimizu 890ddd
		allocateTextures(groupIdx, ras, aux, x, y, textureLx_2, textureLy, premultiplied);
Toshihiro Shimizu 890ddd
		allocateTextures(groupIdx, ras, aux, x + textureLx_2, y, textureLx_2, textureLy, premultiplied);
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		int textureLy_2 = textureLy >> 1;
Toshihiro Shimizu 890ddd
		allocateTextures(groupIdx, ras, aux, x, y, textureLx, textureLy_2, premultiplied);
Toshihiro Shimizu 890ddd
		allocateTextures(groupIdx, ras, aux, x, y + textureLy_2, textureLx, textureLy_2, premultiplied);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
MeshTexturizer::TextureData *MeshTexturizer::Imp::getTextureData(int groupIdx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	typedef MeshTexturizer::TextureData TextureData;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Copy tile datas container
Toshihiro Shimizu 890ddd
	return m_textureDatas[groupIdx].get();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//******************************************************************************************
Toshihiro Shimizu 890ddd
//    MeshTexturizer  implementation
Toshihiro Shimizu 890ddd
//******************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
MeshTexturizer::MeshTexturizer()
Toshihiro Shimizu 890ddd
	: m_imp(new Imp)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
MeshTexturizer::~MeshTexturizer()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	delete m_imp;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int MeshTexturizer::bindTexture(const TRaster32P &ras, const TRectD &geom,
Toshihiro Shimizu 890ddd
								PremultMode premultiplyMode)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QWriteLocker locker(&m_imp->m_lock);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Backup the state of some specific OpenGL variables that will be changed throughout the code
Toshihiro Shimizu 890ddd
	int row_length, alignment;
Toshihiro Shimizu 890ddd
	glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length);
Toshihiro Shimizu 890ddd
	glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Initialize a new texture data
Toshihiro Shimizu 890ddd
	int dataIdx = m_imp->m_textureDatas.push_back(boost::make_shared<texturedata>(geom));</texturedata>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Textures must have 2-power sizes. So, let's start with the smallest 2 power
Toshihiro Shimizu 890ddd
	// >= ras's sizes.
Toshihiro Shimizu 890ddd
	int textureLx = tcg::numeric_ops::GE_2Power((unsigned int)ras->getLx() + TOTAL_BORDER_2);
Toshihiro Shimizu 890ddd
	int textureLy = tcg::numeric_ops::GE_2Power((unsigned int)ras->getLy() + TOTAL_BORDER_2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// We'll assume a strict granularity max of 512 x 512 textures
Toshihiro Shimizu 890ddd
	textureLx = tmin(textureLx, 1 << 9);
Toshihiro Shimizu 890ddd
	textureLy = tmin(textureLy, 1 << 9);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Allocate a suitable texture raster. The texture will include a transparent 1-pix border
Toshihiro Shimizu 890ddd
	// that is needed to perform texture mapping with GL_CLAMP transparent wrapping
Toshihiro Shimizu 890ddd
	TRaster32P tex(textureLx, textureLy);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Now, let's tile the specified raster. We'll start from the lower-left corner in case
Toshihiro Shimizu 890ddd
	// the raster can be completely included in just one tile
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int lx = ras->getLx(), ly = ras->getLy();
Toshihiro Shimizu 890ddd
	int tileLx = textureLx - TOTAL_BORDER_2, tileLy = textureLy - TOTAL_BORDER_2; // Texture size without border
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int xEntireCells = (lx - 1) / tileLx, yEntireCells = (ly - 1) / tileLy; // +1 so in case l == tileL, we get the remainder case
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int lastTexLx = tcg::numeric_ops::GE_2Power((unsigned int)(lx - xEntireCells * tileLx + TOTAL_BORDER_2));
Toshihiro Shimizu 890ddd
	int lastTexLy = tcg::numeric_ops::GE_2Power((unsigned int)(ly - yEntireCells * tileLy + TOTAL_BORDER_2));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int lastTileLx = lastTexLx - TOTAL_BORDER_2, lastTileLy = lastTexLy - TOTAL_BORDER_2;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool premultiplied = (premultiplyMode == PREMULTIPLIED);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int i, j;
Toshihiro Shimizu 890ddd
	for (i = 0; i < yEntireCells; ++i) {
Toshihiro Shimizu 890ddd
		for (j = 0; j < xEntireCells; ++j)
Toshihiro Shimizu 890ddd
			// Perform a (possibly subdividing) allocation of the specified tile
Toshihiro Shimizu 890ddd
			m_imp->allocateTextures(dataIdx, ras, tex, j * tileLx, i * tileLy, tileLx, tileLy, premultiplied);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_imp->allocateTextures(dataIdx, ras, tex, j * tileLx, i * tileLy, lastTileLx, tileLy, premultiplied);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (j = 0; j < xEntireCells; ++j)
Toshihiro Shimizu 890ddd
		m_imp->allocateTextures(dataIdx, ras, tex, j * tileLx, i * tileLy, tileLx, lastTileLy, premultiplied);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_imp->allocateTextures(dataIdx, ras, tex, j * tileLx, i * tileLy, lastTileLx, lastTileLy, premultiplied);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Restore OpenGL variables
Toshihiro Shimizu 890ddd
	glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
Toshihiro Shimizu 890ddd
	glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return dataIdx;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void MeshTexturizer::rebindTexture(int texId, const TRaster32P &ras, const TRectD &geom,
Toshihiro Shimizu 890ddd
								   PremultMode premultiplyMode)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QWriteLocker locker(&m_imp->m_lock);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	unbindTexture(texId);
Toshihiro Shimizu 890ddd
	int newTexId = bindTexture(ras, geom, premultiplyMode);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(texId == newTexId);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void MeshTexturizer::unbindTexture(int texId)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QWriteLocker locker(&m_imp->m_lock);
Toshihiro Shimizu 890ddd
	m_imp->m_textureDatas.erase(texId);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
MeshTexturizer::TextureData *MeshTexturizer::getTextureData(int textureId)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QReadLocker locker(&m_imp->m_lock);
Toshihiro Shimizu 890ddd
	return m_imp->getTextureData(textureId);
Toshihiro Shimizu 890ddd
}