360 degree 3d projection formula

A place for people with an interest in developing new shmups.
Post Reply
User avatar
louisg
Posts: 2897
Joined: Wed Jul 20, 2005 7:27 pm
Location: outer richmond
Contact:

360 degree 3d projection formula

Post by louisg »

Hey, this isn't really a shmup-related question, but this is the only dev board I really frequent.. so..:

I'm trying to come up with a good formula for projecting 360 degrees worth of points onto the screen. So, the end result would be a strip of graphic that you could pan around to get the impression of 3d (with some minor distortions and tweaks). Now, you can use the standard projection formula up to a 180 degrees horizontal FOV, but I believe it falls apart after that (or I'm not doing it right).

I did come up with a formula I think might work, but it's just a polar coordinates trick: x_screen = atan(y/x) (where x and y are 'top view' coordinates). Then the distance to that point would just be sqrt(x^2 + y^2). That'd place 0 degrees on the left-hand side of the strip and just-below-360-degrees on the far right hand side. The drawback is that it'd be slow.

But, I'd be interested in why it is that the standard 3d projection formula is failing me here if it's so mathematically consistent. Anyone know? I figure there must be some math nerds around here :)

EDIT: well, I guess it's because it's projecting onto a frustum. But still, is there a way to get a 360 degree mapping which isn't reliant on trigonometric functions?
Humans, think about what you have done
Ixmucane2
Posts: 776
Joined: Mon Jan 19, 2009 3:26 pm
Location: stuck at the continue prompt

Re: 360 degree 3d projection formula

Post by Ixmucane2 »

Your problem is far from clear. How do you expect to display "360 degrees" of anything in a normal 3D display? What do you mean by "standard projection"?
The closest reasonable thing I can think of is a cylindrical backdrop that wraps around a 3D environment, very far, normally including sky and horizon; it can be obviously approximated in practice with a texture-mapped prism, but any trigonometric functions can be precomputed (vertices are fixed).

As you more or less already found, (x,y,z) vertices of the vertices of such a prism skybox are (R*cos theta, R* sin theta, below ground) and (R*cos theta, R* sin theta, far up off camera) for theta varying from 0 to 2*PI and R large enough to have little parallax. The whole texture covers the whole cylinder; texture coordinates of each face are 0 to 1 along Z and k/N to (k+1)/N for face k of N along the other direction.
User avatar
louisg
Posts: 2897
Joined: Wed Jul 20, 2005 7:27 pm
Location: outer richmond
Contact:

Re: 360 degree 3d projection formula

Post by louisg »

Ixmucane2 wrote:Your problem is far from clear. How do you expect to display "360 degrees" of anything in a normal 3D display? What do you mean by "standard projection"?
The closest reasonable thing I can think of is a cylindrical backdrop that wraps around a 3D environment, very far, normally including sky and horizon; it can be obviously approximated in practice with a texture-mapped prism, but any trigonometric functions can be precomputed (vertices are fixed).

As you more or less already found, (x,y,z) vertices of the vertices of such a prism skybox are (R*cos theta, R* sin theta, below ground) and (R*cos theta, R* sin theta, far up off camera) for theta varying from 0 to 2*PI and R large enough to have little parallax. The whole texture covers the whole cylinder; texture coordinates of each face are 0 to 1 along Z and k/N to (k+1)/N for face k of N along the other direction.
OK, so to explain what I'm after more: the broad idea is to create a graphic that shows 360 degrees of a view as long strip of graphics. This strip could then be zoomed in on until it shows roughly a 90 degree FOV and panned around like a simple panoramic effect. Say that the graphic ends up being dimensions 2500x480. x=0 might map to x_angle=0 and x=2499 might map to x_angle=359 degrees. So, I guess what I really am after is cylindrical projection.

Oh, and when I used the not-very-scientific term standard projection, I mean 3d projection onto a frustum (ala x_screen = x_world*scale/z + screen_width/2).

Now, what you're suggesting is similar to a skybox, right? So, if I were to simulate a cylinder using a polygon, I would create a shape surrounding the viewpoint with N sides. I would take renders of the scene I want to map onto that shape at N/360 degree intervals, and map those on..?

It's also dawned on me that if I rendered a 360 degree view as a raycaster, I could just use a standard raycast effect and not correct for fisheye. That is, instead of shooting rays from (player_angle - 45_degrees) to (player_angle + 45_degrees), I'd just shoot rays from 0 to 360 degrees. The information contained in the resulting graphic I think would be exactly the same as a normal raycast, and all you'd have to do to make it look truly 3d again is to multiply each column by cos(angle) as you pan (!). I wonder if this means that any panoramic engine could be done by obtaining a 360 degree graphic (say a photo) with a certain amount of fisheyeing and then multiplying by cos(angle) for each column.
Humans, think about what you have done
User avatar
Keade
Posts: 385
Joined: Mon Jul 16, 2007 8:44 pm

