Apophysis-AV/Variations/varJulia3Djf.pas

461 lines
10 KiB
ObjectPascal

{
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
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.
}
unit varJulia3Djf; // original variation code by Joel Faber, modified & optimized by Peter Sdobnov
interface
uses
{$ifdef CPUX86}
AsmRandom,
{$endif}
BaseVariation, XFormMan;
const
var_name = 'julia3D';
var_n_name='julia3D_power';
{$ifdef CPUX86}
{$define _ASM_}
{$endif}
type
TVariationJulia3DJF = class(TBaseVariation)
private
N: integer;
absN: integer;
cN: double;
procedure CalcPower1;
procedure CalcPowerMinus1;
procedure CalcPower2;
procedure CalcPowerMinus2;
public
constructor Create;
class function GetName: string; override;
class function GetInstance: TBaseVariation; override;
function GetNrVariables: integer; override;
function GetVariableNameAt(const Index: integer): string; override;
function SetVariable(const Name: string; var value: double): boolean; override;
function GetVariable(const Name: string; var value: double): boolean; override;
function ResetVariable(const Name: string): boolean; override;
procedure Prepare; override;
procedure CalcFunction; override;
procedure GetCalcFunction(var f: TCalcFunction); override;
end;
implementation
uses
Math;
// TVariationJulia3DJF
///////////////////////////////////////////////////////////////////////////////
constructor TVariationJulia3DJF.Create;
begin
N := random(5) + 2;
if random(2) = 0 then N := -N;
end;
procedure TVariationJulia3DJF.Prepare;
begin
absN := abs(N);
cN := (1/N - 1) / 2;
end;
///////////////////////////////////////////////////////////////////////////////
procedure TVariationJulia3DJF.GetCalcFunction(var f: TCalcFunction);
begin
if N = 2 then f := CalcPower2
else if N = -2 then f := CalcPowerMinus2
else if N = 1 then f := CalcPower1
else if N = -1 then f := CalcPowerMinus1
else f := CalcFunction;
end;
///////////////////////////////////////////////////////////////////////////////
procedure TVariationJulia3DJF.CalcFunction;
{$ifndef _ASM_}
var
r, r2d, z, tmp: double;
sina, cosa: extended;
begin
z := FTz^ / absN;
r2d := sqr(FTx^) + sqr(FTy^);
r := vvar * Math.Power(r2d + sqr(z), cN); // r^n / sqrt(r) --> r^(n-0.5)
FPz^ := FPz^ + r * z;
tmp := r * sqrt(r2d);
sincos((arctan2(FTy^, FTx^) + 2*pi*random(absN)) / N, sina, cosa);
FPx^ := FPx^ + tmp * cosa;
FPy^ := FPy^ + tmp * sina;
{$else}
asm
mov edx, [eax + FTx]
fld qword ptr [edx + 32] // FTz
fidiv dword ptr [eax + absN]
fld qword ptr [edx] // FTx
fld qword ptr [edx + 8] // FTy
fld st(1)
fmul st, st
fld st(1)
fmul st, st
faddp
fld qword ptr [eax + cN]
fld st(4)
fmul st, st
fadd st, st(2)
// --- x^y = 2^(y*log2(x))
fyl2x
fld st
frndint
fsub st(1), st
fxch st(1)
f2xm1
fld1
fadd
fscale
fstp st(1)
// ---
fmul qword ptr [eax + vvar]
fmul st(4), st
fxch st(1)
fsqrt
fmulp
fxch st(2)
fpatan
mov ecx, eax
mov eax, dword ptr [eax + absN]
call AsmRandInt
push eax
fild dword ptr [esp]
add esp, 4
fldpi
fadd st, st
fmulp
faddp
fidiv dword ptr [ecx + N]
fsincos
mov edx, [ecx + FPx]
fmul st, st(2)
fadd qword ptr [edx] // FPx
fstp qword ptr [edx]
fmulp
fadd qword ptr [edx + 8] // FPy
fstp qword ptr [edx + 8]
fadd qword ptr [edx + $18] // FPz
fstp qword ptr [edx + $18]
fwait
{$endif}
end;
procedure TVariationJulia3DJF.CalcPower2;
{$ifndef _ASM_}
var
r, r2d, z, tmp: double;
sina, cosa: extended;
begin
z := FTz^ / 2;
r2d := sqr(FTx^) + sqr(FTy^);
r := vvar / sqrt(sqrt(r2d + sqr(z))); // vvar * sqrt(r3d) / r3d --> vvar / sqrt(r3d)
FPz^ := FPz^ + r * z;
tmp := r * sqrt(r2d);
sincos(arctan2(FTy^, FTx^) / 2 + pi*random(2), sina, cosa);
FPx^ := FPx^ + tmp * cosa;
FPy^ := FPy^ + tmp * sina;
{$else}
asm
mov edx, [eax + FTx]
fld qword ptr [edx + 32] // FTz
fld1
fadd st, st
fdiv st(1), st
fld qword ptr [edx + 8] // FTy
fld qword ptr [edx] // FTx
fld st(1)
fld st(1)
fpatan
fdivrp st(3), st
fmul st, st
fxch st(1)
fmul st, st
faddp
fld st(2)
fmul st, st
fadd st, st(1)
fsqrt
fsqrt
fdivr qword ptr [eax + vvar]
fmul st(3), st
fxch st(1)
fsqrt
fmulp
fxch st(1)
mov ecx, eax
mov eax, 2
call AsmRandInt
fldpi
push eax
fimul dword ptr [esp]
add esp, 4
faddp
fsincos
mov edx, [ecx + FPx]
fmul st, st(2)
fadd qword ptr [edx] // FPx
fstp qword ptr [edx]
fmulp
fadd qword ptr [edx + 8] // FPy
fstp qword ptr [edx + 8]
fadd qword ptr [edx + $18] // FPz
fstp qword ptr [edx + $18]
fwait
{$endif}
end;
procedure TVariationJulia3DJF.CalcPowerMinus2;
{$ifndef _ASM_}
var
r, r2d, r3d, z, tmp: double;
sina, cosa: extended;
begin
z := FTz^ / 2;
r2d := sqr(FTx^) + sqr(FTy^);
r3d := sqrt(r2d + sqr(z));
r := vvar / (sqrt(r3d) * r3d);
FPz^ := FPz^ + r * z;
tmp := r * sqrt(r2d);
sincos(arctan2(FTy^, FTx^) / 2 + pi*random(2), sina, cosa);
FPx^ := FPx^ + tmp * cosa;
FPy^ := FPy^ - tmp * sina;
{$else}
asm
mov edx, [eax + FTx]
fld qword ptr [edx + 32] // FTz
fld1
fadd st, st
fdiv st(1), st
fld qword ptr [edx + 8] // FTy
fld qword ptr [edx] // FTx
fld st(1)
fld st(1)
fpatan
fdivrp st(3), st
fmul st, st
fxch st(1)
fmul st, st
faddp
fld st(2)
fmul st, st
fadd st, st(1)
fsqrt
fld st
fsqrt
fmulp
fdivr qword ptr [eax + vvar]
fmul st(3), st
fxch st(1)
fsqrt
fmulp
fxch st(1)
mov ecx, eax
mov eax, 2
call AsmRandInt
fldpi
push eax
fimul dword ptr [esp]
add esp, 4
faddp
fsincos
mov edx, [ecx + FPx]
fmul st, st(2)
fadd qword ptr [edx] // FPx
fstp qword ptr [edx]
fmulp
fsubr qword ptr [edx + 8] // FPy
fstp qword ptr [edx + 8]
fadd qword ptr [edx + $18] // FPz
fstp qword ptr [edx + $18]
fwait
{$endif}
end;
procedure TVariationJulia3DJF.CalcPower1;
{$ifndef _ASM_}
begin
FPx^ := FPx^ + vvar * FTx^;
FPy^ := FPy^ + vvar * FTy^;
FPz^ := FPz^ + vvar * FTz^;
{$else}
asm
fld qword ptr [eax + vvar]
mov edx, [eax + FTx]
fld qword ptr [edx] // FTx
fmul st, st(1)
fadd qword ptr [edx + 16] // FPx
fstp qword ptr [edx + 16]
fld qword ptr [edx + 8] // FTy
fmul st, st(1)
fadd qword ptr [edx + 24] // FPy
fstp qword ptr [edx + 24]
fmul qword ptr [edx + 32] // FTz
fadd qword ptr [edx + 40] // FPz
fstp qword ptr [edx + 40]
fwait
{$endif}
end;
procedure TVariationJulia3DJF.CalcPowerMinus1;
{$ifndef _ASM_}
var
r: double;
begin
r := vvar / (sqr(FTx^) + sqr(FTy^) + sqr(FTz^));
FPx^ := FPx^ + r * FTx^;
FPy^ := FPy^ - r * FTy^;
FPz^ := FPz^ + r * FTz^;
{$else}
asm
mov edx, [eax + FTx]
fld qword ptr [edx + 32] // FTz
fld qword ptr [edx + 8] // FTy
fld qword ptr [edx] // FTx
fld st(2)
fmul st, st
fld st(2)
fmul st, st
faddp
fld st(1)
fmul st, st
faddp
fdivr qword ptr [eax + vvar]
fmul st(3), st
fmul st(2), st
fmulp
fadd qword ptr [edx + 16] // FPx
fstp qword ptr [edx + 16]
fsubr qword ptr [edx + 24] // FPy
fstp qword ptr [edx + 24]
fadd qword ptr [edx + 40] // FPz
fstp qword ptr [edx + 40]
fwait
{$endif}
end;
///////////////////////////////////////////////////////////////////////////////
class function TVariationJulia3DJF.GetInstance: TBaseVariation;
begin
Result := TVariationJulia3DJF.Create;
end;
///////////////////////////////////////////////////////////////////////////////
class function TVariationJulia3DJF.GetName: string;
begin
Result := var_name;
end;
///////////////////////////////////////////////////////////////////////////////
function TVariationJulia3DJF.GetVariableNameAt(const Index: integer): string;
begin
case Index of
0: Result := var_n_name;
else
Result := '';
end
end;
///////////////////////////////////////////////////////////////////////////////
function TVariationJulia3DJF.SetVariable(const Name: string; var value: double): boolean;
begin
Result := False;
if Name = var_n_name then begin
N := Round(Value);
if N = 0 then N := 1;
Value := N;
Result := True;
end;
end;
function TVariationJulia3DJF.ResetVariable(const Name: string): boolean;
begin
Result := False;
if Name = var_n_name then begin
if N = 2 then N := -2
else N := 2;
Result := True;
end;
end;
///////////////////////////////////////////////////////////////////////////////
function TVariationJulia3DJF.GetNrVariables: integer;
begin
Result := 1;
end;
///////////////////////////////////////////////////////////////////////////////
function TVariationJulia3DJF.GetVariable(const Name: string; var value: double): boolean;
begin
Result := False;
if Name = var_n_name then begin
Value := N;
Result := true;
end;
end;
///////////////////////////////////////////////////////////////////////////////
initialization
RegisterVariation(TVariationClassLoader.Create(TVariationJulia3DJF), true, false);
end.