Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

Eriond

Can't add object to std::vector

This topic is 5206 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

//********************

// Cube.h

//********************

class Cube
{
public:
	Cube();
	~Cube();
	bool Init();
	bool Draw() const;
private:
	class Vertex
	{
	public:
		Vertex() {}
		Vertex(const D3DXVECTOR3 &position_, const D3DCOLOR &color_)
			: position(position_), color(color_) {}
		D3DXVECTOR3 position;
		D3DCOLOR color;
		static const DWORD FVF;
	};

	IDirect3DVertexBuffer9 *vertexBuffer;
	IDirect3DIndexBuffer9 *indexBuffer;
	D3DCOLOR color;
	float x, y, z;
};

//********************

// Cube.cpp

//********************

#include "Cube.h"

Cube::Cube() : vertexBuffer(0), indexBuffer(0), color(D3DCOLOR_XRGB(0, 0, 0)), 
				x(0), y(0), z(0)
{
}

bool Cube::Init()
{
	scene->GetDevice()->CreateVertexBuffer(24 * sizeof(Vertex),
								0,
								Vertex::FVF,
								D3DPOOL_MANAGED,
								&vertexBuffer,
								0);
	Vertex *vertices;
	vertexBuffer->Lock(0, 0, reinterpret_cast<void **> (&vertices), 0);

	//front

	vertices[0] = Vertex(D3DXVECTOR3(-1.0f, -1.0f, -1.0f), color);
	vertices[1] = Vertex(D3DXVECTOR3(-1.0f,  1.0f, -1.0f), color);
	vertices[2] = Vertex(D3DXVECTOR3(1.0f,  1.0f, -1.0f), color);
	vertices[3] = Vertex(D3DXVECTOR3(1.0f, -1.0f, -1.0f), color);
	//back

	vertices[4] = Vertex(D3DXVECTOR3(-1.0f, -1.0f, 1.0f), color);
	vertices[5] = Vertex(D3DXVECTOR3(1.0f, -1.0f, 1.0f), color);
	vertices[6] = Vertex(D3DXVECTOR3(1.0f,  1.0f, 1.0f), color);
	vertices[7] = Vertex(D3DXVECTOR3(-1.0f,  1.0f, 1.0f), color);
	//top

	vertices[8] = Vertex(D3DXVECTOR3(-1.0f, 1.0f, -1.0f), color);
	vertices[9] = Vertex(D3DXVECTOR3(-1.0f, 1.0f,  1.0f), color);
	vertices[10] = Vertex(D3DXVECTOR3(1.0f, 1.0f,  1.0f), color);
	vertices[11] = Vertex(D3DXVECTOR3(1.0f, 1.0f, -1.0f), color);
	//bottom

	vertices[12] = Vertex(D3DXVECTOR3(-1.0f, -1.0f, -1.0f), color);
	vertices[13] = Vertex(D3DXVECTOR3(1.0f, -1.0f, -1.0f), color);
	vertices[14] = Vertex(D3DXVECTOR3(1.0f, -1.0f,  1.0f), color);
	vertices[15] = Vertex(D3DXVECTOR3(-1.0f, -1.0f,  1.0f), color);
	//left

	vertices[16] = Vertex(D3DXVECTOR3(-1.0f, -1.0f,  1.0f), color);
	vertices[17] = Vertex(D3DXVECTOR3(-1.0f,  1.0f,  1.0f), color);
	vertices[18] = Vertex(D3DXVECTOR3(-1.0f,  1.0f, -1.0f), color);
	vertices[19] = Vertex(D3DXVECTOR3(-1.0f, -1.0f, -1.0f), color);
	//right

	vertices[20] = Vertex(D3DXVECTOR3(1.0f, -1.0f, -1.0f), color);
	vertices[21] = Vertex(D3DXVECTOR3(1.0f,  1.0f, -1.0f), color);
	vertices[22] = Vertex(D3DXVECTOR3(1.0f,  1.0f,  1.0f), color);
	vertices[23] = Vertex(D3DXVECTOR3(1.0f, -1.0f,  1.0f), color);

	vertexBuffer->Unlock();

	scene->GetDevice()->CreateIndexBuffer(36 * sizeof(WORD),
								D3DUSAGE_WRITEONLY,
								D3DFMT_INDEX16,
								D3DPOOL_MANAGED,
								&indexBuffer,
								0);
	WORD* i = 0;
	indexBuffer->Lock(0, 0, reinterpret_cast<void **> (&i), 0);

	// fill in the front face index data

	i[0] = 0; i[1] = 1; i[2] = 2;
	i[3] = 0; i[4] = 2; i[5] = 3;

	// fill in the back face index data

	i[6] = 4; i[7]  = 5; i[8]  = 6;
	i[9] = 4; i[10] = 6; i[11] = 7;

	// fill in the top face index data

	i[12] = 8; i[13] =  9; i[14] = 10;
	i[15] = 8; i[16] = 10; i[17] = 11;

	// fill in the bottom face index data

	i[18] = 12; i[19] = 13; i[20] = 14;
	i[21] = 12; i[22] = 14; i[23] = 15;

	// fill in the left face index data

	i[24] = 16; i[25] = 17; i[26] = 18;
	i[27] = 16; i[28] = 18; i[29] = 19;

	// fill in the right face index data

	i[30] = 20; i[31] = 21; i[32] = 22;
	i[33] = 20; i[34] = 22; i[35] = 23;

	indexBuffer->Unlock();

	return true;
}

