#if defined(__APPLE__)
#include <OpenGL/OpenGL.h>
#include <OpenGL/Glu.h>
#else
#if defined(JAMBUILD)
#else
#include <gl/glu.h>
#endif
#endif
#include <QtOpenGL/QGLWidget>
#include <QtOpenGL/QGLFormat>
#include <QtOpenGL/QGLContext>
#include "PtexPaintLayerImporter.h"
#include <QtGui/QMessageBox>
#if defined(JAMBUILD)
#include <MudboxIntern/CgFile.h>
#else
#include "CgFile.h"
#endif
IMPLEMENT_CLASS( PtexPaintLayerImporter, PaintLayerImporter,
"pteximporter" );
#define MIN_TRI_UV_SIZE 64
class fCoord {
fCoord(
float a,
float b) : x(a), y(b) {}
fCoord() : x(0), y(0) {}
};
inline bool isUVRightHanded(
const Mesh & mesh,
unsigned face)
{
if ((mesh.Type() == Topology::typeQuadric))
{
TC o = mesh.QuadVertexTC(face, 0);
TC
a = mesh.QuadVertexTC(face, 1) - o;
TC
b = mesh.QuadVertexTC(face, 3) - o;
float zOfCrossProduct = a.u*b.v - b.u*a.v;
return zOfCrossProduct > 0.0f;
}
else
{
if (face >= (mesh.FaceCount() - 1))
return false;
TC o = mesh.TriangleVertexTC(face, 0);
TC a = mesh.TriangleVertexTC(face, 1) - o;
TC b = mesh.TriangleVertexTC(face+1, 2) - o;
float zOfCrossProduct = a.u*b.v - b.u*a.v;
return zOfCrossProduct > 0.0f;
}
}
bool PtexPaintLayerImporter::Prepare(
const QString &sFileName, Mesh *pMesh,
bool bAsMask, bool bSilentMode )
{
if ( !m_Importer )
{
m_Importer = CreateInstance<PtexImporter>();
if ( !m_Importer )
return false;
m_Importer->CreateMeshFromPtex(sFileName, false, bSilentMode);
}
pMesh = pMesh->Geometry()->LowestLevel();
if (!m_Importer->m_FaceMap)
m_Importer->BuildMapsFromBaseMesh(pMesh);
PtexTexture *pT = PtexTexture::open( a.
constData(),
s );
if (!pT) {
if ( !bSilentMode )
Kernel()->Interface()->HUDMessageShow( tr(
"Unable to open PTEX file. Mudbox cannot import it."),
Kernel()->Log(
QString(
"Unable to open PTEX file. Mudbox cannot import it.\n" ));
return false;
}
if (pT->meshType() != Ptex::mt_quad) {
if ( !bSilentMode )
Kernel()->Interface()->HUDMessageShow( tr(
"This PTEX file is not quadrangular. "
"Mudbox cannot import it."),
Kernel()->Log(
QString(
"This PTEX file is not quadrangular. Mudbox cannot import it.\n" ));
pT->release();
return false;
}
if ( pT->numFaces() != m_Importer->m_iSubFaceCount )
{
if ( !bSilentMode )
Kernel()->Interface()->HUDMessageShow( tr(
"This PTEX file has different number of faces than your mesh. "
"Mudbox cannot import it."),
Kernel()->Log(
QString(
"PTEX Import failed: Your mesh: %1 faces, file: %2 faces.\n" )
.arg( pMesh->FaceCount() ).arg( pT->numFaces() ) );
pT->release();
return false;
}
if ( pMesh->FaceCount() != m_Importer->m_iTotalTesselatedFaceCount ) {
if ( !bSilentMode )
Kernel()->Interface()->HUDMessageShow( tr(
"This PTEX file has different number of faces than your mesh. "
"Mudbox cannot import it."),
Kernel()->Log(
QString(
"PTEX Import failed: Your mesh: %1 faces, file: %2 faces.\n" )
.arg( pMesh->FaceCount() ).arg( m_Importer->m_iTotalTesselatedFaceCount ) );
pT->release();
return false;
}
if ((pMesh->Type() == Topology::typeQuadric))
{
if ( m_Importer && !m_Importer->m_allQuads )
{
if ( !bSilentMode )
Kernel()->Interface()->HUDMessageShow( tr(
"This PTEX file is not compatible with your mesh. "
"Mudbox cannot import it. (1)"),
Kernel()->Log(
QString(
"PTEX Import failed: Ptex is mixed quads and tris/n-gons, your mesh is all quads.\n" ));
pT->release();
return false;
}
for (
unsigned int f = 0;
f < pMesh->FaceCount();
f++ )
{
const Ptex::FaceInfo &i = pT->getFaceInfo(
f );
for (
int c = 0;
c < 4;
c++ )
{
int a = i.adjface(
c ), b = i.adjedge(
c ), d = pMesh->QuadAdjacency(
f,
c );
if ( (i.adjface(
c ) == -1 && pMesh->QuadAdjacency(
f,
c ) != 0xffffffff) ||
(i.adjface(
c ) != -1 && pMesh->QuadAdjacency(
f,
c ) != i.adjface(
c )*4+i.adjedge(
c )) )
{
if ( !bSilentMode )
Kernel()->Interface()->HUDMessageShow( tr(
"This PTEX file is not compatible with your mesh. "
"Mudbox cannot import it. (2)"),
Kernel()->Log(
QString(
"PTEX Import failed: Ptex adjacency does not match mudbox mesh adjacency.\n" ));
pT->release();
return false;
}
}
}
}
else
{
if ( m_Importer->m_allQuads )
{
if ( !bSilentMode )
Kernel()->Interface()->HUDMessageShow( tr(
"This PTEX file is not compatible with your mesh. "
"Mudbox cannot import it. (3)"),
Kernel()->Log(
QString(
"PTEX Import failed: Ptex is all quads, mudbox mesh is mixed quads and tris/n-gons.\n" ));
pT->release();
return false;
}
}
if ( pG )
{
unsigned int iMaxSize = 1;
while ( iMaxSize*2 < pG->
UVTileSize() )
iMaxSize *= 2;
for (
int f = 0;
f < pT->numFaces();
f++ )
{
const Ptex::FaceInfo &i = pT->getFaceInfo(
f );
if ( (1u << i.res.ulog2) > iMaxSize || (1u << i.res.vlog2) > iMaxSize )
{
if ( !bSilentMode )
Kernel()->Interface()->HUDMessageShow( tr(
"This PTEX contains faces with too big resolution. "
"Mudbox cannot import it."),
Kernel()->Log(
QString(
"PTEX Import failed: Ptex contains faces bigger than the tile size.\n" ));
pT->release();
return false;
}
}
}
else
{
bool bConvertToPtex = false;
if ( pMesh->UVlessPaintingStatus() == 0 )
{
if ( (
Kernel()->Scene()->ActivePaintLayer() ||
Kernel()->Scene()->ActivePaintLayerGroup() ) && !bAsMask )
{
if ( !bSilentMode )
{
tr("PTEX paint layer import"),
tr("The mesh %1 has UV paint layers. "
"Do you want to convert them to PTEX Layers?").
arg(pMesh->Geometry()->Name()),
pT->release();
return false;
}
}
else
bConvertToPtex = true;
}
else
{
if ( bAsMask )
bConvertToPtex = true;
if ( !bSilentMode )
{
msgBox.setWindowTitle( tr("PTEX paint layer import") );
msgBox.setText(
QString( tr(
"To import a PTEX paint layer, the model %1 must first be set up for PTEX.") ).
arg(pMesh->Geometry()->Name()));
msgBox.exec();
if ( msgBox.clickedButton() == CancelBtn ) {
pT->release();
return false;
}
}
}
}
unsigned int iMaxSize = 1;
while ( (iMaxSize * 2) < pG->UVTileSize() )
iMaxSize *= 2;
for (
int f = 0;
f < pT->numFaces();
f++ )
{
const Ptex::FaceInfo &i = pT->getFaceInfo(
f );
if ( (1u << i.res.ulog2) > iMaxSize || (1u << i.res.vlog2) > iMaxSize )
{
if ( !bSilentMode )
Kernel()->Interface()->HUDMessageShow( tr(
"This PTEX contains faces with too big resolution. "
"Mudbox cannot import it."),
Kernel()->Log(
QString(
"PTEX Import failed: Ptex contains faces bigger than the tile size.\n" ));
pT->release();
return false;
}
}
for ( unsigned int mf = 0; mf < pMesh->FaceCount(); mf++ )
{
const int pf = m_Importer->m_ReverseFaceMap[mf];
unsigned int ppf = m_Importer->m_FaceMap[pf].m_PTexSubfaceID;
const Ptex::FaceInfo &i = pT->getFaceInfo( ppf );
int maxU = i.res.ulog2;
int maxV = i.res.vlog2;
unsigned int boost = 0;
if ( m_Importer->m_FaceMap[pf].m_NumEdges != 4)
{
for (int j = 0; j < m_Importer->m_FaceMap[pf].m_NumEdges; ++j)
{
const Ptex::FaceInfo &ii = pT->getFaceInfo( ppf );
if (ii.res.ulog2 > maxU) maxU = ii.res.ulog2;
if (ii.res.vlog2 > maxV) maxV = ii.res.vlog2;
for (int k = 0; k < 4; ++k)
{
const Ptex::FaceInfo &jj = pT->getFaceInfo( ii.adjface(k) );
if (jj.res.ulog2 > maxU) maxU = jj.res.ulog2;
if (jj.res.vlog2 > maxV) maxV = jj.res.vlog2;
}
ppf++;
}
if ( m_Importer->m_FaceMap[pf].m_NumEdges != 4)
boost = 1;
}
unsigned int nu = 1u << (maxU + boost);
unsigned int nv = 1u << (maxV + boost);
if (nu > iMaxSize) nu = iMaxSize;
if (nv > iMaxSize) nv = iMaxSize;
if ( m_Importer->m_FaceMap[pf].m_NumEdges == 3)
{
if (nu < MIN_TRI_UV_SIZE) nu = MIN_TRI_UV_SIZE;
if (nv < MIN_TRI_UV_SIZE) nv = MIN_TRI_UV_SIZE;
}
else if ( m_Importer->m_FaceMap[pf].m_NumEdges > 4)
{
if (nu < (MIN_TRI_UV_SIZE * 2)) nu = MIN_TRI_UV_SIZE * 2;
if (nv < (MIN_TRI_UV_SIZE * 2)) nv = MIN_TRI_UV_SIZE * 2;
}
pG->
SetFaceSize( mf, nu, nv );
}
pT->release();
}
return true;
}
bool PtexPaintLayerImporter::Import(
const QString &sFileName,
int iFileTypeIndex,
Mesh *pMesh,
TexturePool *pTargetPool )
{
pMesh = pMesh->Geometry()->LowestLevel();
if ( !pG )
{
}
return false;
if ( !m_Importer ) {
m_Importer = CreateInstance<PtexImporter>();
if ( !m_Importer )
return false;
m_Importer->BuildMapsFromBaseMesh(pMesh);
}
if (!m_Importer->m_FaceMap) {
m_Importer->BuildMapsFromBaseMesh(pMesh);
}
if ( !m_Importer ||
(m_Importer && !m_Importer->m_FaceMap) ||
(m_Importer && !m_Importer->m_ReverseFaceMap) ) {
return false;
}
pMesh = pMesh->Geometry()->LowestLevel();
if ( !pMesh->HasExpandedTCs() )
pMesh->CreateExpandedTCs();
Material *pMat = pMesh->Geometry()->Material();
if ( pTargetPool == 0 )
{
for ( unsigned int j = 0; j < pMat->TextureCount(); j++ )
{
TexturePool *pTP = pMat->Texture( j );
if ( pTP->Name() ==
NTR(
"Diffuse") )
{
LayerContainer *pC = dynamic_cast<LayerContainer *>( pTP );
if ( pC )
{
Layer *pL = pC->CreateLayer();
pTargetPool = dynamic_cast<TexturePool *>( pL );
}
pTP->SetRenderMode( TexturePool::renderModeTexture );
}
}
}
{
Kernel()->Interface()->ProgressStart( tr(
"Reading Ptex Texture..."),
m_Importer->m_iSubFaceCount );
pTargetPool->Node::SetName( i.baseName() );
PtexTexture *pT = PtexTexture::open( a.
constData(),
s );
if (!pT) {
Kernel()->Interface()->HUDMessageShow( tr(
"Unable to open PTEX file. "
"Mudbox cannot import it."),
Kernel()->Log(
QString(
"Unable to open PTEX file. Mudbox cannot import it.\n" ));
if ( m_Importer )
{
if (m_Importer->m_FaceMap != 0) {
delete [] m_Importer->m_FaceMap;
m_Importer->m_FaceMap = 0;
}
if (m_Importer->m_ReverseFaceMap != 0) {
delete [] m_Importer->m_ReverseFaceMap;
m_Importer->m_ReverseFaceMap = 0;
}
}
return false;
}
if (pT->meshType() != Ptex::mt_quad) {
Kernel()->Interface()->HUDMessageShow( tr(
"This PTEX file is not quadrangular. "
"Mudbox cannot import it."),
Kernel()->Log(
QString(
"This PTEX file is not quadrangular. Mudbox cannot import it.\n" ));
pT->release();
return false;
}
LoadPtexTexture( pT, pTargetPool, pMesh, pG );
pT->release();
Kernel()->Interface()->ProgressEnd();
}
if ( m_Importer )
{
if (m_Importer->m_FaceMap != 0) {
delete [] m_Importer->m_FaceMap;
m_Importer->m_FaceMap = 0;
}
if (m_Importer->m_ReverseFaceMap != 0) {
delete [] m_Importer->m_ReverseFaceMap;
m_Importer->m_ReverseFaceMap = 0;
}
}
return true;
}
static void drawQuad(float x0, float y0, float x1, float y1,
float x2, float y2, float x3, float y3)
{
glBegin( GL_QUADS );
glColor4f( 1, 1, 1, 1 );
glTexCoord2f( x0, y0 ); glVertex2f( x0, y0 );
glTexCoord2f( x1, y1 ); glVertex2f( x1, y1 );
glTexCoord2f( x2, y2 ); glVertex2f( x2, y2 );
glTexCoord2f( x3, y3 ); glVertex2f( x3, y3 );
glEnd();
}
void PtexPaintLayerImporter::LoadPtexTexture( PtexTexture *pT,
TexturePool *pTP,
const Mesh *pMesh,
{
bool bDescriptorInitialized = false;
static const enum Image::Format aPtexFormats[4] = { Image::e8integer, Image::e16integer,
Image::e16float, Image::e32float };
const unsigned int iTileSize = pG->UVTileSize();
if (!pMesh->m_pTCs) {
Kernel()->Interface()->HUDMessageShow( tr(
"This mesh has no PTEX UVs!"),
return;
}
if (!pG->
getMesh()->m_pTCs) {
Kernel()->Interface()->HUDMessageShow( tr(
"This mesh has no PTEX UVs (2)!"),
return;
}
int unresampledQuads = 0;
int resampledQuads = 0;
int resampledSubFaces = 0;
unsigned int iUS = 0, iUE = 0, iVS = 0, iVE = 0;
for ( unsigned int mf = 0; mf < pMesh->FaceCount(); mf++ )
{
UVGeneratorNode::DimData2 d = pG->
FaceUVArea( mf );
iUE =
Max( iUE, d[0] + 1 );
iVE =
Max( iVE, d[1] + 1 );
}
bool * swapUV = new bool[pMesh->FaceCount()];
for (unsigned int mf = 0; mf < pMesh->FaceCount(); mf++)
swapUV[mf] = !isUVRightHanded(*pMesh, mf);
for ( unsigned int u = iUS; u < iUE; u++ ) {
for (
unsigned int v = iVS;
v < iVE;
v++ )
{
bool quadResampling = false;
if ( !bDescriptorInitialized )
{
bDescriptorInitialized = true;
pTP->SetDefaultTileDescriptor( TexturePool::TileDescriptor( iTileSize, iTileSize, aPtexFormats[pT->dataType()], 4,
NTR(
"ptx"),
Color::transparent ) );
};
Instance<Image> i;
i->Create( iTileSize, iTileSize, 4, aPtexFormats[pT->dataType()], true );
for ( int pf = 0; pf < m_Importer->m_iFaceCount; pf++ )
{
if ( m_Importer->m_FaceMap[pf].m_NumEdges == 4 )
{
const unsigned int mf = m_Importer->m_FaceMap[pf].m_MBFaceID;
const unsigned int ppf = m_Importer->m_FaceMap[pf].m_PTexSubfaceID;
if ( pG->FaceUVArea( mf )[0] != u || pG->FaceUVArea( mf )[1] !=
v )
continue;
if ( (pG->
FaceSizeExponent( mf )[swapUV[mf] ? 1 : 0] != pT->getFaceInfo( ppf ).res.ulog2) ||
(pG->FaceSizeExponent( mf )[swapUV[mf] ? 0 : 1] != pT->getFaceInfo( ppf ).res.vlog2 ) ) {
quadResampling = true;
continue;
}
MB_ASSERT( pG->FaceSizeExponent( mf )[swapUV[mf] ? 1 : 0] == pT->getFaceInfo( ppf ).res.ulog2 );
MB_ASSERT( pG->FaceSizeExponent( mf )[swapUV[mf] ? 0 : 1] == pT->getFaceInfo( ppf ).res.vlog2 );
++unresampledQuads;
UVGeneratorNode::DimData2 d = pG->
FaceUVPosition( mf );
const char iOrientation = pG->
FaceOrientation( mf );
switch ( pT->dataType() )
{
case Ptex::dt_uint8:
p = PrepareFaceBuffer<unsigned char, 255>( pT, ppf, iOrientation, swapUV[mf] );
break;
case Ptex::dt_uint16:
p = PrepareFaceBuffer<unsigned short, 65535>( pT, ppf, iOrientation, swapUV[mf] );
break;
case Ptex::dt_half:
p = PrepareFaceBuffer<half_, 1>( pT, ppf, iOrientation, swapUV[mf] );
break;
case Ptex::dt_float:
p = PrepareFaceBuffer<float, 1>( pT, ppf, iOrientation, swapUV[mf] );
break;
}
i->setTile( d[0]%iTileSize, d[1]%iTileSize, pG->
FaceUVSize( mf )[0], pG->FaceUVSize( mf )[1],
p );
free( p );
Kernel()->Interface()->ProgressAdd();
}
}
Texture *pO = pTP->Tile( AxisAlignedBoundingBox( Vector( u,
v, 0.5 ), Vector( u+1,
v+1, 0.5 ) ) );
pO->CopyFrom( i );
if (!m_Importer->m_allQuads || quadResampling)
{
unsigned char proxyLevel = pO->getProxyLevel();
if (proxyLevel != 0)
pO->setProxyLevel(0);
pO->SetAsRenderTarget();
glFlush();
glPushAttrib( GL_ENABLE_BIT | GL_TEXTURE_BIT );
glDisable( GL_LIGHTING );
glPushMatrix();
glLoadIdentity();
glMatrixMode( GL_PROJECTION );
glPushMatrix();
glLoadIdentity();
glViewport( 0, 0, pO->Width(), pO->Height() );
gluOrtho2D(0, pO->Width(), 0, pO->Height() );
glMatrixMode( GL_MODELVIEW );
glPushMatrix();
glLoadIdentity();
bool dirty = false;
#if defined(JAMBUILD)
CgFile
f(
NTR(
"Shaders/TexturePaint/quad_linear.bin") );
#else
CgFile
f(
NTR(
"Shaders/Simple.cg") );
#endif
for ( int pf = 0; pf < m_Importer->m_iFaceCount; pf++ )
{
const unsigned int mf = m_Importer->m_FaceMap[pf].m_MBFaceID;
const unsigned int ppf = m_Importer->m_FaceMap[pf].m_PTexSubfaceID;
if ( pG->FaceUVArea( mf )[0] != u || pG->FaceUVArea( mf )[1] !=
v )
continue;
const int numEdges = m_Importer->m_FaceMap[pf].m_NumEdges;
if ( numEdges != 4 &&
numEdges > 2 &&
numEdges < MAX_EDGE_COUNT) {
static const float jitterOffsets [3] = { -1.0f, 0.0f, 1.0f };
TC TCs[MAX_EDGE_COUNT+1];
TCs[0] = pMesh->TriangleVertexTC(mf, 0);
TCs[1] = pMesh->TriangleVertexTC(mf, 1);
TCs[2] = pMesh->TriangleVertexTC(mf, 2);
for (int j = 3; j < numEdges; ++j) {
TCs[j] = pMesh->TriangleVertexTC(mf + j - 2, 2);
}
for (int j = 0; j < numEdges; ++j) {
float dd = 0.0f;
TCs[j].u = modff(TCs[j].u, &dd) * iTileSize;
TCs[j].v = modff(TCs[j].
v, &dd) * iTileSize;
}
for (int ii = 0; ii < 3; ++ii) {
for (int jj = 0; jj < 3; ++jj) {
TC tempTCs[MAX_EDGE_COUNT+1];
memcpy(tempTCs, TCs, sizeof(TCs));
for (int kk = 0; kk < numEdges; ++kk) {
tempTCs[kk].u += jitterOffsets[jj];
tempTCs[kk].v += jitterOffsets[ii];
}
fCoord polyCenter(0, 0);
for (int j = 0; j < numEdges; ++j) {
polyCenter.x += TCs[j].u;
polyCenter.y += TCs[j].v;
}
polyCenter.x /= (float) numEdges;
polyCenter.y /= (float) numEdges;
tempTCs[numEdges] = tempTCs[0];
fCoord edgeCenters[MAX_EDGE_COUNT];
for (int j = 0; j < numEdges; ++j) {
edgeCenters[j].x = (tempTCs[j].u + tempTCs[j + 1].u) * 0.5
f;
edgeCenters[j].y = (tempTCs[j].v + tempTCs[j + 1].v) * 0.5
f;
}
for (int subFace = 0; subFace < numEdges; ++subFace) {
const int fId = ppf + subFace;
Ptex::FaceInfo fInfo = pT->getFaceInfo(fId);
const char iOrientation = 0;
void *p = NULL;
switch ( pT->dataType() )
{
case Ptex::dt_uint8:
p = PrepareFaceBuffer<unsigned char, 255>( pT, fId, iOrientation, false );
break;
case Ptex::dt_uint16:
p = PrepareFaceBuffer<unsigned short, 65535>( pT, fId, iOrientation, false );
break;
case Ptex::dt_half:
p = PrepareFaceBuffer<half_, 1>( pT, fId, iOrientation, false );
break;
case Ptex::dt_float:
p = PrepareFaceBuffer<float, 1>( pT, fId, iOrientation, false );
break;
}
const unsigned int iUsize = 1u << fInfo.res.ulog2;
const unsigned int iVsize = 1u << fInfo.res.vlog2;
Instance<Image> i;
i->Create( iUsize, iVsize, 4, aPtexFormats[pT->dataType()], true );
i->setTile( 0, 0, iUsize, iVsize, p );
free( p );
t->Create(iUsize, iVsize, 4, aPtexFormats[pT->dataType()]);
t->CopyFrom(i);
t->Activate();
const int lastIndex = (subFace == 0) ? numEdges-1 : subFace-1;
drawQuad(tempTCs[subFace].u, tempTCs[subFace].
v,
edgeCenters[subFace].
x, edgeCenters[subFace].
y,
polyCenter.x, polyCenter.y,
edgeCenters[lastIndex].x, edgeCenters[lastIndex].y);
}
}
}
fCoord polyCenter(0, 0);
for (int j = 0; j < numEdges; ++j) {
polyCenter.x += TCs[j].u;
polyCenter.y += TCs[j].v;
}
polyCenter.x /= (float) numEdges;
polyCenter.y /= (float) numEdges;
TCs[numEdges] = TCs[0];
fCoord edgeCenters[MAX_EDGE_COUNT];
for (int j = 0; j < numEdges; ++j) {
edgeCenters[j].x = (TCs[j].u + TCs[j + 1].u) * 0.5
f;
edgeCenters[j].y = (TCs[j].v + TCs[j + 1].v) * 0.5
f;
}
for (int subFace = 0; subFace < numEdges; ++subFace) {
const int fId = ppf + subFace;
Ptex::FaceInfo fInfo = pT->getFaceInfo(fId);
const char iOrientation = 0;
void *p = NULL;
switch ( pT->dataType() )
{
case Ptex::dt_uint8:
p = PrepareFaceBuffer<unsigned char, 255>( pT, fId, iOrientation, false );
break;
case Ptex::dt_uint16:
p = PrepareFaceBuffer<unsigned short, 65535>( pT, fId, iOrientation, false );
break;
case Ptex::dt_half:
p = PrepareFaceBuffer<half_, 1>( pT, fId, iOrientation, false );
break;
case Ptex::dt_float:
p = PrepareFaceBuffer<float, 1>( pT, fId, iOrientation, false );
break;
}
const unsigned int iUsize = 1u << fInfo.res.ulog2;
const unsigned int iVsize = 1u << fInfo.res.vlog2;
Instance<Image> i;
i->Create( iUsize, iVsize, 4, aPtexFormats[pT->dataType()], true );
i->setTile( 0, 0, iUsize, iVsize, p );
free( p );
t->Create(iUsize, iVsize, 4, aPtexFormats[pT->dataType()]);
t->CopyFrom(i);
t->Activate();
const int lastIndex = (subFace == 0) ? numEdges-1 : subFace-1;
drawQuad(TCs[subFace].u, TCs[subFace].
v,
edgeCenters[subFace].
x, edgeCenters[subFace].
y,
polyCenter.x, polyCenter.y,
edgeCenters[lastIndex].x, edgeCenters[lastIndex].y);
dirty = true;
++resampledSubFaces;
Kernel()->Interface()->ProgressAdd();
}
} else
if ( numEdges == 4 && quadResampling ) {
if ( (pG->FaceSizeExponent( mf )[swapUV[mf] ? 1 : 0] == pT->getFaceInfo( ppf ).res.ulog2) &&
(pG->FaceSizeExponent( mf )[swapUV[mf] ? 0 : 1] == pT->getFaceInfo( ppf ).res.vlog2 ) ) {
continue;
}
TC TCs[4];
if (m_Importer->m_allQuads) {
TCs[0] = pMesh->QuadVertexTC(mf, 0);
TCs[1] = pMesh->QuadVertexTC(mf, 1);
TCs[2] = pMesh->QuadVertexTC(mf, 2);
TCs[3] = pMesh->QuadVertexTC(mf, 3);
} else {
TCs[0] = pMesh->TriangleVertexTC(mf, 0);
TCs[1] = pMesh->TriangleVertexTC(mf, 1);
TCs[2] = pMesh->TriangleVertexTC(mf, 2);
TCs[3] = pMesh->TriangleVertexTC(mf+1, 2);
}
for (int j = 0; j < 4; ++j) {
float dd = 0.0f;
TCs[j].u = modff(TCs[j].u, &dd) * iTileSize;
TCs[j].v = modff(TCs[j].
v, &dd) * iTileSize;
}
const int fId = ppf;
Ptex::FaceInfo fInfo = pT->getFaceInfo(fId);
const char iOrientation = 0;
void *p = NULL;
switch ( pT->dataType() )
{
case Ptex::dt_uint8:
p = PrepareFaceBuffer<unsigned char, 255>( pT, fId, iOrientation, false );
break;
case Ptex::dt_uint16:
p = PrepareFaceBuffer<unsigned short, 65535>( pT, fId, iOrientation, false );
break;
case Ptex::dt_half:
p = PrepareFaceBuffer<half_, 1>( pT, fId, iOrientation, false );
break;
case Ptex::dt_float:
p = PrepareFaceBuffer<float, 1>( pT, fId, iOrientation, false );
break;
}
const unsigned int iUsize = 1u << fInfo.res.ulog2;
const unsigned int iVsize = 1u << fInfo.res.vlog2;
Instance<Image> i;
i->Create( iUsize, iVsize, 4, aPtexFormats[pT->dataType()], true );
i->setTile( 0, 0, iUsize, iVsize, p );
free( p );
t->Create(iUsize, iVsize, 4, aPtexFormats[pT->dataType()]);
t->CopyFrom(i);
t->Activate();
drawQuad(TCs[0].u, TCs[0].
v, TCs[1].u, TCs[1].v,
TCs[2].u, TCs[2].v, TCs[3].u, TCs[3].v);
dirty = true;
++resampledQuads;
Kernel()->Interface()->ProgressAdd();
}
}
glFlush();
glMatrixMode( GL_MODELVIEW );
glPopMatrix();
glMatrixMode( GL_PROJECTION );
glPopMatrix();
glPopMatrix();
glMatrixMode( GL_MODELVIEW );
glPopAttrib();
pO->RestoreRenderTarget();
if (dirty)
pO->AddDirtyTile(ImgTile(0, 0, iTileSize, iTileSize));
if (proxyLevel != 0)
pO->setProxyLevel(proxyLevel);
}
}
}
delete [] swapUV;
Kernel()->Log(
QString(
"PTEX Import processed %1 quad faces with NO resampling. \n").arg(unresampledQuads));
Kernel()->Log(
QString(
"PTEX Import processed %1 resampled / resized quad faces.\n").arg(resampledQuads));
Kernel()->Log(
QString(
"PTEX Import processed %1 resampled / resized sub-faces.\n\n").arg(resampledSubFaces));
}
template <typename eFormat, const int iMax>
void *PtexPaintLayerImporter::PrepareFaceBuffer( PtexTexture *pTexture,
unsigned int pTexFaceIndex,
char iDirection,
bool bSwapUV )
{
if (bSwapUV && iDirection % 2)
iDirection = 4 - iDirection;
static int NoPremultiply = -1;
if (NoPremultiply == -1) {
NoPremultiply = (
int)(::getenv(
"MUDBOX_NO_PTEX_PREMULTIPLY_ON_IMPORT") != 0);
}
const unsigned int iChannelCount = (
unsigned int)pTexture->numChannels();
const unsigned int iU = 1u << pTexture->getFaceInfo( pTexFaceIndex ).res.ulog2;
const unsigned int iV = 1u << pTexture->getFaceInfo( pTexFaceIndex ).res.vlog2;
eFormat *pTmp = new eFormat[iU*iV*iChannelCount];
pTexture->getData( pTexFaceIndex, pTmp, iU*iChannelCount*sizeof(eFormat) );
eFormat *pBuffer = (eFormat *)malloc(sizeof(eFormat) * 4 * iU * iV);
const float fMax = (float)iMax;
const float invMax = 1.0f / fMax;
for (
unsigned int y = 0;
y < iV;
y++ ) {
for (
unsigned int x = 0;
x < iU;
x++ )
{
unsigned int d = 0;
switch ( iDirection )
{
case 0:
d = bSwapUV ? 4*(
y+
x*iV) : 4*(
x+
y*iU);
break;
case 1:
d = bSwapUV ? 4*(
x+(iV-
y-1)*iU) : 4*(
y+(iU-
x-1)*iV);
break;
case 2:
d = bSwapUV ? 4*((iV-
y-1)+(iU-
x-1)*iV) : 4*((iU-
x-1)+(iV-
y-1)*iU);
break;
case 3:
d = bSwapUV ? 4*((iU-
x-1)+
y*iU) : 4*((iV-
y-1)+
x*iV);
break;
}
while ( c < iChannelCount )
{
pBuffer[d+
c] = pTmp[iChannelCount*(
x+
y*iU)+c];
c++;
}
if ((NoPremultiply == false) && (iChannelCount == 4)) {
float alpha = (float)pBuffer[d+3];
if (iMax != 1) {
pBuffer[d+0] = (eFormat)((((float)pBuffer[d+0] * invMax) * (alpha * invMax)) * fMax);
pBuffer[d+1] = (eFormat)((((float)pBuffer[d+1] * invMax) * (alpha * invMax)) * fMax);
pBuffer[d+2] = (eFormat)((((float)pBuffer[d+2] * invMax) * (alpha * invMax)) * fMax);
} else {
pBuffer[d+0] = pBuffer[d+0] *
alpha;
pBuffer[d+1] = pBuffer[d+1] *
alpha;
pBuffer[d+2] = pBuffer[d+2] *
alpha;
}
} else
{
while ( c < 4 )
{
if ( c == 3 )
else
pBuffer[d+
c] = pBuffer[d];
c++;
}
}
}
}
delete [] pTmp;
return pBuffer;
}