Problem calculating normals

Started by
3 comments, last by robustpotato 13 years, 1 month ago
I am trying to calculate the vertex normals for my random terrain generation. I am fine on the logic (i think). I am using the method where 1st I work out the surface normals of each triangle and use an average of adjacent triangles to get the vertex normal.
The problem is not with the calculations. Rather the fact that the program crashes.

I get the following dialog after running



"Windows has triggered a breakpoint in RenderEngine.exe.

This may be due to a corruption of the heap, which indicates a bug in RenderEngine.exe or any of the DLLs it has loaded.


This may also be due to the user pressing F12 while RenderEngine.exe has focus.

The output window may have more diagnostic information.
t".
[/quote]
Here is the method:



D3DXVECTOR3* Terrain::CalculateSurfaceNormals(TerrainVertex* verts)
{
D3DXVECTOR3* triangleNormals = new D3DXVECTOR3[((width-1) * (length-1))];

for (int x = 0; x < width-1; x++)
{
for (int z = 0; z < length-1; z++)
{
int i0,i1,i2,i3;
//calculate the 4 indices of this quad
i0 = x+(z*width);
i1 = (x+1)+z*width;
i2 = (x)+(z+1)*width;
i3 = (x+1)+(z+1)*width;

// ###############
//triangle 1
D3DXVECTOR3 v1 = *new D3DXVECTOR3(verts[i0].x,verts[i0].y,verts[i0].z);
D3DXVECTOR3 v2 = *new D3DXVECTOR3(verts[i1].x,verts[i1].y,verts[i1].z);
D3DXVECTOR3 v3 = *new D3DXVECTOR3(verts[i2].x,verts[i2].y,verts[i2].z);

D3DXVECTOR3 e1 = v2-v1;
D3DXVECTOR3 e2 = v3-v1;

//CROSS PRODUCT
D3DXVECTOR3 cross;
cross.x = e1.y*e2.z - e1.z*e2.y;
cross.y = e1.z*e2.x - e1.x*e2.z;
cross.z = e1.x*e2.y - e1.y*e2.x;

//NORMALIZE THE VECTOR
float magnitude = sqrt((cross.x * cross.x) +(cross.y * cross.y) + (cross.z * cross.z));
cross.x /= magnitude;
cross.z /= magnitude;
cross.y /= magnitude;

triangleNormals[(2*x) + ((z) * (2*(width-1)))] = cross;

//############
////triangle 2
D3DXVECTOR3 v1_2 = v3;
D3DXVECTOR3 v2_2 = v2;
D3DXVECTOR3 v3_2 = *new D3DXVECTOR3(verts[i3].x, verts[i3].y, verts[i3].z);

D3DXVECTOR3 e1_2 = v2_2-v1_2;
D3DXVECTOR3 e2_2 = v3_2-v1_2;

//CROSS PRODUCT
D3DXVECTOR3 cross_2;
cross_2.x = e1_2.y*e2_2.z - e1_2.z*e2_2.y;
cross_2.y = e1_2.z*e2_2.x - e1_2.x*e2_2.z;
cross_2.z = e1_2.x*e2_2.y - e1_2.y*e2_2.x;

//NORMALIZE THE VECTOR
float magnitude_2 = sqrt((cross_2.x * cross_2.x) +(cross_2.y * cross_2.y) + (cross_2.z * cross_2.z));
cross_2.x /= magnitude_2;
cross_2.z /= magnitude_2;
cross_2.y /= magnitude_2;

triangleNormals[(2*x) + ((z) * (2*(width-1))) + 1] = cross_2;

}
}
return triangleNormals;

}


additional info:
- currently the terrain grid is 64*64, ideally id want to go bigger when i program optimization.
- when it crashes it is about halfway through the nested loop x =34, y = 0
- the code is executed at the start of the program. during initialization and not in the game loop


Im not the most advanced when it comes to c++, i can only imagine its a memory problem.

I think the logic is correct (its late) but if you see any please make me aware because I would hate to get it running and see the wrong results.




thank you for your time.
Advertisement
Firstly, you're leaking a ton of memory. Remove all of those "* new" snippets!
i.e. replace:
[font="Lucida Console"]D3DXVECTOR3 v3_2 [/font][font="Lucida Console"]= *new D3DXVECTOR3(verts[i3].x, verts[i3].y, verts[i3].z);[/font]
with:
[font="Lucida Console"]D3DXVECTOR3 v3_2 [/font][font="Lucida Console"]= D3DXVECTOR3(verts[i3].x, verts[i3].y, verts[i3].z);[/font]


