## Fun with Toratopes & POVray

Discussion of shapes with curves and holes in various dimensions.

### Fun with Toratopes & POVray

Thanks to Plasmath for giving me a little intro on the code, and thanks to the years of my mind saying "nope" to povray to the point where it eventually said "yep" , I've been very busy lately learning and playing with povray. Part of the problem wasn't even the code, it was my computer constantly crashing to the lovely BSOD. After much searching, I think I found the solution, which is how I made this torisphere animation. I don't know for sure if this is working, but I greatly increased the virtual memory page file size mins and maxes. Still have more tests to run, though. The bright phong finish combined with nested transparent surfaces combined with anti-aliasing really put my new pc through the paces. Plus, I found the super useful rotation controls for the camera, which greatly helps me get the best position for the shot.

So, here is the latest. Getting the large yellow reflection on the purple pigment was not the easiest task. Also, keeping it purple was tricky since the yellow light changes the color. So, I tried many combos, and found using a little emission with phong and phong_size helped a lot.

The Torisphere:

((III)I) - toratope symbol
((xyz)w) - variables
((xyz-2)w-1) - vars w/params

• Implicit equation:

(sqrt(x^2 + y^2 + z^2) -2)^2 + w^2 = 1

• POVray isosurface function:

pow((sqrt(pow(x,2) + pow(y,2) + pow(z,2)) -2),2) + pow(w,2) -1

• Set up rotation + translation on ZW plane:

z = (z*cos(b)-a*sin(b))
w = (z*sin(b)+a*cos(b))

• Gives:

pow((sqrt(pow(x,2) + pow(y,2) + pow((z*cos(b)-a*sin(b)),2)) -2),2) + pow((z*sin(b)+a*cos(b)),2) -0.5

**reducing the minor radius to 0.5 makes the torisphere's hole easier to grasp, and the topo changes easier to see during rotation

• Torisphere ZW rotation Source code:

Command Line (or place in your ini file):

+q7 +a0.2

Code: Select all
`#version 3.7;global_settings { assumed_gamma 1.0 adc_bailout 0.01 }#include "colors.inc" sky_sphere{pigment{ SkyBlue }}camera {location <8,0,0>look_at <0,0,0>rotate  <-90,25,0>  right x*image_width/image_height}     light_source {<-30,-100,-100> color Goldenrod }   #declare a = 0; #declare b = clock;   isosurface {  function {pow((sqrt(pow(x,2) + pow(y,2) + pow((z*cos(b)-a*sin(b)),2)) -2),2) + pow((z*sin(b)+a*cos(b)),2) -0.5 }  max_gradient 12                                                                 contained_by{ box { -5 , 5 } }  pigment { Orchid transmit 0.5 }     finish {        emission .2        ambient .0        diffuse albedo .7        specular .0          roughness 0.1        reflection {Yellow 0}         phong .7          phong_size 5        metallic 0        brilliance 1}        }`

animation .ini file:

Code: Select all
`+W640+H480Input_File_Name=torisphere.povInitial_Frame=1Final_Frame=100Initial_Clock=0Final_Clock=1.57`

It is by will alone, I set my donuts in motion
ICN5D
Pentonian

Posts: 1133
Joined: Mon Jul 28, 2008 4:25 am
Location: Orlando, FL

### Re: Fun with Toratopes & POVray

Okay, now this time I really really tested the crap out of povray, by throwing one of the nasty toratopes at it. And it passed, with flying donuts. These are the trippy donut morphing visuals that I've been seeing over the last 8 years, in blocky low resolution, always itching to make an animation in hi-res. But, the calcplot way is extra tedious, by manually taking the screencap for every frame. As I've said, an automatic screencap feature has been a dream for a long time.

Now comes in povray.

These two functions below are what you can use to generate any combination of n-torus shapes, starting from a circle.

The translate - then - revolve into n+1 dimensions function; aka "donut making function" :

(sqrt(pow(x,2) + pow(x,2)) -2)

A circle:

pow(x,2) + pow(y,2) -1

• Toratope Symbol:
a gradual construction of a 9D toratope, starting from the circle (II)

