home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: Graphics
/
Graphics.zip
/
povsrc31.zip
/
quatern.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-10-20
|
12KB
|
557 lines
/*****************************************************************************
* quatern.c
*
* This module implements Quaternion algebra julia fractals.
*
* This file was written by Pascal Massimino.
* Revised and updated for POV-Ray 3.x by Tim Wegner
*
* from Persistence of Vision(tm) Ray Tracer
* Copyright 1996,1999 Persistence of Vision Team
*---------------------------------------------------------------------------
* NOTICE: This source code file is provided so that users may experiment
* with enhancements to POV-Ray and to port the software to platforms other
* than those supported by the POV-Ray Team. There are strict rules under
* which you are permitted to use this file. The rules are in the file
* named POVLEGAL.DOC which should be distributed with this file.
* If POVLEGAL.DOC is not available or for more info please contact the POV-Ray
* Team Coordinator by email to team-coord@povray.org or visit us on the web at
* http://www.povray.org. The latest version of POV-Ray may be found at this site.
*
* This program is based on the popular DKB raytracer version 2.12.
* DKBTrace was originally written by David K. Buck.
* DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
*
*****************************************************************************/
#include "frame.h"
#include "povray.h"
#include "vector.h"
#include "povproto.h"
#include "fractal.h"
#include "quatern.h"
#include "spheres.h"
/*****************************************************************************
* Local preprocessor defines
******************************************************************************/
#ifndef Fractal_Tolerance
#define Fractal_Tolerance 1e-8
#endif
#define Deriv_z2(n1,n2,n3,n4) \
{ \
tmp = (n1)*x - (n2)*y - (n3)*z - (n4)*w; \
(n2) = (n1)*y + x*(n2); \
(n3) = (n1)*z + x*(n3); \
(n4) = (n1)*w + x*(n4); \
(n1) = tmp; \
}
#define Deriv_z3(n1,n2,n3,n4) \
{ \
dtmp = 2.0*((n2)*y + (n3)*z + (n4)*w); \
dtmp2 = 6.0*x*(n1) - dtmp; \
(n1) = ( (n1)*x3 - x*dtmp )*3.0; \
(n2) = (n2)*x4 + y*dtmp2; \
(n3) = (n3)*x4 + z*dtmp2; \
(n4) = (n4)*x4 + w*dtmp2; \
}
/*****************************************************************************
* Local typedefs
******************************************************************************/
/*****************************************************************************
* Static functions
******************************************************************************/
/*****************************************************************************
* Local variables
******************************************************************************/
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* Pascal Massimino
*
* DESCRIPTION
*
* -
*
* CHANGES
*
* Dec 1994 : Creation.
*
******************************************************************************/
int Iteration_z3(VECTOR point, FRACTAL *Julia)
{
int i;
DBL x, y, z, w;
DBL d, x2, tmp;
DBL Exit_Value;
Sx[0] = x = point[X];
Sy[0] = y = point[Y];
Sz[0] = z = point[Z];
Sw[0] = w = (Julia->SliceDist
- Julia->Slice[X]*x
- Julia->Slice[Y]*y
- Julia->Slice[Z]*z)/Julia->Slice[T];
Exit_Value = Julia->Exit_Value;
for (i = 1; i <= Julia->n; ++i)
{
d = y * y + z * z + w * w;
x2 = x * x;
if ((d + x2) > Exit_Value)
{
return (FALSE);
}
tmp = 3.0 * x2 - d;
Sx[i] = x = x * (x2 - 3.0 * d) + Julia->Julia_Parm[X];
Sy[i] = y = y * tmp + Julia->Julia_Parm[Y];
Sz[i] = z = z * tmp + Julia->Julia_Parm[Z];
Sw[i] = w = w * tmp + Julia->Julia_Parm[T];
}
return (TRUE);
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* Pascal Massimino
*
* DESCRIPTION
*
* -
*
* CHANGES
*
* Dec 1994 : Creation.
*
******************************************************************************/
int Iteration_Julia(VECTOR point, FRACTAL *Julia)
{
int i;
DBL x, y, z, w;
DBL d, x2;
DBL Exit_Value;
Sx[0] = x = point[X];
Sy[0] = y = point[Y];
Sz[0] = z = point[Z];
Sw[0] = w = (Julia->SliceDist
- Julia->Slice[X]*x
- Julia->Slice[Y]*y
- Julia->Slice[Z]*z)/Julia->Slice[T];
Exit_Value = Julia->Exit_Value;
for (i = 1; i <= Julia->n; ++i)
{
d = y * y + z * z + w * w;
x2 = x * x;
if ((d + x2) > Exit_Value)
{
return (FALSE);
}
x *= 2.0;
Sy[i] = y = x * y + Julia->Julia_Parm[Y];
Sz[i] = z = x * z + Julia->Julia_Parm[Z];
Sw[i] = w = x * w + Julia->Julia_Parm[T];
Sx[i] = x = x2 - d + Julia->Julia_Parm[X];;
}
return (TRUE);
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* Pascal Massimino
*
* DESCRIPTION
*
* D_Iteration puts in *Dist a lower bound for the distance from *point to the
* set
*
* CHANGES
*
* Dec 1994 : Creation.
*
******************************************************************************/
/*----------- Distance estimator + iterations ------------*/
int D_Iteration_z3(VECTOR point, FRACTAL *Julia, DBL *Dist)
{
int i, j;
DBL Norm, d;
DBL xx, yy, zz;
DBL x, y, z, w;
DBL tmp, x2;
DBL Exit_Value;
DBL Pow;
x = Sx[0] = point[X];
y = Sy[0] = point[Y];
z = Sz[0] = point[Z];
w = Sw[0] = (Julia->SliceDist
- Julia->Slice[X]*x
- Julia->Slice[Y]*y
- Julia->Slice[Z]*z)/Julia->Slice[T];
Exit_Value = Julia->Exit_Value;
for (i = 1; i <= Julia->n; i++)
{
d = y * y + z * z + w * w;
x2 = x * x;
if ((Norm = d + x2) > Exit_Value)
{
/* Distance estimator */
x = Sx[0];
y = Sy[0];
z = Sz[0];
w = Sw[0];
Pow = 1.0 / 3.0;
for (j = 1; j < i; ++j)
{
xx = x * Sx[j] - y * Sy[j] - z * Sz[j] - w * Sw[j];
yy = x * Sy[j] + y * Sx[j] - z * Sw[j] + w * Sz[j];
zz = x * Sz[j] + y * Sw[j] + z * Sx[j] - w * Sy[j];
w = x * Sw[j] - y * Sz[j] + z * Sy[j] + w * Sx[j];
x = xx;
y = yy;
z = zz;
Pow /= 3.0;
}
*Dist = Pow * sqrt(Norm / (x * x + y * y + z * z + w * w)) * log(Norm);
return (FALSE);
}
tmp = 3.0 * x2 - d;
Sx[i] = x = x * (x2 - 3.0 * d) + Julia->Julia_Parm[X];
Sy[i] = y = y * tmp + Julia->Julia_Parm[Y];
Sz[i] = z = z * tmp + Julia->Julia_Parm[Z];
Sw[i] = w = w * tmp + Julia->Julia_Parm[T];
}
*Dist = Precision;
return (TRUE);
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* Pascal Massimino
*
* DESCRIPTION
*
* -
*
* CHANGES
*
* Dec 1994 : Creation.
*
******************************************************************************/
int D_Iteration_Julia(VECTOR point, FRACTAL *Julia, DBL *Dist)
{
int i, j;
DBL Norm, d;
DBL Exit_Value;
DBL x, y, z, w;
DBL xx, yy, zz, x2;
DBL Pow;
x = Sx[0] = point[X];
y = Sy[0] = point[Y];
z = Sz[0] = point[Z];
w = Sw[0] = (Julia->SliceDist
- Julia->Slice[X]*x
- Julia->Slice[Y]*y
- Julia->Slice[Z]*z)/Julia->Slice[T];
Exit_Value = Julia->Exit_Value;
for (i = 1; i <= Julia->n; i++)
{
d = y * y + z * z + w * w;
x2 = x * x;
if ((Norm = d + x2) > Exit_Value)
{
/* Distance estimator */
x = Sx[0];
y = Sy[0];
z = Sz[0];
w = Sw[0];
Pow = 1.0 / 2.0;
for (j = 1; j < i; ++j)
{
xx = x * Sx[j] - y * Sy[j] - z * Sz[j] - w * Sw[j];
yy = x * Sy[j] + y * Sx[j] + w * Sz[j] - z * Sw[j];
zz = x * Sz[j] + z * Sx[j] + y * Sw[j] - w * Sy[j];
w = x * Sw[j] + w * Sx[j] + z * Sy[j] - y * Sz[j];
x = xx;
y = yy;
z = zz;
Pow /= 2.0;
}
*Dist = Pow * sqrt(Norm / (x * x + y * y + z * z + w * w)) * log(Norm);
return (FALSE);
}
x *= 2.0;
Sy[i] = y = x * y + Julia->Julia_Parm[Y];
Sz[i] = z = x * z + Julia->Julia_Parm[Z];
Sw[i] = w = x * w + Julia->Julia_Parm[T];
Sx[i] = x = x2 - d + Julia->Julia_Parm[X];
}
*Dist = Precision;
return (TRUE);
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* Pascal Massimino
*
* DESCRIPTION
*
* Provided the iterations sequence has been built, perform the computation of
* the Normal
*
* CHANGES
*
* Dec 1994 : Creation.
*
******************************************************************************/
void Normal_Calc_z3(VECTOR Result, int N_Max, FRACTAL *fractal)
{
DBL
n11 = 1.0, n12 = 0.0, n13 = 0.0, n14 = 0.0,
n21 = 0.0, n22 = 1.0, n23 = 0.0, n24 = 0.0,
n31 = 0.0, n32 = 0.0, n33 = 1.0, n34 = 0.0;
DBL x, y, z, w;
int i;
DBL tmp, dtmp, dtmp2, x2, x3, x4;
x = Sx[0];
y = Sy[0];
z = Sz[0];
w = Sw[0];
for (i = 1; i <= N_Max; i++)
{
tmp = y * y + z * z + w * w;
x2 = x * x;
x3 = x2 - tmp;
x4 = 3.0 * x2 - tmp;
Deriv_z3(n11, n12, n13, n14);
Deriv_z3(n21, n22, n23, n24);
Deriv_z3(n31, n32, n33, n34);
x = Sx[i];
y = Sy[i];
z = Sz[i];
w = Sw[i];
}
Result[X] = n11 * x + n12 * y + n13 * z + n14 * w;
Result[Y] = n21 * x + n22 * y + n23 * z + n24 * w;
Result[Z] = n31 * x + n32 * y + n33 * z + n34 * w;
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* Pascal Massimino
*
* DESCRIPTION
*
* -
*
* CHANGES
*
* Dec 1994 : Creation.
*
******************************************************************************/
void Normal_Calc_Julia(VECTOR Result, int N_Max, FRACTAL *fractal)
{
DBL
n11 = 1.0, n12 = 0.0, n13 = 0.0, n14 = 0.0,
n21 = 0.0, n22 = 1.0, n23 = 0.0, n24 = 0.0,
n31 = 0.0, n32 = 0.0, n33 = 1.0, n34 = 0.0;
DBL tmp;
DBL x, y, z, w;
int i;
x = Sx[0];
y = Sy[0];
z = Sz[0];
w = Sw[0];
for (i = 1; i <= N_Max; i++)
{
Deriv_z2(n11, n12, n13, n14);
Deriv_z2(n21, n22, n23, n24);
Deriv_z2(n31, n32, n33, n34);
x = Sx[i];
y = Sy[i];
z = Sz[i];
w = Sw[i];
}
Result[X] = n11 * x + n12 * y + n13 * z + n14 * w;
Result[Y] = n21 * x + n22 * y + n23 * z + n24 * w;
Result[Z] = n31 * x + n32 * y + n33 * z + n34 * w;
}
/*****************************************************************************
*
* FUNCTION
*
* INPUT
*
* OUTPUT
*
* RETURNS
*
* AUTHOR
*
* Pascal Massimino
*
* DESCRIPTION
*
* -
*
* CHANGES
*
* Dec 1994 : Creation.
*
******************************************************************************/
int F_Bound_Julia(RAY *Ray, FRACTAL *Fractal, DBL *Depth_Min, DBL *Depth_Max)
{
return (Intersect_Sphere(Ray, Fractal->Center, Fractal->Radius_Squared, Depth_Min, Depth_Max));
}