# Single point perspective tunnel movement function

Imagine you are in a tunnel which is a perfect cylinder placed horizontally. The tunnel is formed by an infinite number of segments with same girth (4 meters diameter) and a fixed length of 20 meters. Your point of view is in the center of the cylinder section. You are travelling through the tunnel with a constant speed, 5 m/s. In between the segments there's a distinctive groove that is visible to you, lying in a plane that is perpendicular to your viewing direction vector, your travelling direction vector and the tunnel wall.

The only way that you can perceive the act of travelling through the tunnel is by observing the grooves in between the segments, that form concentric circles that are constantly growing in diameter until they surpass your viewing area.

I need to represent this motion on a 2D medium, the screen.

What I fail to accomplish is applying the correct "speed" to the circles. I feel that the best approach is to consider that: the closer the circles get, the faster they should grow in diameter. I am trying to find a function that would work well in the range [0;1] since I'm providing a ratio where 1 is the farthest possible position for the circle to be visible and 0 is the camera position. I guess function range doesn't matter since it can be adapted to [0;1] and it only needs to work for positive values.

I don't require a mathematically accurate solution I simply require something close enough to the look and feel of a moving tunnel. I tried applying y=x*x*x*x; but the curve of the function is too early (somewhere around x=0.5). I need something that would be almost linear in the range [0;0.5] and with a significant curve in the range (0.5,1].

Thanks to anyone who took the time to go through this.

• A completely-detailed, well worded question :) – Mark K Cowan May 6 '14 at 12:01

Model it using the perspective transform.

Projected distance r' between two points which are separated by distance $r$ in a plane normal to the view axis is proportional to the reciprocal of their plane's distance $d$ from the viewer.

For the circle, this gives:

$r^\prime(r, d) = k \frac{r}{d}$

Where k related to the FoV angle of the perspective view.

Take one point to be a circles centre and the other to be a point on the circumference, and $r^\prime$ gives the projected radius of a circle with radius $r$ at distance d viewed with a perspective FoV related to $k$ (by the cotangent I think, but check it yourself as I'm unsure). $k$ is also linearly related to the viewport size.

For radius 2 (diameter 4), velocity 5/second and circle inter-plane distance 20, this gives circles of projected radius:

$r^\prime_i = k \frac{2}{20i - 5t}\\ 20i - 5t > 0, i.e: i > \frac{t}{4}$

Render from $i_{min} = 1 + floor(\frac{t}{4})$ to $i_{max} = i_{min} + depth$, where increasing depth makes the tunnel appear longer, but decreases performance.

Use the inverse square law to set the intensity of the ring colour for each ring, based on its distance from the viewer. Optionally, add a cosine law too to simulate light scattering.

• A great and thorough explanation. Thank you! I implemented this logic and it works like a charm. – Dean Panayotov May 5 '14 at 23:39
• For the k value, look at the projection matrix that OpenGL uses for gluPerspective. How well did my lighting approximation work? Did you try the cosine law at all? I'm curious now to see how it looks :) if you want the tunnel to bend like some weird wormhole, i can suggest things for that too :) – Mark K Cowan May 6 '14 at 11:57
• I'm surprised at the lack of mistakes, I typed that answer out on a smartphone! – Mark K Cowan May 10 '14 at 18:01
• github.com/battlesnake/html5-canvas-wormhole – Mark K Cowan May 10 '14 at 22:49