D3DXComputeBoundingSphere causes Access Violation on next line

Started by
3 comments, last by Buckeye 13 years, 7 months ago
I keep getting an access violation on the next line after D3DXComputeBoundingSphere(). The mesh object loads and draws with no problems

The vertex buffer lock returns ok, whilst D3DXGetFVFVertexSize and GetNumBytesPerVertex give different values and whichever I use, it doesn't solve the problem. The casting of the void pointer to the vertices produces sensible results.

I'm guessing D3DXComputeBoundingSphere goes off the end of the vertices array, but I'm not sure how to fix this or quite what I'm doing wrong

my code:

D3DXVECTOR3 * centre;

float * radius;

#define CUSTOMFVF (D3DFVF_XYZ | D3DFVF_NORMAL)

void modelX::calculateBoundingSphere(){


void * vPtr_vertices;

HRESULT hr;

hr = mesh->LockVertexBuffer( D3DLOCK_READONLY, (void**)&vPtr_vertices );

const D3DXVECTOR3 * vertices = (D3DXVECTOR3*)vPtr_vertices;

DWORD fvfsize = D3DXGetFVFVertexSize(CUSTOMFVF);

DWORD bytespervertex = mesh->GetNumBytesPerVertex();

DWORD numvertices = mesh->GetNumVertices();

D3DXComputeBoundingSphere(vertices,numvertices,fvfsize,centre,radius);

int a = 0;

mesh->UnlockVertexBuffer();

}
Android Developer for Crystalline Green
Advertisement
change "float* radius" to "float radius" and pass "&radius" to D3DXComputeBoundingSphere.

that's because radius is pointing to some random memory location.

same with the "center" variable.

To make things clearer, D3DXComputeBoundingSphere computes the center and the radius and is going to store them in the variables passed. So you either need to create them on the stack with "float radius;" or on the heap using "float* radius = new float();", but don't forget to call delete if you do it the latter way ;-)

A valid example would look like this:

class modelX{	float radius;	D3DXVECTOR3 centre;	// other stuff};void modelX::calculateBoundingSphere(){	void* vPtr_vertices;	mesh->LockVertexBuffer(D3DLOCK_READONLY, (void**)&vPtr_vertices);	D3DXComputeBoundingSphere	(		(D3DXVECTOR3*)vPtr_vertices,		mesh->GetNumVertices(),		mesh->GetNumBytesPerVertex(),		&centre,		&radius	);	mesh->UnlockVertexBuffer();}


btw, if D3DXGetFVFVertexSize and GetNumBytesPerVertex don't give you the same values, the mesh is definately not created with the FVF specified. Did you forget to use CloneMeshFVF by any chance?

[Edited by - scope on August 29, 2010 8:33:41 PM]
Clearly I have a much deeper problem. Things worked fine without CloneMeshFVF. When I put it in, the textures no longer display (even though SetMaterial and SetTexture return OK).

Having made the changes suggested, calculateBoundingSphere returns OK for locking, unlocking and correctly calculates the radius and centre of the mesh.

However, I get the following error upon calling the destructor (which I don't get if I don't execute calculateBoundingSphere):

"Windows has triggered a breakpoint in MyGame v0.2.exe.

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

my code:
#define CUSTOMFVF (D3DFVF_XYZ | D3DFVF_NORMAL)class modelX{public://modelX();modelX(LPDIRECT3DDEVICE9&, std::string);~modelX();void draw();void loadmodelX(std::string);D3DMATERIAL9 * getmeshMaterials(int i){return &meshMaterials;}LPDIRECT3DTEXTURE9 getmeshTextures(int i){return meshTextures;}LPD3DXMESH getmesh(){return mesh;}DWORD getnumMaterials(){return numMaterials;}void calculateBoundingSphere();protected:LPDIRECT3DDEVICE9 d3ddev;LPD3DXBUFFER materialBuffer; //material buffer for meshD3DMATERIAL9 *meshMaterials;LPDIRECT3DTEXTURE9 *meshTextures;LPD3DXMESH mesh;DWORD numMaterials;D3DXVECTOR3 centre;float radius;};modelX::modelX(LPDIRECT3DDEVICE9 &d3ddev_in, std::string filename){d3ddev = d3ddev_in;loadmodelX(filename);}modelX::~modelX(){// need to get rid of material/texture arrays safelyif(meshMaterials)delete meshMaterials;if(meshTextures)delete meshTextures;}void modelX::loadmodelX(std::string filename){// Load the mesh from the specified fileHRESULT hr=D3DXLoadMeshFromX(filename.c_str(), D3DXMESH_SYSTEMMEM,d3ddev, NULL,&materialBuffer,NULL, &(numMaterials),&mesh);if ( FAILED( hr ) ){}else{D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)materialBuffer->GetBufferPointer();meshMaterials = new D3DMATERIAL9[numMaterials];meshTextures = new LPDIRECT3DTEXTURE9[numMaterials];for (DWORD i=0; i<numMaterials; i++){meshMaterials = d3dxMaterials.MatD3D;meshMaterials.Ambient = meshMaterials.Diffuse;meshTextures = NULL;if (d3dxMaterials.pTextureFilename)D3DXCreateTextureFromFile(d3ddev, d3dxMaterials.pTextureFilename, &(meshTextures));}materialBuffer->Release();calculateBoundingSphere();}}void modelX::draw(){HRESULT hr;// select which vertex format we are usingd3ddev->SetFVF(CUSTOMFVF);for (DWORD i=0; i< numMaterials; i++){// Set the material and texture for this subsethr = d3ddev->SetMaterial(&(meshMaterials));hr = d3ddev->SetTexture(0,(meshTextures));// Draw the mesh subsetd3ddev->SetTransform(D3DTS_WORLD, &transformmodelX);mesh->DrawSubset( i );}}void modelX::calculateBoundingSphere(){void * vPtr_vertices;HRESULT hr;hr = mesh->LockVertexBuffer( D3DLOCK_READONLY, (void**)&vPtr_vertices );const D3DXVECTOR3 * vertices = (D3DXVECTOR3*)vPtr_vertices;DWORD bytespervertex = mesh->GetNumBytesPerVertex();DWORD numvertices = mesh->GetNumVertices();hr = D3DXComputeBoundingSphere(vertices,numvertices,bytespervertex,&centre,&radius);hr = mesh->UnlockVertexBuffer();}
Android Developer for Crystalline Green
Quote:Original post by Spoon Thumb
Clearly I have a much deeper problem. Things worked fine without CloneMeshFVF. When I put it in, the textures no longer display (even though SetMaterial and SetTexture return OK).


That might be because your FVF doesn't declare space for texture coordinates.

Change it to D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_NORMAL for that.

Quote:
Having made the changes suggested, calculateBoundingSphere returns OK for locking, unlocking and correctly calculates the radius and centre of the mesh.

However, I get the following error upon calling the destructor (which I don't get if I don't execute calculateBoundingSphere):


Can't see anything wrong with the code, but my eyes aren't that well trained. A look at the call stack might give clues about where the heap corruption takes place.
You have several problems, Spoon Thumb. I'm not sure that fixing them will solve your problem, but I'd urge you to fix them so you can be more confident in what you find during trouble-shooting.

1. You use CUSTOMFVF without knowing if the mesh you loaded has that vertex structure. Whenever you need the mesh's FVF, use mesh->GetFVF() instead. Don't guess at what the FVF of the mesh may be.

2. You create one or more COM interfaces which you never release - the mesh itself and texture pointers. Your class destructor should have something like:
if( mesh ) mesh->Release();for( WORD m=0; m < numMaterials; m++){   if( meshTextures[m] ) meshTextures[m]->Release();}

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

This topic is closed to new replies.

Advertisement