(II)
((II)I)
(((II)I)I)
((((II)I)I)I)
(((((II)I)I)I)I)
(((((II)I)(II))I)I)
(((((II)I)(II))I)(II))
(((((II)I)(II))I)((II)I))
(((((xy)z)(wv))u)((ts)r)) - variables

(1)
((2)1)
(((4)2)1)
((((8)4)2)1)
(((((16)8)4)2)1)
(((((16)8)(8)4)2)1)
(((((16)8)(8)4)2)(2)1)
(((((16)8)(8)4)2)((4)2)1)

(((((xy-16)z-8)(wv-8)-4)u-2)((ts-4)r-2)1) - vars w/params

• Using the above notation as a guide, now generate the isosurface according to the sequence:

pow(x,2) + pow(y,2) -1

pow((sqrt(pow(x,2) + pow(x,2)) -2),2) + pow(y,2) -1

pow((sqrt(pow((sqrt(pow(x,2) + pow(x,2)) -4),2) + pow(x,2)) -2),2) + pow(y,2) -1

pow((sqrt(pow((sqrt(pow((sqrt(pow(x,2) + pow(x,2)) -8),2) + pow(x,2)) -4),2) + pow(x,2)) -2),2) + pow(y,2) -1

pow((sqrt(pow((sqrt(pow((sqrt(pow((sqrt(pow(x,2) + pow(x,2)) -16),2) + pow(x,2)) -8),2) + pow(x,2)) -4),2) + pow(x,2)) -2),2) + pow(y,2) -1

pow((sqrt(pow((sqrt(pow((sqrt(pow((sqrt(pow(x,2) + pow(x,2)) -16),2) + pow(x,2)) -8),2) + pow((sqrt(pow(x,2) + pow(x,2)) -8),2)) -4),2) + pow(x,2)) -2),2) + pow(y,2) -1

pow((sqrt(pow((sqrt(pow((sqrt(pow((sqrt(pow(x,2) + pow(x,2)) -16),2) + pow(x,2)) -8),2) + pow((sqrt(pow(x,2) + pow(x,2)) -8),2)) -4),2) + pow(x,2)) -2),2) + pow((sqrt(pow(x,2) + pow(x,2)) -2),2) -1

pow((sqrt(pow((sqrt(pow((sqrt(pow((sqrt(pow(x,2) + pow(x,2)) -16),2) + pow(x,2)) -8),2) + pow((sqrt(pow(x,2) + pow(x,2)) -8),2)) -4),2) + pow(x,2)) -2),2) + pow((sqrt(pow((sqrt(pow(x,2) + pow(x,2)) -4),2) + pow(x,2)) -2),2) -1

• Set the variables:

(((((xy-16)z-8)(wv-8)-4)u-2)((ts-4)r-2)1)

pow((sqrt(pow((sqrt(pow((sqrt(pow((sqrt(pow(x,2) + pow(y,2)) -16),2) + pow(z,2)) -8),2) + pow((sqrt(pow(w,2) + pow(v,2)) -8),2)) -4),2) + pow(u,2)) -2),2) + pow((sqrt(pow((sqrt(pow(t,2) + pow(s,2)) -4),2) + pow(r,2)) -2),2) -1

The trace array, lowest dimensional real solution (in fewest variables) :

(((((x))(y)))((z))) : 4x2x4,[r1-2]

pow((sqrt(pow((sqrt(pow((sqrt(pow((sqrt(pow(x,2) + pow(0,2)) -16),2) + pow(0,2)) -8),2) + pow((sqrt(pow(y,2) + pow(0,2)) -8),2)) -4),2) + pow(0,2)) -2),2) + pow((sqrt(pow((sqrt(pow(z,2) + pow(0,2)) -4),2) + pow(0,2)) -2),2) -1

Rotation functions:

• Single Rotate

X = (x*cos(a))
x = (x*sin(a))
--
Y = (y*cos(a))
y = (y*sin(a))
--
Z = (z*cos(a))
z = (z*sin(a))

• Double rotate + single translate

x = (x*cos(b)-a*sin(b))
y = (y*cos(c)-(x*sin(b)+a*cos(b))*sin(c))
[xy] = (y*sin(c)+(x*sin(b)+a*cos(b))*cos(c))

• Triple rotate + single translate

