This is a diff of the original fractal.cpp from mandelbulber 1.08 and the generalized box fold changes. The code essentially replaces the Tglad mandelbox box fold with the generalized fold. I had trouble implementing the "folding limit" function, so I have used this parameter to select between a number of polyhedron.
Folding limit polyhedron
default tet
2 cube
3 oct
4 dodeca
5 turncated oct.
Disclaimer. The cube selection does not reproduce the original box fold. This points to a bug in either the theory or the implementation. However it produces some interesting fractals as is. I expect to find the bug when I try to implement the melting poly version suggested by Hobold.
I would be honored if Budda wants to integrate this into the mandelbulber, but he might want to wait a couple of days to see if I can fix the bug and melt some polys.
19a20,111
>
>
> inline CVector3 Cross(CVector3 A , CVector3 B){
> CVector3 C;
> C.x = A.y*B.z - A.z*B.y;
> C.y = -A.x*B.z + A.z*B.x;
> C.z = A.x*B.y - A.y*B.x;
> return (C);
> }
>
> // The box used by the generalized box fold is specified by a set
> // of normalized unit vectors. Each vector is a normal that defines a plane.
> // Xp dot N = foldingvalue.
> #define sqrt_i3 .57735
> CVector3 Nv_tet[] =
> {
> { sqrt_i3, sqrt_i3,-sqrt_i3},
> { sqrt_i3,-sqrt_i3, sqrt_i3},
> {-sqrt_i3, sqrt_i3, sqrt_i3},
> {-sqrt_i3,-sqrt_i3,-sqrt_i3}
> };
>
> int sides_tet = 4;
>
>
> CVector3 Nv_cube[] =
> {
> { 1, 0, 0},
> {-1, 0, 0},
> { 0, 1, 0},
> { 0,-1, 0},
> { 0, 0, 1},
> { 0, 0,-1}
> };
>
> int sides_cube = 6;
>
> CVector3 Nv_oct[] =
> {
> { sqrt_i3, sqrt_i3,-sqrt_i3},
> { sqrt_i3,-sqrt_i3, sqrt_i3},
> {-sqrt_i3, sqrt_i3, sqrt_i3},
> {-sqrt_i3,-sqrt_i3,-sqrt_i3},
> { sqrt_i3, sqrt_i3, sqrt_i3},
> {-sqrt_i3,-sqrt_i3, sqrt_i3},
> {-sqrt_i3, sqrt_i3,-sqrt_i3},
> { sqrt_i3,-sqrt_i3,-sqrt_i3}
> };
>
> int sides_oct = 8;
>
> CVector3 Nv_oct_cube[] =
> {
> { sqrt_i3, sqrt_i3,-sqrt_i3},
> { sqrt_i3,-sqrt_i3, sqrt_i3},
> {-sqrt_i3, sqrt_i3, sqrt_i3},
> {-sqrt_i3,-sqrt_i3,-sqrt_i3},
> { sqrt_i3, sqrt_i3, sqrt_i3},
> {-sqrt_i3,-sqrt_i3, sqrt_i3},
> {-sqrt_i3, sqrt_i3,-sqrt_i3},
> { sqrt_i3,-sqrt_i3,-sqrt_i3},
> { 1, 0, 0},
> {-1, 0, 0},
> { 0, 1, 0},
> { 0,-1, 0},
> { 0, 0, 1},
> { 0, 0,-1}
> };
> int sides_oct_cube = 14;
>
>
> #define aa ((1.0+sqrt(5.0))/2.0)
> #define bb (1.0/sqrt(aa*aa+1))
>
> CVector3 Nv_dodeca[] =
> {
> { 0, bb, aa*bb},
> { 0, bb,-aa*bb},
> { 0,-bb, aa*bb},
> { 0,-bb,-aa*bb},
> { bb, aa*bb, 0},
> { bb,-aa*bb, 0},
> {-bb, aa*bb, 0},
> {-bb,-aa*bb, 0},
> { aa*bb, 0, bb},
> {-aa*bb, 0, bb},
> { aa*bb, 0,-bb},
> {-aa*bb, 0,-bb}
> };
> int sides_dodeca = 12;
>
>
456,484c548,626
< if (z.x > par.mandelbox.doubles.foldingLimit)
< {
< z.x = par.mandelbox.doubles.foldingValue - z.x;
< tgladColor += par.mandelbox.doubles.colorFactorX;
< }
< else if (z.x < -par.mandelbox.doubles.foldingLimit)
< {
< z.x = -par.mandelbox.doubles.foldingValue - z.x;
< tgladColor += par.mandelbox.doubles.colorFactorX;
< }
< if (z.y > par.mandelbox.doubles.foldingLimit)
< {
< z.y = par.mandelbox.doubles.foldingValue - z.y;
< tgladColor += par.mandelbox.doubles.colorFactorY;
< }
< else if (z.y < -par.mandelbox.doubles.foldingLimit)
< {
< z.y = -par.mandelbox.doubles.foldingValue - z.y;
< tgladColor += par.mandelbox.doubles.colorFactorY;
< }
< if (z.z > par.mandelbox.doubles.foldingLimit)
< {
< z.z = par.mandelbox.doubles.foldingValue - z.z;
< tgladColor += par.mandelbox.doubles.colorFactorZ;
< }
< else if (z.z < -par.mandelbox.doubles.foldingLimit)
< {
< z.z = -par.mandelbox.doubles.foldingValue - z.z;
< tgladColor += par.mandelbox.doubles.colorFactorZ;
---
> int i;
> CVector3 *Nv;
> int sides;
> // HACK HACK HACK. I high jacked the foldingLimit parameter to chose the poly type.
> // Do not try this at home.
> Nv = Nv_tet;
> sides = sides_tet;
>
> if(int(par.mandelbox.doubles.foldingLimit) == 2){
> Nv = Nv_cube;
> sides = sides_cube;
> }
> if(int(par.mandelbox.doubles.foldingLimit) == 3){
> Nv = Nv_oct;
> sides = sides_oct;
> }
> if(int(par.mandelbox.doubles.foldingLimit) == 4){
> Nv = Nv_dodeca;
> sides = sides_dodeca;
> }
> if(int(par.mandelbox.doubles.foldingLimit) == 5){
> Nv = Nv_oct_cube;
> sides = sides_oct_cube;
> }
>
> int sort[3];
> int tmp_sort;
> double Z_Dot_Nv[3];
> double tmp_Z_Dot_Nv;
>
> // Find the three closest normal vectors to z as defined by max dot product.
> sort[0] = 0;
> Z_Dot_Nv[0] = z.Dot(Nv[0]);
> sort[1]= 1;
> Z_Dot_Nv[1] = z.Dot(Nv[1]);
> sort[2]= 2;
> Z_Dot_Nv[2] = z.Dot(Nv[2]);
>
> if(Z_Dot_Nv[1]>Z_Dot_Nv[0]){
> tmp_sort = sort[0];
> tmp_Z_Dot_Nv = Z_Dot_Nv[0];
> sort[0] = sort[1];
> Z_Dot_Nv[0]=Z_Dot_Nv[1];
> sort[1]=tmp_sort;
> Z_Dot_Nv[1]= tmp_Z_Dot_Nv;
> }
> if(Z_Dot_Nv[2]>Z_Dot_Nv[1]){
> tmp_sort = sort[1];
> tmp_Z_Dot_Nv = Z_Dot_Nv[1];
> sort[1] = sort[2];
> Z_Dot_Nv[1]=Z_Dot_Nv[2];
> sort[2]=tmp_sort;
> Z_Dot_Nv[2]=tmp_Z_Dot_Nv;
> }
> if(Z_Dot_Nv[1]>Z_Dot_Nv[0]){
> tmp_sort = sort[0];
> tmp_Z_Dot_Nv = Z_Dot_Nv[0];
> sort[0] = sort[1];
> Z_Dot_Nv[0]=Z_Dot_Nv[1];
> sort[1]=tmp_sort;
> Z_Dot_Nv[1]= tmp_Z_Dot_Nv;
> }
>
> for(i=3;i<sides;i++){
> tmp_Z_Dot_Nv = z.Dot(Nv[i]);
> tmp_sort = i;
> if(tmp_Z_Dot_Nv>Z_Dot_Nv[2]){
> sort[2] = tmp_sort;
> Z_Dot_Nv[2]= tmp_Z_Dot_Nv;
> if(tmp_Z_Dot_Nv>Z_Dot_Nv[1]){
> sort[2] = sort[1];
> Z_Dot_Nv[2]=Z_Dot_Nv[1];
> sort[1]=tmp_sort;
> Z_Dot_Nv[1]= tmp_Z_Dot_Nv;
> if(tmp_Z_Dot_Nv>Z_Dot_Nv[0]){
> sort[1] = sort[0];
> Z_Dot_Nv[1]=Z_Dot_Nv[0];
> sort[0]=tmp_sort;
> Z_Dot_Nv[0]= tmp_Z_Dot_Nv;
485a628,674
> }
> }
> }
> CVector3 Nv0=Nv[sort[0]];
> CVector3 Nv1=Nv[sort[1]];
> CVector3 Nv2=Nv[sort[2]];
>
> CVector3 new_z;
> double new_z_sqr;
> CVector3 Zm;
>
> // Assume z inside the poly and we are wasting our time.
> new_z = z;
> new_z_sqr = new_z.Dot(new_z);
>
> // Find reflection point to closest plain.
> Zm = z - (Nv0 + Nv0)*(z.Dot(Nv0) - par.mandelbox.doubles.foldingValue);
> if(new_z_sqr > Zm.Dot(Zm)){
> new_z = Zm;
> new_z_sqr = new_z.Dot(new_z);
> tgladColor += par.mandelbox.doubles.colorFactorX;
> }
>
> // Find rotation point to closest line.
> CVector3 T01, L01;
> L01 = Cross(Nv0,Nv1);
> L01 = L01 * (1.0/L01.Length());
> T01 = (Nv0+Nv1) * ( (par.mandelbox.doubles.foldingValue)/(1 + Nv0.Dot(Nv1)));
> CVector3 Zr;
> Zr = (T01 + L01 * z.Dot(L01)) * 2 - z;
> if(new_z_sqr > Zr.Dot(Zr)){
> new_z = Zr;
> new_z_sqr = new_z.Dot(new_z);
> tgladColor += par.mandelbox.doubles.colorFactorY;
> }
>
> // Find inversion point to closest vert.
> CVector3 Zi;
> double a;
> a = ((par.mandelbox.doubles.foldingValue)-T01.Dot(Nv2))/(L01.Dot(Nv2));
> Zi = (L01*a + T01) * 2 - z;
> if(new_z_sqr > Zi.Dot(Zi)){
> new_z = Zi;
> new_z_sqr = new_z.Dot(new_z);
> tgladColor += par.mandelbox.doubles.colorFactorZ;
> }
> z = new_z;
487c676
<
---
>