95a2f54683
git-svn-id: https://svn.code.sf.net/p/apophysis7x/svn/trunk@1 a5d1c0f9-a0e9-45c6-87dd-9d276e40c949
103 lines
3.2 KiB
C
103 lines
3.2 KiB
C
/*
|
|
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;
|
|
}
|