x = (x*cos(b)-a*sin(b))
y = (y*cos(c)-(x*sin(b)+a*cos(b))*sin(c))
z = (z*cos(d)-(y*sin(c)+(x*sin(b)+a*cos(b))*cos(c))*sin(d))
[xyz] = (z*sin(d)+(y*sin(c)+(x*sin(b)+a*cos(b))*cos(c))*cos(d))

• 15 distinct Real -> Complex rotations from the 4x2x4,[r1-2] trace array
There are no real -> real rotations for this shape. All rotations place our 3-plane inside a hole, where the shape is circling around it. This makes the cluster disappear in cool looking ways. Which is the only reason anyone needs, really.

(((((X)x)(I)))((I)))
pow((sqrt(pow((sqrt(pow((sqrt(pow((sqrt(pow((x*cos(a)),2) + pow(0,2)) -16),2) + pow((x*sin(a)),2)) -8),2) + pow((sqrt(pow(y,2) + pow(0,2)) -8),2)) -4),2) + pow(0,2)) -2),2) + pow((sqrt(pow((sqrt(pow(z,2) + pow(0,2)) -4),2) + pow(0,2)) -2),2) -0.75

(((((X))(Ix)))((I)))
pow((sqrt(pow((sqrt(pow((sqrt(pow((sqrt(pow((x*cos(a)),2) + pow(0,2)) -16),2) + pow(0,2)) -8),2) + pow((sqrt(pow(y,2) + pow((x*sin(a)),2)) -8),2)) -4),2) + pow(0,2)) -2),2) + pow((sqrt(pow((sqrt(pow(z,2) + pow(0,2)) -4),2) + pow(0,2)) -2),2) -0.75

(((((X))(I))x)((I)))
pow((sqrt(pow((sqrt(pow((sqrt(pow((sqrt(pow((x*cos(a)),2) + pow(0,2)) -16),2) + pow(0,2)) -8),2) + pow((sqrt(pow(y,2) + pow(0,2)) -8),2)) -4),2) + pow((x*sin(a)),2)) -2),2) + pow((sqrt(pow((sqrt(pow(z,2) + pow(0,2)) -4),2) + pow(0,2)) -2),2) -0.75

(((((X))(I)))((Ix)))
pow((sqrt(pow((sqrt(pow((sqrt(pow((sqrt(pow((x*cos(a)),2) + pow(0,2)) -16),2) + pow(0,2)) -8),2) + pow((sqrt(pow(y,2) + pow(0,2)) -8),2)) -4),2) + pow(0,2)) -2),2) + pow((sqrt(pow((sqrt(pow(z,2) + pow((x*sin(a)),2)) -4),2) + pow(0,2)) -2),2) -0.75

(((((X))(I)))((I)x))
pow((sqrt(pow((sqrt(pow((sqrt(pow((sqrt(pow((x*cos(a)),2) + pow(0,2)) -16),2) + pow(0,2)) -8),2) + pow((sqrt(pow(y,2) + pow(0,2)) -8),2)) -4),2) + pow(0,2)) -2),2) + pow((sqrt(pow((sqrt(pow(z,2) + pow(0,2)) -4),2) + pow((x*sin(a)),2)) -2),2) -0.75

---

(((((Iy))(Y)))((I)))
pow((sqrt(pow((sqrt(pow((sqrt(pow((sqrt(pow(x,2) + pow((y*sin(a)),2)) -16),2) + pow(0,2)) -8),2) + pow((sqrt(pow((y*cos(a)),2) + pow(0,2)) -8),2)) -4),2) + pow(0,2)) -2),2) + pow((sqrt(pow((sqrt(pow(z,2) + pow(0,2)) -4),2) + pow(0,2)) -2),2) -0.75

(((((I)y)(Y)))((I)))
pow((sqrt(pow((sqrt(pow((sqrt(pow((sqrt(pow(x,2) + pow(0,2)) -16),2) + pow((y*sin(a)),2)) -8),2) + pow((sqrt(pow((y*cos(a)),2) + pow(0,2)) -8),2)) -4),2) + pow(0,2)) -2),2) + pow((sqrt(pow((sqrt(pow(z,2) + pow(0,2)) -4),2) + pow(0,2)) -2),2) -0.75

(((((I))(Y))y)((I)))
pow((sqrt(pow((sqrt(pow((sqrt(pow((sqrt(pow(x,2) + pow(0,2)) -16),2) + pow(0,2)) -8),2) + pow((sqrt(pow((y*cos(a)),2) + pow(0,2)) -8),2)) -4),2) + pow((y*sin(a)),2)) -2),2) + pow((sqrt(pow((sqrt(pow(z,2) + pow(0,2)) -4),2) + pow(0,2)) -2),2) -0.75

(((((I))(Y)))((Iy)))
pow((sqrt(pow((sqrt(pow((sqrt(pow((sqrt(pow(x,2) + pow(0,2)) -16),2) + pow(0,2)) -8),2) + pow((sqrt(pow((y*cos(a)),2) + pow(0,2)) -8),2)) -4),2) + pow(0,2)) -2),2) + pow((sqrt(pow((sqrt(pow(z,2) + pow((y*sin(a)),2)) -4),2) + pow(0,2)) -2),2) -0.75

(((((I))(Y)))((I)y))
pow((sqrt(pow((sqrt(pow((sqrt(pow((sqrt(pow(x,2) + pow(0,2)) -16),2) + pow(0,2)) -8),2) + pow((sqrt(pow((y*cos(a)),2) + pow(0,2)) -8),2)) -4),2) + pow(0,2)) -2),2) + pow((sqrt(pow((sqrt(pow(z,2) + pow(0,2)) -4),2) + pow((y*sin(a)),2)) -2),2) -0.75

---

(((((Iz))(I)))((Z)))
pow((sqrt(pow((sqrt(pow((sqrt(pow((sqrt(pow(x,2) + pow((z*sin(a)),2)) -16),2) + pow(0,2)) -8),2) + pow((sqrt(pow(y,2) + pow(0,2)) -8),2)) -4),2) + pow(0,2)) -2),2) + pow((sqrt(pow((sqrt(pow((z*cos(a)),2) + pow(0,2)) -4),2) + pow(0,2)) -2),2) -0.75

(((((I)z)(I)))((Z)))
pow((sqrt(pow((sqrt(pow((sqrt(pow((sqrt(pow(x,2) + pow(0,2)) -16),2) + pow((z*sin(a)),2)) -8),2) + pow((sqrt(pow(y,2) + pow(0,2)) -8),2)) -4),2) + pow(0,2)) -2),2) + pow((sqrt(pow((sqrt(pow((z*cos(a)),2) + pow(0,2)) -4),2) + pow(0,2)) -2),2) -0.75

(((((I))(Iz)))((Z)))
pow((sqrt(pow((sqrt(pow((sqrt(pow((sqrt(pow(x,2) + pow(0,2)) -16),2) + pow(0,2)) -8),2) + pow((sqrt(pow(y,2) + pow((z*sin(a)),2)) -8),2)) -4),2) + pow(0,2)) -2),2) + pow((sqrt(pow((sqrt(pow((z*cos(a)),2) + pow(0,2)) -4),2) + pow(0,2)) -2),2) -0.75

(((((I))(I))z)((Z)))
pow((sqrt(pow((sqrt(pow((sqrt(pow((sqrt(pow(x,2) + pow(0,2)) -16),2) + pow(0,2)) -8),2) + pow((sqrt(pow(y,2) + pow(0,2)) -8),2)) -4),2) + pow((z*sin(a)),2)) -2),2) + pow((sqrt(pow((sqrt(pow((z*cos(a)),2) + pow(0,2)) -4),2) + pow(0,2)) -2),2) -0.75

(((((I))(I)))((Z)z))
left as an exercise for the reader

• A few double rotate + single translate params

(((((X))(Y)))((I)[xy]))
pow((sqrt(pow((sqrt(pow((sqrt(pow((sqrt(pow((x*cos(b)-a*sin(b)),2) + pow(0,2)) -16),2) + pow(0,2)) -8),2) + pow((sqrt(pow((y*cos(c)-(x*sin(b)+a*cos(b))*sin(c)),2) + pow(0,2)) -8),2)) -4),2) + pow(0,2)) -2),2) + pow((sqrt(pow((sqrt(pow(z,2) + pow(0,2)) -4),2) + pow((y*sin(c)+(x*sin(b)+a*cos(b))*cos(c)),2)) -2),2) -0.75

