|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "trasterfx.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Core-system includes
|
|
Toshihiro Shimizu |
890ddd |
#include "tsystem.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tthreadmessage.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Fx basics
|
|
Toshihiro Shimizu |
890ddd |
#include "tparamcontainer.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tbasefx.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tfxattributes.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Images components
|
|
Toshihiro Shimizu |
890ddd |
#include "timagecache.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "trasterimage.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "trop.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Optimization components
|
|
Toshihiro Shimizu |
890ddd |
#include "trenderresourcemanager.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tfxcachemanager.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "trenderer.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Diagnostics
|
|
Toshihiro Shimizu |
890ddd |
//#define DIAGNOSTICS
|
|
Toshihiro Shimizu |
890ddd |
#ifdef DIAGNOSTICS
|
|
Toshihiro Shimizu |
890ddd |
#include "diagnostics.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
#endif // DIAGNOSTICS
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//===================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
namespace {
|
|
Shinya Kitaoka |
120a6e |
inline bool areEqual(const TRasterFxRenderDataP &d1,
|
|
Shinya Kitaoka |
120a6e |
const TRasterFxRenderDataP &d2) {
|
|
Shinya Kitaoka |
120a6e |
return (*d1 == *d2);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
inline int myCeil(double x) {
|
|
Shinya Kitaoka |
120a6e |
return ((x - (int)(x)) > TConsts::epsilon ? (int)(x) + 1 : (int)(x));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
inline TRect myConvert(const TRectD &r, TPointD &dp) {
|
|
Shinya Kitaoka |
120a6e |
TRect ri(tfloor(r.x0), tfloor(r.y0), myCeil(r.x1), myCeil(r.y1));
|
|
Shinya Kitaoka |
120a6e |
dp.x = r.x0 - ri.x0;
|
|
Shinya Kitaoka |
120a6e |
dp.y = r.y0 - ri.y0;
|
|
Shinya Kitaoka |
120a6e |
assert(dp.x >= 0 && dp.y >= 0);
|
|
Shinya Kitaoka |
120a6e |
return ri;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
inline bool myIsEmpty(const TRectD &r) {
|
|
Shinya Kitaoka |
120a6e |
return r.getLx() < 1 || r.getLy() < 1;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
inline TRect myConvert(const TRectD &rect) {
|
|
Shinya Kitaoka |
120a6e |
return TRect(tround(rect.x0), tround(rect.y0), tround(rect.x1) - 1,
|
|
Shinya Kitaoka |
120a6e |
tround(rect.y1) - 1);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
inline TRectD myConvert(const TRect &rect) {
|
|
Shinya Kitaoka |
120a6e |
return TRectD(rect.x0, rect.y0, rect.x1 + 1, rect.y1 + 1);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
inline void enlargeToI(TRectD &r) {
|
|
Shinya Kitaoka |
120a6e |
TRectD temp(tfloor(r.x0), tfloor(r.y0), tceil(r.x1), tceil(r.y1));
|
|
Shinya Kitaoka |
120a6e |
// NOTE: If we enlarge a TConsts::infiniteRectD or one which trespass
|
|
Shinya Kitaoka |
120a6e |
// ints' numerical bounds, the rect may become empty.
|
|
Shinya Kitaoka |
120a6e |
if (!myIsEmpty(temp)) r = temp;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Calculates the 2-norm of the passed affine A - that is, the max modulus
|
|
Shinya Kitaoka |
120a6e |
// of A*A's eigenvalues (*A being the adjoint).
|
|
Shinya Kitaoka |
120a6e |
double norm2(const TAffine &aff) {
|
|
Shinya Kitaoka |
120a6e |
double a11 = aff.a11 * aff.a11 + aff.a12 * aff.a12;
|
|
Shinya Kitaoka |
120a6e |
double a12 = aff.a11 * aff.a21 + aff.a12 * aff.a22;
|
|
Shinya Kitaoka |
120a6e |
double a21 = aff.a21 * aff.a11 + aff.a22 * aff.a12;
|
|
Shinya Kitaoka |
120a6e |
double a22 = aff.a21 * aff.a21 + aff.a22 * aff.a22;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
double a11plusa22 = a11 + a22;
|
|
Shinya Kitaoka |
120a6e |
double delta = sq(a11 - a22) + 4 * a12 * a21;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
delta = sqrt(delta);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
double eig1 = a11plusa22 + delta;
|
|
Shinya Kitaoka |
120a6e |
double eig2 = a11plusa22 - delta;
|
|
Shinya Kitaoka |
120a6e |
return std::max(sqrt(eig1 / 2.0), sqrt(eig2 / 2.0));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
inline int getResampleFilterRadius(const TRenderSettings &info) {
|
|
Shinya Kitaoka |
120a6e |
switch (info.m_quality) {
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::StandardResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
return 1;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::ImprovedResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
return 2;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::HighResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
return 3;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::Triangle_FilterResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
return 1;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::Mitchell_FilterResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
return 2;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::Cubic5_FilterResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
return 2;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::Cubic75_FilterResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
return 2;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::Cubic1_FilterResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
return 2;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::Hann2_FilterResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
return 2;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::Hann3_FilterResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
return 3;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::Hamming2_FilterResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
return 2;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::Hamming3_FilterResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
return 3;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::Lanczos2_FilterResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
return 2;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::Lanczos3_FilterResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
return 3;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::Gauss_FilterResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
return 2;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::ClosestPixel_FilterResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
return 1;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::Bilinear_FilterResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
return 1;
|
|
Shinya Kitaoka |
120a6e |
default:
|
|
Shinya Kitaoka |
120a6e |
assert(false);
|
|
Shinya Kitaoka |
120a6e |
return -1;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
inline QString traduce(const TRectD &rect) {
|
|
Shinya Kitaoka |
120a6e |
return "[" + QString::number(rect.x0) + " " + QString::number(rect.y0) + " " +
|
|
Shinya Kitaoka |
120a6e |
QString::number(rect.x1) + " " + QString::number(rect.y1) + "]";
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
inline QString traduce(const TRect &rect) {
|
|
Shinya Kitaoka |
120a6e |
return "[" + QString::number(rect.x0) + " " + QString::number(rect.y0) + " " +
|
|
Shinya Kitaoka |
120a6e |
QString::number(rect.x1) + " " + QString::number(rect.y1) + "]";
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
inline QString qTraduce(const TAffine &aff) {
|
|
Shinya Kitaoka |
120a6e |
return "[" + QString::number(aff.a11, 'g', 15) + "," +
|
|
Shinya Kitaoka |
120a6e |
QString::number(aff.a12, 'g', 15) + "," +
|
|
Shinya Kitaoka |
120a6e |
QString::number(aff.a13, 'g', 15) + "," +
|
|
Shinya Kitaoka |
120a6e |
QString::number(aff.a21, 'g', 15) + "," +
|
|
Shinya Kitaoka |
120a6e |
QString::number(aff.a22, 'g', 15) + "," +
|
|
Shinya Kitaoka |
120a6e |
QString::number(aff.a23, 'g', 15) + "]";
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
inline std::string traduce(const TAffine &aff) {
|
|
Shinya Kitaoka |
120a6e |
return
|
|
Shinya Kitaoka |
120a6e |
// Observe that toString distinguishes + and - 0. That is a problem
|
|
Shinya Kitaoka |
120a6e |
// when comparing aliases - so near 0 values are explicitly rounded to 0.
|
|
Shinya Kitaoka |
120a6e |
(areAlmostEqual(aff.a11, 0.0) ? "0" : ::to_string(aff.a11, 5)) + "," +
|
|
Shinya Kitaoka |
120a6e |
(areAlmostEqual(aff.a12, 0.0) ? "0" : ::to_string(aff.a12, 5)) + "," +
|
|
Shinya Kitaoka |
120a6e |
(areAlmostEqual(aff.a13, 0.0) ? "0" : ::to_string(aff.a13, 5)) + "," +
|
|
Shinya Kitaoka |
120a6e |
(areAlmostEqual(aff.a21, 0.0) ? "0" : ::to_string(aff.a21, 5)) + "," +
|
|
Shinya Kitaoka |
120a6e |
(areAlmostEqual(aff.a22, 0.0) ? "0" : ::to_string(aff.a22, 5)) + "," +
|
|
Shinya Kitaoka |
120a6e |
(areAlmostEqual(aff.a23, 0.0) ? "0" : ::to_string(aff.a23, 5));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
shun-iwasawa |
78a7b2 |
} // namespace
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// The following should be cleared - and its functionalities surrendered
|
|
Shinya Kitaoka |
120a6e |
// directly
|
|
Shinya Kitaoka |
120a6e |
// to an appropriate resource manager...
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
//! Declares an image to be kept in cache until the render ends or is canceled.
|
|
Shinya Kitaoka |
120a6e |
void addRenderCache(const std::string &alias, TImageP image) {
|
|
Shinya Kitaoka |
120a6e |
TFxCacheManager::instance()->add(alias, image);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
//! The inverse function to addRenderCache.
|
|
Shinya Kitaoka |
120a6e |
void removeRenderCache(const std::string &alias) {
|
|
Shinya Kitaoka |
120a6e |
TFxCacheManager::instance()->remove(alias);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//==============================================================================
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
// TrFx (Affine Transformer Fx)
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
//! Internal fx node which applies the implicit affine stored in the
|
|
Shinya Kitaoka |
120a6e |
//! TRenderSettings structure,
|
|
Toshihiro Shimizu |
890ddd |
//! replacing the old TRasterFx::doCompute.
|
|
Shinya Kitaoka |
d1f6c4 |
class TrFx final : public TBaseRasterFx {
|
|
Shinya Kitaoka |
120a6e |
FX_DECLARATION(TrFx)
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRasterFx *m_fx;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
TrFx() {}
|
|
Shinya Kitaoka |
120a6e |
~TrFx() {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void setFx(TRasterFx *fx) { m_fx = fx; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
473e70 |
bool isCachable() const override {
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Shinya Kitaoka |
120a6e |
} // Currently cachable as a test. Observe that it was NOT in Toonz 6.1
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
38fd86 |
bool canHandle(const TRenderSettings &info, double frame) override {
|
|
Shinya Kitaoka |
38fd86 |
return true;
|
|
Shinya Kitaoka |
38fd86 |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
38fd86 |
std::string getAlias(double frame,
|
|
Shinya Kitaoka |
38fd86 |
const TRenderSettings &info) const override {
|
|
Shinya Kitaoka |
120a6e |
// NOTE: TrFx are not present at this recursive level. Affines dealing is
|
|
Shinya Kitaoka |
120a6e |
// currently handled by inserting the
|
|
Shinya Kitaoka |
120a6e |
// rendering affine AFTER a getAlias call. Ever.
|
|
Shinya Kitaoka |
120a6e |
std::string alias = getFxType();
|
|
Shinya Kitaoka |
120a6e |
return alias + "[" + m_fx->getAlias(frame, info) + "]";
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
38fd86 |
bool doGetBBox(double frame, TRectD &bBox,
|
|
Shinya Kitaoka |
38fd86 |
const TRenderSettings &info) override {
|
|
Shinya Kitaoka |
120a6e |
// NOTE: TrFx are not present at this recursive level. Affines dealing is
|
|
Shinya Kitaoka |
120a6e |
// still handled by TGeometryFxs here....
|
|
Shinya Kitaoka |
120a6e |
return m_fx->doGetBBox(frame, bBox, info);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
38fd86 |
void doCompute(TTile &tile, double frame,
|
|
Shinya Kitaoka |
38fd86 |
const TRenderSettings &info) override {
|
|
Shinya Kitaoka |
120a6e |
const TRectD &rectOut =
|
|
Shinya Kitaoka |
120a6e |
myConvert(tile.getRaster()->getBounds()) + tile.m_pos;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRectD rectIn;
|
|
Shinya Kitaoka |
120a6e |
TRenderSettings infoIn(info);
|
|
Shinya Kitaoka |
120a6e |
TAffine appliedAff;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (!buildInput(rectOut, frame, info, rectIn, infoIn, appliedAff)) return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
const TRect &rectInI = myConvert(rectIn);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// rasIn e' un raster dello stesso tipo di tile.getRaster()
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TTile inTile;
|
|
Shinya Kitaoka |
120a6e |
m_fx->allocateAndCompute(inTile, rectIn.getP00(),
|
|
Shinya Kitaoka |
120a6e |
TDimension(rectInI.getLx(), rectInI.getLy()),
|
|
Shinya Kitaoka |
120a6e |
tile.getRaster(), frame, infoIn);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
infoIn.m_affine = appliedAff;
|
|
Shinya Kitaoka |
120a6e |
TRasterFx::applyAffine(tile, inTile, infoIn);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
38fd86 |
void doDryCompute(TRectD &rect, double frame,
|
|
Shinya Kitaoka |
38fd86 |
const TRenderSettings &info) override {
|
|
Shinya Kitaoka |
120a6e |
TRectD rectIn;
|
|
Shinya Kitaoka |
120a6e |
TRenderSettings infoIn(info);
|
|
Shinya Kitaoka |
120a6e |
TAffine appliedAff;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (!buildInput(rect, frame, info, rectIn, infoIn, appliedAff)) return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
m_fx->dryCompute(rectIn, frame, infoIn);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
//-----------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
int getMemoryRequirement(const TRectD &rect, double frame,
|
|
Shinya Kitaoka |
473e70 |
const TRenderSettings &info) override {
|
|
Shinya Kitaoka |
120a6e |
TRectD rectIn;
|
|
Shinya Kitaoka |
120a6e |
TRenderSettings infoIn(info);
|
|
Shinya Kitaoka |
120a6e |
TAffine appliedAff;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (!buildInput(rect, frame, info, rectIn, infoIn, appliedAff)) return 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
return TRasterFx::memorySize(rectIn, info.m_bpp);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
private:
|
|
Shinya Kitaoka |
120a6e |
bool buildInput(const TRectD &rectOut, double frame,
|
|
Shinya Kitaoka |
120a6e |
const TRenderSettings &infoOut, TRectD &rectIn,
|
|
Shinya Kitaoka |
120a6e |
TRenderSettings &infoIn, TAffine &appliedAff) {
|
|
Shinya Kitaoka |
120a6e |
if (myIsEmpty(rectOut)) return false;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Build the affines
|
|
Shinya Kitaoka |
120a6e |
infoIn.m_affine = m_fx->handledAffine(infoOut, frame);
|
|
Shinya Kitaoka |
120a6e |
appliedAff = infoOut.m_affine * infoIn.m_affine.inv();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Quick fix - prevent near-singular transforms.
|
|
Shinya Kitaoka |
120a6e |
// NOTE: This check **SHOULD BE REMOVED** and dealt with at the RESAMPLING
|
|
Shinya Kitaoka |
120a6e |
// level.
|
|
Shinya Kitaoka |
120a6e |
// Observe how the tolerance value is quite arbitrary! Yeah I know
|
|
Shinya Kitaoka |
120a6e |
// it's shameful... :(
|
|
Shinya Kitaoka |
120a6e |
if (fabs(appliedAff.det()) < 1e-6) // TO BE REMOVED
|
|
Shinya Kitaoka |
120a6e |
return false; // TO BE REMOVED
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Build the input rect
|
|
Shinya Kitaoka |
120a6e |
const TAffine &appliedAffInv = appliedAff.inv();
|
|
Shinya Kitaoka |
120a6e |
int filterRadius = getResampleFilterRadius(infoOut);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRectD bbox;
|
|
Shinya Kitaoka |
120a6e |
m_fx->getBBox(frame, bbox, infoIn);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
rectIn =
|
|
Shinya Kitaoka |
120a6e |
((appliedAffInv * rectOut)
|
|
Shinya Kitaoka |
120a6e |
.enlarge(
|
|
Shinya Kitaoka |
120a6e |
filterRadius) + // The filter size applies in input during
|
|
Shinya Kitaoka |
120a6e |
(appliedAffInv * rectOut.enlarge(filterRadius))) *
|
|
Shinya Kitaoka |
120a6e |
bbox; // magnifications, and in output during
|
|
Shinya Kitaoka |
120a6e |
// minifications. Thus, they basically cumulate.
|
|
Shinya Kitaoka |
120a6e |
if (myIsEmpty(rectIn)) return false;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
enlargeToI(rectIn);
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
FX_IDENTIFIER_IS_HIDDEN(TrFx, "trFx")
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//==============================================================================
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
// FxResourceBuilder
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// This class is the internal interface with the cache regarding intermediate
|
|
Shinya Kitaoka |
120a6e |
// render
|
|
Shinya Kitaoka |
120a6e |
// results. Please refer to the ResourceBuilder documentation in
|
|
Shinya Kitaoka |
120a6e |
// tfxcachemanager.cpp
|
|
Shinya Kitaoka |
d1f6c4 |
class FxResourceBuilder final : public ResourceBuilder {
|
|
Shinya Kitaoka |
120a6e |
TRasterFxP m_rfx;
|
|
Shinya Kitaoka |
120a6e |
double m_frame;
|
|
Shinya Kitaoka |
120a6e |
const TRenderSettings *m_rs;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TTile *m_outTile;
|
|
Shinya Kitaoka |
120a6e |
TTile *m_currTile;
|
|
Shinya Kitaoka |
120a6e |
TTile m_newTile;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRectD m_outRect;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
FxResourceBuilder(const std::string &resourceName, const TRasterFxP &fx,
|
|
Shinya Kitaoka |
120a6e |
const TRenderSettings &rs, double frame)
|
|
Shinya Kitaoka |
120a6e |
: ResourceBuilder(resourceName, fx.getPointer(), frame, rs)
|
|
Shinya Kitaoka |
120a6e |
, m_rfx(fx)
|
|
Shinya Kitaoka |
120a6e |
, m_frame(frame)
|
|
Shinya Kitaoka |
120a6e |
, m_rs(&rs)
|
|
Shinya Kitaoka |
120a6e |
, m_currTile(0) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
inline void build(TTile &tile);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
protected:
|
|
Shinya Kitaoka |
473e70 |
void simCompute(const TRectD &rect) override {
|
|
Shinya Kitaoka |
120a6e |
TRectD rectCpy(
|
|
Shinya Kitaoka |
120a6e |
rect); // Why the hell dryCompute(..) has non-const TRectD& input ????
|
|
Shinya Kitaoka |
120a6e |
m_rfx->doDryCompute(rectCpy, m_frame, *m_rs);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void buildTileToCalculate(const TRectD &tileRect);
|
|
Shinya Kitaoka |
473e70 |
void compute(const TRectD &tileRect) override;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
473e70 |
void upload(TCacheResourceP &resource) override;
|
|
Shinya Kitaoka |
473e70 |
bool download(TCacheResourceP &resource) override;
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
inline void FxResourceBuilder::build(TTile &tile) {
|
|
Shinya Kitaoka |
120a6e |
m_outTile = &tile;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TDimension dim(tile.getRaster()->getSize());
|
|
Shinya Kitaoka |
120a6e |
m_outRect = TRectD(tile.m_pos, TDimensionD(dim.lx, dim.ly));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
ResourceBuilder::build(m_outRect);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void FxResourceBuilder::buildTileToCalculate(const TRectD &tileGeom) {
|
|
Shinya Kitaoka |
120a6e |
if (tileGeom == m_outRect) {
|
|
Shinya Kitaoka |
120a6e |
m_currTile = m_outTile;
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
m_newTile.m_pos = tileGeom.getP00();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRasterP outRas(m_outTile->getRaster());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// If possible, try to reuse outRas's buffer.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TDimension outputSize(outRas->getSize());
|
|
Shinya Kitaoka |
120a6e |
TDimension requiredSize(tceil(tileGeom.getLx()), tceil(tileGeom.getLy()));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRasterP ras;
|
|
Shinya Kitaoka |
120a6e |
if (outputSize.lx >= requiredSize.lx && outputSize.ly >= requiredSize.ly) {
|
|
Shinya Kitaoka |
120a6e |
// Reuse fxOutput's buffer
|
|
Shinya Kitaoka |
120a6e |
TRect rect(0, 0, requiredSize.lx - 1, requiredSize.ly - 1);
|
|
Shinya Kitaoka |
120a6e |
ras = outRas->extract(rect);
|
|
Shinya Kitaoka |
120a6e |
ras->clear();
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
ras = outRas->create(requiredSize.lx, requiredSize.ly);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
m_newTile.setRaster(ras);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
m_currTile = &m_newTile;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void FxResourceBuilder::compute(const TRectD &tileRect) {
|
|
Toshihiro Shimizu |
890ddd |
#ifdef DIAGNOSTICS
|
|
Shinya Kitaoka |
120a6e |
TStopWatch sw;
|
|
Shinya Kitaoka |
120a6e |
sw.start();
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
buildTileToCalculate(tileRect);
|
|
Shinya Kitaoka |
120a6e |
m_rfx->doCompute(*m_currTile, m_frame, *m_rs);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef DIAGNOSTICS
|
|
Shinya Kitaoka |
120a6e |
sw.stop();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
DIAGNOSTICS_THRSET("FComputeTime", sw.getTotalTime());
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void FxResourceBuilder::upload(TCacheResourceP &resource) {
|
|
Shinya Kitaoka |
120a6e |
resource->upload(*m_currTile);
|
|
Shinya Kitaoka |
120a6e |
if (m_currTile == &m_newTile) m_newTile.setRaster(0);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
bool FxResourceBuilder::download(TCacheResourceP &resource) {
|
|
Shinya Kitaoka |
120a6e |
// In case the output tile was used to calculate the fx, avoid downloading
|
|
Shinya Kitaoka |
120a6e |
if (m_currTile == m_outTile) return true;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
return resource->downloadAll(*m_outTile);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//==============================================================================
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
// TRasterFx
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
class TRasterFx::TRasterFxImp {
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
bool m_cacheEnabled;
|
|
Shinya Kitaoka |
120a6e |
TTile m_cachedTile;
|
|
Shinya Kitaoka |
120a6e |
double m_frame;
|
|
Shinya Kitaoka |
120a6e |
bool m_isEnabled;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRenderSettings m_info;
|
|
Shinya Kitaoka |
120a6e |
std::string m_interactiveCacheId;
|
|
Shinya Kitaoka |
120a6e |
mutable TThread::Mutex m_mutex; // brutto
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRasterFxImp() : m_cacheEnabled(false), m_isEnabled(true), m_cachedTile(0) {}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
~TRasterFxImp() {}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
void enableCache(bool on) {
|
|
Shinya Kitaoka |
120a6e |
QMutexLocker sl(&m_mutex);
|
|
Shinya Kitaoka |
120a6e |
m_cacheEnabled = on;
|
|
Shinya Kitaoka |
120a6e |
if (!m_cacheEnabled) {
|
|
Shinya Kitaoka |
120a6e |
m_interactiveCacheId = "";
|
|
Shinya Kitaoka |
120a6e |
m_frame = 0;
|
|
Shinya Kitaoka |
120a6e |
m_info = TRenderSettings();
|
|
Shinya Kitaoka |
120a6e |
m_cachedTile.setRaster(0);
|
|
Shinya Kitaoka |
120a6e |
m_cachedTile.m_pos = TPointD();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
bool isCacheEnabled() const { return m_cacheEnabled; }
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
bool isEnabled() const {
|
|
Shinya Kitaoka |
120a6e |
QMutexLocker sl(&m_mutex); // a che serve??
|
|
Shinya Kitaoka |
120a6e |
return m_isEnabled;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
void enable(bool on) {
|
|
Shinya Kitaoka |
120a6e |
QMutexLocker sl(&m_mutex); // a che serve
|
|
Shinya Kitaoka |
120a6e |
m_isEnabled = on;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRasterFx::TRasterFx() : m_rasFxImp(new TRasterFxImp) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRasterFx::~TRasterFx() { delete m_rasFxImp; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TAffine TRasterFx::handledAffine(const TRenderSettings &info, double frame) {
|
|
Shinya Kitaoka |
120a6e |
return (info.m_affine.a11 == info.m_affine.a22 && info.m_affine.a12 == 0 &&
|
|
Shinya Kitaoka |
120a6e |
info.m_affine.a21 == 0 && info.m_affine.a13 == 0 &&
|
|
Shinya Kitaoka |
120a6e |
info.m_affine.a23 == 0)
|
|
Shinya Kitaoka |
120a6e |
? info.m_affine
|
|
Shinya Kitaoka |
120a6e |
: TScale(norm2(info.m_affine));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
bool TRasterFx::getBBox(double frame, TRectD &bBox,
|
|
Shinya Kitaoka |
120a6e |
const TRenderSettings &info) {
|
|
Shinya Kitaoka |
120a6e |
bool ret = doGetBBox(frame, bBox, info);
|
|
shun-iwasawa |
e526d5 |
if (!bBox.isEmpty()) { // TODO: check if bbox can always be empty when ret ==
|
|
shun-iwasawa |
e526d5 |
// false
|
|
shun-iwasawa |
e526d5 |
bBox = info.m_affine * bBox;
|
|
shun-iwasawa |
e526d5 |
enlargeToI(bBox);
|
|
shun-iwasawa |
e526d5 |
}
|
|
Shinya Kitaoka |
120a6e |
return ret;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TRasterFx::transform(double frame, int port, const TRectD &rectOnOutput,
|
|
Shinya Kitaoka |
120a6e |
const TRenderSettings &infoOnOutput,
|
|
Shinya Kitaoka |
120a6e |
TRectD &rectOnInput, TRenderSettings &infoOnInput) {
|
|
Shinya Kitaoka |
120a6e |
rectOnInput = rectOnOutput;
|
|
Shinya Kitaoka |
120a6e |
infoOnInput = infoOnOutput;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
int TRasterFx::memorySize(const TRectD &rect, int bpp) {
|
|
Shinya Kitaoka |
120a6e |
if (rect.x1 <= rect.x0 || rect.y1 <= rect.y0) return 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
return (unsigned long)(rect.getLx() + 1) * (unsigned long)(rect.getLy() + 1) *
|
|
Shinya Kitaoka |
120a6e |
(bpp >> 3) >>
|
|
Shinya Kitaoka |
120a6e |
20;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
//! Specifies the approximate size (in MegaBytes) of the maximum allocation
|
|
Shinya Kitaoka |
120a6e |
//! instance that this fx
|
|
Toshihiro Shimizu |
890ddd |
//! will need to perform in order to render the passed input.
|
|
Shinya Kitaoka |
120a6e |
//! This method should be reimplemented in order to make the Toonz rendering
|
|
Shinya Kitaoka |
120a6e |
//! process aware of
|
|
Toshihiro Shimizu |
890ddd |
//! the use of big raster memory chunks, at least.
|
|
Shinya Kitaoka |
120a6e |
//! Observe that the passed tile geometry is implicitly already allocated
|
|
Shinya Kitaoka |
120a6e |
//! <\i> for the fx output.
|
|
Toshihiro Shimizu |
890ddd |
//! \n
|
|
Shinya Kitaoka |
120a6e |
//! The default implementation returns 0, assuming that the passed implicit
|
|
Shinya Kitaoka |
120a6e |
//! memory size is passed
|
|
Shinya Kitaoka |
120a6e |
//! below in node computation without further allocation of resources. Fxs can
|
|
Shinya Kitaoka |
120a6e |
//! reimplement this
|
|
Toshihiro Shimizu |
890ddd |
//! to -1 to explicitly disable the Toonz's smart memory handling.
|
|
Toshihiro Shimizu |
890ddd |
//! \n \n
|
|
Shinya Kitaoka |
120a6e |
//! \note The rendering process ensures that the passed render settings are \a
|
|
Shinya Kitaoka |
120a6e |
//! handled
|
|
Toshihiro Shimizu |
890ddd |
//! by the fx before this function is invoked - do not waste code for it.
|
|
Toshihiro Shimizu |
890ddd |
//! \sa TRasterFx::memorySize and TRasterFx::canHandle methods.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
int TRasterFx::getMemoryRequirement(const TRectD &rect, double frame,
|
|
Shinya Kitaoka |
120a6e |
const TRenderSettings &info) {
|
|
Shinya Kitaoka |
120a6e |
return 0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
std::string TRasterFx::getAlias(double frame,
|
|
Shinya Kitaoka |
120a6e |
const TRenderSettings &info) const {
|
|
Shinya Kitaoka |
120a6e |
std::string alias = getFxType();
|
|
Shinya Kitaoka |
120a6e |
alias += "[";
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// alias degli effetti connessi alle porte di input separati da virgole
|
|
Shinya Kitaoka |
120a6e |
// una porta non connessa da luogo a un alias vuoto (stringa vuota)
|
|
Shinya Kitaoka |
120a6e |
int i;
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < getInputPortCount(); i++) {
|
|
Shinya Kitaoka |
120a6e |
TFxPort *port = getInputPort(i);
|
|
Shinya Kitaoka |
120a6e |
if (port->isConnected()) {
|
|
Shinya Kitaoka |
120a6e |
TRasterFxP ifx = port->getFx();
|
|
Shinya Kitaoka |
120a6e |
assert(ifx);
|
|
Shinya Kitaoka |
120a6e |
alias += ifx->getAlias(frame, info);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
alias += ",";
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// alias dei valori dei parametri dell'effetto al frame dato
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < getParams()->getParamCount(); i++) {
|
|
Shinya Kitaoka |
120a6e |
TParam *param = getParams()->getParam(i);
|
|
Shinya Kitaoka |
120a6e |
alias += param->getName() + "=" + param->getValueAlias(frame, 3);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
alias += "]";
|
|
Shinya Kitaoka |
120a6e |
return alias;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TRasterFx::dryCompute(TRectD &rect, double frame,
|
|
Shinya Kitaoka |
120a6e |
const TRenderSettings &info) {
|
|
Shinya Kitaoka |
120a6e |
if (checkActiveTimeRegion() && !getActiveTimeRegion().contains(frame)) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (!getAttributes()->isEnabled() || !m_rasFxImp->isEnabled()) {
|
|
Shinya Kitaoka |
120a6e |
if (getInputPortCount() == 0) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TFxPort *port = getInputPort(getPreferredInputPort());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (port->isConnected())
|
|
Shinya Kitaoka |
120a6e |
TRasterFxP(port->getFx())->dryCompute(rect, frame, info);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// If the input tile has a fractionary position, it is passed to the
|
|
Shinya Kitaoka |
120a6e |
// rendersettings' accumulated affine.
|
|
Shinya Kitaoka |
120a6e |
TPoint intTilePos(tfloor(rect.x0), tfloor(rect.y0));
|
|
Shinya Kitaoka |
120a6e |
TPointD fracTilePos(rect.x0 - intTilePos.x, rect.y0 - intTilePos.y);
|
|
Shinya Kitaoka |
120a6e |
TPointD fracInfoTranslation(info.m_affine.a13 - fracTilePos.x,
|
|
Shinya Kitaoka |
120a6e |
info.m_affine.a23 - fracTilePos.y);
|
|
Shinya Kitaoka |
120a6e |
TPoint intInfoTranslation(tfloor(fracInfoTranslation.x),
|
|
Shinya Kitaoka |
120a6e |
tfloor(fracInfoTranslation.y));
|
|
Shinya Kitaoka |
120a6e |
TPointD newTilePos(intTilePos.x - intInfoTranslation.x,
|
|
Shinya Kitaoka |
120a6e |
intTilePos.y - intInfoTranslation.y);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (rect.getP00() != newTilePos) {
|
|
Shinya Kitaoka |
120a6e |
TRenderSettings newInfo(info);
|
|
Shinya Kitaoka |
120a6e |
newInfo.m_affine.a13 = fracInfoTranslation.x - intInfoTranslation.x;
|
|
Shinya Kitaoka |
120a6e |
newInfo.m_affine.a23 = fracInfoTranslation.y - intInfoTranslation.y;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRectD newRect(newTilePos, rect.getSize());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
dryCompute(newRect, frame, newInfo);
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// If the fx can't handle the whole affine passed with the TRenderSettings,
|
|
Shinya Kitaoka |
120a6e |
// the part
|
|
Shinya Kitaoka |
120a6e |
// of it that the fx can't handle is retained and applied by an affine
|
|
Shinya Kitaoka |
120a6e |
// transformer fx (TrFx)
|
|
Shinya Kitaoka |
120a6e |
// after the node has been computed.
|
|
Shinya Kitaoka |
120a6e |
bool canHandleAffine =
|
|
Shinya Kitaoka |
120a6e |
canHandle(info, frame) || (handledAffine(info, frame) == info.m_affine);
|
|
Shinya Kitaoka |
120a6e |
if (!info.m_affine.isIdentity() && !canHandleAffine) {
|
|
Shinya Kitaoka |
120a6e |
TrFx *transformerFx = new TrFx;
|
|
Shinya Kitaoka |
120a6e |
TFxP locker(transformerFx);
|
|
Shinya Kitaoka |
120a6e |
transformerFx->setFx(this);
|
|
Shinya Kitaoka |
120a6e |
transformerFx->dryCompute(rect, frame, info);
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
std::string alias = getAlias(frame, info) + "[" + ::traduce(info.m_affine) +
|
|
Shinya Kitaoka |
120a6e |
"][" + std::to_string(info.m_bpp) + "]";
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int renderStatus =
|
|
Shinya Kitaoka |
120a6e |
TRenderer::instance().getRenderStatus(TRenderer::renderId());
|
|
Shinya Kitaoka |
120a6e |
TFxCacheManager *cacheManager = TFxCacheManager::instance();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (renderStatus == TRenderer::FIRSTRUN) {
|
|
Shinya Kitaoka |
120a6e |
TRectD bbox;
|
|
Shinya Kitaoka |
120a6e |
// ret = getBBox... puo' darsi che l'enlarge del trFx (o naturale del bbox)
|
|
Shinya Kitaoka |
120a6e |
// faccia
|
|
Shinya Kitaoka |
120a6e |
// diventare TRectD() non vuoto!!
|
|
Shinya Kitaoka |
120a6e |
getBBox(frame, bbox, info);
|
|
Shinya Kitaoka |
120a6e |
enlargeToI(bbox);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRectD interestingRect(rect * bbox);
|
|
Shinya Kitaoka |
120a6e |
if (myIsEmpty(interestingRect)) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Declare the tile to the tiles manager
|
|
Shinya Kitaoka |
120a6e |
ResourceBuilder::declareResource(alias, this, interestingRect, frame, info);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
doDryCompute(interestingRect, frame, info);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
TRectD bbox;
|
|
Shinya Kitaoka |
120a6e |
getBBox(frame, bbox, info);
|
|
Shinya Kitaoka |
120a6e |
enlargeToI(bbox);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRectD interestingRect(rect * bbox);
|
|
Shinya Kitaoka |
120a6e |
if (myIsEmpty(interestingRect)) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Invoke the fx-specific simulation process
|
|
Shinya Kitaoka |
120a6e |
FxResourceBuilder rBuilder(alias, this, info, frame);
|
|
Shinya Kitaoka |
120a6e |
rBuilder.simBuild(interestingRect);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
//! Declares the computation scheme of this fx for rendering optimization
|
|
Shinya Kitaoka |
120a6e |
//! purposes.
|
|
Shinya Kitaoka |
120a6e |
//! This is an important function of the Toonz rendering API, and should be
|
|
Shinya Kitaoka |
120a6e |
//! reimplemented
|
|
Toshihiro Shimizu |
890ddd |
//! with the necessary care.
|
|
Toshihiro Shimizu |
890ddd |
//! The Toonz rendering process makes use of this function to enact most of the
|
|
Toshihiro Shimizu |
890ddd |
//! optimization steps about the fx computation, in particular fx caching.
|
|
Toshihiro Shimizu |
890ddd |
//! A correct implementation of this method should follow these rules:
|
|
Shinya Kitaoka |
120a6e |
//! The invocation of child node computations should be faithfully
|
|
Shinya Kitaoka |
120a6e |
//! reproduced.
|
|
Toshihiro Shimizu |
890ddd |
//! TRasterFx::compute and TRasterFx::allocateAndCompute calls have to be
|
|
Toshihiro Shimizu |
890ddd |
//! translated to TRasterFx::dryCompute calls.
|
|
Shinya Kitaoka |
120a6e |
//! This fx is intended for precomputation stage, so the hard rendering
|
|
Shinya Kitaoka |
120a6e |
//! code
|
|
Toshihiro Shimizu |
890ddd |
//! should be skipped here.
|
|
Shinya Kitaoka |
120a6e |
//! By default, this method raises a dryCompute call to each input port in
|
|
Shinya Kitaoka |
120a6e |
//! increasing
|
|
Shinya Kitaoka |
120a6e |
//! order, using the TRasterFx::transform method to identify the tiles to be
|
|
Shinya Kitaoka |
120a6e |
//! passed
|
|
Toshihiro Shimizu |
890ddd |
//! on input precomputation.
|
|
Shinya Kitaoka |
120a6e |
void TRasterFx::doDryCompute(TRectD &rect, double frame,
|
|
Shinya Kitaoka |
120a6e |
const TRenderSettings &info) {
|
|
Shinya Kitaoka |
120a6e |
int inputPortCount = getInputPortCount();
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < inputPortCount; ++i) {
|
|
Shinya Kitaoka |
120a6e |
TFxPort *port = getInputPort(i);
|
|
Shinya Kitaoka |
120a6e |
if (port->isConnected()) {
|
|
Shinya Kitaoka |
120a6e |
TRectD rectOnInput;
|
|
Shinya Kitaoka |
120a6e |
TRenderSettings infoOnInput;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRasterFxP fx = port->getFx();
|
|
Shinya Kitaoka |
120a6e |
transform(frame, i, rect, info, rectOnInput, infoOnInput);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (!myIsEmpty(rectOnInput))
|
|
Shinya Kitaoka |
120a6e |
fx->dryCompute(rectOnInput, frame, infoOnInput);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! This is an overloaded member function that deals with
|
|
Toshihiro Shimizu |
890ddd |
//! the allocation of an input tile before invoking the TRasterFx::compute
|
|
Toshihiro Shimizu |
890ddd |
//! method on it.
|
|
Shinya Kitaoka |
120a6e |
void TRasterFx::allocateAndCompute(TTile &tile, const TPointD &pos,
|
|
Shinya Kitaoka |
120a6e |
const TDimension &size, TRasterP templateRas,
|
|
Shinya Kitaoka |
120a6e |
double frame, const TRenderSettings &info) {
|
|
Shinya Kitaoka |
120a6e |
if (templateRas) {
|
|
Shinya Kitaoka |
120a6e |
TRaster32P ras32(templateRas);
|
|
Shinya Kitaoka |
120a6e |
TRaster64P ras64(templateRas);
|
|
Shinya Kitaoka |
120a6e |
templateRas = 0; // Release the reference to templateRas before allocation
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRasterP tileRas;
|
|
Shinya Kitaoka |
120a6e |
if (ras32)
|
|
Shinya Kitaoka |
120a6e |
tileRas = TRaster32P(size.lx, size.ly);
|
|
Shinya Kitaoka |
120a6e |
else if (ras64)
|
|
Shinya Kitaoka |
120a6e |
tileRas = TRaster64P(size.lx, size.ly);
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
assert(false);
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
tile.setRaster(tileRas);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
if (info.m_bpp == 32) {
|
|
Shinya Kitaoka |
120a6e |
TRaster32P tileRas(size.lx, size.ly);
|
|
Shinya Kitaoka |
120a6e |
tile.setRaster(tileRas);
|
|
Shinya Kitaoka |
120a6e |
} else if (info.m_bpp == 64) {
|
|
Shinya Kitaoka |
120a6e |
TRaster64P tileRas(size.lx, size.ly);
|
|
Shinya Kitaoka |
120a6e |
tile.setRaster(tileRas);
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
assert(false);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
tile.m_pos = pos;
|
|
Shinya Kitaoka |
120a6e |
compute(tile, frame, info);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! This method supplies the actual fx rendering code.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TRasterFx::compute(TTile &tile, double frame,
|
|
Shinya Kitaoka |
120a6e |
const TRenderSettings &info) {
|
|
Shinya Kitaoka |
120a6e |
// If the render was aborted, avoid everything
|
|
Shinya Kitaoka |
120a6e |
// if(TRenderer::instance().isAborted(TRenderer::renderId()))
|
|
Shinya Kitaoka |
120a6e |
// throw TException("Render canceled");
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (checkActiveTimeRegion() && !getActiveTimeRegion().contains(frame)) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (!getAttributes()->isEnabled() || !m_rasFxImp->isEnabled()) {
|
|
Shinya Kitaoka |
120a6e |
if (getInputPortCount() == 0) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TFxPort *port = getInputPort(0);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// la porta 0 non deve essere una porta di controllo
|
|
Shinya Kitaoka |
120a6e |
assert(port->isaControlPort() == false);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (port->isConnected()) {
|
|
Shinya Kitaoka |
120a6e |
TRasterFxP(port->getFx())->compute(tile, frame, info);
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// If the input tile has a fractionary position, it is passed to the
|
|
Shinya Kitaoka |
120a6e |
// rendersettings' accumulated affine. At the same time, the integer part of
|
|
Shinya Kitaoka |
120a6e |
// such affine is transferred to the tile.
|
|
Shinya Kitaoka |
120a6e |
TPoint intTilePos(tfloor(tile.m_pos.x), tfloor(tile.m_pos.y));
|
|
Shinya Kitaoka |
120a6e |
TPointD fracTilePos(tile.m_pos.x - intTilePos.x, tile.m_pos.y - intTilePos.y);
|
|
Shinya Kitaoka |
120a6e |
TPointD fracInfoTranslation(info.m_affine.a13 - fracTilePos.x,
|
|
Shinya Kitaoka |
120a6e |
info.m_affine.a23 - fracTilePos.y);
|
|
Shinya Kitaoka |
120a6e |
TPoint intInfoTranslation(tfloor(fracInfoTranslation.x),
|
|
Shinya Kitaoka |
120a6e |
tfloor(fracInfoTranslation.y));
|
|
Shinya Kitaoka |
120a6e |
TPointD newTilePos(intTilePos.x - intInfoTranslation.x,
|
|
Shinya Kitaoka |
120a6e |
intTilePos.y - intInfoTranslation.y);
|
|
Shinya Kitaoka |
120a6e |
/*-- 入力タイルの位置が、小数値を持っていた場合 --*/
|
|
Shinya Kitaoka |
120a6e |
if (tile.m_pos != newTilePos) {
|
|
Shinya Kitaoka |
120a6e |
/*-- RenderSettingsのaffine行列に位置ずれを足しこむ --*/
|
|
Shinya Kitaoka |
120a6e |
TRenderSettings newInfo(info);
|
|
Shinya Kitaoka |
120a6e |
newInfo.m_affine.a13 = fracInfoTranslation.x - intInfoTranslation.x;
|
|
Shinya Kitaoka |
120a6e |
newInfo.m_affine.a23 = fracInfoTranslation.y - intInfoTranslation.y;
|
|
Shinya Kitaoka |
120a6e |
/*-- タイルの位置は整数値にする --*/
|
|
Shinya Kitaoka |
120a6e |
TPointD oldPos(tile.m_pos);
|
|
Shinya Kitaoka |
120a6e |
tile.m_pos = newTilePos;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
compute(tile, frame, newInfo);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
tile.m_pos = oldPos;
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
bool canHandleAffine =
|
|
Shinya Kitaoka |
120a6e |
canHandle(info, frame) || (handledAffine(info, frame) == info.m_affine);
|
|
Shinya Kitaoka |
120a6e |
if (!info.m_affine.isIdentity() && !canHandleAffine) {
|
|
Shinya Kitaoka |
120a6e |
TrFx *transformerFx = new TrFx;
|
|
Shinya Kitaoka |
120a6e |
TFxP locker(transformerFx);
|
|
Shinya Kitaoka |
120a6e |
transformerFx->setFx(this);
|
|
Shinya Kitaoka |
120a6e |
transformerFx->compute(tile, frame, info);
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Retrieve tile's geometry
|
|
Shinya Kitaoka |
120a6e |
TRectD tilePlacement = myConvert(tile.getRaster()->getBounds()) + tile.m_pos;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Build the fx result alias (in other words, its name)
|
|
Shinya Kitaoka |
120a6e |
std::string alias = getAlias(frame, info) + "[" + ::traduce(info.m_affine) +
|
|
Shinya Kitaoka |
120a6e |
"][" + std::to_string(info.m_bpp) +
|
|
Shinya Kitaoka |
120a6e |
"]"; // To be moved below
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRectD bbox;
|
|
Shinya Kitaoka |
120a6e |
getBBox(frame, bbox, info);
|
|
Shinya Kitaoka |
120a6e |
enlargeToI(bbox);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRectD interestingRect(tilePlacement * bbox);
|
|
Shinya Kitaoka |
120a6e |
if (myIsEmpty(interestingRect)) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Extract the interesting tile from requested one
|
|
Shinya Kitaoka |
120a6e |
TTile interestingTile;
|
|
Shinya Kitaoka |
120a6e |
interestingTile.m_pos = interestingRect.getP00();
|
|
Shinya Kitaoka |
120a6e |
TRect interestingRectI(myConvert(interestingRect - tilePlacement.getP00()));
|
|
Shinya Kitaoka |
120a6e |
interestingTile.setRaster(tile.getRaster()->extract(interestingRectI));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef DIAGNOSTICS
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// 1. Push fx name on call stack
|
|
Shinya Kitaoka |
120a6e |
QString fxName = QString::fromStdString(getDeclaration()->getId());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
DIAGNOSTICS_PUSH("FName", fxName);
|
|
Shinya Kitaoka |
120a6e |
DIAGNOSTICS_THRSET("FComputeTime", 0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TStopWatch sw;
|
|
Shinya Kitaoka |
120a6e |
sw.start();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Invoke the fx-specific computation process
|
|
Shinya Kitaoka |
120a6e |
FxResourceBuilder rBuilder(alias, this, info, frame);
|
|
Shinya Kitaoka |
120a6e |
rBuilder.build(interestingTile);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef DIAGNOSTICS
|
|
Shinya Kitaoka |
120a6e |
sw.stop();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
QString countsStr("#ftimes.txt | 4. " + fxName + " | 4. Calls count");
|
|
Shinya Kitaoka |
120a6e |
QString fxStr("fcum_4. " + fxName);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
long computeTime = DIAGNOSTICS_THRGET("FComputeTime");
|
|
Shinya Kitaoka |
120a6e |
long fxTime = sw.getTotalTime();
|
|
Shinya Kitaoka |
120a6e |
long fxCumulativeTime = DIAGNOSTICS_GLOGET(fxStr);
|
|
Shinya Kitaoka |
120a6e |
long count = DIAGNOSTICS_GET(countsStr);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// 2. Add this time to fx time, and subtract it from parent time
|
|
Shinya Kitaoka |
120a6e |
DIAGNOSTICS_GLOADD(fxStr, computeTime);
|
|
Shinya Kitaoka |
120a6e |
DIAGNOSTICS_ADD(countsStr, 1);
|
|
Shinya Kitaoka |
120a6e |
DIAGNOSTICS_SET("#ftimes.txt | 4. " + fxName + " | 3. Mean time",
|
|
Shinya Kitaoka |
120a6e |
(fxCumulativeTime + computeTime) / (count + 1));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
DIAGNOSTICS_POP("FName", 1);
|
|
Shinya Kitaoka |
120a6e |
QString parentFxName = DIAGNOSTICS_STACKGET("FName");
|
|
Shinya Kitaoka |
120a6e |
if (!parentFxName.isEmpty())
|
|
Shinya Kitaoka |
120a6e |
DIAGNOSTICS_GLOADD("fcum_4. " + parentFxName, -fxTime);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
DIAGNOSTICS_GLOADD("fcum_03. Cached Fxs Retrieval", fxTime - computeTime);
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef WRITEIMAGES
|
|
Shinya Kitaoka |
120a6e |
static int iCount = 0;
|
|
Shinya Kitaoka |
120a6e |
QString qPath("C:\\butta\\image_" +
|
|
Shinya Kitaoka |
120a6e |
QString::number(++iCount).rightJustified(3, '0') + ".tif");
|
|
Shinya Kitaoka |
120a6e |
TImageWriter::save(TFilePath(qPath.toStdWString()), tile.getRaster());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (iCount >= 35) int aa = 1;
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
/*
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
tryCanceled:
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
//if(TRenderer::instance().isAborted(TRenderer::renderId()))
|
|
Shinya Kitaoka |
120a6e |
// throw TException("Render canceled");
|
|
Shinya Kitaoka |
120a6e |
;
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRasterP TRasterFx::applyAffine(TTile &tileOut, const TTile &tileIn,
|
|
Shinya Kitaoka |
120a6e |
const TRenderSettings &info) {
|
|
Shinya Kitaoka |
120a6e |
TAffine aff = info.m_affine;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRasterP src_ras = tileIn.getRaster();
|
|
Shinya Kitaoka |
120a6e |
TRasterP dst_ras = tileOut.getRaster();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (aff.isTranslation()) {
|
|
Shinya Kitaoka |
120a6e |
// Check the tile origins' fractionary displacement
|
|
Shinya Kitaoka |
120a6e |
TPointD diff(tileOut.m_pos - tileIn.m_pos - TPointD(aff.a13, aff.a23));
|
|
Shinya Kitaoka |
120a6e |
double fracX = diff.x - tfloor(diff.x);
|
|
Shinya Kitaoka |
120a6e |
double fracY = diff.y - tfloor(diff.y);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if ((fracX < 0.01 || fracX > 0.99) && (fracY < 0.01 || fracY > 0.99)) {
|
|
Shinya Kitaoka |
120a6e |
// Just copy part of tileIn into tileOut
|
|
Shinya Kitaoka |
120a6e |
TRect geomIn(src_ras->getBounds());
|
|
Shinya Kitaoka |
120a6e |
TRect geomOut(dst_ras->getBounds());
|
|
Shinya Kitaoka |
120a6e |
TPoint diffI(convert(diff));
|
|
Shinya Kitaoka |
120a6e |
geomIn -= diffI;
|
|
Shinya Kitaoka |
120a6e |
geomOut += diffI;
|
|
Shinya Kitaoka |
120a6e |
geomIn *= dst_ras->getBounds();
|
|
Shinya Kitaoka |
120a6e |
geomOut *= src_ras->getBounds();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (geomIn.isEmpty()) return dst_ras;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRasterP rasIn(src_ras->extract(geomOut));
|
|
Shinya Kitaoka |
120a6e |
TRasterP rasOut(dst_ras->extract(geomIn));
|
|
Shinya Kitaoka |
120a6e |
TRop::copy(rasOut, rasIn);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
return dst_ras;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRectD rectIn = myConvert(src_ras->getBounds()) + tileIn.m_pos;
|
|
Shinya Kitaoka |
120a6e |
TRectD rectOut = myConvert(dst_ras->getBounds()) + tileOut.m_pos;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRectD rectInAfter = aff * myConvert(src_ras->getBounds());
|
|
Shinya Kitaoka |
120a6e |
TAffine rasterAff = TTranslation((aff * rectIn).getP00() - rectOut.getP00() -
|
|
Shinya Kitaoka |
120a6e |
rectInAfter.getP00()) *
|
|
Shinya Kitaoka |
120a6e |
aff;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRop::ResampleFilterType qual;
|
|
Shinya Kitaoka |
120a6e |
switch (info.m_quality) {
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::StandardResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
qual = TRop::Triangle;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::ImprovedResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
qual = TRop::Hann2;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::HighResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
qual = TRop::Hamming3;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::Triangle_FilterResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
qual = TRop::Triangle;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::Mitchell_FilterResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
qual = TRop::Mitchell;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::Cubic5_FilterResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
qual = TRop::Cubic5;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::Cubic75_FilterResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
qual = TRop::Cubic75;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::Cubic1_FilterResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
qual = TRop::Cubic1;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::Hann2_FilterResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
qual = TRop::Hann2;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::Hann3_FilterResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
qual = TRop::Hann3;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::Hamming2_FilterResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
qual = TRop::Hamming2;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::Hamming3_FilterResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
qual = TRop::Hamming3;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::Lanczos2_FilterResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
qual = TRop::Lanczos2;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::Lanczos3_FilterResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
qual = TRop::Lanczos3;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::Gauss_FilterResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
qual = TRop::Gauss;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::ClosestPixel_FilterResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
qual = TRop::ClosestPixel;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
case TRenderSettings::Bilinear_FilterResampleQuality:
|
|
Shinya Kitaoka |
120a6e |
qual = TRop::Bilinear;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
default:
|
|
Shinya Kitaoka |
120a6e |
assert(false);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRop::resample(dst_ras, src_ras, rasterAff, qual);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
return dst_ras;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
bool TRasterFx::isCacheEnabled() const { return m_rasFxImp->m_cacheEnabled; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//--------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TRasterFx::enableCache(bool on) { m_rasFxImp->enableCache(on); }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//==============================================================================
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
// TRenderSettings
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TRenderSettings::TRenderSettings()
|
|
Shinya Kitaoka |
120a6e |
: m_gamma(1)
|
|
Shinya Kitaoka |
120a6e |
, m_timeStretchFrom(25)
|
|
Shinya Kitaoka |
120a6e |
, m_timeStretchTo(25)
|
|
Shinya Kitaoka |
120a6e |
, m_stereoscopicShift(0.05)
|
|
Shinya Kitaoka |
120a6e |
, m_bpp(32)
|
|
Shinya Kitaoka |
120a6e |
, m_maxTileSize((std::numeric_limits<int>::max)())</int>
|
|
Shinya Kitaoka |
120a6e |
, m_shrinkX(1)
|
|
Shinya Kitaoka |
120a6e |
, m_shrinkY(1)
|
|
Shinya Kitaoka |
120a6e |
, m_quality(StandardResampleQuality)
|
|
Shinya Kitaoka |
120a6e |
, m_fieldPrevalence(NoField)
|
|
Shinya Kitaoka |
120a6e |
, m_stereoscopic(false)
|
|
Shinya Kitaoka |
120a6e |
, m_isSwatch(false)
|
|
Shinya Kitaoka |
120a6e |
, m_applyShrinkToViewer(false)
|
|
Shinya Kitaoka |
120a6e |
, m_userCachable(true)
|
|
shun-iwasawa |
78a7b2 |
, m_isCanceled(NULL)
|
|
shun-iwasawa |
78a7b2 |
, m_getFullSizeBBox(false) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRenderSettings::~TRenderSettings() {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
std::string TRenderSettings::toString() const {
|
|
Shinya Kitaoka |
120a6e |
std::string ss =
|
|
Shinya Kitaoka |
120a6e |
std::to_string(m_bpp) + ";" + std::to_string(m_quality) + ";" +
|
|
Shinya Kitaoka |
120a6e |
std::to_string(m_gamma) + ";" + std::to_string(m_timeStretchFrom) + ";" +
|
|
Shinya Kitaoka |
120a6e |
std::to_string(m_timeStretchTo) + ";" +
|
|
Shinya Kitaoka |
120a6e |
std::to_string(m_fieldPrevalence) + ";" + std::to_string(m_shrinkX) +
|
|
Shinya Kitaoka |
120a6e |
"," + std::to_string(m_shrinkY) + ";" + std::to_string(m_affine.a11) +
|
|
Shinya Kitaoka |
120a6e |
"," + std::to_string(m_affine.a12) + "," + std::to_string(m_affine.a13) +
|
|
Shinya Kitaoka |
120a6e |
"," + std::to_string(m_affine.a21) + "," + std::to_string(m_affine.a22) +
|
|
Shinya Kitaoka |
120a6e |
"," + std::to_string(m_affine.a23) + ";" + std::to_string(m_maxTileSize) +
|
|
Shinya Kitaoka |
120a6e |
";" + std::to_string(m_isSwatch) + ";" + std::to_string(m_userCachable) +
|
|
Shinya Kitaoka |
120a6e |
";{";
|
|
Shinya Kitaoka |
120a6e |
if (!m_data.empty()) {
|
|
Shinya Kitaoka |
120a6e |
ss += m_data[0]->toString();
|
|
Shinya Kitaoka |
120a6e |
for (int i = 1; i < (int)m_data.size(); i++)
|
|
Shinya Kitaoka |
120a6e |
ss += "," + m_data[i]->toString();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
ss += "}";
|
|
Shinya Kitaoka |
120a6e |
return ss;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
bool TRenderSettings::operator==(const TRenderSettings &rhs) const {
|
|
Shinya Kitaoka |
120a6e |
if (m_bpp != rhs.m_bpp || m_quality != rhs.m_quality ||
|
|
Shinya Kitaoka |
120a6e |
m_fieldPrevalence != rhs.m_fieldPrevalence ||
|
|
Shinya Kitaoka |
120a6e |
m_stereoscopic != rhs.m_stereoscopic ||
|
|
Shinya Kitaoka |
120a6e |
m_stereoscopicShift != rhs.m_stereoscopicShift ||
|
|
Shinya Kitaoka |
120a6e |
m_gamma != rhs.m_gamma || m_timeStretchFrom != rhs.m_timeStretchFrom ||
|
|
Shinya Kitaoka |
120a6e |
m_timeStretchTo != rhs.m_timeStretchTo || m_shrinkX != rhs.m_shrinkX ||
|
|
Shinya Kitaoka |
120a6e |
m_shrinkY != rhs.m_shrinkY ||
|
|
Shinya Kitaoka |
120a6e |
m_applyShrinkToViewer != rhs.m_applyShrinkToViewer ||
|
|
Shinya Kitaoka |
120a6e |
m_maxTileSize != rhs.m_maxTileSize || m_affine != rhs.m_affine ||
|
|
Shinya Kitaoka |
120a6e |
m_mark != rhs.m_mark || m_isSwatch != rhs.m_isSwatch ||
|
|
Shinya Kitaoka |
120a6e |
m_userCachable != rhs.m_userCachable)
|
|
Shinya Kitaoka |
120a6e |
return false;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
return std::equal(m_data.begin(), m_data.end(), rhs.m_data.begin(), areEqual);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
bool TRenderSettings::operator!=(const TRenderSettings &rhs) const {
|
|
Shinya Kitaoka |
120a6e |
return !operator==(rhs);
|
|
Toshihiro Shimizu |
890ddd |
}
|