SFML community forums

General => Feature requests => Topic started by: xerzi on July 08, 2013, 09:12:41 am

Title: Change Unit of Measure
Post by: xerzi on July 08, 2013, 09:12:41 am
I know this is unlikely to happen, it would break too much in terms of compatibility (perhaps in SFML 3.0 someday). Angles are currently represented as degrees, it would be much easier for a lot of implementations for angles to be represented as radians instead. Yah sure degrees are easier to work with, but realistically when do you ever use degrees ? Perhaps when you are manually inputting a constant variable (in this case having a toRadian() function would cost nothing in terms of computation as it is a constant) but in every other case it costs cycles. The standard C math libraries all use radians so whenever you want to calculate sin or otherwise computations are wasted again.

As an example if I choose to store my angles are radians I would need to convert to degrees and than say I pass it to Transform::rotate(), well rotate() needs to convert them back to radians to use the sin/cos functions so I do a conversion that was never necessary.

Transform& Transform::rotate(float angle)
{
    float rad = angle * 3.141592654f / 180.f;
    float cos = std::cos(rad);
    float sin = std::sin(rad);

    Transform rotation(cos, -sin, 0,
                       sin,  cos, 0,
                       0,    0,   1);

    return combine(rotation);
}

I guess a question for the author, any reasoning for the use of degrees over radians ?
Title: Re: Change Unit of Measure
Post by: zsbzsb on July 08, 2013, 12:42:07 pm
The standard C math libraries all use radians so whenever you want to calculate sin or otherwise computations are wasted again.

I guess a question for the author, any reasoning for the use of degrees over radians ?

I am not the SFML author (Laurent is) or an OpenGL programmer but I am going to say I believe the answer lies with OpenGL. From the quick looking at OpenGL I just did it seems that OpenGL uses degrees instead of radians and since SFML is a wrapper around OpenGL, Laurent decided to let the conversions up to the user instead of providing an API with radians.

http://stackoverflow.com/questions/2146884/why-does-opengl-use-degrees-instead-of-radians (http://stackoverflow.com/questions/2146884/why-does-opengl-use-degrees-instead-of-radians)
http://www.swiftless.com/tutorials/opengl/rotation.html (http://www.swiftless.com/tutorials/opengl/rotation.html)
Title: Re: Change Unit of Measure
Post by: Lynix on July 08, 2013, 01:17:43 pm
The standard C math libraries all use radians so whenever you want to calculate sin or otherwise computations are wasted again.

I guess a question for the author, any reasoning for the use of degrees over radians ?

I am not the SFML author (Laurent is) or an OpenGL programmer but I am going to say I believe the answer lies with OpenGL. From the quick looking at OpenGL I just did it seems that OpenGL uses degrees instead of radians and since SFML is a wrapper around OpenGL, Laurent decided to let the conversions up to the user instead of providing an API with radians.

http://stackoverflow.com/questions/2146884/why-does-opengl-use-degrees-instead-of-radians (http://stackoverflow.com/questions/2146884/why-does-opengl-use-degrees-instead-of-radians)
http://www.swiftless.com/tutorials/opengl/rotation.html (http://www.swiftless.com/tutorials/opengl/rotation.html)

This has nothing to do with OpenGL, it's a choice Laurent has made, he doesn't use any OpenGL function that takes angles.
Degrees are easiers to work with, that's why (I think).
Title: Re: Change Unit of Measure
Post by: xerzi on July 08, 2013, 02:55:16 pm
Yah the only function that takes degrees in OpenGL is glRotatef and that's been deprecated since OpenGL 3.0+ and removed since 3.1+. I think that's a bad call if the only reason is degrees are easier to work with, at least from my standpoint if you want to be compatible with SFML that means you have to have a function to convert from degrees to radians whenever you want to use any trig. If I were to use radians than I'd need to convert from radians to degrees for SFML. If SFML used radians and I used radians though, there would be no need for conversion except for the odd case of a constant angle in code or printing some sort of debug message. In either case there is conversions but I find it is obvious which case would require less conversions and is more efficient than the other cases.
Title: Re: Change Unit of Measure
Post by: Laurent on July 08, 2013, 03:18:31 pm
Yes, I chose degrees because they are more natural. A good question would be: why did the standard C library choose radians?

