Jump to content
  • Advertisement
Sign in to follow this  
Calin

DrawIndexedPrimitive Problem

This topic is 4683 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

I converted a DX8 Terrain tutorial to DX9. The code compiles with no error. When I execute the code although I see everything else the terrain does not get drawn. During game execution the debugger gives me this errors :
The following error occurred on line 254 of c:\documents and settings\calin\my documents\5sg_engine\alphabuild12b(firstpersonlook)\alphabuild\primitives1vb\terrainengine.cpp
D3DERR_INVALIDCALL
Extra information: Failed to draw primitives
Direct3D9: (ERROR) :Current vertex shader declaration doesn't match VB's FVF

First-chance exception at 0x7c81eb33 (kernel32.dll) in Primitives.exe: Microsoft C++ exception: long at memory location 0x0012f6d8..
Direct3D9: (ERROR) :DrawIndexedPrimitive failed.






The terrain generation code I use:

// Terrain Engine implementation

#include <d3d9.h>
#include <d3dx9.h>

#include "D3DFuncs.h"
#include "TerrainEngine.h"
#include "resource.h"

// =====================================================================================
// Constructor/Destructor
// =====================================================================================

CTerrainEngine::CTerrainEngine()
{

}

CTerrainEngine::~CTerrainEngine()
{
	if(m_pTextureHeightmap)
		m_pTextureHeightmap->Release();

	if(m_pTextureGround)
		m_pTextureGround->Release();

	if(m_pVertexBuffer)
		m_pVertexBuffer->Release();

	if(m_pIndexBuffer)
		m_pIndexBuffer->Release();
}

// =====================================================================================
// Initialisation
// =====================================================================================

HRESULT CTerrainEngine::Initialise(LPDIRECT3DDEVICE9& pDevice, char* pszHeightmap)
{
	HRESULT rslt;

	// First, we load our source images to texture surfaces. 

	rslt=D3DXCreateTextureFromFileEx(pDevice, pszHeightmap, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0,
									 D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL,
									 &m_pTextureHeightmap);
	if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "Could not load heightmap"); }





	rslt=D3DXCreateTextureFromFileEx(pDevice, "islandmap.bmp", D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0,
									 D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL,
									 &m_pTextureGround);
	if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "Could not load texmap"); }




	// ----------------------------------------------------------------------------
	// Extract heightmap information to 256*256 array. We do this the good old
	// fashioned lock-the-texture-and-index-through-it manner.
	// ----------------------------------------------------------------------------

	D3DLOCKED_RECT	lockedrect;
	::ZeroMemory(&lockedrect, sizeof(lockedrect));
	
	rslt=m_pTextureHeightmap->LockRect(0, &lockedrect, NULL, 0);//Texture-> LockRect , DX9 same
	if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "Could not lock heightmap surface"); }

	DWORD* pBits=(DWORD*)lockedrect.pBits;
	int index=0;

	// Display offset (bytes)=((Pitch * y) + x) * Num Bytes per pixel
	{
	for(int y=0; y<256;y+=2)
	{
		for(int x=0; x<256; x+=2)
		{	
						
			m_nHeightArray[y][x]=(getr(pBits[(y*256)+x]))/5;
		}
	}
	}
	m_pTextureHeightmap->UnlockRect(0);
	m_pTextureHeightmap->Release();
	m_pTextureHeightmap=NULL;


	// ----------------------------------------------------------------------------
	// Create vertices from array
	// ----------------------------------------------------------------------------

	{
	int z=128;				// Our starting Z axis position, 128 units "into" the screen
	float texX, texY;		// Texture coordinates
	int nArrayIndex=0;		// And an index into the array

	// First we index through each row, and create our vertex buffer - one vertice for every pixel
	// on the heightmap

	for(int nIndexY=0; nIndexY<256; nIndexY+=2)
	{
		texY=(float)(((float)nIndexY/(float)2)/(float)128);
		for(int nIndexX=0; nIndexX<256; nIndexX+=2)
		{
			// Vertice config
			//  1_____2
			// 4|\    |
			//  |  \  |
			//  |____\|3
			//  6     5
			//
			
			int x=nIndexX-128;
			texX=(float)(((float)nIndexX/(float)2)/(float)128);

			// Vertice 1
			m_vTerrain[((nIndexY/2) * 128)+(nIndexX/2)].x=(float)x;
			m_vTerrain[((nIndexY/2) * 128)+(nIndexX/2)].y=(float)m_nHeightArray[nIndexY][nIndexX];
			m_vTerrain[((nIndexY/2) * 128)+(nIndexX/2)].z=(float)z;

			m_vTerrain[((nIndexY/2) * 128)+(nIndexX/2)].tu1=texX;
			m_vTerrain[((nIndexY/2) * 128)+(nIndexX/2)].tv1=texY;

			int col=m_nHeightArray[nIndexY][nIndexX]*5;
			m_vTerrain[((nIndexY/2) * 128)+(nIndexX/2)].dwColour=D3DCOLOR_ARGB(255, col, col, col);
		}
		z-=2;
	}
	}

	// Now that we have our vertices, we create an index buffer array for them

	{
	int nArrayIndex=0;
	for(int nIndexY=0; nIndexY<128; nIndexY++)
	{
		for(int nIndexX=0; nIndexX<127; nIndexX++)
		{
			//int nIndexY=0;
			m_sIndices[nArrayIndex]=((nIndexY+1) * 128)+nIndexX;
			m_sIndices[nArrayIndex+1]=(nIndexY * 128)+nIndexX;
			m_sIndices[nArrayIndex+2]=((nIndexY+1) * 128)+nIndexX+1;

			m_sIndices[nArrayIndex+3]=((nIndexY+1) * 128)+nIndexX+1;
			m_sIndices[nArrayIndex+4]=(nIndexY * 128)+nIndexX;
			m_sIndices[nArrayIndex+5]=(nIndexY * 128)+nIndexX+1;
			
			nArrayIndex+=6;
		}
	}
	}
	

	rslt=pDevice->CreateVertexBuffer(sizeof(m_vTerrain), 0, D3DFVF_TERRAIN, D3DPOOL_MANAGED,
 									 &m_pVertexBuffer,NULL);
	if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "CreateVertexBuffer() failed."); }

	// Now lock the vertex buffer...
	BYTE* pVerticeLock=0;
	rslt=m_pVertexBuffer->Lock(0, sizeof(m_vTerrain),(void**)&pVerticeLock, 0);
	if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "Failed to lock Vertex Buffer."); }

	// ...and copy our array of vertices straight into it
	CopyMemory(pVerticeLock, &m_vTerrain, sizeof(m_vTerrain));

	// Remember to unlock the vertex buffer once we're done.
	m_pVertexBuffer->Unlock();


	BYTE* pIndexData=0;

	// Create the index buffer...
	rslt=pDevice->CreateIndexBuffer(sizeof(m_sIndices), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &m_pIndexBuffer,NULL);
	if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "Failed to lock Index Buffer."); }

	// ...lock it
	rslt=m_pIndexBuffer->Lock(0, sizeof(m_sIndices),(void**) &pIndexData, 0);
	if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "Failed to lock Index Buffer."); }

	// ...copy the indicies in, and unlock
	CopyMemory(pIndexData, &m_sIndices, sizeof(m_sIndices));
	m_pIndexBuffer->Unlock();


	return S_OK;
}