(((((X))(Y))[xy])((I)))
pow((sqrt(pow((sqrt(pow((sqrt(pow((sqrt(pow((x*cos(b)-a*sin(b)),2) + pow(0,2)) -16),2) + pow(0,2)) -8),2) + pow((sqrt(pow((y*cos(c)-(x*sin(b)+a*cos(b))*sin(c)),2) + pow(0,2)) -8),2)) -4),2) + pow((y*sin(c)+(x*sin(b)+a*cos(b))*cos(c)),2)) -2),2) + pow((sqrt(pow((sqrt(pow(z,2) + pow(0,2)) -4),2) + pow(0,2)) -2),2) -0.75

(((((X))(I))[xz])((Z)))
pow((sqrt(pow((sqrt(pow((sqrt(pow((sqrt(pow((x*cos(c)-(z*sin(b)+a*cos(b))*sin(c)),2) + pow(0,2)) -16),2) + pow(0,2)) -8),2) + pow((sqrt(pow(y,2) + pow(0,2)) -8),2)) -4),2) + pow((x*sin(c)+(z*sin(b)+a*cos(b))*cos(c)),2)) -2),2) + pow((sqrt(pow((sqrt(pow((z*cos(b)-a*sin(b)),2) + pow(0,2)) -4),2) + pow(0,2)) -2),2) -0.75

• A few triple rotate + single translate
These produce some of the wildest and most awesome donut morphing visuals ever. Best way to slice super high-d toratopes, for sure. Just turn up your virtual memory page file cache.

(((((X)[xyz])(Y)))((Z)))
pow((sqrt(pow((sqrt(pow((sqrt(pow((sqrt(pow((x*cos(b)-a*sin(b)),2) + pow(0,2)) -16),2) + pow((z*sin(d)+(y*sin(c)+(x*sin(b)+a*cos(b))*cos(c))*cos(d)),2)) -8),2) + pow((sqrt(pow((y*cos(c)-(x*sin(b)+a*cos(b))*sin(c)),2) + pow(0,2)) -8),2)) -4),2) + pow(0,2)) -2),2) + pow((sqrt(pow((sqrt(pow((z*cos(d)-(y*sin(c)+(x*sin(b)+a*cos(b))*cos(c))*sin(d)),2) + pow(0,2)) -4),2) + pow(0,2)) -2),2) -0.75

(((((X))(Y))[xyz])((Z)))
pow((sqrt(pow((sqrt(pow((sqrt(pow((sqrt(pow((x*cos(b)-a*sin(b)),2) + pow(0,2)) -16),2) + pow(0,2)) -8),2) + pow((sqrt(pow((y*cos(c)-(x*sin(b)+a*cos(b))*sin(c)),2) + pow(0,2)) -8),2)) -4),2) + pow((z*sin(d)+(y*sin(c)+(x*sin(b)+a*cos(b))*cos(c))*cos(d)),2)) -2),2) + pow((sqrt(pow((sqrt(pow((z*cos(d)-(y*sin(c)+(x*sin(b)+a*cos(b))*cos(c))*sin(d)),2) + pow(0,2)) -4),2) + pow(0,2)) -2),2) -0.75

(((((X))(Y)))((Z)[xyz]))
pow((sqrt(pow((sqrt(pow((sqrt(pow((sqrt(pow((x*cos(b)-a*sin(b)),2) + pow(0,2)) -16),2) + pow(0,2)) -8),2) + pow((sqrt(pow((y*cos(c)-(x*sin(b)+a*cos(b))*sin(c)),2) + pow(0,2)) -8),2)) -4),2) + pow(0,2)) -2),2) + pow((sqrt(pow((sqrt(pow((z*cos(d)-(y*sin(c)+(x*sin(b)+a*cos(b))*cos(c))*sin(d)),2) + pow(0,2)) -4),2) + pow((z*sin(d)+(y*sin(c)+(x*sin(b)+a*cos(b))*cos(c))*cos(d)),2)) -2),2) -0.75

• 9D toratope source code: (has the function (((((X)[xyz])(Y)))((Z))) in it, but you can use any of them on this post)

