I'm trying to write vector's members to file but I get this error for loop operation:
no operator "<<" matches these operands
How can I write those members to file?
std::ofstream raport;
raport.open("test.txt", std::ios_base::app);
std::vector<std::vector<float>> targetInputs = {
{0.0f, 0.0f},
{1.0f, 1.0f},
{1.0f, 0.0f},
{0.0f, 1.0f}
};
for (int i = 0;i < targetInputs.size(); i++) {
raport << targetInputs[i];
}
Example with range based for loop.
The const references are there since output should never modify the input data.
The ostringstream is a standin stream for your file.
#include <iostream>
#include <sstream>
#include <vector>
int main()
{
std::ostringstream raport;
//raport.open("test.txt", std::ios_base::app);
std::vector<std::vector<float>> targetInputs = {
{0.0f, 0.0f},
{1.0f, 1.0f},
{1.0f, 0.0f},
{0.0f, 1.0f}
};
for (const auto& values : targetInputs)
{
for (const auto& value : values)
{
raport << value << " ";
}
raport << "\n";
}
std::cout << raport.str();
return 0;
}
I have got all the vertices of the 3d mesh. And I need to scale it into a unit cube with the diagonal point being(-0.5,-0.5,-0.5),(0.5,0.5,0.5);
How could I get the new vertice of the 3d mesh?
And since I need to do this in the vertex shader, which matrix can I multiple the vertice?
It's very usual to provide a model matrix for OPs purpose. There are plenty of sources in the Web where OpenGL transformations are explained. To name a few of them:
SO: How to scale a model in OpenGL?
Learn OpenGL: Transformations
OpenGL Tutorial: Matrices.
Transformations and transformation matrices are absolutely worth to be learned even although this might appear difficult at the first glance. It's the basic tool for a lot of things in 3d graphics, Visual Simulation, and Animation.
The transformation of the mesh could / should be done by the shader. For this, the resp. model matrix has to be passed as uniform (and used to transform the incoming vertices, of course).
To prepare this model matrix:
Determine the bounding box of your mesh. This is rather trivial: get min and max for x, y, z components of all vertices.
size = max - min provides the size in x, y, z direction.
center = (min + max) / 2 provides the center of your bounding box.
To scale the size to 1 you need a scale matrix with (1 / size.x, 1 / size.y, 1 / size.z). (Hopefully, no component of size will be 0. Otherwise, you have to exclude it.)
Multiply the scale matrix with a translate matrix for -center. (In the special case, that the center is already (0, 0, 0) this won't do any harm.)
Demo:
int main()
{
const float vertices[] = {
-10.0f, -3.0f, -2.0f,
3.0f, 10.0f, 0.0f,
2.0f, -3.0f, 1.0f,
};
const size_t nVtcs = std::size(vertices) / 3;
// determine bounding box
std::pair<Vec3f, Vec3f> bBox = boundingBox(vertices, nVtcs);
std::cout << "min: " << bBox.first << ", max: " << bBox.second << '\n';
// size of bounding box
const Vec3f sizeBBox = bBox.second - bBox.first;
std::cout << "size: " << sizeBBox << '\n';
// center of bound box
const Vec3f center = (bBox.first + bBox.second) * 0.5f;
std::cout << "center: " << center << '\n';
// make scale matrix
const Mat4x4f matS
= scale(Vec3f{
sizeBBox.x > 0.0f ? 1 / sizeBBox.x : 1.0f,
sizeBBox.y > 0.0f ? 1 / sizeBBox.y : 1.0f,
sizeBBox.z > 0.0f ? 1 / sizeBBox.z : 1.0f });
//std::cout << "matS:\n" << matS;
// make center matrix
const Mat4x4f matT = translate(-center);
//std::cout << "matT:\n" << matT;
// make model matrix
const Mat4x4f matM = matS * matT;
//std::cout << "matM:\n" << matM;
// check model matrix (would be done in shader):
std::cout << "Vertex transform:\n";
for (size_t i = 0; i < nVtcs; ++i) {
const Vec3f vtx(vertices[3 * i + 0], vertices[3 * i + 1], vertices[3 * i + 2]);
std::cout << " " << (matM * Vec4f(vtx, 1.0f)) << '\n';
}
}
Output:
min: -10, -3, -2, max: 3, 10, 1
size: 13, 13, 3
center: -3.5, 3.5, -0.5
Vertex transform:
-0.5, -0.5, -0.5, 1
0.5, 0.5, 0.166667, 1
0.423077, -0.5, 0.5, 1
Live Demo on coliru
The output looks promising: for each component, at least, one vector provides the target min. and max. values of -0.5 and 0.5.
To make it an MCVE, I included all needed lin. algebra. This is for what the OP might use glm instead, which is more comprehensive but similar to use.
Instead of the final transformation of vertices (done in output loop), OP would feed vertices and the model matrix into the shader which will be in charge to do it. (The vertices will become a shader attribute, the model matrix a uniform.)
#include <iostream>
template <typename V>
struct Vec3T {
V x = (V)0;
V y = (V)0;
V z = (V)0;
Vec3T() = default;
Vec3T(V x, V y, V z): x(x), y(y), z(z) { }
};
template <typename V>
Vec3T<V> operator-(const Vec3T<V>& vec)
{
return { -vec.x, -vec.y, -vec.z };
}
template <typename V>
Vec3T<V> operator+(const Vec3T<V>& vec1, const Vec3T<V>& vec2)
{
return { vec1.x + vec2.x, vec1.y + vec2.y, vec1.z + vec2.z };
}
template <typename V>
Vec3T<V> operator-(const Vec3T<V>& vec1, const Vec3T<V>& vec2)
{
return { vec1.x - vec2.x, vec1.y - vec2.y, vec1.z - vec2.z };
}
template <typename V, typename S>
Vec3T<V> operator*(const Vec3T<V>& vec, S s)
{
return { vec.x * s, vec.y * s, vec.z * s };
}
template <typename V>
std::ostream& operator<<(std::ostream& out, const Vec3T<V>& vec)
{
return out << vec.x << ", " << vec.y << ", " << vec.z;
}
template <typename V>
struct Vec4T {
V x = (V)0;
V y = (V)0;
V z = (V)0;
V w = (V)0;
Vec4T() = default;
Vec4T(V x, V y, V z, V w): x(x), y(y), z(z), w(w) { }
template<typename U>
Vec4T(const Vec3T<U>& vec, V w): x(vec.x), y(vec.y), z(vec.z), w(w) { }
};
template <typename V>
std::ostream& operator<<(std::ostream& out, const Vec4T<V>& vec)
{
return out << vec.x << ", " << vec.y << ", " << vec.z << ", " << vec.w;
}
template <typename V>
constexpr V dot(const Vec4T<V>& vec1, const Vec4T<V>& vec2)
{
return vec1.x * vec2.x + vec1.y * vec2.y
+ vec1.z * vec2.z + vec1.w * vec2.w;
}
template <typename V>
struct Mat4x4T {
Vec4T<V> cols[4] = { };
Mat4x4T() = default;
Mat4x4T(const Vec4T<V> (&cols)[4]): cols(cols) { }
Vec4T<V>& operator[](size_t i) { return cols[i]; }
const Vec4T<V>& operator[](size_t i) const { return cols[i]; }
};
template <typename V>
Mat4x4T<V> transpose(const Mat4x4T<V>& mat)
{
return Mat4x4T<V>({
{ mat[0].x, mat[1].x, mat[2].x, mat[3].x },
{ mat[0].y, mat[1].y, mat[2].y, mat[3].y },
{ mat[0].z, mat[1].z, mat[2].z, mat[3].z },
{ mat[0].w, mat[1].w, mat[2].w, mat[3].w }
});
}
template <typename V>
Mat4x4T<V> operator*(const Mat4x4T<V>& mat1, const Mat4x4T<V>& mat2)
{
const Mat4x4T<V> mat1T = transpose(mat1);
return Mat4x4T<V>({
{ dot(mat1T.cols[0], mat2.cols[0]),
dot(mat1T.cols[1], mat2.cols[0]),
dot(mat1T.cols[2], mat2.cols[0]),
dot(mat1T.cols[3], mat2.cols[0])
},
{ dot(mat1T.cols[0], mat2.cols[1]),
dot(mat1T.cols[1], mat2.cols[1]),
dot(mat1T.cols[2], mat2.cols[1]),
dot(mat1T.cols[3], mat2.cols[1])
},
{ dot(mat1T.cols[0], mat2.cols[2]),
dot(mat1T.cols[1], mat2.cols[2]),
dot(mat1T.cols[2], mat2.cols[2]),
dot(mat1T.cols[3], mat2.cols[2])
},
{ dot(mat1T.cols[0], mat2.cols[3]),
dot(mat1T.cols[1], mat2.cols[3]),
dot(mat1T.cols[2], mat2.cols[3]),
dot(mat1T.cols[3], mat2.cols[3])
}
});
}
template <typename V>
Vec4T<V> operator*(const Mat4x4T<V>& mat, const Vec4T<V>& vec)
{
const Mat4x4T<V> matT = transpose(mat);
return Vec4T<V>(
dot(matT.cols[0], vec),
dot(matT.cols[1], vec),
dot(matT.cols[2], vec),
dot(matT.cols[3], vec));
}
template <typename V>
Mat4x4T<V> scale(const Vec3T<V>& s)
{
return Mat4x4T<V>({
{ s.x, (V)0, (V)0, (V)0 },
{ (V)0, s.y, (V)0, (V)0 },
{ (V)0, (V)0, s.z, (V)0 },
{ (V)0, (V)0, (V)0, (V)1 }
});
}
template <typename V>
Mat4x4T<V> translate(const Vec3T<V>& t)
{
return Mat4x4T<V>({
{ (V)1, (V)0, (V)0, (V)0 },
{ (V)0, (V)1, (V)0, (V)0 },
{ (V)0, (V)0, (V)1, (V)0 },
{ t.x, t.y, t.z, (V)1 }
});
}
template <typename V>
std::ostream& operator<<(std::ostream& out, const Mat4x4T<V>& mat)
{
return out
<< mat[0].x << '\t' << mat[1].x << '\t' << mat[2].x << '\t' << mat[3].x << '\n'
<< mat[0].y << '\t' << mat[1].y << '\t' << mat[2].y << '\t' << mat[3].y << '\n'
<< mat[0].z << '\t' << mat[1].z << '\t' << mat[2].z << '\t' << mat[3].z << '\n'
<< mat[0].w << '\t' << mat[1].w << '\t' << mat[2].w << '\t' << mat[3].w << '\n';
}
template <typename V>
void updateMinMax(Vec3T<V> value, Vec3T<V>& min, Vec3T<V>& max)
{
if (min.x > value.x) min.x = value.x;
if (max.x < value.x) max.x = value.x;
if (min.y > value.y) min.y = value.y;
if (max.y < value.y) max.y = value.y;
if (min.z > value.z) min.z = value.z;
if (max.z < value.z) max.z = value.z;
}
using Vec3f = Vec3T<float>;
using Vec4f = Vec4T<float>;
using Mat4x4f = Mat4x4T<float>;
template <typename V>
std::pair<Vec3T<V>, Vec3T<V>> boundingBox(const V* vtcs, size_t nVtcs)
{
if (!nVtcs) return { { }, { } };
Vec3T<V> min(vtcs[0], vtcs[1], vtcs[2]);
Vec3T<V> max = min;
for (size_t i = 1; i < nVtcs; ++i) {
const Vec3T<V> vtx(vtcs[3 * i + 0], vtcs[3 * i + 1], vtcs[3 * i + 2]);
updateMinMax(vtx, min, max);
}
return { min, max };
}
int main()
{
const float vertices[] = {
-10.0f, -3.0f, -2.0f,
3.0f, 10.0f, 0.0f,
2.0f, -3.0f, 1.0f,
};
const size_t nVtcs = std::size(vertices) / 3;
// determine bounding box
std::pair<Vec3f, Vec3f> bBox = boundingBox(vertices, nVtcs);
std::cout << "min: " << bBox.first << ", max: " << bBox.second << '\n';
// size of bounding box
const Vec3f sizeBBox = bBox.second - bBox.first;
std::cout << "size: " << sizeBBox << '\n';
// center of bound box
const Vec3f center = (bBox.first + bBox.second) * 0.5f;
std::cout << "center: " << center << '\n';
// make scale matrix
const Mat4x4f matS
= scale(Vec3f{
sizeBBox.x > 0.0f ? 1 / sizeBBox.x : 1.0f,
sizeBBox.y > 0.0f ? 1 / sizeBBox.y : 1.0f,
sizeBBox.z > 0.0f ? 1 / sizeBBox.z : 1.0f });
//std::cout << "matS:\n" << matS;
// make center matrix
const Mat4x4f matT = translate(-center);
//std::cout << "matT:\n" << matT;
// make model matrix
const Mat4x4f matM = matS * matT;
//std::cout << "matM:\n" << matM;
// check model matrix (would be done in shader):
std::cout << "Vertex transform:\n";
for (size_t i = 0; i < nVtcs; ++i) {
const Vec3f vtx(vertices[3 * i + 0], vertices[3 * i + 1], vertices[3 * i + 2]);
std::cout << " " << (matM * Vec4f(vtx, 1.0f)) << '\n';
}
}
I'm trying to overload the << and >> operators for a polygon class and a derived triangle class. The problem is that my compiler is returning the following error:
error: undefined reference to `operator<<(std::ostream&, triangle const&)'
I am fairly certain that I did define the above operator however. I have the following line in my triangle.h file:
std::ostream & operator << (std::ostream & os, triangle const&);
This problem occurs specifically for the triangle class. When I remove the line trying to output a triangle, my program works correctly. There is no problem outputting a polygon. What is causing this problem and how do I fix it? Is it a problem with my include hierarchy?
I think the relevant files are main.cpp, triangle.h, and triangle.cpp but I included a full copy of my code below in case the error is caused by something else. Thank you for your help and patience.
main.cpp
#include <iostream>
#include "triangle.h"
using namespace std;
int main()
{
triangle t (vertex (0, 0), vertex (5, 0), vertex (0, 5));
triangle l (t);
cout << l[0] << endl;
cout << "L: " << l << endl; //not working
polygon p;
p.add (vertex (0,0));
cout << "P: " << p << endl; //working
return 0;
}
triangle.h
#include "polygon.h"
#include <iostream>
class triangle : public polygon
{
public:
triangle(vertex = vertex(), vertex = vertex(), vertex = vertex());
triangle(const triangle &);
double area() const;
vertex operator[](size_t i) const;
private:
size_t size() const;
void add(vertex iv);
std::vector<vertex> v;
};
std::ostream & operator << (std::ostream & os, triangle const&);
std::istream & operator >> (std::istream & is, triangle & t);
triangle.cpp
#include "triangle.h"
#include <math.h>
#include <cassert>
triangle::triangle(vertex ta, vertex tb, vertex tc)
{
v.push_back(ta);
v.push_back(tb);
v.push_back(tc);
}
triangle::triangle(const triangle & t)
{
v=t.v;
}
double triangle::area() const
{
double a=sqrt((v[0].x-v[1].x)*(v[0].x-v[1].x)+(v[0].y-v[1].y)*(v[0].y-v[1].y));
double b=sqrt((v[1].x-v[2].x)*(v[1].x-v[2].x)+(v[1].y-v[2].y)*(v[1].y-v[2].y));
double c=sqrt((v[2].x-v[0].x)*(v[2].x-v[0].x)+(v[2].y-v[0].y)*(v[2].y-v[0].y));
double s=((a+b+c)/2);
return sqrt(s*(s-a)*(s-b)*(s-c));
}
vertex triangle::operator[] (std::size_t i) const
{
assert (i<3);
return v[i];
}
inline std::ostream & operator << (std::ostream & os, triangle const & t)
{
std::cout << "test" << std::endl;
return os << t[0];
}
std::istream & operator >> (std::istream & is, triangle & t)
{
vertex vx;
for (size_t i = 0; i < 3; ++i)
{
is >> vx.x >> vx.y;
//t.v.push_back(vx);
}
return is;
}
polygon.h
#include <iostream>
#include <vector>
#include "vertex.h"
class polygon
{
public:
// pre:
// post: empty polygon created
polygon();
// pre:
// post: polygon created and initialized to given polygon source
polygon(const polygon & source);
// pre:
// post: return number of vertices in this polygon
std::size_t size() const;
// pre: 0 <= i < size()
// post: return vertex i in this polygon
vertex operator[](size_t i) const;
// pre:
// post: vertex is added to this polygon
void add(const vertex & v);
private:
std::vector<vertex> v;
};
std::ostream & operator << (std::ostream & os, const polygon & p);
std::istream & operator >> (std::istream & is, polygon & p);
polygon.cpp
#include <cassert>
#include "polygon.h"
polygon::polygon()
{
v = std::vector<vertex> ();
}
polygon::polygon(const polygon & p)
{
v = p.v;
}
std::size_t polygon::size() const
{
return v.size();
}
vertex polygon::operator[] (std::size_t i) const
{
assert(i < size());
return v[i];
}
void polygon::add(const vertex & vx)
{
v.push_back(vx);
}
std::ostream & operator << (std::ostream & os, const polygon & p)
{
for (std::size_t i = 0; i < p.size(); ++i)
os << p[i] << " ";
return os;
}
std::istream & operator >> (std::istream & is, polygon & p)
{
std::size_t n;
vertex vx;
is >> n;
for (size_t i = 0; i < n; ++i)
{
is >> vx.x >> vx.y;
p.add(vx);
}
return is;
}
vertex.h
#include <iostream>
struct vertex
{
double x, y;
vertex(double ix = 0.0, double iy = 0.0)
{
x = ix;
y = iy;
}
};
std::ostream & operator << (std::ostream & os, const vertex & v);
vertex.cpp
#include "vertex.h"
std::ostream & operator << (std::ostream & os, const vertex & v)
{
os << "(" << v.x << ", " << v.y << ")";
return os;
}
Here's your problem:
// triangle.cpp
inline std::ostream & operator << (std::ostream & os, triangle const & t)
^^^^^^
Inline functions must be defined in all translation units that use them, and this is only defined in one. Either remove inline, or move the definition into the header to make it available anywhere its used.
I initialize normal-type vectors like this:
vector<float> data = {0.0f, 0.0f};
But when I use structure instead of normal-type
struct Vertex
{
float position[3];
float color[4];
};
vector<Vertex> data = {{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}};
I get error could not convert '{{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}}' from '<brace-enclosed initializer list>' to 'std::vector<Vertex>'. What's wrong with this?
A set of {} is missing:
std::vector<Vertex> data =
{ // for the vector
{ // for a Vertex
{0.0f, 0.0f, 0.0f}, // for array 'position'
{0.0f, 0.0f, 0.0f, 0.0f} // for array 'color'
},
{
{0.0f, 0.0f, 0.0f},
{0.0f, 0.0f, 0.0f, 0.0f}
}
};
you need one more {} actually
vector<Vertex> data = {{{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}}};
one '{' for vector, one for struct, one (couple of) for struct member-arrays...
An object with vector members can also be initialized.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Test
{
public:
struct NumStr
{
int num;
string str;
};
Test(vector<int> v1,vector<NumStr> v2) : _v1(v1),_v2(v2) {}
vector<int> _v1;
vector<NumStr> _v2;
};
int main()
{
Test t={ {1,2,3}, {{1,"one"}, {2,"two"}, {3,"three"}} };
cout << t._v1[1] << " " << t._v2[1].num << " " << t._v2[1].str << endl;
return 0;
}
2 2 two