Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonz/plasticdeformerfx.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzLib includes
Toshihiro Shimizu 890ddd
#include "toonz/txsheet.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshleveltypes.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshcell.h"
Toshihiro Shimizu 890ddd
#include "toonz/tcolumnfx.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshlevelcolumn.h"
Toshihiro Shimizu 890ddd
#include "toonz/dpiscale.h"
Toshihiro Shimizu 890ddd
#include "toonz/stage.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzExt includes
Toshihiro Shimizu 890ddd
#include "ext/plasticskeleton.h"
Toshihiro Shimizu 890ddd
#include "ext/plasticdeformerstorage.h"
Toshihiro Shimizu 890ddd
#include "ext/ttexturesstorage.h"
Toshihiro Shimizu 890ddd
#include "ext/plasticvisualsettings.h"
Toshihiro Shimizu 890ddd
#include "ext/meshutils.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzBase includes
Toshihiro Shimizu 890ddd
#include "trenderer.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "tgl.h"
Toshihiro Shimizu 890ddd
#include "tofflinegl.h"
Toshihiro Shimizu 890ddd
#include "tgldisplaylistsmanager.h"
Toshihiro Shimizu 890ddd
#include "tconvert.h"
Toshihiro Shimizu 890ddd
#include "trop.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
FX_IDENTIFIER_IS_HIDDEN(PlasticDeformerFx, "plasticDeformerFx")
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//***************************************************************************************************
Toshihiro Shimizu 890ddd
//    Local namespace
Toshihiro Shimizu 890ddd
//***************************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
std::string toString(const TAffine &aff)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return
Toshihiro Shimizu 890ddd
		//Observe that toString distinguishes + and - 0. That is a problem
Toshihiro Shimizu 890ddd
		//when comparing aliases - so near 0 values are explicitly rounded to 0.
Toshihiro Shimizu 890ddd
		(areAlmostEqual(aff.a11, 0.0) ? "0" : ::toString(aff.a11, 5)) + "," +
Toshihiro Shimizu 890ddd
		(areAlmostEqual(aff.a12, 0.0) ? "0" : ::toString(aff.a12, 5)) + "," +
Toshihiro Shimizu 890ddd
		(areAlmostEqual(aff.a13, 0.0) ? "0" : ::toString(aff.a13, 5)) + "," +
Toshihiro Shimizu 890ddd
		(areAlmostEqual(aff.a21, 0.0) ? "0" : ::toString(aff.a21, 5)) + "," +
Toshihiro Shimizu 890ddd
		(areAlmostEqual(aff.a22, 0.0) ? "0" : ::toString(aff.a22, 5)) + "," +
Toshihiro Shimizu 890ddd
		(areAlmostEqual(aff.a23, 0.0) ? "0" : ::toString(aff.a23, 5));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
