Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "stdfx.h"
Toshihiro Shimizu 890ddd
#include "tfxparam.h"
Toshihiro Shimizu 890ddd
#include "warp.h"
Toshihiro Shimizu 890ddd
#include "trop.h"
Toshihiro Shimizu 890ddd
#include "trasterfx.h"
Toshihiro Shimizu 890ddd
#include "tspectrumparam.h"
Toshihiro Shimizu 890ddd
#include "gradients.h"
Toshihiro Shimizu 890ddd
#include "timage_io.h"
Toshihiro Shimizu 890ddd
#include "perlinnoise.h"
Toshihiro Shimizu 890ddd
#include "tparamuiconcept.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class RandomWaveFx : public TStandardRasterFx {
Shinya Kitaoka 120a6e
  FX_PLUGIN_DECLARATION(RandomWaveFx)
Toshihiro Shimizu 890ddd
protected:
Shinya Kitaoka 120a6e
  TRasterFxPort m_warped;
Shinya Kitaoka 120a6e
  TDoubleParamP m_intensity;
Shinya Kitaoka 120a6e
  TDoubleParamP m_gridStep;
Shinya Kitaoka 120a6e
  TDoubleParamP m_evol;
Shinya Kitaoka 120a6e
  TDoubleParamP m_posx;
Shinya Kitaoka 120a6e
  TDoubleParamP m_posy;
Shinya Kitaoka 120a6e
  TBoolParamP m_sharpen;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  RandomWaveFx()
Shinya Kitaoka 120a6e
      : m_intensity(20)
Shinya Kitaoka 120a6e
      , m_gridStep(2)
Shinya Kitaoka 120a6e
      , m_evol(0.0)
Shinya Kitaoka 120a6e
      , m_posx(0.0)
Shinya Kitaoka 120a6e
      , m_posy(0.0)