Quote
it costs cycles
Seriously? Come back when it becomes the bottleneck of your application... :P
Title: Re: Change Unit of Measure
Post by: AxelRantila on July 08, 2013, 03:32:54 pm
It's easier to count derivates and such in radians
Title: Re: Change Unit of Measure
Post by: binary1248 on July 08, 2013, 03:38:16 pm
From Transformable.cpp:
////////////////////////////////////////////////////////////
const Transform& Transformable::getTransform() const
{
    // Recompute the combined transform if needed
    if (m_transformNeedUpdate)
    {
        float angle  = -m_rotation * 3.141592654f / 180.f;
        float cosine = static_cast<float>(std::cos(angle));
        float sine   = static_cast<float>(std::sin(angle));
        float sxc    = m_scale.x * cosine;
        float syc    = m_scale.y * cosine;
        float sxs    = m_scale.x * sine;
        float sys    = m_scale.y * sine;
        float tx     = -m_origin.x * sxc - m_origin.y * sys + m_position.x;
        float ty     =  m_origin.x * sxs - m_origin.y * syc + m_position.y;

        m_transform = Transform( sxc, sys, tx,
                                -sxs, syc, ty,
                                 0.f, 0.f, 1.f);
        m_transformNeedUpdate = false;
    }

    return m_transform;
}
So obviously Laurent accepts degrees, converts them to radians to generate the transformation matrix and feeds that to OpenGL via glLoadMatrix.

he doesn't use any OpenGL function that takes angles
He does the matrix maths himself instead of let OpenGL do it for him.

Yah the only function that takes degrees in OpenGL is glRotatef and that's been deprecated since OpenGL 3.0+ and removed since 3.1+.
Just like almost every other function Laurent uses in SFML... Laurent has other things to worry about than self-imposed deprecation restrictions. He already said OpenGL ES support was a goal, but until then, you just have to live with the fact that SFML runs on deprecated OpenGL code.

In either case there is conversions but I find it is obvious which case would require less conversions and is more efficient than the other cases.
You really shouldn't worry about angle conversions. It is a pure mult/div in hardware. It can be done in very few clock cycles if indeed more than a single one. This is not even nearly comparable to other things in your code.
Title: Re: Change Unit of Measure
Post by: xerzi on July 08, 2013, 03:57:38 pm
@Laurent
Believe that is partially at least because C took some roots from Fortran which was targeted for scientific computing which doesn't use degrees. Now though there is hardware support for said functions and last I've they take radians with no support for degrees. I guess it can be argued whether degrees are natural or not, from my viewpoint at least I haven't seen degrees on a mathematical equation for years all while using triple integrals to calculate volumes using degrees becomes irrelevant.

Also a bit curious why you didn't simply define a PI constant somewhere, do you have those several digits of PI memorized ?

You really shouldn't worry about angle conversions. It is a pure mult/div in hardware. It can be done in very few clock cycles if indeed more than a single one. This is not even nearly comparable to other things in your code.
Can be said otherwise when I have an entity with 5-10 angles all of which are used in multiple calculations, when I have on a scale of 1000 objects those few cycles now become a few 100 000 cycles of meaningless and avoidable operations.

Quote
Just like almost every other function Laurent uses in SFML... Laurent has other things to worry about than self-imposed deprecation restrictions. He already said OpenGL ES support was a goal, but until then, you just have to live with the fact that SFML runs on deprecated OpenGL code.
Wasn't really the intention of that comment, I could careless what he uses underneath, the API I am interacting with is what I am worried about. For 2D purposes there is no need for any of the new OpenGL features. The fixed pipeline was also great for debug purposes, bit bummed they completely removed it instead of just removing support in shader objects.

