apophysis7x/Plugin/dc_triangle.c

103 lines
3.2 KiB
C
Raw 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.
*/
typedef struct
{
double dc_triangle_scatter_area, A;
int dc_triangle_zero_edges;
} Variables;
#include "apoplugin.h"
APO_PLUGIN("dc_triangle");
APO_VARIABLES(
VAR_REAL(dc_triangle_scatter_area, 0.0),
VAR_INTEGER_RANGE(dc_triangle_zero_edges, 0, 1, 0)
);
int PluginVarPrepare(Variation* vp)
{
VAR(A) = VAR(dc_triangle_scatter_area) < -1 ? -1 :
VAR(dc_triangle_scatter_area) > 1 ? 1 :
VAR(dc_triangle_scatter_area);
return TRUE;
}
/* This function is called during calculation.
You must call the argument "vp"
*/
int PluginVarCalc(Variation* vp)
{
// set up triangle
const double
xx = TM(a), xy = TM(b), // X
yx = TM(c) * -1, yy = TM(d) * -1, // Y
ox = TM(e), oy = TM(f), // O
px = FTx - ox, py = FTy - oy; // P
// calculate dot products
const double dot00 = xx * xx + xy * xy; // X * X
const double dot01 = xx * yx + xy * yy; // X * Y
const double dot02 = xx * px + xy * py; // X * P
const double dot11 = yx * yx + yy * yy; // Y * Y
const double dot12 = yx * px + yy * py; // Y * P
// calculate barycentric coordinates
const double denom = (dot00 * dot11 - dot01 * dot01);
const double num_u = (dot11 * dot02 - dot01 * dot12);
const double num_v = (dot00 * dot12 - dot01 * dot02);
// u, v must not be constant
double u = num_u / denom;
double v = num_v / denom;
int inside = 0, f = 1;
// case A - point escapes edge XY
if (u + v > 1) { f = -1;
if (u > v) { u = u>1?1:u; v = 1-u; }
else { v = v>1?1:v; u = 1-v; } }
// case B - point escapes either edge OX or OY
else if ((u < 0) || (v < 0)) {
u = u<0?0:u>1?1:u; v = v<0?0:v>1?1:v; }
// case C - point is in triangle
else inside = 1;
// handle outside points
if (VAR(dc_triangle_zero_edges) && !inside) u = v = 0;
else if (!inside) {
u = (u + random01() * VAR(A) * f);
v = (v + random01() * VAR(A) * f);
u = u<-1?-1:u>1?1:u; v = v<-1?-1:v>1?1:v;
if ((u + v > 1) && (VAR(A) > 0))
if (u > v) { u = u>1?1:u; v = 1-u; }
else { v = v>1?1:v; u = 1-v; }
}
// set output
FPx += VVAR * (ox + u * xx + v * yx);
FPy += VVAR * (oy + u * xy + v * yy);
FPz += VVAR * FTz;
TC = fmod(fabs(u+v),1.0);
// done
return TRUE;
}