views:

66

answers:

3

Hi there,

I try to use GLM vector classes in STL containers. No big deal as long as I don't try to use <algorithm>. Most algorithms rely on the == operator which is not implemented for GLM classes.

Anyone knows an easy way to work around this? Without (re-)implementing STL algorithms :(

Kind Regards, Florian

GLM is a great math library implementing GLSL functions in c++

Update

I just found out that glm actually implements comparison operators in an extension (here). But how do i use them in stl?

Update 2

This question has been superseded by this one: http://stackoverflow.com/questions/3891497/how-to-use-glms-operator-in-stl-algorithms

+4  A: 

Many STL algorithms accept a functor for object comparison (of course, you need to exercise special care when comparing two vectors containing floating point values for equality).

Example:

To sort a std::list<glm::vec3> (it's up to you whether sorting vectors that way would make any practical sense), you could use

std::sort(myVec3List.begin(), myVec3List.end(), MyVec3ComparisonFunc)

with

bool MyVec3ComparisonFunc(const glm::vec3 &vecA, const glm::vec3 &vecB)
{
 return vecA[0]<vecB[0] 
        && vecA[1]<vecB[1] 
        && vecA[2]<vecB[2];
}

So, thankfully, there is no need to modify GLM or even reinvent the wheel.

Greg S
this is the 'nice object oriented' solution ... i actually like that ... but the other is simpler
Florian
@Florian: I'm not sure if this one is more object-oriented, but it is the more flexible one. My criteria for which to use would be whether this is *always* the way vectors are ordered. If this is the one and only way to test if one glm vectors is "less than" another, go ahead and define an `operator<` (it probably isn't. Vectors could also be ordered by length, for example). Otherwise, write it as a functor, and use it when you need this particular definition.
jalf
yep ... i think both are valid answers (and i would mark them both as accepted if it were possible) ... but i'll be going this wayThe guys over at glm's will have their reasons not to include the == operator so i won't implement it myself.Thanks everybody!
Florian
+3  A: 

You should be able to implement a operator== as a stand-alone function:

// (Actually more Greg S's code than mine.....)

bool operator==(const glm::vec3 &vecA, const glm::vec3 &vecB) 
{ 
   const double epsilion = 0.0001;  // choose something apprpriate.

   return    fabs(vecA[0] -vecB[0]) < epsilion   
          && fabs(vecA[1] -vecB[1]) < epsilion   
          && fabs(vecA[2] -vecB[2]) < epsilion   
} 
James Curran
Greg S
@Greg: I gotta pay more attention when I steal code...
James Curran
this is the simpler solution ... i actually like that ... but the other is more object oriented :/
Florian
@Florian : No, the two solutions have the same "OOP depth". James' solution is global, deciding the "normal" way of comparing GLM vectors using the `operator ==` function. Greg S's solution is more context specific: For this or this processing or container, the comparison should be done using this or this functor... Conclusion: If you believe there is only one (or only one major) way to compare GLM vectors, then put the implementation in a `operator ==` function.
paercebal
+1  A: 

James Curran and Greg S have already shown you the two major approaches to solving the problem.

  • define a functor to be used explicitly in the STL algorithms that need it, or
  • define the actual operators == and < which STL algorithms use if no functor is specified.

Both solutions are perfectly fine and idiomatic, but a thing to remember when defining operators is that they effectively extend the type. Once you've defined operator< for a glm::vec3, these vectors are extended to define a "less than" relationship, which means that any time someone wants to test if one vector is "less than" another, they'll use your operator. So operators should only be used if they're universally applicable. If this is always the one and only way to define a less than relationship between 3D vectors, go ahead and make it an operator.

The problem is, it probably isn't. We could order vectors in several different ways, and none of them is obviously the "right one". For example, you might order vectors by length. Or by magnitude of the x component specifically, ignoring the y and z ones. Or you could define some relationship using all three components (say, if a.x == b.x, check the y coordinates. If those are equal, check the z coordinates)

There is no obvious way to define whether one vector is "less than" another, so an operator is probably a bad way to go.

For equality, an operator might work better. We do have a single definition of equality for vectors: two vectors are equal if every component is equal.

The only problem here is that the vectors consist of floating point values, and so you may want to do some kind of epsilon comparison so they're equal if all members are nearly equal. But then the you may also want the epsilon to be variable, and that can't be done in operator==, as it only takes two parameters.

Of course, operator== could just use some kind of default epsilon value, and functors could be defined for comparisons with variable epsilons.

There's no clear cut answer on which to prefer. Both techniques are valid. Just pick the one that best fits your needs.

jalf