particles fx motion blur
This commit is contained in:
parent
1f338049db
commit
a74ae094a0
|
@ -821,6 +821,8 @@
|
|||
<item>"STD_particlesFx.source_gradation" "Use Control Image Gradation" </item>
|
||||
<item>"STD_particlesFx.pick_color_for_every_frame" "Pick Control Image's Color for Every Frame" </item>
|
||||
<item>"STD_particlesFx.perspective_distribution" "Perspective Distribution" </item>
|
||||
<item>"STD_particlesFx.motion_blur" "Motion Blur" </item>
|
||||
<item>"STD_particlesFx.motion_blur_gamma" "Gamma" </item>
|
||||
|
||||
|
||||
<!------------------------------ Function Editor ------------------------------------------->
|
||||
|
|
|
@ -599,25 +599,6 @@ rt
|
|||
<td class=xl7729647 width=103 style='border-top:none;border-left:none;
|
||||
width:77pt'>○</td>
|
||||
</tr>
|
||||
<tr height=24 style='mso-height-source:userset;height:18.0pt'>
|
||||
<td height=24 class=xl7029647 width=89 style='height:18.0pt;width:67pt'> </td>
|
||||
<td class=xl6929647 width=83 style='border-top:none;border-left:none;
|
||||
width:62pt'>Trail</td>
|
||||
<td class=xl6729647 width=161 style='border-top:none;width:121pt'>Trail</td>
|
||||
<td class=xl6629647 width=474 style='border-top:none;border-left:none;
|
||||
width:356pt'>Muestra una estela para cada partícula, que se desvanecerá a lo largo de la cantidad de fotogramas especificados en el parámetro Trail.</td>
|
||||
<td class=xl7729647 width=103 style='border-top:none;border-left:none;
|
||||
width:77pt'>―</td>
|
||||
</tr>
|
||||
<tr height=42 style='mso-height-source:userset;height:31.5pt'>
|
||||
<td height=42 class=xl7029647 width=89 style='height:31.5pt;width:67pt'> </td>
|
||||
<td class=xl7329647 width=83 style='width:62pt'> </td>
|
||||
<td class=xl6729647 width=161 style='border-top:none;width:121pt'>Step</td>
|
||||
<td class=xl6629647 width=474 style='border-top:none;border-left:none;
|
||||
width:356pt'>Permite definir cuántas imágenes se mostrarán en la estela. Cada estela estará compuesta por (Trail/Step) imágenes.</td>
|
||||
<td class=xl7729647 width=103 style='border-top:none;border-left:none;
|
||||
width:77pt'>―</td>
|
||||
</tr>
|
||||
<tr height=36 style='height:27.0pt'>
|
||||
<td height=36 class=xl7029647 width=89 style='height:27.0pt;width:67pt'> </td>
|
||||
<td class=xl7129647 width=83 style='border-top:none;width:62pt'>Lifetime</td>
|
||||
|
@ -855,6 +836,43 @@ rt
|
|||
<td class=xl7729647 width=103 style='border-top:none;border-left:none;
|
||||
width:77pt'>―</td>
|
||||
</tr>
|
||||
<tr height=24 style='mso-height-source:userset;height:18.0pt'>
|
||||
<td height=24 class=xl7029647 width=89 style='height:18.0pt;width:67pt'> </td>
|
||||
<td class=xl6929647 width=83 style='border-top:none;border-left:none;
|
||||
width:62pt'>Trail</td>
|
||||
<td class=xl6729647 width=161 style='border-top:none;width:121pt'>Trail</td>
|
||||
<td class=xl6629647 width=474 style='border-top:none;border-left:none;
|
||||
width:356pt'>Muestra una estela para cada partícula, que se desvanecerá a lo largo de la cantidad de fotogramas especificados en el parámetro Trail.</td>
|
||||
<td class=xl7729647 width=103 style='border-top:none;border-left:none;
|
||||
width:77pt'>―</td>
|
||||
</tr>
|
||||
<tr height=42 style='mso-height-source:userset;height:31.5pt'>
|
||||
<td height=42 class=xl7029647 width=89 style='height:31.5pt;width:67pt'> </td>
|
||||
<td class=xl7029647 width=83 style='border-left:none;width:62pt'> </td>
|
||||
<td class=xl6729647 width=161 style='border-top:none;width:121pt'>Step</td>
|
||||
<td class=xl6629647 width=474 style='border-top:none;border-left:none;
|
||||
width:356pt'>Permite definir cuántas imágenes se mostrarán en la estela. Cada estela estará compuesta por (Trail/Step) imágenes.</td>
|
||||
<td class=xl7729647 width=103 style='border-top:none;border-left:none;
|
||||
width:77pt'>―</td>
|
||||
</tr>
|
||||
<tr height=42 style='mso-height-source:userset;height:31.5pt'>
|
||||
<td height=42 class=xl7029647 width=89 style='height:31.5pt;width:67pt'> </td>
|
||||
<td class=xl7029647 width=83 style='border-left:none;width:62pt'> </td>
|
||||
<td class=xl6729647 width=161 style='border-top:none;width:121pt'>Motion Blur</td>
|
||||
<td class=xl6629647 width=474 style='border-top:none;border-left:none;
|
||||
width:356pt'>When turned ON, particles will be rendered with motion blur according to its movement.</td>
|
||||
<td class=xl7729647 width=103 style='border-top:none;border-left:none;
|
||||
width:77pt'>―</td>
|
||||
</tr>
|
||||
<tr height=42 style='mso-height-source:userset;height:18.0pt'>
|
||||
<td height=42 class=xl7029647 width=89 style='height:18.0pt;width:67pt'> </td>
|
||||
<td class=xl7329647 width=83 style='width:62pt'> </td>
|
||||
<td class=xl6729647 width=161 style='border-top:none;width:121pt'>Gamma</td>
|
||||
<td class=xl6629647 width=474 style='border-top:none;border-left:none;
|
||||
width:356pt'>Film gamma value used for the motion blur.</td>
|
||||
<td class=xl7729647 width=103 style='border-top:none;border-left:none;
|
||||
width:77pt'>―</td>
|
||||
</tr>
|
||||
<tr height=36 style='height:27.0pt'>
|
||||
<td height=36 class=xl6829647 width=89 style='height:27.0pt;width:67pt'> </td>
|
||||
<td class=xl6629647 width=83 style='border-top:none;border-left:none;
|
||||
|
|
|
@ -597,25 +597,6 @@ rt
|
|||
<td class=xl7729647 width=103 style='border-top:none;border-left:none;
|
||||
width:77pt'>○</td>
|
||||
</tr>
|
||||
<tr height=24 style='mso-height-source:userset;height:18.0pt'>
|
||||
<td height=24 class=xl7029647 width=89 style='height:18.0pt;width:67pt'> </td>
|
||||
<td class=xl6929647 width=83 style='border-top:none;border-left:none;
|
||||
width:62pt'>Trail</td>
|
||||
<td class=xl6729647 width=161 style='border-top:none;width:121pt'>Trail</td>
|
||||
<td class=xl6629647 width=474 style='border-top:none;border-left:none;
|
||||
width:356pt'>Display a trail for each particle, that fades out over the number of frames specified in the Trail parameter.</td>
|
||||
<td class=xl7729647 width=103 style='border-top:none;border-left:none;
|
||||
width:77pt'>―</td>
|
||||
</tr>
|
||||
<tr height=42 style='mso-height-source:userset;height:31.5pt'>
|
||||
<td height=42 class=xl7029647 width=89 style='height:31.5pt;width:67pt'> </td>
|
||||
<td class=xl7329647 width=83 style='width:62pt'> </td>
|
||||
<td class=xl6729647 width=161 style='border-top:none;width:121pt'>Step</td>
|
||||
<td class=xl6629647 width=474 style='border-top:none;border-left:none;
|
||||
width:356pt'>The particle trail will be displayed every Step value. That is, there will be (Trail/Step) images displayed in the trail.</td>
|
||||
<td class=xl7729647 width=103 style='border-top:none;border-left:none;
|
||||
width:77pt'>―</td>
|
||||
</tr>
|
||||
<tr height=36 style='height:27.0pt'>
|
||||
<td height=36 class=xl7029647 width=89 style='height:27.0pt;width:67pt'> </td>
|
||||
<td class=xl7129647 width=83 style='border-top:none;width:62pt'>Lifetime</td>
|
||||
|
@ -849,7 +830,44 @@ rt
|
|||
<td class=xl6729647 width=161 style='border-top:none;width:121pt'>Trail
|
||||
Opacity</td>
|
||||
<td class=xl6629647 width=474 style='border-top:none;border-left:none;
|
||||
width:356pt'>When a trail is defined in Birth Params → Trail, it specifies the minimum / maximum values for the opacity of the particles in the trail.</td>
|
||||
width:356pt'>When a trail is defined in Animation → Trail, it specifies the minimum / maximum values for the opacity of the particles in the trail.</td>
|
||||
<td class=xl7729647 width=103 style='border-top:none;border-left:none;
|
||||
width:77pt'>―</td>
|
||||
</tr>
|
||||
<tr height=24 style='mso-height-source:userset;height:18.0pt'>
|
||||
<td height=24 class=xl7029647 width=89 style='height:18.0pt;width:67pt'> </td>
|
||||
<td class=xl6929647 width=83 style='border-top:none;border-left:none;
|
||||
width:62pt'>Trail</td>
|
||||
<td class=xl6729647 width=161 style='border-top:none;width:121pt'>Trail</td>
|
||||
<td class=xl6629647 width=474 style='border-top:none;border-left:none;
|
||||
width:356pt'>Display a trail for each particle, that fades out over the number of frames specified in the Trail parameter.</td>
|
||||
<td class=xl7729647 width=103 style='border-top:none;border-left:none;
|
||||
width:77pt'>―</td>
|
||||
</tr>
|
||||
<tr height=42 style='mso-height-source:userset;height:31.5pt'>
|
||||
<td height=42 class=xl7029647 width=89 style='height:31.5pt;width:67pt'> </td>
|
||||
<td class=xl7029647 width=83 style='border-left:none;width:62pt'> </td>
|
||||
<td class=xl6729647 width=161 style='border-top:none;width:121pt'>Step</td>
|
||||
<td class=xl6629647 width=474 style='border-top:none;border-left:none;
|
||||
width:356pt'>The particle trail will be displayed every Step value. That is, there will be (Trail/Step) images displayed in the trail.</td>
|
||||
<td class=xl7729647 width=103 style='border-top:none;border-left:none;
|
||||
width:77pt'>―</td>
|
||||
</tr>
|
||||
<tr height=42 style='mso-height-source:userset;height:31.5pt'>
|
||||
<td height=42 class=xl7029647 width=89 style='height:31.5pt;width:67pt'> </td>
|
||||
<td class=xl7029647 width=83 style='border-left:none;width:62pt'> </td>
|
||||
<td class=xl6729647 width=161 style='border-top:none;width:121pt'>Motion Blur</td>
|
||||
<td class=xl6629647 width=474 style='border-top:none;border-left:none;
|
||||
width:356pt'>When turned ON, particles will be rendered with motion blur according to its movement.</td>
|
||||
<td class=xl7729647 width=103 style='border-top:none;border-left:none;
|
||||
width:77pt'>―</td>
|
||||
</tr>
|
||||
<tr height=42 style='mso-height-source:userset;height:18.0pt'>
|
||||
<td height=42 class=xl7029647 width=89 style='height:18.0pt;width:67pt'> </td>
|
||||
<td class=xl7329647 width=83 style='width:62pt'> </td>
|
||||
<td class=xl6729647 width=161 style='border-top:none;width:121pt'>Gamma</td>
|
||||
<td class=xl6629647 width=474 style='border-top:none;border-left:none;
|
||||
width:356pt'>Film gamma value used for the motion blur.</td>
|
||||
<td class=xl7729647 width=103 style='border-top:none;border-left:none;
|
||||
width:77pt'>―</td>
|
||||
</tr>
|
||||
|
|
|
@ -599,25 +599,6 @@ rt
|
|||
<td class=xl7729647 width=103 style='border-top:none;border-left:none;
|
||||
width:77pt'><3E>›</td>
|
||||
</tr>
|
||||
<tr height=24 style='mso-height-source:userset;height:18.0pt'>
|
||||
<td height=24 class=xl7029647 width=89 style='height:18.0pt;width:67pt'> </td>
|
||||
<td class=xl6929647 width=83 style='border-top:none;border-left:none;
|
||||
width:62pt'>Trail</td>
|
||||
<td class=xl6729647 width=161 style='border-top:none;width:121pt'>Trail</td>
|
||||
<td class=xl6629647 width=474 style='border-top:none;border-left:none;
|
||||
width:356pt'>軌跡を表示させる。Trailで指定したフレーム数かけてフェードアウトする。</td>
|
||||
<td class=xl7729647 width=103 style='border-top:none;border-left:none;
|
||||
width:77pt'>―</td>
|
||||
</tr>
|
||||
<tr height=42 style='mso-height-source:userset;height:31.5pt'>
|
||||
<td height=42 class=xl7029647 width=89 style='height:31.5pt;width:67pt'> </td>
|
||||
<td class=xl7329647 width=83 style='width:62pt'> </td>
|
||||
<td class=xl6729647 width=161 style='border-top:none;width:121pt'>Step</td>
|
||||
<td class=xl6629647 width=474 style='border-top:none;border-left:none;
|
||||
width:356pt'>軌跡をStep値おきに表示する。すなわち、軌跡の画像は(Trail)/(Frame)枚表示されることになる。</td>
|
||||
<td class=xl7729647 width=103 style='border-top:none;border-left:none;
|
||||
width:77pt'>―</td>
|
||||
</tr>
|
||||
<tr height=36 style='height:27.0pt'>
|
||||
<td height=36 class=xl7029647 width=89 style='height:27.0pt;width:67pt'><EFBFBD>@</td>
|
||||
<td class=xl7129647 width=83 style='border-top:none;width:62pt'>Lifetime</td>
|
||||
|
@ -855,7 +836,44 @@ rt
|
|||
<td class=xl6729647 width=161 style='border-top:none;width:121pt'>Trail
|
||||
Opacity</td>
|
||||
<td class=xl6629647 width=474 style='border-top:none;border-left:none;
|
||||
width:356pt'>BirthParam→TrailでTrailを指定したとき、その軌跡のパーティクルの不透明度の最小/最大値を決める。</td>
|
||||
width:356pt'>Animation→TrailでTrailを指定したとき、その軌跡のパーティクルの不透明度の最小/最大値を決める。</td>
|
||||
<td class=xl7729647 width=103 style='border-top:none;border-left:none;
|
||||
width:77pt'>―</td>
|
||||
</tr>
|
||||
<tr height=24 style='mso-height-source:userset;height:18.0pt'>
|
||||
<td height=24 class=xl7029647 width=89 style='height:18.0pt;width:67pt'> </td>
|
||||
<td class=xl6929647 width=83 style='border-top:none;border-left:none;
|
||||
width:62pt'>Trail</td>
|
||||
<td class=xl6729647 width=161 style='border-top:none;width:121pt'>Trail</td>
|
||||
<td class=xl6629647 width=474 style='border-top:none;border-left:none;
|
||||
width:356pt'>軌跡を表示させる。Trailで指定したフレーム数かけてフェードアウトする。</td>
|
||||
<td class=xl7729647 width=103 style='border-top:none;border-left:none;
|
||||
width:77pt'>―</td>
|
||||
</tr>
|
||||
<tr height=42 style='mso-height-source:userset;height:31.5pt'>
|
||||
<td height=42 class=xl7029647 width=89 style='height:31.5pt;width:67pt'> </td>
|
||||
<td class=xl7029647 width=83 style='border-left:none;width:62pt'> </td>
|
||||
<td class=xl6729647 width=161 style='border-top:none;width:121pt'>Step</td>
|
||||
<td class=xl6629647 width=474 style='border-top:none;border-left:none;
|
||||
width:356pt'>軌跡をStep値おきに表示する。すなわち、軌跡の画像は(Trail)/(Frame)枚表示されることになる。</td>
|
||||
<td class=xl7729647 width=103 style='border-top:none;border-left:none;
|
||||
width:77pt'>―</td>
|
||||
</tr>
|
||||
<tr height=42 style='mso-height-source:userset;height:31.5pt'>
|
||||
<td height=42 class=xl7029647 width=89 style='height:31.5pt;width:67pt'> </td>
|
||||
<td class=xl7029647 width=83 style='border-left:none;width:62pt'> </td>
|
||||
<td class=xl6729647 width=161 style='border-top:none;width:121pt'>Motion Blur</td>
|
||||
<td class=xl6629647 width=474 style='border-top:none;border-left:none;
|
||||
width:356pt'>When turned ON, particles will be rendered with motion blur according to its movement.</td>
|
||||
<td class=xl7729647 width=103 style='border-top:none;border-left:none;
|
||||
width:77pt'>―</td>
|
||||
</tr>
|
||||
<tr height=42 style='mso-height-source:userset;height:18.0pt'>
|
||||
<td height=42 class=xl7029647 width=89 style='height:18.0pt;width:67pt'> </td>
|
||||
<td class=xl7329647 width=83 style='width:62pt'> </td>
|
||||
<td class=xl6729647 width=161 style='border-top:none;width:121pt'>Gamma</td>
|
||||
<td class=xl6629647 width=474 style='border-top:none;border-left:none;
|
||||
width:356pt'>Film gamma value used for the motion blur.</td>
|
||||
<td class=xl7729647 width=103 style='border-top:none;border-left:none;
|
||||
width:77pt'><3E>\</td>
|
||||
</tr>
|
||||
|
|
|
@ -56,9 +56,6 @@
|
|||
<control>mass</control>
|
||||
<control>rot</control>
|
||||
<control>rot_ctrl</control>
|
||||
<separator label="Trail"/>
|
||||
<control>trail</control>
|
||||
<control>trail_step</control>
|
||||
<separator label="Lifetime"/>
|
||||
<control>lifetime</control>
|
||||
<control>lifetime_ctrl</control>
|
||||
|
@ -119,6 +116,14 @@
|
|||
<control>fade_out</control>
|
||||
</hbox>
|
||||
<control>trail_opacity</control>
|
||||
<separator label="Trail"/>
|
||||
<control>trail</control>
|
||||
<control>trail_step</control>
|
||||
|
||||
<hbox>
|
||||
<control>motion_blur</control>
|
||||
<control>motion_blur_gamma</control>
|
||||
</hbox>
|
||||
<separator label="Size Increase"/>
|
||||
<control>scale_step</control>
|
||||
<control>scale_step_ctrl</control>
|
||||
|
|
|
@ -174,10 +174,12 @@ Particle::Particle(int g_lifetime, int seed, std::map<int, TTile *> porttiles,
|
|||
|
||||
trail =
|
||||
(int)(values.trail_val.first + (ranges.trail_range) * random.getFloat());
|
||||
vx = random_speed * sin(random_s_a_range);
|
||||
vy = -random_speed * cos(random_s_a_range);
|
||||
oldx = 0;
|
||||
oldy = 0;
|
||||
vx = random_speed * sin(random_s_a_range);
|
||||
vy = -random_speed * cos(random_s_a_range);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
oldx[i] = 0.;
|
||||
oldy[i] = 0.;
|
||||
}
|
||||
mass = values.mass_val.first + (ranges.mass_range) * random.getFloat();
|
||||
if (values.scale_ctrl_val &&
|
||||
(porttiles.find(values.scale_ctrl_val) != porttiles.end())) {
|
||||
|
@ -670,8 +672,13 @@ void Particle::move(std::map<int, TTile *> porttiles,
|
|||
if (values.scalestep_ctrl_val)
|
||||
scalestepreference = imagereferences[values.scalestep_ctrl_val];
|
||||
lifetime--;
|
||||
oldx = x;
|
||||
oldy = y;
|
||||
// slide the old positions
|
||||
for (int i = 2; i >= 1; i--) {
|
||||
oldx[i] = oldx[i - 1];
|
||||
oldy[i] = oldy[i - 1];
|
||||
}
|
||||
oldx[0] = x;
|
||||
oldy[0] = y;
|
||||
// time=genlifetime-lifetime-1;
|
||||
// if(time<0) time=0;
|
||||
if (values.gravity_ctrl_val &&
|
||||
|
|
|
@ -56,8 +56,6 @@ struct particles_values {
|
|||
bool scale_ctrl_all_val;
|
||||
DoublePair rot_val;
|
||||
int rot_ctrl_val;
|
||||
DoublePair trail_val;
|
||||
double trailstep_val;
|
||||
int rotswingmode_val;
|
||||
double rotspeed_val;
|
||||
DoublePair rotsca_val;
|
||||
|
@ -66,7 +64,8 @@ struct particles_values {
|
|||
DoublePair opacity_val;
|
||||
int opacity_ctrl_val;
|
||||
DoublePair trailopacity_val;
|
||||
double mblur_val;
|
||||
DoublePair trail_val;
|
||||
double trailstep_val;
|
||||
DoublePair scalestep_val;
|
||||
int scalestep_ctrl_val;
|
||||
double fadein_val;
|
||||
|
@ -93,6 +92,8 @@ struct particles_values {
|
|||
bool reset_random_for_every_frame_val;
|
||||
bool pick_color_for_every_frame_val;
|
||||
bool perspective_distribution_val;
|
||||
bool motion_blur_val;
|
||||
double motion_blur_gamma_val;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -133,8 +134,8 @@ class Particle {
|
|||
public:
|
||||
double x;
|
||||
double y;
|
||||
double oldx;
|
||||
double oldy;
|
||||
double oldx[3];
|
||||
double oldy[3];
|
||||
double vx; /*sono le velox iniziali*/
|
||||
double vy; /*sono le velox iniziali*/
|
||||
double mass;
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
|
||||
#include <sstream>
|
||||
|
||||
#include <QPointF>
|
||||
#include <QMatrix4x4>
|
||||
|
||||
/*-----------------------------------------------------------------*/
|
||||
|
||||
Particles_Engine::Particles_Engine(ParticlesFx *parent, double frame)
|
||||
|
@ -135,6 +138,9 @@ void Particles_Engine::fill_value_struct(struct particles_values &myvalues,
|
|||
m_parent->pick_color_for_every_frame_val->getValue();
|
||||
myvalues.perspective_distribution_val =
|
||||
m_parent->perspective_distribution_val->getValue();
|
||||
myvalues.motion_blur_val = m_parent->motion_blur_val->getValue();
|
||||
myvalues.motion_blur_gamma_val =
|
||||
m_parent->motion_blur_gamma_val->getValue(frame);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------*/
|
||||
|
@ -411,7 +417,6 @@ void Particles_Engine::normalize_values(struct particles_values &values,
|
|||
(values.opacity_val.second) = (values.opacity_val.second) * 0.01;
|
||||
(values.trailopacity_val.first) = (values.trailopacity_val.first) * 0.01;
|
||||
(values.trailopacity_val.second) = (values.trailopacity_val.second) * 0.01;
|
||||
(values.mblur_val) = (values.mblur_val) * 0.01;
|
||||
(values.friction_val) = -(values.friction_val) * 0.01;
|
||||
(values.windangle_val) = (values.windangle_val) * M_PI_180;
|
||||
(values.g_angle_val) = (values.g_angle_val + 180) * M_PI_180;
|
||||
|
@ -856,6 +861,14 @@ void Particles_Engine::do_render(
|
|||
// Particles parameters
|
||||
M = ri.m_affine * M * TScale(1.0 / partScale);
|
||||
|
||||
// render with motion blur
|
||||
if (values.motion_blur_val) {
|
||||
if (do_render_motion_blur(part, tile, tileRas, rfinalpart, M, bbox,
|
||||
values.trailopacity_val,
|
||||
values.motion_blur_gamma_val, ri))
|
||||
return;
|
||||
}
|
||||
|
||||
// Then, retrieve the particle position in current reference.
|
||||
TPointD pos(part->x, part->y);
|
||||
pos = ri.m_affine * pos;
|
||||
|
@ -875,6 +888,376 @@ void Particles_Engine::do_render(
|
|||
|
||||
/*-----------------------------------------------------------------*/
|
||||
|
||||
bool Particles_Engine::do_render_motion_blur(
|
||||
Particle *part, TTile *tile, TRasterP tileRas, TRaster32P rfinalpart,
|
||||
TAffine &M, const TRectD &bbox, const DoublePair &trailOpacity,
|
||||
const double gamma, const TRenderSettings &ri) {
|
||||
QList<TPointD> points;
|
||||
QList<double> lengths;
|
||||
|
||||
// do not render new-born particles as it has no trace
|
||||
if (part->genlifetime - part->lifetime == 0) return true;
|
||||
|
||||
TRectD partBBoxD =
|
||||
M * TTranslation(bbox.getP00()) * convert(rfinalpart->getBounds());
|
||||
partBBoxD = partBBoxD.enlarge(1.0);
|
||||
|
||||
TRect partBBox = convert(partBBoxD);
|
||||
|
||||
TRaster32P partRas(partBBox.getSize());
|
||||
TRop::over(
|
||||
partRas, rfinalpart,
|
||||
TTranslation(-partBBoxD.getP00()) * M * TTranslation(bbox.getP00()));
|
||||
|
||||
// create trace vertices list
|
||||
// render straight trace in the first 4 frames
|
||||
if (part->genlifetime - part->lifetime < 3) {
|
||||
TPointD p0(part->x, part->y);
|
||||
TPointD p1(part->oldx[0], part->oldy[0]);
|
||||
p0 = ri.m_affine * p0;
|
||||
p1 = ri.m_affine * p1;
|
||||
points.append(TPointD(0, 0));
|
||||
points.append(p1 - p0);
|
||||
}
|
||||
// Cubic spline interpolation
|
||||
else {
|
||||
// divide into 8 lines (= 9 segments)
|
||||
int pointAmount = 9;
|
||||
TPointD keyP[4] = {TPointD(part->x, part->y),
|
||||
TPointD(part->oldx[0], part->oldy[0]),
|
||||
TPointD(part->oldx[1], part->oldy[1]),
|
||||
TPointD(part->oldx[2], part->oldy[2])};
|
||||
for (int i = 0; i < 4; i++) {
|
||||
keyP[i] = ri.m_affine * keyP[i];
|
||||
if (i > 0) {
|
||||
keyP[i] -= keyP[0];
|
||||
}
|
||||
}
|
||||
keyP[0] = TPointD(0, 0);
|
||||
|
||||
double u[4];
|
||||
u[0] = 0.;
|
||||
u[1] = u[0] + norm(keyP[1] - keyP[0]);
|
||||
u[2] = u[1] + norm(keyP[2] - keyP[1]);
|
||||
u[3] = u[2] + norm(keyP[3] - keyP[2]);
|
||||
|
||||
QMatrix4x4 mat(u[0] * u[0] * u[0], u[0] * u[0], u[0], 1.,
|
||||
u[1] * u[1] * u[1], u[1] * u[1], u[1], 1.,
|
||||
u[2] * u[2] * u[2], u[2] * u[2], u[2], 1.,
|
||||
u[3] * u[3] * u[3], u[3] * u[3], u[3], 1.);
|
||||
|
||||
bool ok;
|
||||
mat = mat.inverted(&ok);
|
||||
if (!ok) return false;
|
||||
|
||||
QPointF coeff[4];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
coeff[i] = mat(i, 0) * QPointF(keyP[0].x, keyP[0].y) +
|
||||
mat(i, 1) * QPointF(keyP[1].x, keyP[1].y) +
|
||||
mat(i, 2) * QPointF(keyP[2].x, keyP[2].y) +
|
||||
mat(i, 3) * QPointF(keyP[3].x, keyP[3].y);
|
||||
}
|
||||
|
||||
for (int p = 0; p <= pointAmount; p++) {
|
||||
double ratio = (double)p / (double)pointAmount;
|
||||
double cur_u = u[0] * ratio + u[1] * (1 - ratio);
|
||||
|
||||
points.append(TPointD(
|
||||
cur_u * cur_u * cur_u * coeff[0].x() + cur_u * cur_u * coeff[1].x() +
|
||||
cur_u * coeff[2].x() + coeff[3].x(),
|
||||
cur_u * cur_u * cur_u * coeff[0].y() + cur_u * cur_u * coeff[1].y() +
|
||||
cur_u * coeff[2].y() + coeff[3].y()));
|
||||
}
|
||||
}
|
||||
|
||||
// compute lengths
|
||||
for (int p = 0; p < points.size() - 1; p++) {
|
||||
TPointD vec = points[p + 1] - points[p];
|
||||
lengths.append(norm(vec));
|
||||
}
|
||||
|
||||
/* Get upper, lower, left and right margin */
|
||||
double minX = 0.0;
|
||||
double maxX = 0.0;
|
||||
double minY = 0.0;
|
||||
double maxY = 0.0;
|
||||
for (int p = 0; p < points.size(); p++) {
|
||||
if (points.at(p).x > maxX) maxX = points.at(p).x;
|
||||
if (points.at(p).x < minX) minX = points.at(p).x;
|
||||
if (points.at(p).y > maxY) maxY = points.at(p).y;
|
||||
if (points.at(p).y < minY) minY = points.at(p).y;
|
||||
}
|
||||
int marginLeft = (int)std::ceil(std::abs(minX));
|
||||
int marginRight = (int)std::ceil(std::abs(maxX));
|
||||
int marginTop = (int)std::ceil(std::abs(maxY));
|
||||
int marginBottom = (int)std::ceil(std::abs(minY));
|
||||
if (marginLeft == 0 && marginRight == 0 && marginTop == 0 &&
|
||||
marginBottom == 0)
|
||||
return false;
|
||||
|
||||
// end opacity is computed so that the trace will be connected smoothly in the
|
||||
// trail
|
||||
float end_opacity =
|
||||
trailOpacity.second +
|
||||
(trailOpacity.first - trailOpacity.second) / std::max(1, part->trail);
|
||||
|
||||
// create the blur filter
|
||||
TDimensionI filterDim(marginLeft + marginRight + 1,
|
||||
marginTop + marginBottom + 1);
|
||||
TRasterGR8P filter_ras(sizeof(float) * filterDim.lx, filterDim.ly);
|
||||
filter_ras->lock();
|
||||
float *filter_p = (float *)filter_ras->getRawData();
|
||||
/* Variable for adding filter value*/
|
||||
float fil_val_sum = 0.0f;
|
||||
/* The current filter position to be looped in the 'for' statement */
|
||||
float *current_fil_p = filter_p;
|
||||
/* For each coordinate in the filter */
|
||||
for (int fily = 0; fily < filterDim.ly; fily++) {
|
||||
for (int filx = 0; filx < filterDim.lx; filx++, current_fil_p++) {
|
||||
/* Get filter coordinates */
|
||||
TPointD pos(static_cast<float>(filx - marginLeft),
|
||||
static_cast<float>(fily - marginBottom));
|
||||
/* Value to be updated */
|
||||
float nearestDist2 = 100.0f;
|
||||
int nearestIndex = -1;
|
||||
float nearestFramePosRatio = 0.0f;
|
||||
|
||||
/* Find the nearest point for each pair of sample points */
|
||||
for (int v = 0; v < points.count() - 1; v++) {
|
||||
TPointD p0 = points[v];
|
||||
TPointD p1 = points[v + 1];
|
||||
|
||||
/* If it is not within the range, continue */
|
||||
if (pos.x < std::min(p0.x, p1.x) - 1.0f ||
|
||||
pos.x > std::max(p0.x, p1.x) + 1.0f ||
|
||||
pos.y < std::min(p0.y, p1.y) - 1.0f ||
|
||||
pos.y > std::max(p0.y, p1.y) + 1.0f)
|
||||
continue;
|
||||
|
||||
/* Since it is within the range, obtain the distance between the line
|
||||
* segment and the point. */
|
||||
/* Calculate the inner product of 'p0'->sampling point and 'p0'->'p1' */
|
||||
TPointD vec_p0_sample(static_cast<float>(pos.x - p0.x),
|
||||
static_cast<float>(pos.y - p0.y));
|
||||
TPointD vec_p0_p1(static_cast<float>(p1.x - p0.x),
|
||||
static_cast<float>(p1.y - p0.y));
|
||||
float dot =
|
||||
vec_p0_sample.x * vec_p0_p1.x + vec_p0_sample.y * vec_p0_p1.y;
|
||||
/* Calculate the square of distance */
|
||||
float dist2;
|
||||
float framePosRatio;
|
||||
/* If it is before 'p0' */
|
||||
if (dot <= 0.0f) {
|
||||
dist2 = vec_p0_sample.x * vec_p0_sample.x +
|
||||
vec_p0_sample.y * vec_p0_sample.y;
|
||||
framePosRatio = 0.0f;
|
||||
} else {
|
||||
/* Calculate the square of the length of the trajectory vector */
|
||||
float length2 = lengths[v] * lengths[v];
|
||||
|
||||
/* If it is between 'p0' and 'p1'
|
||||
* If the trajectory at p is a point,
|
||||
* 'length2' becomes 0, so it will never fall into this condition.
|
||||
* So, there should not be worry of becoming ZeroDivide. */
|
||||
if (dot < length2) {
|
||||
float p0_sample_dist2 = vec_p0_sample.x * vec_p0_sample.x +
|
||||
vec_p0_sample.y * vec_p0_sample.y;
|
||||
dist2 = p0_sample_dist2 - dot * dot / length2;
|
||||
framePosRatio = dot / length2;
|
||||
}
|
||||
/* If it is before 'p1' */
|
||||
else {
|
||||
TPointD vec_p1_sample = pos - p1;
|
||||
dist2 = vec_p1_sample.x * vec_p1_sample.x +
|
||||
vec_p1_sample.y * vec_p1_sample.y;
|
||||
framePosRatio = 1.0f;
|
||||
}
|
||||
}
|
||||
/* If the distance is farther than (√ 2 + 1) / 2, continue
|
||||
* Because it is a comparison with dist2, the value is squared */
|
||||
if (dist2 > 1.4571f) continue;
|
||||
|
||||
/* Update if distance is closer */
|
||||
if (dist2 < nearestDist2) {
|
||||
nearestDist2 = dist2;
|
||||
nearestIndex = v;
|
||||
nearestFramePosRatio = framePosRatio;
|
||||
}
|
||||
}
|
||||
|
||||
/* If neighborhood vector of the current pixel can not be found,
|
||||
* set the filter value to 0 and return */
|
||||
if (nearestIndex == -1) {
|
||||
*current_fil_p = 0.0f;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Count how many subpixels (16 * 16) of the current pixel
|
||||
* are in the range 0.5 from the neighborhood vector.
|
||||
*/
|
||||
int count = 0;
|
||||
TPointD np0 = points[nearestIndex];
|
||||
TPointD np1 = points[nearestIndex + 1];
|
||||
for (int yy = 0; yy < 16; yy++) {
|
||||
/* Y coordinate of the subpixel */
|
||||
float subPosY = pos.y + ((float)yy - 7.5f) / 16.0f;
|
||||
for (int xx = 0; xx < 16; xx++) {
|
||||
/* X coordinate of the subpixel */
|
||||
float subPosX = pos.x + ((float)xx - 7.5f) / 16.0f;
|
||||
|
||||
TPointD vec_np0_sub = TPointD(subPosX, subPosY) - np0;
|
||||
TPointD vec_np0_np1 = np1 - np0;
|
||||
float dot =
|
||||
vec_np0_sub.x * vec_np0_np1.x + vec_np0_sub.y * vec_np0_np1.y;
|
||||
/* Calculate the square of the distance */
|
||||
float dist2;
|
||||
/* If it is before 'p0' */
|
||||
if (dot <= 0.0f)
|
||||
dist2 =
|
||||
vec_np0_sub.x * vec_np0_sub.x + vec_np0_sub.y * vec_np0_sub.y;
|
||||
else {
|
||||
/* Compute the square of the length of the trajectory vector */
|
||||
float length2 = lengths[nearestIndex] * lengths[nearestIndex];
|
||||
/* If it is between 'p0' and 'p1' */
|
||||
if (dot < length2) {
|
||||
float np0_sub_dist2 =
|
||||
vec_np0_sub.x * vec_np0_sub.x + vec_np0_sub.y * vec_np0_sub.y;
|
||||
dist2 = np0_sub_dist2 - dot * dot / length2;
|
||||
}
|
||||
/* if it is before 'p1' */
|
||||
else {
|
||||
TPointD vec_np1_sub = TPointD(subPosX, subPosY) - np1;
|
||||
dist2 =
|
||||
vec_np1_sub.x * vec_np1_sub.x + vec_np1_sub.y * vec_np1_sub.y;
|
||||
}
|
||||
}
|
||||
/* Increment count if squared distance is less than 0.25 */
|
||||
if (dist2 <= 0.25f) count++;
|
||||
}
|
||||
}
|
||||
/* 'safeguard' - If the count is 0, set the field value to 0 and return.
|
||||
*/
|
||||
if (count == 0) {
|
||||
*current_fil_p = 0.0f;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Count is 256 at a maximum */
|
||||
float countRatio = (float)count / 256.0f;
|
||||
|
||||
/* The brightness of the filter value is inversely proportional
|
||||
* to the area of the line of width 1 made by the vector.
|
||||
*
|
||||
* Since there are semicircular caps with radius 0.5
|
||||
* before and after the vector, it will never be 0-divide
|
||||
* even if the length of vector is 0.
|
||||
*/
|
||||
|
||||
/* Area of the neighborhood vector when width = 1 */
|
||||
float vecMenseki = 0.25f * 3.14159265f + lengths[nearestIndex];
|
||||
|
||||
float opacity = 1.0f;
|
||||
if (end_opacity < 1.0f) {
|
||||
float ratio = ((float)nearestIndex + nearestFramePosRatio) /
|
||||
(float)(points.size() - 1);
|
||||
opacity = ratio + end_opacity * (1.f - ratio);
|
||||
}
|
||||
/* Store field value */
|
||||
*current_fil_p = opacity * countRatio / vecMenseki;
|
||||
fil_val_sum += *current_fil_p;
|
||||
}
|
||||
}
|
||||
|
||||
/* Normalization */
|
||||
current_fil_p = filter_p;
|
||||
for (int f = 0; f < filterDim.lx * filterDim.ly; f++, current_fil_p++) {
|
||||
*current_fil_p /= fil_val_sum;
|
||||
}
|
||||
|
||||
// apply the filter
|
||||
TDimension blurredSize =
|
||||
partRas->getSize() +
|
||||
TDimension(marginLeft + marginRight, marginTop + marginBottom);
|
||||
float4 *blurred_p;
|
||||
TRasterGR8P blurred_ras(sizeof(float4) * blurredSize.lx, blurredSize.ly);
|
||||
blurred_ras->lock();
|
||||
blurred_ras->clear();
|
||||
blurred_p = (float4 *)blurred_ras->getRawData();
|
||||
// for each texture pixels,
|
||||
// distribute to all pixels in the filter
|
||||
for (int ty = 0; ty < partRas->getLy(); ty++) {
|
||||
TPixel32 *t_p = partRas->pixels(ty);
|
||||
for (int tx = 0; tx < partRas->getLx(); tx++, t_p++) {
|
||||
if (t_p->m == 0) continue;
|
||||
|
||||
float4 tex = {(float)t_p->r / (float)(TPixel32::maxChannelValue),
|
||||
(float)t_p->g / (float)(TPixel32::maxChannelValue),
|
||||
(float)t_p->b / (float)(TPixel32::maxChannelValue),
|
||||
(float)t_p->m / (float)(TPixel32::maxChannelValue)};
|
||||
if (gamma > 1.f) {
|
||||
tex.x = std::pow(tex.x / tex.w, gamma) * tex.w;
|
||||
tex.y = std::pow(tex.y / tex.w, gamma) * tex.w;
|
||||
tex.z = std::pow(tex.z / tex.w, gamma) * tex.w;
|
||||
}
|
||||
|
||||
current_fil_p = filter_p;
|
||||
for (int outy = ty; outy < ty + filterDim.ly; outy++) {
|
||||
for (int outx = tx; outx < tx + filterDim.lx; outx++, current_fil_p++) {
|
||||
if (*current_fil_p == 0.f) continue;
|
||||
int outIndex = outy * blurredSize.lx + outx;
|
||||
blurred_p[outIndex].x += *current_fil_p * tex.x;
|
||||
blurred_p[outIndex].y += *current_fil_p * tex.y;
|
||||
blurred_p[outIndex].z += *current_fil_p * tex.z;
|
||||
blurred_p[outIndex].w += *current_fil_p * tex.w;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
filter_ras->unlock();
|
||||
|
||||
float4 *b_p = blurred_p;
|
||||
TRaster32P blurred(blurredSize);
|
||||
for (int by = 0; by < blurredSize.ly; by++) {
|
||||
TPixel32 *b_ras_p = blurred->pixels(by);
|
||||
for (int bx = 0; bx < blurredSize.lx; bx++, b_ras_p++, b_p++) {
|
||||
if (gamma > 1.f && (*b_p).w > 0.f) {
|
||||
(*b_p).x = std::pow((*b_p).x / (*b_p).w, 1.f / gamma) * (*b_p).w;
|
||||
(*b_p).y = std::pow((*b_p).y / (*b_p).w, 1.f / gamma) * (*b_p).w;
|
||||
(*b_p).z = std::pow((*b_p).z / (*b_p).w, 1.f / gamma) * (*b_p).w;
|
||||
}
|
||||
|
||||
b_ras_p->r = (TPixel32::Channel)std::round(
|
||||
(*b_p).x * (float)(TPixel32::maxChannelValue));
|
||||
b_ras_p->g = (TPixel32::Channel)std::round(
|
||||
(*b_p).y * (float)(TPixel32::maxChannelValue));
|
||||
b_ras_p->b = (TPixel32::Channel)std::round(
|
||||
(*b_p).z * (float)(TPixel32::maxChannelValue));
|
||||
b_ras_p->m = (TPixel32::Channel)std::round(
|
||||
(*b_p).w * (float)(TPixel32::maxChannelValue));
|
||||
}
|
||||
}
|
||||
|
||||
blurred_ras->unlock();
|
||||
|
||||
// composite particle
|
||||
TPointD pos(part->x, part->y);
|
||||
pos = ri.m_affine * pos;
|
||||
M = TTranslation(pos - tile->m_pos) *
|
||||
TTranslation(-TPointD(marginLeft, marginBottom) + partBBoxD.getP00());
|
||||
|
||||
if (TRaster32P myras32 = tileRas)
|
||||
TRop::over(tileRas, blurred, M);
|
||||
else if (TRaster64P myras64 = tileRas)
|
||||
TRop::over(tileRas, blurred, M);
|
||||
else
|
||||
throw TException("ParticlesFx: unsupported Pixel Type");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------*/
|
||||
|
||||
void Particles_Engine::fill_array(TTile *ctrl1, int ®ioncount,
|
||||
std::vector<int> &myarray,
|
||||
std::vector<int> &lista,
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
#include "particles.h"
|
||||
#include "particlesfx.h"
|
||||
|
||||
struct float4 {
|
||||
float x, y, z, w;
|
||||
};
|
||||
class Particle;
|
||||
|
||||
class Particles_Engine {
|
||||
|
@ -51,6 +54,11 @@ public:
|
|||
int curr_frame,
|
||||
std::map<std::pair<int, int>, double> &partScales);
|
||||
|
||||
bool do_render_motion_blur(Particle *part, TTile *tile, TRasterP tileRas,
|
||||
TRaster32P rfinalpart, TAffine &M,
|
||||
const TRectD &bbox, const DoublePair &trailOpacity,
|
||||
const double gamma, const TRenderSettings &ri);
|
||||
|
||||
bool port_is_used(int i, struct particles_values &values);
|
||||
bool port_is_used_for_value(int i, struct particles_values &values);
|
||||
bool port_is_used_for_gradient(int i, struct particles_values &values);
|
||||
|
|
|
@ -98,7 +98,9 @@ ParticlesFx::ParticlesFx()
|
|||
, foutfadecol_val(0.0)
|
||||
, source_gradation_val(false)
|
||||
, pick_color_for_every_frame_val(false)
|
||||
, perspective_distribution_val(false) {
|
||||
, perspective_distribution_val(false)
|
||||
, motion_blur_val(false)
|
||||
, motion_blur_gamma_val(2.2) {
|
||||
addInputPort("Texture1", new TRasterFxPort, 0);
|
||||
addInputPort("Control1", new TRasterFxPort, 1);
|
||||
|
||||
|
@ -264,6 +266,9 @@ ParticlesFx::ParticlesFx()
|
|||
bindParam(this, "source_gradation", source_gradation_val);
|
||||
bindParam(this, "pick_color_for_every_frame", pick_color_for_every_frame_val);
|
||||
bindParam(this, "perspective_distribution", perspective_distribution_val);
|
||||
bindParam(this, "motion_blur", motion_blur_val);
|
||||
bindParam(this, "motion_blur_gamma", motion_blur_gamma_val);
|
||||
motion_blur_gamma_val->setValueRange(1.0, 5.0);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
|
|
@ -56,8 +56,6 @@ public:
|
|||
TBoolParamP scale_ctrl_all_val;
|
||||
TRangeParamP rot_val;
|
||||
TIntParamP rot_ctrl_val;
|
||||
TRangeParamP trail_val;
|
||||
TDoubleParamP trailstep_val;
|
||||
TIntEnumParamP rotswingmode_val;
|
||||
TDoubleParamP rotspeed_val;
|
||||
TRangeParamP rotsca_val;
|
||||
|
@ -66,6 +64,8 @@ public:
|
|||
TRangeParamP opacity_val;
|
||||
TIntParamP opacity_ctrl_val;
|
||||
TRangeParamP trailopacity_val;
|
||||
TRangeParamP trail_val;
|
||||
TDoubleParamP trailstep_val;
|
||||
TRangeParamP scalestep_val;
|
||||
TIntParamP scalestep_ctrl_val;
|
||||
TDoubleParamP fadein_val;
|
||||
|
@ -90,6 +90,8 @@ public:
|
|||
TBoolParamP source_gradation_val;
|
||||
TBoolParamP pick_color_for_every_frame_val;
|
||||
TBoolParamP perspective_distribution_val;
|
||||
TBoolParamP motion_blur_val;
|
||||
TDoubleParamP motion_blur_gamma_val;
|
||||
|
||||
public:
|
||||
enum { UNIT_SMALL_INCH, UNIT_INCH };
|
||||
|
|
Loading…
Reference in a new issue