0
\$\begingroup\$

The game development library SFML has a Vector2 class template (and a Vector3 for that matter), which can use any arithmetic type for its x- and y-value: Vector2<float>, Vector2<int>, Vector2<double>, etc.

My question is simply: Why? Why would you ever want to use any other type than float for positional math? I realize SFML is a public library that is made very open to suit what the user feels appropriate, but still. The library even has typedefs like Vector2i for Vector2<int>, and Vector2u for Vector<unsigned int>. What would any possible use-cases be for those two types?

I found this similar question and all answers say that float is pretty much always used. So what do you think is the idea behind SFML's Vector2 being templated? Could it be merited?

\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

Unity, for example, has both Vector2 and Vector2Int types (and so on for other dimensionalities), since C# didn't/doesn't have good support for making math generic across different number formats. Peeking at their APIs can give a clue as to why game or engine developers might go to that trouble.

You'll find these types are used prominently in their grid and tilemap APIs for making tile-based games, where you naturally want positions to be expressed in units of discrete "hops", and fractions of tiles might not make sense. This gives you the familiar vector math tools for manipulating positions/displacements, footprints or selection bounds, while saving you unnecessary number format conversions when you want to use a tile position as an index into an array of tile types / contents. In particular, if the corner of your map is always (0,0) and tile positions are exclusively non-negative, then you can use unsigned types and be certain you'll never get an invalid negative index from them.

You might even opt to use a smaller integer type that's only 1 or 2 bytes, if your maps are never larger than 256 / 65536 tiles wide, or you can quantize your positions to that level of granularity for storage without negative gameplay impacts. That lets you pack more positions in a cache line for bulk operations, or to compress data packets for network communication in multiplayer, or to shrink the size of files you're loading/saving to disc.

It's also sometimes desirable when you want to store and manipulate cardinal direction vectors like (0, 1), and want to be certain that no matter what sequence of rotations/shifts you put them through, you'll never get accumulating floating point rounding error that makes them deviate from the expected values.

It's also sometimes the case that you need vectors to retain high precision even a long distance from the origin, where single-precision floating point numbers have to trade off significant precision for range. For instance, you can't make a scale representation of the solar system that both faithfully reproduces the orbits of planets AND lets you move around your spaceship on a scale of meters within a single 32-bit float coordinate system. When you hit this precision limitation, it can be convenient to work around it by adding more bits: trading up to 64-bit doubles, while keeping the rest of the code pretty much unchanged. (Though arguably a better solution for many such cases is to divide the space into chunks and express position relative to the nearest chunk origin instead — this will depend on the specifics of your application)

So that's four possible reasons why you might sometimes reach for a different number format in your vector types, even though 32-bit floats are "good enough" 90% of the time. If you're not making a game/tool that runs into one of those reasons, you can pretty safely ignore it and just use floats exclusively.

\$\endgroup\$
1
  • \$\begingroup\$ Thanks, this is exactly the kind of answer I was looking for. \$\endgroup\$
    – JensB
    Commented Sep 9, 2023 at 12:24
2
\$\begingroup\$

Why would you ever want to use any other type than float for positional math?

The other answer covers this pretty well but some aspects of your post has not been tackled.


Is there a logical reason for SFML's Vector2 being templated?

Because SFML is written in c++ and as such, you don't re-write code when you can template it instead. Failing to have done so would likely have let folks judge negatively the library.

Why? [...] What would any possible use-cases be for those two types?

The answer lies partly here: "[...] I realize SFML is a public library that is made very open to suit what the user feels appropriate [...]". SFML is built over other APIs, including Windows and OpenGL. The fact that floats are not used all over the place is likely due in part to those APIs, where they provide functions that accept ints and uints. Having SFML's own API use those can indicate to the end user something like "look, we'll pass ints anyway, so better handle what you want to do with decimal values rather than be surprised that we just ignore them or do something you wouldn't expect."

As an example, the Windows API CreateWindowW function used in Window class construction implementation uses ints for the positioning/size, and as such, VideoMode holds Vector2u.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .