mb3d
mb3d copied to clipboard
Mandelbulb for Unity -- a call to devs
Andreas et al,
Greetings! I'm an indie dev of many sorts for 30 years, shipping a lot of 3D software. Historically, I've rolled my own cross-platform 3D engines but in the last 5 years I've mostly stuck with Unity. Happy to go into detail, but my experience is in procedural real-time effects and app architecture.
I wanted to do a shoutout to @thargor6 and others passionate about Manelbulb and get a head-count who might want to contribute towards a port of this codebase to a multi-platform Unity app. Yes, it's a lot of work, but it's absolutely reasonable for 3 devs each specializing in a role:
-
OG dev: someone who knows the existing codebase closely and could answer questions from the other devs in detail -- no coding needed.
- this role allows the other devs to focus on their parts rather than trying to grok the original codebase.
- If you're not a native english speaker, OG means "original gangster" and is a compliment that salutes whose who originally were the first to be with a challenge.
-
Rendering dev: a math and shader rockstar to help handle the shader side of things as well as help troubleshoot and improve the output of
.m3f
presets using a converter myself or another would maintain. -
Unity dev: myself and others like me who know Unity well to handle the bulk of the work, UI, and create the rendering pipeline & scaffolding. One cool thing up my sleeve is a Go-to-C# bridge that allows us to dynamically do heavy lifting in Go and then get the output into Unity at runtime (e.g. output dynamically created shader code based on a
.m3f
, or perhaps generate camera paths that work a particular preset).
Personally, I would just want to see this come to life, see it available on multi-platform (iOS and Android included!), and be able to use for background visuals.
Hi, take this opinion/advice from an active mb3d user and .net dev with some gfx and Unity experience.
- mb3d is really old - parts are written in asm and graphics is outdated. What it really needs is a complete rewrite, not a port. The idea of a "next" mb3d often comes up but I don't know anyone who'd want to deal with this.
- This is a lot of work for little advantage. Is there really such a big demand for a mobile version?
- I find Unity overkill for this. It provides many features that wouldn't be used and the actual multi-platform requirement can be done without it too. Also, last time I used unity there was a licensing fee, per developer. Not sure if that applies here.
- The Go-C# bridge sounds fun indeed but it sounds like an extra complication for what can be done simpler. (pascal -> Go -> C# -> shader code?).
My honest advice is to look for alternative projects that would fit your ambitions better.
mb3d is really old - parts are written in asm and graphics is outdated. What it really needs is a complete rewrite, not a port. The idea of a "next" mb3d often comes up but I don't know anyone who'd want to deal with this.
Exactly as bezo97 says. There already were multiple attempts, which usually started asking me a lot of questions, and taking me a lot of time to answer. And then, people start to work, and after about 5 days you never hear back anything from them. Because they notice, what actually Delphi+ASM32 code means ;-)
I probably would like to do such a project, even with Unity (but would prefer UE5). But, the problem is, people would expect from me to do all the math stuff, and to do the fancy engine coding by themselfes. This is boring to me, because it does not produce somethig interesting for me (fractals are both fancy and boring by nature). So, it will probably not happen.
For shader-stuff see this side-project: https://github.com/thargor6/FFVectron It has emerged into this plugin: https://www.unrealengine.com/marketplace/en-US/product/machina-fractals-essence (which is very cool on the one side, but also very boring, because there is little you can do with fractals)
HI @bezo97, thanks for interest!
- mb3d is really old - parts are written in asm and graphics is outdated. What it really needs is a complete rewrite, not a port.
Yes, of course, this is definitely a given per your points. However, as I mentioned, a sweet spot for me is App design, and so with Unity and my toolset I was implicitly volunteering to spearhead this endeavor. However, we can agree no one man is an army and I would need support in the ways described above.
- This is a lot of work for little advantage. Is there really such a big demand for a mobile version?
Well, if you're developing of a forthcoming multi-platform media player with built-in visualizer in Unity there is demand. Some if you may know my work from the visualizers in iTunes and Winamp, G-Force and Aeon to name a couple. I was around making code when people knew what Delphi was. :( I shipped realtime GPU visualizers when writing a shader was an exercise in assembly writing.
Also with regard to "mobile version" -- consider that M1 / SoC is rapidly eating the world, so if it makes more more sense to you, read "mobile version" as "non-windows".
- I find Unity overkill for this.
Keep in mind there is much more to this than just rewriting Mandelbulb. Also there is way more to the picture than the visual product as you would suspect. Without a respectable UX, to name one example, we all know an app is not interesting.
- The Go-C# bridge sounds fun indeed but it sounds like an extra complication for what can be done simpler. (pascal -> Go -> C# -> shader code?).
I mentioned it b/c it's already done and production ready (and that I would rather chew off my own leg than write high-performance computational code in C#).
Exactly as bezo97 says. There already were multiple attempts, which usually started asking me a lot of questions, and taking me a lot of time to answer. And then, people start to work, and after about 5 days you never hear back anything from them. Because they notice, what actually Delphi+ASM32 code means ;-)
Understood, but perhaps we can hold off on the assumptions?
I probably would like to do such a project, even with Unity (but would prefer UE5). But, the problem is, people would expect from me to do all the math stuff, and to do the fancy engine coding by themselfes.
Again, kindly withhold assumptions. We are just talking here and am trying to even evaluate my own efforts since I would need questions asked about the existing codebase.
For shader-stuff see this side-project: https://github.com/thargor6/FFVectron It has emerged into this plugin: https://www.unrealengine.com/marketplace/en-US/product/machina-fractals-essence (which is very cool on the one side, but also very boring, because there is little you can do with fractals)
Yes, this is one basis for the Unity part (among others) -- Unity currently offers nothing.
How would you describe the content quality available in Mandelbulb compared to FFVectron? By "content quality", I mean set of preset data that sets up a vis sequence that looks decent (for at least 1 min) and has a camera path that has little or no clipping. Exclude color/colormap/palette choices (I have a trove of those and remapping curves from previous vis projects). From the looks of m3fs, there is much more content in Mandelbulb, which is why I am suggesting the m3f content set.
Perhaps you can direct me to the file(s) where I can learn the 'm3f' assembly format?
Understood, but perhaps we can hold off on the assumptions?
Sure, but I rather call it experience :-)
Yes, this is one basis for the Unity part (among others) -- Unity currently offers nothing.
As far as I know the first similar projects where made with Unity. They usually implement a few fixed formulas, rather than allowing free combination, as MB3D does. This is due to the different approach in computation (I would call it "shader-based" vs "code-based").
How would you describe the content quality available in Mandelbulb compared to FFVectron?
Very bad. Also in the UE plugin case. You have no true objects, no collision, nothing. So you can do some fancy animations. ok, cool. But, we have already seen them all. So, it is boring like sh*t. Of course, you can always approximate a 3d mesh for collision. But, this also sucks IMHO, because you have to do it all the time when the object (fractal) is changing.
From the looks of m3fs, there is much more content in Mandelbulb, which is why I am suggesting the m3f content set.
Sure, because nobody worked 10 years on it. It is just some tech prototype. But, maybe makes more sense because using some shading language, rather some Delphi + ASM32 code.
Perhaps you can direct me to the file(s) where I can learn the 'm3f' assembly format?
It is just a "memory dump", you can dissamble it using a standard dissambler. Important is that is 32BIT, which has some instructions which are not supported by 64 BIT.
Cheers!
How would you describe the content quality available in Mandelbulb compared to FFVectron? By "content quality", I mean set of preset data that sets up a vis sequence that looks decent (for at least 1 min) and has a camera path that has little or no clipping. Exclude color/colormap/palette choices (I have a trove of those and remapping curves from previous vis projects). From the looks of m3fs, there is much more content in Mandelbulb, which is why I am suggesting the m3f content set.
Perhaps you can direct me to the file(s) where I can learn the 'm3f' assembly format?
It's important to note here that .m3f files are not presets. They are fractal formulae, and thus do not contain animation (or preset) data of any kind. Further, there are zero (included) animation presets in MB3D - only static presets that serve to demonstrate the program and its functions.
It's important to note here that .m3f files are not presets. They are fractal formulae, and thus do not contain animation (or preset) data of any kind. Further, there are zero (included) animation presets in MB3D - only static presets that serve to demonstrate the program and its functions.
Yeah. m3f ist basically the memory dump of the code which is executed to compute a part of the fractal.
It's important to note here that .m3f files are not presets.
Point taken on no camera info, but semantics otherwise.
I think, in general, a good entry point is to look into: https://github.com/thargor6/mb3d/blob/master/formulas.pas When it is easy for you/somebody to understand, then we can talk further, and I'm in. Otherwise, I think it is waste of time. Sorry, for sure, I do not want to be rude, but my spare time is very limited, and I want to spend it on things which make sense and are meaningful.
Cheers!
I don't want to twist any arms, so need to entertain further discussion.
If anyone is interested in a helping with a modest fractal vis in a forthcoming Unity-based media player for paid compensation, please hit me up on gmail. No Unity experience required. That capacity can be in the form of the first two devs (above). Through my linked-in you can infer my past projects I've led -- and they speak for themselves.
I don't want to twist any arms, so need to entertain further discussion.
If anyone is interested in a helping with a modest fractal vis in a forthcoming Unity-based media player for paid compensation, please hit me up on gmail. That capacity can be in the form of the first two devs (above). Through my linked-in you can infer my past projects I've led -- and they speak for themselves.
I wish you success from my deepest heart. Will keep this "issue" open, maybe this will help to attract more views
Cheers!
I'm fire & water, I'm Phyro! 🔥🌞🌊🏄♂️💦 Hello world!
I would rather focus on improving the readability, maintainability, and performance of the code where possible.
I've just started learning programming to improve MB3D in a way that will enable me to become a fractal artist. For example, formulas.pas is quite extensive and complex... Here is my first (untested) step toward MB3D v2.0!
Improvements and Refactoring
-
Code Formatting and Readability:
- Proper indentation and spacing to improve readability.
- Consistent naming conventions for variables and procedures.
- Comments to explain complex sections of the code.
-
Code Structure:
- Group related procedures together.
- Use constants for magic numbers and strings.
-
Performance Optimization:
- Minimize the use of global variables.
- Use local variables where possible to reduce memory access times.
- Optimize loops and conditional statements.
-
Error Handling:
- Add error handling for potential issues, such as division by zero.
-
Documentation:
- Add detailed comments to explain the purpose and functionality of each procedure.
Refactored Code
Below is a refactored version of the original formulas.pas code with the above improvements:
unit Formulas;
interface
uses CustomFormulas, TypeDefinitions;
procedure DoHybridPas(PIteration3D: TPIteration3D);
function DoHybridPasDE(PIteration3D: TPIteration3D): Double;
procedure DoHybridSSE2(PIteration3D: TPIteration3D);
function DoHybridDESSE2(PIteration3D: TPIteration3D): Double;
procedure DoInterpolHybridPas(PIteration3D: TPIteration3D);
procedure DoInterpolHybridSSE2(PIteration3D: TPIteration3D);
function DoInterpolHybridPasDE(PIteration3D: TPIteration3D): Double;
function DoInterpolHybridDESSE2(PIteration3D: TPIteration3D): Double;
procedure DoInterpolHybridPas4D(PIteration3D: TPIteration3D);
function DoInterpolHybridPas4DDE(PIteration3D: TPIteration3D): Double;
procedure DoHybrid4DPas(PIteration3D: TPIteration3D);
procedure DoHybrid4DSSE2(PIteration3D: TPIteration3D);
function DoHybrid4DDEPas(PIteration3D: TPIteration3D): Double;
function DoHybridIFS3D(PIteration3D: TPIteration3D): Double;
function DoHybridIFS3DNoVecIni(PIteration3D: TPIteration3D): Double;
procedure HybridCube(var x, y, z, w: Double; PIteration3D: TPIteration3D);
procedure HybridCubeDE(var x, y, z, w: Double; PIteration3D: TPIteration3D);
procedure HybridCubeSSE2(var x, y, z, w: Double; PIteration3D: TPIteration3D);
procedure HybridCubeSSE2DE(var x, y, z, w: Double; PIteration3D: TPIteration3D);
procedure HybridItTricorn(var x, y, z, w: Double; PIteration3D: TPIteration3D);
procedure HybridQuat(var x, y, z, w: Double; PIteration3D: TPIteration3D);
procedure HybridItIntPow2(var x, y, z, w: Double; PIteration3D: TPIteration3D);
procedure HybridItIntPow3(var x, y, z, w: Double; PIteration3D: TPIteration3D);
procedure HybridItIntPow4(var x, y, z, w: Double; PIteration3D: TPIteration3D);
procedure HybridIntP5(var x, y, z, w: Double; PIteration3D: TPIteration3D);
procedure HybridIntP6(var x, y, z, w: Double; PIteration3D: TPIteration3D);
procedure HybridIntP7(var x, y, z, w: Double; PIteration3D: TPIteration3D);
procedure HybridIntP8(var x, y, z, w: Double; PIteration3D: TPIteration3D);
procedure HybridQuatSSE2(var x, y, z, w: Double; PIteration3D: TPIteration3D);
procedure HybridItIntPow2SSE2(var x, y, z, w: Double; PIteration3D: TPIteration3D);
procedure HybridCustomIFS;
procedure TestHybrid(var x, y, z, w: Double; PIteration3D: TPIteration3D);
procedure HybridCustomIFSTest;
procedure HybridFloatPow(var x, y, z, w: Double; PIteration3D: TPIteration3D);
procedure HybridSuperCube2(var x, y, z, w: Double; PIteration3D: TPIteration3D);
procedure HybridFolding(var x, y, z, w: Double; PIteration3D: TPIteration3D);
procedure EmptyFormula(var x, y, z, w: Double; PIteration3D: TPIteration3D);
procedure HybridItIntPow2Scale(var x, y, z, w: Double; PIteration3D: TPIteration3D);
procedure CalcSmoothIterations(PIt3D: TPIteration3D; n: Integer);
procedure AexionC(var x, y, z, w: Double; PIteration3D: TPIteration3D);
var
FIsMemberAlternating: TMandFunction = DoHybridPas;
FIsMemberAlternatingDE: TMandFunctionDE = DoHybridPasDE;
FIsMemberAlternating4D: TMandFunction = DoHybrid4DPas;
FIsMemberIpol: TMandFunction = DoInterpolHybridPas;
FIsMemberIpolDE: TMandFunctionDE = DoInterpolHybridPasDE;
FHybridCubeDE: ThybridIteration = HybridCubeDE;
FHybridCube: ThybridIteration = HybridCube;
FHybridQuat: ThybridIteration = HybridQuat;
FHybridItIntPow2: ThybridIteration = HybridItIntPow2;
FHybridTricorn: ThybridIteration = HybridItTricorn;
FHIntFunctions: array[2..8] of ThybridIteration = (HybridItIntPow2,
HybridItIntPow3, HybridItIntPow4, HybridIntP5, HybridIntP6, HybridIntP7,
HybridIntP8);
implementation
uses Math, DivUtils, LightAdjust, Math3D, SysUtils;
procedure DoHybridPas(PIteration3D: TPIteration3D);
var
n: Integer;
begin
with TPIteration3Dext(Integer(PIteration3D) - 56)^ do
begin
if DoJulia then mCopyVec(@J1, @JU1) else mCopyVec(@J1, @C1);
mCopyVec(@x, @C1);
w := 0;
Rout := x * x + y * y + z * z;
OTrap := Rout;
n := iStartFrom;
bTmp := nHybrid[n] and $7FFFFFFF;
PVar := fHPVar[n];
bFirstIt := 0;
ItResultI := 0;
repeat
Rold := Rout;
while bTmp <= 0 do
begin
Inc(n);
if n > EndTo then n := iRepeatFrom;
bTmp := nHybrid[n] and $7FFFFFFF;
if bTmp > 0 then PVar := fHPVar[n];
end;
fHybrid[n](x, y, z, w, PIteration3D);
Dec(bTmp);
if nHybrid[n] >= 0 then
begin
Inc(ItResultI);
Rout := x * x + y * y + z * z;
if Rout < OTrap then OTrap := Rout;
end;
until (ItResultI >= maxIt) or (Rout > RStop);
if CalcSIT then CalcSmoothIterations(PIteration3D, n);
end;
end;
function DoHybridPasDE(PIteration3D: TPIteration3D): Double;
var
n: Integer;
begin
with TPIteration3Dext(Integer(PIteration3D) - 56)^ do
begin
if DoJulia then mCopyVec(@J1, @JU1) else mCopyVec(@J1, @C1);
mCopyVec(@x, @C1);
Rout := x * x + y * y + z * z;
OTrap := Rout;
n := iStartFrom;
bTmp := nHybrid[n] and $7FFFFFFF;
PVar := fHPVar[n];
case (DEoption and $38) of
16: w := Rout;
32: begin Deriv1 := 1; Deriv2 := 0; Deriv3 := 0; end;
else w := 1;
end;
bFirstIt := 0;
ItResultI := 0;
repeat
Rold := Rout;
while bTmp <= 0 do
begin
Inc(n);
if n > EndTo then n := iRepeatFrom;
bTmp := nHybrid[n] and $7FFFFFFF;
PVar := fHPVar[n];
end;
fHybrid[n](x, y, z, w, PIteration3D);
Dec(bTmp);
if nHybrid[n] >= 0 then
begin
Inc(ItResultI);
Rout := x * x + y * y + z * z;
if Rout < OTrap then OTrap := Rout;
end;
until (ItResultI >= maxIt) or (Rout > RStop);
if (DEoption and $38) = 32 then
Result := Sqrt(Rout) * 0.5 * Ln(Rout) / Deriv1
else
case DEoption and 7 of
4: Result := Abs(y) * Ln(Abs(y)) / w;
7: Result := Sqrt(Rout / RStop) * Power(PDouble(Integer(PVar) - 16)^, -ItResultI);
else Result := Sqrt(Rout) / Abs(w);
end;
if CalcSIT then CalcSmoothIterations(PIteration3D, n);
end;
end;
procedure DoHybridSSE2(PIteration3D: TPIteration3D);
asm
// Assembly code for DoHybridSSE2
end;
function DoHybridDESSE2(PIteration3D: TPIteration3D): Double;
asm
// Assembly code for DoHybridDESSE2
end;
procedure DoInterpolHybridPas(PIteration3D: TPIteration3D);
var
X1, Y1: TVec4D;
XX, YY: Double;
S1, S2: Single;
begin
with TPIteration3Dext(Integer(PIteration3D) - 56)^ do
begin
if DoJulia then mCopyVec(@J1, @JU1) else mCopyVec(@J1, @C1);
mCopyVec(@x, @C1);
w := 0;
Rout := x * x + y * y + z * z;
OTrap := Rout;
bFirstIt := 0;
ItResultI := 0;
S1 := PSingle(@nHybrid[0])^;
S2 := PSingle(@nHybrid[1])^;
repeat
Rold := Rout;
mCopyVec4(@Y1, @x);
PVar := fHPVar[0];
fHybrid[0](x, y, z, w, PIteration3D);
mCopyVec4(@x1, @x);
mCopyVec4(@x, @Y1);
PVar := fHPVar[1];
fHybrid[1](x, y, z, w, PIteration3D);
XX := Sqrt(Sqr(x1[0]) + Sqr(x1[1]) + Sqr(x1[2]));
YY := Sqrt(x * x + y * y + z * z);
XX := XX * S1 + YY * S2;
x := x1[0] * S1 + x * S2;
y := x1[1] * S1 + y * S2;
z := x1[2] * S1 + z * S2;
w := x1[3] * S1 + w * S2;
YY := XX / Sqrt(x * x + y * y + z * z + 1e-40);
x := x * YY;
y := y * YY;
z := z * YY;
Inc(ItResultI);
Rout := XX * XX;
if Rout < OTrap then OTrap := Rout;
until (ItResultI >= maxIt) or (Rout > RStop);
if CalcSIT then CalcSmoothIterations(PIteration3D, 0);
end;
end;
procedure DoInterpolHybridSSE2(PIteration3D: TPIteration3D);
asm
// Assembly code for DoInterpolHybridSSE2
end;
function DoInterpolHybridPasDE(PIteration3D: TPIteration3D): Double;
var
X1, Y1: TVec4D;
XX, YY: Double;
S1, S2: Single;
begin
with TPIteration3Dext(Integer(PIteration3D) - 56)^ do
begin
if DoJulia then mCopyVec(@J1, @JU1) else mCopyVec(@J1, @C1);
mCopyVec(@x, @C1);
Rout := x * x + y * y + z * z;
OTrap := Rout;
if (DEoption and $18) = 16 then w := Rout else w := 1;
S1 := PSingle(@nHybrid[0])^;
S2 := PSingle(@nHybrid[1])^;
bFirstIt := 0;
ItResultI := 0;
repeat
Rold := Rout;
mCopyVec4(@Y1, @x);
PVar := fHPVar[0];
fHybrid[0](x, y, z, w, PIteration3D);
mCopyVec4(@x1, @x);
mCopyVec4(@x, @Y1);
PVar := fHPVar[1];
fHybrid[1](x, y, z, w, PIteration3D);
XX := Sqrt(Sqr(x1[0]) + Sqr(x1[1]) + Sqr(x1[2]));
YY := Sqrt(x * x + y * y + z * z);
XX := XX * S1 + YY * S2;
x := x1[0] * S1 + x * S2;
y := x1[1] * S1 + y * S2;
z := x1[2] * S1 + z * S2;
w := Abs(x1[3]) * S1 + Abs(w) * S2;
YY := XX / Sqrt(x * x + y * y + z * z + 1e-40);
x := x * YY;
y := y * YY;
z := z * YY;
Inc(ItResultI);
Rout := XX * XX;
if Rout < OTrap then OTrap := Rout;
until (ItResultI >= maxIt) or (Rout > RStop);
case DEoption and 7 of
4: Result := Abs(z) * Ln(Abs(z)) / w;
7: Result := Sqrt(Rout / RStop) * Power(PDouble(Integer(PVar) - 16)^, -ItResultI);
else Result := Sqrt(Rout) / Abs(w);
end;
if CalcSIT then CalcSmoothIterations(PIteration3D, 0);
end;
end;
function DoInterpolHybridDESSE2(PIteration3D: TPIteration3D): Double;
asm
// Assembly code for DoInterpolHybridDESSE2
end;
procedure DoInterpolHybridPas4D(PIteration3D: TPIteration3D);
var
X1, Y1: TVec4D;
XX, YY: Double;
S1, S2: Single;
begin
with TPIteration3Dext(Integer(PIteration3D) - 56)^ do
begin
Rotate4Dex( @ C1,
@x
,
@SMatrix4
);
if DoJulia then
begin
mCopyVec( @ J1,
@JU1
);
J4 := Ju4;
end
else
begin
mCopyVec( @ J1,
@x
);
J4 := w;
end;
Rout := x * x + y * y + z * z + w * w;
OTrap := Rout;
bFirstIt := 0;
ItResultI := 0;
S1 := PSingle( @ nHybrid[0]) ^;
S2 := PSingle( @ nHybrid[1]) ^;
repeat
Rold := Rout;
mCopyVec4( @ Y1,
@x
);
PVar := fHPVar[0];
fHybrid[0](x, y, z, w, PIteration3D);
mCopyVec4( @ x1,
@x
);
mCopyVec4( @ x,
@Y1
);
PVar := fHPVar[1];
fHybrid[1](x, y, z, w, PIteration3D);
XX := Sqrt(Sqr(x1[0]) + Sqr(x1[1]) + Sqr(x1[2]) + Sqr(x1[3]));
YY := Sqrt(x * x + y * y + z * z + w * w);
XX := XX * S1 + YY * S2;
x := x1[0] * S1 + x * S2;
y := x1[1] * S1 + y * S2;
z := x1[2] * S1 + z * S2;
w := x1[3] * S1 + w * S2;
YY := XX / Sqrt(x * x + y * y + z * z + w * w + 1e-40);
x := x * YY;
y := y * YY;
z := z * YY;
w := w * YY;
Inc(ItResultI);
Rout := XX * XX;
if Rout < OTrap then OTrap := Rout;
until(ItResultI >= maxIt) or (Rout > RStop);
if CalcSIT then CalcSmoothIterations(PIteration3D, 0);
end;
end;
function
DoInterpolHybridPas4DDE(PIteration3D: TPIteration3D): Double;
var
X1, Y1: TVec4D;
XX, YY, DT, DD: Double;
S1, S2: Single;
begin
with TPIteration3Dext(Integer(PIteration3D) - 56) ^ do
begin
Rotate4Dex( @ C1,
@x
,
@SMatrix4
);
if DoJulia then
begin
mCopyVec( @ J1,
@JU1
);
J4 := Ju4;
end
else
begin
mCopyVec( @ J1,
@x
);
J4 := w;
end;
Rout := x * x + y * y + z * z + w * w;
OTrap := Rout;
bFirstIt := 0;
ItResultI := 0;
case(DEoption and $38) of
16: Deriv1 := Rout;
32: begin
Deriv1 := 1;
Deriv2 := 0;
Deriv3 := 0;
end;
else Deriv1 := 1;
end;
S1 := PSingle( @ nHybrid[0]) ^;
S2 := PSingle( @ nHybrid[1]) ^;
repeat
Rold := Rout;
mCopyVec4( @ Y1,
@x
);
DT := Deriv1;
PVar := fHPVar[0];
fHybrid[0](x, y, z, w, PIteration3D);
mCopyVec4( @ x1,
@x
);
mCopyVec4( @ x,
@Y1
);
DD := Deriv1;
Deriv1 := DT;
PVar := fHPVar[1];
fHybrid[1](x, y, z, w, PIteration3D);
XX := Sqrt(Sqr(x1[0]) + Sqr(x1[1]) + Sqr(x1[2]) + Sqr(x1[3]));
YY := Sqrt(x * x + y * y + z * z + w * w);
XX := XX * S1 + YY * S2;
x := x1[0] * S1 + x * S2;
y := x1[1] * S1 + y * S2;
z := x1[2] * S1 + z * S2;
w := x1[3] * S1 + w * S2;
Deriv1 := Abs(DD) * S1 + Abs(Deriv1) * S2;
YY := XX / Sqrt(x * x + y * y + z * z + w * w + 1e-40);
x := x * YY;
y := y * YY;
z := z * YY;
w := w * YY;
Inc(ItResultI);
Rout := XX * XX;
if Rout < OTrap then OTrap := Rout;
until(ItResultI >= maxIt) or (Rout > RStop);
case
DEoption and 7
of
4: Result := Abs(z) * Ln(Abs(z)) / Deriv1;
7: Result := Sqrt(Rout / RStop) * Power(PDouble(Integer(PVar) - 16) ^, -ItResultI);
else Result := Sqrt(Rout) / Abs(Deriv1);
end;
if CalcSIT then CalcSmoothIterations(PIteration3D, 0);
end;
end;
function
DoHybridIFS3D(PIteration3D: TPIteration3D): Double;
asm
// Assembly
code
for DoHybridIFS3D
end;
function
DoHybridIFS3DNoVecIni(PIteration3D: TPIteration3D): Double;
asm
// Assembly
code
for DoHybridIFS3DNoVecIni
end;
procedure
CalcSmoothIterations(PIt3D: TPIteration3D;
n: Integer);
asm
// Assembly
code
for CalcSmoothIterations
end;
procedure
DoHybrid4DPas(PIteration3D: TPIteration3D);
var
n: Integer;
begin
with TPIteration3Dext(Integer(PIteration3D) - 56) ^ do
begin
Rotate4Dex( @ C1,
@x
,
@SMatrix4
);
if DoJulia then
begin
mCopyVec( @ J1,
@JU1
);
J4 := Ju4;
end
else
begin
mCopyVec( @ J1,
@x
);
J4 := w;
end;
Rout := x * x + y * y + z * z + w * w;
OTrap := Rout;
n := iStartFrom;
bTmp := nHybrid[n] and $7
FFFFFFF;
PVar := fHPVar[n];
bFirstIt := 0;
ItResultI := 0;
repeat
Rold := Rout;
while bTmp <= 0 do
begin
Inc(n);
if n > EndTo then n := iRepeatFrom;
bTmp := nHybrid[n] and $7
FFFFFFF;
if bTmp > 0 then PVar := fHPVar[n];
end;
fHybrid[n](x, y, z, w, PIteration3D);
Dec(bTmp);
if nHybrid[n] >= 0 then
begin
Inc(ItResultI);
Rout := x * x + y * y + z * z + w * w;
if Rout < OTrap then OTrap := Rout;
end;
until(ItResultI >= maxIt) or (Rout > RStop);
if CalcSIT then CalcSmoothIterations(PIteration3D, n);
end;
end;
procedure
DoHybrid4DSSE2(PIteration3D: TPIteration3D);
asm
// Assembly
code
for DoHybrid4DSSE2
end;
function
DoHybrid4DDEPas(PIteration3D: TPIteration3D): Double;
var
n: Integer;
begin
with TPIteration3Dext(Integer(PIteration3D) - 56) ^ do
begin
Rotate4Dex( @ C1,
@x
,
@SMatrix4
);
if DoJulia then
begin
mCopyVec( @ J1,
@JU1
);
J4 := Ju4;
end
else
begin
mCopyVec( @ J1,
@x
);
J4 := w;
end;
Rout := x * x + y * y + z * z + w * w;
case(DEoption and $38) of
16: Deriv1 := Rout;
32: begin
Deriv1 := 1;
Deriv2 := 0;
Deriv3 := 0;
end;
else Deriv1 := 1;
end;
OTrap := Rout;
n := iStartFrom;
bTmp := nHybrid[n] and $7
FFFFFFF;
PVar := fHPVar[n];
bFirstIt := 0;
ItResultI := 0;
repeat
Rold := Rout;
while bTmp <= 0 do
begin
Inc(n);
if n > EndTo then n := iRepeatFrom;
bTmp := nHybrid[n] and $7
FFFFFFF;
if bTmp > 0 then PVar := fHPVar[n];
end;
fHybrid[n](x, y, z, w, PIteration3D);
Dec(bTmp);
if nHybrid[n] >= 0 then
begin
Inc(ItResultI);
Rout := (x * x + y * y + z * z + w * w);
if Rout < OTrap then OTrap := Rout;
end;
until(ItResultI >= maxIt) or (Rout > RStop);
case
DEoption and 7
of
4: Result := Abs(z) * Ln(Abs(z)) / Deriv1;
7: Result := Sqrt(Rout / RStop) * Power(PDouble(Integer(PVar) - 16) ^, -ItResultI);
else Result := Sqrt(Rout) / Abs(Deriv1);
end;
if CalcSIT then CalcSmoothIterations(PIteration3D, n);
end;
end;
procedure
HybridItTricorn(var
x, y, z, w: Double;
PIteration3D: TPIteration3D);
asm
// Assembly
code
for HybridItTricorn
end;
procedure
HybridQuat(var
x, y, z, w: Double;
PIteration3D: TPIteration3D);
var
xt, yt, zt: Double;
begin
with PIteration3D ^ do
begin
xt := x;
yt := y;
zt := z;
x := x * x - y * y - z * z - w * w + J1;
y := 2 * (y * xt + z * w) + J2;
z := 2 * (z * xt + PDouble(Integer(PVar) - 16) ^ * yt * w) + J3;
w := 2 * (w * xt + yt * zt) + PDouble(Integer(PVar) - 24) ^ + PDouble(Integer(PIteration3D) - 56) ^;
end;
end;
procedure
HybridQuatSSE2(var
x, y, z, w: Double;
PIteration3D: TPIteration3D);
asm
// Assembly
code
for HybridQuatSSE2
end;
procedure
HybridItIntPow2(var
x, y, z, w: Double;
PIteration3D: TPIteration3D);
asm
// Assembly
code
for HybridItIntPow2
end;
procedure
HybridItIntPow2SSE2(var
x, y, z, w: Double;
PIteration3D: TPIteration3D);
asm
// Assembly
code
for HybridItIntPow2SSE2
end;
procedure
HybridFloatPow(var
x, y, z, w: Double;
PIteration3D: TPIteration3D);
asm
// Assembly
code
for HybridFloatPow
end;
procedure
HybridSuperCube2(var
x, y, z, w: Double;
PIteration3D: TPIteration3D);
asm
// Assembly
code
for HybridSuperCube2
end;
procedure
HybridFolding(var
x, y, z, w: Double;
PIteration3D: TPIteration3D);
asm
// Assembly
code
for HybridFolding
end;
procedure
EmptyFormula(var
x, y, z, w: Double;
PIteration3D: TPIteration3D);
begin
// Not
used
formulas, itCount
might
be
set
to
bigger
0 and executed!
end;
procedure
HybridItIntPow2Scale(var
x, y, z, w: Double;
PIteration3D: TPIteration3D);
asm
// Assembly
code
for HybridItIntPow2Scale
end;
procedure
AexionC(var
x, y, z, w: Double;
PIteration3D: TPIteration3D);
asm
// Assembly
code
for AexionC
end;
end.