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
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename t=""></typename>
Toshihiro Shimizu 890ddd
struct RaylitFuncTraits {
Shinya Kitaoka 120a6e
  typedef void (*function_type)(T *, T *, int, int, int, int, const TRect &,
Shinya Kitaoka 120a6e
                                const TRect &, const TRop::RaylitParams &);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename t=""></typename>
Shinya Kitaoka 120a6e
void performStandardRaylit(T *bufIn, T *bufOut, int dxIn, int dyIn, int dxOut,
Shinya Kitaoka 120a6e
                           int dyOut, const TRect &srcRect,
Shinya Kitaoka 120a6e
                           const TRect &dstRect,
Shinya Kitaoka 120a6e
                           const TRop::RaylitParams ¶ms) {
Shinya Kitaoka 120a6e
  /* NOTATION:  Diagram assuming octant 1
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /                   |
Shinya Kitaoka 120a6e
 /                    |
Shinya Kitaoka 120a6e
/  - ray_final_y      | octLy
Shinya Kitaoka 120a6e
/ 1                    |
Shinya Kitaoka 120a6e
+----                   |
Shinya Kitaoka 120a6e
_____  octLx
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
So, octLx and octLy are the octant's lx and ly;  ray_final_y is the final height
Shinya Kitaoka 120a6e
of the ray we're tracing
Shinya Kitaoka 120a6e
*/
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Build colors-related variables
Shinya Kitaoka 120a6e
  int max = T::maxChannelValue;
shun-iwasawa 443318
  /*-- Color of transparent part --*/
Shinya Kitaoka 120a6e
  int transp_val = (params.m_invert) ? max : 0, opaque_val = max - transp_val;
Shinya Kitaoka 120a6e
  int value, val_r, val_g, val_b, val_m;
Shinya Kitaoka 120a6e
  double lightness, r_fac, g_fac, b_fac, m_fac;
shun-iwasawa 443318
  /*--  Coefficients to absorb 8bit/16bit difference --*/
Shinya Kitaoka 120a6e
  double factor = max / 255.0;
Shinya Kitaoka 120a6e
shun-iwasawa 255f14
  // NOTE: These variable initializations are, well,
shun-iwasawa 255f14
  // heuristic at least. They were probably tested
shun-iwasawa 255f14
  // to be good, but didn't quite make any REAL sense.
Shinya Kitaoka 120a6e
  // They could be done MUCH better, but changing them
shun-iwasawa 255f14
  // would alter the way raylit has been applied until now.
shun-iwasawa 255f14
  // Should be changed at some point, though...
shun-iwasawa 255f14
shun-iwasawa 255f14
  double scale      = params.m_scale;
shun-iwasawa 255f14
  double decay      = log(params.m_decay / 100.0 + 1.0) + 1.0;
shun-iwasawa 255f14
  double intensity  = 1e8 * log(params.m_intensity / 100.0 + 1.0) / scale;
shun-iwasawa 255f14
  double smoothness = log(params.m_smoothness * 5.0 / 100.0 + 1.0);
shun-iwasawa 255f14
  double radius     = params.m_radius;
shun-iwasawa 255f14
shun-iwasawa 443318
  /*-- The rate at which light diminishes when there is no light source at the
shun-iwasawa 443318
   * next pixel when advancing one step. --*/
shun-iwasawa 255f14
  double neg_delta_p = smoothness * intensity;
shun-iwasawa 443318
  /*-- The rate at which light intensifies when there is a light source at the
shun-iwasawa 443318
   * next pixel when advancing one step. --*/
Shinya Kitaoka 120a6e
  double quot_delta_p = intensity / max;  //
shun-iwasawa 255f14
Shinya Kitaoka 120a6e
  /*--
shun-iwasawa 443318
   * m_color is the Color value of RaylitFx. r_fac, g_fac, b_fac are the
shun-iwasawa 443318
   * premultiplied values of each channel
Shinya Kitaoka 120a6e
   * --*/
Shinya Kitaoka 120a6e
  m_fac = (params.m_color.m / 255.0);
Shinya Kitaoka 120a6e
  r_fac = m_fac * (params.m_color.r / 255.0);
Shinya Kitaoka 120a6e
  g_fac = m_fac * (params.m_color.g / 255.0);
Shinya Kitaoka 120a6e
  b_fac = m_fac * (params.m_color.b / 255.0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Geometry-related variables
Shinya Kitaoka 120a6e
  int x, y, ray_final_y;
Shinya Kitaoka 120a6e
  int octLx = dstRect.x1 - dstRect.x0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double rayPosIncrementX = 1.0 / scale;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double sq_z = sq(params.m_lightOriginSrc.z);  // We'll be making square
Shinya Kitaoka 120a6e
                                                // distances from p, so square
Shinya Kitaoka 120a6e
                                                // it once now
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Perform raylit
Shinya Kitaoka 120a6e
  T *pixIn, *pixOut;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (ray_final_y = 0; ray_final_y < octLx; ++ray_final_y) {
Shinya Kitaoka 120a6e
    // Initialize increment variables
Shinya Kitaoka 120a6e
    lightness = 0.0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    double rayPosIncrementY = rayPosIncrementX * (ray_final_y / (double)octLx);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Use an integer counter to know when y must increase. Will add ray_final_y
Shinya Kitaoka 120a6e
    // as long as
Shinya Kitaoka 120a6e
    // a multiple of octLx-1 is reached, then increase
Shinya Kitaoka 120a6e
    int yIncrementCounter = 0, yIncrementThreshold = octLx - 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Trace a single ray of light
Shinya Kitaoka 120a6e
    TPointD rayPos(rayPosIncrementX, rayPosIncrementY);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    for (x = dstRect.x0, y = dstRect.y0, pixIn = bufIn, pixOut = bufOut;
Shinya Kitaoka 120a6e
         (x < dstRect.x1) && (y < dstRect.y1); ++x) {
Shinya Kitaoka 120a6e
      bool insideSrc = (x >= srcRect.x0) && (x < srcRect.x1) &&
Shinya Kitaoka 120a6e
                       (y >= srcRect.y0) && (y < srcRect.y1);
Shinya Kitaoka 120a6e
      if (insideSrc) {
Shinya Kitaoka 120a6e
        // Add a light component depending on source's matte
Shinya Kitaoka 120a6e
        if (pixIn->m == opaque_val)
Shinya Kitaoka 120a6e
          lightness = std::max(
Shinya Kitaoka 120a6e
              0.0, lightness - neg_delta_p);  // No light source - ray fading
Shinya Kitaoka 120a6e
        else {
Shinya Kitaoka 120a6e
          if (pixIn->m == transp_val)
Shinya Kitaoka 120a6e
            lightness += intensity;  // Full light source - ray enforcing
Shinya Kitaoka 120a6e
          else
Shinya Kitaoka 120a6e
            lightness = std::max(
Shinya Kitaoka 120a6e
                0.0, lightness +  // Half light source
Shinya Kitaoka 120a6e
                         (params.m_invert ? pixIn->m : (max - pixIn->m)) *
Shinya Kitaoka 120a6e
                             quot_delta_p);  //   matte-linear enforcing
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (params.m_includeInput) {
Shinya Kitaoka 120a6e
          val_r = pixIn->r;
Shinya Kitaoka 120a6e
          val_g = pixIn->g;
Shinya Kitaoka 120a6e
          val_b = pixIn->b;
Shinya Kitaoka 120a6e
          val_m = pixIn->m;
Shinya Kitaoka 120a6e
        } else
Shinya Kitaoka 120a6e
          val_r = val_g = val_b = val_m = 0;
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        if (!params.m_invert)
Shinya Kitaoka 120a6e
          lightness += intensity;
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
          lightness = std::max(0.0, lightness - neg_delta_p);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        val_r = val_g = val_b = val_m = 0;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      bool insideDst = (x >= 0) && (y >= 0);
Shinya Kitaoka 120a6e
      if (insideDst) {
Shinya Kitaoka 120a6e
        // Write the corresponding destination pixel
shun-iwasawa 255f14
        if (lightness > 0.0) {
shun-iwasawa 255f14
          if (radius == 0.0) {
shun-iwasawa 255f14
            value = (int)(factor * lightness /
shun-iwasawa 255f14
                              (rayPos.x *
shun-iwasawa 255f14
                               pow((double)(sq(rayPos.x) + sq(rayPos.y) + sq_z),
shun-iwasawa 255f14
                                   decay)) +
shun-iwasawa 255f14
                          0.5);  // * ^-d...  0.5 rounds
shun-iwasawa 255f14
          } else {
shun-iwasawa 255f14
            double ratio = std::max(0.001, 1.0 - radius / norm(rayPos));
shun-iwasawa 255f14
            value        = (int)(factor * lightness /
shun-iwasawa 255f14
                              (rayPos.x * ratio *
shun-iwasawa 255f14
                               pow((double)(sq(rayPos.x * ratio) +
shun-iwasawa 255f14
                                            sq(rayPos.y * ratio) + sq_z),
shun-iwasawa 481b59
                                          decay)) +
shun-iwasawa 255f14
                          0.5);  // * ^-d...  0.5 rounds
shun-iwasawa 255f14
          }
shun-iwasawa 255f14
        } else
Shinya Kitaoka 120a6e
          value = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        // NOTE: pow() could be slow. If that is the case, it could be cached
Shinya Kitaoka 120a6e
        // for the whole octant along the longest ray at integer positions,
Shinya Kitaoka 120a6e
        // and then linearly interpolated between those... Have to profile this
Shinya Kitaoka 120a6e
        // before resorting to that...
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        val_r += value * r_fac;
Shinya Kitaoka 120a6e
        val_g += value * g_fac;
Shinya Kitaoka 120a6e
        val_b += value * b_fac;
Shinya Kitaoka 120a6e
        val_m += value * m_fac;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        pixOut->r = (val_r > max) ? max : val_r;
Shinya Kitaoka 120a6e
        pixOut->g = (val_g > max) ? max : val_g;
Shinya Kitaoka 120a6e
        pixOut->b = (val_b > max) ? max : val_b;
Shinya Kitaoka 120a6e
        pixOut->m = (val_m > max) ? max : val_m;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // Increment variables along the x-axis
Shinya Kitaoka 120a6e
      pixIn += dxIn, pixOut += dxOut;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      rayPos.x += rayPosIncrementX, rayPos.y += rayPosIncrementY;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // Increment variables along the y-axis
Shinya Kitaoka 120a6e
      if ((yIncrementCounter += ray_final_y) >= yIncrementThreshold) {
Shinya Kitaoka 120a6e
        ++y, pixIn += dyIn, pixOut += dyOut;
Shinya Kitaoka 120a6e
        yIncrementCounter -= yIncrementThreshold;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
shun-iwasawa 481b59
// specialization for floating point pixel
shun-iwasawa 481b59
shun-iwasawa 481b59
template <>
shun-iwasawa 481b59
void performStandardRaylit<tpixelf>(TPixelF *bufIn, TPixelF *bufOut, int dxIn,</tpixelf>
shun-iwasawa 481b59
                                    int dyIn, int dxOut, int dyOut,
shun-iwasawa 481b59
                                    const TRect &srcRect, const TRect &dstRect,
shun-iwasawa 481b59
                                    const TRop::RaylitParams ¶ms) {
shun-iwasawa 481b59
  /* NOTATION:  Diagram assuming octant 1
shun-iwasawa 481b59
shun-iwasawa 481b59
  /                   |
shun-iwasawa 481b59
 /                    |
shun-iwasawa 481b59
/  - ray_final_y      | octLy
shun-iwasawa 481b59
/ 1                    |
shun-iwasawa 481b59
+----                   |
shun-iwasawa 481b59
_____  octLx
shun-iwasawa 481b59
shun-iwasawa 481b59
shun-iwasawa 481b59
So, octLx and octLy are the octant's lx and ly;  ray_final_y is the final height
shun-iwasawa 481b59
of the ray we're tracing
shun-iwasawa 481b59
*/
shun-iwasawa 481b59
shun-iwasawa 481b59
  // Build colors-related variables
shun-iwasawa 481b59
  float max = TPixelF::maxChannelValue;
shun-iwasawa 443318
  /*-- Color of transparent part --*/
shun-iwasawa 481b59
  float transp_val = (params.m_invert) ? max : 0.f,
shun-iwasawa 481b59
        opaque_val = max - transp_val;
shun-iwasawa 481b59
  float value, val_r, val_g, val_b, val_m;
shun-iwasawa 481b59
  double lightness, r_fac, g_fac, b_fac, m_fac;
shun-iwasawa 443318
  /*-- Coefficients to absorb 8bit/16bit difference --*/
shun-iwasawa 481b59
  double factor = max / 255.0;
shun-iwasawa 481b59
shun-iwasawa 481b59
  // NOTE: These variable initializations are, well,
shun-iwasawa 481b59
  // heuristic at least. They were probably tested
shun-iwasawa 481b59
  // to be good, but didn't quite make any REAL sense.
shun-iwasawa 481b59
  // They could be done MUCH better, but changing them
shun-iwasawa 481b59
  // would alter the way raylit has been applied until now.
shun-iwasawa 481b59
  // Should be changed at some point, though...
shun-iwasawa 481b59
shun-iwasawa 481b59
  double scale      = params.m_scale;
shun-iwasawa 481b59
  double decay      = log(params.m_decay / 100.0 + 1.0) + 1.0;
shun-iwasawa 481b59
  double intensity  = 1e8 * log(params.m_intensity / 100.0 + 1.0) / scale;
shun-iwasawa 481b59
  double smoothness = log(params.m_smoothness * 5.0 / 100.0 + 1.0);
shun-iwasawa 481b59
  double radius     = params.m_radius;
shun-iwasawa 481b59
shun-iwasawa 443318
  /*-- The rate at which light diminishes when there is no light source at the
shun-iwasawa 443318
   * next pixel when advancing one step. --*/
shun-iwasawa 481b59
  double neg_delta_p = smoothness * intensity;
shun-iwasawa 443318
  /*-- The rate at which light intensifies when there is a light source at the
shun-iwasawa 443318
   * next pixel when advancing one step. --*/
shun-iwasawa 481b59
  double quot_delta_p = intensity / max;  //
shun-iwasawa 481b59
shun-iwasawa 481b59
  /*--
shun-iwasawa 443318
   * m_color is the Color value of RaylitFx. r_fac, g_fac, b_fac are the
shun-iwasawa 443318
   * premultiplied values of each channel
shun-iwasawa 481b59
   * --*/
shun-iwasawa 481b59
  TPixelF colorF = toPixelF(params.m_color);
shun-iwasawa 481b59
  m_fac          = colorF.m;
shun-iwasawa 481b59
  r_fac          = m_fac * colorF.r;
shun-iwasawa 481b59
  g_fac          = m_fac * colorF.g;
shun-iwasawa 481b59
  b_fac          = m_fac * colorF.b;
shun-iwasawa 481b59
shun-iwasawa 481b59
  // Geometry-related variables
shun-iwasawa 481b59
  int x, y, ray_final_y;
shun-iwasawa 481b59
  int octLx = dstRect.x1 - dstRect.x0;
shun-iwasawa 481b59
shun-iwasawa 481b59
  double rayPosIncrementX = 1.0 / scale;
shun-iwasawa 481b59
shun-iwasawa 481b59
  double sq_z = sq(params.m_lightOriginSrc.z);  // We'll be making square
shun-iwasawa 481b59
                                                // distances from p, so square
shun-iwasawa 481b59
                                                // it once now
shun-iwasawa 481b59
shun-iwasawa 481b59
  // Perform raylit
shun-iwasawa 481b59
  TPixelF *pixIn, *pixOut;
shun-iwasawa 481b59
shun-iwasawa 481b59
  for (ray_final_y = 0; ray_final_y < octLx; ++ray_final_y) {
shun-iwasawa 481b59
    // Initialize increment variables
shun-iwasawa 481b59
    lightness = 0.0;
shun-iwasawa 481b59
shun-iwasawa 481b59
    double rayPosIncrementY = rayPosIncrementX * (ray_final_y / (double)octLx);
shun-iwasawa 481b59
shun-iwasawa 481b59
    // Use an integer counter to know when y must increase. Will add ray_final_y
shun-iwasawa 481b59
    // as long as
shun-iwasawa 481b59
    // a multiple of octLx-1 is reached, then increase
shun-iwasawa 481b59
    int yIncrementCounter = 0, yIncrementThreshold = octLx - 1;
shun-iwasawa 481b59
shun-iwasawa 481b59
    // Trace a single ray of light
shun-iwasawa 481b59
    TPointD rayPos(rayPosIncrementX, rayPosIncrementY);
shun-iwasawa 481b59
shun-iwasawa 481b59
    for (x = dstRect.x0, y = dstRect.y0, pixIn = bufIn, pixOut = bufOut;
shun-iwasawa 481b59
         (x < dstRect.x1) && (y < dstRect.y1); ++x) {
shun-iwasawa 481b59
      bool insideSrc = (x >= srcRect.x0) && (x < srcRect.x1) &&
shun-iwasawa 481b59
                       (y >= srcRect.y0) && (y < srcRect.y1);
shun-iwasawa 481b59
      if (insideSrc) {
shun-iwasawa 481b59
        // Add a light component depending on source's matte
shun-iwasawa 481b59
        if (areAlmostEqual((double)pixIn->m, (double)opaque_val))
shun-iwasawa 481b59
          lightness = std::max(
shun-iwasawa 481b59
              0.0, lightness - neg_delta_p);  // No light source - ray fading
shun-iwasawa 481b59
        else {
shun-iwasawa 481b59
          if (areAlmostEqual((double)pixIn->m, (double)transp_val))
shun-iwasawa 481b59
            lightness += intensity;  // Full light source - ray enforcing
shun-iwasawa 481b59
          else
shun-iwasawa 481b59
            lightness = std::max(
shun-iwasawa 481b59
                0.0, lightness +  // Half light source
shun-iwasawa 481b59
                         (params.m_invert ? pixIn->m : (max - pixIn->m)) *
shun-iwasawa 481b59
                             quot_delta_p);  //   matte-linear enforcing
shun-iwasawa 481b59
        }
shun-iwasawa 481b59
shun-iwasawa 481b59
        if (params.m_includeInput) {
shun-iwasawa 481b59
          val_r = pixIn->r;
shun-iwasawa 481b59
          val_g = pixIn->g;
shun-iwasawa 481b59
          val_b = pixIn->b;
shun-iwasawa 481b59
          val_m = pixIn->m;
shun-iwasawa 481b59
        } else
shun-iwasawa 481b59
          val_r = val_g = val_b = val_m = 0.f;
shun-iwasawa 481b59
      } else {
shun-iwasawa 481b59
        if (!params.m_invert)
shun-iwasawa 481b59
          lightness += intensity;
shun-iwasawa 481b59
        else
shun-iwasawa 481b59
          lightness = std::max(0.0, lightness - neg_delta_p);
shun-iwasawa 481b59
shun-iwasawa 481b59
        val_r = val_g = val_b = val_m = 0.f;
shun-iwasawa 481b59
      }
shun-iwasawa 481b59
shun-iwasawa 481b59
      bool insideDst = (x >= 0) && (y >= 0);
shun-iwasawa 481b59
      if (insideDst) {
shun-iwasawa 481b59
        // Write the corresponding destination pixel
shun-iwasawa 481b59
        if (lightness > 0.0) {
shun-iwasawa 481b59
          if (radius == 0.0) {
shun-iwasawa 481b59
            value =
shun-iwasawa 481b59
                factor * lightness /
shun-iwasawa 481b59
                (rayPos.x * pow((double)(sq(rayPos.x) + sq(rayPos.y) + sq_z),
shun-iwasawa 481b59
                                decay));  // * ^-d...
shun-iwasawa 481b59
          } else {
shun-iwasawa 481b59
            double ratio = std::max(0.001, 1.0 - radius / norm(rayPos));
shun-iwasawa 481b59
            value        = factor * lightness /
shun-iwasawa 481b59
                    (rayPos.x * ratio *
shun-iwasawa 481b59
                     pow((double)(sq(rayPos.x * ratio) + sq(rayPos.y * ratio) +
shun-iwasawa 481b59
                                  sq_z),
shun-iwasawa 481b59
                         decay));  // * ^-d...
shun-iwasawa 481b59
          }
shun-iwasawa 481b59
        } else
shun-iwasawa 481b59
          value = 0.f;
shun-iwasawa 481b59
shun-iwasawa 481b59
        // NOTE: pow() could be slow. If that is the case, it could be cached
shun-iwasawa 481b59
        // for the whole octant along the longest ray at integer positions,
shun-iwasawa 481b59
        // and then linearly interpolated between those... Have to profile this
shun-iwasawa 481b59
        // before resorting to that...
shun-iwasawa 481b59
shun-iwasawa 481b59
        val_r += value * r_fac;
shun-iwasawa 481b59
        val_g += value * g_fac;
shun-iwasawa 481b59
        val_b += value * b_fac;
shun-iwasawa 481b59
        val_m += value * m_fac;
shun-iwasawa 481b59
shun-iwasawa 481b59
        pixOut->r = val_r;
shun-iwasawa 481b59
        pixOut->g = val_g;
shun-iwasawa 481b59
        pixOut->b = val_b;
shun-iwasawa 481b59
        pixOut->m = (val_m > max) ? max : val_m;
shun-iwasawa 481b59
      }
shun-iwasawa 481b59
shun-iwasawa 481b59
      // Increment variables along the x-axis
shun-iwasawa 481b59
      pixIn += dxIn, pixOut += dxOut;
shun-iwasawa 481b59
shun-iwasawa 481b59
      rayPos.x += rayPosIncrementX, rayPos.y += rayPosIncrementY;
shun-iwasawa 481b59
shun-iwasawa 481b59
      // Increment variables along the y-axis
shun-iwasawa 481b59
      if ((yIncrementCounter += ray_final_y) >= yIncrementThreshold) {
shun-iwasawa 481b59
        ++y, pixIn += dyIn, pixOut += dyOut;
shun-iwasawa 481b59
        yIncrementCounter -= yIncrementThreshold;
shun-iwasawa 481b59
      }
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
}
shun-iwasawa 481b59
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename t=""></typename>
Shinya Kitaoka 120a6e
void performColorRaylit(T *bufIn, T *bufOut, int dxIn, int dyIn, int dxOut,
Shinya Kitaoka 120a6e
                        int dyOut, const TRect &srcRect, const TRect &dstRect,
Shinya Kitaoka 120a6e
                        const TRop::RaylitParams ¶ms) {
Shinya Kitaoka 120a6e
  // Build colors-related variables
Shinya Kitaoka 120a6e
  int max = T::maxChannelValue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int val_r, val_g, val_b, val_m;
Shinya Kitaoka 120a6e
  double lightness_r, lightness_g, lightness_b;
Shinya Kitaoka 120a6e
  double factor = max / 255.0;
Shinya Kitaoka 120a6e
shun-iwasawa 255f14
  // NOTE: These variable initializations are, well,
shun-iwasawa 255f14
  // heuristic at least. They were probably tested
shun-iwasawa 255f14
  // to be good, but didn't quite make any REAL sense.
Shinya Kitaoka 120a6e
  // They could be done MUCH better, but changing them
shun-iwasawa 255f14
  // would alter the way raylit has been applied until now.
shun-iwasawa 255f14
  // Should be changed at some point, though...
shun-iwasawa 255f14
shun-iwasawa 255f14
  double scale      = params.m_scale;
shun-iwasawa 255f14
  double decay      = log(params.m_decay / 100.0 + 1.0) + 1.0;
shun-iwasawa 255f14
  double intensity  = 1e8 * log(params.m_intensity / 100.0 + 1.0) / scale;
shun-iwasawa 255f14
  double smoothness = log(params.m_smoothness * 5.0 / 100.0 + 1.0);
shun-iwasawa 255f14
  double radius     = params.m_radius;
shun-iwasawa 255f14
Shinya Kitaoka 120a6e
  double neg_delta_p =
Shinya Kitaoka 120a6e
      smoothness *
Shinya Kitaoka 120a6e
      intensity;  // would alter the way raylit has been applied until now.
Shinya Kitaoka 120a6e
  double quot_delta_p = intensity / max;  //
Shinya Kitaoka 120a6e
  // Should be changed at some point, though...
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Geometry-related variables
Shinya Kitaoka 120a6e
  int x, y, ray_final_y;
Shinya Kitaoka 120a6e
  int octLx = dstRect.x1 - dstRect.x0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double rayPosIncrementX = 1.0 / scale;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double fac, sq_z = sq(params.m_lightOriginSrc.z);  // We'll be making square
Shinya Kitaoka 120a6e
                                                     // distances from p, so
Shinya Kitaoka 120a6e
                                                     // square it once now
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Perform raylit
Shinya Kitaoka 120a6e
  T *pixIn, *pixOut;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (ray_final_y = 0; ray_final_y < octLx; ++ray_final_y) {
Shinya Kitaoka 120a6e
    // Initialize increment variables
Shinya Kitaoka 120a6e
    lightness_r = lightness_g = lightness_b = 0.0;
Shinya Kitaoka 120a6e
    int l, l_max;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    double rayPosIncrementY = rayPosIncrementX * (ray_final_y / (double)octLx);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Use an integer counter to know when y must increase. Will add ray_final_y
Shinya Kitaoka 120a6e
    // as long as
Shinya Kitaoka 120a6e
    // a multiple of octLx-1 is reached, then increase
Shinya Kitaoka 120a6e
    int yIncrementCounter = 0, yIncrementThreshold = octLx - 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Trace a single ray of light
Shinya Kitaoka 120a6e
    TPointD rayPos(rayPosIncrementX, rayPosIncrementY);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    for (x = dstRect.x0, y = dstRect.y0, pixIn = bufIn, pixOut = bufOut;
Shinya Kitaoka 120a6e
         (x < dstRect.x1) && (y < dstRect.y1); ++x) {
Shinya Kitaoka 120a6e
      bool insideSrc = (x >= srcRect.x0) && (x < srcRect.x1) &&
Shinya Kitaoka 120a6e
                       (y >= srcRect.y0) && (y < srcRect.y1);
Shinya Kitaoka 120a6e
      if (insideSrc) {
Shinya Kitaoka 120a6e
        val_r = pixIn->r;
Shinya Kitaoka 120a6e
        val_g = pixIn->g;
Shinya Kitaoka 120a6e
        val_b = pixIn->b;
Shinya Kitaoka 120a6e
        val_m = pixIn->m;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        lightness_r = std::max(0.0, val_r ? lightness_r + val_r * quot_delta_p
Shinya Kitaoka 120a6e
                                          : lightness_r - neg_delta_p);
Shinya Kitaoka 120a6e
        lightness_g = std::max(0.0, val_g ? lightness_g + val_g * quot_delta_p
Shinya Kitaoka 120a6e
                                          : lightness_g - neg_delta_p);
Shinya Kitaoka 120a6e
        lightness_b = std::max(0.0, val_b ? lightness_b + val_b * quot_delta_p
Shinya Kitaoka 120a6e
                                          : lightness_b - neg_delta_p);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (!params.m_includeInput) val_r = val_g = val_b = val_m = 0;
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        lightness_r = std::max(0.0, lightness_r - neg_delta_p);
Shinya Kitaoka 120a6e
        lightness_g = std::max(0.0, lightness_g - neg_delta_p);
Shinya Kitaoka 120a6e
        lightness_b = std::max(0.0, lightness_b - neg_delta_p);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        val_r = val_g = val_b = val_m = 0;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      bool insideDst = (x >= 0) && (y >= 0);
Shinya Kitaoka 120a6e
      if (insideDst) {
Shinya Kitaoka 120a6e
        // Write the corresponding destination pixel
shun-iwasawa 255f14
        if (radius == 0.0) {
shun-iwasawa 255f14
          fac = factor /
shun-iwasawa 255f14
                (rayPos.x *
shun-iwasawa 255f14
                 pow((double)(sq(rayPos.x) + sq(rayPos.y) + sq_z), decay));
shun-iwasawa 255f14
        } else {
shun-iwasawa 255f14
          double ratio = std::max(0.001, 1.0 - radius / norm(rayPos));
shun-iwasawa 255f14
          fac =
shun-iwasawa 255f14
              factor /
shun-iwasawa 255f14
              (rayPos.x * ratio *
shun-iwasawa 255f14
               pow((double)(sq(rayPos.x * ratio) + sq(rayPos.y * ratio) + sq_z),
shun-iwasawa 255f14
                   decay));
shun-iwasawa 255f14
        }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        // NOTE: pow() could be slow. If that is the case, it could be cached
Shinya Kitaoka 120a6e
        // for the whole octant along the longest ray at integer positions,
Shinya Kitaoka 120a6e
        // and then linearly interpolated between those... Have to profile this
Shinya Kitaoka 120a6e
        // before resorting to that...
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        val_r += l = (int)(fac * lightness_r + 0.5);
Shinya Kitaoka 120a6e
        l_max      = l;
Shinya Kitaoka 120a6e
        val_g += l = (int)(fac * lightness_g + 0.5);
Shinya Kitaoka 120a6e
        l_max      = std::max(l, l_max);
Shinya Kitaoka 120a6e
        val_b += l = (int)(fac * lightness_b + 0.5);
Shinya Kitaoka 120a6e
        l_max      = std::max(l, l_max);
Shinya Kitaoka 120a6e
        val_m += l_max;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        pixOut->r = (val_r > max) ? max : val_r;
Shinya Kitaoka 120a6e
        pixOut->g = (val_g > max) ? max : val_g;
Shinya Kitaoka 120a6e
        pixOut->b = (val_b > max) ? max : val_b;
Shinya Kitaoka 120a6e
        pixOut->m = (val_m > max) ? max : val_m;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // Increment variables along the x-axis
Shinya Kitaoka 120a6e
      pixIn += dxIn, pixOut += dxOut;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      rayPos.x += rayPosIncrementX, rayPos.y += rayPosIncrementY;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // Increment variables along the y-axis
Shinya Kitaoka 120a6e
      if ((yIncrementCounter += ray_final_y) >= yIncrementThreshold) {
Shinya Kitaoka 120a6e
        ++y, pixIn += dyIn, pixOut += dyOut;
Shinya Kitaoka 120a6e
        yIncrementCounter -= yIncrementThreshold;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
shun-iwasawa 481b59
// specialization for floating point pixel
shun-iwasawa 481b59
shun-iwasawa 481b59
template <>
shun-iwasawa 481b59
void performColorRaylit<tpixelf>(TPixelF *bufIn, TPixelF *bufOut, int dxIn,</tpixelf>
shun-iwasawa 481b59
                                 int dyIn, int dxOut, int dyOut,
shun-iwasawa 481b59
                                 const TRect &srcRect, const TRect &dstRect,
shun-iwasawa 481b59
                                 const TRop::RaylitParams ¶ms) {
shun-iwasawa 481b59
  // Build colors-related variables
shun-iwasawa 481b59
  float max = TPixelF::maxChannelValue;
shun-iwasawa 481b59
shun-iwasawa 481b59
  float val_r, val_g, val_b, val_m;
shun-iwasawa 481b59
  double lightness_r, lightness_g, lightness_b;
shun-iwasawa 481b59
  double factor = max / 255.0;
shun-iwasawa 481b59
shun-iwasawa 481b59
  // NOTE: These variable initializations are, well,
shun-iwasawa 481b59
  // heuristic at least. They were probably tested
shun-iwasawa 481b59
  // to be good, but didn't quite make any REAL sense.
shun-iwasawa 481b59
  // They could be done MUCH better, but changing them
shun-iwasawa 481b59
  // would alter the way raylit has been applied until now.
shun-iwasawa 481b59
  // Should be changed at some point, though...
shun-iwasawa 481b59
shun-iwasawa 481b59
  double scale      = params.m_scale;
shun-iwasawa 481b59
  double decay      = log(params.m_decay / 100.0 + 1.0) + 1.0;
shun-iwasawa 481b59
  double intensity  = 1e8 * log(params.m_intensity / 100.0 + 1.0) / scale;
shun-iwasawa 481b59
  double smoothness = log(params.m_smoothness * 5.0 / 100.0 + 1.0);
shun-iwasawa 481b59
  double radius     = params.m_radius;
shun-iwasawa 481b59
shun-iwasawa 481b59
  double neg_delta_p =
shun-iwasawa 481b59
      smoothness *
shun-iwasawa 481b59
      intensity;  // would alter the way raylit has been applied until now.
shun-iwasawa 481b59
  double quot_delta_p = intensity / max;  //
shun-iwasawa 481b59
  // Should be changed at some point, though...
shun-iwasawa 481b59
shun-iwasawa 481b59
  // Geometry-related variables
shun-iwasawa 481b59
  int x, y, ray_final_y;
shun-iwasawa 481b59
  int octLx = dstRect.x1 - dstRect.x0;
shun-iwasawa 481b59
shun-iwasawa 481b59
  double rayPosIncrementX = 1.0 / scale;
shun-iwasawa 481b59
shun-iwasawa 481b59
  double fac, sq_z = sq(params.m_lightOriginSrc.z);  // We'll be making square
shun-iwasawa 481b59
                                                     // distances from p, so
shun-iwasawa 481b59
                                                     // square it once now
shun-iwasawa 481b59
shun-iwasawa 481b59
  // Perform raylit
shun-iwasawa 481b59
  TPixelF *pixIn, *pixOut;
shun-iwasawa 481b59
shun-iwasawa 481b59
  for (ray_final_y = 0; ray_final_y < octLx; ++ray_final_y) {
shun-iwasawa 481b59
    // Initialize increment variables
shun-iwasawa 481b59
    lightness_r = lightness_g = lightness_b = 0.0;
shun-iwasawa 481b59
    double l, l_max;
shun-iwasawa 481b59
shun-iwasawa 481b59
    double rayPosIncrementY = rayPosIncrementX * (ray_final_y / (double)octLx);
shun-iwasawa 481b59
shun-iwasawa 481b59
    // Use an integer counter to know when y must increase. Will add ray_final_y
shun-iwasawa 481b59
    // as long as
shun-iwasawa 481b59
    // a multiple of octLx-1 is reached, then increase
shun-iwasawa 481b59
    int yIncrementCounter = 0, yIncrementThreshold = octLx - 1;
shun-iwasawa 481b59
shun-iwasawa 481b59
    // Trace a single ray of light
shun-iwasawa 481b59
    TPointD rayPos(rayPosIncrementX, rayPosIncrementY);
shun-iwasawa 481b59
shun-iwasawa 481b59
    for (x = dstRect.x0, y = dstRect.y0, pixIn = bufIn, pixOut = bufOut;
shun-iwasawa 481b59
         (x < dstRect.x1) && (y < dstRect.y1); ++x) {
shun-iwasawa 481b59
      bool insideSrc = (x >= srcRect.x0) && (x < srcRect.x1) &&
shun-iwasawa 481b59
                       (y >= srcRect.y0) && (y < srcRect.y1);
shun-iwasawa 481b59
      if (insideSrc) {
shun-iwasawa 481b59
        val_r = pixIn->r;
shun-iwasawa 481b59
        val_g = pixIn->g;
shun-iwasawa 481b59
        val_b = pixIn->b;
shun-iwasawa 481b59
        val_m = pixIn->m;
shun-iwasawa 481b59
shun-iwasawa 481b59
        lightness_r = std::max(0.0, val_r ? lightness_r + val_r * quot_delta_p
shun-iwasawa 481b59
                                          : lightness_r - neg_delta_p);
shun-iwasawa 481b59
        lightness_g = std::max(0.0, val_g ? lightness_g + val_g * quot_delta_p
shun-iwasawa 481b59
                                          : lightness_g - neg_delta_p);
shun-iwasawa 481b59
        lightness_b = std::max(0.0, val_b ? lightness_b + val_b * quot_delta_p
shun-iwasawa 481b59
                                          : lightness_b - neg_delta_p);
shun-iwasawa 481b59
shun-iwasawa 481b59
        if (!params.m_includeInput) val_r = val_g = val_b = val_m = 0.f;
shun-iwasawa 481b59
      } else {
shun-iwasawa 481b59
        lightness_r = std::max(0.0, lightness_r - neg_delta_p);
shun-iwasawa 481b59
        lightness_g = std::max(0.0, lightness_g - neg_delta_p);
shun-iwasawa 481b59
        lightness_b = std::max(0.0, lightness_b - neg_delta_p);
shun-iwasawa 481b59
shun-iwasawa 481b59
        val_r = val_g = val_b = val_m = 0.f;
shun-iwasawa 481b59
      }
shun-iwasawa 481b59
shun-iwasawa 481b59
      bool insideDst = (x >= 0) && (y >= 0);
shun-iwasawa 481b59
      if (insideDst) {
shun-iwasawa 481b59
        // Write the corresponding destination pixel
shun-iwasawa 481b59
        if (radius == 0.0) {
shun-iwasawa 481b59
          fac = factor /
shun-iwasawa 481b59
                (rayPos.x *
shun-iwasawa 481b59
                 pow((double)(sq(rayPos.x) + sq(rayPos.y) + sq_z), decay));
shun-iwasawa 481b59
        } else {
shun-iwasawa 481b59
          double ratio = std::max(0.001, 1.0 - radius / norm(rayPos));
shun-iwasawa 481b59
          fac =
shun-iwasawa 481b59
              factor /
shun-iwasawa 481b59
              (rayPos.x * ratio *
shun-iwasawa 481b59
               pow((double)(sq(rayPos.x * ratio) + sq(rayPos.y * ratio) + sq_z),
shun-iwasawa 481b59
                   decay));
shun-iwasawa 481b59
        }
shun-iwasawa 481b59
shun-iwasawa 481b59
        // NOTE: pow() could be slow. If that is the case, it could be cached
shun-iwasawa 481b59
        // for the whole octant along the longest ray at integer positions,
shun-iwasawa 481b59
        // and then linearly interpolated between those... Have to profile this
shun-iwasawa 481b59
        // before resorting to that...
shun-iwasawa 481b59
shun-iwasawa 481b59
        val_r += l = fac * lightness_r;
shun-iwasawa 481b59
        l_max      = l;
shun-iwasawa 481b59
        val_g += l = fac * lightness_g;
shun-iwasawa 481b59
        l_max      = std::max(l, l_max);
shun-iwasawa 481b59
        val_b += l = fac * lightness_b;
shun-iwasawa 481b59
        l_max      = std::max(l, l_max);
shun-iwasawa 481b59
        val_m += l_max;
shun-iwasawa 481b59
shun-iwasawa 481b59
        pixOut->r = val_r;
shun-iwasawa 481b59
        pixOut->g = val_g;
shun-iwasawa 481b59
        pixOut->b = val_b;
shun-iwasawa 481b59
        pixOut->m = (val_m > max) ? max : val_m;
shun-iwasawa 481b59
      }
shun-iwasawa 481b59
shun-iwasawa 481b59
      // Increment variables along the x-axis
shun-iwasawa 481b59
      pixIn += dxIn, pixOut += dxOut;
shun-iwasawa 481b59
shun-iwasawa 481b59
      rayPos.x += rayPosIncrementX, rayPos.y += rayPosIncrementY;
shun-iwasawa 481b59
shun-iwasawa 481b59
      // Increment variables along the y-axis
shun-iwasawa 481b59
      if ((yIncrementCounter += ray_final_y) >= yIncrementThreshold) {
shun-iwasawa 481b59
        ++y, pixIn += dyIn, pixOut += dyOut;
shun-iwasawa 481b59
        yIncrementCounter -= yIncrementThreshold;
shun-iwasawa 481b59
      }
shun-iwasawa 481b59
    }
shun-iwasawa 481b59
  }
shun-iwasawa 481b59
}
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------------
shun-iwasawa 443318
/*-- Calculate one of the 8 pizza-shaped regions --*/
Toshihiro Shimizu 890ddd
template <typename t=""></typename>
Shinya Kitaoka 120a6e
void computeOctant(const TRasterPT<t> &src, const TRasterPT<t> &dst, int octant,</t></t>
Shinya Kitaoka 120a6e
                   const TRop::RaylitParams ¶ms,
Shinya Kitaoka 120a6e
                   typename RaylitFuncTraits<t>::function_type raylitFunc) {</t>
Shinya Kitaoka 120a6e
  // Build octant geometry variables
Shinya Kitaoka 120a6e
  int x0, x1, lxIn, lxOut, dxIn, dxOut;
Shinya Kitaoka 120a6e
  int y0, y1, lyIn, lyOut, dyIn, dyOut;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  const T3DPoint &pIn  = params.m_lightOriginSrc,
Shinya Kitaoka 120a6e
                 &pOut = params.m_lightOriginDst;
Shinya Kitaoka 120a6e
  int srcWrap = src->getWrap(), dstWrap = dst->getWrap();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  T *bufIn = (T *)src->getRawData() + tfloor(pIn.y) * srcWrap + tfloor(pIn.x);
Shinya Kitaoka 120a6e
  T *bufOut =
Shinya Kitaoka 120a6e
      (T *)dst->getRawData() + tfloor(pOut.y) * dstWrap + tfloor(pOut.x);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRect srcRect(src->getBounds() +
Shinya Kitaoka 120a6e
                TPoint(tround(pOut.x - pIn.x), tround(pOut.y - pIn.y)));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  lxIn = src->getLx(), lxOut = dst->getLx();
Shinya Kitaoka 120a6e
  lyIn = src->getLy(), lyOut = dst->getLy();
Shinya Kitaoka 120a6e
shun-iwasawa 443318
  /*-- Movement value when moving forward by 1 pixel --*/
Shinya Kitaoka 120a6e
  // Vertical octant pairs
Shinya Kitaoka 120a6e
  if (octant == 1 || octant == 8)
Shinya Kitaoka 120a6e
    dxIn = 1, dxOut = 1, x0 = tfloor(pOut.x), x1 = lxOut;
Shinya Kitaoka 120a6e
  if (octant == 2 || octant == 7)
Shinya Kitaoka 120a6e
    dyIn = 1, dyOut = 1, y0 = tfloor(pOut.x), y1 = lxOut;
Shinya Kitaoka 120a6e
  if (octant == 3 || octant == 6)
Shinya Kitaoka 120a6e
    dyIn = -1, dyOut = -1, y0 = lxOut - tfloor(pOut.x) - 1, y1 = lxOut,
otakuto ed7dcd
    std::swap(srcRect.x0, srcRect.x1), srcRect.x0 = lxOut - srcRect.x0,
Shinya Kitaoka 120a6e
    srcRect.x1 = lxOut - srcRect.x1;
Shinya Kitaoka 120a6e
  if (octant == 4 || octant == 5)
Shinya Kitaoka 120a6e
    dxIn = -1, dxOut = -1, x0 = lxOut - tfloor(pOut.x) - 1, x1 = lxOut,
otakuto ed7dcd
    std::swap(srcRect.x0, srcRect.x1), srcRect.x0 = lxOut - srcRect.x0,
Shinya Kitaoka 120a6e
    srcRect.x1 = lxOut - srcRect.x1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Horizontal octant pairs
Shinya Kitaoka 120a6e
  if (octant == 2 || octant == 3)
Shinya Kitaoka 120a6e
    dxIn = srcWrap, dxOut = dstWrap, x0 = tfloor(pOut.y), x1 = lyOut;
Shinya Kitaoka 120a6e
  if (octant == 1 || octant == 4)
Shinya Kitaoka 120a6e
    dyIn = srcWrap, dyOut = dstWrap, y0 = tfloor(pOut.y), y1 = lyOut;
Shinya Kitaoka 120a6e
  if (octant == 5 || octant == 8)
Shinya Kitaoka 120a6e
    dyIn = -srcWrap, dyOut = -dstWrap, y0 = lyOut - tfloor(pOut.y) - 1,
shun-iwasawa 255f14
    y1         = lyOut, std::swap(srcRect.y0, srcRect.y1),
shun-iwasawa 255f14
    srcRect.y0 = lyOut - srcRect.y0, srcRect.y1 = lyOut - srcRect.y1;
Shinya Kitaoka 120a6e
  if (octant == 6 || octant == 7)
Shinya Kitaoka 120a6e
    dxIn = -srcWrap, dxOut = -dstWrap, x0 = lyOut - tfloor(pOut.y) - 1,
shun-iwasawa 255f14
    x1         = lyOut, std::swap(srcRect.y0, srcRect.y1),
shun-iwasawa 255f14
    srcRect.y0 = lyOut - srcRect.y0, srcRect.y1 = lyOut - srcRect.y1;
Shinya Kitaoka 120a6e
shun-iwasawa 443318
  /*-- To calculate the pizza area in vertical orientation, rotate 90 degrees in
shun-iwasawa 443318
   * advance --*/
Shinya Kitaoka 120a6e
  // Swap x and y axis where necessary
Shinya Kitaoka 120a6e
  if (octant == 2 || octant == 3 || octant == 6 || octant == 7) {
otakuto ed7dcd
    std::swap(lxIn, lyIn), std::swap(lxOut, lyOut);
otakuto ed7dcd
    std::swap(srcRect.x0, srcRect.y0), std::swap(srcRect.x1, srcRect.y1);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int octLx = (x1 - x0), octLy = (y1 - y0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  assert(octLx > 0 && octLy > 0);
Shinya Kitaoka 120a6e
  if (octLx <= 0 && octLy <= 0) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  raylitFunc(bufIn, bufOut, dxIn, dyIn, dxOut, dyOut, srcRect,
Shinya Kitaoka 120a6e
             TRect(x0, y0, x1, y1), 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>
Shinya Kitaoka 120a6e
void doRaylit(const TRasterPT<t> &src, const TRasterPT<t> &dst,</t></t>
Shinya Kitaoka 120a6e
              const TRop::RaylitParams ¶ms,
Shinya Kitaoka 120a6e
              typename RaylitFuncTraits<t>::function_type raylitFunc) {</t>
Shinya Kitaoka 120a6e
  int lxOut = dst->getLx(), lyOut = dst->getLy();
Shinya Kitaoka 120a6e
  const T3DPoint &p = params.m_lightOriginDst;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  src->lock();
Shinya Kitaoka 120a6e
  dst->lock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Depending on the position of p, only some of the quadrants need to be built
Shinya Kitaoka 120a6e
  if (p.y < lyOut) {
Shinya Kitaoka 120a6e
    if (p.x < lxOut) {
Shinya Kitaoka 120a6e
      // Compute the raylit fx on each octant independently
Shinya Kitaoka 120a6e
      computeOctant(src, dst, 1, params, raylitFunc);
Shinya Kitaoka 120a6e
      computeOctant(src, dst, 2, params, raylitFunc);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (p.x >= 0) {
Shinya Kitaoka 120a6e
      computeOctant(src, dst, 3, params, raylitFunc);
Shinya Kitaoka 120a6e
      computeOctant(src, dst, 4, params, raylitFunc);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (p.y >= 0) {
Shinya Kitaoka 120a6e
    if (p.x >= 0) {
Shinya Kitaoka 120a6e
      computeOctant(src, dst, 5, params, raylitFunc);
Shinya Kitaoka 120a6e
      computeOctant(src, dst, 6, params, raylitFunc);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (p.x < lxOut) {
Shinya Kitaoka 120a6e
      computeOctant(src, dst, 7, params, raylitFunc);
Shinya Kitaoka 120a6e
      computeOctant(src, dst, 8, params, raylitFunc);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  dst->unlock();
Shinya Kitaoka 120a6e
  src->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
//    TRop::raylit implementation
Toshihiro Shimizu 890ddd
//***********************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TRop::raylit(const TRasterP &dstRas, const TRasterP &srcRas,
Shinya Kitaoka 120a6e
                  const RaylitParams ¶ms) {
Shinya Kitaoka 120a6e
  if ((TRaster32P)dstRas && (TRaster32P)srcRas)
Shinya Kitaoka 120a6e
    doRaylit<tpixel32>(srcRas, dstRas, params,</tpixel32>
Shinya Kitaoka 120a6e
                       &performStandardRaylit<tpixel32>);</tpixel32>
Shinya Kitaoka 120a6e
  else if ((TRaster64P)dstRas && (TRaster64P)srcRas)
Shinya Kitaoka 120a6e
    doRaylit<tpixel64>(srcRas, dstRas, params,</tpixel64>
Shinya Kitaoka 120a6e
                       &performStandardRaylit<tpixel64>);</tpixel64>
shun-iwasawa 481b59
  else if ((TRasterFP)dstRas && (TRasterFP)srcRas)
shun-iwasawa 481b59
    doRaylit<tpixelf>(srcRas, dstRas, params, &performStandardRaylit<tpixelf>);</tpixelf></tpixelf>
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    throw TException("TRop::raylit unsupported pixel type");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TRop::glassRaylit(const TRasterP &dstRas, const TRasterP &srcRas,
Shinya Kitaoka 120a6e
                       const RaylitParams ¶ms) {
Shinya Kitaoka 120a6e
  if ((TRaster32P)dstRas && (TRaster32P)srcRas)
Shinya Kitaoka 120a6e
    doRaylit<tpixel32>(srcRas, dstRas, params, &performColorRaylit<tpixel32>);</tpixel32></tpixel32>
Shinya Kitaoka 120a6e
  else if ((TRaster64P)dstRas && (TRaster64P)srcRas)
Shinya Kitaoka 120a6e
    doRaylit<tpixel64>(srcRas, dstRas, params, &performColorRaylit<tpixel64>);</tpixel64></tpixel64>
shun-iwasawa 481b59
  else if ((TRasterFP)dstRas && (TRasterFP)srcRas)
shun-iwasawa 481b59
    doRaylit<tpixelf>(srcRas, dstRas, params, &performColorRaylit<tpixelf>);</tpixelf></tpixelf>
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    throw TException("TRop::raylit unsupported pixel type");
Toshihiro Shimizu 890ddd
}