How do I print vector values of type glm::vec3 that have been passed by reference?

C++Glm Math

C++ Problem Overview


I have a small obj loader and it takes two parameters and passes them back to the input variables.. however this is my first time doing this and i'm not sure how to print said values now. Here is my main function to test if the loader is working. I have two vectors of type glm::vec3 to hold the vertex and normal data.

std::vector<glm::vec3> vertices;
std::vector<glm::vec3> normals;    

int main() {
    bool test = loadOBJ("cube.obj", vertices, normals);
    for (int i = 0; i < vertices.size(); i++) {
       std::cout << vertices[i] << std::endl;   // problem line
    }

    return 0;   
}

The line commented above is what is generating useless info. If I leave it like that and run the program I get a bunch of errors spewed at me (too unformatted and long to paste here) and if I add the reference operator I get output like this:

0x711ea0
0x711eac
0x711eb8
0x711ec4    // etc

Any idea what I am doing wrong?

C++ Solutions


Solution 1 - C++

glm has an extension for this. Add #include "glm/ext.hpp" or "glm/gtx/string_cast.hpp"

Then to print a vector for example:

glm::vec4 test;
std::cout<<glm::to_string(test)<<std::endl;

Solution 2 - C++

I think the most elegant solution might be a combination of the two answers already posted, with the addition of templating so you don't have to reimplement the operator for all vector/matrix types (this restricts the function definition to header files, though).

#include <glm/gtx/string_cast.hpp>

template<typename genType>
std::ostream& operator<<(std::ostream& out, const genType& g)
{
    return out << glm::to_string(g);
}

Solution 3 - C++

glm::vec3 doesn't overload operator<< so you can't print the vector itself. What you can do, though, is print the members of the vector:

std::cout << "{" 
          << vertices[i].x << " " << vertices[i].y << " " << vertices[i].z 
          << "}";

Even better, if you use that a lot, you can overload operator<< yourself:

std::ostream &operator<< (std::ostream &out, const glm::vec3 &vec) {
    out << "{" 
        << vec.x << " " << vec.y << " "<< vec.z 
        << "}";

    return out;
}

Then to print, just use:

std::cout << vertices[i];

Solution 4 - C++

GLM has operator<<() in <glm/gtx/io.hpp>

#include <iostream>
#include <glm/glm.hpp>
#include <glm/gtx/io.hpp>

int main()
{
   glm::vec3 v(1.0f, 2.0f, 3.0f);
   std::cout << v << std::endl;
}

Output is:

[    1.000,    2.000,    3.000]

Solution 5 - C++

To get the overload resolution right, you can do something like:

// Writes a generic GLM vector type to a stream.
template <int D, typename T, glm::qualifier P>
std::ostream &operator<<(std::ostream &os, glm::vec<D, T, P> v) {
  return os << glm::to_string(v);
}

Solution 6 - C++

Elaborating on JAB's answer, I use the following to avoid 'operator <<' is ambiguous errors:

#include <glm/glm.hpp>
#include <glm/gtx/string_cast.hpp>

/**
 * can_cout<T> tells whether there already exists an override of operator<< that
 * supports T.
 */
template <typename, typename = void>
struct can_cout : public std::false_type {};

template <typename T>
struct can_cout<T, std::void_t<decltype(operator<<(std::declval<std::ostream>(), std::declval<T>()))> > : public std::true_type {};

/**
 * Implement operator<< iff GlmType is handled by glm::to_string but there is
 * not already an override of operator<< that hanldes this type.
 */
template<
	typename GlmType,
	typename = std::enable_if_t<!can_cout<GlmType>::value>,
	typename = decltype(glm::to_string(std::declval<GlmType>()))
>
std::ostream& operator<<(std::ostream& out, const GlmType& g)
{
    return out << glm::to_string(g);
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestioniKlsRView Question on Stackoverflow
Solution 1 - C++user2103388View Answer on Stackoverflow
Solution 2 - C++JABView Answer on Stackoverflow
Solution 3 - C++chrisView Answer on Stackoverflow
Solution 4 - C++GrumbelView Answer on Stackoverflow
Solution 5 - C++Matthew GingellView Answer on Stackoverflow
Solution 6 - C++LithyView Answer on Stackoverflow