Reputation: 53
I'm trying to create an std::set of GLM vectors (glm::vec3 specifically). Since C++ does not know how to perform < operation on the vectors, I must pass in a Compare funciton.
I can write my own by creating a structure like so:
struct compareVec
{
bool operator() (const glm::vec3& lhs, const glm::vec3& rhs) const
{
return lhs.x < rhs.x && lhs.y < rhs.y && lhs.z < rhs.z;
}
};
std::set< glm::vec3, compareVec > myset;
However, I'm sure that GLM includes their own vector comparison functions.
I found the following resource, but I'm unsure of how to use it: https://glm.g-truc.net/0.9.4/api/a00137.html
How can I pass one of these comparison functions to my set?
Upvotes: 3
Views: 4999
Reputation: 11
By giving priority to early components of the vec, we can avoid (1,2,3) and (0,1,4) from both being less than each other. what we want is something that does the same thing as this:
lh.x != rh.x ?
lh.x < rh.x
: lh.y != rh.y ?
lh.y < rh.y
: lh.z < rh.z
I believe this should work as the compareVec:
struct compareVec {
bool operator() (const glm::vec3& lhs, const glm::vec3& rhs) const
{
glm::vec3 nequ = glm::notEqual(lhs, rhs);
return glm::lessThan(lhs, rhs)[nequ[0] ? 0 : nequ[1] ? : 1 : 2];
}
};
I couldn't find a glm function that returns the first index that is true, so I just used nequ[0] ? 0 : nequ[1]? : 1 : 2
Upvotes: 1
Reputation:
Ok, almost there! The glm::lessThan returns a vector type, not a bool. This is why your comparator does not work. You could use glm::all
on it to get a bool. From Documentation of glm::all
bool glm::all ( vecType< bool > const & v )
Returns true if all components of x are true.
Template Parameters vecType Boolean vector types.
If this makes sense for you, you have to decide for yourself, even if I recommend against it as this, as far as I understand, will lead to the following issue:
Consider:
lhs = (1,2,3)
rhs = (0,1,4)
Than:
lhs < rhs ==> false, since lhs.x and lhs.y are larger than the corresponding components of rhs
rhs < lhs ==> false, since rhs.z component is larger than lhs.z
Since neither vector can be ordered to be less, this implies that they are equal. I doubt this is the behavior you have in mind (I was already warning you about this).
If you still decide to use it, here is a minimal working example tested on MSVC2010:
#include <set>
#include <glm/vec3.hpp>
#include <glm/detail/func_vector_relational.hpp>
struct compareVec
{
bool operator() (const glm::vec3& lhs, const glm::vec3& rhs) const
{
return glm::all(glm::lessThan(lhs, rhs));
}
};
int main()
{
std::set<glm::vec3, compareVec> myset;
return 0;
}
Maybe this helps.
Upvotes: 7