NOTE: Sprite 3D is now included (and maintained) as a part of Selba Ward.Sprite3dSprite3d could be considered a follow-up to the sprite animation temporary class,
SpinningCard, which allows you to rotate a sprite around
either the x axis
or the y axis. It does this by animated the corners in an ellipse.
However, where SpinningCard was only intended to used during the spinning animation and then discarded, Sprite3d is intended to be used on its own.
Sprite3d does not animate corners using an ellipse; it uses a "proper" transformation matrix (albeit a rather compact one) to rotate around the x and y axes. This combined with the usual rotation around the z axis (this class inherits from sf::Transformable) and you can rotate around all three axes.
Sprite3d
injects itself into the same namespace as SFML to allow for an easy and seamless transition from sf::Sprite to sf::Sprite3d.
Sprite3d is intended to be able to used in place of a standard SFML sprite with no changes to the code.The source is, of course,
available on my GitHub and is also available on
its Wiki page.
Here's an early test screenshot (it really does not do it justice!):
The screenshot doesn't properly show what it does so here is a video of an early test example:
One thing to note is that this class doesn't solve the texture mapping problem evident in SpinningCard (and is evident in that screenshot - look at the lines). It does attempt to reduce the effects by a user-controlled number of triangles. The quality of this effect is therefore dependant on both mesh size and apparent depth.
If you want to see the mesh fixing the texture distortion, run the current example and start the rotation (press
Space). Increase the Mesh Density to 4 (use the square brackets
[ ] to adjust) and turn on dynamic subdivision (
Return). Then increase the depth to 50 (use
- and
= to adjust). The example displays how many triangles are being used at any point in time.
For more controls, see the comments at the head of the example code.
To combat the texture distortion evident when a non-affine transformation (three dimensional rotation is a non-affine transformation as the edges stop being parallel) is applied to a quad, there are three features in Sprite3d that alter the mesh (size and number of triangles).
- Mesh Density
This is how many points are used per dimension, not including the edges. For example, if the mesh is created from 5x5 points, that's 5 points per dimension - 3 points per dimension, not including the edges. So, a mesh density of 3 would give you a mesh created from 5x5 points (a single quad is 2x2 points; 5x5 points creates 4x4 quads) - Subdivision level
This is very similar to Mesh Density. It changes how many points are used for the mesh. Each subdivision divides each quad in the mesh into four quads. e.g.: 1 quad that is subdivided once becomes 4 quads, 1 quad that is subdivided twice becomes 16 quads, etc. - Dynamic Subdivision
When enabled, Dynamic Subdivision changes the subdivision level automatically based on the most extreme angle. That is, the greatest rotation angle of pitch and yaw (around the x and y axes respectively). The range of subdivision can be specified; the default range is 1 to 4.
Example: Using the default range, if pitch and yaw are both 0 (object is flat), the subdivision level would be 1, whereas if pitch or yaw is close to 90°, the subdivision level would be 3. Subdivision level 2 would be used if the most extreme angle was not almost 90° but was not almost flat.
The range is interpolated linearly so (in the case of the default range) from 0° up to 30° the subdivision level would be 1, from 30° up to 60° degrees it would be 2, from 60° up to 90° it would be 3, and at 90° it would be 4.
I invite people to try Sprite3d in place of any standard sprite you already have to see if the replacement is seemless or needs some work. I would appreciate any feedback on this (or any) matter.
GitHub repository for Sprite3d.
EDIT: updated to reflect complete version (1.0.0)
If anyone knows if it's possible to use a shader to fix the texture distortion, please let me know how.