Apophysis-AV/Flame/XForm.pas

2157 lines
53 KiB
ObjectPascal
Raw Permalink Normal View History

2022-03-08 12:25:51 -05:00
{
Apophysis Copyright (C) 2001-2004 Mark Townsend
Apophysis Copyright (C) 2005-2006 Ronald Hordijk, Piotr Borys, Peter Sdobnov
Apophysis Copyright (C) 2007-2008 Piotr Borys, Peter Sdobnov
Apophysis "3D hack" Copyright (C) 2007-2008 Peter Sdobnov
Apophysis "7X" Copyright (C) 2009-2010 Georg Kiehne
Apophysis AV "Phoenix Edition" Copyright (C) 2021-2022 Alice V. Koryagina
2022-03-08 12:25:51 -05:00
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.
}
// REMOVE COMMENT TO COMPILE T-500
//{$define T500}
//{$define Light}
unit XForm;
interface
uses
{$ifdef CPUX86}
2022-03-08 12:25:51 -05:00
AsmRandom,
{$endif}
XFormMan, BaseVariation, Classes;
const
MAX_WEIGHT = 1000.0;
{$ifndef Light}
{$ifndef T500}
NXFORMS = 100;
{$else}
NXFORMS = 250; // 500; // AV: to use 1-byte type
{$endif}
{$else}
NXFORMS = 50;
{$endif}
type
TCPpoint = record
x, y, z, c: double;
end;
PCPpoint = ^TCPpoint;
TXYpoint = record
x, y: double;
end;
PXYpoint = ^TXYpoint;
{
2022-03-08 12:25:51 -05:00
T2Cpoint = record
x, y, c1, c2: double;
end;
P2Cpoint = ^T2Cpoint;
2022-03-08 12:25:51 -05:00
TMatrix = array[0..2, 0..2] of double;
}
2022-03-08 12:25:51 -05:00
// AV: rewrote all asm-code from Apo7X to make it work properly again
{$ifdef CPUX86}
2022-03-08 12:25:51 -05:00
{$define _ASM_}
{$endif}
type
TCoefsArray = array[0..2, 0..1] of double; // AV: moved from ControlPoint
//pCoefsArray = ^TCoefsArray;
2022-03-08 12:25:51 -05:00
TXForm = class
public
c: TCoefsArray; // the coefs to the affine part of the function
p: TCoefsArray; // post-transform coefs!
density: double; // prob is this function is chosen
color: double; // color coord for this function. 0 - 1
color2: double; // Second color coord for this function. 0 - 1
vc: double; // Calculated color to be passed to the plugin
2022-03-08 12:25:51 -05:00
symmetry: double;
c00, c01, c10, c11, c20, c21: double; // unnecessary duplicated variables
p00, p01, p10, p11, p20, p21: double; // :-)
postXswap: boolean;
TransformName : string;
autoZscale: boolean; // for 3d editing
transOpacity: double;
pluginColor: double;
modWeights: array [0..NXFORMS] of double;
PropTable: array of TXForm;
// Orientationtype: integer;
ifs: TStringList; // AV: to keep custom variation order
private
vars: array of double; // {normalized} interp coefs between variations
FNrFunctions: Integer;
FFunctionList: array of TCalcFunction;
FCalcFunctionList: array of TCalcFunction;
FTx, FTy: double; // must remain in this order
FPx, FPy: double; // some asm code relies on this
FTz, FPz: double; // 3d hack
FAngle: double;
FSinA: double;
FCosA: double;
FLength: double;
colorC1, colorC2: double;
// precalculated constants for some variations
polar_vpi, disc_vpi: double;
polar2_vpi, p2vv2: double;
gauss_rnd: array [0..3] of double;
gauss_N: integer;
rx_sin, rx_cos, ry_sin, ry_cos: double;
px_sin, px_cos, py_sin, py_cos: double;
FRegVariations: array of TBaseVariation;
procedure PrecalcAngle;
procedure PrecalcSinCos;
procedure PrecalcAll;
procedure DoPostTransform;
procedure DoInvalidOperation;
procedure Linear3D; // vars[0]
procedure PreBlur3D; // vars[2]
procedure Spherical; // vars[3]
procedure Swirl; // vars[4]
procedure Horseshoe; // vars[5]
procedure Polar; // vars[6]
procedure Disc; // vars[7]
procedure Spiral; // vars[8]
procedure hyperbolic; // vars[9]
procedure Diamond; // vars[10]
procedure Eyefish; // vars[11]
procedure Bubble; // vars[12]
procedure Cylinder; // vars[13]
procedure Noise; // vars[14]
procedure Blur; // vars[15]
procedure Gaussian; // vars[16]
procedure ZBlur; // vars[17]
procedure Blur3D; // vars[18]
procedure PreBlur; // vars[19]
procedure PreZScale; // vars[20]
2022-03-08 12:25:51 -05:00
procedure PreZTranslate; // vars[21]
procedure PreRotateX; // vars[22]
procedure PreRotateY; // vars[23]
procedure Flatten; // vars[1]
procedure ZScale; // vars[24]
procedure ZTranslate; // vars[25]
procedure ZCone; // vars[26]
procedure PostRotateX; // vars[27]
procedure PostRotateY; // vars[28]
procedure PostMirrorX; // vars[29]
procedure PostMirrorY; // vars[30]
procedure PostMirrorZ; // vars[31]
procedure Hemisphere; // vars[32]
procedure Cross; // vars[33]
procedure Pyramid; // vars[34]
procedure Polar2; // vars[35]
//function Mul33(const M1, M2: TMatrix): TMatrix;
//function Identity: TMatrix;
2022-03-08 12:25:51 -05:00
procedure BuildFunctionlist;
procedure AddRegVariations;
public
constructor Create;
destructor Destroy; override;
procedure Clear(keepXaos: boolean = false);
procedure Prepare;
procedure PrepareInvalidXForm;
procedure Assign(Xform: TXForm);
procedure NextPoint(var CPpoint: TCPpoint);
procedure NextPointTo(var CPpoint, ToPoint: TCPpoint);
procedure NextPointXY(var px, py: double);
//procedure NextPoint2C(var p: T2CPoint);
2022-03-08 12:25:51 -05:00
// AV: extended all following methods for post-coefs support
procedure Rotate(var t: TCoefsArray; const degrees: double);
procedure Translate(var t: TCoefsArray; const x, y: double);
procedure Multiply(var t: TCoefsArray; const k, l, m, n: double);
procedure Scale(var t: TCoefsArray; const s: double);
procedure RandomizeCoefs(var t: TCoefsArray); // AV: for random flames
function detC: double; inline;
function detP: double; inline;
2022-03-08 12:25:51 -05:00
procedure GetVariable(const name: string; var Value: double);
procedure SetVariable(const name: string; var Value: double);
procedure ResetVariable(const name: string);
function GetVariableStr(const name: string): string;
procedure SetVariableStr(const name: string; var Value: string);
function ToXMLString: string;
function FinalToXMLString(IsEnabled: boolean): string;
function GetVariation(index : integer) : double;
procedure SetVariation(index : integer; value : double);
function NumVariations : integer;
end;
implementation
uses
SysUtils, Math, StrUtils;
const
EPS: double = 1E-300;
function TXForm.NumVariations : integer;
begin
Result := length(vars);
end;
function TXForm.GetVariation(index : integer) : double;
begin
Result := vars[index];
end;
procedure TXForm.SetVariation(index : integer; value : double);
begin
{
if (vars[index] = 0) and (value <> 0) then begin
// Activate var here
end else begin
// Deactivate var here
end;
}
vars[index] := value;
end;
{ TXForm }
///////////////////////////////////////////////////////////////////////////////
constructor TXForm.Create;
var i: Integer;
begin
AddRegVariations;
BuildFunctionlist;
SetLength(vars, NrVar); // <-- AV // NRLOCVAR + Length(FRegVariations));
2022-03-08 12:25:51 -05:00
// AV: set default variations order
ifs := TStringList.Create;
for i := 0 to NrVar-1 do ifs.Add(Varnames(i));
Clear;
end;
procedure TXForm.Clear(keepXaos: boolean = false);
var
i: Integer;
begin
density := 0;
color := 0;
symmetry := 0;
postXswap := false;
autoZscale := false;
c[0, 0] := 1;
c[0, 1] := 0;
c[1, 0] := 0;
c[1, 1] := 1;
c[2, 0] := 0;
c[2, 1] := 0;
p[0, 0] := 1;
p[0, 1] := 0;
p[1, 0] := 0;
p[1, 1] := 1;
p[2, 0] := 0;
p[2, 1] := 0;
vars[0] := 1;
for i := 1 to High(vars) do
vars[i] := 0;
if not keepXaos then // AV: for linked xforms
for i := 0 to NXFORMS do
modWeights[i] := 1;
for i := 0 to NrVar-1 do // restore default order
ifs.Strings[i] := Varnames(i);
transOpacity := 1;
pluginColor := 1;
end;
///////////////////////////////////////////////////////////////////////////////
procedure TXForm.Prepare;
var
i, v: integer;
CalculateAngle, CalculateSinCos, CalculateLength: boolean;
mode: double;
vn: string;
UsedVars: TStringList;
2022-03-08 12:25:51 -05:00
begin
c00 := c[0][0];
c01 := c[0][1];
c10 := c[1][0];
c11 := c[1][1];
c20 := c[2][0];
c21 := c[2][1];
colorC1 := (1 + symmetry)/2;
colorC2 := color*(1 - symmetry)/2;
FNrFunctions := 0;
for i := 0 to High(FRegVariations) do begin
FRegVariations[i].FPX := @FPX;
FRegVariations[i].FPY := @FPY;
FRegVariations[i].FPz := @FPz;
FRegVariations[i].FTX := @FTX;
FRegVariations[i].FTY := @FTY;
FRegVariations[i].FTz := @FTz;
FRegVariations[i].a := c00;
FRegVariations[i].b := c01;
FRegVariations[i].c := c10;
FRegVariations[i].d := c11;
FRegVariations[i].e := c20;
FRegVariations[i].f := c21;
FRegVariations[i].color := @vc;
FRegVariations[i].vvar := vars[i + NRLOCVAR];
FRegVariations[i].Prepare;
FRegVariations[i].GetCalcFunction(FFunctionList[NRLOCVAR + i]);
end;
SetLength(FCalcFunctionList, NrVar + 2);
CalculateAngle := (vars[6] <> 0.0) or (vars[7] <> 0.0) or (vars[35] <> 0.0);
// CalculateLength := False;
CalculateSinCos := (vars[8] <> 0.0) or (vars[10] <> 0.0);
UsedVars := TStringList.Create;
2022-03-08 12:25:51 -05:00
// Pre- variations
for vn in ifs do
begin
v := GetVariationIndex(vn);
if (vars[v] <> 0.0) then
2022-03-08 12:25:51 -05:00
begin
UsedVars.Add(vn); // AV: remember all used variations in the right order
if (LeftStr(vn, 4) = 'pre_') or (vn = 'flatten') then // AV: flatten became pre_
begin
FCalcFunctionList[FNrFunctions] := FFunctionList[v];
Inc(FNrFunctions);
end
// AV: added some universal variations
else if (vn = 'affine3D') or (vn = 'trianglecrop') or (vn = 'projective')
or (vn = 'spherecrop') then
2022-03-08 12:25:51 -05:00
begin
GetVariable(vn + '_mode', mode);
if (mode = 0) then
2022-03-08 12:25:51 -05:00
begin
FCalcFunctionList[FNrFunctions] := FFunctionList[v];
Inc(FNrFunctions);
end;
end;
end;
end;
2022-03-08 12:25:51 -05:00
// Precalc must be called after pre- vars
if CalculateAngle or CalculateSinCos then
begin
if CalculateAngle and CalculateSinCos then
FCalcFunctionList[FNrFunctions] := PrecalcAll
else if CalculateAngle then
FCalcFunctionList[FNrFunctions] := PrecalcAngle
else //if CalculateSinCos then
FCalcFunctionList[FNrFunctions] := PrecalcSinCos;
Inc(FNrFunctions);
end;
// Normal variations
for vn in UsedVars do // AV: iterate through used variations only
2022-03-08 12:25:51 -05:00
begin
if (LeftStr(vn, 4) = 'pre_') or (LeftStr(vn, 5) = 'post_') or (vn = 'flatten')
then continue
else if (vn = 'affine3D') or (vn = 'trianglecrop') or (vn = 'projective')
or (vn = 'spherecrop') then
2022-03-08 12:25:51 -05:00
begin
GetVariable(vn + '_mode', mode);
if (mode <> 1) then continue;
2022-03-08 12:25:51 -05:00
end;
v := GetVariationIndex(vn);
FCalcFunctionList[FNrFunctions] := FFunctionList[v];
Inc(FNrFunctions);
2022-03-08 12:25:51 -05:00
end;
// Post- variations
for vn in UsedVars do // AV: iterate through used variations only
2022-03-08 12:25:51 -05:00
begin
if (LeftStr(vn, 5) = 'post_') then
begin
v := GetVariationIndex(vn);
FCalcFunctionList[FNrFunctions] := FFunctionList[v];
Inc(FNrFunctions);
end
// AV: added some universal variations
else if (vn = 'affine3D') or (vn = 'trianglecrop') or (vn = 'projective')
or (vn = 'spherecrop') then
begin
GetVariable(vn + '_mode', mode);
if (mode = 2) then
2022-03-08 12:25:51 -05:00
begin
v := GetVariationIndex(vn);
FCalcFunctionList[FNrFunctions] := FFunctionList[v];
Inc(FNrFunctions);
2022-03-08 12:25:51 -05:00
end;
end;
2022-03-08 12:25:51 -05:00
end;
UsedVars.Free;
2022-03-08 12:25:51 -05:00
polar_vpi := vars[6]/pi;
disc_vpi := vars[7]/pi;
polar2_vpi := vars[35]/pi;
p2vv2 := polar2_vpi * 0.5;
gauss_rnd[0] := random;
gauss_rnd[1] := random;
gauss_rnd[2] := random;
gauss_rnd[3] := random;
gauss_N := 0;
rx_sin := sin(vars[22] * pi/2);
rx_cos := cos(vars[22] * pi/2);
ry_sin := sin(vars[23] * pi/2);
ry_cos := cos(vars[23] * pi/2);
px_sin := sin(vars[27] * pi/2);
px_cos := cos(vars[27] * pi/2);
py_sin := sin(vars[28] * pi/2);
py_cos := cos(vars[28] * pi/2);
if (p[0,0]<>1) or (p[0,1]<>0) or(p[1,0]<>0) or (p[1,1]<>1) or (p[2,0]<>0) or (p[2,1]<>0) then
begin
p00 := p[0][0];
p01 := p[0][1];
p10 := p[1][0];
p11 := p[1][1];
p20 := p[2][0];
p21 := p[2][1];
FCalcFunctionList[FNrFunctions] := DoPostTransform;
Inc(FNrFunctions);
end;
end;
procedure TXForm.PrepareInvalidXForm;
begin
c00 := 1;
c01 := 0;
c10 := 0;
c11 := 1;
c20 := 0;
c21 := 0;
colorC1 := 1;
colorC2 := 0;
FNrFunctions := 1;
SetLength(FCalcFunctionList, 1);
FCalcFunctionList[0] := DoInvalidOperation;
end;
procedure TXForm.PrecalcAngle;
{$ifndef _ASM_}
begin
FAngle := arctan2(FTx, FTy);
{$else}
asm
fld qword ptr [eax + FTx]
fld qword ptr [eax + FTy]
fpatan
fstp qword ptr [eax + FAngle]
//fwait
{$endif}
end;
procedure TXForm.PrecalcSinCos;
{$ifndef _ASM_}
begin
FLength := sqrt(sqr(FTx) + sqr(FTy)) + EPS;
FSinA := FTx / FLength;
FCosA := FTy / FLength;
{$else}
asm
fld qword ptr [eax + FTx]
fld qword ptr [eax + FTy]
fld st(1)
fmul st, st
fld st(1)
fmul st, st
faddp
fsqrt
fadd qword ptr [EPS] // avoid divide by zero...(?)
fdiv st(1), st
fdiv st(2), st
fstp qword ptr [eax + FLength]
fstp qword ptr [eax + FCosA]
fstp qword ptr [eax + FSinA]
//fwait
{$endif}
end;
procedure TXForm.PrecalcAll;
{$ifndef _ASM_}
begin
FLength := sqrt(sqr(FTx) + sqr(FTy)) + EPS;
FSinA := FTx / FLength;
FCosA := FTy / FLength;
FAngle := arctan2(FTx, FTy);
{$else}
asm
fld qword ptr [eax + FTx]
fld qword ptr [eax + FTy]
fld st(1)
fld st(1)
fpatan
fstp qword ptr [eax + FAngle]
fld st(1)
fmul st, st
fld st(1)
fmul st, st
faddp
fsqrt
fadd qword ptr [EPS] // avoid divide by zero...(?)
fdiv st(1), st
fdiv st(2), st
fstp qword ptr [eax + FLength]
fstp qword ptr [eax + FCosA]
fstp qword ptr [eax + FSinA]
//fwait
{$endif}
end;
procedure TXForm.DoPostTransform;
{$ifndef _ASM_}
var
tmp: double;
begin
tmp := FPx;
FPx := p00 * FPx + p10 * FPy + p20;
FPy := p01 * tmp + p11 * FPy + p21;
{$else}
asm
fld qword ptr [eax + FPy]
fld qword ptr [eax + FPx]
fld st(1)
fmul qword ptr [eax + p10]
fld st(1)
fmul qword ptr [eax + p00]
faddp
fadd qword ptr [eax + p20]
fstp qword ptr [eax + FPx]
fmul qword ptr [eax + p01]
fld qword ptr [eax + p11]
fmulp st(2), st
faddp
fadd qword ptr [eax + p21]
fstp qword ptr [eax + FPy]
fwait
{$endif}
end;
procedure TXForm.DoInvalidOperation;
begin
raise EMathError.Create('FCalcFunction not initialized!? Probably corrupted flame.');
end;
//--0--////////////////////////////////////////////////////////////////////////
procedure TXForm.Linear3D;
{$ifndef _ASM_}
begin
FPx := FPx + vars[0] * FTx;
FPy := FPy + vars[0] * FTy;
FPz := FPz + vars[0] * FTz;
{$else}
asm
mov edx, [eax + vars]
fld qword ptr [edx]
fld qword ptr [eax + FTz]
fmul st, st(1)
fadd qword ptr [eax + FPz]
fstp qword ptr [eax + FPz]
fld qword ptr [eax + FTx]
fmul st, st(1)
fadd qword ptr [eax + FPx]
fstp qword ptr [eax + FPx]
fld qword ptr [eax + FTy]
fmulp
fadd qword ptr [eax + FPy]
fstp qword ptr [eax + FPy]
fwait
{$endif}
end;
///////////////////////////////////////////////////////////////////////////////
procedure TXForm.Flatten;
begin
// FPz := 0;
// AV: changed to pre_mode for compatibility with "3D-Hack" flames
2022-03-08 12:25:51 -05:00
FTz := 0;
end;
//--1--////////////////////////////////////////////////////////////////////////
procedure TXForm.PreBlur3D; // AV
var
r, sina, cosa, sinb, cosb: double;
begin
Randomize;
SinCos(random * 2 * pi, sina, cosa);
r := vars[2] * (gauss_rnd[0] + gauss_rnd[1] + gauss_rnd[2] + gauss_rnd[3] - 2);
gauss_rnd[gauss_N] := random;
gauss_N := (gauss_N+1) and $3;
SinCos(random * pi, sinb, cosb);
FTx := FTx + r * sinb * cosa;
FTy := FTy + r * sinb * sina;
FTz := FTz + r * cosb;
end;
//--2--////////////////////////////////////////////////////////////////////////
procedure TXForm.Spherical;
{$ifndef _ASM_}
var
r: double;
begin
r := vars[3] / (sqr(FTx) + sqr(FTy) + EPS);
FPx := FPx + FTx * r;
FPy := FPy + FTy * r;
FPz := FPz + FTz * vars[3];
{$else}
asm
fld qword ptr [eax + FTy]
fld qword ptr [eax + FTx]
fld st(1)
fmul st, st
fld st(1)
fmul st, st
faddp
fadd qword ptr [EPS]
mov edx, [eax + vars]
// AV: for Apo7X.15C compatibility
fld qword ptr [edx + 3*8]
fmul qword ptr [eax + FTz]
fadd qword ptr [eax + FPz]
fstp qword ptr [eax + FPz]
// main code
fdivr qword ptr [edx + 3*8]
fmul st(2), st
fmulp
fadd qword ptr [eax + FPx]
fstp qword ptr [eax + FPx]
fadd qword ptr [eax + FPy]
fstp qword ptr [eax + FPy]
fwait
{$endif}
end;
//--3--////////////////////////////////////////////////////////////////////////
procedure TXForm.Swirl;
{$ifndef _ASM_}
var
sinr, cosr: double;
begin
SinCos(sqr(FTx) + sqr(FTy), sinr, cosr);
FPx := FPx + vars[4] * (sinr * FTx - cosr * FTy);
FPy := FPy + vars[4] * (cosr * FTx + sinr * FTy);
FPz := FPz + FTz * vars[4];
{$else}
asm
mov edx, [eax + vars]
fld qword ptr [edx + 4*8]
// AV: 3D stuff
fld st
fmul qword ptr [eax + FTz]
fadd qword ptr [eax + FPz]
fstp qword ptr [eax + FPz]
// main calculations
fld qword ptr [eax + FTy]
fld qword ptr [eax + FTx]
fld st(1)
fmul st, st
fld st(1)
fmul st, st
faddp
fsincos
fld st(1)
fmul st, st(3)
fld st(1)
fmul st, st(5)
fsubp st(1), st
fmul st, st(5)
fadd qword ptr [eax + FPx]
fstp qword ptr [eax + FPx]
fmulp st(2), st
fmulp st(2), st
faddp
fmulp
fadd qword ptr [eax + FPy]
fstp qword ptr [eax + FPy]
fwait
{$endif}
end;
//--4--////////////////////////////////////////////////////////////////////////
procedure TXForm.Horseshoe;
{$ifndef _ASM_}
var
r: double;
begin
r := vars[5] / (sqrt(sqr(FTx) + sqr(FTy)) + EPS);
FPx := FPx + (FTx - FTy) * (FTx + FTy) * r;
FPy := FPy + (2*FTx*FTy) * r;
FPz := FPz + FTz * vars[5];
{$else}
asm
fld qword ptr [eax + FTx]
fld qword ptr [eax + FTy]
fld st(1)
fmul st, st
fld st(1)
fmul st, st
faddp
fsqrt
fadd qword ptr [EPS]
mov edx, [eax + vars]
// AV: for Apo7X.15C compatibility
fld qword ptr [edx + 5*8]
fmul qword ptr [eax + FTz]
fadd qword ptr [eax + FPz]
fstp qword ptr [eax + FPz]
// main code
fdivr qword ptr [edx + 5*8]
fld st(2)
fadd st, st(2)
fld st(3)
fsub st, st(3)
fmulp
fmul st, st(1)
fadd qword ptr [eax + FPx]
fstp qword ptr [eax + FPx]
fmulp
fmulp
fadd st, st
fadd qword ptr [eax + FPy]
fstp qword ptr [eax + FPy]
fwait
{$endif}
end;
//--5--////////////////////////////////////////////////////////////////////////
procedure TXForm.Polar;
{$ifndef _ASM_}
begin
FPx := FPx + polar_vpi * FAngle; //vars[5] * FAngle / PI;
FPy := FPy + vars[6] * (sqrt(sqr(FTx) + sqr(FTy)) - 1.0);
FPz := FPz + FTz * vars[6];
{$else}
asm
fld qword ptr [eax + FAngle]
fmul qword ptr [eax + polar_vpi]
fadd qword ptr [eax + FPx]
fstp qword ptr [eax + FPx]
fld qword ptr [eax + FTx]
fmul st, st
fld qword ptr [eax + FTy]
fmul st, st
faddp
fsqrt
fld1
fsubp st(1), st
mov edx, [eax + vars]
// AV: for Apo7X.15C compatibility
fld qword ptr [edx + 6*8]
fmul qword ptr [eax + FTz]
fadd qword ptr [eax + FPz]
fstp qword ptr [eax + FPz]
// main code
fmul qword ptr [edx + 6*8]
fadd qword ptr [eax + FPy]
fstp qword ptr [eax + FPy]
fwait
{$endif}
end;
//--6--////////////////////////////////////////////////////////////////////////
procedure TXForm.Disc;
{$ifndef _ASM_}
var
r, sinr, cosr: double;
begin
SinCos(PI * sqrt(sqr(FTx) + sqr(FTy)), sinr, cosr);
r := disc_vpi * FAngle; //vars[7] * FAngle / PI;
FPx := FPx + sinr * r;
FPy := FPy + cosr * r;
FPz := FPz + FTz * vars[7];
{$else}
asm
// AV: 3D stuff
mov edx, [eax + vars]
fld qword ptr [edx + 7*8]
fmul qword ptr [eax + FTz]
fadd qword ptr [eax + FPz]
fstp qword ptr [eax + FPz]
// main calculations
fld qword ptr [eax + disc_vpi]
fmul qword ptr [eax + FAngle]
fld qword ptr [eax + FTx]
fmul st, st
fld qword ptr [eax + FTy]
fmul st, st
faddp
fsqrt
fldpi
fmulp
fsincos
fmul st, st(2)
fadd qword ptr [eax + FPy]
fstp qword ptr [eax + FPy]
fmulp
fadd qword ptr [eax + FPx]
fstp qword ptr [eax + FPx]
fwait
{$endif}
end;
//--7--////////////////////////////////////////////////////////////////////////
procedure TXForm.Spiral;
{$ifndef _ASM_}
var
r, sinr, cosr: double;
begin
r := Flength + EPS; // 1E-6;
SinCos(r, sinr, cosr);
r := vars[8] / r;
FPx := FPx + (FCosA + sinr) * r;
FPy := FPy + (FsinA - cosr) * r;
FPz := FPz + FTz * vars[8];
{$else}
asm
mov edx, [eax + vars]
fld qword ptr [edx + 8*8]
// AV: 3D stuff
fld st
fmul qword ptr [eax + FTz]
fadd qword ptr [eax + FPz]
fstp qword ptr [eax + FPz]
// main calculations
fld qword ptr [eax + FLength]
fadd qword ptr [EPS]
fdiv st(1), st
fsincos
fsubr qword ptr [eax + FSinA]
fmul st, st(2)
fadd qword ptr [eax + FPy]
fstp qword ptr [eax + FPy]
fadd qword ptr [eax + FCosA]
fmulp
fadd qword ptr [eax + FPx]
fstp qword ptr [eax + FPx]
fwait
{$endif}
end;
//--10--///////////////////////////////////////////////////////////////////////
procedure TXForm.Hyperbolic;
{$ifndef _ASM_}
begin
FPx := FPx + vars[9] * FTx / (sqr(FTx) + sqr(FTy) + EPS);
FPy := FPy + vars[9] * FTy;
FPz := FPz + FTz * vars[9];
{$else}
asm
mov edx, [eax + vars]
fld qword ptr [edx + 9*8]
// AV: 3D stuff
fld st
fmul qword ptr [eax + FTz]
fadd qword ptr [eax + FPz]
fstp qword ptr [eax + FPz]
// main calculations
fld qword ptr [eax + FTy]
fld qword ptr [eax + FTx]
fld st(1)
fmul st, st
fld st(1)
fmul st, st
faddp
fadd qword ptr [EPS]
fdivp st(1), st
fmul st, st(2)
fadd qword ptr [eax + FPx]
fstp qword ptr [eax + FPx]
fmulp
fadd qword ptr [eax + FPy]
fstp qword ptr [eax + FPy]
fwait
{$endif}
end;
//--11--///////////////////////////////////////////////////////////////////////
procedure TXForm.Diamond; // AV: Diamond, i.e. rotated Square
{$ifndef _ASM_}
var
sinr, cosr: double;
begin
SinCos(FLength, sinr, cosr);
FPx := FPx + vars[10] * FSinA * cosr;
FPy := FPy + vars[10] * FCosA * sinr;
FPz := FPz + FTz * vars[10];
{$else}
asm
mov edx, [eax + vars]
fld qword ptr [edx + 10*8]
// AV: 3D stuff
fld st
fmul qword ptr [eax + FTz]
fadd qword ptr [eax + FPz]
fstp qword ptr [eax + FPz]
// main calculations
fld qword ptr [eax + FLength]
fsincos
fmul qword ptr [eax + FSinA]
fmul st, st(2)
fadd qword ptr [eax + FPx]
fstp qword ptr [eax + FPx]
fmul qword ptr [eax + FCosA]
fmulp
fadd qword ptr [eax + FPy]
fstp qword ptr [eax + FPy]
fwait
{$endif}
end;
//--12--///////////////////////////////////////////////////////////////////////
procedure TXForm.Eyefish;
{$ifndef _ASM_}
var
r: double;
begin
r := 2 * vars[11] / (sqrt(sqr(FTx) + sqr(FTy)) + 1);
FPx := FPx + r * FTx;
FPy := FPy + r * FTy;
FPz := FPz + FTz * vars[11];
{$else}
asm
mov edx, [eax + vars]
fld qword ptr [edx + 11*8]
// AV: 3D stuff
fld st
fmul qword ptr [eax + FTz]
fadd qword ptr [eax + FPz]
fstp qword ptr [eax + FPz]
// main calculations
fadd st, st
fld qword ptr [eax + FTy]
fld qword ptr [eax + FTx]
fld st(1)
fmul st, st
fld st(1)
fmul st, st
faddp
fsqrt
fld1
faddp
fdivp st(3), st
fmul st, st(2)
fadd qword ptr [eax + FPx]
fstp qword ptr [eax + FPx]
fmulp
fadd qword ptr [eax + FPy]
fstp qword ptr [eax + FPy]
fwait
{$endif}
end;
///////////////////////////////////////////////////////////////////////////////
procedure TXForm.Bubble;
{$ifndef _ASM_}
var
r: double;
begin
r := (sqr(FTx) + sqr(FTy))/4 + 1;
FPz := FPz + vars[12] * (2 / r - 1);
r := vars[12] / r;
FPx := FPx + r * FTx;
FPy := FPy + r * FTy;
{$else}
asm
fld qword ptr [eax + FTy]
fld qword ptr [eax + FTx]
fld st(1)
fmul st, st
fld st(1)
fmul st, st
faddp
fld1
fadd st, st
fadd st, st
fdivp st(1), st
mov edx, [eax + vars]
fld qword ptr [edx + 12*8]
fld1
fadd st(2), st
fdivr st(2), st
fld st(2)
fadd st, st
fsubrp st(1), st
fmul st, st(1)
fadd qword ptr [eax + FPz]
fstp qword ptr [eax + FPz]
fmulp
fmul st(2), st
fmulp
fadd qword ptr [eax + FPx]
fstp qword ptr [eax + FPx]
fadd qword ptr [eax + FPy]
fstp qword ptr [eax + FPy]
fwait
{$endif}
end;
///////////////////////////////////////////////////////////////////////////////
procedure TXForm.Cylinder;
{$ifndef _ASM_}
begin
FPx := FPx + vars[13] * sin(FTx);
FPy := FPy + vars[13] * FTy;
FPz := FPz + vars[13] * cos(FTx);
{$else}
asm
mov edx, [eax + vars]
fld qword ptr [edx + 13*8]
fld qword ptr [eax + FTx]
fsincos
fmul st, st(2)
fadd qword ptr [eax + FPz]
fstp qword ptr [eax + FPz]
fld qword ptr [eax + FTy]
fmul st, st(2)
fadd qword ptr [eax + FPy]
fstp qword ptr [eax + FPy]
fmulp
fadd qword ptr [eax + FPx]
fstp qword ptr [eax + FPx]
fwait
{$endif}
end;
///////////////////////////////////////////////////////////////////////////////
procedure TXForm.Noise;
{$ifndef _ASM_}
var
r, s, sinr, cosr: double;
begin
// Randomize here = HACK! Fix me...
Randomize; SinCos(random * 2*pi, sinr, cosr);
s := vars[14];
r := s * random;
FPx := FPx + FTx * r * cosr;
FPy := FPy + FTy * r * sinr;
FPz := FPz + FTz * s;
{$else}
asm
mov edx, [eax + vars]
fld qword ptr [edx + 14*8]
// AV: 3D stuff
fld st
fmul qword ptr [eax + FTz]
fadd qword ptr [eax + FPz]
fstp qword ptr [eax + FPz]
// main calculations
call AsmRandExt
fmulp
call AsmRandExt
fadd st, st
fldpi
fmulp
fsincos
fmul st, st(2)
fmul qword ptr [eax + FTx]
fadd qword ptr [eax + FPx]
fstp qword ptr [eax + FPx]
fmulp
fmul qword ptr [eax + FTy]
fadd qword ptr [eax + FPy]
fstp qword ptr [eax + FPy]
fwait
{$endif}
end;
///////////////////////////////////////////////////////////////////////////////
procedure TXForm.Blur;
{$ifndef _ASM_}
var
r, sina, cosa: double;
begin
// Randomize here = HACK! Fix me...
Randomize; SinCos(random * 2*pi, sina, cosa);
r := vars[15] * random;
FPx := FPx + r * cosa;
FPy := FPy + r * sina;
FPz := FPz + vars[15] * FTz;
{$else}
asm
mov edx, [eax + vars]
fld qword ptr [edx + 15*8]
// AV: 3D stuff
fld st
fmul qword ptr [eax + FTz]
fadd qword ptr [eax + FPz]
fstp qword ptr [eax + FPz]
// main calculations
call AsmRandExt
fmulp
call AsmRandExt
fadd st, st
fldpi
fmulp
fsincos
fmul st, st(2)
fadd qword ptr [eax + FPx]
fstp qword ptr [eax + FPx]
fmulp
fadd qword ptr [eax + FPy]
fstp qword ptr [eax + FPy]
fwait
{$endif}
end;
///////////////////////////////////////////////////////////////////////////////
procedure TXForm.Gaussian;
{$ifndef _ASM_}
var
r, sina, cosa: double;
begin
// Randomize here = HACK! Fix me...
Randomize; SinCos(random * 2*pi, sina, cosa);
r := vars[16] * (gauss_rnd[0] + gauss_rnd[1] + gauss_rnd[2] + gauss_rnd[3] - 2);
gauss_rnd[gauss_N] := random;
gauss_N := (gauss_N+1) and $3;
FPx := FPx + r * cosa;
FPy := FPy + r * sina;
//FPz := FPz + vars[16] * FTz; // AV removed
{$else}
asm
fld qword ptr [eax + gauss_rnd]
fadd qword ptr [eax + gauss_rnd+8]
fadd qword ptr [eax + gauss_rnd+16]
fadd qword ptr [eax + gauss_rnd+24]
fld1
fadd st,st
fsubp st(1),st
mov edx, [eax + vars]
// AV: removed 3D-support since we have zcale and blur3D
{
fld qword ptr [edx + 16*8]
fmul qword ptr [eax + FTz]
fadd qword ptr [eax + FPz]
fstp qword ptr [eax + FPz]
}
fmul qword ptr [edx + 16*8]
call AsmRandExt
mov edx, [eax + gauss_N]
fst qword ptr [eax + gauss_rnd + edx*8]
inc edx
and edx,$03
mov [eax + gauss_N], edx
fadd st, st
fldpi
fmulp
fsincos
fmul st, st(2)
fadd qword ptr [eax + FPx]
fstp qword ptr [eax + FPx]
fmulp
fadd qword ptr [eax + FPy]
fstp qword ptr [eax + FPy]
fwait
{$endif}
end;
///////////////////////////////////////////////////////////////////////////////
procedure TXForm.ZBlur;
{$ifndef _ASM_}
begin
FPz := FPz + vars[17] * (gauss_rnd[0] + gauss_rnd[1] + gauss_rnd[2] + gauss_rnd[3] - 2);
gauss_rnd[gauss_N] := random;
gauss_N := (gauss_N+1) and $3;
{$else}
asm
fld qword ptr [eax + gauss_rnd]
fadd qword ptr [eax + gauss_rnd+8]
fadd qword ptr [eax + gauss_rnd+16]
fadd qword ptr [eax + gauss_rnd+24]
fld1
fadd st,st
fsubp st(1),st
mov edx, [eax + vars]
fmul qword ptr [edx + 17*8]
call AsmRandExt
mov edx, [eax + gauss_N]
fstp qword ptr [eax + gauss_rnd + edx*8]
inc edx
and edx,$03
mov [eax + gauss_N], edx
fadd qword ptr [eax + FPz]
fstp qword ptr [eax + FPz]
fwait
{$endif}
end;
///////////////////////////////////////////////////////////////////////////////
procedure TXForm.Blur3D;
var
r, sina, cosa, sinb, cosb: double;
begin
// Randomize here = HACK! Fix me...
Randomize; SinCos(random * 2*pi, sina, cosa);
r := vars[18] * (gauss_rnd[0] + gauss_rnd[1] + gauss_rnd[2] + gauss_rnd[3] - 2);
gauss_rnd[gauss_N] := random;
gauss_N := (gauss_N+1) and $3;
SinCos(random * pi, sinb, cosb);
FPx := FPx + r * sinb * cosa;
FPy := FPy + r * sinb * sina;
FPz := FPz + r * cosb;
end;
///////////////////////////////////////////////////////////////////////////////
procedure TXForm.PreBlur;
{$ifndef _ASM_}
var
r, sina, cosa: double;
begin
// Randomize here = HACK! Fix me...
Randomize; SinCos(random * 2*pi, sina, cosa);
r := vars[19] * (gauss_rnd[0] + gauss_rnd[1] + gauss_rnd[2] + gauss_rnd[3] - 2);
gauss_rnd[gauss_N] := random;
gauss_N := (gauss_N+1) and $3;
FTx := FTx + r * cosa;
FTy := FTy + r * sina;
{$else}
asm
fld qword ptr [eax + gauss_rnd]
fadd qword ptr [eax + gauss_rnd+8]
fadd qword ptr [eax + gauss_rnd+16]
fadd qword ptr [eax + gauss_rnd+24]
fld1
fadd st,st
fsubp st(1),st
mov edx, [eax + vars]
fmul qword ptr [edx + 19*8]
call AsmRandExt
mov edx, [eax + gauss_N]
fst qword ptr [eax + gauss_rnd + edx*8]
inc edx
and edx,$03
mov [eax + gauss_N], edx
fadd st, st
fldpi
fmulp
fsincos
fmul st, st(2)
fadd qword ptr [eax + FTx]
fstp qword ptr [eax + FTx]
fmulp
fadd qword ptr [eax + FTy]
fstp qword ptr [eax + FTy]
fwait
{$endif}
end;
///////////////////////////////////////////////////////////////////////////////
procedure TXForm.PreZScale;
begin
FTz := FTz * vars[20];
end;
///////////////////////////////////////////////////////////////////////////////
procedure TXForm.PreZTranslate;
begin
FTz := FTz + vars[21];
end;
///////////////////////////////////////////////////////////////////////////////
procedure TXForm.PreRotateX;
var
z: double;
begin
z := rx_cos * FTz - rx_sin * FTy;
FTy := rx_sin * FTz + rx_cos * FTy;
FTz := z;
end;
///////////////////////////////////////////////////////////////////////////////
procedure TXForm.PreRotateY;
var
x: double;
begin
x := ry_cos * FTx - ry_sin * FTz;
FTz := ry_sin * FTx + ry_cos * FTz;
FTx := x;
end;
///////////////////////////////////////////////////////////////////////////////
procedure TXForm.ZScale;
{$ifndef _ASM_}
begin
FPz := FPz + vars[24] * FTz;
{$else}
asm
fld qword ptr [eax + FTz]
mov edx, [eax + vars]
fmul qword ptr [edx + 24*8]
fadd qword ptr [eax + FPz]
fstp qword ptr [eax + FPz]
fwait
{$endif}
end;
///////////////////////////////////////////////////////////////////////////////
procedure TXForm.ZTranslate;
begin
FPz := FPz + vars[25];
end;
///////////////////////////////////////////////////////////////////////////////
procedure TXForm.ZCone;
{$ifndef _ASM_}
begin
FPz := FPz + vars[26] * sqrt(sqr(FTx) + sqr(FTy));
{$else}
asm
fld qword ptr [eax + FTx]
fmul st,st
fld qword ptr [eax + FTy]
fmul st,st
faddp
fsqrt
mov edx, [eax + vars]
fmul qword ptr [edx + 26*8]
fadd qword ptr [eax + FPz]
fstp qword ptr [eax + FPz]
fwait
{$endif}
end;
///////////////////////////////////////////////////////////////////////////////
procedure TXForm.PostRotateX;
var
z: double;
begin
z := px_cos * FPz - px_sin * FPy;
FPy := px_sin * FPz + px_cos * FPy;
FPz := z;
end;
///////////////////////////////////////////////////////////////////////////////
procedure TXForm.PostRotateY;
var
x: double;
begin
x := py_cos * FPx - py_sin * FPz;
FPz := py_sin * FPx + py_cos * FPz;
FPx := x;
end;
///////////////////////////////////////////////////////////////////////////////
procedure TXForm.PostMirrorX;
begin
FPx := abs(FPx);
if (random(2) = 1) then FPx := -FPx;
end;
///////////////////////////////////////////////////////////////////////////////
procedure TXForm.PostMirrorY;
begin
FPy := abs(FPy);
if (random(2) = 1) then FPy := -FPy;
end;
///////////////////////////////////////////////////////////////////////////////
procedure TXForm.PostMirrorZ;
begin
FPz := abs(FPz);
if (random(2) = 1) then FPz := -FPz;
end;
/////////////////////////////////
procedure TXForm.Hemisphere;
{$ifndef _ASM_}
var
t: double;
begin
t := vars[32] / sqrt(sqr(FTx) + sqr(FTy) + 1);
FPx := FPx + FTx * t;
FPy := FPy + FTy * t;
FPz := FPz + t;
{$else}
asm // rewritten by AV
fld qword ptr [eax + FTy]
fld qword ptr [eax + FTx]
fld st(1)
fmul st, st
fld st(1)
fmul st, st
faddp
fld1
faddp
fsqrt
mov edx, [eax + vars]
fdivr qword ptr [edx + 32*8]
fmul st(2), st
fmul st(1), st
fadd qword ptr [eax + FPz]
fstp qword ptr [eax + FPz]
fadd qword ptr [eax + FPx]
fstp qword ptr [eax + FPx]
fadd qword ptr [eax + FPy]
fstp qword ptr [eax + FPy]
fwait
{$endif}
end;
//////////////////////////////
procedure TXForm.Cross;
const epsv: double = 1.0e-20;
{$ifndef _ASM_}
var
r: double;
begin
r := abs((FTx - FTy) * (FTx + FTy)) + epsv; // AV: fixed
// AV: abs cannot be negative, so it's useless
//if (r < 0) then r := r * -1.0;
r := vars[33] / r;
FPx := FPx + FTx * r;
FPy := FPy + FTy * r;
FPz := FPz + vars[33] * FTz;
{$else}
asm //written by AV
fld qword ptr [eax + FTy]
fld qword ptr [eax + FTx]
fld st
fsub st, st(2)
fld st(1)
fadd st, st(3)
fmulp
fabs
fadd epsv
mov edx, [eax + vars]
// for Apo7X.15C compatibility
fld qword ptr [edx + 33*8]
fmul qword ptr [eax + FTz]
fadd qword ptr [eax + FPz]
fstp qword ptr [eax + FPz]
// main code
fdivr qword ptr [edx + 33*8]
fmul st(2), st
fmulp
fadd qword ptr [eax + FPx]
fstp qword ptr [eax + FPx]
fadd qword ptr [eax + FPy]
fstp qword ptr [eax + FPy]
fwait
{$endif}
end;
/////////////////////////////
procedure TXForm.Pyramid;
var
x, y, z, r: double;
begin
x := IntPower(FTx, 3);
y := IntPower(FTy, 3);
z := IntPower(abs(FTz), 3);
r := vars[34] / (abs(x) + abs(y) + z + 1E-9);
FPx := FPx + x * r;
FPy := FPy + y * r;
FPz := FPz + z * r;
end;
////////////////////////////////////////////////
procedure TXForm.Polar2;
{$ifndef _ASM_}
begin
FPx := FPx + polar2_vpi * FAngle;
FPy := FPy + p2vv2 * Ln(sqr(FTx) + sqr(FTy) + EPS);
FPz := FPz + FTz * vars[35];
{$else}
asm // written by AV
fld qword ptr [eax + FAngle]
fmul qword ptr [eax + polar2_vpi]
fadd qword ptr [eax + FPx]
fstp qword ptr [eax + FPx]
fld qword ptr [eax + FTx]
fmul st, st
fld qword ptr [eax + FTy]
fmul st, st
faddp
fadd qword ptr [EPS]
fldln2
fxch
fyl2x
fmul qword ptr [eax + p2vv2]
mov edx, [eax + vars]
// AV: for Apo7X.15C compatibility
fld qword ptr [edx + 35*8]
fmul qword ptr [eax + FTz]
fadd qword ptr [eax + FPz]
fstp qword ptr [eax + FPz]
// main code
fmul qword ptr [edx + 35*8]
fadd qword ptr [eax + FPy]
fstp qword ptr [eax + FPy]
fwait
{$endif}
end;
///////////////////////////////////////////////////////////////////////////////
procedure TXForm.NextPoint(var CPpoint: TCPpoint);
var
i: Integer;
begin
// first compute the color coord
CPpoint.c := CPpoint.c * colorC1 + colorC2;
vc := CPpoint.c;
FTx := c00 * CPpoint.x + c10 * CPpoint.y + c20;
FTy := c01 * CPpoint.x + c11 * CPpoint.y + c21;
FTz := CPpoint.z;
Fpx := 0;
Fpy := 0;
Fpz := 0;
for i:= 0 to FNrFunctions-1 do
FCalcFunctionList[i];
CPpoint.c := CPpoint.c + pluginColor * (vc - CPpoint.c);
CPpoint.x := FPx;
CPpoint.y := FPy;
CPPoint.z := FPz;
end;
procedure TXForm.NextPointTo(var CPpoint, ToPoint: TCPpoint);
var
i: Integer;
begin
ToPoint.c := CPpoint.c * colorC1 + colorC2;
vc := ToPoint.c;
FTx := c00 * CPpoint.x + c10 * CPpoint.y + c20;
FTy := c01 * CPpoint.x + c11 * CPpoint.y + c21;
FTz := CPpoint.z;
Fpx := 0;
Fpy := 0;
Fpz := 0;
for i:= 0 to FNrFunctions-1 do
FCalcFunctionList[i];
ToPoint.c := ToPoint.c + pluginColor * (vc - ToPoint.c);
ToPoint.x := FPx;
ToPoint.y := FPy;
ToPoint.z := FPz;
2022-03-08 12:25:51 -05:00
end;
///////////////////////////////////////////////////////////////////////////////
(*
2022-03-08 12:25:51 -05:00
procedure TXForm.NextPoint2C(var p: T2CPoint);
var
i: Integer;
begin
// first compute the color coord
p.c1 := p.c1 * colorC1 + colorC2;
p.c2 := p.c2 * colorC1 + colorC2;
FTx := c00 * p.x + c10 * p.y + c20;
FTy := c01 * p.x + c11 * p.y + c21;
Fpx := 0;
Fpy := 0;
for i:= 0 to FNrFunctions-1 do
FCalcFunctionList[i];
p.x := FPx;
p.y := FPy;
end;
*)
2022-03-08 12:25:51 -05:00
///////////////////////////////////////////////////////////////////////////////
procedure TXForm.NextPointXY(var px, py: double);
var
i: integer;
begin
FTx := c00 * px + c10 * py + c20;
FTy := c01 * px + c11 * py + c21;
FTz := 0;
Fpx := 0;
Fpy := 0;
for i:= 0 to FNrFunctions-1 do
FCalcFunctionList[i];
px := FPx;
py := FPy;
end;
//************ Math utils ***************************************//
function TXForm.detC;
begin
Result := c[0,0] * c[1,1] - c[0,1] * c[1,0];
end;
function TXForm.detP;
begin
Result := p[0,0] * p[1,1] - p[0,1] * p[1,0];
end;
//************ Matrix multiplication ***************************************//
procedure TXForm.Multiply(var t: TCoefsArray; const k, l, m, n: double); // AV
var
ta, tb, tc, td: double;
begin
ta := t[0, 0];
tb := -t[1, 0];
tc := -t[0, 1];
td := t[1, 1];
{
[a, b][e ,f] [a*e+b*g, a*f+b*h]
[ ][ ] = [ ]
[c, d][g, h] [c*e+d*g, c*f+d*h]
}
t[0, 0] := ta * k + tc * l;
t[0, 1] := -(ta * m + tc * n);
t[1, 0] := -(tb * k + td * l);
t[1, 1] := tb * m + td * n;
end;
procedure TXForm.Rotate(var t: TCoefsArray; const degrees: double); // AV
var
v, sv, cv: double;
begin
v := DegToRad(degrees);
SinCos(v, sv, cv);
Multiply(t, cv, -sv, sv, cv);
end;
procedure TXForm.Scale(var t: TCoefsArray; const s: double);
begin
t[0, 0] := t[0, 0] * s;
t[0, 1] := t[0, 1] * s;
t[1, 0] := t[1, 0] * s;
t[1, 1] := t[1, 1] * s;
end;
procedure TXForm.Translate(var t: TCoefsArray; const x, y: double);
begin
t[2,0] := t[2,0] + x;
t[2,1] := t[2,1] - y; // AV: notice the sign here
end;
procedure TXForm.RandomizeCoefs(var t: TCoefsArray); // AV
begin
t[0][0] := 2 * random - 1;
t[0][1] := 2 * random - 1;
t[1][0] := 2 * random - 1;
t[1][1] := 2 * random - 1;
t[2][0] := 4 * random - 2;
t[2][1] := 4 * random - 2;
end;
(*
2022-03-08 12:25:51 -05:00
///////////////////////////////////////////////////////////////////////////////
{
[00 01 02]
[10 11 12]
[20 21 22]
[a b e ]
[c d f ]
[0 0 1 ]
}
function TXForm.Mul33(const M1, M2: TMatrix): TMatrix;
begin
result[0, 0] := M1[0][0] * M2[0][0] + M1[0][1] * M2[1][0] + M1[0][2] * M2[2][0];
result[0, 1] := M1[0][0] * M2[0][1] + M1[0][1] * M2[1][1] + M1[0][2] * M2[2][1];
result[0, 2] := M1[0][0] * M2[0][2] + M1[0][1] * M2[1][2] + M1[0][2] * M2[2][2];
result[1, 0] := M1[1][0] * M2[0][0] + M1[1][1] * M2[1][0] + M1[1][2] * M2[2][0];
result[1, 1] := M1[1][0] * M2[0][1] + M1[1][1] * M2[1][1] + M1[1][2] * M2[2][1];
result[1, 2] := M1[1][0] * M2[0][2] + M1[1][1] * M2[1][2] + M1[1][2] * M2[2][2];
result[2, 0] := M1[2][0] * M2[0][0] + M1[2][1] * M2[1][0] + M1[2][2] * M2[2][0];
result[2, 1] := M1[2][0] * M2[0][1] + M1[2][1] * M2[1][1] + M1[2][2] * M2[2][1]; // AV: fixed indices
result[2, 2] := M1[2][0] * M2[0][2] + M1[2][1] * M2[1][2] + M1[2][2] * M2[2][2]; // AV: fixed indices
end;
function TXForm.Identity: TMatrix;
var
i, j: integer;
begin
for i := 0 to 2 do
for j := 0 to 2 do
Result[i, j] := 0;
Result[0][0] := 1;
Result[1][1] := 1;
Result[2][2] := 1;
end;
///////////////////////////////////////////////////////////////////////////////
2022-03-08 12:25:51 -05:00
procedure TXForm.Rotate(const degrees: double);
var
r: double;
Matrix, M1: TMatrix;
begin
r := degrees * pi / 180;
M1 := Identity;
M1[0, 0] := cos(r);
M1[0, 1] := -sin(r);
M1[1, 0] := sin(r);
M1[1, 1] := cos(r);
Matrix := Identity;
Matrix[0][0] := c[0, 0];
Matrix[0][1] := c[0, 1];
Matrix[1][0] := c[1, 0];
Matrix[1][1] := c[1, 1];
Matrix[0][2] := c[2, 0];
Matrix[1][2] := c[2, 1];
Matrix := Mul33(Matrix, M1);
c[0, 0] := Matrix[0][0];
c[0, 1] := Matrix[0][1];
c[1, 0] := Matrix[1][0];
c[1, 1] := Matrix[1][1];
c[2, 0] := Matrix[0][2];
c[2, 1] := Matrix[1][2];
end;
procedure TXForm.Translate(const x, y: double);
var
Matrix, M1: TMatrix;
begin
M1 := Identity;
M1[0, 2] := x;
M1[1, 2] := y;
Matrix := Identity;
Matrix[0][0] := c[0, 0];
Matrix[0][1] := c[0, 1];
Matrix[1][0] := c[1, 0];
Matrix[1][1] := c[1, 1];
Matrix[0][2] := c[2, 0];
Matrix[1][2] := c[2, 1];
Matrix := Mul33(Matrix, M1);
c[0, 0] := Matrix[0][0];
c[0, 1] := Matrix[0][1];
c[1, 0] := Matrix[1][0];
c[1, 1] := Matrix[1][1];
c[2, 0] := Matrix[0][2];
c[2, 1] := Matrix[1][2];
end;
procedure TXForm.Multiply(const a, b, c, d: double);
var
Matrix, M1: TMatrix;
begin
M1 := Identity;
M1[0, 0] := a;
M1[0, 1] := b;
M1[1, 0] := c;
M1[1, 1] := d;
Matrix := Identity;
Matrix[0][0] := Self.c[0, 0];
Matrix[0][1] := Self.c[0, 1];
Matrix[1][0] := Self.c[1, 0];
Matrix[1][1] := Self.c[1, 1];
Matrix[0][2] := Self.c[2, 0];
Matrix[1][2] := Self.c[2, 1];
Matrix := Mul33(Matrix, M1);
Self.c[0, 0] := Matrix[0][0];
Self.c[0, 1] := Matrix[0][1];
Self.c[1, 0] := Matrix[1][0];
Self.c[1, 1] := Matrix[1][1];
Self.c[2, 0] := Matrix[0][2];
Self.c[2, 1] := Matrix[1][2];
end;
procedure TXForm.Scale(const s: double);
var
Matrix, M1: TMatrix;
begin
M1 := Identity;
M1[0, 0] := s;
M1[1, 1] := s;
Matrix := Identity;
Matrix[0][0] := c[0, 0];
Matrix[0][1] := c[0, 1];
Matrix[1][0] := c[1, 0];
Matrix[1][1] := c[1, 1];
Matrix[0][2] := c[2, 0];
Matrix[1][2] := c[2, 1];
Matrix := Mul33(Matrix, M1);
c[0, 0] := Matrix[0][0];
c[0, 1] := Matrix[0][1];
c[1, 0] := Matrix[1][0];
c[1, 1] := Matrix[1][1];
c[2, 0] := Matrix[0][2];
c[2, 1] := Matrix[1][2];
end;
*)
2022-03-08 12:25:51 -05:00
///////////////////////////////////////////////////////////////////////////////
destructor TXForm.Destroy;
var
i: integer;
begin
for i := 0 to High(FRegVariations) do
FRegVariations[i].Free;
if assigned(ifs) then ifs.Clear;
ifs.Free; // AV
inherited;
end;
///////////////////////////////////////////////////////////////////////////////
procedure TXForm.BuildFunctionlist;
begin
// AV: why NRVAR is used here? maybe NRLOCVAR instead?
//SetLength(FFunctionList, NrVar + Length(FRegVariations));
SetLength(FFunctionList, NrVar); // <-- AV: reduced the length to actually used
2022-03-08 12:25:51 -05:00
//fixed
FFunctionList[0] := Linear3D;
FFunctionList[1] := Flatten; // AV: replased 2D-Linear
FFunctionList[2] := PreBlur3D; // AV: replaced Sinusoidal
FFunctionList[3] := Spherical;
FFunctionList[4] := Swirl;
FFunctionList[5] := Horseshoe;
FFunctionList[6] := Polar;
FFunctionList[7] := Disc;
FFunctionList[8] := Spiral;
FFunctionList[9] := Hyperbolic;
FFunctionList[10] := Diamond; // AV: renamed from Square
FFunctionList[11] := Eyefish;
FFunctionList[12] := Bubble;
FFunctionList[13] := Cylinder;
FFunctionList[14] := Noise;
FFunctionList[15] := Blur;
FFunctionList[16] := Gaussian;
FFunctionList[17] := ZBlur;
FFunctionList[18] := Blur3D;
FFunctionList[19] := PreBlur;
FFunctionList[20] := PreZScale; // AV: index is used by auto-pre_zscale option
2022-03-08 12:25:51 -05:00
FFunctionList[21] := PreZTranslate;
FFunctionList[22] := PreRotateX;
FFunctionList[23] := PreRotateY;
FFunctionList[24] := ZScale;
FFunctionList[25] := ZTranslate;
FFunctionList[26] := ZCone;
FFunctionList[27] := PostRotateX;
FFunctionList[28] := PostRotateY;
// AV: new local variations
FFunctionList[29] := PostMirrorX;
FFunctionList[30] := PostMirrorY;
FFunctionList[31] := PostMirrorZ;
FFunctionList[32] := Hemisphere;
FFunctionList[33] := Cross;
FFunctionList[34] := Pyramid;
FFunctionList[35] := Polar2;
end;
///////////////////////////////////////////////////////////////////////////////
procedure TXForm.AddRegVariations;
var
i: integer;
begin
SetLength(FRegVariations, GetNrRegisteredVariations);
for i := 0 to GetNrRegisteredVariations - 1 do begin
FRegVariations[i] := GetRegisteredVariation(i).GetInstance;
end;
end;
///////////////////////////////////////////////////////////////////////////////
procedure TXForm.Assign(XForm: TXForm);
var
i,j: integer;
Name: string;
Value: double;
begin
if Not assigned(XForm) then
Exit;
for i := 0 to High(vars) do
vars[i] := XForm.vars[i];
c := Xform.c;
p := Xform.p;
density := XForm.density;
color := XForm.color;
color2 := XForm.color2;
symmetry := XForm.symmetry;
// Orientationtype := XForm.Orientationtype;
TransformName := XForm.TransformName;
postXswap := Xform.postXswap;
autoZscale := Xform.autoZscale;
for i := 0 to High(FRegVariations) do begin
for j := 0 to FRegVariations[i].GetNrVariables - 1 do begin
Name := FRegVariations[i].GetVariableNameAt(j);
XForm.FRegVariations[i].GetVariable(Name, Value);
FRegVariations[i].SetVariable(Name, Value);
end;
end;
for i := 0 to High(modWeights) do
modWeights[i] := xform.modWeights[i];
ifs.Assign(xform.ifs); // AV
transOpacity := xform.transOpacity;
pluginColor := xform.pluginColor;
end;
///////////////////////////////////////////////////////////////////////////////
function TXForm.ToXMLString: string;
var
i, j: integer;
Name: string;
Value: double;
numChaos: integer;
strvar: string;
begin
result := Format(' <xform weight="%g" color="%g" ', [density, color]);
if symmetry <> 0 then result := result + format('symmetry="%g" ', [symmetry]);
// AV: write variation order
2022-03-08 12:25:51 -05:00
strvar := '';
for Name in ifs do begin
if vars[GetVariationIndex(Name)] <> 0 then
strvar := strvar + Name + #32;
2022-03-08 12:25:51 -05:00
end;
if (strvar <> '') and (pos(#32, strvar) < length(strvar)) then
Result := Result + format('var_order="%s" ', [strvar]);
///////////////////////
(*
for i := 0 to nrvar - 1 do begin
if vars[i] <> 0 then
Result := Result + varnames(i) + format('="%g" ', [vars[i]]);
end;
*)
for Name in ifs do // AV: write in correct order
2022-03-08 12:25:51 -05:00
begin
Value := vars[GetVariationIndex(Name)];
if Value <> 0 then
Result := Result + Name + format('="%g" ', [Value]);
end;
Result := Result + Format('coefs="%g %g %g %g %g %g" ', [c[0,0], c[0,1], c[1,0], c[1,1], c[2,0], c[2,1]]);
if (p[0,0]<>1) or (p[0,1]<>0) or(p[1,0]<>0) or (p[1,1]<>1) or (p[2,0]<>0) or (p[2,1]<>0) then
Result := Result + Format('post="%g %g %g %g %g %g" ', [p[0,0], p[0,1], p[1,0], p[1,1], p[2,0], p[2,1]]);
for i := 0 to High(FRegVariations) do begin
if vars[i+NRLOCVAR] <> 0 then
for j := 0 to FRegVariations[i].GetNrVariables - 1 do begin
Name := FRegVariations[i].GetVariableNameAt(j);
Result := Result + Format('%s="%s" ', [name, FRegVariations[i].GetVariableStr(Name)]);
end;
end;
numChaos := -1;
for i := NXFORMS-1 downto 0 do
if modWeights[i] <> 1 then begin
numChaos := i;
break;
end;
if numChaos >= 0 then begin
Result := Result + 'chaos="';
for i := 0 to numChaos do
Result := Result + Format('%g ', [modWeights[i]]);
Result := Result + '" ';
end;
Result := Result + Format('opacity="%g" ', [transOpacity]);
if TransformName <> '' then
Result := Result + 'name="' + TransformName + '"';
if pluginColor <> 1 then
Result := Result + Format('var_color="%g" ', [pluginColor]);
Result := Result + '/>';
end;
function TXForm.FinalToXMLString(IsEnabled: boolean): string;
var
i, j: integer;
Name: string;
Value: double;
strvar: string;
begin
// result := Format(' <finalxform enabled="%d" color="%g" symmetry="%g" ',
// [ifthen(IsEnabled, 1, 0), color, symmetry]);
result := Format(' <finalxform color="%g" ', [color]);
if symmetry <> 0 then result := result + format('symmetry="%g" ', [symmetry]);
// AV: write variation order
2022-03-08 12:25:51 -05:00
strvar := '';
for Name in ifs do begin
if vars[GetVariationIndex(Name)] <> 0 then
strvar := strvar + Name + #32;
2022-03-08 12:25:51 -05:00
end;
if (strvar <> '') and (pos(#32, strvar) < length(strvar)) then
Result := Result + format('var_order="%s" ', [strvar]);
//////////////////////////////////////////
(*
for i := 0 to nrvar - 1 do begin
if vars[i] <> 0 then
Result := Result + varnames(i) + format('="%g" ', [vars[i]]);
end;
*)
for Name in ifs do // AV: write in correct order
2022-03-08 12:25:51 -05:00
begin
Value := vars[GetVariationIndex(Name)];
if Value <> 0 then
Result := Result + Name + format('="%g" ', [Value]);
end;
Result := Result + Format('coefs="%g %g %g %g %g %g" ', [c[0,0], c[0,1], c[1,0], c[1,1], c[2,0], c[2,1]]);
if (p[0,0]<>1) or (p[0,1]<>0) or(p[1,0]<>0) or (p[1,1]<>1) or (p[2,0]<>0) or (p[2,1]<>0) then
Result := Result + Format('post="%g %g %g %g %g %g" ', [p[0,0], p[0,1], p[1,0], p[1,1], p[2,0], p[2,1]]);
if pluginColor <> 1 then
Result := Result + Format('var_color="%g" ', [pluginColor]);
for i := 0 to High(FRegVariations) do begin
if vars[i+NRLOCVAR] <> 0 then
for j := 0 to FRegVariations[i].GetNrVariables - 1 do begin
Name := FRegVariations[i].GetVariableNameAt(j);
Result := Result + Format('%s="%s" ', [name, FRegVariations[i].GetVariableStr(Name)]);
end;
end;
Result := Result + '/>';
end;
///////////////////////////////////////////////////////////////////////////////
procedure TXForm.GetVariable(const name: string; var Value: double);
var
i: integer;
begin
for i := 0 to High(FRegVariations) do
if FRegVariations[i].GetVariable(name, value) then
break;
end;
procedure TXForm.SetVariable(const name: string; var Value: double);
var
i: integer;
begin
for i := 0 to High(FRegVariations) do
if FRegVariations[i].SetVariable(name, value) then
break;
end;
procedure TXForm.ResetVariable(const name: string);
var
i: integer;
begin
for i := 0 to High(FRegVariations) do
if FRegVariations[i].ResetVariable(name) then
break;
end;
///////////////////////////////////////////////////////////////////////////////
function TXForm.GetVariableStr(const name: string): string;
var
i: integer;
begin
for i := 0 to High(FRegVariations) do begin
Result := FRegVariations[i].GetVariableStr(name);
if Result <> '' then break;
end;
end;
procedure TXForm.SetVariableStr(const name: string; var Value: string);
var
i: integer;
begin
for i := 0 to High(FRegVariations) do begin
if FRegVariations[i].SetVariableStr(name, value) then break;
end;
end;
end.