particlesfx : use 16bpc control image for gradient
This commit is contained in:
parent
5d866328ea
commit
3b3c1b2fa1
4 changed files with 136 additions and 94 deletions
|
@ -150,12 +150,14 @@ Particle::Particle(int g_lifetime, int seed, std::map<int, TTile *> porttiles,
|
|||
|
||||
/*- Speed Angleの制御。RangeモードとGradientモードがある -*/
|
||||
if (values.speeda_ctrl_val &&
|
||||
(porttiles.find(values.speeda_ctrl_val) != porttiles.end())) {
|
||||
(porttiles.find(values.speeda_ctrl_val) != porttiles.end() ||
|
||||
porttiles.find(values.speeda_ctrl_val + Ctrl_64_Offset) !=
|
||||
porttiles.end())) {
|
||||
if (values.speeda_use_gradient_val) {
|
||||
/*- 参照画像のGradientを得る関数を利用して角度を得る -*/
|
||||
float dir_x, dir_y;
|
||||
get_image_gravity(porttiles[values.speeda_ctrl_val], values, dir_x,
|
||||
dir_y);
|
||||
get_image_gravity(porttiles[values.speeda_ctrl_val + Ctrl_64_Offset],
|
||||
values, dir_x, dir_y);
|
||||
if (dir_x == 0.0f && dir_y == 0.0f)
|
||||
random_s_a_range = values.speed_val.first;
|
||||
else
|
||||
|
@ -558,67 +560,41 @@ void Particle::get_image_reference(TTile *ctrl, const particles_values &values,
|
|||
/*-----------------------------------------------------------------*/
|
||||
void Particle::get_image_gravity(TTile *ctrl1, const particles_values &values,
|
||||
float &gx, float &gy) {
|
||||
TRaster32P raster32 = ctrl1->getRaster();
|
||||
TRaster64P raster64 = ctrl1->getRaster();
|
||||
TPointD tmp(x, y);
|
||||
tmp -= ctrl1->m_pos;
|
||||
int radius = 4;
|
||||
int radius = 2;
|
||||
gx = 0;
|
||||
gy = 0;
|
||||
//#define OLDSTUFF
|
||||
#ifdef OLDSTUFF
|
||||
int i;
|
||||
#endif
|
||||
raster32->lock();
|
||||
#ifdef OLDSTUFF
|
||||
if (!values.gravity_radius_val) {
|
||||
radius = 4;
|
||||
if (raster32 && tmp.x >= radius && tmp.x < raster32->getLx() - radius &&
|
||||
tmp.y >= radius && tmp.y < raster32->getLy() - radius) {
|
||||
TPixel32 *pix = &(raster32->pixels(troundp(tmp.y))[(int)tmp.x]);
|
||||
double norm = 1 / ((double)TPixelGR8::maxChannelValue);
|
||||
for (i = 1; i < radius; i++) {
|
||||
gx += TPixelGR8::from(*(pix + i)).value;
|
||||
gx -= TPixelGR8::from(*(pix - i)).value;
|
||||
gy += TPixelGR8::from(*(pix + raster32->getWrap() * i)).value;
|
||||
gy -= TPixelGR8::from(*(pix - raster32->getWrap() * i)).value;
|
||||
}
|
||||
gx = gx * norm;
|
||||
gy = gy * norm;
|
||||
raster64->lock();
|
||||
if (raster64 && tmp.x >= radius && tmp.x < raster64->getLx() - radius &&
|
||||
tmp.y >= radius && tmp.y < raster64->getLy() - radius) {
|
||||
TPixel64 *pix = &(raster64->pixels(troundp(tmp.y))[(int)tmp.x]);
|
||||
|
||||
gx += 2 * TPixelGR16::from(*(pix + 1)).value;
|
||||
gx += TPixelGR16::from(*(pix + 1 + raster64->getWrap() * 1)).value;
|
||||
gx += TPixelGR16::from(*(pix + 1 - raster64->getWrap() * 1)).value;
|
||||
|
||||
gx -= 2 * TPixelGR16::from(*(pix - 1)).value;
|
||||
gx -= TPixelGR16::from(*(pix - 1 + raster64->getWrap() * 1)).value;
|
||||
gx -= TPixelGR16::from(*(pix - 1 - raster64->getWrap() * 1)).value;
|
||||
|
||||
gy += 2 * TPixelGR16::from(*(pix + raster64->getWrap() * 1)).value;
|
||||
gy += TPixelGR16::from(*(pix + raster64->getWrap() * 1 + 1)).value;
|
||||
gy += TPixelGR16::from(*(pix + raster64->getWrap() * 1 - 1)).value;
|
||||
|
||||
gy -= 2 * TPixelGR16::from(*(pix - raster64->getWrap() * 1)).value;
|
||||
gy -= TPixelGR16::from(*(pix - raster64->getWrap() * 1 + 1)).value;
|
||||
gy -= TPixelGR16::from(*(pix - raster64->getWrap() * 1 - 1)).value;
|
||||
|
||||
double norm = std::sqrt(gx * gx + gy * gy);
|
||||
if (norm) {
|
||||
double inorm = 0.1 / norm;
|
||||
gx = gx * inorm;
|
||||
gy = gy * inorm;
|
||||
}
|
||||
} else {
|
||||
#endif
|
||||
radius = 2;
|
||||
if (raster32 && tmp.x >= radius && tmp.x < raster32->getLx() - radius &&
|
||||
tmp.y >= radius && tmp.y < raster32->getLy() - radius) {
|
||||
TPixel32 *pix = &(raster32->pixels(troundp(tmp.y))[(int)tmp.x]);
|
||||
|
||||
gx += 2 * TPixelGR8::from(*(pix + 1)).value;
|
||||
gx += TPixelGR8::from(*(pix + 1 + raster32->getWrap() * 1)).value;
|
||||
gx += TPixelGR8::from(*(pix + 1 - raster32->getWrap() * 1)).value;
|
||||
|
||||
gx -= 2 * TPixelGR8::from(*(pix - 1)).value;
|
||||
gx -= TPixelGR8::from(*(pix - 1 + raster32->getWrap() * 1)).value;
|
||||
gx -= TPixelGR8::from(*(pix - 1 - raster32->getWrap() * 1)).value;
|
||||
|
||||
gy += 2 * TPixelGR8::from(*(pix + raster32->getWrap() * 1)).value;
|
||||
gy += TPixelGR8::from(*(pix + raster32->getWrap() * 1 + 1)).value;
|
||||
gy += TPixelGR8::from(*(pix + raster32->getWrap() * 1 - 1)).value;
|
||||
|
||||
gy -= 2 * TPixelGR8::from(*(pix - raster32->getWrap() * 1)).value;
|
||||
gy -= TPixelGR8::from(*(pix - raster32->getWrap() * 1 + 1)).value;
|
||||
gy -= TPixelGR8::from(*(pix - raster32->getWrap() * 1 - 1)).value;
|
||||
|
||||
double norm = sqrt(gx * gx + gy * gy);
|
||||
if (norm) {
|
||||
double inorm = 0.1 / norm;
|
||||
gx = gx * inorm;
|
||||
gy = gy * inorm;
|
||||
}
|
||||
}
|
||||
#ifdef OLDSTUFF
|
||||
}
|
||||
#endif
|
||||
raster32->unlock();
|
||||
raster64->unlock();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------*/
|
||||
|
@ -701,9 +677,10 @@ void Particle::move(std::map<int, TTile *> porttiles,
|
|||
// time=genlifetime-lifetime-1;
|
||||
// if(time<0) time=0;
|
||||
if (values.gravity_ctrl_val &&
|
||||
(porttiles.find(values.gravity_ctrl_val) != porttiles.end())) {
|
||||
get_image_gravity(porttiles[values.gravity_ctrl_val], values, xgravity,
|
||||
ygravity);
|
||||
(porttiles.find(values.gravity_ctrl_val + Ctrl_64_Offset) !=
|
||||
porttiles.end())) {
|
||||
get_image_gravity(porttiles[values.gravity_ctrl_val + Ctrl_64_Offset],
|
||||
values, xgravity, ygravity);
|
||||
xgravity *= values.gravity_val;
|
||||
ygravity *= values.gravity_val;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#include "tspectrum.h"
|
||||
#include "trandom.h"
|
||||
|
||||
const int Ctrl_64_Offset = 1000;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
struct particles_values {
|
||||
|
|
|
@ -160,15 +160,31 @@ void Particles_Engine::fill_range_struct(struct particles_values &values,
|
|||
}
|
||||
|
||||
bool Particles_Engine::port_is_used(int i, struct particles_values &values) {
|
||||
return port_is_used_for_value(i, values) ||
|
||||
port_is_used_for_gradient(i, values);
|
||||
}
|
||||
|
||||
// Returns true if the pixel value of control image is used.
|
||||
// Such image will be computed in 8bpc.
|
||||
bool Particles_Engine::port_is_used_for_value(int i,
|
||||
struct particles_values &values) {
|
||||
return values.fincol_ctrl_val == i || values.foutcol_ctrl_val == i ||
|
||||
values.friction_ctrl_val == i || values.gencol_ctrl_val == i ||
|
||||
values.gravity_ctrl_val == i || values.opacity_ctrl_val == i ||
|
||||
values.rot_ctrl_val == i || values.scale_ctrl_val == i ||
|
||||
values.scalestep_ctrl_val == i || values.source_ctrl_val == i ||
|
||||
values.speed_ctrl_val == i || values.speeda_ctrl_val == i ||
|
||||
values.opacity_ctrl_val == i || values.rot_ctrl_val == i ||
|
||||
values.scale_ctrl_val == i || values.scalestep_ctrl_val == i ||
|
||||
values.source_ctrl_val == i || values.speed_ctrl_val == i ||
|
||||
(values.speeda_ctrl_val == i && !values.speeda_use_gradient_val) ||
|
||||
values.lifetime_ctrl_val == i || values.randomx_ctrl_val == i ||
|
||||
values.randomy_ctrl_val == i;
|
||||
}
|
||||
|
||||
// Returns true if the gradient of control image is used.
|
||||
// Such image will be computed in 16bpc to get smooth result.
|
||||
bool Particles_Engine::port_is_used_for_gradient(
|
||||
int i, struct particles_values &values) {
|
||||
return values.gravity_ctrl_val == i ||
|
||||
(values.speeda_ctrl_val == i && values.speeda_use_gradient_val);
|
||||
}
|
||||
/*-----------------------------------------------------------------*/
|
||||
/*-- Startフレームからカレントフレームまで順番に回す関数 --*/
|
||||
void Particles_Engine::roll_particles(
|
||||
|
@ -255,7 +271,7 @@ void Particles_Engine::roll_particles(
|
|||
{
|
||||
/*- 新たに作るパーティクルの数だけ繰り返す -*/
|
||||
for (i = 0; i < newparticles; i++) {
|
||||
int seed = (int)((std::numeric_limits<int>::max)() *
|
||||
int seed = (int)((std::numeric_limits<int>::max)() *
|
||||
values.random_val->getFloat());
|
||||
int level = (int)(values.random_val->getFloat() * level_n);
|
||||
|
||||
|
@ -291,7 +307,7 @@ void Particles_Engine::roll_particles(
|
|||
switch (values.toplayer_val) {
|
||||
case ParticlesFx::TOP_YOUNGER:
|
||||
for (i = 0; i < newparticles; i++) {
|
||||
int seed = (int)((std::numeric_limits<int>::max)() *
|
||||
int seed = (int)((std::numeric_limits<int>::max)() *
|
||||
values.random_val->getFloat());
|
||||
int level = (int)(values.random_val->getFloat() * level_n);
|
||||
|
||||
|
@ -320,7 +336,7 @@ void Particles_Engine::roll_particles(
|
|||
for (int j = 0; j < tmp; j++, it++)
|
||||
;
|
||||
{
|
||||
int seed = (int)((std::numeric_limits<int>::max)() *
|
||||
int seed = (int)((std::numeric_limits<int>::max)() *
|
||||
values.random_val->getFloat());
|
||||
int level = (int)(values.random_val->getFloat() * level_n);
|
||||
int lifetime = 0;
|
||||
|
@ -344,7 +360,7 @@ void Particles_Engine::roll_particles(
|
|||
|
||||
default:
|
||||
for (i = 0; i < newparticles; i++) {
|
||||
int seed = (int)((std::numeric_limits<int>::max)() *
|
||||
int seed = (int)((std::numeric_limits<int>::max)() *
|
||||
values.random_val->getFloat());
|
||||
int level = (int)(values.random_val->getFloat() * level_n);
|
||||
int lifetime = 0;
|
||||
|
@ -402,9 +418,9 @@ void Particles_Engine::normalize_values(struct particles_values &values,
|
|||
(values.speeda_val.first) = (values.speeda_val.first) * M_PI_180;
|
||||
(values.speeda_val.second) = (values.speeda_val.second) * M_PI_180;
|
||||
if (values.step_val < 1) values.step_val = 1;
|
||||
values.genfadecol_val = (values.genfadecol_val) * 0.01;
|
||||
values.finfadecol_val = (values.finfadecol_val) * 0.01;
|
||||
values.foutfadecol_val = (values.foutfadecol_val) * 0.01;
|
||||
values.genfadecol_val = (values.genfadecol_val) * 0.01;
|
||||
values.finfadecol_val = (values.finfadecol_val) * 0.01;
|
||||
values.foutfadecol_val = (values.foutfadecol_val) * 0.01;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------*/
|
||||
|
@ -492,6 +508,9 @@ void Particles_Engine::render_particles(
|
|||
TRenderSettings riAux(ri);
|
||||
riAux.m_affine = TAffine();
|
||||
riAux.m_bpp = 32;
|
||||
// control image using its gradient is computed in 64bpp
|
||||
TRenderSettings riAux64(riAux);
|
||||
riAux64.m_bpp = 64;
|
||||
|
||||
int r_frame; // Useful in case of negative roll frames
|
||||
if (frame < 0)
|
||||
|
@ -538,32 +557,74 @@ void Particles_Engine::render_particles(
|
|||
// dryComputed - so, declare the same here.
|
||||
(*it->second)->dryCompute(bbox, r_frame, riAux);
|
||||
} else {
|
||||
tmp = new TTile;
|
||||
// control image is used its gradient
|
||||
if (port_is_used_for_gradient(it->first, values)) {
|
||||
tmp = new TTile;
|
||||
|
||||
if (isPrecomputingEnabled)
|
||||
(*it->second)
|
||||
->allocateAndCompute(*tmp, bbox.getP00(),
|
||||
convert(bbox).getSize(), 0, r_frame,
|
||||
riAux);
|
||||
else {
|
||||
std::string alias =
|
||||
"CTRL: " + (*(it->second))->getAlias(r_frame, riAux);
|
||||
TRasterImageP rimg = TImageCache::instance()->get(alias, false);
|
||||
if (isPrecomputingEnabled)
|
||||
(*it->second)
|
||||
->allocateAndCompute(*tmp, bbox.getP00(),
|
||||
convert(bbox).getSize(), 0, r_frame,
|
||||
riAux64);
|
||||
else {
|
||||
std::string alias =
|
||||
"CTRL64: " + (*(it->second))->getAlias(r_frame, riAux64);
|
||||
TRasterImageP rimg = TImageCache::instance()->get(alias, false);
|
||||
|
||||
if (rimg) {
|
||||
if (rimg) {
|
||||
tmp->m_pos = bbox.getP00();
|
||||
tmp->setRaster(rimg->getRaster());
|
||||
} else {
|
||||
(*it->second)
|
||||
->allocateAndCompute(*tmp, bbox.getP00(),
|
||||
convert(bbox).getSize(), 0, r_frame,
|
||||
riAux64);
|
||||
|
||||
addRenderCache(alias, TRasterImageP(tmp->getRaster()));
|
||||
}
|
||||
}
|
||||
|
||||
porttiles[it->first + Ctrl_64_Offset] = tmp;
|
||||
|
||||
// in case the control image is also used for non-gradient
|
||||
if (port_is_used_for_value(it->first, values)) {
|
||||
TRaster32P tileRas(tmp->getRaster()->getSize());
|
||||
TRop::convert(tileRas, tmp->getRaster());
|
||||
tmp = new TTile;
|
||||
tmp->m_pos = bbox.getP00();
|
||||
tmp->setRaster(rimg->getRaster());
|
||||
} else {
|
||||
tmp->setRaster(tileRas);
|
||||
porttiles[it->first] = tmp;
|
||||
}
|
||||
}
|
||||
// control images used only for non-gradient
|
||||
else {
|
||||
tmp = new TTile;
|
||||
|
||||
if (isPrecomputingEnabled)
|
||||
(*it->second)
|
||||
->allocateAndCompute(*tmp, bbox.getP00(),
|
||||
convert(bbox).getSize(), 0, r_frame,
|
||||
riAux);
|
||||
else {
|
||||
std::string alias =
|
||||
"CTRL: " + (*(it->second))->getAlias(r_frame, riAux);
|
||||
TRasterImageP rimg = TImageCache::instance()->get(alias, false);
|
||||
|
||||
addRenderCache(alias, TRasterImageP(tmp->getRaster()));
|
||||
if (rimg) {
|
||||
tmp->m_pos = bbox.getP00();
|
||||
tmp->setRaster(rimg->getRaster());
|
||||
} else {
|
||||
(*it->second)
|
||||
->allocateAndCompute(*tmp, bbox.getP00(),
|
||||
convert(bbox).getSize(), 0, r_frame,
|
||||
riAux);
|
||||
|
||||
addRenderCache(alias, TRasterImageP(tmp->getRaster()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
porttiles[it->first] = tmp;
|
||||
porttiles[it->first] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -849,7 +910,7 @@ void Particles_Engine::fill_array(TTile *ctrl1, int ®ioncount,
|
|||
mask[1] = myarray[i - 1 + lx * (j - 1)];
|
||||
}
|
||||
if (i != lx - 1) mask[3] = myarray[i + 1 + lx * (j - 1)];
|
||||
mask[2] = myarray[i + lx * (j - 1)];
|
||||
mask[2] = myarray[i + lx * (j - 1)];
|
||||
if (!mask[0] && !mask[1] && !mask[2] && !mask[3]) {
|
||||
(regioncount)++;
|
||||
myarray[i + lx * j] = (regioncount);
|
||||
|
@ -883,7 +944,7 @@ void Particles_Engine::fill_array(TTile *ctrl1, int ®ioncount,
|
|||
void Particles_Engine::normalize_array(
|
||||
std::vector<std::vector<TPointD>> &myregions, TPointD pos, int lx, int ly,
|
||||
int regioncounter, std::vector<int> &myarray, std::vector<int> &lista,
|
||||
std::vector<int> &listb, std::vector<int> & final) {
|
||||
std::vector<int> &listb, std::vector<int> &final) {
|
||||
int i, j, k, l;
|
||||
|
||||
std::vector<int> tmp;
|
||||
|
@ -896,13 +957,13 @@ void Particles_Engine::normalize_array(
|
|||
j = lista[l];
|
||||
/*TMSG_INFO("j vale %d\n", j);*/
|
||||
while (final[j] != j) j = final[j];
|
||||
k = listb[l];
|
||||
k = listb[l];
|
||||
/*TMSG_INFO("k vale %d\n", k);*/
|
||||
while (final[k] != k) k = final[k];
|
||||
if (j != k) final[j] = k;
|
||||
if (j != k) final[j] = k;
|
||||
}
|
||||
// TMSG_INFO("esco dal for\n");
|
||||
for (j = 1; j <= regioncounter; j++)
|
||||
for (j = 1; j <= regioncounter; j++)
|
||||
while (final[j] != final[final[j]]) final[j] = final[final[j]];
|
||||
|
||||
/*conto quante cavolo di regioni sono*/
|
||||
|
|
|
@ -52,6 +52,8 @@ public:
|
|||
std::map<std::pair<int, int>, double> &partScales);
|
||||
|
||||
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);
|
||||
|
||||
/*-
|
||||
do_source_gradationがONのとき、入力画像のアルファ値に比例して発生濃度を変える。
|
||||
|
@ -81,7 +83,7 @@ public:
|
|||
void normalize_array(std::vector<std::vector<TPointD>> &myregions,
|
||||
TPointD pos, int lx, int ly, int regioncounter,
|
||||
std::vector<int> &myarray, std::vector<int> &lista,
|
||||
std::vector<int> &listb, std::vector<int> & final);
|
||||
std::vector<int> &listb, std::vector<int> &final);
|
||||
|
||||
void fill_array(TTile *ctrl1, int ®ioncount, std::vector<int> &myarray,
|
||||
std::vector<int> &lista, std::vector<int> &listb, int thres);
|
||||
|
|
Loading…
Reference in a new issue