What is the logic behind this index calculation?
[font="Lucida Console"]triangleNormals[/font][font="Lucida Console"][(2*x) + ((z) * (2*(width-1)))] = cross;[/font]
The index values that you're calculating seem to go outside the range of that array allocation (i.e. you're calculating indices greater than "[font="Lucida Console"](([/font][font="Lucida Console"]width-1) * (length-1[/font][font="Lucida Console"]))[/font]"), which will be causing the heap corruption.


I'd reccommend using assertions whenever doing something like this, to ensure that your indices never go out of bounds. E.g.
[font="Lucida Console"]int arraySize = [/font][font="Lucida Console"]((width-1) * (length-1));[/font]
[font="Lucida Console"]D3DXVECTOR3[/font][font="Lucida Console"]* triangleNormals = new D3DXVECTOR3[[/font][font="Lucida Console"]arraySize[/font][font="Lucida Console"]];[/font]
[font="Lucida Console"]...
int index =[/font][font="Lucida Console"] (2*x) + ((z) * (2*(width-1)));[/font]
[font="Lucida Console"]assert( index < arraySize )
[/font][font="Lucida Console"]triangleNormals[/font][font="Lucida Console"][index] = cross;
[/font]

Firstly, you're leaking a ton of memory. Remove all of those "* new" snippets!
i.e. replace:
[font="Lucida Console"]D3DXVECTOR3 v3_2 [/font][font="Lucida Console"]= *new D3DXVECTOR3(verts[i3].x, verts[i3].y, verts[i3].z);[/font]
with:
[font="Lucida Console"]D3DXVECTOR3 v3_2 [/font][font="Lucida Console"]= D3DXVECTOR3(verts[i3].x, verts[i3].y, verts[i3].z);[/font]


I will give that a try thanks.



What is the logic behind this index calculation?
[font="Lucida Console"]triangleNormals[/font][font="Lucida Console"][(2*x) + ((z) * (2*(width-1)))] = cross;[/font]
The index values that you're calculating seem to go outside the range of that array allocation (i.e. you're calculating indices greater than "[font="Lucida Console"](([/font][font="Lucida Console"]width-1) * (length-1[/font][font="Lucida Console"]))[/font]"), which will be causing the heap corruption.



i see i didn't make the array big enough should be *2

ok ill try explain my thinking

width and height are the width and height in vertices so width-1 is the number of polys on the grid.

i multiply it by 2 as there are 2 triangles on every grid square.

multiply that by the z to get the index of the triangle at the start of this row.

now ad 2x, to get to the current position in this row (again its doubled because of there being 2 triangles on each row




my array should be like this



D3DXVECTOR3* triangleNormals = new D3DXVECTOR3[((width-1) * (length-1))* 2];




Ive come from Java and c#,.
Ive heard stuff here and there about memory leakage. what i hear is c++ needs more care when dealing with memory.
i was unaware that using new would cause this problem. Ive made ammendments as you recommended.
Would declaring the vectors outside the loop have the same effect/improve it. since its the same memory location getting re-used.
or was that just totally wrong?

Thanks for the help though i will try immediately.


Ive heard stuff here and there about memory leakage. what i hear is c++ needs more care when dealing with memory.
i was unaware that using new would cause this problem. Ive made ammendments as you recommended.
Would declaring the vectors outside the loop have the same effect/improve it. since its the same memory location getting re-used.
or was that just totally wrong?


When you [font="Courier New"]new[/font] something, you must also [font="Courier New"]delete[/font] it when you are done (ditto [font="Courier New"]new[][/font] and [font="Courier New"]delete[][/font]). [font="Courier New"]delete[/font] works by taking a pointer to a chunk of memory allocated by [font="Courier New"]new[/font] and which has not yet been deleted. When you do "[font="Courier New"]... = * new...[/font]" you lose the pointer that [font="Courier New"]new[/font] returned and consequently cannot deallocate this memory - you lose it until your program dies and the operating system reclaims all of its resources.

The key difference in this aspect is that C# and Java are both garbage collected and will automatically perform that deallocation for you when they detect you are no longer using it (roughly, when no references to it remain). However, you don't normally need to allocate memory on the heap everywhere in C++ - you can allocate things on the stack by simply not using new, as shown above. Finally, there are things called smart pointers - classes which emulate the general interface of a pointer but which will try to provide automatic memory management for you (by reference counting or otherwise).
[TheUnbeliever]
Right. Thanks for the info. I made the amendments given by Hodgman and got rid of the *new snippits. Also the other problem you pointed out to me with my logic seemed fine, i double the size of the array as I said.

Heres the results :







DX+terrain1.jpg DX+terrain2.jpg

This topic is closed to new replies.

Advertisement