Just in case my other comment got dropped - hi! I independently rendered a similar toroidal wormhole around two weeks(!) after you posted this. I believed I was the first to do it - evidently not! I ended up using a much less elegant construction that doesn't glue to a space with nice geodesics - that's a really good idea on your part for making it performant! Mine is very slow in comparison. I would greatly appreciate it if you wrote up the finer details of this construction somewhere - it really is a neat approach.
Thank you! Very cool hearing someone else trying to render a toroidal wormhole! I would be very interested to hear about your approach too. When a ray touches the torus, we compute on the point of contact three orthonormal vectors. One of them is the normal vector of the torus at this point. The other two are the directions to circle around the torus. They must be chosen in a consistent manner for the whole surface of the torus. For the interior of the torus, I used the Poincaré half-plane model in three dimensions (hyperbolic geometry). Take the plane z = c and put a rectangular lattice on it. When we reduce modulo this lattice, the plane becomes a flat torus. So we need a map from the torus in R^3 to the rectangle (0,0,c), (a,0,c), (0,b,c), (a,b,c). Using the three orthonormal vectors described above, we can find the direction of the ray in the Poincaré model and vice versa. Hope this helps, I can clarify further.
@@falkush I typed up a rather long reply, and then YT completely ate my comment. It seems like I can't mention the site-that-hosts-code-repositories at all, even without a URL. At any rate, you can find my repos at [that site]/KaarelKurik, the relevant ones being "wormhole" and "CPUWormhole", the latter of which explains my overall approach. Roughly, I have a bunch of ambient spaces, and I connect pairs of them with (coordinate) toroidal throats. This means I have a transition function between regions that lie between two toroidal surfaces, which swap the outside and inside. In my case I do this using an affine function of the fiber parameter, given a simple fibration each region (I believe the fibers are parallel with the gradient of the outer torus' sdf). Each throat comes with two charts, one for each end, and I take some partition-of-unity subordinate to this cover, and use it to interpolate the inverse metrics of the respective ambient spaces. (You can also use a non-partition-of-unity, as long as it's smooth enough, sums to 1 outside the throat, has the right support, has everywhere-nonnegative components and its sum is everywhere-positive. Maybe this is more strict than necessary.) This interpolation is then the inverse metric of the true geometry, and we use it to set up the geodesic equation in the Hamiltonian form, and solve this using whatever integrator we like. (My CPU version uses a funny symplectic integrator - I recommend checking out the paper in the README.) --- Your explanation is pretty clear, thanks! One gap I still have here is, why use hyperbolic space, as opposed to (T^2 x R)? Does it not glue as nicely/require some discontinuity that you can avoid with the hyperbolic approach?
It's a glitch that happens when the torus self-intersects, mostly because I did not design the code to handle such situations. It appears black because most rays get stuck in the torus for too long, it would take too much time to compute their final destination, if they ever get out. I also think the patterns we see at the end comes from the quartic polynomial solver which fails at some special values. I thought it looked interesting so I included it in the video. Thank you for your interest!