Cube::~Cube()
{
	vertexBuffer->Release();
	vertexBuffer = 0;
	indexBuffer->Release();
	indexBuffer = 0;
}

bool Cube::Draw() const
{
	D3DXMATRIX mtrx;
	D3DXMatrixTranslation(&mtrx, x, y, z);
	scene->GetDevice()->SetTransform(D3DTS_WORLD, &mtrx);
	scene->GetDevice()->SetStreamSource(0, vertexBuffer, 0, sizeof(Vertex));
	scene->GetDevice()->SetIndices(indexBuffer);
	scene->GetDevice()->SetFVF(Vertex::FVF);
	scene->GetDevice()->DrawIndexedPrimitive(
					D3DPT_TRIANGLELIST, 
					0,                  

					0,                  
					24,
					0,
					12);
	return true;
}
If I create a Cube like this: Cube cube; cube.Init(); cube.Draw(); Then it works. But if I try to add some cubes to a std::vector the program crashes:
vector<Cube> v;
for (int i = 0; i < 4; ++i)
{
    v.push_back(Cube());
}[/souce]So for some reason I can't have them in a stl-container.

<SPAN CLASS=editedby>[edited by - Eriond on March 21, 2004 3:50:49 PM]</SPAN>

Share this post


Link to post
Share on other sites
Advertisement
Actually the culprit looks like that the temporary object created by the Cube() invocation doesn''t actually meet the class invariants implied by the destrctor. In simplier terms, you create a Cube object, and in the constructor all the variables are set to 0 including the the vertexBuffer pointer. You create a copy and stick it in the vector. All is ok up to this point. Then the temporary object you created goes out of scope and needs to be destroyed. The first line in your destructor is vertexBuffer->Release(). This means you''re trying to de-reference a null pointer, which likely is crashing your program.

Share this post


Link to post
Share on other sites
I tried:
Cube::Cube(const Cube &c)
{
*vertexBuffer = *c.vertexBuffer;
*indexBuffer = *c.indexBuffer;
/* also tried:
vertexBuffer = 0;
indexBuffer = 0;
*/

color = c.color;
x = c.x;
y = c.y;
z = c.z;
}
It still crashes.

Edit: Thank you sicrane that solved it. Didn't really think of that

[edited by - Eriond on March 21, 2004 4:06:26 PM]

Share this post


Link to post
Share on other sites
and don''t forget you must have BOTH a copy constructor AND an assignment operator for types to be managed by the stl.

Share this post


Link to post
Share on other sites
Instead of creating a new topic. Now I can add Cubes to my vector but when I try to call Init() for all Cubes the program crashes(again). I added a copy ctor and an assignment operator.
Cube::Cube(const Cube &c)
{
if (this != &c)
{
*vertexBuffer = *c.vertexBuffer;
*indexBuffer = *c.indexBuffer;
color = c.color;
x = c.x;
y = c.y;
z = c.z;
}
}

Cube &Cube::operator=(const Cube &c)
{
if (this != &c)
{
*vertexBuffer = *c.vertexBuffer;
*indexBuffer = *c.indexBuffer;
color = c.color;
x = c.x;
y = c.y;
z = c.z;
}
return *this;
}
I don't really know how to copy the vertex and indexbuffer :/

[edited by - Eriond on March 21, 2004 4:25:48 PM]

Share this post


Link to post
Share on other sites
I think the SiCrance post is still your problem ... I think you are making SHALLOW copies of something (pointing to the same buffers in your copies of the object), but each copy thinks it''s the owner, and so upon destruction, each copy is trying to delete the object it points to (the same object)

hence, when the FIRST object gets DELETED ... all the rest of your objects are becomming INVALID - because the shared buffer has been released.

I didn''t read every line of your code ... but at a glance it seems true ... if that isn''t true - I''ll dig deeper ...

the 2 likely solutions to this problem are:

1. Add some sort of Ref Counting system ... where each items which wants to point to the same buffer adds a ref, and upon delete releases the reference ... then the buffer object destroys itself upon the reference going to 0.

2. Make deep copies, in the copy constructor and assignment operators, make complete duplicates of your object ... in other words go through the WHOLE process of initializing sets of buffers that have the same properties as the originals ... so at the end of your copy constructor, you have 2 seperate objects (and are using twice the buffer / vertex space) ... then each can be safely deleted as needed.

Share this post


Link to post
Share on other sites
If I use *vb = *c.vb; it crashes, if I use, vb = c.vb; it crashes, if I put the create vertex/indexbuffer code in the copy ctor and assignment operator it crashes. Then I thought of using boost::shared_ptr, but ran into problems directly.
boost::shared_ptr<IDirect3DVertexBuffer9> vertexBuffer;
//...

device->CreateVertexBuffer(24 * sizeof(Vertex),
0,
Vertex::FVF,
D3DPOOL_MANAGED,
&vertexBuffer, //error here, cant convert to IDirect3DVertexBuffer9**

0);


[edited by - Eriond on March 22, 2004 1:56:30 AM]

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!