diff --git a/toonz/sources/stdfx/iwa_fractalnoisefx.cpp b/toonz/sources/stdfx/iwa_fractalnoisefx.cpp index c694f24..649c0b9 100644 --- a/toonz/sources/stdfx/iwa_fractalnoisefx.cpp +++ b/toonz/sources/stdfx/iwa_fractalnoisefx.cpp @@ -33,7 +33,7 @@ inline const T &clamp(const T &v, const T &lo, const T &hi) { const double turbulentGamma = 2.2; // magic number to offset evolution between generations -const double evolutionOffsetStep = 19.82; +const double evolutionOffsetStep = 19.82; const double evolutionOffsetStepW = 31.1; } // namespace //------------------------------------------------------------------ @@ -61,11 +61,11 @@ Iwa_FractalNoiseFx::Iwa_FractalNoiseFx() ///, m_randomSeed(0) , m_dynamicIntensity(1.0) , m_alphaRendering(false) -, m_doConical(false) -, m_conicalEvolution(0.0) -, m_conicalAngle(60.0) -, m_cameraFov(60.0) -, m_zScale(2.0) { + , m_doConical(false) + , m_conicalEvolution(0.0) + , m_conicalAngle(60.0) + , m_cameraFov(60.0) + , m_zScale(2.0) { m_fractalType->addItem(TurbulentSmooth, "Turbulent Smooth"); m_fractalType->addItem(TurbulentBasic, "Turbulent Basic"); m_fractalType->addItem(TurbulentSharp, "Turbulent Sharp"); @@ -167,7 +167,7 @@ void Iwa_FractalNoiseFx::doCompute(TTile &tile, double frame, double *work_buf = (double *)work_buf_ras->getRawData(); // affine transformations - TAffine globalAff = TTranslation(-tile.m_pos) * ri.m_affine; + TAffine globalAff = TTranslation(-tile.m_pos) * ri.m_affine; TAffine parentAff = TScale(param.scale.lx, param.scale.ly) * TRotation(-param.rotation); TAffine subAff = TTranslation(param.subOffset) * TScale(param.subScaling) * @@ -195,34 +195,34 @@ void Iwa_FractalNoiseFx::doCompute(TTile &tile, double frame, for (int gen = 0; gen < genCount; gen++) { // affine transformation for the current generation TAffine currentAff = - (globalAff * parentOffsetAff * parentAff * genAff).inv(); + (globalAff * parentOffsetAff * parentAff * genAff).inv(); // scale of the current pattern ( used for the Dynamic / Dynamic Twist // offset ) double scale = sqrt(std::abs(currentAff.det())); // for each pixel - double* buf_p = work_buf; + double *buf_p = work_buf; for (int y = 0; y < outDim.ly; y++) { for (int x = 0; x < outDim.lx; x++, buf_p++) { // obtain sampling position // For Dynamic and Dynamic Twist patterns, the position offsets using // gradient / rotation of the parent pattern TPointD samplePos = - getSamplePos(x, y, outDim, out_buf, gen, scale, param); + getSamplePos(x, y, outDim, out_buf, gen, scale, param); // multiply affine transformation samplePos = currentAff * samplePos; // adjust position for the block pattern if (param.noiseType == Block) samplePos = TPointD(std::floor(samplePos.x) + 0.5, - std::floor(samplePos.y) + 0.5); + std::floor(samplePos.y) + 0.5); // calculate the base noise if (param.cycleEvolution) *buf_p = (pn.noise(samplePos.x, samplePos.y, evolution_zw.x, - evolution_zw.y) + - 1.0) * - 0.5; + evolution_zw.y) + + 1.0) * + 0.5; else *buf_p = - (pn.noise(samplePos.x, samplePos.y, evolution_z) + 1.0) * 0.5; + (pn.noise(samplePos.x, samplePos.y, evolution_z) + 1.0) * 0.5; // convert the noise convert(buf_p, param); @@ -232,17 +232,16 @@ void Iwa_FractalNoiseFx::doCompute(TTile &tile, double frame, // just copy the values for the first generation if (gen == 0) { memcpy(out_buf, work_buf, outDim.lx * outDim.ly * sizeof(double)); - } - else { + } else { // intensity of the last generation will take the fraction part of // complexity double genIntensity = std::min(1.0, param.complexity - (double)gen); // influence of the current generation double influence = - genIntensity * std::pow(param.subInfluence, (double)gen); + genIntensity * std::pow(param.subInfluence, (double)gen); // composite the base noise pattern - buf_p = work_buf; - double* out_p = out_buf; + buf_p = work_buf; + double *out_p = out_buf; for (int i = 0; i < outDim.lx * outDim.ly; i++, buf_p++, out_p++) composite(out_p, buf_p, influence, param); } @@ -253,9 +252,9 @@ void Iwa_FractalNoiseFx::doCompute(TTile &tile, double frame, // according to the sub scale if (param.perspectiveOffset) parentOffsetAff = TScale(param.subScaling) * - TRotation(-param.subRotation) * parentOffsetAff * - TRotation(param.subRotation) * - TScale(1 / param.subScaling); + TRotation(-param.subRotation) * parentOffsetAff * + TRotation(param.subRotation) * + TScale(1 / param.subScaling); if (param.cycleEvolution) evolution_zw.x += evolutionOffsetStep; @@ -269,8 +268,8 @@ void Iwa_FractalNoiseFx::doCompute(TTile &tile, double frame, // angle of slope of the cone double theta_n = param.conicalAngle * M_PI_180; // half of the vertical fov - double phi_2 = param.cameraFov * 0.5 * M_PI_180; - double z_scale = std::pow(10.0, param.zScale); + double phi_2 = param.cameraFov * 0.5 * M_PI_180; + double z_scale = std::pow(10.0, param.zScale); double evolution_w = param.conicalEvolution; // pixel distance between camera and the screen @@ -284,83 +283,99 @@ void Iwa_FractalNoiseFx::doCompute(TTile &tile, double frame, // accumulate base noise pattern for each generation for (int gen = 0; gen < genCount; gen++) { // affine transformation for the current generation - TAffine currentAff = - (globalAff * parentAff * genAff).inv(); + TAffine currentAff = (globalAff * parentAff * genAff).inv(); // scale of the current pattern ( used for the Dynamic / Dynamic Twist // offset ) double scale = sqrt(std::abs(currentAff.det())); // for each pixel - double* buf_p = work_buf; + double *buf_p = work_buf; for (int y = 0; y < outDim.ly; y++) { for (int x = 0; x < outDim.lx; x++, buf_p++) { - double dx, dy, dz; if (theta_n == 0.0) { dx = x; dy = y; dz = 0.0; - } - else { + } else { // conical, without offset if (center == TPointD()) { TPointD p = TTranslation(tile.m_pos) * TPointD(x, y); // pixel distance from the screen center double d = tdistance(p, TPointD()); // line of sight : d = S * z + T - double S = d / D; - double T = d; - dz = (V - T) / (S - U); + double S = d / D; + double T = d; + dz = (V - T) / (S - U); double dp = S * dz + T; if (d != 0.0) { p.x *= dp / d; p.y *= dp / d; } p += center * (dp / V); - p = TTranslation(tile.m_pos).inv() * p; + p = TTranslation(tile.m_pos).inv() * p; dx = p.x; dy = p.y; dz /= z_scale; } // conical, with offset else { - // compute the intersecting point between the "noise cone" and the line of sight + // compute the intersecting point between the "noise cone" and the + // line of sight TPointD _p = TTranslation(tile.m_pos) * TPointD(x, y); - QVector3D p(_p.x, _p.y, 0.0); - QVector3D eye_O(center.x, center.y, -D); - QVector3D eye_d = (p - eye_O).normalized(); + // offset by combination of offsets of A) projection position and + // B) eye positon. + // + // A) 0.5 * projection position offset + QVector3D p(_p.x - center.x * 0.5, _p.y - center.y * 0.5, 0.0); QVector3D cone_C(0.0, 0.0, V * std::tan(theta_n)); QVector3D cone_a(0, 0, -1); + // B) 0.5 * eye position offset + double offsetAdj = 0.5 * (D + cone_C.z()) / cone_C.z(); + QVector3D eye_O(center.x * offsetAdj, center.y * offsetAdj, -D); + QVector3D eye_d = (p - eye_O).normalized(); double cos_ConeT = std::sin(theta_n); - float d_a = QVector3D::dotProduct(eye_d, cone_a); - float Ca_Oa = QVector3D::dotProduct(cone_C, cone_a) - QVector3D::dotProduct(eye_O, cone_a); + float d_a = QVector3D::dotProduct(eye_d, cone_a); + float Ca_Oa = QVector3D::dotProduct(cone_C, cone_a) - + QVector3D::dotProduct(eye_O, cone_a); // A * t^2 + B * t + C = 0 - float A = d_a * d_a - eye_d.lengthSquared() * cos_ConeT; - float B = 2.0 * (QVector3D::dotProduct(eye_d, cone_C) - QVector3D::dotProduct(eye_d, eye_O)) * cos_ConeT * cos_ConeT - - 2.0 * Ca_Oa * d_a; - float C = Ca_Oa * Ca_Oa - - cos_ConeT * cos_ConeT * (cone_C.lengthSquared() - 2.0 * QVector3D::dotProduct(eye_O, cone_C) + eye_O.lengthSquared()); + float A = + d_a * d_a - eye_d.lengthSquared() * cos_ConeT * cos_ConeT; + float B = 2.0 * + (QVector3D::dotProduct(eye_d, cone_C) - + QVector3D::dotProduct(eye_d, eye_O)) * + cos_ConeT * cos_ConeT - + 2.0 * Ca_Oa * d_a; + float C = Ca_Oa * Ca_Oa - + cos_ConeT * cos_ConeT * + (cone_C.lengthSquared() - + 2.0 * QVector3D::dotProduct(eye_O, cone_C) + + eye_O.lengthSquared()); // obtain t double t1 = (-B + std::sqrt(B * B - 4.0 * A * C)) / (2.0 * A); double t2 = (-B - std::sqrt(B * B - 4.0 * A * C)) / (2.0 * A); - if (t1 < 0) t1 = t2; - else if (t2 < 0) t2 = t1; + if (t1 < 0) + t1 = t2; + else if (t2 < 0) + t2 = t1; double t = std::min(t1, t2); // intersecting point QVector3D sampleP = eye_O + eye_d * t; - _p.x = sampleP.x(); - _p.y = sampleP.y(); - _p = TTranslation(tile.m_pos).inv() * _p; - dx = _p.x; - dy = _p.y; - dz = sampleP.z() / z_scale; + _p.x = sampleP.x(); + _p.y = sampleP.y(); + _p = TTranslation(tile.m_pos).inv() * _p; + dx = _p.x; + dy = _p.y; + dz = sampleP.z() / z_scale; } if (param.cycleEvolution) { - double cycle_theta = 2.0 * M_PI * (param.evolution + param.conicalEvolution + dz) / param.cycleEvolutionRange; + double cycle_theta = + 2.0 * M_PI * (param.evolution + param.conicalEvolution + dz) / + param.cycleEvolutionRange; double cycle_d = param.cycleEvolutionRange / (2.0 * M_PI); evolution_zw.x = cycle_d * cos(cycle_theta); evolution_zw.y = cycle_d * sin(cycle_theta); @@ -370,22 +385,24 @@ void Iwa_FractalNoiseFx::doCompute(TTile &tile, double frame, // For Dynamic and Dynamic Twist patterns, the position offsets using // gradient / rotation of the parent pattern TPointD samplePos = - getSamplePos(dx, dy, outDim, out_buf, gen, scale, param); + getSamplePos(dx, dy, outDim, out_buf, gen, scale, param); // multiply affine transformation samplePos = currentAff * samplePos; // adjust position for the block pattern if (param.noiseType == Block) samplePos = TPointD(std::floor(samplePos.x) + 0.5, - std::floor(samplePos.y) + 0.5); + std::floor(samplePos.y) + 0.5); // calculate the base noise if (param.cycleEvolution) *buf_p = (pn.noise(samplePos.x, samplePos.y, evolution_zw.x, - evolution_zw.y) + - 1.0) * - 0.5; + evolution_zw.y) + + 1.0) * + 0.5; else - *buf_p = - (pn.noise(samplePos.x, samplePos.y, evolution_z, evolution_w + dz) + 1.0) * 0.5; + *buf_p = (pn.noise(samplePos.x, samplePos.y, evolution_z, + evolution_w + dz) + + 1.0) * + 0.5; // convert the noise convert(buf_p, param); @@ -395,17 +412,16 @@ void Iwa_FractalNoiseFx::doCompute(TTile &tile, double frame, // just copy the values for the first generation if (gen == 0) { memcpy(out_buf, work_buf, outDim.lx * outDim.ly * sizeof(double)); - } - else { + } else { // intensity of the last generation will take the fraction part of // complexity double genIntensity = std::min(1.0, param.complexity - (double)gen); // influence of the current generation double influence = - genIntensity * std::pow(param.subInfluence, (double)gen); + genIntensity * std::pow(param.subInfluence, (double)gen); // composite the base noise pattern - buf_p = work_buf; - double* out_p = out_buf; + buf_p = work_buf; + double *out_p = out_buf; for (int i = 0; i < outDim.lx * outDim.ly; i++, buf_p++, out_p++) composite(out_p, buf_p, influence, param); } @@ -422,7 +438,6 @@ void Iwa_FractalNoiseFx::doCompute(TTile &tile, double frame, } } - work_buf_ras->unlock(); // finalize pattern (converting the color space) @@ -483,13 +498,13 @@ void Iwa_FractalNoiseFx::obtainParams(FNParam ¶m, const double frame, param.cycleEvolutionRange = m_cycleEvolutionRange->getValue(frame); param.dynamicIntensity = m_dynamicIntensity->getValue(frame) * 10.0; - param.doConical = m_doConical->getValue(); + param.doConical = m_doConical->getValue(); param.conicalEvolution = m_conicalEvolution->getValue(frame); - param.conicalAngle = m_conicalAngle->getValue(frame); - param.cameraFov = m_cameraFov->getValue(frame); - param.zScale = m_zScale->getValue(frame); + param.conicalAngle = m_conicalAngle->getValue(frame); + param.cameraFov = m_cameraFov->getValue(frame); + param.zScale = m_zScale->getValue(frame); - param.alphaRendering = m_alphaRendering->getValue(); + param.alphaRendering = m_alphaRendering->getValue(); } //------------------------------------------------------------------ @@ -529,7 +544,8 @@ void Iwa_FractalNoiseFx::getParamUIs(TParamUIConcept *&concepts, int &length) { //------------------------------------------------------------------ // For Dynamic and Dynamic Twist patterns, the position offsets using gradient / // rotation of the parent pattern -TPointD Iwa_FractalNoiseFx::getSamplePos(double x, double y, const TDimension outDim, +TPointD Iwa_FractalNoiseFx::getSamplePos(double x, double y, + const TDimension outDim, const double *out_buf, const int gen, const double scale, const FNParam ¶m) { @@ -541,43 +557,47 @@ TPointD Iwa_FractalNoiseFx::getSamplePos(double x, double y, const TDimension ou auto clampPos = [&](double x, double y) { if (x < 0.0) x = 0.0; - else if (x > (double)(outDim.lx-1)) + else if (x > (double)(outDim.lx - 1)) x = (double)(outDim.lx - 1); if (y < 0.0) y = 0.0; - else if (y > (double)(outDim.ly-1)) + else if (y > (double)(outDim.ly - 1)) y = (double)(outDim.ly - 1); return TPointD(x, y); }; - auto val = [&](const TPoint& p) { - return out_buf[std::min(p.y, outDim.ly - 1) * outDim.lx + std::min(p.x, outDim.lx - 1)]; + auto val = [&](const TPoint &p) { + return out_buf[std::min(p.y, outDim.ly - 1) * outDim.lx + + std::min(p.x, outDim.lx - 1)]; }; auto lerp = [](double v0, double v1, double ratio) { return (1.0 - ratio) * v0 + ratio * v1; }; - auto lerpVal = [&](const TPointD &p) { - int id_x = (int)std::floor(p.x); + auto lerpVal = [&](const TPointD &p) { + int id_x = (int)std::floor(p.x); double ratio_x = p.x - (double)id_x; - int id_y = (int)std::floor(p.y); + int id_y = (int)std::floor(p.y); double ratio_y = p.y - (double)id_y; - return lerp ( lerp(val(TPoint(id_x, id_y)), val(TPoint(id_x+1, id_y)), ratio_x), - lerp(val(TPoint(id_x, id_y+1)), val(TPoint(id_x + 1, id_y+1)), ratio_x), ratio_y); + return lerp( + lerp(val(TPoint(id_x, id_y)), val(TPoint(id_x + 1, id_y)), ratio_x), + lerp(val(TPoint(id_x, id_y + 1)), val(TPoint(id_x + 1, id_y + 1)), + ratio_x), + ratio_y); }; - int range = std::max(2, (int)(0.1 / scale)); - TPointD left = clampPos(x - range, y); + int range = std::max(2, (int)(0.1 / scale)); + TPointD left = clampPos(x - range, y); TPointD right = clampPos(x + range, y); TPointD down = clampPos(x, y - range); TPointD up = clampPos(x, y + range); double dif_x = param.dynamicIntensity * (1 / scale) * (lerpVal(left) - lerpVal(right)) / (left.x - right.x); - double dif_y = param.dynamicIntensity * (1 / scale) * (lerpVal(up) - lerpVal(down)) / - (up.y - down.y); + double dif_y = param.dynamicIntensity * (1 / scale) * + (lerpVal(up) - lerpVal(down)) / (up.y - down.y); if (param.fractalType == Dynamic) return TPointD(x + dif_x, y + dif_y); // gradient - else // Dynamic_twist + else // Dynamic_twist return TPointD(x + dif_y, y - dif_x); // rotation } diff --git a/toonz/sources/stdfx/iwa_fractalnoisefx.h b/toonz/sources/stdfx/iwa_fractalnoisefx.h index e58d61b..0debcbc 100644 --- a/toonz/sources/stdfx/iwa_fractalnoisefx.h +++ b/toonz/sources/stdfx/iwa_fractalnoisefx.h @@ -113,7 +113,7 @@ protected: // ダイナミックの度合い TDoubleParamP m_dynamicIntensity; - //- - - Conical Noise - - - + //- - - Conical Noise - - - TBoolParamP m_doConical; TDoubleParamP m_conicalEvolution; TDoubleParamP m_conicalAngle; @@ -126,7 +126,7 @@ protected: public: Iwa_FractalNoiseFx(); bool canHandle(const TRenderSettings &info, double frame) override { - return true; + return !m_doConical->getValue(); } bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &ri) override;