class REB_Hyperparaboloid(common.ulb:UserTransform) {
; 3D Hyperparaboloid shape to create 3D "saddles" <br>
public:
import "common.ulb"
; constructor
func REB_Hyperparaboloid(Generic pparent)
UserTransform.UserTransform(pparent)
endfunc
; call for each iterated point
complex func Iterate(complex pz)
UserTransform.Iterate(pz)
float tt = 0
float lambda = 0
float u = 0
float v = 0
float x = 0
float y = 0
float z = 0
; Construct a line from the current pixel on the screen through 3D space.
; The line is defined by (sx, sy, sz) + lambda * (dx, dy, dz) where
; lambda can be any real value > 0. So the line does not extend behind
; the screen.
float sx = -@transx
float sy = -@transy
float sz = -@transz
float dx = real(pz-#center+@hcen)*#magn*@hscale
float dy = imag(pz-#center+@hcen)*#magn*@hscale+4
float dz = 4
; Convert angles from degrees to radians.
float angx = (@rotx * #pi) / 180
float angy = (@roty * #pi) / 180
float angz = (@rotz * #pi) / 180
; Rotate the line according to the (rotx, roty, rotz) angle.
; Apply rotation around Z axis
tt = cos(angz) * sy - sin(angz) * sx
sx = cos(angz) * sx + sin(angz) * sy
sy = tt
tt = cos(angz) * dy - sin(angz) * dx
dx = cos(angz) * dx + sin(angz) * dy
dy = tt
; Apply rotation around Y axis
tt = cos(angy) * sx - sin(angy) * sz
sz = cos(angy) * sz + sin(angy) * sx
sx = tt
tt = cos(angy) * dx - sin(angy) * dz
dz = cos(angy) * dz + sin(angy) * dx
dx = tt
; Apply rotation around X axis
tt = cos(angx) * sz - sin(angx) * sy
sy = cos(angx) * sy + sin(angx) * sz
sz = tt
tt = cos(angx) * dz - sin(angx) * dy
dy = cos(angx) * dy + sin(angx) * dz
dz = tt
; Now compute the intersection of the line with the hyperparaboloid, and return
; the intersection point in #pixel (texture coordinates).
; This is the only shape-dependent part.
; Sphere shape (radius 0.5)
;
; This must be solved:
; [ sx ] [ dx ] [ x ]
; [ sy ] + lambda [ dy ] = [ y ]
; [ sz ] [ dz ] [ z ]
; and
; x^2 - y^2 = 10*z
float a = sqr(dx) - sqr(dy)
float b = 2 * sx * dx - 2 * sy * dy - 10*dz
float c = sqr(sx) - sqr(sy) - 10*sz
float d = sqr(b) - 4 * a * c
if d < 0
; No roots exist.
m_solid = true
else
; One or two roots: select smallest.
if a >= 0
lambda = (-b - sqrt(d)) / (2 * a)
else
lambda = (-b + sqrt(d)) / (2 * a)
endif
if lambda < 0
; Intersection point is behind the screen.
m_solid = true
else
x = sx + lambda * dx
y = sy + lambda * dy
z = sz + lambda * dz
if z == 0
if x > 0
u = 2
else
u = -2
endif
else
u = (4 / #pi) * atan(x / abs(z))
endif
v = (4 / #pi) * atan(y / sqrt(sqr(x) + sqr(z)))
endif
endif
pz = u + flip(v)
pz = @fraccenter + pz * exp(flip((@fracangle * #pi) / 180)) / @fracmagn
return pz
endfunc
protected:
default:
title = "Hyperparaboloid"
int param v_hyperparaboloid
caption = "Version (Hyperparaboloid)"
default = 100
hint = "This version parameter is used to detect when a change has been made to the formula that is incompatible with the previous version. When that happens, this field will reflect the old version number to alert you to the fact that an alternate rendering is being used."
visible = @v_hyperparaboloid < 100
endparam
param rotx
caption = "X rotation"
default = 0.0
hint = "Rotation around the x-axis, in degrees. The x-axis points to \
the right. To determine the direction in which the rotation will \
take place, hold up your left hand with your thumb pointing to \
the right. Your (curled) fingers now indicate the direction of \
positive X rotation."
endparam
param roty
caption = "Y rotation"
default = 0.0
hint = "Rotation around the y-axis, in degrees. The y-axis points \
upwards. To determine the direction in which the rotation will \
take place, hold up your left hand with your thumb pointing \
upwards. Your (curled) fingers now indicate the direction of \
positive Y rotation."
endparam
param rotz
caption = "Z rotation"
default = 270.0
hint = "Rotation around the z-axis, in degrees. The z-axis points into \
the screen. To determine the direction in which the rotation will \
take place, hold up your left hand with your thumb pointing into \
the screen. Your (curled) fingers now indicate the direction of \
positive Z rotation."
endparam
param transx
caption = "X Translation"
default = 0.0
hint = "Translation along the x-axis. The x-axis points to the right, \
so increasing this value will move the fractal to the right, too."
endparam
param transy
caption = "Y Translation"
default = -0.5
hint = "Translation along the y-axis. The y-axis points upwards, \
so increasing this value will move the fractal upwards, too."
endparam
param transz
caption = "Z Translation"
default = 2.0
hint = "Translation along the z-axis. The z-axis points into the screen, \
so increasing this value will move the fractal away."
endparam
param fraccenter
caption = "Fractal Center"
default = (0,0)
hint = "Center of the fractal image. Use here what you would \
normally enter in the Location tab."
endparam
param fracmagn
caption = "Fractal Magnification"
default = 1.0
hint = "Magnification of the fractal image. Use here what you would \
normally enter in the Location tab."
endparam
param fracangle
caption = "Fractal Rotation"
default = 0.0
hint = "Rotation angle (in degrees) of the fractal image. Use here \
what you would normally enter in the Location tab."
endparam
float param hscale
caption = "Hyperbolic scale"
default = 1.0
endparam
complex param hcen
caption = "Hyperbolic center"
default = (0,0)
endparam
}