apophysis7x/Plugin/xtrb.c

296 lines
7.5 KiB
C
Raw Permalink Normal View History

/*
Apophysis Plugin
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
Some comments on TriBorders plugin structure. It builds dual tessellation
on triangle grid as Boarders variation does for square one and it uses
trilinear coordinates ([link])
instead of usual Cartesian system (from where Tri Borders in plugin name).
Hex function doesn<EFBFBD>t work correctly in general case because its second part
(determines nonlinear texture) doesn<EFBFBD>t transform lines (passes from triangle vertex)
to itself for arbitrary triangle.
It possible to do and I<EFBFBD>ve done main job but have not finished.
*/
// Must define this structure before we include apoplugin.h
typedef struct
{
int xtrb_power;
double xtrb_dist;
double xtrb_radius, xtrb_width, xtrb_a, xtrb_b;
double angle_Ar, angle_Br, angle_Cr;
double sinA2, cosA2, sinB2, cosB2, sinC2, cosC2, sinC, cosC;
double a, b, c;
double Ha, Hb, Hc, S2;
double ab, ac, ba, bc, ca, cb, S2a, S2b, S2c, S2ab, S2ac, S2bc;
double width1, width2, width3;
double absN, cN;
} Variables;
#define _USE_MATH_DEFINES
#include "apoplugin.h"
// Set the name of this plugin
APO_PLUGIN("xtrb");
// Define the Variables
APO_VARIABLES(
VAR_INTEGER_NONZERO(xtrb_power, 2),
VAR_REAL(xtrb_radius, 1.0),
VAR_REAL(xtrb_width, 0.5),
VAR_REAL(xtrb_dist, 1.0),
VAR_REAL(xtrb_a, 1.0),
VAR_REAL(xtrb_b, 1.0)
);
// You must call the argument "vp".
int PluginVarPrepare(Variation* vp)
{
//VAR(angle_B)= 60;
//VAR(angle_C)= 60;
VAR(angle_Br) = 0.047 + VAR(xtrb_a);///180.0*M_PI; // angeles in radians
VAR(angle_Cr) = 0.047 + VAR(xtrb_b);///180.0*M_PI;
VAR(angle_Ar) =M_PI - VAR(angle_Br) - VAR(angle_Cr);
fsincos(0.5*VAR(angle_Ar), &VAR(sinA2), &VAR(cosA2)); // its sin, cos
fsincos(0.5*VAR(angle_Br), &VAR(sinB2), &VAR(cosB2));
fsincos(0.5*VAR(angle_Cr), &VAR(sinC2), &VAR(cosC2));
fsincos( VAR(angle_Cr), &VAR(sinC), &VAR(cosC));
VAR(a) = VAR(xtrb_radius)*( VAR(sinC2)/VAR(cosC2)+ VAR(sinB2)/VAR(cosB2)); //sides
VAR(b) = VAR(xtrb_radius)*( VAR(sinC2)/VAR(cosC2)+ VAR(sinA2)/VAR(cosA2));
VAR(c) = VAR(xtrb_radius)*( VAR(sinB2)/VAR(cosB2)+ VAR(sinA2)/VAR(cosA2));
VAR(width1) = 1 - VAR(xtrb_width);
VAR(width2) = 2* VAR(xtrb_width);
VAR(width3) = 1 - VAR(xtrb_width)*VAR(xtrb_width);
VAR(S2) = VAR(xtrb_radius)*( VAR(a)+VAR(b) +VAR(c)); //square
VAR(Ha) = VAR(S2)/VAR(a)/6.0; //Hight div on 6.0
VAR(Hb) = VAR(S2)/VAR(b)/6.0;
VAR(Hc) = VAR(S2)/VAR(c)/6.0;
VAR(ab) = VAR(a)/VAR(b);// a div on b
VAR(ac) = VAR(a)/VAR(c);
VAR(ba) = VAR(b)/VAR(a);
VAR(bc) = VAR(b)/VAR(c);
VAR(ca) = VAR(c)/VAR(a);
VAR(cb) = VAR(c)/VAR(b);
VAR(S2a) = 6.0*VAR(Ha);
VAR(S2b) = 6.0*VAR(Hb);
VAR(S2c) = 6.0*VAR(Hc);
VAR(S2bc) =VAR(S2)/(VAR(b)+VAR(c))/6.0;
VAR(S2ab) =VAR(S2)/(VAR(a)+VAR(b))/6.0;
VAR(S2ac) =VAR(S2)/(VAR(a)+VAR(c))/6.0;
VAR(absN) = (int)abs(VAR(xtrb_power));
VAR(cN) = VAR(xtrb_dist) / VAR(xtrb_power) / 2;
// Always return TRUE.
return TRUE;
}
void DirectTrilinear(Variation* vp, double x, double y, double* Al, double* Be, double* Ga)
{
double U = y + VAR(xtrb_radius);
double V = x * VAR(sinC) - y * VAR(cosC) + VAR(xtrb_radius);
*Al =U;
*Be =V;
*Ga = VAR(S2c) - VAR(ac) * U - VAR(bc) * V;
}
void InverseTrilinear(Variation* vp, double Al, double Be, double* x, double* y)
{
double inx = (Be - VAR(xtrb_radius) +(Al - VAR(xtrb_radius))* VAR(cosC))/ VAR(sinC);
double iny = Al - VAR(xtrb_radius);
double sina = 0.0, cosa = 0.0;
double angle = (atan2(iny, inx) + M_2PI * (rand() % (int)VAR(absN)))/ VAR(xtrb_power);
double r = VVAR * pow(sqr(inx) + sqr(iny), VAR(cN));
fsincos(angle, &sina, &cosa);
*x = r * cosa;
*y = r * sina;
//*x = 0; *y = 0;
}
void Hex(Variation* vp, double Al, double Be, double Ga, double* Al1, double* Be1) // it's necessary
//to improve for correct work for any triangle
{
double Ga1, De1, R;
R = random01();
if (Be < Al)
{
if (Ga < Be)
{
if (R >= VAR(width3))
{
De1 = VAR(xtrb_width) * Be;
Ga1 = VAR(xtrb_width) * Ga;
}
else
{
Ga1 = VAR(width1) * Ga + VAR(width2)*VAR(Hc)* Ga / Be;
De1 = VAR(width1)*Be+VAR(width2)*VAR(S2ab)*(3 -Ga / Be);
}
*Al1 = VAR(S2a) - VAR(ba)* De1 - VAR(ca)* Ga1;
*Be1 = De1;
}
else
{
if (Ga < Al)
{
if (R >= VAR(width3))
{
Ga1 = VAR(xtrb_width) * Ga;
De1 = VAR(xtrb_width) * Be;
}
else
{
De1 = VAR(width1) * Be + VAR(width2)*VAR(Hb)* Be / Ga;
Ga1 = VAR(width1)*Ga+VAR(width2)*VAR(S2ac)*(3 -Be / Ga);
}
*Al1 = VAR(S2a) - VAR(ba)* De1 - VAR(ca)* Ga1;
*Be1 = De1;
}
else
{
if (R >= VAR(width3))
{
*Al1 = VAR(xtrb_width) * Al;
*Be1 = VAR(xtrb_width) * Be;
}
else
{
*Be1 = VAR(width1) * Be+VAR(width2)*VAR(Hb)* Be / Al;
*Al1 = VAR(width1) * Al+VAR(width2)*VAR(S2ac)*(3-Be /Al);
}
}
}
}
else
{
if (Ga < Al)
{
if (R >= VAR(width3))
{
De1 = VAR(xtrb_width) * Al;
Ga1 = VAR(xtrb_width) * Ga;
}
else
{
Ga1 = VAR(width1) * Ga+VAR(width2)*VAR(Hc)* Ga / Al;
De1 = VAR(width1) *Al+VAR(width2)*VAR(S2ab)*(3 -Ga /Al);
}
*Be1 = VAR(S2b) - VAR(ab)* De1 - VAR(cb)* Ga1;
*Al1 = De1;
}
else
{
if (Ga < Be)
{
if (R >= VAR(width3))
{
Ga1 = VAR(xtrb_width) * Ga;
De1 = VAR(xtrb_width) * Al;
}
else
{
De1 = VAR(width1) * Al + VAR(width2)*VAR(Ha)* Al / Ga;
Ga1 = VAR(width1)*Ga + VAR(width2)*VAR(S2bc)*(3 -Al/Ga);
}
*Be1 = VAR(S2b) - VAR(ab)* De1 - VAR(cb)* Ga1;
*Al1 = De1;
}
else
{
if (R >= VAR(width3))
{
*Be1 = VAR(xtrb_width) * Be;
*Al1 = VAR(xtrb_width) * Al;
}
else
{
*Al1 = VAR(width1) * Al + VAR(width2)*VAR(Ha)* Al / Be;
*Be1 = VAR(width1)*Be+VAR(width2)*VAR(S2bc)*(3-Al / Be);
}
}
}
}
}
// You must call the argument "vp".
int PluginVarCalc(Variation* vp)
{
double Alpha, Beta, Gamma, OffsetAl, OffsetBe, OffsetGa, X, Y;
int M, N;
// transfer to trilinear coordinates, normalized to real distances from triangle sides
DirectTrilinear(vp, FTx, FTy, &Alpha, &Beta, &Gamma);
M = floor(Alpha/VAR(S2a));
OffsetAl = Alpha - M*VAR(S2a);
N = floor(Beta/VAR(S2b));
OffsetBe = Beta - N*VAR(S2b);
OffsetGa = VAR(S2c) - VAR(ac)*OffsetAl - VAR(bc)*OffsetBe;
if ( OffsetGa > 0 )
{
Hex(vp, OffsetAl, OffsetBe, OffsetGa, &Alpha, &Beta);
}
else
{
OffsetAl = VAR(S2a) - OffsetAl;
OffsetBe = VAR(S2b) - OffsetBe;
OffsetGa = - OffsetGa;
Hex(vp, OffsetAl, OffsetBe, OffsetGa, &Alpha, &Beta);
Alpha = VAR(S2a) - Alpha;
Beta = VAR(S2b) - Beta;
}
Alpha = Alpha + M*VAR(S2a);
Beta = Beta + N*VAR(S2b);
InverseTrilinear(vp, Alpha, Beta, &X, &Y);
FPx += VVAR * X;
FPy += VVAR * Y;
return TRUE;
}