Code: Select all
`#version 3.7;global_settings { assumed_gamma 1.0 }#include "colors.inc" sky_sphere{pigment{ SkyBlue }}camera {location <70,0,0>look_at <0,-3,-3>rotate  <90, -40,-50>  right x*image_width/image_height}     light_source {<100,-100,50> color White shadowless}   #declare a = 0;#declare b = 0;#declare c = 0;#declare d = 0;   isosurface {  function {pow((sqrt(pow((sqrt(pow((sqrt(pow((sqrt(pow((x*cos(b)-a*sin(b)),2) + pow(0,2)) -16),2) + pow((z*sin(d)+(y*sin(c)+(x*sin(b)+a*cos(b))*cos(c))*cos(d)),2)) -8),2) + pow((sqrt(pow((y*cos(c)-(x*sin(b)+a*cos(b))*sin(c)),2) + pow(0,2)) -8),2)) -4),2) + pow(0,2)) -2),2) + pow((sqrt(pow((sqrt(pow((z*cos(d)-(y*sin(c)+(x*sin(b)+a*cos(b))*cos(c))*sin(d)),2) + pow(0,2)) -4),2) + pow(0,2)) -2),2) -0.75 }  max_gradient 70                                                                 contained_by{ box { -40 , 40 } }  pigment { Orange transmit 0 }     finish {        emission 0.0        ambient .1        diffuse .9        specular .2         reflection 0        brilliance 1}        }`

Animations

• Single rotation from Real -> Complex solution

• Double tilted translation
You'll have to reposition the camera a little to get a better view in some of these.

• Triple tilted translation
You'll have to reposition the camera a little to get a better view in some of these.

It is by will alone, I set my donuts in motion
ICN5D
Pentonian

Posts: 1133
Joined: Mon Jul 28, 2008 4:25 am
Location: Orlando, FL

### Re: Fun with Toratopes & POVray

This all looks really great!
I'm currently working on some Python code that will automatically generate povray code given some toratopic notation, hopefully then images can be made much easier! I should be done pretty soon with it.
Plasmath
Dionian

Posts: 33
Joined: Mon Feb 08, 2021 10:57 pm

### Re: Fun with Toratopes & POVray

Very nice. Thanks for sharing.

I have some POV-Ray animations in my youtube channel. They are mainly based on your animations. But I only took the algebraic isosurfaces, because they are highly faster rendered with POV-Ray.
_stla_
Mononian

Posts: 6
Joined: Wed Jun 01, 2022 1:55 pm

### Re: Fun with Toratopes & POVray

_stla_ wrote:I have some POV-Ray animations in my youtube channel. They are mainly based on your animations.

Hey there, yes I noticed that. You've re-created several of my animations, at least the ones I provided an equation for. I figured someone might get a kick out of that one day! You'll have to show me how you did the python code, since I was considering that program before povray. I see it handles the new mantis equation derived by mr e-man, which is impressive.

Also, don't forget to check out the double and triple rotations of a 7D toratope : https://imgur.com/gallery/62TFe
It is by will alone, I set my donuts in motion
ICN5D
Pentonian

Posts: 1133
Joined: Mon Jul 28, 2008 4:25 am
Location: Orlando, FL

### Re: Fun with Toratopes & POVray

Hi ICN5D,

Thanks for the link, very nice.

Almost all animation on my youtube channel are accompanied with a link to the code, in the comments of the video. I use the PyVista library in Python. It easily allows to plot an isosurface. There's no shadow as we have with POV-Ray though.
_stla_
Mononian

Posts: 6
Joined: Wed Jun 01, 2022 1:55 pm

### Re: Fun with Toratopes & POVray

By the way this site provides the following implicit equation of the torisphere:

(sqrt(x^2 + y^2 + z^2) -2)^2 + w^2 = 1

The torisphere surely admits an algebraic implicit equation derived from the non-algebraic above one, similary to the 3D torus. It would be worth to note it.

Torus, non algebraic:

(sqrt(x^2 + y^2) - R^2)^2 + z^2 = r^2

Algebraic (i.e. polynomial):

(x^2 + y^2 + z^2 + R^2 - r^2)^2 = 4 * R^2 * (x^2 + y^2)
_stla_
Mononian

Posts: 6
Joined: Wed Jun 01, 2022 1:55 pm