I have two vectors, and I would like to fill the first one with the second. The vectors are declared like this:
vector<Vec3> firstVector;
Where Vec3 is a struct with float x, y, z.
I have tried liked this with assign:
secondVector.assign(firstVector.begin(), firstVector.end());
But it stops and complains, that there is problem with the end().
I have also tried pushback, but of course it's not working.
As I read before I should do it with assign, but I don't know how to solve it properly.
EDIT:
The error message with insert and assign are the same:
this 0x00000000 ... std::vector > * const
[size] CXX0030: Error: expression cannot be evaluated
[capacity] CXX0030: Error: expression cannot be evaluated
And it points to Visual Studio's vector file to iterator end to the return. With insert it points to iterator begin.
THE CODE:
The first Vector is also part of a struct:
struct o3DModel
{
vector<Vec3> v_Vertices;
};
struct Vec3 {
public:
Vec3() {}
Vec3(float X, float Y, float Z)
{
x = X;
y = Y;
z = Z;
}
float x, y, z;
};
I declare the "o3DModel" struct above in my app class like this and send it to my loader class:
o3DModel *tfTable;
void TheApp::Init()
{
objLoader->ImportOBJ(tfTable, "testcube.obj");
}
The objLoader class, where I successfully fill my "v_Vertices" vector, where "oModel" is the sent "tfTable":
bool OBJLoader::ImportOBJ(o3DModel *oModel, char *strFileName)
{
FillObjData(oModel);
...
return true;
}
void OBJLoader::FillObjData(o3DModel *oModel)
{
oModel->v_Vertices.insert(oModel->v_Vertices.begin(), v_Vertices.begin(), v_Vertices.end());
// This here with insert
outFile2 << oModel->v_Vertices[0].x << "\n";
}
Hope this helps.
If you want secondVector to take on all of the values of firstVector and no others,
secondVector = firstVector;
If you want each of the elements of firstVector to be added to the end secondVector:
secondVector.insert(secondVector.end(),
firstvector.begin(), firstVector.end());
If you want each of the elements of firstVector to be added to the beginning of secondVector:
secondVector.insert(secondVector.begin(),
firstVector.begin(), firstVector.end());
Or if you don't want to do it in the ctor use
secondVector = firstVector
This should work:
vector<Vec3> secondVector(firstVector.begin(), firstVector.end());
That's the case when you're interested in using the vector constructor.
You second vector needs to be declared as a vector of vectors of Vec3 strucs.
vector<vector<Vec3>> secondVector;
secondVector.push_back(firstVector);
Okay, I have solved it, but with a little roundabout. In FillObjData I have created a new Vec3, created an if, gived the first vector x, y, z coordinate to the new Vec3, and pushed the Vec3 into the vector. And when I declared my struct I have declared it real not as a pointer. Now it works perfectly.
Related
I'm only beginning in C++ and I'm struggling to understand some code from a custom vector class in an article I'm working through. The author writes it as:
class vec3
{
public:
vec3() {}
vec3(float e0, float e1, float e2)
{
e[0] = e0;
e[1] = e1;
e[2] = e2;
}
(...)
But so far I've only seen class definitions where the types of data it holds are defined, such as:
class vec3
{
public:
float m_x;
float m_y;
float m_z;
vec3(float x, float y, float z) : m_x(x), m_y(y), m_z(z)
{}
My guess was that the code in the article is creating an empty vector which it then populates with floats or there was something assumed in the definition. Is this just a syntax difference or is there something more fundamental that I'm missing? Apologies for what seems like a basic question but I couldn't find any similar questions. . . it might be too basic for that! But I just wanted to understand it before I moved on.
Thanks,
Paddy
In the code you've posted, you are correct that there is no declaration for the variable e anywhere. I'm not sure if this is because you didn't post that part of the code from the book, or if the book omitted that for brevity.
Without knowing what the book author was meaning by e, I don't want to suggest a completion of the code. There are several things that e could be declared as that would be compatible with the code you've posted.
It defines e as just a float array [e[3]].
With this information added, then there is no relevant difference between three separate members and an array. In the end, both variants will require the same amount of memory, and in most cases, the (optimised!) code generated by the compiler will be exactly the same:
float getY()
{
return m_y;
// will result in address of object + offset to m_y
}
float getY()
{
return e[1];
// will result in address of object + offset to e + offset to second element
// as both offsets are constant, they will be joined to one single summand
// and we are back at first variant...
}
One of the few things you can do with arrays but not with separate members is having a loop, such as the following:
float magnitude()
{
float sum = 0.0F;
for(auto f : e)
sum += f*f;
return sqrtf(sum);
}
However, for such short loops, loop unrolling is pretty likely, and the code generated again is with high probability equivalent to the separate member variant:
float magnitude()
{
return sqrtf(m_x * m_x + m_y * m_y + m_z * m_z);
}
With an array, you could pass all three members in one single parameter to other functions (as pointer to first element), with separate members, you'd have to pass all of them separately (well, there are ways around, but they either require extra effort or are "dirty"...).
I read somewhere a piece of code for defining 3d coordinate. So, they used x, y & z coordinate like this below:
union
{
struct
{
float x, y, z;
};
float _v[3];
};
My question is that why a union is required here and also what is the advantage of using struct with an array?
Important note: this construct leads to undefined behavior. What follows is a description of its authors' intentions, which, unfortunately, many compilers translate to precisely the behavior the authors expect, which in turn leads to proliferation of code like that.
union construct is not really required here: the authors used it for convenience. The reason they put a union there is to give themselves a syntax for accessing x, y, and z in two distinct ways:
By specifying the field name - that is, coord.x, coord.y, or coord.z, or
By specifying the field index - that is, coord._v[0], coord._v[1], or coord._v[2].
An approach that provides comparable functionality without running into undefined behavior is to use inline member functions for your access:
struct Vector3D {
int v[3];
int& x() { return v[0]; }
int& y() { return v[1]; }
int& z() { return v[2]; }
};
int main() {
Vector3D coord;
coord.v[0] = 5;
cout << coord.x() << endl;
coord.y() = 10;
cout << coord.v[1] << endl;
return 0;
}
Demo.
As Gill Bates says, in this way you can (maybe) access the 3 coordinates both as x, y, z and as v[0], v[1], v[2]
But as per #Richard Critten comment, this is actually an UB.
You can get the same result in a "safe" way with something like this:
struct Coordinates
{
Coordinates():x(v[0]), y(v[1]), z(v[2])
{
}
int v[3];
int& x;
int& y;
int& z;
};
i.e., using references to the array values and initializing them in constructor
Size of this struct will be obviously different (larger) than the union you show in OP
This way you can address the 3d coordinate as a struct..
foo.x;
foo.y; // etc
But it also allows you to get the 3 variables as an array while occupying the same space (that's the plan at least), accessing them like..
foo._v[0] // x, etc
Anyway, that's the idea. But the moment the struct has any sort of padding between members your array will be misaligned and you will end up reading garbage values. Long story short, this code has undefined behaviour, a bad implementation that shouldn't be used.
I am writing a small program for learning C++ and 3D.
I have already written a vertex class with usefull methods. (like Dot,Cross, etc...)
class cVector {
...
float x, y, z;
...
float dot(cVector& v);
cVector cross(cVector& v);
...
}
Now I realize OpenGL expects buffers where elements are more like a struct (VBO).
struct sVector {
float x, y, z;
}
So my vertex class is no longer useless, because if i want to manipulate data in the buffer :
1 - I need to extract data of elements in the buffer.
2 - Create a temporary instance of vertex class with the data.
3 - Use vertex class method. (Dot, cross, etc...)
4 - Put the data back to the buffer.
It's not very efficient :(.
I wonder if I should not use a struct to organize my vectors and create global functions that take a pointer to a struct as an argument.
I could handle data buffers more efficiently (just moving pointer) but I feel i would lose the "convenient power" of C++.
In every 3D C++ source code i ever see, all use class for vertex but i dont understand how they can manipulate large amount of vertex in a "struct like" buffer.
Can you help me to understand ? What is the best approach ?
The most common approach in a language like C++ is actually neither of these things.
You are more likely to encounter the following:
struct Vector3 {
union {
struct {
float x,y,z;
};
float v [3];
};
...
Vector3 (float x_, float y_, float z_) : x (x_), y (y_), z (z_) { };
float Norm (void) { return sqrt ((x * x) + (y * y) + (z * z)); }
void Normalize (void) {
float norm = Norm ();
v [0] /= norm;
v [1] /= norm;
v [2] /= norm;
}
};
The reason for this is because using anonymous unions and structs, you can treat the data as either an array of floats (v [...]) or reference the individual components by their name (x, y, z) without a lot of muss or fuss. You get the best of both worlds by using the language more intelligently.
As for the difference between a struct and a class in this particular case, there is none from the perspective of memory representation. The only real difference between a class and a struct in C++ is the default access; struct has public access by default.
When GL needs to access the object's internal memory, you would accomplish this by passing it the pointer: Vector3::v or the individual components, depending on the particular function.
For instance:
Vector3 vec (1.0f, 2.0f, 3.0f);
---------------------------------
glVertex3fv (vec.v);
and
glVertex3f (vec.x, vec.y, vec.z);
are equivalent
On a side-note, anonymous structures are a non-standard extension to C++ but supported virtually everywhere. In the case that you have a compiler that does not support them, you may have to qualify access to x, y, and z by giving the struct a name.
struct Vector3 {
union {
struct {
float x,y,z;
} s;
float v [3];
};
};
If you write your struct this way, then:
Vector3 vec;
assert (vec.v [0] == vec.s.x);
It is messier to have to qualify x that way (using an anonymous struct you can use vec.x).
There is exactly one difference between struct and class: For class the default scope is private, while for struct it is public.
So
class cVector {
...
float x, y, z; // data
...
float dot(cVector& v); // just a function
cVector cross(cVector& v); // just a function
...
}
and
struct sVector {
float x, y, z; // data
}
have exactly the same memory layout (given that x,y,z are the only members variables of cVector).
You can use &v.x to get a pointer to (x,y,z) for OpenGL, e.g. glVertex3f(&v.x);.
You can even do the following to get a pointer to a continuous sequence of vertices for usage with OpenGL:
std::vector<cVector> vertices(100);
const float* data = &(vertices[0].x);
I have a strange problem. There is a vector of structures. With a temporary structure, I push_back to that vector of structures. But when I check the first member's cnt, I see that it became changed. Any idea? (Below code is a simplified version but a representative one)
struct Vector
{
float *dim;
Vector ()
{
dim = new float [3];
}
};
struct Face
{
float an_N, an_P;
int P, N;
Vector Af;
float Ad;
Vector cnt;
float ifac;
float mf;
};
std::vector <Face> face;
Face temp_face;
for (;;)
{
temp_face.cnt.dim[0] = 0.f;
temp_face.cnt.dim[1] = 0.f;
temp_face.cnt.dim[2] = 0.f;
for (int q=0; q<n_vtx_2D; ++q)
{
temp_face.cnt = temp_face.cnt + pt[vtx[q]] / n_vtx_2D;
}
face.push_back(temp_face);
}
std::cout << face[0].cnt.dim[0] << std::endl;
Output
0.25
0
The default compiler generated copy constructor (and assignment operator) is being used for Vector and Face (but most importantly Vector). As the code re-uses the same instance of Face, named temp_face, all the instances of Face in the vector face point to the same Face.cnt.dim array (as the faces will contain copies of temp_face).
I can't see any reason for dynamically allocated the array inside Vector as it is a fixed size. Suggest changing to:
struct Vector
{
float dim[3];
};
Or you need to implement copy constructor, assignment operator and destructor for Vector.
See What is The Rule of Three? for more information.
I have Vector class, representing a 3D point, written as follows in Vector.h:
class Vector {
public:
float x,y,z;
Vector(float _x=0.0,float _y=0.0,float _z=0.0){x=_x;y=_y;z=_z;};
operator float *() { return &x;};
};
I also declare a extern vector<Vector>model_vertices; on model.h
On a model.cpp file I implement Vector.h and declare a std::vector<Vector>model_vertices; globally (yes, I know the vector/Vector thing is confusing, but I must use the Vector naming for consistency).
On model.cpp, when initializing the contents of this vector I use a for loop with the following content:
float X,Y,Z;
offFileStream>>X;
offFileStream>>Y;
offFileStream>>Z;
Vector v=new Vector(X,Y,Z);
model_vertices[loadVertexIndex]=v;
I get the following error:
error C2440: 'initializing' : cannot convert from 'Vector *' to 'Vector'
Why?
The error is on this line:
Vector v=new Vector(X,Y,Z);
v is of type Vector, but new Vector(X,Y,Z) returns a Vector*:
What you probably wanted instead is just:
Vector v(X,Y,Z);
As a side note, I didn't see you initialize a size for the model_vertices. So you may want to use push_back() instead.
It's not quite clear what you're trying to achieve, but perhaps you're overthinking this.
First off, please forget the keyword new. Just pretend it doesn't exist. (By the time you'll need it, you'll know enough C++ to realize that you can ignore this post.)
Second, you can improve your class constructor to use an initializer list:
Vector(float _x = 0.0, float _y = 0.0, float _z = 0.0)
: x(_x), y(_y), z(_z)
{ }
Third, to populate a vector, just insert temporaries directly:
std::vector<Vector> v;
float x, y, z;
while (get_values(x,y,z)) // or any sort of loop you like
{
v.push_back(Vector(x,y,z));
}
If you have a recent version of C++, you can use the more efficient emplacement instead:
v.emplace_back(x, y, z); // no temporary
Vector v=new Vector(X,Y,Z);
model_vertices[loadVertexIndex]=v;
should be
Vector *v=new Vector(X,Y,Z);
model_vertices[loadVertexIndex]=*v;
new() allocated from the heap and it returns a pointer to an object.
If you want to call the constructor and allocate on the stack, do this instead.
Vector v(X,Y,Z);
The new operator can only be used when asigning to a pointer. If you just want to have an object v of type vector then you should use:
Vector v(X,Y,Z);
If you would like to have a pointer to Vector object then you should use:
Vector *v=new Vector(X,Y,Z);