Shinya Kitaoka 120a6e
      , m_sharpen(false) {
Shinya Kitaoka 120a6e
    m_posx->setMeasureName("fxLength");
Shinya Kitaoka 120a6e
    m_posy->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    addInputPort("Source", m_warped);
Shinya Kitaoka 120a6e
    bindParam(this, "intensity", m_intensity);
Shinya Kitaoka 120a6e
    bindParam(this, "sensitivity", m_gridStep);
Shinya Kitaoka 120a6e
    bindParam(this, "evolution", m_evol);
Shinya Kitaoka 120a6e
    bindParam(this, "positionx", m_posx);
Shinya Kitaoka 120a6e
    bindParam(this, "positiony", m_posy);
Shinya Kitaoka 120a6e
    bindParam(this, "sharpen", m_sharpen);
Shinya Kitaoka 120a6e
    m_intensity->setValueRange(-1000, 1000);
Shinya Kitaoka 120a6e
    m_gridStep->setValueRange(2, 20);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //-------------------------------------------------------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  virtual ~RandomWaveFx() {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //-------------------------------------------------------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void getParamUIs(TParamUIConcept *&concepts, int &length) override {
Shinya Kitaoka 120a6e
    concepts = new TParamUIConcept[length = 1];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    concepts[0].m_type  = TParamUIConcept::POINT_2;
Shinya Kitaoka 120a6e
    concepts[0].m_label = "Position";
Shinya Kitaoka 120a6e
    concepts[0].m_params.push_back(m_posx);
Shinya Kitaoka 120a6e
    concepts[0].m_params.push_back(m_posy);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //-------------------------------------------------------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  bool canHandle(const TRenderSettings &info, double frame) override {
Shinya Kitaoka 120a6e
    return isAlmostIsotropic(info.m_affine);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //-------------------------------------------------------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info) override {
Shinya Kitaoka 120a6e
    if (m_warped.isConnected()) {
Shinya Kitaoka 120a6e
      int ret = m_warped->doGetBBox(frame, bBox, info);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (ret && !bBox.isEmpty()) {
Shinya Kitaoka 120a6e
        if (bBox != TConsts::infiniteRectD) {
Shinya Kitaoka 120a6e
          WarpParams params;
Shinya Kitaoka 120a6e
          params.m_intensity = m_intensity->getValue(frame);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          bBox = bBox.enlarge(getWarpRadius(params));
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        return true;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    bBox = TRectD();
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //-------------------------------------------------------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void doDryCompute(TRectD &rect, double frame, const TRenderSettings &info) override {
Shinya Kitaoka 120a6e
    bool isWarped = m_warped.isConnected();
Shinya Kitaoka 120a6e
    if (!isWarped) return;
Shinya Kitaoka 120a6e
    if (fabs(m_intensity->getValue(frame)) < 0.01) {
Shinya Kitaoka 120a6e
      m_warped->dryCompute(rect, frame, info);
Shinya Kitaoka 120a6e
      return;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    double scale    = sqrt(fabs(info.m_affine.det()));
Shinya Kitaoka 120a6e
    double gridStep = 1.5 * m_gridStep->getValue(frame);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    WarpParams params;
Shinya Kitaoka 120a6e
    params.m_intensity   = m_intensity->getValue(frame) / gridStep;
Shinya Kitaoka 120a6e
    params.m_warperScale = scale * gridStep;
Shinya Kitaoka 120a6e
    params.m_sharpen     = m_sharpen->getValue();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TRectD warpedBox, warpedComputeRect, tileComputeRect;
Shinya Kitaoka 120a6e
    m_warped->getBBox(frame, warpedBox, info);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    getWarpComputeRects(tileComputeRect, warpedComputeRect, warpedBox, rect,
Shinya Kitaoka 120a6e
                        params);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (tileComputeRect.getLx() <= 0 || tileComputeRect.getLy() <= 0) return;
Shinya Kitaoka 120a6e
    if (warpedComputeRect.getLx() <= 0 || warpedComputeRect.getLy() <= 0)
Shinya Kitaoka 120a6e
      return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_warped->dryCompute(warpedComputeRect, frame, info);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //-------------------------------------------------------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void doCompute(TTile &tile, double frame, const TRenderSettings &info) override {
Shinya Kitaoka 120a6e
    bool isWarped = m_warped.isConnected();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (!isWarped) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (fabs(m_intensity->getValue(frame)) < 0.01) {
Shinya Kitaoka 120a6e
      m_warped->compute(tile, frame, info);
Shinya Kitaoka 120a6e
      return;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int shrink      = (info.m_shrinkX + info.m_shrinkY) / 2;
Shinya Kitaoka 120a6e
    double scale    = sqrt(fabs(info.m_affine.det()));
Shinya Kitaoka 120a6e
    double gridStep = 1.5 * m_gridStep->getValue(frame);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    WarpParams params;
Shinya Kitaoka 120a6e
    params.m_intensity   = m_intensity->getValue(frame) / gridStep;
Shinya Kitaoka 120a6e
    params.m_warperScale = scale * gridStep;
Shinya Kitaoka 120a6e
    params.m_sharpen     = m_sharpen->getValue();
Shinya Kitaoka 120a6e
    params.m_shrink      = shrink;
Shinya Kitaoka 120a6e
    double evolution     = m_evol->getValue(frame);
Shinya Kitaoka 120a6e
    double size          = 100.0 / info.m_shrinkX;
Shinya Kitaoka 120a6e
    TPointD pos(m_posx->getValue(frame), m_posy->getValue(frame));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // The warper is calculated on a standard reference, with fixed dpi. This
Shinya Kitaoka 120a6e
    // makes sure
Shinya Kitaoka 120a6e
    // that the lattice created for the warp does not depend on camera
Shinya Kitaoka 120a6e
    // transforms and resolution.
Shinya Kitaoka 120a6e
    TRenderSettings warperInfo(info);
Shinya Kitaoka 120a6e
    double warperScaleFactor = 1.0 / params.m_warperScale;
Shinya Kitaoka 120a6e
    warperInfo.m_affine      = TScale(warperScaleFactor) * info.m_affine;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Retrieve tile's geometry
Shinya Kitaoka 120a6e
    TRectD tileRect;
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      TRasterP tileRas = tile.getRaster();
Shinya Kitaoka 120a6e
      tileRect =
Shinya Kitaoka 120a6e
          TRectD(tile.m_pos, TDimensionD(tileRas->getLx(), tileRas->getLy()));
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Build the compute rect
Shinya Kitaoka 120a6e
    TRectD warpedBox, warpedComputeRect, tileComputeRect;
Shinya Kitaoka 120a6e
    m_warped->getBBox(frame, warpedBox, info);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    getWarpComputeRects(tileComputeRect, warpedComputeRect, warpedBox, tileRect,
Shinya Kitaoka 120a6e
                        params);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (tileComputeRect.getLx() <= 0 || tileComputeRect.getLy() <= 0) return;
Shinya Kitaoka 120a6e
    if (warpedComputeRect.getLx() <= 0 || warpedComputeRect.getLy() <= 0)
Shinya Kitaoka 120a6e
      return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TRectD warperComputeRect(TScale(warperScaleFactor) * tileComputeRect);
Shinya Kitaoka 120a6e
    double warperEnlargement = getWarperEnlargement(params);
Shinya Kitaoka 120a6e
    warperComputeRect        = warperComputeRect.enlarge(warperEnlargement);
Shinya Kitaoka 120a6e
    warperComputeRect.x0     = tfloor(warperComputeRect.x0);
Shinya Kitaoka 120a6e
    warperComputeRect.y0     = tfloor(warperComputeRect.y0);
Shinya Kitaoka 120a6e
    warperComputeRect.x1     = tceil(warperComputeRect.x1);
Shinya Kitaoka 120a6e
    warperComputeRect.y1     = tceil(warperComputeRect.y1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Compute the warped tile
Shinya Kitaoka 120a6e
    TTile tileIn;
Shinya Kitaoka 120a6e
    m_warped->allocateAndCompute(
Shinya Kitaoka 120a6e
        tileIn, warpedComputeRect.getP00(),
Shinya Kitaoka 120a6e
        TDimension(warpedComputeRect.getLx(), warpedComputeRect.getLy()),
Shinya Kitaoka 120a6e
        tile.getRaster(), frame, info);
Shinya Kitaoka 120a6e
    TRasterP rasIn = tileIn.getRaster();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Compute the warper tile
Shinya Kitaoka 120a6e
    TSpectrum::ColorKey colors[] = {TSpectrum::ColorKey(0, TPixel32::White),
Shinya Kitaoka 120a6e
                                    TSpectrum::ColorKey(1, TPixel32::Black)};
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TSpectrumParamP cloudscolors = TSpectrumParamP(tArrayCount(colors), colors);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Build the warper
Shinya Kitaoka 120a6e
    warperInfo.m_affine = warperInfo.m_affine;
Shinya Kitaoka 120a6e
    TAffine aff         = warperInfo.m_affine.inv();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TTile warperTile;
Shinya Kitaoka 120a6e
    TRasterP rasWarper =
Shinya Kitaoka 120a6e
        rasIn->create(warperComputeRect.getLx(), warperComputeRect.getLy());
Shinya Kitaoka 120a6e
    warperTile.m_pos = warperComputeRect.getP00();
Shinya Kitaoka 120a6e
    warperTile.setRaster(rasWarper);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      TRenderSettings info2(warperInfo);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // Now, separate the part of the affine the Fx can handle from the rest.
Shinya Kitaoka 120a6e
      TAffine fxHandledAffine = handledAffine(warperInfo, frame);
Shinya Kitaoka 120a6e
      info2.m_affine          = fxHandledAffine;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TAffine aff = warperInfo.m_affine * fxHandledAffine.inv();
Shinya Kitaoka 120a6e
      aff.a13 /= warperInfo.m_shrinkX;
Shinya Kitaoka 120a6e
      aff.a23 /= warperInfo.m_shrinkY;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TRectD rectIn = aff.inv() * warperComputeRect;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // rectIn = rectIn.enlarge(getResampleFilterRadius(info));  //Needed to
Shinya Kitaoka 120a6e
      // counter the resample filter
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TRect rectInI(tfloor(rectIn.x0), tfloor(rectIn.y0), tceil(rectIn.x1) - 1,
Shinya Kitaoka 120a6e
                    tceil(rectIn.y1) - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // rasIn e' un raster dello stesso tipo di tile.getRaster()
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TTile auxtile(
Shinya Kitaoka 120a6e
          warperTile.getRaster()->create(rectInI.getLx(), rectInI.getLy()),
Shinya Kitaoka 120a6e
          convert(rectInI.getP00()));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TPointD mypos(auxtile.m_pos - pos);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      double scale2 = sqrt(fabs(info2.m_affine.det()));
Shinya Kitaoka 120a6e
      doClouds(auxtile.getRaster(), cloudscolors, mypos, evolution, size, 0.0,
Shinya Kitaoka 120a6e
               1.0, PNOISE_CLOUDS, scale2, frame);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      info2.m_affine = aff;
Shinya Kitaoka 120a6e
      TRasterFx::applyAffine(warperTile, auxtile, info2);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Warp
Shinya Kitaoka 120a6e
    TPointD db;
Shinya Kitaoka 120a6e
    TRect rasComputeRectI(convert(tileComputeRect - tileRect.getP00(), db));
Shinya Kitaoka 120a6e
    TRasterP tileRas = tile.getRaster()->extract(rasComputeRectI);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TPointD rasInPos(warpedComputeRect.getP00() - tileComputeRect.getP00());
Shinya Kitaoka 120a6e
    TPointD warperPos(
Shinya Kitaoka 120a6e
        (TScale(params.m_warperScale) * warperComputeRect.getP00()) -
Shinya Kitaoka 120a6e
        tileComputeRect.getP00());
Shinya Kitaoka 120a6e
    warp(tileRas, rasIn, rasWarper, rasInPos, warperPos, params);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
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
    // return -1;   //Deactivated. This fx is currently very inefficient if
Shinya Kitaoka 120a6e
    // subdivided!
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    int shrink      = (info.m_shrinkX + info.m_shrinkY) / 2;
Shinya Kitaoka 120a6e
    double scale    = sqrt(fabs(info.m_affine.det()));
Shinya Kitaoka 120a6e
    double gridStep = 1.5 * m_gridStep->getValue(frame);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    WarpParams params;
Shinya Kitaoka 120a6e
    params.m_intensity   = m_intensity->getValue(frame) / gridStep;
Shinya Kitaoka 120a6e
    params.m_warperScale = scale * gridStep;
Shinya Kitaoka 120a6e
    params.m_sharpen     = m_sharpen->getValue();
Shinya Kitaoka 120a6e
    params.m_shrink      = shrink;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    double warperScaleFactor = 1.0 / params.m_warperScale;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TRectD warpedBox, warpedComputeRect, tileComputeRect;
Shinya Kitaoka 120a6e
    m_warped->getBBox(frame, warpedBox, info);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    getWarpComputeRects(tileComputeRect, warpedComputeRect, warpedBox, rect,
Shinya Kitaoka 120a6e
                        params);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TRectD warperComputeRect(TScale(warperScaleFactor) * tileComputeRect);
Shinya Kitaoka 120a6e
    double warperEnlargement = getWarperEnlargement(params);
Shinya Kitaoka 120a6e
    warperComputeRect        = warperComputeRect.enlarge(warperEnlargement);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    return std::max(TRasterFx::memorySize(warpedComputeRect, info.m_bpp),
Shinya Kitaoka 120a6e
                    TRasterFx::memorySize(warperComputeRect, info.m_bpp));
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
FX_PLUGIN_IDENTIFIER(RandomWaveFx, "randomWaveFx")