4
\$\begingroup\$

I'm going to start with some background, so jump to my question at the bottom for the TLDR version.

Problem:

In a Japanese 4gamer article (english translation via Chev on Polycount) explaining some of the technology and design behind Guilty Gear Xrd (a highly-stylized, 2.5D, toon-shaded fighting game) they detail some of the challenges concerning the game's development. One of the challenges had to do with the use of an orthographic 2D collision detection system on top of 3D character models that were rendered in perspective. In short, rendering character models through a perspective projection would naturally result in the characters looking wider towards the edges of the camera. As such, at various points on the screen the visual representation of the characters would fail to accurately represent their 'hitboxes' and 'hurtboxes'.

Example 1: Models using perspective projection. Character models rendered with a perspective projection.

The character model for Player 2 (orange) more closely matches his collision data because of his location towards the center of the screen.

Example 2: Models using orthographic projection. Character models rendered with an orthographic projection.

Using an orthographic projection, characters are accurately aligned with their collision data regardless of position. However, the desired visual effects of perspective are lost.

Their Solution:

The developers at Arc System Works solved this issues by creating a 'partial perspective' projection - a non-uniform mixture of perspective and orthographic (maybe parallel is more accurate) projections. On the horizontal axis, the camera's projection is said to be a '70% orthographic and 30% perspective' hybrid. On the vertical axis, the projection remains 100% perspective.

Example 3: Models using 'hybrid' projection. enter image description here

Mixing perspective and orthographic horizontally allowed them to preserve collision alignment and visual spacing (an important aspect in competitive fighting games). At the same time, the 'fully perspective' projection on the vertical axis allowed them to achieve extra visual depth when the characters jump.

My Question:

How would one go about achieving this kind of non-uniform, semi-perspective, semi-parallel camera projection?

When I think about this, I can imagine a camera frustum with a wide vertical FoV and a somewhat more narrow (but not necessarily parallel) horizontal FoV. Is this the correct interpretation of what they're describing, or am I visualizing it incorrectly?

Typically how would you generate a projection/modelview matrix like this? Is there a way to ask libraries like OpenGL and Direct3D for non-uniform matrices like these, or is there some way to combine an orthographic matrix and a perspective matrix in a non-uniform way through matrix math?

\$\endgroup\$
  • \$\begingroup\$ This seems like treating a symptom instead of dealing with the real problem; that 2D hitboxes were used when 3D collision meshes would likely have been the wiser choice. \$\endgroup\$ – bcrist Nov 7 '14 at 10:29
  • 4
    \$\begingroup\$ @bcrist I think having fixed-size 2D hitboxes is a design decision, and it perfectly makes sense. You don't want gameplay metrics to change depending on where characters are positioned. \$\endgroup\$ – Laurent Couvidou Nov 7 '14 at 11:45
  • \$\begingroup\$ Going to agree with @laurent on that one. As a 2.5D game, the actual game logic is 2D while the visual representation is 3D. It makes little sense to change the logic to reflect the visualization - especially when you consider the lineage of the game and its roots as a 2D fighter. Regardless, that was the solution that they went with. \$\endgroup\$ – MrKatSwordfish Nov 8 '14 at 4:37
3
\$\begingroup\$

What you want is a curvilinear perspective projection matrix to correct for the perspective projection distortion.

aka barrel or pincushion projection: http://en.wikipedia.org/wiki/Curvilinear_perspective

Basically, you distort the image with a projection that is the opposite of the distortion you don't want so it all comes out straight in the end. Mathematically, you can set the distortion on each axis independently for different effects.

This is common in real-world compound optics. Think telescope.

Unfortunately, I do not know of a way to make OpenGL calculate these for you, although you can use the math in the Wikipedia article to generate your own projection matrix.

I don't believe you will be able to concatenate these matrices, so you'll need to render dual-pass. Render your standard perspective view to an off-screen texture the way you normally would. Then re-render your offscreen texture mapped to a quad to the viewport using the curvilinear perspective projection to correct for the edge-of-the-screen curvature. That should get you the effect you want.

Grid projected with barrel distortion:

distortion example

\$\endgroup\$
  • \$\begingroup\$ Thanks for the comment, @lisa, but I don't think this is actually the solution that I need. The main issue with a curvilinear perspective is that the it creates a warped 'fish eye' effect. The images in the OP are a bit misleading because the 3d assets in the background are warped strangely before they're exported. If you look at the vertical edges on the building in the background you'll see what I mean. So, I'm looking for something that still preserves the parallel nature of horizontal and vertical lines. Thanks though! :] \$\endgroup\$ – MrKatSwordfish Dec 1 '14 at 10:21
3
\$\begingroup\$

I suspect the method actually used doesn't actually rely on parallel projection and it only seems so through the approximation of the article writer and subsequent translation. The problem with bringing a parallel projection into this is you'll attenuate perspective, which is not what you may want. At any rate the method I describe here achieves the same desired effect, a consistent silhouette size no matter the on-screen position, to an extent that can be directed per object.

enter image description here

From top to bottom:

Standard perspective projection: All cubes have their vanishing point at the center of the screen

The manipulated perspective: Each cube has its vanishing point in the same place relative to the cube itself and each presents the same silhouette. The size change due to distance is unaffected.

more manipulation: All the cubes behave as if they were on the left.

It's done by shearing each object in relation to the camera, as seen in the following pic, so that each object "faces" the camera. The shear value to use to bring the vanishing point in the center of the object is the slope of the camera-object vector over the camera eye direction.

enter image description here

What follows assumes a camera looking horizontally and the perspective manipulation being in the horizontal plane but more general cases should work.

Consider three points on the horizontal plane (assuming a strictly horizontal correction), the character position, the camera position, and P being the projection of the character position on the camera eye vector (in the case of a fighting game, usually orthogonal to the gameplay plane).

The shear value is (length of P to Character) / (length of Camera to P). The sign should be adjusted depending on which side of the camera the object is. The shear matrix is constructed by taking an identity matrix and changing the third row's first column value to the shear value. Then you just use shearMatrix * worldMatrix to position the object in the world rather than just worldMatrix.

The whole process can be applied independently for the vertical axis.

Note that you can weigh that shear value to attenuate how much it brings the vanishing point towards the object's center, and add an offset to it (like in the third cubes picture).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.