Sign in to follow this  

D3DXComputeBoundingSphere causes Access Violation on next line

This topic is 2664 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 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();

}

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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[i];}
LPDIRECT3DTEXTURE9 getmeshTextures(int i){return meshTextures[i];}
LPD3DXMESH getmesh(){return mesh;}
DWORD getnumMaterials(){return numMaterials;}
void calculateBoundingSphere();

protected:
LPDIRECT3DDEVICE9 d3ddev;
LPD3DXBUFFER materialBuffer; //material buffer for mesh
D3DMATERIAL9 *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 safely
if(meshMaterials)
delete meshMaterials;

if(meshTextures)
delete meshTextures;
}


void modelX::loadmodelX(std::string filename){

// Load the mesh from the specified file
HRESULT 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[i] = d3dxMaterials[i].MatD3D;

meshMaterials[i].Ambient = meshMaterials[i].Diffuse;

meshTextures[i] = NULL;
if (d3dxMaterials[i].pTextureFilename)
D3DXCreateTextureFromFile(d3ddev, d3dxMaterials[i].pTextureFilename, &(meshTextures[i]));

}

materialBuffer->Release();

calculateBoundingSphere();
}

}

void modelX::draw(){

HRESULT hr;

// select which vertex format we are using
d3ddev->SetFVF(CUSTOMFVF);

for (DWORD i=0; i< numMaterials; i++){
// Set the material and texture for this subset
hr = d3ddev->SetMaterial(&(meshMaterials[i]));
hr = d3ddev->SetTexture(0,(meshTextures[i]));

// Draw the mesh subset
d3ddev->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();

}



Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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();
}


Share this post


Link to post
Share on other sites

This topic is 2664 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this