Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "traster.h"
Toshihiro Shimizu 890ddd
#include "tpixelutils.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "trop.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
//    Local namespace stuff
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename t=""></typename>
Toshihiro Shimizu 890ddd
struct RaylitFuncTraits {
Toshihiro Shimizu 890ddd
	typedef void (*function_type)(T *, T *, int, int, int, int, const TRect &, const TRect &, const TRop::RaylitParams &);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename t=""></typename>
Toshihiro Shimizu 890ddd
void performStandardRaylit(T *bufIn, T *bufOut,
Toshihiro Shimizu 890ddd
						   int dxIn, int dyIn, int dxOut, int dyOut,
Toshihiro Shimizu 890ddd
						   const TRect &srcRect, const TRect &dstRect,
Toshihiro Shimizu 890ddd
						   const TRop::RaylitParams ¶ms)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	/* NOTATION:  Diagram assuming octant 1
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
        /                   |
Toshihiro Shimizu 890ddd
       /                    |
Toshihiro Shimizu 890ddd
      /  - ray_final_y      | octLy
Toshihiro Shimizu 890ddd
     / 1                    |
Toshihiro Shimizu 890ddd
    +----                   |
Toshihiro Shimizu 890ddd
    _____  octLx
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
    So, octLx and octLy are the octant's lx and ly;  ray_final_y is the final height of the ray we're tracing
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Build colors-related variables
Toshihiro Shimizu 890ddd
	int max = T::maxChannelValue;
Toshihiro Shimizu 890ddd
	/*-- 透明部分の色 --*/
Toshihiro Shimizu 890ddd
	int transp_val = (params.m_invert) ? max : 0, opaque_val = max - transp_val;
Toshihiro Shimizu 890ddd
	int value, val_r, val_g, val_b, val_m;
Toshihiro Shimizu 890ddd
	double lightness, r_fac, g_fac, b_fac, m_fac;
Toshihiro Shimizu 890ddd
	/*-- 8bit/16bitの違いを吸収する係数 --*/
Toshihiro Shimizu 890ddd
	double factor = max / 255.0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double scale = params.m_scale;											// NOTE: These variable initializations are, well,
Toshihiro Shimizu 890ddd
	double decay = log(params.m_decay / 100.0 + 1.0) + 1.0;					// heuristic at least. They were probably tested
Toshihiro Shimizu 890ddd
	double intensity = 1e8 * log(params.m_intensity / 100.0 + 1.0) / scale; // to be good, but didn't quite make any REAL sense.
Toshihiro Shimizu 890ddd
	double smoothness = log(params.m_smoothness * 5.0 / 100.0 + 1.0);		//
Toshihiro Shimizu 890ddd
																			// They could be done MUCH better, but changing them
Toshihiro Shimizu 890ddd
	/*-- 1ステップ進んだ時、次のピクセルで光源が無かったときの光の弱まる割合 --*/
Toshihiro Shimizu 890ddd
	double neg_delta_p = smoothness * intensity; // would alter the way raylit has been applied until now.
Toshihiro Shimizu 890ddd
	/*-- 1ステップ進んだ時、次のピクセルで光源が有ったときの光の強まる割合 --*/
Toshihiro Shimizu 890ddd
	double quot_delta_p = intensity / max; //
Toshihiro Shimizu 890ddd
										   // Should be changed at some point, though...
Toshihiro Shimizu 890ddd
	/*-- m_colorはRaylitFxのColor値。r_fac、g_fac、b_facは各チャンネルをPremultiplyした値 --*/
Toshihiro Shimizu 890ddd
	m_fac = (params.m_color.m / 255.0);
Toshihiro Shimizu 890ddd
	r_fac = m_fac * (params.m_color.r / 255.0);
Toshihiro Shimizu 890ddd
	g_fac = m_fac * (params.m_color.g / 255.0);
Toshihiro Shimizu 890ddd
	b_fac = m_fac * (params.m_color.b / 255.0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Geometry-related variables
Toshihiro Shimizu 890ddd
	int x, y, ray_final_y;
Toshihiro Shimizu 890ddd
	int octLx = dstRect.x1 - dstRect.x0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double rayPosIncrementX = 1.0 / scale;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double sq_z = sq(params.m_lightOriginSrc.z); // We'll be making square distances from p, so square it once now
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Perform raylit
Toshihiro Shimizu 890ddd
	T *pixIn, *pixOut;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (ray_final_y = 0; ray_final_y < octLx; ++ray_final_y) {
Toshihiro Shimizu 890ddd
		// Initialize increment variables
Toshihiro Shimizu 890ddd
		lightness = 0.0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		double rayPosIncrementY = rayPosIncrementX * (ray_final_y / (double)octLx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Use an integer counter to know when y must increase. Will add ray_final_y as long as
Toshihiro Shimizu 890ddd
		// a multiple of octLx-1 is reached, then increase
Toshihiro Shimizu 890ddd
		int yIncrementCounter = 0, yIncrementThreshold = octLx - 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Trace a single ray of light
Toshihiro Shimizu 890ddd
		TPointD rayPos(rayPosIncrementX, rayPosIncrementY);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (x = dstRect.x0, y = dstRect.y0, pixIn = bufIn, pixOut = bufOut; (x < dstRect.x1) && (y < dstRect.y1); ++x) {
Toshihiro Shimizu 890ddd
			bool insideSrc = (x >= srcRect.x0) && (x < srcRect.x1) && (y >= srcRect.y0) && (y < srcRect.y1);
Toshihiro Shimizu 890ddd
			if (insideSrc) {
Toshihiro Shimizu 890ddd
				// Add a light component depending on source's matte
Toshihiro Shimizu 890ddd
				if (pixIn->m == opaque_val)
Toshihiro Shimizu 890ddd
					lightness = tmax(0.0, lightness - neg_delta_p); // No light source - ray fading
Toshihiro Shimizu 890ddd
				else {
Toshihiro Shimizu 890ddd
					if (pixIn->m == transp_val)
Toshihiro Shimizu 890ddd
						lightness += intensity; // Full light source - ray enforcing
Toshihiro Shimizu 890ddd
					else
Toshihiro Shimizu 890ddd
						lightness = tmax(0.0, lightness +														   // Half light source
Toshihiro Shimizu 890ddd
												  (params.m_invert ? pixIn->m : (max - pixIn->m)) * quot_delta_p); //   matte-linear enforcing
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (params.m_includeInput) {
Toshihiro Shimizu 890ddd
					val_r = pixIn->r;
Toshihiro Shimizu 890ddd
					val_g = pixIn->g;
Toshihiro Shimizu 890ddd
					val_b = pixIn->b;
Toshihiro Shimizu 890ddd
					val_m = pixIn->m;
Toshihiro Shimizu 890ddd
				} else
Toshihiro Shimizu 890ddd
					val_r = val_g = val_b = val_m = 0;
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				if (!params.m_invert)
Toshihiro Shimizu 890ddd
					lightness += intensity;
Toshihiro Shimizu 890ddd
				else
Toshihiro Shimizu 890ddd
					lightness = tmax(0.0, lightness - neg_delta_p);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				val_r = val_g = val_b = val_m = 0;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			bool insideDst = (x >= 0) && (y >= 0);
Toshihiro Shimizu 890ddd
			if (insideDst) {
Toshihiro Shimizu 890ddd
				// Write the corresponding destination pixel
Toshihiro Shimizu 890ddd
				if (lightness > 0.0)
Toshihiro Shimizu 890ddd
					value = (int)(factor * lightness / (rayPos.x * pow((double)(sq(rayPos.x) + sq(rayPos.y) + sq_z), decay)) + 0.5); // * ^-d...  0.5 rounds
Toshihiro Shimizu 890ddd
				else
Toshihiro Shimizu 890ddd
					value = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				//NOTE: pow() could be slow. If that is the case, it could be cached for the whole octant along the longest ray at integer positions,
Toshihiro Shimizu 890ddd
				// and then linearly interpolated between those... Have to profile this before resorting to that...
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				val_r += value * r_fac;
Toshihiro Shimizu 890ddd
				val_g += value * g_fac;
Toshihiro Shimizu 890ddd
				val_b += value * b_fac;
Toshihiro Shimizu 890ddd
				val_m += value * m_fac;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				pixOut->r = (val_r > max) ? max : val_r;
Toshihiro Shimizu 890ddd
				pixOut->g = (val_g > max) ? max : val_g;
Toshihiro Shimizu 890ddd
				pixOut->b = (val_b > max) ? max : val_b;
Toshihiro Shimizu 890ddd
				pixOut->m = (val_m > max) ? max : val_m;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// Increment variables along the x-axis
Toshihiro Shimizu 890ddd
			pixIn += dxIn, pixOut += dxOut;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			rayPos.x += rayPosIncrementX, rayPos.y += rayPosIncrementY;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// Increment variables along the y-axis
Toshihiro Shimizu 890ddd
			if ((yIncrementCounter += ray_final_y) >= yIncrementThreshold) {
Toshihiro Shimizu 890ddd
				++y, pixIn += dyIn, pixOut += dyOut;
Toshihiro Shimizu 890ddd
				yIncrementCounter -= yIncrementThreshold;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename t=""></typename>
Toshihiro Shimizu 890ddd
void performColorRaylit(T *bufIn, T *bufOut,
Toshihiro Shimizu 890ddd
						int dxIn, int dyIn, int dxOut, int dyOut,
Toshihiro Shimizu 890ddd
						const TRect &srcRect, const TRect &dstRect,
Toshihiro Shimizu 890ddd
						const TRop::RaylitParams ¶ms)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// Build colors-related variables
Toshihiro Shimizu 890ddd
	int max = T::maxChannelValue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int val_r, val_g, val_b, val_m;
Toshihiro Shimizu 890ddd
	double lightness_r, lightness_g, lightness_b;
Toshihiro Shimizu 890ddd
	double factor = max / 255.0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double scale = params.m_scale;											// NOTE: These variable initializations are, well,
Toshihiro Shimizu 890ddd
	double decay = log(params.m_decay / 100.0 + 1.0) + 1.0;					// heuristic at least. They were probably tested
Toshihiro Shimizu 890ddd
	double intensity = 1e8 * log(params.m_intensity / 100.0 + 1.0) / scale; // to be good, but didn't quite make any REAL sense.
Toshihiro Shimizu 890ddd
	double smoothness = log(params.m_smoothness * 5.0 / 100.0 + 1.0);		//
Toshihiro Shimizu 890ddd
																			// They could be done MUCH better, but changing them
Toshihiro Shimizu 890ddd
	double neg_delta_p = smoothness * intensity;							// would alter the way raylit has been applied until now.
Toshihiro Shimizu 890ddd
	double quot_delta_p = intensity / max;									//
Toshihiro Shimizu 890ddd
																			// Should be changed at some point, though...
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Geometry-related variables
Toshihiro Shimizu 890ddd
	int x, y, ray_final_y;
Toshihiro Shimizu 890ddd
	int octLx = dstRect.x1 - dstRect.x0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double rayPosIncrementX = 1.0 / scale;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double fac, sq_z = sq(params.m_lightOriginSrc.z); // We'll be making square distances from p, so square it once now
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Perform raylit
Toshihiro Shimizu 890ddd
	T *pixIn, *pixOut;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (ray_final_y = 0; ray_final_y < octLx; ++ray_final_y) {
Toshihiro Shimizu 890ddd
		// Initialize increment variables
Toshihiro Shimizu 890ddd
		lightness_r = lightness_g = lightness_b = 0.0;
Toshihiro Shimizu 890ddd
		int l, l_max;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		double rayPosIncrementY = rayPosIncrementX * (ray_final_y / (double)octLx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Use an integer counter to know when y must increase. Will add ray_final_y as long as
Toshihiro Shimizu 890ddd
		// a multiple of octLx-1 is reached, then increase
Toshihiro Shimizu 890ddd
		int yIncrementCounter = 0, yIncrementThreshold = octLx - 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// Trace a single ray of light
Toshihiro Shimizu 890ddd
		TPointD rayPos(rayPosIncrementX, rayPosIncrementY);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (x = dstRect.x0, y = dstRect.y0, pixIn = bufIn, pixOut = bufOut; (x < dstRect.x1) && (y < dstRect.y1); ++x) {
Toshihiro Shimizu 890ddd
			bool insideSrc = (x >= srcRect.x0) && (x < srcRect.x1) && (y >= srcRect.y0) && (y < srcRect.y1);
Toshihiro Shimizu 890ddd
			if (insideSrc) {
Toshihiro Shimizu 890ddd
				val_r = pixIn->r;
Toshihiro Shimizu 890ddd
				val_g = pixIn->g;
Toshihiro Shimizu 890ddd
				val_b = pixIn->b;
Toshihiro Shimizu 890ddd
				val_m = pixIn->m;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				lightness_r = tmax(0.0, val_r ? lightness_r + val_r * quot_delta_p : lightness_r - neg_delta_p);
Toshihiro Shimizu 890ddd
				lightness_g = tmax(0.0, val_g ? lightness_g + val_g * quot_delta_p : lightness_g - neg_delta_p);
Toshihiro Shimizu 890ddd
				lightness_b = tmax(0.0, val_b ? lightness_b + val_b * quot_delta_p : lightness_b - neg_delta_p);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (!params.m_includeInput)
Toshihiro Shimizu 890ddd
					val_r = val_g = val_b = val_m = 0;
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				lightness_r = tmax(0.0, lightness_r - neg_delta_p);
Toshihiro Shimizu 890ddd
				lightness_g = tmax(0.0, lightness_g - neg_delta_p);
Toshihiro Shimizu 890ddd
				lightness_b = tmax(0.0, lightness_b - neg_delta_p);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				val_r = val_g = val_b = val_m = 0;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			bool insideDst = (x >= 0) && (y >= 0);
Toshihiro Shimizu 890ddd
			if (insideDst) {
Toshihiro Shimizu 890ddd
				// Write the corresponding destination pixel
Toshihiro Shimizu 890ddd
				fac = factor / (rayPos.x * pow((double)(sq(rayPos.x) + sq(rayPos.y) + sq_z), decay));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				//NOTE: pow() could be slow. If that is the case, it could be cached for the whole octant along the longest ray at integer positions,
Toshihiro Shimizu 890ddd
				// and then linearly interpolated between those... Have to profile this before resorting to that...
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				val_r += l = (int)(fac * lightness_r + 0.5);
Toshihiro Shimizu 890ddd
				l_max = l;
Toshihiro Shimizu 890ddd
				val_g += l = (int)(fac * lightness_g + 0.5);
Toshihiro Shimizu 890ddd
				l_max = tmax(l, l_max);
Toshihiro Shimizu 890ddd
				val_b += l = (int)(fac * lightness_b + 0.5);
Toshihiro Shimizu 890ddd
				l_max = tmax(l, l_max);
Toshihiro Shimizu 890ddd
				val_m += l_max;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				pixOut->r = (val_r > max) ? max : val_r;
Toshihiro Shimizu 890ddd
				pixOut->g = (val_g > max) ? max : val_g;
Toshihiro Shimizu 890ddd
				pixOut->b = (val_b > max) ? max : val_b;
Toshihiro Shimizu 890ddd
				pixOut->m = (val_m > max) ? max : val_m;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// Increment variables along the x-axis
Toshihiro Shimizu 890ddd
			pixIn += dxIn, pixOut += dxOut;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			rayPos.x += rayPosIncrementX, rayPos.y += rayPosIncrementY;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// Increment variables along the y-axis
Toshihiro Shimizu 890ddd
			if ((yIncrementCounter += ray_final_y) >= yIncrementThreshold) {
Toshihiro Shimizu 890ddd
				++y, pixIn += dyIn, pixOut += dyOut;
Toshihiro Shimizu 890ddd
				yIncrementCounter -= yIncrementThreshold;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*-- ピザ状に8分割された領域の1つを計算する --*/
Toshihiro Shimizu 890ddd
template <typename t=""></typename>
Toshihiro Shimizu 890ddd
void computeOctant(const TRasterPT<t> &src, const TRasterPT<t> &dst,</t></t>
Toshihiro Shimizu 890ddd
				   int octant, const TRop::RaylitParams ¶ms,
Toshihiro Shimizu 890ddd
				   typename RaylitFuncTraits<t>::function_type raylitFunc)</t>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// Build octant geometry variables
Toshihiro Shimizu 890ddd
	int x0, x1, lxIn, lxOut, dxIn, dxOut;
Toshihiro Shimizu 890ddd
	int y0, y1, lyIn, lyOut, dyIn, dyOut;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const T3DPoint &pIn = params.m_lightOriginSrc, &pOut = params.m_lightOriginDst;
Toshihiro Shimizu 890ddd
	int srcWrap = src->getWrap(), dstWrap = dst->getWrap();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	T *bufIn = (T *)src->getRawData() + tfloor(pIn.y) * srcWrap + tfloor(pIn.x);
Toshihiro Shimizu 890ddd
	T *bufOut = (T *)dst->getRawData() + tfloor(pOut.y) * dstWrap + tfloor(pOut.x);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRect srcRect(src->getBounds() + TPoint(tround(pOut.x - pIn.x), tround(pOut.y - pIn.y)));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	lxIn = src->getLx(), lxOut = dst->getLx();
Toshihiro Shimizu 890ddd
	lyIn = src->getLy(), lyOut = dst->getLy();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*-- 1ピクセルずつ進むときの移動値 --*/
Toshihiro Shimizu 890ddd
	// Vertical octant pairs
Toshihiro Shimizu 890ddd
	if (octant == 1 || octant == 8)
Toshihiro Shimizu 890ddd
		dxIn = 1, dxOut = 1, x0 = tfloor(pOut.x), x1 = lxOut;
Toshihiro Shimizu 890ddd
	if (octant == 2 || octant == 7)
Toshihiro Shimizu 890ddd
		dyIn = 1, dyOut = 1, y0 = tfloor(pOut.x), y1 = lxOut;
Toshihiro Shimizu 890ddd
	if (octant == 3 || octant == 6)
Toshihiro Shimizu 890ddd
		dyIn = -1, dyOut = -1, y0 = lxOut - tfloor(pOut.x) - 1, y1 = lxOut, tswap(srcRect.x0, srcRect.x1), srcRect.x0 = lxOut - srcRect.x0, srcRect.x1 = lxOut - srcRect.x1;
Toshihiro Shimizu 890ddd
	if (octant == 4 || octant == 5)
Toshihiro Shimizu 890ddd
		dxIn = -1, dxOut = -1, x0 = lxOut - tfloor(pOut.x) - 1, x1 = lxOut, tswap(srcRect.x0, srcRect.x1), srcRect.x0 = lxOut - srcRect.x0, srcRect.x1 = lxOut - srcRect.x1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Horizontal octant pairs
Toshihiro Shimizu 890ddd
	if (octant == 2 || octant == 3)
Toshihiro Shimizu 890ddd
		dxIn = srcWrap, dxOut = dstWrap, x0 = tfloor(pOut.y), x1 = lyOut;
Toshihiro Shimizu 890ddd
	if (octant == 1 || octant == 4)
Toshihiro Shimizu 890ddd
		dyIn = srcWrap, dyOut = dstWrap, y0 = tfloor(pOut.y), y1 = lyOut;
Toshihiro Shimizu 890ddd
	if (octant == 5 || octant == 8)
Toshihiro Shimizu 890ddd
		dyIn = -srcWrap, dyOut = -dstWrap, y0 = lyOut - tfloor(pOut.y) - 1, y1 = lyOut, tswap(srcRect.y0, srcRect.y1), srcRect.y0 = lyOut - srcRect.y0, srcRect.y1 = lyOut - srcRect.y1;
Toshihiro Shimizu 890ddd
	if (octant == 6 || octant == 7)
Toshihiro Shimizu 890ddd
		dxIn = -srcWrap, dxOut = -dstWrap, x0 = lyOut - tfloor(pOut.y) - 1, x1 = lyOut, tswap(srcRect.y0, srcRect.y1), srcRect.y0 = lyOut - srcRect.y0, srcRect.y1 = lyOut - srcRect.y1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*-- 縦向きのピザ領域を計算する場合は、90度回転してから --*/
Toshihiro Shimizu 890ddd
	// Swap x and y axis where necessary
Toshihiro Shimizu 890ddd
	if (octant == 2 || octant == 3 || octant == 6 || octant == 7) {
Toshihiro Shimizu 890ddd
		tswap(lxIn, lyIn), tswap(lxOut, lyOut);
Toshihiro Shimizu 890ddd
		tswap(srcRect.x0, srcRect.y0), tswap(srcRect.x1, srcRect.y1);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int octLx = (x1 - x0), octLy = (y1 - y0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(octLx > 0 && octLy > 0);
Toshihiro Shimizu 890ddd
	if (octLx <= 0 && octLy <= 0)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	raylitFunc(
Toshihiro Shimizu 890ddd
		bufIn, bufOut,
Toshihiro Shimizu 890ddd
		dxIn, dyIn, dxOut, dyOut,
Toshihiro Shimizu 890ddd
		srcRect, TRect(x0, y0, x1, y1),
Toshihiro Shimizu 890ddd
		params);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
  OCTANTS:
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
    \ 3 | 2 /
Toshihiro Shimizu 890ddd
     \  |  /
Toshihiro Shimizu 890ddd
      \ | /
Toshihiro Shimizu 890ddd
     4 \|/ 1
Toshihiro Shimizu 890ddd
    ----+----
Toshihiro Shimizu 890ddd
     5 /|\ 8
Toshihiro Shimizu 890ddd
      / | \
Toshihiro Shimizu 890ddd
     /  |  \
Toshihiro Shimizu 890ddd
    / 6 | 7 \
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename t=""></typename>
Toshihiro Shimizu 890ddd
void doRaylit(const TRasterPT<t> &src, const TRasterPT<t> &dst, const TRop::RaylitParams ¶ms,</t></t>
Toshihiro Shimizu 890ddd
			  typename RaylitFuncTraits<t>::function_type raylitFunc)</t>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int lxOut = dst->getLx(), lyOut = dst->getLy();
Toshihiro Shimizu 890ddd
	const T3DPoint &p = params.m_lightOriginDst;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	src->lock();
Toshihiro Shimizu 890ddd
	dst->lock();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Depending on the position of p, only some of the quadrants need to be built
Toshihiro Shimizu 890ddd
	if (p.y < lyOut) {
Toshihiro Shimizu 890ddd
		if (p.x < lxOut) {
Toshihiro Shimizu 890ddd
			// Compute the raylit fx on each octant independently
Toshihiro Shimizu 890ddd
			computeOctant(src, dst, 1, params, raylitFunc);
Toshihiro Shimizu 890ddd
			computeOctant(src, dst, 2, params, raylitFunc);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (p.x >= 0) {
Toshihiro Shimizu 890ddd
			computeOctant(src, dst, 3, params, raylitFunc);
Toshihiro Shimizu 890ddd
			computeOctant(src, dst, 4, params, raylitFunc);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (p.y >= 0) {
Toshihiro Shimizu 890ddd
		if (p.x >= 0) {
Toshihiro Shimizu 890ddd
			computeOctant(src, dst, 5, params, raylitFunc);
Toshihiro Shimizu 890ddd
			computeOctant(src, dst, 6, params, raylitFunc);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (p.x < lxOut) {
Toshihiro Shimizu 890ddd
			computeOctant(src, dst, 7, params, raylitFunc);
Toshihiro Shimizu 890ddd
			computeOctant(src, dst, 8, params, raylitFunc);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	dst->unlock();
Toshihiro Shimizu 890ddd
	src->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
//    TRop::raylit implementation
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TRop::raylit(const TRasterP &dstRas, const TRasterP &srcRas, const RaylitParams ¶ms)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if ((TRaster32P)dstRas && (TRaster32P)srcRas)
Toshihiro Shimizu 890ddd
		doRaylit<tpixel32>(srcRas, dstRas, params, &performStandardRaylit<tpixel32>);</tpixel32></tpixel32>
Toshihiro Shimizu 890ddd
	else if ((TRaster64P)dstRas && (TRaster64P)srcRas)
Toshihiro Shimizu 890ddd
		doRaylit<tpixel64>(srcRas, dstRas, params, &performStandardRaylit<tpixel64>);</tpixel64></tpixel64>
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		throw TException("TRop::raylit unsupported pixel type");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TRop::glassRaylit(const TRasterP &dstRas, const TRasterP &srcRas, const RaylitParams ¶ms)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if ((TRaster32P)dstRas && (TRaster32P)srcRas)
Toshihiro Shimizu 890ddd
		doRaylit<tpixel32>(srcRas, dstRas, params, &performColorRaylit<tpixel32>);</tpixel32></tpixel32>
Toshihiro Shimizu 890ddd
	else if ((TRaster64P)dstRas && (TRaster64P)srcRas)
Toshihiro Shimizu 890ddd
		doRaylit<tpixel64>(srcRas, dstRas, params, &performColorRaylit<tpixel64>);</tpixel64></tpixel64>
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		throw TException("TRop::raylit unsupported pixel type");
Toshihiro Shimizu 890ddd
}