Avoid floating point precision issues - c#

I'm about to create a terrain for a mobile game which allows a huge terrain which is mostly limited by the available hardisk space.
This requires to keep the floating points limited to a "after-point-precision" of 2 numbers.
What is a good approach to keep it at the precision of 2 numbers after the point?
Remember: I'm running on a mobile device, so the method should be fast and easy to use and should be applicable to any arithmetic which is needed for games.
More information
I'm not talking about space( i know how much space a float takes guys, really ), i'm talking about the issue that i loose precision when my floating point is going to have to many numbers after the decimal point.
Using a int would cause that i've to convert the int into a float each frame. I don't know how fast the conversion is but this seems to cost a lot of performance when doing it for a lot of objects. ( Remeber i'm on a mobile device ).
Of course i'm also not talking about the terrain, i'm talking about objects in the terrain! The terrain is a specialized system which actually can hold a terrain size which extends the limits of the floats a lot ( It's even possible to save north america in this system when you have enough disk space, but actually the limits are set to -99km to +99km ).
Edit 2
As usual in games the movement is timebased, means i need to multiply the speed of the object with a modifier given to me by unity, this corrupts my numbers which are limited to 2 numbers after the decimal point.

An interesting way would be to implement this into the movement function:
float result = //multiply force by time
float modulus = result%0.01f;
result -= modulus; //you will do this in any case
if(modulus>=0.005f) {/*round up. if you want it to only round down, remove
the next 2 lines, if you want it to only round up, remove
the conditional statement*/
result+=0.01f; }
I can't think about how to optimize it further, I removed the else statement and have it take away the modulus without condition as it will be done anyway.

Huh, doesn't matter what precision you choose to operate at they still take up the same amount of space. Single or double would make a difference, but the real question you should ask is do you need floating points at all. If you can fit the numbers in an int, do that.

Related

Unity Coordinate Limitations and its impact

Some objects which I have placed at a position (-19026.65,58.29961, 1157) from the origin (0,0,0) are rendering with issues, the problem is referred to as spatial Jitter (SJ) ref. Like You can check its detail here or You can see the below image. The objects are rendering with black spots/lines or maybe it is Mesh flickering. (Actually, I can't describe the problem, maybe the picture will help you to understand it)
I have also tried to change the camera near and far clipping but it was useless. Why I am getting this? Maybe my object and camera are far away from the origin.
Remember:
I have a large environment and some of my game objects (where the problem is) are at (-19026.65,58.29961, 1157) position. And I guess this is the problem that Object and Camera are very far from the origin (0,0,0). I found numerous discussions which is given below
GIS Terrain and Unity
Unity Coordinates bound Question at unity
Unity Coordinate and Scale - Post
Infinite Runner and Unity Coordinates
I didn't find that what is the minimum or maximum limit to place the Object in unity so that works correctly.
Since the world origin is a vector 3(0,0,0), the max limit that you can place an object would be 3.402823 × 10^38 since it is a floating point. However, as you are finding, this does not necessarily mean that placing something here will insure it works properly. Your limitation will be bound by what other performance factors your have in your game. If you need to have items placed at this point in the world space,consider building objects at runtime based on where the camera is. This will allow the performance to work at different points from the origin.
Unity suggests: not recommended to go any further than 100,000 units away from the center, the editor will warn you. If you notice in today's gaming world, many games move the world around the player rather than the player around the world.
To quote Dave Newson's site Read Here:
Floating Point Accuracy
Unity allows you to place objects anywhere
within the limitations of the float-based coordinate system. The
limitation for the X, Y and Z Position Transform is 7 significant
digits, with a decimal place anywhere within those 7 digits; in effect
you could place an object at 12345.67 or 12.34567, for just two
examples.
With this system, the further away from the origin (0.000000 -
absolute zero) you get, the more floating-point precision you lose.
For example, accepting that one unit (1u) equals one meter (1m), an
object at 1.234567 has a floating point accuracy to 6 decimal places
(a micrometer), while an object at 76543.21 can only have two decimal
places (a centimeter), and is thus less accurate.
The degradation of accuracy as you get further away from the origin
becomes an obvious problem when you want to work at a small scale. If
you wanted to move an object positioned at 765432.1 by 0.01 (one
centimeter), you wouldn't be able to as that level of accuracy doesn't
exist that far away from the origin.
This may not seem like a huge problem, but this issue of losing
floating point accuracy at greater distances is the reason you start
to see things like camera jitter and inaccurate physics when you stray
too far from the origin. Most games try to keep things reasonably
close to the origin to avoid these problems.

What is the best approach to plot graphs?

I am working on a graphing calculator application, and of course, the main feature of the application is to display graphs.
Right now, this is how my algorithm of plotting graphs works: I divide the drawing canvas in N intervals (where N is defined the application's settings, default value is about 700). For each interval, I evaluate the function for the two ends, and I draw a segment between the two points.
Here are the disadvantages I found to this method:
The precision of the graph isn't great (for example the function sin(tan(x)) )
Rendering gets slow for a higher number of intervals (e.g. N is above 1000). Also, zoom and navigation controls suffer.
So is there a better approach to drawing graphs?
I am programming in C# (WPF), but I think this is irrelevant, because I am looking for an algorithm.
A better approach would be to use adaptive interval sizes. That is, start with relatively coarse intervals, say 20. For each interval, compute the function for the interval ends and the middle. If the middle point is close to the line connecting the two end points, draw a line and you're done with that interval. If not, split the interval in two and repeat with the two smaller intervals.
If the interval gets too small without converging to a line, you've probably found a discontinuity and should not connect the interval endpoints.
You don't need to write your own algorithm if you are plotting some arbitrary functions. Use a graph control from a relevant library, see here and provide the neccessary data (x, y cordinates).
I hope i can help you with this snippet of C++ program which i made few years back using primitive graphics.h ported for mingw compiler. The variable names are pretty much clear.
void func_gen(char expr[100],float precision,int color)
{
float x=-(xres/2)/(float)zoom_factor;
float max_range=-x;
while(x<=max_range)
{
float y;
y = evalu(expr,x); //user defined function which i used to evaluate ann expression
float xcord=xby2+zoom_factor*x+xshift;
float ycord=yby2-zoom_factor*y+yshift;
if(xcord<=xres && xcord>=0 && ycord>=0 && ycord<=yres)
putpixel(xcord,ycord,color);
x=x+precision;
}
}
This method gets pretty slow when i reduce the precision value (which actually increases the precision of the plot :p, sorry for noobness)
I think you should do with DrawPath. That method use an auxiliary structure (a GraphicsPath) optimized just for kind of task as you are coding. edit A small optimization could be to eval the function just at the left point of the segment, and eval at close point just on last segment.

C# double precision issue, how to detect and handle in a safe way

I was looking for satisfactory and safe workaround to my double precision issue specified to this problem:
This program tries to find how many small circle can fit into a large circle. It fills the large circle and then culls those that intersect the large circumference. using this formula:
distance_small_pos_from_center + small_radius < big_radius
All calculations were in double, except for screen output on WinForms which takes int for coords.
The above image shows the result of the culling. You can see that it is not symmetric when it should really be because the constraint is that there must be one small circle exactly in the center. I step through the code and find that this is because some calculations yield, for example,
99.9999999 < 100
This answer C++ double precision and rounding off says we should use all the precision available, but in this case, I had to do a Math.Round(distance_small_pos_from_center + small_radius, 3) using 3 arbitarily.
The result of the culling differs very much without Math.Round. In retrospect, this is one kind of bug that is hard to detect if I had not drawn it out. Maybe I did something wrong, or didn't understand doubles as much as I thought I had.
So, anyone has solutions or tips to avoid this kind of problem?
Sorry for not beeing able to provide a complete answer to your question, but i have no time for that right now. But when you compare floats, compare them with a "tolerance" since a float is not exact.
EDIT: modified with abs() in case you don't know which is big and small, as pointed out by Hans Kesting
Ie, do something like if(abs(big_radius - distance_small_pos_from_center) < epsilon) where epsilon is your tolerance, selected with consideration to how "inexact" the floats will be in the range where you are working..
For more precise information see:
http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
http://download.oracle.com/docs/cd/E19957-01/806-3568/ncg_goldberg.html
http://www.cplusplus.com/forum/articles/3638/
Use System.Decimal:
http://msdn.microsoft.com/en-us/library/system.decimal.aspx

Simple way to calculate point of intersection between two polygons in C#

I've got two polygons defined as a list of Vectors, I've managed to write routines to transform and intersect these two polygons (seen below Frame 1). Using line-intersection I can figure out whether these collide, and have written a working Collide() function.
This is to be used in a variable step timed game, and therefore (as shown below) in Frame 1 the right polygon is not colliding, it's perfectly normal for on Frame 2 for the polygons to be right inside each other, with the right polygon having moved to the left.
My question is, what is the best way to figure out the moment of intersection? In the example, let's assume in Frame 1 the right polygon is at X = 300, Frame 2 it moved -100 and is now at 200, and that's all I know by the time Frame 2 comes about, it was at 300, now it's at 200. What I want to know is when did it actually collide, at what X value, here it was probably about 250.
I'm preferably looking for a C# source code solution to this problem.
Maybe there's a better way of approaching this for games?
I would use the separating axis theorem, as outlined here:
Metanet tutorial
Wikipedia
Then I would sweep test or use multisampling if needed.
GMan here on StackOverflow wrote a sample implementation over at gpwiki.org.
This may all be overkill for your use-case, but it handles polygons of any order. Of course, for simple bounding boxes it can be done much more efficiently through other means.
I'm no mathematician either, but one possible though crude solution would be to run a mini simulation.
Let us call the moving polygon M and the stationary polygon S (though there is no requirement for S to actually be stationary, the approach should work just the same regardless). Let us also call the two frames you have F1 for the earlier and F2 for the later, as per your diagram.
If you were to translate polygon M back towards its position in F1 in very small increments until such time that they are no longer intersecting, then you would have a location for M at which it 'just' intersects, i.e. the previous location before they stop intersecting in this simulation. The intersection in this 'just' intersecting location should be very small — small enough that you could treat it as a point. Let us call this polygon of intersection I.
To treat I as a point you could choose the vertex of it that is nearest the centre point of M in F1: that vertex has the best chance of being outside of S at time of collision. (There are lots of other possibilities for interpreting I as a point that you could experiment with too that may have better results.)
Obviously this approach has some drawbacks:
The simulation will be slower for greater speeds of M as the distance between its locations in F1 and F2 will be greater, more simulation steps will need to be run. (You could address this by having a fixed number of simulation cycles irrespective of speed of M but that would mean the accuracy of the result would be different for faster and slower moving bodies.)
The 'step' size in the simulation will have to be sufficiently small to get the accuracy you require but smaller step sizes will obviously have a larger calculation cost.
Personally, without the necessary mathematical intuition, I would go with this simple approach first and try to find a mathematical solution as an optimization later.
If you have the ability to determine whether the two polygons overlap, one idea might be to use a modified binary search to detect where the two hit. Start by subdividing the time interval in half and seeing if the two polygons intersected at the midpoint. If so, recursively search the first half of the range; if not, search the second half. If you specify some tolerance level at which you no longer care about small distances (for example, at the level of a pixel), then the runtime of this approach is O(log D / K), where D is the distance between the polygons and K is the cutoff threshold. If you know what point is going to ultimately enter the second polygon, you should be able to detect the collision very quickly this way.
Hope this helps!
For a rather generic solution, and assuming ...
no polygons are intersecting at time = 0
at least one polygon is intersecting another polygon at time = t
and you're happy to use a C# clipping library (eg Clipper)
then use a binary approach to deriving the time of intersection by...
double tInterval = t;
double tCurrent = 0;
int direction = +1;
while (tInterval > MinInterval)
{
tInterval = tInterval/2;
tCurrent += (tInterval * direction);
MovePolygons(tCurrent);
if (PolygonsIntersect)
direction = +1;
else
direction = -1;
}
Well - you may see that it's allways a point of one of the polygons that hits the side of the other first (or another point - but thats after all almost the same) - a possible solution would be to calculate the distance of the points from the other lines in the move-direction. But I think this would end beeing rather slow.
I guess normaly the distances between frames are so small that it's not importand to really know excactly where it hit first - some small intersections will not be visible and after all the things will rebound or explode anyway - don't they? :)

Datatypes for physics

I'm currently designing a program that will involve some physics (nothing too fancy, a few balls crashing to each other)
What's the most exact datatype I can use to represent position (without a feeling of discrete jumps) in c#?
Also, what's the smallest ammount of time I can get between t and t+1? One tick?
EDIT: Clarifying: What is the smallest unit of time in C#? [TimeSpan].Tick?
In .Net a decimal will be the most precise datatype that you could use for position. I would just write a class for the position:
public class Position
{
decimal x;
decimal y;
decimal z;
}
As for time, your processor can't give you anything smaller than one tick.
Sounds like an fun project! Good luck!
The Decimal data type although precise might not be the optimum choice depending on what you want to do. Generally Direct3D and GPUs use 32-bit floats, and vectors of 3 (total 96 bits) to represent a position in x,y,z.
This will usually give more than enough precision unless you need to mix both huge scale (planets) and microscopic level (basketballs) in the same "world".
Reasons for not using Decimals could be size (4 x larger), speed (orders of magnitude slower) and no trigonometric functions available (AFAIK).
On Windows, the QueryPerformanceCounter API function will give you the highest resolution clock, and QueryPerformanceFrequency the frequency of the counter. I believe the Stopwatch described in other comments wraps this in a .net class.
Unless you're doing rocket-science, a decimal is WAAAY overkill. And although it might give you more precise positions, it will not necessarily give you more precise (eg) velocities, since it is a fixed-point datatype and therefore is limited to a much smaller range than a float or double.
Use floats, but leave the door open to move up to doubles in case precision turns out to be a problem.
I would use a Vector datatype. Just like in Physics, when you want to model an objects movement, you use vectors. Use a Vector2 or Vector3 class out of the XNA framework or roll your own Vector3 struct to represent the position. Vector2 is for 2D and Vector3 is 3D.
TimeSpan struct or the Stopwatch class will be your best options for calculating change in time. If I had to recommend, I would use Stopwatch.
I think you should be able to get away with the Decimal data type with no problem. It has the most precision available. However, the double data type should be just fine.
Yes, a tick is the smallest I'm aware of (using the System.Diagnostics.Stopwatch class).
I'm not sure I understand your last question, could you please clarify?
Edit:
I might still not understand, but you can use any type you want (for example, doubles) to represent time (if what you actually want is to represent the discretization of time for your physics problem, in which case the tick is irrelevant). For most physics problems, doubles would be sufficient.
The tick is the best precision you can achieve when measuring time with your machine.
For a simulation you're probably better off using a decimal/double (same type as position) for a dimensionless time, then converting it from/to something meaningful on input/output. Otherwise you'll be performing a ton of cast operations when you move things around. You'll get arbitrary precision this way, too, because you can choose the timescale to be as large/small as you want.
Hey Juan, I'd recommend that you use the Vector3 class as suggested by several others since it's easy to use and above all - supports all operations you need (like addition, multiplication, matrix multiply etc...) without the need to implement it yourself.
If you have any doubt about how to proceed - inherit it and at later stage you can always change the inner implementation, or disconnect from vector3.
Also, don't use anything less accurate than float - all processors these days runs fast enough to be more accurate than integers (unless it's meant for mobile, but even there...)
Using less than float you would lose precision very fast and end up with jumpy rotations and translations, especially if you plan to use more than a single matrix/quaternion multiplication.

Categories