Toshihiro Shimizu 890ddd
/*------------------------------------
Toshihiro Shimizu 890ddd
Iwa_PerspectiveDistortFx
Toshihiro Shimizu 890ddd
奥行き方向に台形歪みを行うエフェクト
Toshihiro Shimizu 890ddd
ディティールを保持するため、引き伸ばす量に応じて素材の解像度を上げる
Toshihiro Shimizu 890ddd
------------------------------------*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "iwa_perspectivedistortfx.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tparamuiconcept.h"
Toshihiro Shimizu 890ddd
//#include "ino_common.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
float4 getSource_CPU(float4 *source_host,
Toshihiro Shimizu 890ddd
					 TDimensionI &dim,
Toshihiro Shimizu 890ddd
					 int pos_x, int pos_y)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (pos_x < 0 || pos_x >= dim.lx ||
Toshihiro Shimizu 890ddd
		pos_y < 0 || pos_y >= dim.ly)
Toshihiro Shimizu 890ddd
		return float4{0.0f, 0.0f, 0.0f, 0.0f};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return source_host[pos_y * dim.lx + pos_x];
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
float4 interp_CPU(float4 val1,
Toshihiro Shimizu 890ddd
				  float4 val2,
Toshihiro Shimizu 890ddd
				  float ratio)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return float4{(1.0f - ratio) * val1.x + ratio * val2.x,
Toshihiro Shimizu 890ddd
				  (1.0f - ratio) * val1.y + ratio * val2.y,
Toshihiro Shimizu 890ddd
				  (1.0f - ratio) * val1.z + ratio * val2.z,
Toshihiro Shimizu 890ddd
				  (1.0f - ratio) * val1.w + ratio * val2.w};
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*------------------------------------------------------------
Toshihiro Shimizu 890ddd
 出力結果をChannel値に変換して格納
Toshihiro Shimizu 890ddd
------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pixel="" raster,="" typename=""></typename>
Toshihiro Shimizu 890ddd
void Iwa_PerspectiveDistortFx::setOutputRaster(float4 *srcMem,
Toshihiro Shimizu 890ddd
											   const RASTER dstRas,
Toshihiro Shimizu 890ddd
											   TDimensionI dim,
Toshihiro Shimizu 890ddd
											   int drawLevel)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	typename PIXEL::Channel halfChan = (typename PIXEL::Channel)(PIXEL::maxChannelValue / 2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	dstRas->fill(PIXEL::Transparent);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	float4 *chan_p = srcMem;
Toshihiro Shimizu 890ddd
	for (int j = 0; j < drawLevel; j++) {
Toshihiro Shimizu 890ddd
		if (j >= dstRas->getLy())
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		PIXEL *pix = dstRas->pixels(j);
Toshihiro Shimizu 890ddd
		for (int i = 0; i < dstRas->getLx(); i++, chan_p++, pix++) {
Toshihiro Shimizu 890ddd
			float val;
Toshihiro Shimizu 890ddd
			val = (*chan_p).x * (float)PIXEL::maxChannelValue + 0.5f;
Toshihiro Shimizu 890ddd
			pix->r = (typename PIXEL::Channel)((val > (float)PIXEL::maxChannelValue) ? (float)PIXEL::maxChannelValue : val);
Toshihiro Shimizu 890ddd
			val = (*chan_p).y * (float)PIXEL::maxChannelValue + 0.5f;
Toshihiro Shimizu 890ddd
			pix->g = (typename PIXEL::Channel)((val > (float)PIXEL::maxChannelValue) ? (float)PIXEL::maxChannelValue : val);
Toshihiro Shimizu 890ddd
			val = (*chan_p).z * (float)PIXEL::maxChannelValue + 0.5f;
Toshihiro Shimizu 890ddd
			pix->b = (typename PIXEL::Channel)((val > (float)PIXEL::maxChannelValue) ? (float)PIXEL::maxChannelValue : val);
Toshihiro Shimizu 890ddd
			val = (*chan_p).w * (float)PIXEL::maxChannelValue + 0.5f;
Toshihiro Shimizu 890ddd
			pix->m = (typename PIXEL::Channel)((val > (float)PIXEL::maxChannelValue) ? (float)PIXEL::maxChannelValue : val);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*------------------------------------------------------------
Toshihiro Shimizu 890ddd
 ソース画像を0〜1に正規化してホストメモリに読み込む
Toshihiro Shimizu 890ddd
------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename pixel="" raster,="" typename=""></typename>
Toshihiro Shimizu 890ddd
void Iwa_PerspectiveDistortFx::setSourceRaster(const RASTER srcRas,
Toshihiro Shimizu 890ddd
											   float4 *dstMem,
Toshihiro Shimizu 890ddd
											   TDimensionI dim)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	float4 *chann_p = dstMem;
Toshihiro Shimizu 890ddd
	for (int j = 0; j < dim.ly; j++) {
Toshihiro Shimizu 890ddd
		PIXEL *pix = srcRas->pixels(j);
Toshihiro Shimizu 890ddd
		for (int i = 0; i < dim.lx; i++, pix++, chann_p++) {
Toshihiro Shimizu 890ddd
			(*chann_p).x = (float)pix->r / (float)PIXEL::maxChannelValue;
Toshihiro Shimizu 890ddd
			(*chann_p).y = (float)pix->g / (float)PIXEL::maxChannelValue;
Toshihiro Shimizu 890ddd
			(*chann_p).z = (float)pix->b / (float)PIXEL::maxChannelValue;
Toshihiro Shimizu 890ddd
			(*chann_p).w = (float)pix->m / (float)PIXEL::maxChannelValue;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Iwa_PerspectiveDistortFx::Iwa_PerspectiveDistortFx()
Toshihiro Shimizu 890ddd
	: m_vanishingPoint(TPointD(0, 0)), m_anchorPoint(TPointD(0, -100.0)), m_precision(300.0 / 162.5)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	/*- 共通パラメータのバインド -*/
