Skip to main content
gamedev.net
🔒 Locked

Index Buffer causes improper rendering

Started by Ratslayer Mar 6, 2009 at 12:19 PM 2 replies 1k views
Original Post
Ratslayer
Ratslayer
I created a simple export script that takes the mesh from 3ds max and exports its vertices and indices into a .bin file which I then load in the program and render. The problem is that it renders, but the faces are all messed up, so instead of a cube (which it was originally in 3ds max), I get some other shape, not even convex. I assumed that the problem is in the Index Buffer. Here is the code for 3ds Max script:

tmesh = snapshotAsMesh selection[1]

out_name = ((GetDir #export)+"/testmesh.bin")

out_file = fopen out_name "wb"

num_verts = tmesh.numverts 

num_faces = tmesh.numfaces

WriteLong out_file num_verts
WriteLong out_file num_faces

for v = 1 to num_verts do

(

	vert = getVert tmesh v

	WriteFloat out_file vert.x
	WriteFloat out_file vert.y
	WriteFloat out_file vert.z

)

for f = 1 to num_faces do

(

	face = getFace tmesh f

	WriteLong out_file face.x
	WriteLong out_file face.y
	WriteLong out_file face.z

)

fclose out_file

delete tmesh

out_file = fopen out_name "rb"
ReadLong out_file
ReadLong out_file
--ftell out_file

for i = 0 to (num_verts*3-1) do
(
	print (ReadFloat out_file)
)
--ftell out_file

for i = 0 to (num_faces*3-1) do
(
	print (ReadLong out_file)
)

Here is the loading function:

HRESULT LoadModel(const char* path, CD3DDeviceHolder* pdeviceholder)
{
	HRESULT hr = S_OK;
	ifstream filestr;
	char* contentbuffer;
	strVertex* vbuffer;
	unsigned int* ibuffer;
	int size;

	filestr.open(path, ios::in | ios::binary | ios::ate);
	if (filestr.is_open())
	{
		size = filestr.tellg();
		contentbuffer = new char [size];
		filestr.seekg (0, ios::beg);
		filestr.read (contentbuffer, size);
		filestr.close();
	}
	else 
	{
		MessageBox( NULL,
							"Binary File could not be opened",
							"Error", 
							MB_OK );
		return S_FALSE;
	}

	nVertices = *((int*)contentbuffer);
	nFaces = *((int*)(contentbuffer + 4));

	vbuffer = new strVertex [nVertices];
	for (int i = 0; i < nVertices; i++)
		vbuffer.Position = *((D3DXVECTOR3*)(contentbuffer + 8 + 12*i));

	ibuffer = new unsigned int [nFaces*3];
	for (int i = 1; i <= nFaces; i++)
	{
		ibuffer[3*i - 3] = *((int*)(contentbuffer + 8 + 12*nVertices + 4*(3*i - 3)));
		ibuffer[3*i - 2] = *((int*)(contentbuffer + 8 + 12*nVertices + 4*(3*i - 2)));
		ibuffer[3*i - 1] = *((int*)(contentbuffer + 8 + 12*nVertices + 4*(3*i - 1)));
	}

	hr = D3DX10CreateMesh(pdeviceholder->pD3D10Device, 
							pdeviceholder->pstrLayout, 
							pdeviceholder->nLayoutElements, 
							pdeviceholder->pstrLayout[0].SemanticName, 
							nVertices, nFaces, 
							D3DX10_MESH_32_BIT, 
							&pMesh);
	if( FAILED( hr ) )
	{
		MessageBox( NULL,
							"Mesh could not be created!",
							"Error", 
							MB_OK );
        return hr;
	}

	pMesh->SetVertexData(0, vbuffer);
	pMesh->SetIndexData(ibuffer, nFaces*3);
	pMesh->CommitToDevice();
	delete vbuffer;
	delete ibuffer;
	delete contentbuffer;

	return S_OK;
	
}

class CD3DDeviceHolder
{
public:
	CD3DDeviceHolder(void);
	~CD3DDeviceHolder(void);

	LPDIRECT3DDEVICE9		pD3D9Device;
	ID3D10Device*			pD3D10Device;
	D3D10_DRIVER_TYPE       strDriverType;
	IDXGISwapChain*			pSwapChain;
	ID3D10InputLayout*      pVertexLayout;
	D3D10_INPUT_ELEMENT_DESC* pstrLayout;
	ID3D10RenderTargetView* pRenderTargetView;
	UINT					nLayoutElements;

	bool					bDirectX10Enabled;

	HRESULT					InitD3D10Device(HWND hWnd, 
											int width, 
											int height, 
											int framerate, 
											bool windowed);
	HRESULT					InitD3D9Device(HWND hWnd, 
										    int width, 
										    int height, 
										    bool windowed);
	HRESULT					SetInputLayout(ID3D10EffectTechnique* ptechnique);
	HRESULT					SetViewport(int width, int height);

};

Also, the indices returned by Maxscript Listener when I read the binary file are: 1 3 4 4 2 1 5 6 8 8 7 5 1 2 6 6 5 1 2 4 8 8 6 2 4 3 7 7 8 4 3 1 5 5 7 3 I tried this with different boxes, they all have the same shape, although stretched or shrunk depending on the vertex coords. I'm thinking that I have a bad understanding of how an index buffer should be loaded or working, but, if this is the case, what exactly am I doing wrong? Thank you in advance.
Ratslayer
Ratslayer
I also tested the rendering with different models, and it gave me this:



Those are, in order: spiked sphere (Bevel+TurboSmooth), box, sphere;

I also wrote a script to reconvert and render the loaded model in 3ds amx, and it seems fine, so my guess would be that my program code is bad, or that 3ds max uses some different indexing system, or just functions otherwise. That might hint to where the problem lies.
Ximmer
Ximmer
This appears to be an off by one error, index buffers in 3dsmax are 1 based while in D3D they are 0 based.

try adding a -1 to your index buffer creation and see if it corrects your models

ibuffer[3*i - 3] = (*((int*)(contentbuffer + 8 + 12*nVertices + 4*(3*i - 3)))) - 1;ibuffer[3*i - 2] = (*((int*)(contentbuffer + 8 + 12*nVertices + 4*(3*i - 2)))) - 1;ibuffer[3*i - 1] = (*((int*)(contentbuffer + 8 + 12*nVertices + 4*(3*i - 1)))) - 1;
Ratslayer
Ratslayer
Yes it does, thanks you very much. =)

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.