Sign in to follow this  
sirGustav

Recommend a simple math library?

Recommended Posts

Is there a simple math library out there that has - simple(glsl like) syntax - data seperated from functions - no template-based headers - bonus if it would use point3/direction3 syntax instead of vec3 syntax. I've been using cml, but it's massive template usage causes "longer" compilation times and borks up intellisense. If I can't find any, I'm guessing my best bet is to write a wrapper over cml [Edited by - sirGustav on October 11, 2008 4:49:33 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by sirGustav
Is there a simple math library out there that has
- simple(glsl like) syntax
- data seperated from functions
- no template-based headers
- bonus if it would user point3/direction3 syntax instead of vec3 syntax.

I've been using cml, but it's massive template usage causes "longer" compilation times and borks up intellisense. If I can't find any, I'm guessing my best bet is to write a wrapper over cml
Sorry you're having trouble with the CML. Towards the bottom of this page you'll find a list of free math libraries; maybe something there will meet your needs.

You could also take a look at the WildMagic library (which you can find at geometrictools.com). The classes are parameterized by real-number type, but aside from that I think template usage is minimal.

You could also take a look at the Sony math library, which (I believe) is included with the Bullet physics library. I don't know that much about it, but I don't think it uses templates (it's also fully vectorized, I believe).

I don't work with Visual Studio enough to comment on the Intellisense issue, but I'll let the other developer on the CML project know about this thread - maybe he'll be able to address that issue (and perhaps the compilation time issue as well).

Share this post


Link to post
Share on other sites
I checked out that link earlier(sorry I didn't mention that) but I couldn't find any math library that would separate data from function and skip the templates.
It's not that I have problems with compile-times it's more that it bothers me that every class that includes something eventually includes the whole cml library, even though they don't care about how to calculate the dot-product.

wildmagic includes the all math-functions if I include a vector. Is there any design-reason why I get 3 different implementation of sin, cos & tan when I just want to declare a vector?

bullet seems to forget that there is something called namespaces and cpp-files. I'll have to give it credit though for it's (ab)use of inheritance. 3 levels deep! (the goggles do nothing). Here I thought a struct with 3 members was sufficient :)

Share this post


Link to post
Share on other sites
Quote:
Original post by sirGustav
wildmagic includes the all math-functions if I include a vector. Is there any design-reason why I get 3 different implementation of sin, cos & tan when I just want to declare a vector?

I do not understand what you mean. If you declare a Vector3<float>, you get an object with three float members. My Math class has Sin, Cos, Tan wrappers to deal with the choice of template parameter 'float' or 'double'. It also has some "fast" trigonometric functions, where you trade off some accuracy for speed. Is this what you are referring to?

Quote:

bullet seems to forget that there is something called namespaces and cpp-files. I'll have to give it credit though for it's (ab)use of inheritance. 3 levels deep! (the goggles do nothing). Here I thought a struct with 3 members was sufficient :)


And what is your problem with this? If the author of Bullet believes that his class design is necessary to support his physics engine, who are you to question this? You might consider posting more specific comments about what the issues are.

Share this post


Link to post
Share on other sites
Hi sirGustav,

I've never been able to get Intellisense from Visual Studio 2005 to do the Right Thing with CML, particularly because it has documented problems with templates. I haven't had a chance to check 2009's Intellisense against the CML, since I don't normally use the IDE when I compile with VS (I'm a command-line kind of guy). I'll give it a try, though, at the next opportunity I get.

Also, I don't know of a library that is as full-featured as the CML, only works with 3D and homogeneous vectors and matrices, is very fast, and *doesn't* use templates. However, if all you need is the ability to perform vector and matrix algebra (i.e. +, -, *, dot, etc.), writing your own vector and matrix classes is pretty straightforward in a couple hundred lines of code, and there are many references on-line for doing this.

Finally, I'm not sure what to tell you about the compilation times; I've never noticed any significant slowdown due to the CML (though obviously there is some slowdown compared to a linkable, object-code library).

Sorry I couldn't be more help,
Cheers,
Demian

Share this post


Link to post
Share on other sites
sirGustav,

I was poking around GD and randomly happened upon this library:

http://glm.g-truc.net/

Apparently it implements GLSL-like C++ classes.

Hope this helps.
Cheers,
Demian

Share this post


Link to post
Share on other sites
If it sounded as I questioned his (or your) design-decisions I'm sorry. I am looking for a math library for me, to suit my codingstyle, that I can use in my spare-time for my games. I want the library to fit my design goals. The author of bullet(and you) probably had different goals when the library was implemented, resulting in a different API. I am not questioning your decisions per se, I am questioning the library according to my spec - hope that makes sense.

Quote:
Original post by Dave Eberly
I do not understand what you mean. If you declare a Vector3<float>, you get an object with three float members. My Math class has Sin, Cos, Tan wrappers to deal with the choice of template parameter 'float' or 'double'. It also has some "fast" trigonometric functions, where you trade off some accuracy for speed. Is this what you are referring to?
sort of... My main problem is this code:
class Character {
Vector<float> position;
int health;
;
Wherever I include the character, I get the implementation of full mathclass, even though I don't want it. This is the downside of everything being implemented as templates.

Quote:
Original post by dnave
Hi sirGustav,
I've never been able to get Intellisense from Visual Studio 2005 to do the Right Thing with CML, particularly because it has documented problems with templates. I haven't had a chance to check 2009's Intellisense against the CML, since I don't normally use the IDE when I compile with VS (I'm a command-line kind of guy). I'll give it a try, though, at the next opportunity I get.
thanks, though it will probably take some time before I switch to 2009. I am stuck at 2005 until the end of this project...
I've heard some good things about the new intellisense in 2009.

Quote:
Also, I don't know of a library that is as full-featured as the CML, only works with 3D and homogeneous vectors and matrices, is very fast, and *doesn't* use templates. However, if all you need is the ability to perform vector and matrix algebra (i.e. +, -, *, dot, etc.), writing your own vector and matrix classes is pretty straightforward in a couple hundred lines of code, and there are many references on-line for doing this.
I've written my own library in the past, but given the nature of things... the less code I write the less bugs I got :) Besides I'll never get as much testers as cml.
So my best bet is probably to wrap cml, given it's flexibility.

[Edited by - sirGustav on October 12, 2008 10:39:10 AM]

Share this post


Link to post
Share on other sites
Hi sirGustav,

Quote:
Original post by sirGustav
I've written my own library in the past, but given the nature of things... the less code I write the less bugs I got :) Besides I'll never get as much testers as cml.
So my best bet is probably to wrap cml, given it's flexibility.


Understood. :-) Just to warn you, the CML is not currently equipped to use derived classes in its expression templates (CML v2 will support this). What this means is that you won't be able to use algebraic expressions for your wrapped vector and matrix types; e.g. v2 = v1*M1 won't work for your custom types for v1, v2, and M1.

You can partially work around this, although probably with a pretty big performance hit, and with a bit of inconvenience. For example:


#include <iostream>
#include "cml/cml.h"

class MyVector3
: public cml::vector< float, cml::external<3> >
{
public:
typedef cml::vector< float, cml::external<3> > CMLType;

public:
// Initialize the external vector, assuming that x, y, and z
// are contiguous in memory (as they should be):
MyVector3() : CMLType(&x) {}

public:
float x, y, z;
};

int main()
{
// Initialize some values:
cml::vector3f v1(1., 0., 0.), v3(0., 0., 1);
MyVector3 v2; v2.x = 0.; v2.y = 1.; v2.z = 0.;

// Assign to a normal CML vector using an expression including MyVector3:
v3 = v1 + v2;
std::clog << "... v3 = " << v3 << std::endl;

// v2 = v1+v3 doesn't compile, because MyVector3 isn't recognized
// by CML's type system. But, it can be forced to the right type:
((MyVector3::CMLType&)v2) = v1 + v3;
std::clog << "... v2 = " << ((MyVector3::CMLType&)v2) << std::endl;

// Note that MyVector3::operator=() won't work unless it is implemented as
// a template member function taking a const cml::et::VectorXpr<T>, because
// the result of v1 + v3 is a VectorXpr<> instance, not a cml::vector<>.
}


The above code compiles with VS2005, and outputs:


... v3 = [ 1 1 0 ]
... v2 = [ 2 1 0 ]


As you might expect, there are lots of caveats to this, and I can't guarantee that it will work in every possible scenario. Furthermore, if you "override" a cml::matrix<> class using this hack, you'll need to make sure that the data you pass in has the right layout for your application (row-major or col-major).

Hope this helps a bit.
Cheers,
Demian

Share this post


Link to post
Share on other sites
Quote:
Original post by sirGustav
If it sounded as I questioned his (or your) design-decisions I'm sorry.


Sorry, my statement was a bit strong.

Quote:

I am looking for a math library for me, to suit my codingstyle, that I can use in my spare-time for my games. I want the library to fit my design goals.


Given the results of your search, why not build the API framework you want and use the implementation code from the other libraries?

Quote:

My main problem is this code:
class Character {
Vector<float> position;
int health;
;
Wherever I include the character, I get the implementation of full mathclass, even though I don't want it. This is the downside of everything being implemented as templates.


With my libraries, I use explicit instantiation for 'float' and 'double', so you get *everything* generated in LibFoundation. If you were to remove the explicit instantiation and make Math<Real> a template class, the code will still be generated when you use it. Maybe you want to be able to specify some of the template functions to be inline (the only objection I can see that is valid). Even so, is the object code generated by the math class causing your application executable to be too large?

My VectorN<Real> classes (N = 2,3,4) include use of Math<Real> functions, which is why I included Wm4Math.h. If you do not include Wm4Math.h, then the Length function does not have access to Math<Real>::Sqrt. You can hard-code the call using: (Real)sqrt((Real)value), but what does this buy you? One of the reasons I have the wrappers is to avoid the float/double issue (using sqrtf for 'float' and sqrt for 'double'). But more so it allows you to trap unexpected conditions; for example, what if the input to Sqrt is negative? For a game, this is a moot point anyway. I use vectorized math to take advantage of the SIMD processors :)

Bottom line is that with templates and no explicit instantiaion, and given your unwillingness to include the math header, you have to remove any functions from VectorN<Real> that use math functions. Maybe this is all you want--a tuple class that does basic arithmetic.

Share this post


Link to post
Share on other sites
Quote:
Original post by Dave Eberly
Given the results of your search, why not build the API framework you want and use the implementation code from the other libraries?
That is what I'm doing at the moment, however I was hoping someone else already had done it saving me the trouble of writing and testing code :)

Quote:
With my libraries, I use explicit instantiation for 'float' and 'double', so you get *everything* generated in LibFoundation
must have missed that, sorry

Quote:
One of the reasons I have the wrappers is to avoid the float/double issue (using sqrtf for 'float' and sqrt for 'double'). But more so it allows you to trap unexpected conditions; for example, what if the input to Sqrt is negative? For a game, this is a moot point anyway.
I solved that by doing something alike what mfc did with ansi/wide strings. A typedef based on a global #define, and wrapper functions that use that typedef.

Quote:
Maybe this is all you want--a tuple class that does basic arithmetic.
nope maybe it's better with a basic example...

// <sml/vec2d>
#include <sml/config>

namespace sml
{
struct vec2
{
real x; // edit: anon struct(and thus the union) was removed
real y; // since it wasnt standard C++

vec2(real x, real y);
void operator+=(const vec2& rhs);
void operator-=(const vec2& rhs);
void operator*=(const real rhs);
void operator/=(const real rhs);
};
}

// <sml/vec2op>
#include <sml/config>

namespace sml
{
struct vec2;

real LengthOf(const vec2& vec);
real LengthOfSquared(const vec2& vec);

const vec2 GetNormalized(const vec2& vec);
void Normalize(vec2* vec);

const vec2 operator+(const vec2& lhs, const vec2& rhs);
const vec2 operator-(const vec2& lhs, const vec2& rhs);

const vec2 operator*(const real scalar, const vec2& vec);
const vec2 operator*(const vec2& vec, const real scalar);

const vec2 operator/(const vec2& vec, const real scalar);
const vec2 operator-(const vec2& vec);
}


Headers that need the definition can include the definition header(d). Files that actually use the vector can include the operations header(op). Obviously there is still stuff missing.

[Edited by - sirGustav on October 20, 2008 3:56:16 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by sirGustav
Headers that need the definition can include the definition header(d). Files that actually use the vector can include the operations header(op). Obviously there is still stuff missing.


With your system, when someone wants to add two vec2 objects, they need to suck in math code because of the presence of the LengthOf function. How is this any different from what I am doing?

Share this post


Link to post
Share on other sites
The math header is only included in the implementation, so when the operation header is included only the real-typedef-header is included, nothing more. To get the math header you have to include it yourself. However if you include the op header you get than the LengthOf function plus other that you may not want, but there is no "real-world" way around that(afaik).

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this