Toshihiro Shimizu 890ddd
	addInputPort("Source", m_source);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bindParam(this, "vanishingPoint", m_vanishingPoint);
Toshihiro Shimizu 890ddd
	bindParam(this, "anchorPoint", m_anchorPoint);
Toshihiro Shimizu 890ddd
	bindParam(this, "precision", m_precision);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_vanishingPoint->getX()->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
	m_vanishingPoint->getY()->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
	m_anchorPoint->getX()->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
	m_anchorPoint->getY()->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_precision->setValueRange(1.0, 2.0);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool Iwa_PerspectiveDistortFx::doGetBBox(double frame,
Toshihiro Shimizu 890ddd
										 TRectD &bBox,
Toshihiro Shimizu 890ddd
										 const TRenderSettings &info)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_source.isConnected()) {
Toshihiro Shimizu 890ddd
		bool ret = m_source->doGetBBox(frame, bBox, info);
Toshihiro Shimizu 890ddd
		if (ret)
Toshihiro Shimizu 890ddd
			bBox = TConsts::infiniteRectD;
Toshihiro Shimizu 890ddd
		return ret;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool Iwa_PerspectiveDistortFx::canHandle(const TRenderSettings &info,
Toshihiro Shimizu 890ddd
										 double frame)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void Iwa_PerspectiveDistortFx::doCompute(TTile &tile,
Toshihiro Shimizu 890ddd
										 double frame,
Toshihiro Shimizu 890ddd
										 const TRenderSettings &rend_sets)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	/*- ソース画像が刺さっていなければreturn -*/
Toshihiro Shimizu 890ddd
	if (!m_source.isConnected()) {
Toshihiro Shimizu 890ddd
		tile.getRaster()->clear();
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*- パラメータの取得 -*/
Toshihiro Shimizu 890ddd
	TPointD vp = m_vanishingPoint->getValue(frame);
Toshihiro Shimizu 890ddd
	TPointD ap = m_anchorPoint->getValue(frame);
Toshihiro Shimizu 890ddd
	double precision = m_precision->getValue(frame);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*- 基準点が消失点よりも上にあったらreturn -*/
Toshihiro Shimizu 890ddd
	if (vp.y <= ap.y) {
Toshihiro Shimizu 890ddd
		std::cout << "the anchor must be lower than the vanishing point" << std::endl;
Toshihiro Shimizu 890ddd
		tile.getRaster()->clear();
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TAffine aff = rend_sets.m_affine;
Toshihiro Shimizu 890ddd
	/*- カメラ左下を中心としたピクセル座標に変換する -*/
Toshihiro Shimizu 890ddd
	TPointD vanishingPoint = aff * vp - (tile.m_pos + tile.getRaster()->getCenterD()) + TPointD(rend_sets.m_cameraBox.getLx() / 2.0, rend_sets.m_cameraBox.getLy() / 2.0);
Toshihiro Shimizu 890ddd
	TPointD anchorPoint = aff * ap - (tile.m_pos + tile.getRaster()->getCenterD()) + TPointD(rend_sets.m_cameraBox.getLx() / 2.0, rend_sets.m_cameraBox.getLy() / 2.0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double offs = vanishingPoint.x - rend_sets.m_cameraBox.getLx() / 2.0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*- 取り込む解像度の倍率 -*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRectD rectOut(tile.m_pos, TDimensionD(
Toshihiro Shimizu 890ddd
								   tile.getRaster()->getLx(), tile.getRaster()->getLy()));
Toshihiro Shimizu 890ddd
	TDimensionI outDim(rectOut.getLx(), rectOut.getLy());
Toshihiro Shimizu 890ddd
	/*- ソース画像を正規化して格納 -*/
Toshihiro Shimizu 890ddd
	/*- 素材を拡大させて持ち込む -*/
Toshihiro Shimizu 890ddd
	TDimensionI sourceDim(rectOut.getLx() * (int)tceil(precision), anchorPoint.y);
Toshihiro Shimizu 890ddd
	float4 *source_host;
Toshihiro Shimizu 890ddd
	TRasterGR8P source_host_ras(sourceDim.lx * sizeof(float4), sourceDim.ly);
Toshihiro Shimizu 890ddd
	source_host_ras->lock();
Toshihiro Shimizu 890ddd
	source_host = (float4 *)source_host_ras->getRawData();
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TRenderSettings new_sets(rend_sets);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		new_sets.m_affine *= TTranslation(vp.x, vp.y);
Toshihiro Shimizu 890ddd
		new_sets.m_affine *= TScale(precision, 1.0);
Toshihiro Shimizu 890ddd
		new_sets.m_affine *= TTranslation(-vp.x, -vp.y);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		double sourcePosX = offs + precision * (tile.m_pos.x - offs);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TTile sourceTile;
Toshihiro Shimizu 890ddd
		m_source->allocateAndCompute(
Toshihiro Shimizu 890ddd
			sourceTile, TPointD(sourcePosX, tile.m_pos.y),
Toshihiro Shimizu 890ddd
			sourceDim, tile.getRaster(), frame, new_sets);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		/*- タイルの画像を0〜1に正規化してホストメモリに読み込む -*/
Toshihiro Shimizu 890ddd
		TRaster32P ras32 = (TRaster32P)sourceTile.getRaster();
Toshihiro Shimizu 890ddd
		TRaster64P ras64 = (TRaster64P)sourceTile.getRaster();
Toshihiro Shimizu 890ddd
		if (ras32)
Toshihiro Shimizu 890ddd
			setSourceRaster<traster32p, tpixel32="">(ras32, source_host, sourceDim);</traster32p,>
Toshihiro Shimizu 890ddd
		else if (ras64)
Toshihiro Shimizu 890ddd
			setSourceRaster<traster64p, tpixel64="">(ras64, source_host, sourceDim);</traster64p,>
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TDimensionI resultDim(rectOut.getLx(), anchorPoint.y);
Toshihiro Shimizu 890ddd
	TRasterGR8P result_host_ras(resultDim.lx * sizeof(float4), resultDim.ly);
Toshihiro Shimizu 890ddd
	/*- 結果を収めるメモリ -*/
Toshihiro Shimizu 890ddd
	float4 *result_host;
Toshihiro Shimizu 890ddd
	result_host_ras->lock();
Toshihiro Shimizu 890ddd
	result_host = (float4 *)result_host_ras->getRawData();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	doCompute_CPU(tile, frame, rend_sets,
Toshihiro Shimizu 890ddd
				  vanishingPoint,
Toshihiro Shimizu 890ddd
				  anchorPoint,
Toshihiro Shimizu 890ddd
				  source_host,
Toshihiro Shimizu 890ddd
				  result_host,
Toshihiro Shimizu 890ddd
				  sourceDim,
Toshihiro Shimizu 890ddd
				  resultDim,
Toshihiro Shimizu 890ddd
				  precision,
Toshihiro Shimizu 890ddd
				  offs);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	source_host_ras->unlock();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*- 出力結果をChannel値に変換して格納 -*/
Toshihiro Shimizu 890ddd
	TRaster32P outRas32 = (TRaster32P)tile.getRaster();
Toshihiro Shimizu 890ddd
	TRaster64P outRas64 = (TRaster64P)tile.getRaster();
Toshihiro Shimizu 890ddd
	if (outRas32)
Toshihiro Shimizu 890ddd
		setOutputRaster<traster32p, tpixel32="">(result_host, outRas32, outDim, resultDim.ly);</traster32p,>
Toshihiro Shimizu 890ddd
	else if (outRas64)
Toshihiro Shimizu 890ddd
		setOutputRaster<traster64p, tpixel64="">(result_host, outRas64, outDim, resultDim.ly);</traster64p,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	result_host_ras->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void Iwa_PerspectiveDistortFx::doCompute_CPU(TTile &tile,
Toshihiro Shimizu 890ddd
											 const double frame,
Toshihiro Shimizu 890ddd
											 const TRenderSettings &settings,
Toshihiro Shimizu 890ddd
											 TPointD &vp,
Toshihiro Shimizu 890ddd
											 TPointD &ap,
Toshihiro Shimizu 890ddd
											 float4 *source_host,
Toshihiro Shimizu 890ddd
											 float4 *result_host,
Toshihiro Shimizu 890ddd
											 TDimensionI &sourceDim,
Toshihiro Shimizu 890ddd
											 TDimensionI &resultDim,
Toshihiro Shimizu 890ddd
											 const double precision,
Toshihiro Shimizu 890ddd
											 const double offs)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	/*- 結果ポインタ -*/
Toshihiro Shimizu 890ddd
	float4 *result_p = result_host;
Toshihiro Shimizu 890ddd
	/*- 結果画像内でループ -*/
Toshihiro Shimizu 890ddd
	for (int j = 0; j < resultDim.ly; j++) {
Toshihiro Shimizu 890ddd
		/*- サンプルスタート地点 -*/
Toshihiro Shimizu 890ddd
		double sampleX = precision * (vp.x * (ap.y - (double)j) / (vp.y - (double)j));
Toshihiro Shimizu 890ddd
		/*- 1ピクセル横に移動した場合のサンプリング位置の移動量 -*/
Toshihiro Shimizu 890ddd
		double dx = precision * (vp.y - ap.y) / (vp.y - (double)j);
Toshihiro Shimizu 890ddd
		for (int i = 0; i < resultDim.lx; i++, result_p++, sampleX += dx) {
Toshihiro Shimizu 890ddd
			int index = (int)tfloor(sampleX);
Toshihiro Shimizu 890ddd
			double ratio = sampleX - (double)index;
Toshihiro Shimizu 890ddd
			(*result_p) = interp_CPU(getSource_CPU(source_host, sourceDim, index, j),
Toshihiro Shimizu 890ddd
									 getSource_CPU(source_host, sourceDim, index + 1, j),
Toshihiro Shimizu 890ddd
									 ratio);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void Iwa_PerspectiveDistortFx::getParamUIs(TParamUIConcept *&concepts, int &length)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	concepts = new TParamUIConcept[length = 2];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	concepts[0].m_type = TParamUIConcept::POINT;
Toshihiro Shimizu 890ddd
	concepts[0].m_label = "Vanishing Point";
Toshihiro Shimizu 890ddd
	concepts[0].m_params.push_back(m_vanishingPoint);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	concepts[1].m_type = TParamUIConcept::POINT;
Toshihiro Shimizu 890ddd
	concepts[1].m_label = "Anchor Point";
Toshihiro Shimizu 890ddd
	concepts[1].m_params.push_back(m_anchorPoint);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
FX_PLUGIN_IDENTIFIER(Iwa_PerspectiveDistortFx, "iwa_PerspectiveDistortFx")