Vertex structure and vector array

Started by
10 comments, last by AgentShiva 15 years, 6 months ago
I have searched for nearly two days on this topic and can't dig up anything. I have Beginning DirectX 10 Game Programming by Wendy Jones, and in the end of chapter 6 she creates a predefined terrain mesh. What I am trying to do is create a dynamic terrain piece by having the user input the number of rows, the number of columns and cell width and height.

//Terrain Structs
struct VertexStruct
{
	D3DXVECTOR3 pos;
}; 

/* Terrain Class */
class Terrain
{
	public:
		Terrain();
		~Terrain();

		void loadTerrainFile(LPCSTR filename);
		void saveTerrainFile(LPCSTR filename);
		HRESULT createNewTerrain();

	private:
		vector<VertexStruct*> pVertStruct;
		ID3D10Buffer* pVerts;
		ID3D10Buffer* pIndeces;
};

Terrain::Terrain()
{
	pVerts = NULL;
	if(FAILED(createNewTerrain()))
		MessageBox(wndHandle, "Failed to create terrain!", "Error", MB_ICONERROR);
	return;
}

HRESULT Terrain::createNewTerrain()
{
	VertexStruct temp;

	for(UINT z = 0; z < tRows; ++z)
	{
		for(UINT x = 0; x < tColumns; ++x)
		{
			temp.pos.x = (float)x * tCellWidth;
			temp.pos.z = (float)z * tCellHeight;
			temp.pos.y = 1.0f;
			pVertStruct.push_back(&temp);
		}
	}

	D3D10_BUFFER_DESC bufDesc;
	bufDesc.Usage = D3D10_USAGE_DEFAULT;
	bufDesc.ByteWidth = sizeof(VertexStruct) * (tRows * tColumns);
	bufDesc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
	bufDesc.CPUAccessFlags = 0;
	bufDesc.MiscFlags = 0;

	D3D10_SUBRESOURCE_DATA initData;
	initData.pSysMem = &pVertStruct[0];
	
	HRESULT hr = pd3dDevice->CreateBuffer(&bufDesc, &initData, &pVerts);
	if(FAILED(hr))
		return hr;

	return hr;
}


I have tried many many different options. I have tried pVertStruct.resize(tRows*tColumns) and everything turns up memory errors. I have very limited knowledge of vectors and am learning DirectX in the process of making this. I really dont know what I am doing wrong. Every vector tutorial says what I have is correct, but memory errors always pop up. With this build it shows up when the windows API calls up the New Terrain dialog box, which has not turned up memory errors in the past. Any information or help is greatly appreciated.
Advertisement
For starters, you need to change this:
vector<VertexStruct*> pVertStruct;
To this:
vector<VertexStruct> pVertStruct;
And this:
pVertStruct.push_back(&temp);
To this:
pVertStruct.push_back(temp);
In order to understand why your code is wrong, you'll need to have a basic understanding of pointers, and of what it means to store data by reference as opposed to by value. (If you're not entirely up to speed on these topics, the forum archives here on GDNet might be a good place to start - there have been a number of threads in the past on the subject of pointers, what they're for, and how to use them.)

What you're doing currently is repeatedly adding the address of a temporary local variable to your vertex array, which I'm sure is not what you intend. The changes proposed above will have the effect of storing the individual vertices by value rather than by reference, which (I'm fairly certain) is what DirectX expects to see in the data you send it (of course your current data is useless anyway, seeing as how it consists entirely of pointers to a single object that has most likely expired).

Please post back if any of this is unclear.
Actually that pretty much all made sense. I have taken computer science classes before but have only been taught java. Trying to learn all of C++'s intricacies is proving to be a tough challenge.

Thank you for the help, I was going crazy trying to figure this out. It's funny how much comprehensive learning programming takes.

Now to turn a floating point number into a char array =P.

Again thank you!
Quote:
Now to turn a floating point number into a char array =P.


What for? [grin] (unless that was a joke - your smiley is ambiguous)
Writing vertex information to a XML file.

Such as
<Terrain>
<Mesh>
<Verticies count="1024"> //32x32 terrain(small but a test)
<Vertex>
<Position x="float value" y="float value" z="float value"/>
</Vertex> //more data to be added such as Texture coords, normal etc
</Verticies>
</Mesh>
</Terrain>

Custom 3D file format for terrain only.
Quote:Original post by AgentShiva
Writing vertex information to a XML file.

Such as
<Terrain>
<Mesh>
<Verticies count="1024"> //32x32 terrain(small but a test)
<Vertex>
<Position x="float value" y="float value" z="float value"/>
</Vertex> //more data to be added such as Texture coords, normal etc
</Verticies>
</Mesh>
</Terrain>

Custom 3D file format for terrain only.
For converting numbers to text in C++, you'll most likely want to look into the SC++L 'stream' classes (e.g. stringstream, fstream, etc.). Here's a quick example of how you might write out the 'position' line of the above file:
std::ofstream file("my_file.xml");// ...file << "<Position x=" << x << " y=" << y << " z=" << z << "/>\n";

I am actually using a XML parser I found online. It looked fairly easy to use, and comes with a good bit of documentation, but no detailed examples.

It has a function that adds an attribute to a node and it keeps getting memory errors. I am using sprintf() at the moment.

I didn't really expect help with this part of the program though haha.
#include <sstream>#include "XML_Thing.h"void foo(XML::Thing &xml, float f){   std::stringstream stream;   stream << f;   // prototype: XML::Thing::write( const char * )   xml.write(stream.str().c_str());   // std::stringstream::str() returns std::string instance   // std::string::c_str() returns const char *}
Quote:Original post by AgentShiva
Writing vertex information to a XML file.


Why would you convert it into "a char array" when you could instead create an instance of the standard library string class, just as in Java?

But wait, don't answer that - in C++, we don't convert things to text first in order to output them. Instead, we define the operation of outputting them. :) And we can do it with operator overloading, too, which lets us conform to the same interface that is provided for primitive types. (Of course, the overload already exists for double, so you just can output it as jyk shows.)

Of course, if you're working with another library, you might *have to* convert to a string, because it's what the other library is expecting. In which case, you just use a special sort of stream which uses a string as its "output device", and then pass the string along, as rip-off shows. :)
I tried implementing what rip-off said:

for(UINT i = 0; i < (tRows * tColumns); i++) //Print Vertex info{        vertexNode.addChild("Vertex", NULL, NULL).addChild("Position", NULL, NULL);	tempNode = vertexNode.getChildNode("Position", NULL);			stream<<pVertStruct.pos.x;	tempNode.addAttribute("x", stream.str().c_str());	stream.flush();}


But with that when I save the file my program stops responding and its memory usage continually goes up.

addAttribute() takes 2 const char * variables so I thought that stream.str().c_str() would work because .c_str() returns a const char pointer.

I also dont know much about streams, I thought flush cleared the stream but I am most likely wrong. I know I dont want to just keep the stream open and continually write to it because then I would be printing every float sequentially. That is to say the output from c_str() would be "value1" then "value1value2" etc.

This topic is closed to new replies.

Advertisement