StickyBits
StickyBits

Reputation: 53

How do I use GLM Vector Relational Functions?

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

Answers (2)

logan abel
logan abel

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

user4290866
user4290866

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

Related Questions