Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "trop.h"
Toshihiro Shimizu 890ddd
#include "tfxparam.h"
Toshihiro Shimizu 890ddd
#include "tofflinegl.h"
Toshihiro Shimizu 890ddd
//#include "tstroke.h"
Toshihiro Shimizu 890ddd
//#include "drawutil.h"
Toshihiro Shimizu 890ddd
#include "tstopwatch.h"
Toshihiro Shimizu 890ddd
//#include "tpalette.h"
Toshihiro Shimizu 890ddd
//#include "tvectorrenderdata.h"
Toshihiro Shimizu 890ddd
#include "tsystem.h"
Toshihiro Shimizu 890ddd
#include "timagecache.h"
Toshihiro Shimizu 890ddd
#include "tconvert.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "trasterimage.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "timage_io.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tcolorfunctions.h"
Toshihiro Shimizu 890ddd
#include "toonz/tcolumnfx.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "particlesmanager.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "particlesengine.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "trenderer.h"
Toshihiro Shimizu 890ddd
2fc36c
#include <sstream></sstream>
Shinya Kitaoka 9eb50d
Toshihiro Shimizu 890ddd
/*-----------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Particles_Engine::Particles_Engine(ParticlesFx *parent, double frame)
Shinya Kitaoka 120a6e
    : m_parent(parent), m_frame(frame) {}
Shinya Kitaoka 120a6e
Campbell Barton 8c6c57
static void printTime(TStopWatch &sw, std::string name) {
2fc36c
  std::stringstream ss;
Shinya Kitaoka 120a6e
  ss << name << " : ";
Shinya Kitaoka 120a6e
  sw.print(ss);
Shinya Kitaoka 120a6e
  ss << '\n' << '\0';
Shinya Kitaoka 120a6e
  TSystem::outputDebug(ss.str());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
/*-----------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
void Particles_Engine::scramble_particles(std::list <particle*> &myParticles)</particle*>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
double size=myParticles.size()
Toshihiro Shimizu 890ddd
for(i=0; i
Toshihiro Shimizu 890ddd
 {
Toshihiro Shimizu 890ddd
  j=(int)((size)*tnz_random_float());
Toshihiro Shimizu 890ddd
  k=(int)((size)*tnz_random_float());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
 }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
/*-----------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void Particles_Engine::fill_value_struct(struct particles_values &myvalues,
Shinya Kitaoka 120a6e
                                         double frame) {
Shinya Kitaoka 120a6e
  myvalues.source_ctrl_val  = m_parent->source_ctrl_val->getValue();
Shinya Kitaoka 120a6e
  myvalues.bright_thres_val = m_parent->bright_thres_val->getValue();
Shinya Kitaoka 120a6e
  myvalues.multi_source_val = m_parent->multi_source_val->getValue();
Shinya Kitaoka 120a6e
  myvalues.x_pos_val        = m_parent->center_val->getValue(frame).x;
Shinya Kitaoka 120a6e
  myvalues.y_pos_val        = m_parent->center_val->getValue(frame).y;
Shinya Kitaoka 120a6e
  //  myvalues.unit_val=m_parent->unit_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.length_val          = m_parent->length_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.height_val          = m_parent->height_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.maxnum_val          = m_parent->maxnum_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.lifetime_val        = m_parent->lifetime_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.lifetime_ctrl_val   = m_parent->lifetime_ctrl_val->getValue();
Shinya Kitaoka 120a6e
  myvalues.column_lifetime_val = m_parent->column_lifetime_val->getValue();
Shinya Kitaoka 120a6e
  myvalues.startpos_val        = m_parent->startpos_val->getValue();
Shinya Kitaoka 120a6e
  myvalues.randseed_val        = m_parent->randseed_val->getValue();
Shinya Kitaoka 120a6e
  myvalues.gravity_val         = m_parent->gravity_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.g_angle_val         = m_parent->g_angle_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.gravity_ctrl_val    = m_parent->gravity_ctrl_val->getValue();
Shinya Kitaoka 120a6e
  myvalues.friction_val        = m_parent->friction_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.friction_ctrl_val   = m_parent->friction_ctrl_val->getValue();
Shinya Kitaoka 120a6e
  myvalues.windint_val         = m_parent->windint_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.windangle_val       = m_parent->windangle_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.swingmode_val       = m_parent->swingmode_val->getValue();
Shinya Kitaoka 120a6e
  myvalues.randomx_val         = m_parent->randomx_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.randomy_val         = m_parent->randomy_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.randomx_ctrl_val    = m_parent->randomx_ctrl_val->getValue();
Shinya Kitaoka 120a6e
  myvalues.randomy_ctrl_val    = m_parent->randomy_ctrl_val->getValue();
Shinya Kitaoka 120a6e
  myvalues.swing_val           = m_parent->swing_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.speed_val           = m_parent->speed_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.speed_ctrl_val      = m_parent->speed_ctrl_val->getValue();
Shinya Kitaoka 120a6e
  myvalues.speeda_val          = m_parent->speeda_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.speeda_ctrl_val     = m_parent->speeda_ctrl_val->getValue();
Shinya Kitaoka 120a6e
  myvalues.speeda_use_gradient_val =
Shinya Kitaoka 120a6e
      m_parent->speeda_use_gradient_val->getValue();
Shinya Kitaoka 120a6e
  myvalues.speedscale_val     = m_parent->speedscale_val->getValue();
Shinya Kitaoka 120a6e
  myvalues.toplayer_val       = m_parent->toplayer_val->getValue();
Shinya Kitaoka 120a6e
  myvalues.mass_val           = m_parent->mass_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.scale_val          = m_parent->scale_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.scale_ctrl_val     = m_parent->scale_ctrl_val->getValue();
Shinya Kitaoka 120a6e
  myvalues.scale_ctrl_all_val = m_parent->scale_ctrl_all_val->getValue();
Shinya Kitaoka 120a6e
  myvalues.rot_val            = m_parent->rot_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.rot_ctrl_val       = m_parent->rot_ctrl_val->getValue();
Shinya Kitaoka 120a6e
  myvalues.trail_val          = m_parent->trail_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.trailstep_val      = m_parent->trailstep_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.rotswingmode_val   = m_parent->rotswingmode_val->getValue();
Shinya Kitaoka 120a6e
  myvalues.rotspeed_val       = m_parent->rotspeed_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.rotsca_val         = m_parent->rotsca_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.rotswing_val       = m_parent->rotswing_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.pathaim_val        = m_parent->pathaim_val->getValue();
Shinya Kitaoka 120a6e
  myvalues.opacity_val        = m_parent->opacity_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.opacity_ctrl_val   = m_parent->opacity_ctrl_val->getValue();
Shinya Kitaoka 120a6e
  myvalues.trailopacity_val   = m_parent->trailopacity_val->getValue(frame);
Shinya Kitaoka 120a6e
  //  myvalues.mblur_val=m_parent->mblur_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.scalestep_val      = m_parent->scalestep_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.scalestep_ctrl_val = m_parent->scalestep_ctrl_val->getValue();
Shinya Kitaoka 120a6e
  myvalues.fadein_val         = m_parent->fadein_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.fadeout_val        = m_parent->fadeout_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.animation_val      = m_parent->animation_val->getValue();
Shinya Kitaoka 120a6e
  myvalues.step_val           = m_parent->step_val->getValue();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  myvalues.gencol_val         = m_parent->gencol_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.gencol_ctrl_val    = m_parent->gencol_ctrl_val->getValue();
Shinya Kitaoka 120a6e
  myvalues.gencol_spread_val  = m_parent->gencol_spread_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.genfadecol_val     = m_parent->genfadecol_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.fincol_val         = m_parent->fincol_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.fincol_ctrl_val    = m_parent->fincol_ctrl_val->getValue();
Shinya Kitaoka 120a6e
  myvalues.fincol_spread_val  = m_parent->fincol_spread_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.finrangecol_val    = m_parent->finrangecol_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.finfadecol_val     = m_parent->finfadecol_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.foutcol_val        = m_parent->foutcol_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.foutcol_ctrl_val   = m_parent->foutcol_ctrl_val->getValue();
Shinya Kitaoka 120a6e
  myvalues.foutcol_spread_val = m_parent->foutcol_spread_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.foutrangecol_val   = m_parent->foutrangecol_val->getValue(frame);
Shinya Kitaoka 120a6e
  myvalues.foutfadecol_val    = m_parent->foutfadecol_val->getValue(frame);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  myvalues.source_gradation_val = m_parent->source_gradation_val->getValue();
Shinya Kitaoka 120a6e
  myvalues.pick_color_for_every_frame_val =
Shinya Kitaoka 120a6e
      m_parent->pick_color_for_every_frame_val->getValue();
Shinya Kitaoka 120a6e
  myvalues.perspective_distribution_val =
Shinya Kitaoka 120a6e
      m_parent->perspective_distribution_val->getValue();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*-----------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void Particles_Engine::fill_range_struct(struct particles_values &values,
Shinya Kitaoka 120a6e
                                         struct particles_ranges &ranges) {
Shinya Kitaoka 120a6e
  ranges.swing_range = values.swing_val.second - values.swing_val.first;
Shinya Kitaoka 120a6e
  ranges.rotswing_range =
Shinya Kitaoka 120a6e
      values.rotswing_val.second - values.rotswing_val.first;
Shinya Kitaoka 120a6e
  ranges.randomx_range = values.randomx_val.second - values.randomx_val.first;
Shinya Kitaoka 120a6e
  ranges.randomy_range = values.randomy_val.second - values.randomy_val.first;
Shinya Kitaoka 120a6e
  ranges.rotsca_range  = values.rotsca_val.second - values.rotsca_val.first;
Shinya Kitaoka 120a6e
  ranges.rot_range     = values.rot_val.second - values.rot_val.first;
Shinya Kitaoka 120a6e
  ranges.speed_range   = values.speed_val.second - values.speed_val.first;
Shinya Kitaoka 120a6e
  ranges.speeda_range  = values.speeda_val.second - values.speeda_val.first;
Shinya Kitaoka 120a6e
  ranges.mass_range    = values.mass_val.second - values.mass_val.first;
Shinya Kitaoka 120a6e
  ranges.scale_range   = values.scale_val.second - values.scale_val.first;
Shinya Kitaoka 120a6e
  ranges.lifetime_range =
Shinya Kitaoka 120a6e
      values.lifetime_val.second - values.lifetime_val.first;
Shinya Kitaoka 120a6e
  ranges.scalestep_range =
Shinya Kitaoka 120a6e
      values.scalestep_val.second - values.scalestep_val.first;
Shinya Kitaoka 120a6e
  ranges.trail_range = (int)(values.trail_val.second - values.trail_val.first);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool Particles_Engine::port_is_used(int i, struct particles_values &values) {
shun-iwasawa 9ae30f
  return port_is_used_for_value(i, values) ||
shun-iwasawa 9ae30f
         port_is_used_for_gradient(i, values);
shun-iwasawa 9ae30f
}
shun-iwasawa 9ae30f
shun-iwasawa 9ae30f
// Returns true if the pixel value of control image is used.
shun-iwasawa 9ae30f
// Such image will be computed in 8bpc.
shun-iwasawa 9ae30f
bool Particles_Engine::port_is_used_for_value(int i,
shun-iwasawa 9ae30f
                                              struct particles_values &values) {
Shinya Kitaoka 120a6e
  return values.fincol_ctrl_val == i || values.foutcol_ctrl_val == i ||
Shinya Kitaoka 120a6e
         values.friction_ctrl_val == i || values.gencol_ctrl_val == i ||
shun-iwasawa 9ae30f
         values.opacity_ctrl_val == i || values.rot_ctrl_val == i ||
shun-iwasawa 9ae30f
         values.scale_ctrl_val == i || values.scalestep_ctrl_val == i ||
shun-iwasawa 9ae30f
         values.source_ctrl_val == i || values.speed_ctrl_val == i ||
shun-iwasawa 9ae30f
         (values.speeda_ctrl_val == i && !values.speeda_use_gradient_val) ||
Shinya Kitaoka 120a6e
         values.lifetime_ctrl_val == i || values.randomx_ctrl_val == i ||
Shinya Kitaoka 120a6e
         values.randomy_ctrl_val == i;
Toshihiro Shimizu 890ddd
}
shun-iwasawa 9ae30f
shun-iwasawa 9ae30f
// Returns true if the gradient of control image is used.
shun-iwasawa 9ae30f
// Such image will be computed in 16bpc to get smooth result.
shun-iwasawa 9ae30f
bool Particles_Engine::port_is_used_for_gradient(
shun-iwasawa 9ae30f
    int i, struct particles_values &values) {
shun-iwasawa 9ae30f
  return values.gravity_ctrl_val == i ||
shun-iwasawa 9ae30f
         (values.speeda_ctrl_val == i && values.speeda_use_gradient_val);
shun-iwasawa 9ae30f
}
Toshihiro Shimizu 890ddd
/*-----------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
/*-- Startフレームからカレントフレームまで順番に回す関数 --*/
Toshihiro Shimizu 890ddd
void Particles_Engine::roll_particles(
Shinya Kitaoka 120a6e
    TTile *tile, std::map<int, *="" ttile=""> porttiles, const TRenderSettings &ri,</int,>
Shinya Kitaoka 120a6e
    std::list<particle> &myParticles, struct particles_values &values, float cx,</particle>
Shinya Kitaoka 120a6e
    float cy, int frame, int curr_frame, int level_n, bool *random_level,
Shinya Kitaoka 120a6e
    float dpi, std::vector<int> lastframe, int &totalparticles) {</int>
Shinya Kitaoka 120a6e
  particles_ranges ranges;
Shinya Kitaoka 120a6e
  int i, newparticles;
Shinya Kitaoka 120a6e
  float xgravity, ygravity, windx, windy;
Shinya Kitaoka 120a6e
  /*-- 風の強さ/重力の強さをX,Y成分に分ける --*/
Shinya Kitaoka 120a6e
  windx    = values.windint_val * sin(values.windangle_val);
Shinya Kitaoka 120a6e
  windy    = values.windint_val * cos(values.windangle_val);
Shinya Kitaoka 120a6e
  xgravity = values.gravity_val * sin(values.g_angle_val);
Shinya Kitaoka 120a6e
  ygravity = values.gravity_val * cos(values.g_angle_val);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  fill_range_struct(values, ranges);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::vector<std::vector<tpointd>> myregions;</std::vector<tpointd>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*-- [1〜255]
Shinya Kitaoka 120a6e
   * そのIndexに対応するアルファ値を持つピクセルのインデックス値を保存。 [0]
Shinya Kitaoka 120a6e
   * 使用せず --*/
Shinya Kitaoka 120a6e
  std::vector<std::vector<int>> myHistogram;</std::vector<int>
Shinya Kitaoka 120a6e
  /*--
Shinya Kitaoka 120a6e
   * アルファ値255から下がっていき、ピクセル数×重み又はアルファ値を次々足した値を格納
Shinya Kitaoka 120a6e
   * --*/
Shinya Kitaoka 120a6e
  std::vector<float> myWeight;</float>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::map<int, *="" ttile="">::iterator it = porttiles.find(values.source_ctrl_val);</int,>
Shinya Kitaoka 120a6e
  /*-- Perspective
Shinya Kitaoka 120a6e
   * DistributionがONのとき、Sizeに刺さったControlImageが粒子の発生分布を決める
Shinya Kitaoka 120a6e
   * --*/
Shinya Kitaoka 120a6e
  std::map<int, *="" ttile="">::iterator sizeIt =</int,>
Shinya Kitaoka 120a6e
      porttiles.find(values.scale_ctrl_val);
Shinya Kitaoka 120a6e
  if (values.perspective_distribution_val && (sizeIt != porttiles.end())) {
Shinya Kitaoka 120a6e
    /*-- ソース画像にコントロールが付いていた場合、そのアルファ値をマスクに使う
Shinya Kitaoka 120a6e
     * --*/
Shinya Kitaoka 120a6e
    if (values.source_ctrl_val && (it != porttiles.end()))
Shinya Kitaoka 120a6e
      fill_regions_with_size_map(myregions, myHistogram, sizeIt->second,
Shinya Kitaoka 120a6e
                                 it->second, values.bright_thres_val);
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      fill_regions_with_size_map(myregions, myHistogram, sizeIt->second, 0,
Shinya Kitaoka 120a6e
                                 values.bright_thres_val);
Shinya Kitaoka 120a6e
    /*- パーティクルを作る前に myregion内の候補数を合計する--*/
Shinya Kitaoka 120a6e
    if ((int)myHistogram.size() == 256) {
Shinya Kitaoka 120a6e
      for (int m = 255; m >= 0; m--) {
Shinya Kitaoka 120a6e
        /*-- 明度からサイズ サイズから重みを出す --*/
Shinya Kitaoka 120a6e
        float scale =
Shinya Kitaoka 120a6e
            values.scale_val.first + ranges.scale_range * (float)m / 255.0f;
Shinya Kitaoka 120a6e
        float weight = 1.0f / (scale * scale);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        float tmpSum = weight * (float)myHistogram[m].size();
Shinya Kitaoka 120a6e
        int index    = 255 - m;
Shinya Kitaoka 120a6e
        if (index > 0) /*-- これまでの合計に追加する --*/
Shinya Kitaoka 120a6e
          tmpSum += myWeight[index - 1];
Shinya Kitaoka 120a6e
        myWeight.push_back(tmpSum);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    /*- ソース画像にコントロールが付いていた場合 -*/
Shinya Kitaoka 120a6e
    if (values.source_ctrl_val && (it != porttiles.end()))
Shinya Kitaoka 120a6e
      /*-- 入力画像のアルファ値に比例して発生濃度を変える --*/
Shinya Kitaoka 120a6e
      fill_regions(1, myregions, it->second, values.multi_source_val,
Shinya Kitaoka 120a6e
                   values.bright_thres_val, values.source_gradation_val,
Shinya Kitaoka 120a6e
                   myHistogram);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    /*- パーティクルを作る前に myregion内の候補数を合計する--*/
Shinya Kitaoka 120a6e
    /*-- myWeight
Shinya Kitaoka 120a6e
     * の中には、アルファ255から0まで、各アルファ値×ポイント数を足しこんでいったものが格納される。--*/
Shinya Kitaoka 120a6e
    if ((int)myHistogram.size() == 256) {
Shinya Kitaoka 120a6e
      for (int m = 255; m > 0; m--) {
Shinya Kitaoka 120a6e
        float tmpSum = (float)(m * (int)myHistogram[m].size());
Shinya Kitaoka 120a6e
        int index    = 255 - m;
Shinya Kitaoka 120a6e
        if (index > 0) tmpSum += myWeight[index - 1];
Shinya Kitaoka 120a6e
        myWeight.push_back(tmpSum);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*- birth rate を格納 -*/
Shinya Kitaoka 120a6e
  newparticles = (int)values.maxnum_val;
Shinya Kitaoka 120a6e
  if (myParticles.empty() && newparticles)  // Initial creation
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    /*- 新たに作るパーティクルの数だけ繰り返す -*/
Shinya Kitaoka 120a6e
    for (i = 0; i < newparticles; i++) {
shun-iwasawa 9ae30f
      int seed  = (int)((std::numeric_limits<int>::max)() *</int>
Shinya Kitaoka 120a6e
                       values.random_val->getFloat());
Shinya Kitaoka 120a6e
      int level = (int)(values.random_val->getFloat() * level_n);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int lifetime = 0;
Shinya Kitaoka 120a6e
      if (values.column_lifetime_val)
Shinya Kitaoka 120a6e
        lifetime = lastframe[level];
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        lifetime = (int)(values.lifetime_val.first +
Shinya Kitaoka 120a6e
                         ranges.lifetime_range * values.random_val->getFloat());
Shinya Kitaoka 120a6e
      if (lifetime > curr_frame - frame)
Shinya Kitaoka 120a6e
        myParticles.push_back(Particle(
Shinya Kitaoka 120a6e
            lifetime, seed, porttiles, values, ranges, myregions,
Shinya Kitaoka 120a6e
            totalparticles, 0, level, lastframe[level], myHistogram, myWeight));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      totalparticles++;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    std::list<particle>::iterator it;</particle>
Shinya Kitaoka 120a6e
    for (it = myParticles.begin(); it != myParticles.end();) {
Shinya Kitaoka 120a6e
      std::list<particle>::iterator current = it;</particle>
Shinya Kitaoka 120a6e
      ++it;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      Particle &part = (*current);
Shinya Kitaoka 120a6e
      if (part.lifetime <= 0)        // Note: This is in line with the above
Shinya Kitaoka 120a6e
                                     // "lifetime>curr_frame-frame"
Shinya Kitaoka 120a6e
        myParticles.erase(current);  // insertion counterpart
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        part.move(porttiles, values, ranges, windx, windy, xgravity, ygravity,
Shinya Kitaoka 120a6e
                  dpi, lastframe[part.level]);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int oldparticles = myParticles.size();
Shinya Kitaoka 120a6e
    switch (values.toplayer_val) {
Shinya Kitaoka 120a6e
    case ParticlesFx::TOP_YOUNGER:
Shinya Kitaoka 120a6e
      for (i = 0; i < newparticles; i++) {
shun-iwasawa 9ae30f
        int seed  = (int)((std::numeric_limits<int>::max)() *</int>
Shinya Kitaoka 120a6e
                         values.random_val->getFloat());
Shinya Kitaoka 120a6e
        int level = (int)(values.random_val->getFloat() * level_n);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        int lifetime = 0;
Shinya Kitaoka 120a6e
        if (values.column_lifetime_val)
Shinya Kitaoka 120a6e
          lifetime = lastframe[level];
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
          lifetime =
Shinya Kitaoka 120a6e
              (int)(values.lifetime_val.first +
Shinya Kitaoka 120a6e
                    ranges.lifetime_range * values.random_val->getFloat());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (lifetime > curr_frame - frame)
Shinya Kitaoka 120a6e
          myParticles.push_front(Particle(lifetime, seed, porttiles, values,
Shinya Kitaoka 120a6e
                                          ranges, myregions, totalparticles, 0,
Shinya Kitaoka 120a6e
                                          level, lastframe[level], myHistogram,
Shinya Kitaoka 120a6e
                                          myWeight));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        totalparticles++;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    case ParticlesFx::TOP_RANDOM:
Shinya Kitaoka 120a6e
      for (i = 0; i < newparticles; i++) {
Shinya Kitaoka 120a6e
        double tmp = values.random_val->getFloat() * myParticles.size();
Shinya Kitaoka 120a6e
        std::list<particle>::iterator it = myParticles.begin();</particle>
Shinya Kitaoka 120a6e
        for (int j = 0; j < tmp; j++, it++)
Shinya Kitaoka 120a6e
          ;
Shinya Kitaoka 120a6e
        {
shun-iwasawa 9ae30f
          int seed     = (int)((std::numeric_limits<int>::max)() *</int>
Shinya Kitaoka 120a6e
                           values.random_val->getFloat());
Shinya Kitaoka 120a6e
          int level    = (int)(values.random_val->getFloat() * level_n);
Shinya Kitaoka 120a6e
          int lifetime = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          if (values.column_lifetime_val)
Shinya Kitaoka 120a6e
            lifetime = lastframe[level];
Shinya Kitaoka 120a6e
          else
Shinya Kitaoka 120a6e
            lifetime =
Shinya Kitaoka 120a6e
                (int)(values.lifetime_val.first +
Shinya Kitaoka 120a6e
                      ranges.lifetime_range * values.random_val->getFloat());
Shinya Kitaoka 120a6e
          if (lifetime > curr_frame - frame)
Shinya Kitaoka 120a6e
            myParticles.insert(
Shinya Kitaoka 120a6e
                it, Particle(lifetime, seed, porttiles, values, ranges,
Shinya Kitaoka 120a6e
                             myregions, totalparticles, 0, level,
Shinya Kitaoka 120a6e
                             lastframe[level], myHistogram, myWeight));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          totalparticles++;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    default:
Shinya Kitaoka 120a6e
      for (i = 0; i < newparticles; i++) {
shun-iwasawa 9ae30f
        int seed     = (int)((std::numeric_limits<int>::max)() *</int>
Shinya Kitaoka 120a6e
                         values.random_val->getFloat());
Shinya Kitaoka 120a6e
        int level    = (int)(values.random_val->getFloat() * level_n);
Shinya Kitaoka 120a6e
        int lifetime = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (values.column_lifetime_val)
Shinya Kitaoka 120a6e
          lifetime = lastframe[level];
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
          lifetime =
Shinya Kitaoka 120a6e
              (int)(values.lifetime_val.first +
Shinya Kitaoka 120a6e
                    ranges.lifetime_range * values.random_val->getFloat());
Shinya Kitaoka 120a6e
        if (lifetime > curr_frame - frame)
Shinya Kitaoka 120a6e
          myParticles.push_back(Particle(lifetime, seed, porttiles, values,
Shinya Kitaoka 120a6e
                                         ranges, myregions, totalparticles, 0,
Shinya Kitaoka 120a6e
                                         level, lastframe[level], myHistogram,
Shinya Kitaoka 120a6e
                                         myWeight));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        totalparticles++;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      break;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*-----------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void Particles_Engine::normalize_values(struct particles_values &values,
Shinya Kitaoka 120a6e
                                        const TRenderSettings &ri) {
Shinya Kitaoka 120a6e
  double dpicorr = 1;
Shinya Kitaoka 120a6e
  TPointD pos(values.x_pos_val, values.y_pos_val);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  (values.x_pos_val)               = pos.x;
Shinya Kitaoka 120a6e
  (values.y_pos_val)               = pos.y;
Shinya Kitaoka 120a6e
  (values.length_val)              = (values.length_val) * dpicorr;
Shinya Kitaoka 120a6e
  (values.height_val)              = (values.height_val) * dpicorr;
Shinya Kitaoka 120a6e
  (values.gravity_val)             = (values.gravity_val) * dpicorr * 0.1;
Shinya Kitaoka 120a6e
  (values.windint_val)             = (values.windint_val) * dpicorr;
Shinya Kitaoka 120a6e
  (values.speed_val.first)         = (values.speed_val.first) * dpicorr;
Shinya Kitaoka 120a6e
  (values.speed_val.second)        = (values.speed_val.second) * dpicorr;
Shinya Kitaoka 120a6e
  (values.randomx_val.first)       = (values.randomx_val.first) * dpicorr;
Shinya Kitaoka 120a6e
  (values.randomx_val.second)      = (values.randomx_val.second) * dpicorr;
Shinya Kitaoka 120a6e
  (values.randomy_val.first)       = (values.randomy_val.first) * dpicorr;
Shinya Kitaoka 120a6e
  (values.randomy_val.second)      = (values.randomy_val.second) * dpicorr;
Shinya Kitaoka 120a6e
  (values.scale_val.first)         = (values.scale_val.first) * 0.01;
Shinya Kitaoka 120a6e
  (values.scale_val.second)        = (values.scale_val.second) * 0.01;
Shinya Kitaoka 120a6e
  (values.scalestep_val.first)     = (values.scalestep_val.first) * 0.01;
Shinya Kitaoka 120a6e
  (values.scalestep_val.second)    = (values.scalestep_val.second) * 0.01;
Shinya Kitaoka 120a6e
  (values.opacity_val.first)       = (values.opacity_val.first) * 0.01;
Shinya Kitaoka 120a6e
  (values.opacity_val.second)      = (values.opacity_val.second) * 0.01;
Shinya Kitaoka 120a6e
  (values.trailopacity_val.first)  = (values.trailopacity_val.first) * 0.01;
Shinya Kitaoka 120a6e
  (values.trailopacity_val.second) = (values.trailopacity_val.second) * 0.01;
Shinya Kitaoka 120a6e
  (values.mblur_val)               = (values.mblur_val) * 0.01;
Shinya Kitaoka 120a6e
  (values.friction_val)            = -(values.friction_val) * 0.01;
Shinya Kitaoka 120a6e
  (values.windangle_val)           = (values.windangle_val) * M_PI_180;
Shinya Kitaoka 120a6e
  (values.g_angle_val)             = (values.g_angle_val + 180) * M_PI_180;
Shinya Kitaoka 120a6e
  (values.speeda_val.first)        = (values.speeda_val.first) * M_PI_180;
Shinya Kitaoka 120a6e
  (values.speeda_val.second)       = (values.speeda_val.second) * M_PI_180;
Shinya Kitaoka 120a6e
  if (values.step_val < 1) values.step_val = 1;
shun-iwasawa 9ae30f
  values.genfadecol_val  = (values.genfadecol_val) * 0.01;
shun-iwasawa 9ae30f
  values.finfadecol_val  = (values.finfadecol_val) * 0.01;
shun-iwasawa 9ae30f
  values.foutfadecol_val = (values.foutfadecol_val) * 0.01;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*-----------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void Particles_Engine::render_particles(
Jeremy Bullock 175c6b
    TTile *tile, std::vector<trasterfxport *=""> part_ports,</trasterfxport>
Shinya Kitaoka 120a6e
    const TRenderSettings &ri, TDimension &p_size, TPointD &p_offset,
Shinya Kitaoka 120a6e
    std::map<int, *="" trasterfxport=""> ctrl_ports, std::vector<tlevelp> partLevel,</tlevelp></int,>
Shinya Kitaoka 120a6e
    float dpi, int curr_frame, int shrink, double startx, double starty,
Shinya Kitaoka 120a6e
    double endx, double endy, std::vector<int> last_frame, unsigned long fxId) {</int>
Shinya Kitaoka 120a6e
  int frame, startframe, intpart = 0, level_n = 0;
Shinya Kitaoka 120a6e
  struct particles_values values;
Shinya Kitaoka 120a6e
  double dpicorr = dpi * 0.01, fractpart = 0, dpicorr_shrinked = 0,
Shinya Kitaoka 120a6e
         opacity_range = 0;
Shinya Kitaoka 120a6e
  bool random_level    = false;
Shinya Kitaoka 120a6e
  level_n              = part_ports.size();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool isPrecomputingEnabled = false;
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    TRenderer renderer(TRenderer::instance());
Shinya Kitaoka 120a6e
    isPrecomputingEnabled =
Shinya Kitaoka 120a6e
        (renderer && renderer.isPrecomputingEnabled()) ? true : false;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  memset(&values, 0, sizeof(values));
Shinya Kitaoka 120a6e
  /*- 現在のフレームでの各種パラメータを得る -*/
Shinya Kitaoka 120a6e
  fill_value_struct(values, m_frame);
Shinya Kitaoka 120a6e
  /*- 不透明度の範囲(透明〜不透明を 0〜1 に正規化)-*/
Shinya Kitaoka 120a6e
  opacity_range = (values.opacity_val.second - values.opacity_val.first) * 0.01;
Shinya Kitaoka 120a6e
  /*- 開始フレーム -*/
Shinya Kitaoka 120a6e
  startframe = (int)values.startpos_val;
Shinya Kitaoka 120a6e
  if (values.unit_val == ParticlesFx::UNIT_SMALL_INCH)
Shinya Kitaoka 120a6e
    dpicorr_shrinked = dpicorr / shrink;
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    dpicorr_shrinked = dpi / shrink;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::map<std::pair<int, int="">, double> partScales;</std::pair<int,>
Shinya Kitaoka 120a6e
  curr_frame = curr_frame / values.step_val;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ParticlesManager *pc = ParticlesManager::instance();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Retrieve the last rolled frame
Shinya Kitaoka 120a6e
  ParticlesManager::FrameData *particlesData = pc->data(fxId);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::list<particle> myParticles;</particle>
Shinya Kitaoka 120a6e
  TRandom myRandom;
Shinya Kitaoka 120a6e
  values.random_val  = &myRandom;
Shinya Kitaoka 120a6e
  myRandom           = m_parent->randseed_val->getValue();
Shinya Kitaoka 120a6e
  int totalparticles = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int pcFrame = particlesData->m_frame;
Shinya Kitaoka 120a6e
  if (pcFrame > curr_frame) {
Shinya Kitaoka 120a6e
    // Clear stored particlesData
Shinya Kitaoka 120a6e
    particlesData->clear();
Shinya Kitaoka 120a6e
    pcFrame = particlesData->m_frame;
Shinya Kitaoka 120a6e
  } else if (pcFrame >= startframe - 1) {
Shinya Kitaoka 120a6e
    myParticles    = particlesData->m_particles;
Shinya Kitaoka 120a6e
    myRandom       = particlesData->m_random;
Shinya Kitaoka 120a6e
    totalparticles = particlesData->m_totalParticles;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  /*- スタートからカレントフレームまでループ -*/
Shinya Kitaoka 120a6e
  for (frame = startframe - 1; frame <= curr_frame; ++frame) {
Shinya Kitaoka 120a6e
    int dist_frame = curr_frame - frame;
Shinya Kitaoka 120a6e
    /*-
Shinya Kitaoka 120a6e
     * ループ内の現在のフレームでのパラメータを取得。スタートが負ならフレーム=0のときの値を格納
Shinya Kitaoka 120a6e
     * -*/
Shinya Kitaoka 120a6e
    fill_value_struct(values, frame < 0 ? 0 : frame * values.step_val);
Shinya Kitaoka 120a6e
    /*- パラメータの正規化 -*/
Shinya Kitaoka 120a6e
    normalize_values(values, ri);
Shinya Kitaoka 120a6e
    /*- maxnum_valは"birth_rate"のパラメータ -*/
Shinya Kitaoka 120a6e
    intpart = (int)values.maxnum_val;
Shinya Kitaoka 120a6e
    /*-
Shinya Kitaoka 120a6e
     * /birth_rateが小数だったとき、各フレームの小数部分を足しこんだ結果の整数部分をintpartに渡す。
Shinya Kitaoka 120a6e
     * -*/
Shinya Kitaoka 120a6e
    fractpart = fractpart + values.maxnum_val - intpart;
Shinya Kitaoka 120a6e
    if ((int)fractpart) {
Shinya Kitaoka 120a6e
      values.maxnum_val += (int)fractpart;
Shinya Kitaoka 120a6e
      fractpart = fractpart - (int)fractpart;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    std::map<int, *="" ttile=""> porttiles;</int,>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Perform the roll
Shinya Kitaoka 120a6e
    /*- RenderSettingsを複製して現在のフレームの計算用にする -*/
Shinya Kitaoka 120a6e
    TRenderSettings riAux(ri);
Shinya Kitaoka 120a6e
    riAux.m_affine = TAffine();
Shinya Kitaoka 120a6e
    riAux.m_bpp    = 32;
shun-iwasawa 9ae30f
    // control image using its gradient is computed in 64bpp
shun-iwasawa 9ae30f
    TRenderSettings riAux64(riAux);
shun-iwasawa 9ae30f
    riAux64.m_bpp = 64;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int r_frame;  // Useful in case of negative roll frames
Shinya Kitaoka 120a6e
    if (frame < 0)
Shinya Kitaoka 120a6e
      r_frame = 0;
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      r_frame = frame;
Shinya Kitaoka 120a6e
    /*- 出力画像のバウンディングボックス -*/
Shinya Kitaoka 120a6e
    TRectD outTileBBox(tile->m_pos, TDimensionD(tile->getRaster()->getLx(),
Shinya Kitaoka 120a6e
                                                tile->getRaster()->getLy()));
shun-iwasawa bcd08e
shun-iwasawa bcd08e
    // enlarge bounding box for control images with infinite bbox in case the
shun-iwasawa bcd08e
    // source region is larger than output tile
shun-iwasawa bcd08e
    TRectD bboxForInifiniteSource = ri.m_affine.inv() * outTileBBox;
shun-iwasawa bcd08e
    TRectD sourceBbox;
shun-iwasawa bcd08e
    if (values.source_ctrl_val &&
shun-iwasawa bcd08e
        ctrl_ports.at(values.source_ctrl_val)->isConnected()) {
shun-iwasawa bcd08e
      (*(ctrl_ports.at(values.source_ctrl_val)))
shun-iwasawa bcd08e
          ->getBBox(r_frame, sourceBbox, riAux);
shun-iwasawa bcd08e
    }
shun-iwasawa bcd08e
    if (sourceBbox.isEmpty() || sourceBbox == TConsts::infiniteRectD) {
shun-iwasawa bcd08e
      sourceBbox = TRectD(values.x_pos_val - values.length_val * 0.5,
shun-iwasawa bcd08e
                          values.y_pos_val - values.height_val * 0.5,
shun-iwasawa bcd08e
                          values.x_pos_val + values.length_val * 0.5,
shun-iwasawa bcd08e
                          values.y_pos_val + values.height_val * 0.5);
shun-iwasawa bcd08e
    }
shun-iwasawa bcd08e
    bboxForInifiniteSource += sourceBbox;
shun-iwasawa bcd08e
Shinya Kitaoka 120a6e
    /*- Controlに刺さっている各ポートについて -*/
Shinya Kitaoka 120a6e
    for (std::map<int, *="" trasterfxport="">::iterator it = ctrl_ports.begin();</int,>
Shinya Kitaoka 120a6e
         it != ctrl_ports.end(); ++it) {
Shinya Kitaoka 120a6e
      TTile *tmp;
Shinya Kitaoka 120a6e
      /*- ポートが接続されていて、Fx内で実際に使用されていたら -*/
Shinya Kitaoka 120a6e
      if ((it->second)->isConnected() && port_is_used(it->first, values)) {
Shinya Kitaoka 120a6e
        TRectD bbox;
Shinya Kitaoka 120a6e
        (*(it->second))->getBBox(r_frame, bbox, riAux);
Shinya Kitaoka 120a6e
        /*- 素材が存在する場合、portTilesにコントロール画像タイルを格納 -*/
Shinya Kitaoka 120a6e
        if (!bbox.isEmpty()) {
Shinya Kitaoka 120a6e
          if (bbox == TConsts::infiniteRectD)  // There could be an infinite
Shinya Kitaoka 120a6e
                                               // bbox - deal with it
shun-iwasawa bcd08e
            bbox = bboxForInifiniteSource;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          if (frame <= pcFrame) {
Shinya Kitaoka 120a6e
            // This frame will not actually be rolled. However, it was
Shinya Kitaoka 120a6e
            // dryComputed - so, declare the same here.
Shinya Kitaoka 120a6e
            (*it->second)->dryCompute(bbox, r_frame, riAux);
Shinya Kitaoka 120a6e
          } else {
shun-iwasawa 9ae30f
            // control image is used its gradient
shun-iwasawa 9ae30f
            if (port_is_used_for_gradient(it->first, values)) {
shun-iwasawa 9ae30f
              tmp = new TTile;
Shinya Kitaoka 120a6e
shun-iwasawa 9ae30f
              if (isPrecomputingEnabled)
shun-iwasawa 9ae30f
                (*it->second)
shun-iwasawa 9ae30f
                    ->allocateAndCompute(*tmp, bbox.getP00(),
shun-iwasawa 9ae30f
                                         convert(bbox).getSize(), 0, r_frame,
shun-iwasawa 9ae30f
                                         riAux64);
shun-iwasawa 9ae30f
              else {
shun-iwasawa 9ae30f
                std::string alias =
shun-iwasawa 9ae30f
                    "CTRL64: " + (*(it->second))->getAlias(r_frame, riAux64);
shun-iwasawa 9ae30f
                TRasterImageP rimg = TImageCache::instance()->get(alias, false);
shun-iwasawa 9ae30f
shun-iwasawa 9ae30f
                if (rimg) {
shun-iwasawa 9ae30f
                  tmp->m_pos = bbox.getP00();
shun-iwasawa 9ae30f
                  tmp->setRaster(rimg->getRaster());
shun-iwasawa 9ae30f
                } else {
shun-iwasawa 9ae30f
                  (*it->second)
shun-iwasawa 9ae30f
                      ->allocateAndCompute(*tmp, bbox.getP00(),
shun-iwasawa 9ae30f
                                           convert(bbox).getSize(), 0, r_frame,
shun-iwasawa 9ae30f
                                           riAux64);
shun-iwasawa 9ae30f
shun-iwasawa 9ae30f
                  addRenderCache(alias, TRasterImageP(tmp->getRaster()));
shun-iwasawa 9ae30f
                }
shun-iwasawa 9ae30f
              }
Shinya Kitaoka 120a6e
shun-iwasawa 9ae30f
              porttiles[it->first + Ctrl_64_Offset] = tmp;
shun-iwasawa 9ae30f
shun-iwasawa 9ae30f
              // in case the control image is also used for non-gradient
shun-iwasawa 9ae30f
              if (port_is_used_for_value(it->first, values)) {
shun-iwasawa 9ae30f
                TRaster32P tileRas(tmp->getRaster()->getSize());
shun-iwasawa 9ae30f
                TRop::convert(tileRas, tmp->getRaster());
shun-iwasawa 9ae30f
                tmp        = new TTile;
Shinya Kitaoka 120a6e
                tmp->m_pos = bbox.getP00();
shun-iwasawa 9ae30f
                tmp->setRaster(tileRas);
shun-iwasawa 9ae30f
                porttiles[it->first] = tmp;
shun-iwasawa 9ae30f
              }
shun-iwasawa 9ae30f
            }
shun-iwasawa 9ae30f
            // control images used only for non-gradient
shun-iwasawa 9ae30f
            else {
shun-iwasawa 9ae30f
              tmp = new TTile;
shun-iwasawa 9ae30f
shun-iwasawa 9ae30f
              if (isPrecomputingEnabled)
Shinya Kitaoka 120a6e
                (*it->second)
Shinya Kitaoka 120a6e
                    ->allocateAndCompute(*tmp, bbox.getP00(),
Shinya Kitaoka 120a6e
                                         convert(bbox).getSize(), 0, r_frame,
Shinya Kitaoka 120a6e
                                         riAux);
shun-iwasawa 9ae30f
              else {
shun-iwasawa 9ae30f
                std::string alias =
shun-iwasawa 9ae30f
                    "CTRL: " + (*(it->second))->getAlias(r_frame, riAux);
shun-iwasawa 9ae30f
                TRasterImageP rimg = TImageCache::instance()->get(alias, false);
shun-iwasawa 9ae30f
shun-iwasawa 9ae30f
                if (rimg) {
shun-iwasawa 9ae30f
                  tmp->m_pos = bbox.getP00();
shun-iwasawa 9ae30f
                  tmp->setRaster(rimg->getRaster());
shun-iwasawa 9ae30f
                } else {
shun-iwasawa 9ae30f
                  (*it->second)
shun-iwasawa 9ae30f
                      ->allocateAndCompute(*tmp, bbox.getP00(),
shun-iwasawa 9ae30f
                                           convert(bbox).getSize(), 0, r_frame,
shun-iwasawa 9ae30f
                                           riAux);
shun-iwasawa 9ae30f
shun-iwasawa 9ae30f
                  addRenderCache(alias, TRasterImageP(tmp->getRaster()));
shun-iwasawa 9ae30f
                }
Shinya Kitaoka 120a6e
              }
Shinya Kitaoka 120a6e
shun-iwasawa 9ae30f
              porttiles[it->first] = tmp;
shun-iwasawa 9ae30f
            }
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (frame > pcFrame) {
Shinya Kitaoka 120a6e
      // Invoke the actual rolling procedure
Shinya Kitaoka 120a6e
      roll_particles(tile, porttiles, riAux, myParticles, values, 0, 0, frame,
Shinya Kitaoka 120a6e
                     curr_frame, level_n, &random_level, 1, last_frame,
Shinya Kitaoka 120a6e
                     totalparticles);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // Store the rolled data in the particles manager
Shinya Kitaoka 120a6e
      if (!particlesData->m_calculated ||
Shinya Kitaoka 120a6e
          particlesData->m_frame + particlesData->m_maxTrail < frame) {
Shinya Kitaoka 120a6e
        particlesData->m_frame     = frame;
Shinya Kitaoka 120a6e
        particlesData->m_particles = myParticles;
Shinya Kitaoka 120a6e
        particlesData->m_random    = myRandom;
Shinya Kitaoka 120a6e
        particlesData->buildMaxTrail();
Shinya Kitaoka 120a6e
        particlesData->m_calculated     = true;
Shinya Kitaoka 120a6e
        particlesData->m_totalParticles = totalparticles;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Render the particles if the distance from current frame is a trail
Shinya Kitaoka 120a6e
    // multiple
Shinya Kitaoka 120a6e
    if (frame >= startframe - 1 &&
Shinya Kitaoka 120a6e
        !(dist_frame %
Shinya Kitaoka 120a6e
          (values.trailstep_val > 1.0 ? (int)values.trailstep_val : 1))) {
Shinya Kitaoka 120a6e
      // Store the maximum particle size before the do_render cycle
Shinya Kitaoka 120a6e
      std::list<particle>::iterator pt;</particle>
Shinya Kitaoka 120a6e
      for (pt = myParticles.begin(); pt != myParticles.end(); ++pt) {
Shinya Kitaoka 120a6e
        Particle &part = *pt;
Shinya Kitaoka 120a6e
        int ndx        = part.frame % last_frame[part.level];
Shinya Kitaoka 120a6e
        std::pair<int, int=""> ndxPair(part.level, ndx);</int,>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        std::map<std::pair<int, int="">, double>::iterator it =</std::pair<int,>
Shinya Kitaoka 120a6e
            partScales.find(ndxPair);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (it != partScales.end())
Shinya Kitaoka 120a6e
          it->second = std::max(part.scale, it->second);
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
          partScales[ndxPair] = part.scale;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (values.toplayer_val == ParticlesFx::TOP_SMALLER ||
Shinya Kitaoka 120a6e
          values.toplayer_val == ParticlesFx::TOP_BIGGER)
Shinya Kitaoka 120a6e
        myParticles.sort(ComparebySize());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (values.toplayer_val == ParticlesFx::TOP_SMALLER) {
Shinya Kitaoka 120a6e
        std::list<particle>::iterator pt;</particle>
Shinya Kitaoka 120a6e
        for (pt = myParticles.begin(); pt != myParticles.end(); ++pt) {
Shinya Kitaoka 120a6e
          Particle &part = *pt;
Shinya Kitaoka 120a6e
          if (dist_frame <= part.trail && part.scale && part.lifetime > 0 &&
Shinya Kitaoka 120a6e
              part.lifetime <=
Shinya Kitaoka 120a6e
                  part.genlifetime)  // This last... shouldn't always be?
Shinya Kitaoka 120a6e
          {
Jeremy Bullock 852210
            do_render(&part, tile, part_ports, porttiles, ri, p_size, p_offset,
Jeremy Bullock 852210
                      last_frame[part.level], partLevel, values, opacity_range,
Jeremy Bullock 852210
                      dist_frame, partScales);
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        std::list<particle>::reverse_iterator pt;</particle>
Shinya Kitaoka 120a6e
        for (pt = myParticles.rbegin(); pt != myParticles.rend(); ++pt) {
Shinya Kitaoka 120a6e
          Particle &part = *pt;
Shinya Kitaoka 120a6e
          if (dist_frame <= part.trail && part.scale && part.lifetime > 0 &&
Shinya Kitaoka 120a6e
              part.lifetime <= part.genlifetime)  // Same here..?
Shinya Kitaoka 120a6e
          {
Jeremy Bullock 852210
            do_render(&part, tile, part_ports, porttiles, ri, p_size, p_offset,
Jeremy Bullock 852210
                      last_frame[part.level], partLevel, values, opacity_range,
Jeremy Bullock 852210
                      dist_frame, partScales);
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    std::map<int, *="" ttile="">::iterator it;</int,>
Shinya Kitaoka 120a6e
    for (it = porttiles.begin(); it != porttiles.end(); ++it) delete it->second;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*- render_particles から呼ばれる。粒子の数だけ繰り返し -*/
Shinya Kitaoka 120a6e
void Particles_Engine::do_render(
Jeremy Bullock 852210
    Particle *part, TTile *tile, std::vector<trasterfxport *=""> part_ports,</trasterfxport>
Jeremy Bullock 852210
    std::map<int, *="" ttile=""> porttiles, const TRenderSettings &ri,</int,>
Jeremy Bullock 852210
    TDimension &p_size, TPointD &p_offset, int lastframe,
Jeremy Bullock 852210
    std::vector<tlevelp> partLevel, struct particles_values &values,</tlevelp>
Jeremy Bullock 852210
    double opacity_range, int dist_frame,
Shinya Kitaoka 120a6e
    std::map<std::pair<int, int="">, double> &partScales) {</std::pair<int,>
Shinya Kitaoka 120a6e
  // Retrieve the particle frame - that is, the *column frame* from which we are
Shinya Kitaoka 120a6e
  // picking
Shinya Kitaoka 120a6e
  // the particle to be rendered.
Shinya Kitaoka 120a6e
  int ndx = part->frame % lastframe;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRasterP tileRas(tile->getRaster());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::string levelid;
Shinya Kitaoka 120a6e
  double aim_angle = 0;
Shinya Kitaoka 120a6e
  if (values.pathaim_val) {
Shinya Kitaoka 120a6e
    double arctan = atan2(part->vy, part->vx);
Shinya Kitaoka 120a6e
    aim_angle     = arctan * M_180_PI;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Calculate the rotational and scale components we have to apply on the
Shinya Kitaoka 120a6e
  // particle
Shinya Kitaoka 120a6e
  TRotation rotM(part->angle + aim_angle);
Shinya Kitaoka 120a6e
  TScale scaleM(part->scale);
Shinya Kitaoka 120a6e
  TAffine M(rotM * scaleM);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Particles deal with dpi affines on their own
Shinya Kitaoka 120a6e
  TAffine scaleAff(m_parent->handledAffine(ri, m_frame));
Shinya Kitaoka 120a6e
  double partScale =
Shinya Kitaoka 120a6e
      scaleAff.a11 * partScales[std::pair<int, int="">(part->level, ndx)];</int,>
Shinya Kitaoka 120a6e
  TDimensionD partResolution(0, 0);
Shinya Kitaoka 120a6e
  TRenderSettings riNew(ri);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Retrieve the bounding box in the standard reference
Shinya Kitaoka 120a6e
  TRectD bbox(-5.0, -5.0, 5.0, 5.0), standardRefBBox;
Shinya Kitaoka 120a6e
  if (part->level <
Shinya Kitaoka 120a6e
          (int)part_ports.size() &&  // Not the default levelless cases
Shinya Kitaoka 120a6e
      part_ports[part->level]->isConnected()) {
Shinya Kitaoka 120a6e
    TRenderSettings riIdentity(ri);
Shinya Kitaoka 120a6e
    riIdentity.m_affine = TAffine();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    (*part_ports[part->level])->getBBox(ndx, bbox, riIdentity);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // A particle's bbox MUST be finite. Gradients and such which have an
Shinya Kitaoka 120a6e
    // infinite bbox
Shinya Kitaoka 120a6e
    // are just NOT rendered.
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // NOTE: No fx returns half-planes or similar (ie if any coordinate is
Shinya Kitaoka 120a6e
    // either
Shinya Kitaoka 120a6e
    // (std::numeric_limits<double>::max)() or its opposite, then the rect IS</double>
Shinya Kitaoka 120a6e
    // THE infiniteRectD)
shun-iwasawa a26c46
    if (bbox.isEmpty() || bbox == TConsts::infiniteRectD) return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Now, these are the particle rendering specifications
Shinya Kitaoka 120a6e
  bbox            = bbox.enlarge(3);
Shinya Kitaoka 120a6e
  standardRefBBox = bbox;
Shinya Kitaoka 120a6e
  riNew.m_affine  = TScale(partScale);
Shinya Kitaoka 120a6e
  bbox            = riNew.m_affine * bbox;
Shinya Kitaoka 120a6e
  /*- 縮小済みのParticleのサイズ -*/
Shinya Kitaoka 120a6e
  partResolution = TDimensionD(tceil(bbox.getLx()), tceil(bbox.getLy()));
Shinya Kitaoka 120a6e
Jeremy Bullock 852210
  TRasterP ras;
Shinya Kitaoka 120a6e
Jeremy Bullock 852210
  std::string alias;
Jeremy Bullock 852210
  TRasterImageP rimg;
Jeremy Bullock 852210
  rimg = partLevel[part->level]->frame(ndx);
Jeremy Bullock 852210
  if (rimg) {
Jeremy Bullock 852210
    ras = rimg->getRaster();
Jeremy Bullock 852210
  } else {
Jeremy Bullock 852210
    alias = "PART: " + (*part_ports[part->level])->getAlias(ndx, riNew);
Jeremy Bullock 852210
    rimg  = TImageCache::instance()->get(alias, false);
Rozhuk Ivan 823a31
    if (rimg) {
Shinya Kitaoka 120a6e
      ras = rimg->getRaster();
Shinya Kitaoka 120a6e
Jeremy Bullock 852210
      // Check that the raster resolution is sufficient for our purposes
Jeremy Bullock 852210
      if (ras->getLx() < partResolution.lx || ras->getLy() < partResolution.ly)
Jeremy Bullock 852210
        ras = 0;
Jeremy Bullock 852210
      else
Jeremy Bullock 852210
        partResolution = TDimensionD(ras->getLx(), ras->getLy());
Jeremy Bullock 852210
    }
Jeremy Bullock 852210
  }
Shinya Kitaoka 120a6e
Jeremy Bullock 852210
  // We are interested in making the relation between scale and (integer)
Jeremy Bullock 852210
  // resolution
Jeremy Bullock 852210
  // bijective - since we shall cache by using resolution as a partial
Jeremy Bullock 852210
  // identification parameter.
Jeremy Bullock 852210
  // Therefore, we find the current bbox Lx and take a unique scale out of it.
Jeremy Bullock 852210
  partScale      = partResolution.lx / standardRefBBox.getLx();
Jeremy Bullock 852210
  riNew.m_affine = TScale(partScale);
Jeremy Bullock 852210
  bbox           = riNew.m_affine * standardRefBBox;
Jeremy Bullock 852210
Jeremy Bullock 852210
  // If no image was retrieved from the cache (or it was not scaled enough),
Jeremy Bullock 852210
  // calculate it
Jeremy Bullock 852210
  if (!ras) {
Jeremy Bullock 852210
    TTile auxTile;
Jeremy Bullock 852210
    (*part_ports[part->level])
Jeremy Bullock 852210
        ->allocateAndCompute(auxTile, bbox.getP00(),
Jeremy Bullock 852210
                             TDimension(partResolution.lx, partResolution.ly),
Jeremy Bullock 852210
                             tile->getRaster(), ndx, riNew);
Jeremy Bullock 852210
    ras = auxTile.getRaster();
Jeremy Bullock 852210
Jeremy Bullock 852210
    // For now, we'll just use 32 bit particles
Jeremy Bullock 852210
    TRaster32P rcachepart;
Jeremy Bullock 852210
    rcachepart = ras;
Jeremy Bullock 852210
    if (!rcachepart) {
Jeremy Bullock 852210
      rcachepart = TRaster32P(ras->getSize());
Jeremy Bullock 852210
      TRop::convert(rcachepart, ras);
Shinya Kitaoka 120a6e
    }
Jeremy Bullock 852210
    ras = rcachepart;
Shinya Kitaoka 120a6e
Jeremy Bullock 852210
    // Finally, cache the particle
Jeremy Bullock 852210
    addRenderCache(alias, TRasterImageP(ras));
Jeremy Bullock 852210
  }
Jeremy Bullock 852210
Jeremy Bullock 852210
  if (!ras) return;  // At this point, it should never happen anyway...
Jeremy Bullock 852210
Jeremy Bullock 852210
  // Deal with particle colors/opacity
Jeremy Bullock 852210
  TRaster32P rfinalpart;
Jeremy Bullock 852210
  double curr_opacity =
Jeremy Bullock 852210
      part->set_Opacity(porttiles, values, opacity_range, dist_frame);
Jeremy Bullock 852210
  if (curr_opacity != 1.0 || part->gencol.fadecol || part->fincol.fadecol ||
Jeremy Bullock 852210
      part->foutcol.fadecol) {
Jeremy Bullock 852210
    /*- 毎フレーム現在位置のピクセル色を参照 -*/
Jeremy Bullock 852210
    if (values.pick_color_for_every_frame_val && values.gencol_ctrl_val &&
Jeremy Bullock 852210
        (porttiles.find(values.gencol_ctrl_val) != porttiles.end()))
Jeremy Bullock 852210
      part->get_image_reference(porttiles[values.gencol_ctrl_val], values,
Jeremy Bullock 852210
                                part->gencol.col);
Jeremy Bullock 852210
Jeremy Bullock 852210
    rfinalpart = ras->clone();
Jeremy Bullock 852210
    part->modify_colors_and_opacity(values, curr_opacity, dist_frame,
Jeremy Bullock 852210
                                    rfinalpart);
Jeremy Bullock 852210
  } else
Jeremy Bullock 852210
    rfinalpart = ras;
Jeremy Bullock 852210
Jeremy Bullock 852210
  // Now, let's build the particle transform before it is overed on the output
Jeremy Bullock 852210
  // tile
Jeremy Bullock 852210
Jeremy Bullock 852210
  // First, complete the transform by adding the rotational and scale
Jeremy Bullock 852210
  // components from
Jeremy Bullock 852210
  // Particles parameters
Jeremy Bullock 852210
  M = ri.m_affine * M * TScale(1.0 / partScale);
Jeremy Bullock 852210
Jeremy Bullock 852210
  // Then, retrieve the particle position in current reference.
Jeremy Bullock 852210
  TPointD pos(part->x, part->y);
Jeremy Bullock 852210
  pos = ri.m_affine * pos;
Jeremy Bullock 852210
Jeremy Bullock 852210
  // Finally, add the translational component to the particle
Jeremy Bullock 852210
  // NOTE: p_offset is added to account for the particle relative position
Jeremy Bullock 852210
  // inside its level's bbox
Jeremy Bullock 852210
  M = TTranslation(pos - tile->m_pos) * M * TTranslation(bbox.getP00());
Jeremy Bullock 852210
Jeremy Bullock 852210
  if (TRaster32P myras32 = tile->getRaster())
Jeremy Bullock 852210
    TRop::over(tileRas, rfinalpart, M);
Jeremy Bullock 852210
  else if (TRaster64P myras64 = tile->getRaster())
Jeremy Bullock 852210
    TRop::over(tileRas, rfinalpart, M);
Jeremy Bullock 852210
  else
Jeremy Bullock 852210
    throw TException("ParticlesFx: unsupported Pixel Type");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*-----------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void Particles_Engine::fill_array(TTile *ctrl1, int ®ioncount,
Shinya Kitaoka 120a6e
                                  std::vector<int> &myarray,</int>
Shinya Kitaoka 120a6e
                                  std::vector<int> &lista,</int>
Shinya Kitaoka 120a6e
                                  std::vector<int> &listb, int threshold) {</int>
Shinya Kitaoka 120a6e
  int pr = 0;
Shinya Kitaoka 120a6e
  int i, j;
Shinya Kitaoka 120a6e
  int lx, ly;
Shinya Kitaoka 120a6e
  lx = ctrl1->getRaster()->getLx();
Shinya Kitaoka 120a6e
  ly = ctrl1->getRaster()->getLy();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*prima riga*/
Shinya Kitaoka 120a6e
  TRaster32P raster32 = ctrl1->getRaster();
Shinya Kitaoka 120a6e
  raster32->lock();
Shinya Kitaoka 120a6e
  TPixel32 *pix = raster32->pixels(0);
Shinya Kitaoka 120a6e
  for (i = 0; i < lx; i++) {
Shinya Kitaoka 120a6e
    if (pix->m > threshold) {
Shinya Kitaoka 120a6e
      pr++;
Shinya Kitaoka 120a6e
      if (!i) {
Shinya Kitaoka 120a6e
        (regioncount)++;
Shinya Kitaoka 120a6e
        myarray[i] = (regioncount);
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        if (myarray[i - 1]) myarray[i] = myarray[i - 1];
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Rozhuk Ivan 823a31
    pix++;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (j = 1; j < ly; j++) {
Shinya Kitaoka 120a6e
    for (i = 0, pix = raster32->pixels(j); i < lx; i++, pix++) {
Shinya Kitaoka 120a6e
      /*TMSG_INFO("j=%d i=%d\n", j, i);*/
Shinya Kitaoka 120a6e
      if (pix->m > threshold) {
Shinya Kitaoka 120a6e
        std::vector<int> mask(4);</int>
Shinya Kitaoka 120a6e
        pr++;
Shinya Kitaoka 120a6e
        /* l,ul,u,ur;*/
Shinya Kitaoka 120a6e
        if (i) {
Shinya Kitaoka 120a6e
          mask[0] = myarray[i - 1 + lx * j];
Shinya Kitaoka 120a6e
          mask[1] = myarray[i - 1 + lx * (j - 1)];
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        if (i != lx - 1) mask[3] = myarray[i + 1 + lx * (j - 1)];
shun-iwasawa 9ae30f
        mask[2] = myarray[i + lx * (j - 1)];
Shinya Kitaoka 120a6e
        if (!mask[0] && !mask[1] && !mask[2] && !mask[3]) {
Shinya Kitaoka 120a6e
          (regioncount)++;
Shinya Kitaoka 120a6e
          myarray[i + lx * j] = (regioncount);
Shinya Kitaoka 120a6e
        } else {
Shinya Kitaoka 120a6e
          int mc, firsttime = 1;
Shinya Kitaoka 120a6e
          for (mc = 0; mc < 4; mc++) {
Shinya Kitaoka 120a6e
            if (mask[mc]) {
Shinya Kitaoka 120a6e
              if (firsttime) {
Shinya Kitaoka 120a6e
                myarray[i + lx * j] = mask[mc];
Shinya Kitaoka 120a6e
                firsttime           = 0;
Shinya Kitaoka 120a6e
              } else {
Shinya Kitaoka 120a6e
                if (myarray[i + lx * j] != mask[mc]) {
Shinya Kitaoka 120a6e
                  lista.push_back(myarray[i + lx * j]);
Shinya Kitaoka 120a6e
                  listb.push_back(mask[mc]);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
                  /*TMSG_INFO("j=%d i=%d mc=%d, mask=%d\n", j, i, mc,
Shinya Kitaoka 120a6e
                   * mask[mc]);*/
Shinya Kitaoka 120a6e
                }
Shinya Kitaoka 120a6e
              }
Shinya Kitaoka 120a6e
            }
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  raster32->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*-----------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void Particles_Engine::normalize_array(
Shinya Kitaoka 120a6e
    std::vector<std::vector<tpointd>> &myregions, TPointD pos, int lx, int ly,</std::vector<tpointd>
Shinya Kitaoka 120a6e
    int regioncounter, std::vector<int> &myarray, std::vector<int> &lista,</int></int>
shun-iwasawa 9ae30f
    std::vector<int> &listb, std::vector<int> &final) {</int></int>
Shinya Kitaoka 120a6e
  int i, j, k, l;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::vector<int> tmp;</int>
Shinya Kitaoka 120a6e
  int maxregioncounter = 0;
Shinya Kitaoka 120a6e
  int listsize         = (int)lista.size();
Shinya Kitaoka 120a6e
  // TMSG_INFO("regioncounter %d, eqcount=%d\n", regioncounter, eqcount);
Shinya Kitaoka 120a6e
  for (k = 1; k <= regioncounter; k++) final[k] = k;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (l = 0; l < listsize; l++) {
Shinya Kitaoka 120a6e
    j = lista[l];
Shinya Kitaoka 120a6e
    /*TMSG_INFO("j vale %d\n", j);*/
Shinya Kitaoka 120a6e
    while (final[j] != j) j = final[j];
shun-iwasawa 9ae30f
    k = listb[l];
Shinya Kitaoka 120a6e
    /*TMSG_INFO("k vale %d\n", k);*/
Shinya Kitaoka 120a6e
    while (final[k] != k) k = final[k];
shun-iwasawa 9ae30f
    if (j != k) final[j] = k;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  // TMSG_INFO("esco dal for\n");
shun-iwasawa 9ae30f
  for (j = 1; j <= regioncounter; j++)
Shinya Kitaoka 120a6e
    while (final[j] != final[final[j]]) final[j] = final[final[j]];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  /*conto quante cavolo di regioni sono*/
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  tmp.push_back(final[1]);
Shinya Kitaoka 120a6e
  maxregioncounter = 1;
Shinya Kitaoka 120a6e
  for (i = 2; i <= regioncounter; i++) {
Shinya Kitaoka 120a6e
    int diff = 1;
Shinya Kitaoka 120a6e
    for (j = 0; j < maxregioncounter; j++) {
Shinya Kitaoka 120a6e
      if (tmp[j] == final[i]) {
Shinya Kitaoka 120a6e
        diff = 0;
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (diff) {
Shinya Kitaoka 120a6e
      tmp.push_back(final[i]);
Shinya Kitaoka 120a6e
      maxregioncounter++;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  myregions.resize(maxregioncounter);
Shinya Kitaoka 120a6e
  for (j = 0; j < ly; j++) {
Shinya Kitaoka 120a6e
    for (i = 0; i < lx; i++) {
Shinya Kitaoka 120a6e
      int tmpindex;
Shinya Kitaoka 120a6e
      if (myarray[i + lx * j]) {
Shinya Kitaoka 120a6e
        tmpindex = final[myarray[i + lx * j]];
Shinya Kitaoka 120a6e
        /*TMSG_INFO("tmpindex=%d\n", tmpindex);*/
Shinya Kitaoka 120a6e
        for (k = 0; k < maxregioncounter; k++) {
Shinya Kitaoka 120a6e
          if (tmp[k] == tmpindex) break;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        /*TMSG_INFO("k=%d\n", k);*/
Shinya Kitaoka 120a6e
        TPointD tmppoint;
Shinya Kitaoka 120a6e
        tmppoint.x = i;
Shinya Kitaoka 120a6e
        tmppoint.y = j;
Shinya Kitaoka 120a6e
        tmppoint += pos;
Shinya Kitaoka 120a6e
        myregions[k].push_back(tmppoint);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*-----------------------------------------------------------------*/
Toshihiro Shimizu 890ddd
/*- multiがONのときのSource画像(ctrl1)の領域を分析 -*/
Shinya Kitaoka 120a6e
void Particles_Engine::fill_subregions(
Shinya Kitaoka 120a6e
    int cont_index, std::vector<std::vector<tpointd>> &myregions, TTile *ctrl1,</std::vector<tpointd>
Shinya Kitaoka 120a6e
    int thres) {
Shinya Kitaoka 120a6e
  int regioncounter = 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int lx = ctrl1->getRaster()->getLx();
Shinya Kitaoka 120a6e
  int ly = ctrl1->getRaster()->getLy();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::vector<int> myarray(lx * ly);</int>
Shinya Kitaoka 120a6e
  std::vector<int> lista;</int>
Shinya Kitaoka 120a6e
  std::vector<int> listb;</int>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  fill_array(ctrl1, regioncounter, myarray, lista, listb, thres);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (regioncounter) {
Shinya Kitaoka 120a6e
    std::vector<int> final(regioncounter + 1);</int>
Shinya Kitaoka 120a6e
    normalize_array(myregions, ctrl1->m_pos, lx, ly, regioncounter, myarray,
Shinya Kitaoka 120a6e
                    lista, listb, final);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*-----------------------------------------------------------------*/
Shinya Kitaoka 120a6e
/*- 入力画像のアルファ値に比例して発生濃度を変える。各Pointにウェイトを持たせる
Shinya Kitaoka 120a6e
 * -*/
Shinya Kitaoka 120a6e
void Particles_Engine::fill_single_region(
Shinya Kitaoka 120a6e
    std::vector<std::vector<tpointd>> &myregions, TTile *ctrl1, int threshold,</std::vector<tpointd>
Shinya Kitaoka 120a6e
    bool do_source_gradation, std::vector<std::vector<int>> &myHistogram) {</std::vector<int>
Shinya Kitaoka 120a6e
  TRaster32P raster32 = ctrl1->getRaster();
Shinya Kitaoka 120a6e
  assert(raster32);  // per ora gestisco solo i Raster32
Shinya Kitaoka 120a6e
                     //  int lx=raster32->getLx();
Shinya Kitaoka 120a6e
                     //  int ly=raster32->getLy();
Shinya Kitaoka 120a6e
  int j;
Shinya Kitaoka 120a6e
  myregions.resize(1);
Shinya Kitaoka 120a6e
  myregions[0].clear();
Shinya Kitaoka 120a6e
  int cc  = 0;
Shinya Kitaoka 120a6e
  int icc = 0;
Shinya Kitaoka 120a6e
  raster32->lock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!do_source_gradation) /*- 2階調の場合 -*/
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    for (j = 0; j < raster32->getLy(); j++) {
Shinya Kitaoka 120a6e
      TPixel32 *pix    = raster32->pixels(j);
Shinya Kitaoka 120a6e
      TPixel32 *endPix = pix + raster32->getLx();
Shinya Kitaoka 120a6e
      int i            = 0;
Shinya Kitaoka 120a6e
      while (pix < endPix) {
Shinya Kitaoka 120a6e
        cc++;
Shinya Kitaoka 120a6e
        if (pix->m > threshold) {
Shinya Kitaoka 120a6e
          icc++;
Shinya Kitaoka 120a6e
          TPointD tmp;
Shinya Kitaoka 120a6e
          tmp.y = j;
Shinya Kitaoka 120a6e
          tmp.x = i;
Shinya Kitaoka 120a6e
          tmp += ctrl1->m_pos;
Shinya Kitaoka 120a6e
          myregions[0].push_back(tmp);
Shinya Kitaoka 120a6e
          /*TMSG_INFO("total=%d\n", Region[0].total);*/
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        } else {
Shinya Kitaoka 120a6e
          //           int a=0;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        i++;
Rozhuk Ivan 823a31
        pix++;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    for (int i = 0; i < 256; i++) myHistogram.push_back(std::vector<int>());</int>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TRandom rand = TRandom(1);
Shinya Kitaoka 120a6e
    for (j = 0; j < raster32->getLy(); j++) {
Shinya Kitaoka 120a6e
      TPixel32 *pix    = raster32->pixels(j);
Shinya Kitaoka 120a6e
      TPixel32 *endPix = pix + raster32->getLx();
Shinya Kitaoka 120a6e
      int i            = 0;
Shinya Kitaoka 120a6e
      while (pix < endPix) {
Shinya Kitaoka 120a6e
        cc++;
Shinya Kitaoka 120a6e
        /*-- アルファの濃度に比例してパーティクルを発生させるための、
Shinya Kitaoka 120a6e
                シンプルな方法。そのピクセルのアルファ値の数だけ「立候補」させる。
Shinya Kitaoka 120a6e
        --*/
Shinya Kitaoka 120a6e
        if (pix->m > 0) {
Shinya Kitaoka 120a6e
          icc++;
Shinya Kitaoka 120a6e
          TPointD tmp;
Shinya Kitaoka 120a6e
          tmp.y = j;
Shinya Kitaoka 120a6e
          tmp.x = i;
Shinya Kitaoka 120a6e
          tmp += ctrl1->m_pos;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          /*- Histogramの登録 -*/
Shinya Kitaoka 120a6e
          myHistogram[(int)pix->m].push_back((int)myregions[0].size());
Shinya Kitaoka 120a6e
          /*-  各Pointにウェイトを持たせる -*/
Shinya Kitaoka 120a6e
          myregions[0].push_back(tmp);
Shinya Kitaoka 120a6e
        } else {
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
        i++;
Rozhuk Ivan 823a31
        pix++;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (myregions[0].size() == 0) myregions.resize(0);
Shinya Kitaoka 120a6e
  raster32->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*-----------------------------------------------------------------*/
Shinya Kitaoka 120a6e
/*-
Shinya Kitaoka 120a6e
 * 入力画像のアルファ値に比例して発生濃度を変える。Histogramを格納しながら領域を登録
Shinya Kitaoka 120a6e
 * -*/
Shinya Kitaoka 120a6e
void Particles_Engine::fill_regions(
Shinya Kitaoka 120a6e
    int frame, std::vector<std::vector<tpointd>> &myregions, TTile *ctrl1,</std::vector<tpointd>
Shinya Kitaoka 120a6e
    bool multi, int thres, bool do_source_gradation,
Shinya Kitaoka 120a6e
    std::vector<std::vector<int>> &myHistogram) {</std::vector<int>
Shinya Kitaoka 120a6e
  TRaster32P ctrl1ras = ctrl1->getRaster();
Shinya Kitaoka 120a6e
  if (!ctrl1ras) return;
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
  if (frame <= 0)
Shinya Kitaoka 120a6e
    i = 0;
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    i = frame;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (multi) {
Shinya Kitaoka 120a6e
    fill_subregions(i, myregions, ctrl1, thres);
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    fill_single_region(myregions, ctrl1, thres, do_source_gradation,
Shinya Kitaoka 120a6e
                       myHistogram);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------
Shinya Kitaoka 120a6e
/*-- Perspective
Shinya Kitaoka 120a6e
DistributionがONのとき、Sizeに刺さったControlImageが粒子の発生分布を決める。
Shinya Kitaoka 120a6e
        そのとき、SourceのControlが刺さっている場合は、マスクとして用いられる
Toshihiro Shimizu 890ddd
--*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void Particles_Engine::fill_regions_with_size_map(
Shinya Kitaoka 120a6e
    std::vector<std::vector<tpointd>> &myregions,</std::vector<tpointd>
Shinya Kitaoka 120a6e
    std::vector<std::vector<int>> &myHistogram, TTile *sizeTile,</std::vector<int>
Shinya Kitaoka 120a6e
    TTile *sourceTile, int thres) {
Shinya Kitaoka 120a6e
  TRaster32P sizeRas = sizeTile->getRaster();
Shinya Kitaoka 120a6e
  if (!sizeRas) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRaster32P sourceRas;
Shinya Kitaoka 120a6e
  if (sourceTile) sourceRas = sourceTile->getRaster();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  sizeRas->lock();
Shinya Kitaoka 120a6e
  if (sourceRas) sourceRas->lock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  myregions.resize(1);
Shinya Kitaoka 120a6e
  myregions[0].clear();
Shinya Kitaoka 120a6e
  for (int i = 0; i < 256; i++) myHistogram.push_back(std::vector<int>());</int>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (int j = 0; j < sizeRas->getLy(); j++) {
Shinya Kitaoka 120a6e
    TPixel32 *pix    = sizeRas->pixels(j);
Shinya Kitaoka 120a6e
    TPixel32 *endPix = pix + sizeRas->getLx();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TPixel32 *sourcePixHead = 0;
Shinya Kitaoka 120a6e
    if (sourceRas) {
Shinya Kitaoka 120a6e
      int sourceYPos = troundp(j + sizeTile->m_pos.y - sourceTile->m_pos.y);
Shinya Kitaoka 120a6e
      if (sourceYPos >= 0 && sourceYPos < sourceRas->getLy())
Shinya Kitaoka 120a6e
        sourcePixHead = sourceRas->pixels(sourceYPos);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int i               = 0;
Shinya Kitaoka 120a6e
    TPixel32 *sourcePix = 0;
Shinya Kitaoka 120a6e
    while (pix < endPix) {
Shinya Kitaoka 120a6e
      if (sourceRas) {
Shinya Kitaoka 120a6e
        int sourceXPos = (int)(i + sizeTile->m_pos.x - sourceTile->m_pos.x);
Shinya Kitaoka 120a6e
        if (sourcePixHead && sourceXPos >= 0 && sourceXPos < sourceRas->getLx())
Shinya Kitaoka 120a6e
          sourcePix = sourcePixHead + sourceXPos;
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
          sourcePix = 0;
Shinya Kitaoka 120a6e
      } else
Shinya Kitaoka 120a6e
        sourcePix = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      /*-
Shinya Kitaoka 120a6e
       * Source画像があって、ピクセルがバウンディング外またはアルファが0なら抜かす。
Shinya Kitaoka 120a6e
       * -*/
Shinya Kitaoka 120a6e
      if (sourceRas && (!sourcePix || sourcePix->m <= thres)) {
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      /*-
Shinya Kitaoka 120a6e
         明度に比例してパーティクルを発生させる。そのピクセルのアルファ値の数だけ「立候補」させる。-*/
Shinya Kitaoka 120a6e
      else {
Shinya Kitaoka 120a6e
        TPointD tmp;
Shinya Kitaoka 120a6e
        tmp.y = j;
Shinya Kitaoka 120a6e
        tmp.x = i;
Shinya Kitaoka 120a6e
        tmp += sizeTile->m_pos;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        int val = (int)TPixelGR8::from(*pix).value;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        /*- Histogramの登録 -*/
Shinya Kitaoka 120a6e
        myHistogram[val].push_back((int)myregions[0].size());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        /*- 各Pointにウェイトを持たせる -*/
Shinya Kitaoka 120a6e
        myregions[0].push_back(tmp);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      i++;
Shinya Kitaoka 120a6e
      pix++;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (myregions[0].size() == 0) myregions.resize(0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  sizeRas->unlock();
Shinya Kitaoka 120a6e
  if (sourceRas) sourceRas->unlock();
Toshihiro Shimizu 890ddd
}