Title: Re: Change Unit of Measure
Post by: Nexus on July 08, 2013, 04:02:21 pm
A good question would be: why did the standard C library choose radians?
Probably because they are the standard unit for angles in mathematics. Many things are simpler to express with radians, see here (http://en.wikipedia.org/wiki/Radian#Advantages_of_measuring_in_radians). On the contrary, the degree scale is completely arbitrary.

I think it might be a valid point to consider in the future, but not because of cycles, rather to keep code simpler by avoiding conversions. One drawback is that you would have to define sf::Pi.
Title: Re: Change Unit of Measure
Post by: binary1248 on July 08, 2013, 04:09:00 pm
Can be said otherwise when I have an entity with 5-10 angles all of which are used in multiple calculations, when I have on a scale of 1000 objects those few cycles now become a few 100 000 cycles of meaningless and avoidable operations.
Compare that to the 100 000 000 cycles you would need to do other meaningful things with those entities and you have a whole new picture.

A good question would be: why did the standard C library choose radians?
A good guess would be, because C was supposed to interface with hardware well, it had to provide an API that allows access to low level hardware operations, and maybe hardware FPUs handle radians better than degrees. I know for a fact that CORDIC works way better with radians than it does with degrees.
Title: Re: Change Unit of Measure
Post by: xerzi on July 08, 2013, 04:53:59 pm
Quote
Compare that to the 100 000 000 cycles you would need to do other meaningful things with those entities and you have a whole new picture.
What other meaningful stuff takes 100 000 000 do tell.

In any case not being wasteful is only an added benefit. Having to do conversions to have access to function calls is tedious and a design flaw imo.
Title: Re: Change Unit of Measure
Post by: Hiura on July 08, 2013, 07:02:16 pm
Quoting Knuth on premature optimisations:

Quote
"We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil"

Have a look around on the web to get why such modifications should not be considered because of performance. (If a small change improve the design, then that's another story.)
Title: Re: Change Unit of Measure
Post by: Laurent on July 08, 2013, 07:08:52 pm
It won't be changed until at least SFML 3.0 anyway (it breaks the API), so don't expect too much.
Title: Re: Change Unit of Measure
Post by: Klaim on July 10, 2013, 10:03:48 am
In case you want an example of how to provide both (and use only one internally), Ogre does it nicely. It have two types which can be converted to each other but only in an explicit way, which expose the places where conversion happen. It uses radians internally (to talk directly to DX and OGL with no conversion)  but the user easily can use degrees everywhere in his code and provide it to Ogre which will convert it before processing internally. Also easy to get the degree version of any angle value Ogre provide.
It's also pretty simple to setup. As Degree and Radian are different unrelated types there is no way to mix them without explicit conversion. See https://bitbucket.org/sinbad/ogre/src/0bba4f7cdb953c083aa9e3e15a13857e0988d48a/OgreMain/include/OgreMath.h?at=default for details, you can also see that it could be implemented in a simpler way but the idea is clear. (note that by default Real is float, you can change it to double in Ogre hard config macros)

Not sure if it can be done without breaking SFML 2.0 interface, so assuming it would be for 3.0, I think it's a nice example of design for providing angles values.

Title: Re: Change Unit of Measure
Post by: binary1248 on July 10, 2013, 12:26:55 pm
Since SFML 3.0 will probably have C++11 support, Laurent might want to try out making use of user defined literals (http://en.wikipedia.org/wiki/C%2B%2B11#User-defined_literals) in order to solve this problem ;). SFML would probably be one of the first libraries to make use of UDL, but you know it sounds too good to pass up :).
Title: Re: Change Unit of Measure
Post by: Klaim on July 11, 2013, 09:47:29 pm
Since SFML 3.0 will probably have C++11 support, Laurent might want to try out making use of user defined literals (http://en.wikipedia.org/wiki/C%2B%2B11#User-defined_literals) in order to solve this problem ;). SFML would probably be one of the first libraries to make use of UDL, but you know it sounds too good to pass up :).

It don't solve the problem, it just add a shorter syntaxe. You still need some kind of type definitions to use inside the user-defined literals. But yeah that would be cool.
Title: Re: Change Unit of Measure
Post by: binary1248 on July 11, 2013, 10:09:54 pm
What type definitions? The user-defined literal is converted to the appropriate angle type when being passed to any function that would take an angle. No type definitions there...
Title: Re: Change Unit of Measure
Post by: Klaim on July 12, 2013, 12:29:40 am
What type definitions? The user-defined literal is converted to the appropriate angle type when being passed to any function that would take an angle. No type definitions there...

How do you know the angle type? No, better: how does the compiler knows the angle types so that it can stop you when you're implicitely trying to convert?
The user-defined litterals just let you associate litteral shortcut syntaxes to types. So you first need these types.
Title: Re: Change Unit of Measure
Post by: binary1248 on July 12, 2013, 01:00:13 am
Do you need to know the angle type? Not really... if you want to pass an angle in degrees, mark it with _deg, if you want radians then _rad. You don't need to rely on the implicit type if you don't want to. As an example, you could pass shorts around as 10_s if that makes it more clear you intend on it being interpreted as a short as opposed to an int or what not (this is really useful when trying to pack short literals into an sf::Packet without explicit casting). User-defined literals are not meant as a way to prevent errors by passing PODs around. If you wanted that, all functions would take some kind of an Angle type but since this topic was about being able to pass different units to functions without worrying about conversions, user-defined literals solves that problem completely.

User-defined literal is quite literally what the name implies, a mechanism for you do define your own kinds of literals. Literals aren't bound to a type until they are put into a certain context. That is why your literal handling function gets nothing but the string of characters straight out of your source code and it is up to you to interpret them in any way you want. You can make both _deg and _rad return some double value, be it in degrees, radians, gradian or whatever crazy unit you can think of. It just has to fit with the rest of the interface.

With great power comes great responsibility, and the possibility of more facepalms than you might expect. Maybe more facepalms than Laurent is willing to cope with :P.
Title: Re: Change Unit of Measure
Post by: Mario on July 12, 2013, 09:51:19 am
To me this could actually be something for a very simple class/struct like sf::Time. In the end you've got the same issue here: Several different units essentially measuring the same thing (and different functions obviously expecting different dimensions).

This would work on any platform. Using C++11 as an additional feature sounds neat, but at the same time you've still got the same issue in older standards.
Title: Re: Change Unit of Measure
Post by: Foaly on July 12, 2013, 10:05:20 am
I have to agree. Unnessesary converting back and forth between degree and radians is a waste of time and performance. I have worked with ogre before and the way they implemented it is very nice and handy. But something similar to sf::Time would be great too.
Title: Re: Change Unit of Measure
Post by: AxelRantila on July 12, 2013, 04:43:33 pm
But something similar to sf::Time would be great too.
I would like to see something like this as well.
Title: Re: Change Unit of Measure
Post by: Klaim on July 12, 2013, 09:23:04 pm
@binary1248 I think you totally don't understand why you need types in this specific case. As other pointed, it's the same problem than with sf::Time values or std::chrono time values. You don't want implicit conversions. Using user defined literals without types (or by returning a basic type like float for example) is like asking for obscure ninja conversion errors to happen. If you don't understand this, maybe you didn't hit them enough yet. It's typically the kind of error that make space projects fails.

To me this could actually be something for a very simple class/struct like sf::Time. In the end you've got the same issue here: Several different units essentially measuring the same thing (and different functions obviously expecting different dimensions).

Exactly.
The point is that the same values with different referential MUST NOT be mixed without being converted to the same referential, whatever the way.


Quote
This would work on any platform. Using C++11 as an additional feature sounds neat, but at the same time you've still got the same issue in older standards.

You don't need C++11 to do it. User defined literals are basically allowing you to associate a litteral value to a type (with a potential conversion). It is not intended nor should be used as binary1248 described (which is actually a dangerous practice).

I have to agree. Unnessesary converting back and forth between degree and radians is a waste of time and performance. I have worked with ogre before and the way they implemented it is very nice and handy.
But something similar to sf::Time would be great too.

I prefer the typed way of Ogre::Radian/Degree personally as the compiler helps pointing potential errors instead of allowing you to mix with floats like in SFML. It also don't add any conversion until you use only a type different than SFML.
The approach used by Ogre::Radian/Degree is actually similar to std::chrono time values.
sf::Time is nice, but it does force you to convert the value to something at the point of use.

Title: Re: Change Unit of Measure
Post by: Jebbs on July 12, 2013, 09:32:14 pm
To me this could actually be something for a very simple class/struct like sf::Time.

I too think this is a great idea, mostly because it would solve this issue:

Unnessesary converting back and forth between degree and radians is a waste of time and performance.

Let's get an sf::Angle! Simple, yet so useful.
Title: Re: Change Unit of Measure
Post by: Laurent on July 12, 2013, 09:45:57 pm
You should create a task on the tracker if you don't want me to forget this issue :P
Title: Re: Change Unit of Measure
Post by: Nexus on July 12, 2013, 09:58:15 pm
sf::Time is nice, but it does force you to convert the value to something at the point of use.
The same applies to Degree and Radian classes, you have to call something like an asFloat() function as soon as you need to perform a computation with it. That is currently the biggest drawback of such wrappers, every trigonometric function call requires an explicit conversion. The only way to cope with this consists of overloading a large number of functions.


Let's get an sf::Angle! Simple, yet so useful.
I agree, for SFML this approach might be more meaningful than two separate types sf::Degree and sf::Radian. Basically, you are interested in storing an angle, not a specific format thereof. Additionally, sf::Angle would have an API consistent to sf::Time:
class Angle
{
public:
    float asRadians() const;
    float asDegrees() const;  
};

Angle radians(float angle);
Angle degrees(float angle);

... // arithmetic and relational operators


You should create a task on the tracker if you don't want me to forget this issue :P
Yes, let's first come to a conclusion in this thread, to avoid a parallel discussion on GitHub.

We should also agree on whether the additionally introduced complexity (mainly explicit conversion functions) is justified by the advantages.
Title: Re: Change Unit of Measure
Post by: Jebbs on July 12, 2013, 10:47:53 pm
Do you think it would make more sense for asRadians() to return a double? I'd hate to have errors due to lack of precision on those.
Title: Re: Change Unit of Measure
Post by: binary1248 on July 12, 2013, 11:25:49 pm
You still don't get why user-defined literals will help. Even with that Ogre system, you are passing dimensionless values to get converted to some angle object or to be interpreted in whatever way you specify. Does it prevent you from passing 90.0 to a function that takes an angle in radians? Not really, because you need to construct the radian angle using a value as well. If you use user-defined literals, you are forced to explicitly write the unit as part of the value you specify hence making it 100% clear you are passing an angle in the specified unit.

You might disable implicit conversion and force people to write stuff like .setAngle( Degrees( 90.0 ) ) but at what cost? You create a temporary just to make it look safer than it actually is? Someone might end up doing something stupid like .setAngle( Degrees( m_angle ) ) and set m_angle somewhere else, defeating the purpose of making it clear what the unit is. Yes... some programmers are really that dull. With user-defined literals, there is the possibility to use constexpr to make the compiler evaluate the value already at compile time thus eliminating any run-time overhead that might be incurred using temporaries.

If you aren't content with a user-defined literal just evaluating to a POD with known unit type because of those ninja conversion errors, then make it evaluate to an angle. And better still, make it impossible to construct such an angle in any other way than through a literal or any safe construction methods (like copying). That way, you force people not to be lazy and do things like .setAngle( Degrees( m_angle ) ).

Take sf::Time for example. Someone could write something like sf::sleep( sf::seconds( m_sleep_time ) ) in their main. In some other file at line 1337, they might set m_sleep_time to 1000. Do they realize that they have committed an error? No, because they were lazy, and nothing about sf::Time will prevent it from happening.

If, however, they had to construct the sf::Time using a user-defined literal every time, they wouldn't be allowed to do stupid things like that because they would need to set m_sleep_time to 1000_ms and call sf::sleep( m_sleep_time ) hence eliminating that error source.

I'm against adding extra classes/types just to prevent errors, especially since the language provides facilities that can make it impossible even for the most dull of programmers to make stupid mistakes. If there is a weak point in any solution you always have to count on it being its undoing. And to add insult to injury, you add potential runtime overhead as well.
Title: Re: Change Unit of Measure
Post by: Hiura on July 12, 2013, 11:56:51 pm
I haven't yet tried those UDL but I have a question: do they work only on number literals or can they also work on floating point variables?

I.e., is the following code valid with the proper definition of _rad? (I guess it isn't..)

double deg = 180;
double rad = deg _rag;
 

If not, I think having a "true" type, like sf::Time with sf::seconds, would be good to, for example, load values from a file without involving complex serialization systems. Or any other scenario where the values are not hardcoded.

Any additional opinion on that?

EDIT: but having both might also have some upsides..
Title: Re: Change Unit of Measure
Post by: Silvah on July 13, 2013, 12:00:53 am
And how exactly are user-defined literals supposed to help? You still can do sf::sleep(operator "" _s(time)); where time is the number of milliseconds. In fact, that ugly syntax what you have to do when the number is not a compile-time literal.

It's C++, it's virtually always possible to break all idiot-proofing if you try hard enough or are stupid enough.
Title: Re: Change Unit of Measure
Post by: Nexus on July 13, 2013, 12:17:33 am
Do you think it would make more sense for asRadians() to return a double? I'd hate to have errors due to lack of precision on those.
I don't think so, because SFML uses floats everywhere else, and the matrix pushed to OpenGL stores floats, too. It would only help if you performed heavy computations on user side.

Take sf::Time for example. Someone could write something like sf::sleep( sf::seconds( m_sleep_time ) ) in their main. In some other file at line 1337, they might set m_sleep_time to 1000. Do they realize that they have committed an error? No, because they were lazy, and nothing about sf::Time will prevent it from happening.
What you are saying, is that sf::Time cannot prevent errors that occur because sf::Time is not used. Yes, of course that is true.

If, however, they had to construct the sf::Time using a user-defined literal every time, they wouldn't be allowed to do stupid things [...]
They still are. You cannot remove the existing factory functions unless you enforce the ugly syntax mentioned by Silvah. Imagine the users have to convert a float read from a file to a sf::Time. If they are not able to choose the correct factory, the resulting time will be wrong.
Title: Re: Change Unit of Measure
Post by: Klaim on July 13, 2013, 02:17:25 am
Do you need to know the angle type? Not really...

I disagree.

Quote
if you want to pass an angle in degrees, mark it with _deg, if you want radians then _rad.

Which, in a typed context, is exactly a shortcut for Degree(value) and Radian(value). Please check what UDL is really, because I think you don't understand it nor do you understand strong typing.

Quote
You don't need to rely on the implicit type if you don't want to.

If you don't want to use a degree value into an object which is interpret on read as a radian value, you want it typed.


Quote
As an example, you could pass shorts around as 10_s if that makes it more clear you intend on it being interpreted as a short as opposed to an int or what not (this is really useful when trying to pack short literals into an sf::Packet without explicit casting).

I agree, as I was saying, UDL is nothing else than shortcut conversion from source code litteral to a typed value. If you use double or float or any basic type, your conversion is just meaningless in specific context, but useful if it's exactly what you meant, which is why there is already the default litterals L, l,  f etc.

Quote
User-defined literals are not meant as a way to prevent errors by passing PODs around.

Exactly, you need strong typing to prevent these errors. Whatever the way you can't avoid defining one (sf::Angle) or N types (Ogre::Degree/Radian). You can't use int or float and assume everybody will know it's degree and will never make mistakes.

Quote
If you wanted that, all functions would take some kind of an Angle type but since this topic was about being able to pass different units to functions without worrying about conversions, user-defined literals solves that problem completely.

Not if the compiler can't know the difference. You see, if your function takes a radian as float, and you provide say "90deg" and  you have UDL converting it to a float, then you used UDL to give your intent but the code will compile and not do what you intended.
Which is why you need strong typing.

Quote
User-defined literal is quite literally what the name implies, a mechanism for you do define your own kinds of literals.

We strongly agree.

Quote
Literals aren't bound to a type until they are put into a certain context.

No, litteral are strictly always bound to a type, which is what makes auto works in the first place:

Code: [Select]
auto a = 42; // int
auto b = 42.0; // double
auto c = 42.0f; // float
auto d = 42L; // long (or long)  etc.

Quote
That is why your literal handling function gets nothing but the string of characters straight out of your source code and it is up to you to interpret them in any way you want.

And return a type. So, basically UDL solve the ease of writing but types solve the identification of intent and basically allow you to see the points of conversion. If you use UDL to always return a sf::Angle, why not, but don't return a double or float, it's hiding the intent of the library developer side of the contract in the interface of the function.

Quote
You can make both _deg and _rad return some double value, be it in degrees, radians, gradian or whatever crazy unit you can think of. It just has to fit with the rest of the interface.

double, I disagree. A specific type, I agree.


By the way, UDL is a minor improvement here because most games are data-driven so the data were not in the code anyway. When you get the data to inject in SFML, I hope you know what type it is. I wouldn't trust mysefl with it, which is why I let the compiler make sure it's the right type.

sf::Time is nice, but it does force you to convert the value to something at the point of use.
The same applies to Degree and Radian classes, you have to call something like an asFloat() function as soon as you need to perform a computation with it.

Not at all, it provides all the necessary operators, even implicitely converting degree values to radians if you are mixing them in calculus (in which case you pay for mixing the types but it don't make the code uglier by forcing you to explicitely convert). Take a look at the header: https://bitbucket.org/sinbad/ogre/src/0bba4f7cdb953c083aa9e3e15a13857e0988d48a/OgreMain/include/OgreMath.h?at=default
Actually the conversion is implicit between Radian and Degree (I was wrong on this detail), but explicit when you provide a float value (which is where having UDL makes code shorter to read)

Ogre uses Radian by default internally and in all it's interface (which is configurable), which means if you use Radian in your user code then there is strictly no conversion hapening. If you use Degree in all your user code then at least one conversion happen when you push Degrees into Ogre. You can avoid it when you configure Ogre to use Degree but then it will have to convert to Radian before pushing it in the graphic card anyway.

Basically, no conversion until you use Degree. There are also operations on Vector and Matrix types in Ogre which rely on Radian which mean there again there is no conversion until you use Degree.

Which was my initial point with this design. I believe sf::Time/Angle don't have the same properties. I consider it's ok with Time because it's more about time scale and SFML don't work under microseconds and over seconds, so it's good. ( std::chrono necesarily needs to be more flexible and precise because far more generic )
However angles have two defined types which are not just scales so to me it's more obvious to have a different type for each, it fit the semantic and allows the no-conversion-if-same-type semantic.

Quote
That is currently the biggest drawback of such wrappers, every trigonometric function call requires an explicit conversion. The only way to cope with this consists of overloading a large number of functions.


I'm not sure I understand by overloading a large number of functions. If a specific type is used into SFML (or Ogre) for angles, then there is no need for overload, isn't it?
Title: Re: Change Unit of Measure
Post by: Nexus on July 13, 2013, 02:40:00 am
Not at all, it provides all the necessary operators, even implicitely converting degree values to radians if you are mixing them in calculus
Yes, there are implicit conversions between each other, but many computations -- especially trigonometry -- are not covered. That is, you still have to write std::sin(angle.asRadians()), unless you overload all the functions, i.e. write functions that take sf::Angle and return float.


However angles have two defined types which are not just scales so to me it's more obvious to have a different type for each, it fit the semantic and allows the no-conversion-if-same-type semantic.
What do you mean? Radians and degrees are just different scales of an angle. The scaling factor is 180/pi.

I see a different problem with two types sf::Degree and sf::Radian: the amount of operators to overload increases by almost a factor of four. Instead of just providing binary operators like Angle + Angle, the following combinations need to be covered:
And this applies to many arithmetic and relational operators. Without helpers such as Boost.Operators, the implementation results in masses of boilerplate code and code duplication.

On the other hand, I see only one advantage of two types: assuming sf::Angle stores radians and the user converts a lot between raw floats and degrees, there is an unnecessary conversion between degree and radian, which could be avoided with sf::Degree. But in my opinion, this alone isn't worth the trouble and the confusion with two types to describe an angle.
Title: Re: Change Unit of Measure
Post by: Klaim on July 14, 2013, 03:31:46 pm
Indeed it requires a lot of overloads. Ogre manage this by having it's own math library (which is a modified version of an old math library called Magic Box if I remember correctly).
If this is a problem then sf::Angle is certainly a good enough solution.