DrawIndexedPrimitive() Failing (DX9)
EDIT: SOLVED
But I posted the next part to the problem below. You can skip this post.
The For Loops in the InitIndexBuffer() were going one too many rounds. (I.e. while: X < (NumCols -1), should have been the case). After writing it out on paper, it made sense.
Hullo hullo, (again, if anybody's already read this)
I'm getting some peculiar Index Buffer problems going on.
First, I'll blatantly post my code (feel free to skip past it), and below I'll talk about/highlight the key points.
Code:
bool cTerrain::InitIndexBuffer(void)
{
unsigned char *BufferIndices = NULL;
unsigned short *Indices = NULL;
Indices = (unsigned short*)malloc(NumIndices * sizeof(unsigned short));
if(Indices == NULL)
return false;
unsigned short A = 0;
unsigned short B = A + 1;
unsigned short C = NumCols + 1;
unsigned short X = 0;
unsigned short Z = 0;
unsigned long I = 0; //<----This here, this is the guy
//AndyPike's altered idea to meet my own style
for(Z = 0; Z < NumRows; Z = Z + 1)
{
for(X = 0; X < NumCols; X = X + 1)
{
Indices[ I ] = A;
Indices[I + 1] = B;
Indices[I + 2] = C;
Indices[I + 3] = C + 1;
Indices[I + 4] = C;
Indices[I + 5] = B;
A = A + 1;
B = B + 1;
C = C + 1;
I = I + 6;
}
A = A + 2;
B = B + 2;
C = C + 2;
}
IndexBuffer->Lock(0, NumIndices * sizeof(unsigned short), (void**)&BufferIndices, 0);
memcpy(BufferIndices, Indices, NumIndices * sizeof(unsigned short));
IndexBuffer->Unlock();
free(Indices);
Indices = NULL;
return true;
}
void cTerrain::Draw(void)
{
D3DDevice->SetStreamSource(0, VertexBuffer, 0, sizeof(sVertex));
D3DDevice->SetFVF(FVF);
D3DDevice->SetIndices(IndexBuffer);
D3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, NumVertices, 0, NumPolygons);
}
bool cTerrain::LoadTerrainMap(char *FilePath, HWND *hWnd)
{
//Just so you get an idea of what I'm doing, but the itallic part can be skipped
HBITMAP TerrainFile;
TerrainFile = (HBITMAP)LoadImage(0, FilePath, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION|LR_LOADFROMFILE);
if(TerrainFile == NULL)
return false;
BITMAP TerrainMap;
if(!(GetObject(TerrainFile, sizeof(BITMAP), &TerrainMap)))
{...}
BITMAPINFO TerrainInfo;
/*FILL TerrainInfo HERE*/
unsigned long *Pixels = NULL;
Pixels = (unsigned long*)malloc(TerrainInfo.bmiHeader.biHeight * TerrainInfo.bmiHeader.biWidth * sizeof(unsigned long));
if(Pixels == NULL)
{...}
HDC hDC;
hDC = GetDC(*hWnd);
if(hDC == NULL)
{...}
if(!(GetDIBits(hDC, TerrainFile, 0, TerrainInfo.bmiHeader.biHeight, Pixels, &TerrainInfo, DIB_RGB_COLORS)))
{...}
NumCols = (short)TerrainInfo.bmiHeader.biWidth;
NumRows = (short)TerrainInfo.bmiHeader.biHeight;
NumVertices = NumCols * NumRows;
NumPolygons = (NumCols - 1) * (NumRows - 1) * 2;
NumIndices = NumPolygons * 3;
...
if(FAILED(D3DDevice->CreateIndexBuffer(NumIndices * sizeof(unsigned short), D3DUSAGE_WRITEONLY,
D3DFMT_INDEX16, D3DPOOL_MANAGED, &IndexBuffer, NULL)))
{...}
if(InitIndexBuffer() == false)
{...}
...
}
The dots represent edited out code, for the sake of nobody going insane from all the useless code. I tried to keep it condensed to only the important parts.
If you haven't guess it, I'm loading in a Bitmap and creating vertices based on that Bitmap.
Okay, so here's the thing, it all comes down to the I variable in the InitIndexBuffer() function.
I used to be an "unsigned short". However, I have 242406 Indeces. Which I wasn't realizing meant that I would wrap back around to 0 when it hit past 65535. Because of this wrapping, I would never fill in information at the very END of Indeces, therefore my IndexBuffer would be incomplete. This caused the program to crash on:
D3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, NumVertices, 0, NumPolygons); //Can be found in Render()
(Much of this isn't with a reason, this is just what I've seen when trying to figure my problem out).
When I realized it was wrapping back around, I changed the "unsigned short" to an "unsigned long". This caused my program to crash on the line:
free(Indices); //Can be found in InitIndexBuffer()
After thinking my computer was corrupted (I got something like "Block #43 Damaged" popping up in a MessageBox). For no reason, I changed the "unsigned long" back to "unsigned short". And my problem went away. But, back to the Render() crash.
So, as it stood, my variable was wrapping around, and this wasn't acceptable (either was the crash).
So, to test it out, I loaded in a different bitmap, one that would only require 8214 Indeces (definitely reachable by an unsigned short, without wrapping back to 0). The result was the return of my "Block #43 Damaged" error.
So, my only guess here is that I'm not allocating enough space for my IndexBuffer and when I gets too high, it starts writing things to places it shouldn't. But that doesn't explain to me why the free() line is crashing.
Perhaps if somebody could look over my allocations, check that I didn't miss anything? (I've double and triple-checked and I just can't find anything that could cause this. Hopefully a new set of eyes can.)
If nothing else, thanks for reading (or scrolling down to the bottom of) this monstrous post.