Re: 360 degree 3d projection formula

Post by Keade »

PanQuake, a Quake sourceport, might be of relevant to your search. The author provides the source.
Ixmucane2
Posts: 776
Joined: Mon Jan 19, 2009 3:26 pm
Location: stuck at the continue prompt

Re: 360 degree 3d projection formula

Post by Ixmucane2 »

So you are trying to do the opposite? A semi-cylindrical "camera" showing an animated 3D scene unrolled to a long strip?

You might want to simply render stuff based on their polar coordinates: turning (x,y,z) into (r,theta,z), you can use theta directly as your horizontal screen coordinate and shrink world-space r and z with an ordinary perspective transformation: if R is the radius of the camera cylinder and Z the eye height you can project a point at (r,theta,z) to (theta,Z+(z-Z)*R/r) in the picture.
Near and far cylinders (not planes in this case) clip according to r, viewport sides clip according to theta and viewport top and bottom clip according to projected z. In other words, cross sections of the "frustum" retain their normal trapezoidal shape.
User avatar
louisg
Posts: 2897
Joined: Wed Jul 20, 2005 7:27 pm
Location: outer richmond
Contact:

Re: 360 degree 3d projection formula

Post by louisg »

Ixmucane2 wrote:So you are trying to do the opposite? A semi-cylindrical "camera" showing an animated 3D scene unrolled to a long strip?

You might want to simply render stuff based on their polar coordinates: turning (x,y,z) into (r,theta,z), you can use theta directly as your horizontal screen coordinate and shrink world-space r and z with an ordinary perspective transformation: if R is the radius of the camera cylinder and Z the eye height you can project a point at (r,theta,z) to (theta,Z+(z-Z)*R/r) in the picture.
Near and far cylinders (not planes in this case) clip according to r, viewport sides clip according to theta and viewport top and bottom clip according to projected z. In other words, cross sections of the "frustum" retain their normal trapezoidal shape.
Yeah, that's exactly what I want to do. My atan method above should be close but less fleshed out (I think)-- turning the rectangular coordinates into polar and mapping the angles onto the x of the display. I was after a way to do it without dropping trig functions/tables into the transforms, but I guess the only alternative is what panquake does (which looks like it takes N snapshots 360/N angles apart and glues them together).

Very cool.. thanks!
Humans, think about what you have done
Ixmucane2
Posts: 776
Joined: Mon Jan 19, 2009 3:26 pm
Location: stuck at the continue prompt

Re: 360 degree 3d projection formula

Post by Ixmucane2 »

Yes, approximating the cylinder with a prism is the only way to spare trigonometric functions. I look forward to seeing screenshots.
User avatar
louisg
Posts: 2897
Joined: Wed Jul 20, 2005 7:27 pm
Location: outer richmond
Contact:

Re: 360 degree 3d projection formula

Post by louisg »

OK, so here it is: http://www.gorenfeld.net/lou/Panoramic.tar.gz

It has my old voxel source (voxel.c) hotrodded to display 360 degrees, which is how I generated the 360-2.bmp that panorama.c uses. Both need Allegro (4?) to compile. Hitting left and right in panorama.c rotates, and space turns on and off the cosine distort which is supposed to correct for fisheye.

Now, it is pretty obviously distorted when correcting for fisheye. I figured that since each column of the screen is a different angle, that you should be able to correct like this: If you are standing perpendicularly in front of a wall, the correct distance to the wall is the angle in the center of your vision (0 degrees) to the wall. This is the side adjacent to the angle of the column. Now, the distance from your eye to the corner of your vision (say it's 45 degrees) is going to be measured as longer. This is the hypotenuse. However, the wall does not appear smaller on the sides of your vision-- it appears the same size as the center. Therefore, the amount of distortion is going to be:

cos(column_angle) = correct_distance/skewed_distance
or
cos(column_angle)*skewed_distance = correct_distance

Dividing by correct_distance (which is a z value) gives the amount to scale that column to correct for the fisheye. I'm not sure if I explained this well :)

But, with fisheye correction turned on, it looks a little better in the foreground but too obviously distorted in the background. Maybe pasting the distorted (corrected) mountains onto another backdrop would mask the distortion, as opposed to making everything one single static image.

EDIT: Also try with http://www.gorenfeld.net/lou/360-3.bmp .. this makes a good argument that the fisheye correction is OK
Humans, think about what you have done
Post Reply