// =====================================================================================
// Render
// =====================================================================================

HRESULT CTerrainEngine::Render(LPDIRECT3DDEVICE9& pDevice, LPDIRECT3DSURFACE9& pBackBuffer)
{
	HRESULT rslt;

	// One of the simplest Render() methods yet!
	
//	rslt=pDevice->SetVertexShader(pShader);
//	if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "Failed to set vertex shader."); }

	// Use our nice ground texture for the entire set of vertices
	rslt=pDevice->SetTexture(0, m_pTextureGround);
	if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "Failed to set texture."); }

	// Set the texture as the first input for stage 0 
	rslt=pDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
	if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "Failed to set texture stage."); }

	// Set the vertex diffuse colour as the second input for stage 0
	rslt=pDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
	if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "Failed to set texture stage."); }

	// Set D3DTOP_BLENDDIFFUSEALPHA for the colour operation for stage 0
//	rslt=pDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_ADDSIGNED);
//	if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "Failed to set texture stage."); }

	// Do not perform any operations for the alpha operation for stage 0
	rslt=pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE); 
	if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "Failed to set texture stage."); }

	// Set the vertex stream source
	rslt=pDevice->SetStreamSource(0, m_pVertexBuffer, 0,sizeof(TERRAINVERTEX));
	if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "Failed to set stream source."); }

	// Tell D3D we're going to use our index buffer
	rslt=pDevice->SetIndices(m_pIndexBuffer);
	if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "Failed to set Index buffer."); }

	// Iterate and draw each row at a time
	for(int nCount=0; nCount < 128; nCount++)
	{
		rslt=pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0,0, 768, nCount*768, 256);
		if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "Failed to draw primitives"); }
	}

	// Unset texture stage modes - these are the "default" D3D stages
	rslt=pDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
	if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "Failed to set texture stage."); }

	return S_OK;
}








Any help would be appreciated [Edited by - Calin on August 29, 2005 2:13:37 PM]

Share this post


Link to post
Share on other sites
Advertisement
When you render you need to set the fvf and stream source e.g.

gD3dDevice->SetFVF( D3DFVF_YOURFVF );

Share this post


Link to post
Share on other sites
Trip99 I made the correction, now I recive another kind of error:


The following error occurred on line 245 of c:\documents and settings\calin\my documents\5sg_engine\alphabuild12b(firstpersonlook)\alphabuild\primitives1vb\terrainengine.cpp
D3DERR_INVALIDCALL
Extra information: Failed to draw primitives
Direct3D9: (ERROR) :Invalid index in the index stream: 768

First-chance exception at 0x7c81eb33 (kernel32.dll) in Primitives.exe: Microsoft C++ exception: long at memory location 0x0012f768..
Direct3D9: (ERROR) :DrawIndexedPrimitive failed.




It appears that I pass a wrong argument in the DrawIndexedPrimitive function.

Share this post


Link to post
Share on other sites
quote from MSDN:

The MinIndex and NumVertices parameters specify the range of vertex indices used for each IDirect3DDevice9::DrawIndexedPrimitive call. These are used to optimize vertex processing of indexed primitives by processing a sequential range of vertices prior to indexing into these vertices. It is invalid for any indices used during this call to reference any vertices outside of this range.

So if:
BaseVertexIndex == 0
MinIndex == 0
NumVertices == 768
you cannot render from:
StartIndex == nCount*768
cause the start, with values of nCount > 0, go outside the range [0..768] specified.

Share this post


Link to post
Share on other sites
This is somewhat strange. I didn`t change anything in the DrawIndexedPrimitive function. The tutorial must have been posted with code mistakes.


[Edited by - Calin on August 29, 2005 8:47:52 AM]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • 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!