Part VIII: Additional Tutorial: FP16



8. Additional tutorial: FP16
working with engine limitations
Author: bac9-flcl


This tutorial covers the issue that is present only in the late iterations of CryENGINE3. It is not mandatory if you're working with an early Educational release of this engine or with CryENGINE2.

8.1. Introduction

CryENGINE3 employs half-precision floating-point format (FP16) to store the coordinates of vertices in geometry. This gives better performance, but has serious drawbacks: obviously, in some cases, it lacks the precision necessary to represent a geometry properly. Distortions occur, especially in objects of large size with relatively small details, on curved surfaces, and in other complicated cases.

Let's take a look at how this works and how to squeeze the highest precision possible out of that format.

Easiest way to think of the vertex position format limitations is to imagine a 3-dimensional grid. Like this:


Image

Essentially, every intersection of that grid is one possible position that can be occupied by a vertex. Smallest possible step in any direction equals is a grid step size.


Image

Of course, actual range of values of FP16 is bigger. If I remember correctly, it allows 2048 or 1024 possible positions on each axis. So you should imagine a denser grid, closer to something like this:


Image

So, how does it work when your geometry is exported into the engine? Let's take a look at one example. Here is a curve that could have been a part of some complex big object, and a grid of possible values in relation to it:


Image

I think it will be easier to explain if I use 2d grid, hence no third axis, too much visual clutter. So, what will happen with the vertices of our curve? They will be moved to nearest possible position:


Image

Obviously, this isn't nice. Such distortions can often break detailed curves, turn edges with slight slopes into entirely parallel to one axis, or, even worse, merge several vertices into one point. So let's see if we can minimize that impact. We will use a simple flat component like this:


Image

One note before we proceed: everything I cover here is only relevant to the parent component in your object hierarchy, one that you will be exporting. Pivot position and other axes-related settings in sub-components don't matter, as CryENGINE3 exporter is seeing your model as a solid one-layer object, reading only the pivot from the highest component in the structure.

So, as you know, your SketchUp model has coordinate axes and a central point (pivot). Also, each and every component has it's own inner central point, and can even use it's own directional setup of axes. We are particularly interested in the pivot of the parent component, one you will be exporting into the engine. Open it for editing, and you will see this point, with axes intersecting in it:


Image

This is the default pivot position SketchUp creates in every component: corner of the bounding box. Now, what determines the grid precision is, first of all, the scale of your object. In this case, the dimensions are 2.6x2m:


Image

So the grid will be scaled to cover that 2.6x2m area? Unfortunately, no. The possible range of vertex positions has to cover both negative and positive values to an equal extent. So, actually, these are base dimensions: 2.6m both ways and 2m both ways:


Image

This way, your entire geometry is encompassed in the grid range, and the range is equal on both sides of zero. Looks like this:


Image

As you can see, it's a horrible waste: 3/4 or possible range is not employed to describe your geometry. And when we take 3d grid, it's even worse: 7/8 of range goes nowhere. 

But there is a very obvious solution to this: why can't we just move the pivot to a point that is equally distant from extreme points of an object from each axis? Like this:


Image
Image

Now we have equal 1.3m and 1.0m distances from the center point to each border. And here is how it will affect the grid of possible vertex positions:


Image

It's four times better (8x if we're talking about actual 3d)! To complete this example, let's take a look at how this object will change when nearest possible vertex positions will be used:


Image

8.2. Example

Now let's take a look at the real asset and at how can we do the same trick with it. Let's say we have a building. First we should determine the dimensions of the object - center points of these lines will help us to find the place where pivot should be situated. Drawing these lines should be easy:


Image 

Next, we'll need the midpoints of those lines.


Image

From them, we can draw the central point of the whole object:


Image

Here it is with non-hidden building model:


Image

Now all we need to do is just to move the pivot to that point. Open the parent component for editing, click on RMB anywhere in empty space, and choose the Change Axes context menu option:


Image

Carefully fix the axes on that point (don't mess their directions up):


Image

And we're done!


Zoom in (real dimensions: 600 x 600)Image

Now, compare how the grid would've looked without our intervention, and how it looks now:


Image
Image


8.3. Notes


  • Ideal pivot placement is not crucial, you won't lose much of the precision if you have a slight offset. It's just easier sometimes, as just drawing lines from dimensions midpoints saves you some time thinking.
  • If your object vertical dimensions are significantly lower than horizontal ones, you can place the pivot on the horizontal intersection below, without raising it up. Vertex precision on your vertical axis is high anyway, and you will save yourself some time in the editor, as you won't need to excavate your buildings from underground. It is especially recommended for small props or anything else you'd like to place frequently. Precision < headache, especially if you'll need to place 10000 trashcans or something like that.
  • Sometimes, even ideal pivot position does not cut it, and you still see intolerable precision artifacts on your model. If distortions are too severe, consider splitting your model into several smaller ones. One golden rule for this is to always place pivots of the parts on a regular grid (for example, with 1m step), so that it will be extremely easy to assemble them in the Editor (by turning on grid snapping). In this case, again, maintaining ideal center position is not too important, just make sure pivot is placed on the closest grid intersection to the center.