std::string toString(SkVD *vd, double sdFrame)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::string result;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (int p = 0; p < SkVD::PARAMS_COUNT; ++p)
Toshihiro Shimizu 890ddd
		result += ::toString(vd->m_params[p]->getValue(sdFrame), 5) + " ";
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return result;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
std::string toString(const PlasticSkeleton::vertex_type &vx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// TODO: Add z and rigidity
Toshihiro Shimizu 890ddd
	return ::toString(vx.P().x, 5) + " " + ::toString(vx.P().y, 5);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
std::string toString(const PlasticSkeletonDeformationP &sd, double sdFrame)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::string result;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const PlasticSkeletonP &skeleton = sd->skeleton(sdFrame);
Toshihiro Shimizu 890ddd
	if (!skeleton || skeleton->empty())
Toshihiro Shimizu 890ddd
		return result;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const tcg::list<plasticskeleton::vertex_type> &vertices = skeleton->vertices();</plasticskeleton::vertex_type>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	tcg::list<plasticskeleton::vertex_type>::const_iterator vt, vEnd(vertices.end());</plasticskeleton::vertex_type>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	result = toString(*vertices.begin());
Toshihiro Shimizu 890ddd
	for (vt = vertices.begin(); vt != vEnd; ++vt) {
Toshihiro Shimizu 890ddd
		result += "; " + toString(*vt);
Toshihiro Shimizu 890ddd
		result += " " + toString(sd->vertexDeformation(vt->name()), sdFrame);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return result;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//***************************************************************************************************
Toshihiro Shimizu 890ddd
//    PlasticDeformerFx  implementation
Toshihiro Shimizu 890ddd
//***************************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PlasticDeformerFx::PlasticDeformerFx()
Toshihiro Shimizu 890ddd
	: TRasterFx()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	addInputPort("source", m_port);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TFx *PlasticDeformerFx::clone(bool recursive) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	PlasticDeformerFx *fx = dynamic_cast<plasticdeformerfx *="">(TFx::clone(recursive));</plasticdeformerfx>
Toshihiro Shimizu 890ddd
	assert(fx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	fx->m_xsh = m_xsh;
Toshihiro Shimizu 890ddd
	fx->m_col = m_col;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return fx;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool PlasticDeformerFx::canHandle(const TRenderSettings &info, double frame)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// Yep. Affines are handled. Well - it's easy, since OpenGL lets you do that directly
Toshihiro Shimizu 890ddd
	// with a glPushMatrix...
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
string PlasticDeformerFx::getAlias(double frame, const TRenderSettings &info) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::string alias(getFxType());
Toshihiro Shimizu 890ddd
	alias += "[";
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_port.isConnected()) {
Toshihiro Shimizu 890ddd
		TRasterFxP ifx = m_port.getFx();
Toshihiro Shimizu 890ddd
		assert(ifx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		alias += ifx->getAlias(frame, info);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TStageObject *meshColumnObj = m_xsh->getStageObject(TStageObjectId::ColumnId(m_col));
Toshihiro Shimizu 890ddd
	const PlasticSkeletonDeformationP &sd = meshColumnObj->getPlasticSkeletonDeformation();
Toshihiro Shimizu 890ddd
	if (sd)
Toshihiro Shimizu 890ddd
		alias += ", " + toString(sd, meshColumnObj->paramsTime(frame));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	alias + "]";
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return alias;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool PlasticDeformerFx::doGetBBox(double frame, TRectD &bbox, const TRenderSettings &info)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!m_port.isConnected())
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// It's hard work to calculate the bounding box of a plastic deformation. Decline.
Toshihiro Shimizu 890ddd
	bbox = TConsts::infiniteRectD;
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PlasticDeformerFx::buildRenderSettings(double frame, TRenderSettings &info)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// As previously pointed out, this fx is able to handle affines. We can, actually, *decide*
Toshihiro Shimizu 890ddd
	// the input reference to work with.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// So, the best choice is to let the *input fx* decide the appropriate reference, by invoking
Toshihiro Shimizu 890ddd
	// its handledAffine() method.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	info.m_bpp = 32; // We need to fix the input to 32-bpp
Toshihiro Shimizu 890ddd
	info.m_affine = m_port->handledAffine(info, frame);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool PlasticDeformerFx::buildTextureDataSl(
Toshihiro Shimizu 890ddd
	double frame, TRenderSettings &info, TAffine &worldLevelToLevelAff)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int row = (int)frame;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Initialize level vars
Toshihiro Shimizu 890ddd
	TLevelColumnFx *lcfx = (TLevelColumnFx *)m_port.getFx();
Toshihiro Shimizu 890ddd
	TXshLevelColumn *texColumn = lcfx->getColumn();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const TXshCell &texCell = texColumn->getCell(row);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXshSimpleLevel *texSl = texCell.getSimpleLevel();
Toshihiro Shimizu 890ddd
	const TFrameId &texFid = texCell.getFrameId();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!texSl || texSl->getType() == MESH_XSHLEVEL)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Build dpi data
Toshihiro Shimizu 890ddd
	TPointD texDpi(texSl->getDpi(texFid, 0));
Toshihiro Shimizu 890ddd
	if (texDpi.x == 0.0 || texDpi.y == 0.0 || texSl->getType() == PLI_XSHLEVEL)
Toshihiro Shimizu 890ddd
		texDpi.x = texDpi.y = Stage::inch;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Build reference transforms data
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// NOTE: TAffine() corresponds to IMAGE coordinates here, not WORLD coordinates. This is achieved
Toshihiro Shimizu 890ddd
	// by removing the level's dpi affine during render-tree build-up (see scenefx.cpp).
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	worldLevelToLevelAff = TScale(texDpi.x / Stage::inch, texDpi.y / Stage::inch);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Initialize input render settings
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// In the case of vector images, in order to retain the image quality required by info.m_affine,
Toshihiro Shimizu 890ddd
	// the scale component is allowed too.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// In the raster image case, we'll use the original image reference IF the affine is a magnification
Toshihiro Shimizu 890ddd
	// (ie the scale is > 1.0) - OTHERWISE, the OpenGL minification filter is too crude since it renders
Toshihiro Shimizu 890ddd
	// a fragment using its 4 adjacent pixels ONLY; in this case, we'll pass the affine below.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const TAffine &handledAff = TRasterFx::handledAffine(info, frame);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (texSl->getType() == PLI_XSHLEVEL) {
Toshihiro Shimizu 890ddd
		info.m_affine = handledAff;
Toshihiro Shimizu 890ddd
		buildRenderSettings(frame, info);
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		info.m_affine = TAffine();
Toshihiro Shimizu 890ddd
		buildRenderSettings(frame, info);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// NOTE: scale = handledAff.a11 / worldLevelToLevelAff.a11
Toshihiro Shimizu 890ddd
		if (handledAff.a11 < worldLevelToLevelAff.a11)
Toshihiro Shimizu 890ddd
			info.m_affine = TScale(handledAff.a11 / worldLevelToLevelAff.a11) * info.m_affine;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool PlasticDeformerFx::buildTextureData(
Toshihiro Shimizu 890ddd
	double frame, TRenderSettings &info, TAffine &worldLevelToLevelAff)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// Common case (typically happen with sub-xsheets)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	buildRenderSettings(frame, info); // Adjust the info
Toshihiro Shimizu 890ddd
	worldLevelToLevelAff = TAffine(); // Reference match
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PlasticDeformerFx::doCompute(TTile &tile, double frame, const TRenderSettings &info)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!m_port.isConnected()) {
Toshihiro Shimizu 890ddd
		tile.getRaster()->clear();
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int row = (int)frame;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Build texture data
Toshihiro Shimizu 890ddd
	TRenderSettings texInfo(info);
Toshihiro Shimizu 890ddd
	TAffine worldTexLevelToTexLevelAff;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (dynamic_cast<tlevelcolumnfx *="">(m_port.getFx())) {</tlevelcolumnfx>
Toshihiro Shimizu 890ddd
		if (!buildTextureDataSl(frame, texInfo, worldTexLevelToTexLevelAff))
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
	} else
Toshihiro Shimizu 890ddd
		buildTextureData(frame, texInfo, worldTexLevelToTexLevelAff);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Initialize mesh level vars
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const TXshCell &meshCell = m_xsh->getCell(row, m_col);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXshSimpleLevel *meshSl = meshCell.getSimpleLevel();
Toshihiro Shimizu 890ddd
	const TFrameId &meshFid = meshCell.getFrameId();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!meshSl || meshSl->getType() != MESH_XSHLEVEL)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Retrieve mesh image and deformation
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TStageObject *meshColumnObj = m_xsh->getStageObject(TStageObjectId::ColumnId(m_col));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TMeshImageP mi(meshSl->getFrame(meshFid, false));
Toshihiro Shimizu 890ddd
	if (!mi)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Retrieve deformation data
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const PlasticSkeletonDeformationP &sd = meshColumnObj->getPlasticSkeletonDeformation();
Toshihiro Shimizu 890ddd
	assert(sd);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double sdFrame = meshColumnObj->paramsTime(frame);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Build dpi data
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD meshDpi(meshSl->getDpi(meshFid, 0));
Toshihiro Shimizu 890ddd
	assert(meshDpi.x != 0.0 && meshDpi.y != 0.0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Build reference transforms data
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Build affines
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const TAffine &imageToTextureAff = texInfo.m_affine;
Toshihiro Shimizu 890ddd
	const TAffine &worldTexLevelToWorldMeshAff = m_texPlacement;
Toshihiro Shimizu 890ddd
	const TAffine &meshToWorldMeshAff = TScale(Stage::inch / meshDpi.x, Stage::inch / meshDpi.y);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const TAffine &meshToTexLevelAff = worldTexLevelToTexLevelAff * worldTexLevelToWorldMeshAff.inv() * meshToWorldMeshAff;
Toshihiro Shimizu 890ddd
	const TAffine &meshToTextureAff = imageToTextureAff * meshToTexLevelAff;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Retrieve deformer data
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TScale worldMeshToMeshAff(meshDpi.x / Stage::inch, meshDpi.y / Stage::inch);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::auto_ptr<const plasticdeformerdatagroup=""> dataGroup(</const>
Toshihiro Shimizu 890ddd
		PlasticDeformerStorage::instance()->processOnce(
Toshihiro Shimizu 890ddd
			sdFrame, mi.getPointer(), sd.getPointer(), sd->skeletonId(sdFrame), worldMeshToMeshAff));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Build texture
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Build the mesh's bounding box and map it to input reference
Toshihiro Shimizu 890ddd
	TRectD meshBBox(meshToTextureAff * mi->getBBox());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Now, build the tile's geometry
Toshihiro Shimizu 890ddd
	TRectD texBBox;
Toshihiro Shimizu 890ddd
	m_port->getBBox(frame, texBBox, texInfo);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRectD bbox = texBBox * meshBBox;
Toshihiro Shimizu 890ddd
	if (bbox.getLx() <= 0.0 || bbox.getLy() <= 0.0)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bbox.x0 = tfloor(bbox.x0);
Toshihiro Shimizu 890ddd
	bbox.y0 = tfloor(bbox.y0);
Toshihiro Shimizu 890ddd
	bbox.x1 = tceil(bbox.x1);
Toshihiro Shimizu 890ddd
	bbox.y1 = tceil(bbox.y1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TDimension tileSize(tround(bbox.getLx()), tround(bbox.getLy()));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Then, compute the input image
Toshihiro Shimizu 890ddd
	TTile inTile;
Toshihiro Shimizu 890ddd
	m_port->allocateAndCompute(inTile, bbox.getP00(), tileSize, TRasterP(), frame, texInfo);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Draw the textured mesh
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		// Prepare texture
Toshihiro Shimizu 890ddd
		TRaster32P tex(inTile.getRaster());
Toshihiro Shimizu 890ddd
		TRop::depremultiply(tex); // Textures must be stored depremultiplied.
Toshihiro Shimizu 890ddd
								  // See docs about the tglDraw() below.
Toshihiro Shimizu 890ddd
		static TAtomicVar var;
Toshihiro Shimizu 890ddd
		const std::string &texId = "render_tex " + ::toString((int)++var);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Prepare an OpenGL context
Toshihiro Shimizu 890ddd
		std::auto_ptr<tofflinegl> context(new TOfflineGL(tile.getRaster()->getSize()));</tofflinegl>
Toshihiro Shimizu 890ddd
		context->makeCurrent();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Load texture into the context
Toshihiro Shimizu 890ddd
		TTexturesStorage *ts = TTexturesStorage::instance();
Toshihiro Shimizu 890ddd
		const DrawableTextureDataP &texData = ts->loadTexture(texId, tex, bbox);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Draw
Toshihiro Shimizu 890ddd
		glPushMatrix();
Toshihiro Shimizu 890ddd
		tglMultMatrix(TTranslation(-tile.m_pos) * info.m_affine *
Toshihiro Shimizu 890ddd
					  meshToWorldMeshAff);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		glEnable(GL_BLEND);
Toshihiro Shimizu 890ddd
		glEnable(GL_TEXTURE_2D);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		tglDraw(*mi, *texData, meshToTextureAff, *dataGroup);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Retrieve drawing and copy to output tile
Toshihiro Shimizu 890ddd
		context->getRaster(tile.getRaster());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Cleanup
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// No need to disable stuff - the context dies here
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// ts->unloadTexture(texId);                                // Auto-released due to display list destruction
Toshihiro Shimizu 890ddd
		context->doneCurrent();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PlasticDeformerFx::doDryCompute(TRectD &rect, double frame, const TRenderSettings &info)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!m_port.isConnected())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int row = (int)frame;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRenderSettings texInfo(info);
Toshihiro Shimizu 890ddd
	TAffine worldTexLevelToTexLevelAff;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (dynamic_cast<tlevelcolumnfx *="">(m_port.getFx())) {</tlevelcolumnfx>
Toshihiro Shimizu 890ddd
		if (!buildTextureDataSl(frame, texInfo, worldTexLevelToTexLevelAff))
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
	} else
Toshihiro Shimizu 890ddd
		buildTextureData(frame, texInfo, worldTexLevelToTexLevelAff);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const TXshCell &meshCell = m_xsh->getCell(row, m_col);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TXshSimpleLevel *meshSl = meshCell.getSimpleLevel();
Toshihiro Shimizu 890ddd
	const TFrameId &meshFid = meshCell.getFrameId();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!meshSl || meshSl->getType() == MESH_XSHLEVEL)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TStageObject *meshColumnObj = m_xsh->getStageObject(TStageObjectId::ColumnId(m_col));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TMeshImageP mi(meshSl->getFrame(meshFid, false));
Toshihiro Shimizu 890ddd
	if (!mi)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const PlasticSkeletonDeformationP &sd = meshColumnObj->getPlasticSkeletonDeformation();
Toshihiro Shimizu 890ddd
	assert(sd);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD meshDpi(meshSl->getDpi(meshFid, 0));
Toshihiro Shimizu 890ddd
	assert(meshDpi.x != 0.0 && meshDpi.y != 0.0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const TAffine &textureToImageAff = texInfo.m_affine;
Toshihiro Shimizu 890ddd
	const TAffine &worldImageToWorldMeshAff = m_texPlacement;
Toshihiro Shimizu 890ddd
	const TAffine &meshToWorldMeshAff = TScale(Stage::inch / meshDpi.x, Stage::inch / meshDpi.y);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const TAffine &meshToTextureAff =
Toshihiro Shimizu 890ddd
		textureToImageAff.inv() * worldTexLevelToTexLevelAff * worldImageToWorldMeshAff.inv() * meshToWorldMeshAff;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Build the mesh's bounding box and map it to input reference
Toshihiro Shimizu 890ddd
	TRectD meshBBox(meshToTextureAff * mi->getBBox());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Now, build the tile's geometry
Toshihiro Shimizu 890ddd
	TRectD texBBox;
Toshihiro Shimizu 890ddd
	m_port->getBBox(frame, texBBox, texInfo);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRectD bbox = texBBox * meshBBox;
Toshihiro Shimizu 890ddd
	if (bbox.getLx() <= 0.0 || bbox.getLy() <= 0.0)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bbox.x0 = tfloor(bbox.x0);
Toshihiro Shimizu 890ddd
	bbox.y0 = tfloor(bbox.y0);
Toshihiro Shimizu 890ddd
	bbox.x1 = tceil(bbox.x1);
Toshihiro Shimizu 890ddd
	bbox.y1 = tceil(bbox.y1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_port->dryCompute(bbox, frame, texInfo);
Toshihiro Shimizu 890ddd
}