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