operator overload deletes function - c++

So I am getting back into graphics programming, and the book I'm using for reference (Frank Luna's 3D Game Programming with DirectX 11), uses no-longer-supported xnamath.h. I have changed it to use DirectXMath.h seemingly without any problems. However, there seems to be problem when I overload the ostream << operator to work with XMVECTORs. When I try to use cout to print an XMVECTOR object, I get this error:
Error 1 error C2280: 'std::basic_ostream<char,std::char_traits<char>>::basic_ostream(const std::basic_ostream<char,std::char_traits<char>> &)' : attempting to reference a deleted function
There is only one file in this program (main.cpp):
#include <Windows.h>
#include <DirectXMath.h>
#include <iostream>
using namespace DirectX;
using namespace std;
// Overload the "<<" operators so that we can use cout to output XMVECTOR objects
ostream& operator<<(ostream os, FXMVECTOR v);
int main() {
cout.setf(ios_base::boolalpha);
// Check support for SSE2 (Pentium4, AMD K8, and above
if (!XMVerifyCPUSupport()) {
cout << "DirectX Math not supported" << endl;
return 0;
}
XMVECTOR n = XMVectorSet(1.0f, 0.0f, 0.0f, 0.0f);
XMVECTOR u = XMVectorSet(1.0f, 2.0f, 3.0f, 0.0f);
XMVECTOR v = XMVectorSet(-2.0f, 1.0f, -3.0f, 0.0f);
XMVECTOR w = XMVectorSet(0.707f, 0.707f, 0.0f, 0.0f);
// Vector addition: XMVECTOR operator +
XMVECTOR a = u + v;
cout << a;
}
ostream& operator<<(ostream os, FXMVECTOR v) {
XMFLOAT3 dest;
XMStoreFloat3(&dest, v);
os << "(" << dest.x << ", " << dest.y << ", " << dest.z << ")";
return os;
}
I have a feeling I'm messing up the operator-overloading, but I'm not really sure at this point. I couldn't find any similar problems online, but I hope I'm just overlooking something really basic. Any advice will be appreciated.

The problem is in this line:
ostream& operator<<(ostream os, FXMVECTOR v) {
Change it to
ostream& operator<<(ostream& os, FXMVECTOR v) {
The first line tries to make a copy of ostream using a copy constructor. That is not allowed.

Related

How to write vectors member to file

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;
}

How to normalize the vertice of a 3d mesh into a unit cube, centered in the origin?

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';
}
}

Undefined reference to operator << in inherited class

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.

Initializing struct vector with brace-enclosed initializer list

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

C++ weird problem, Undefined reference

getting error: neljastest.cpp: undefined reference to Vector2::Vector2(float, float)
neljastest.cpp:
#include <cstdlib>
#include <iostream>
#include "../include/Vector2.h"
#include "../include/neljas.h"
using namespace std;
int main (int argc, char* argv[]) {
Vector2 p1 (1.0, 2.0);
Vector2 p2 (0.0, 0.0);
Vector2 p3 (5.0, 2.0);
return EXIT_SUCCESS;
}
vector2.h:
#ifndef VECTOR2_H
#define VECTOR2_H
#include <iostream>
using std::ostream;
class Vector2 {
public:
float x;
float y;
Vector2();
Vector2(float nx, float ny);
float distanceFrom(Vector2 v);
};
ostream& operator << (ostream& valja, Vector2 v);
#endif
vector2.cpp:
#include "../include/Vector2.h"
#include <cmath>
using namespace std;
Vector2::Vector2() {
x = 0;
y = 0;
}
Vector2::Vector2(float nx, float ny) {
x = nx;
y = ny;
}
float Vector2::distanceFrom(Vector2 v) {
return sqrt( (x - v.x)*(x - v.x) + (y - v.y)*(y - v.y) );
}
ostream& operator << (ostream& os, Vector2 v) {
return os << "(" << v.x << "," << v.y << ")";
}
C/C++ are case sensitive for headers too.
It seems that on vector2.cpp and neljastest.cpp you must change the include from:
#include "../include/Vector2.h"
To:
#include "../include/vector2.h"
I pasted all your sources on the same folder and successfully compiled them with:
g++ neljastest.cpp vector2.cpp -o neljastest
Edit:
Your problem is that the linking process of neljastest.cpp depends on src/vector2.cpp, and you are not doing that on the Makefile