Thread: using D3DXComputeBoundingSphere with LPD3DXMESH

  1. #1
    Registered User Vick jr's Avatar
    Join Date
    May 2009
    Location
    Galifray
    Posts
    27

    using D3DXComputeBoundingSphere with LPD3DXMESH

    I have a LPD3DXMESH called g_pMesh.
    I want to find the distance from the local origin of this mesh to its farthest out vertex. (to use as a very simple bounding radius from the local origin)

    I was hoping I could use the D3DXComputeBoundingSphere function in a similar way to this in my Mesh class:


    Code:
    //put bounding radius in this float
    void Mesh::getBoundingRadius(float* pBoundingRadius){
    	D3DXVECTOR3 center;//holds the computed center
    	LPDIRECT3DVERTEXBUFFER9* ppVB=NULL;//address of pointer to vertex buffer
    	g_pMesh->GetVertexBuffer(ppVB);//get the address
    
    	//compute bounding radius
    	D3DXComputeBoundingSphere(
    		  (D3DXVECTOR3 *)(ppVB),	//convert to pointer to vector		
    		  g_pMesh->GetNumVertices(),		
    		  g_pMesh->GetNumBytesPerVertex(),	
    		  &center,							
    		  pBoundingRadius					
    	);
    	//add the largest (absolute value) component of the center vector to the radius so the center can be the local origin and the radius will encompass entire mesh
    	*pBoundingRadius+=max(max(abs(center.x),abs(center.y)),abs(center.z));
    }
    But I don't know how to get the starting position. I think i need to dereference the address of the pointer to the vertex buffer one or two times.

    How can I get this to work and is there an easier/better way to do this?
    Thanks!
    Frogblast the ventcore!

  2. #2
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    The first position is the address of the first vertex in your vertex buffer or &ppVB[0].vecPos. Remember that ppVB is a buffer of vertex structures.

  3. #3
    Registered User Vick jr's Avatar
    Join Date
    May 2009
    Location
    Galifray
    Posts
    27
    Quote Originally Posted by Bubba View Post
    The first position is the address of the first vertex in your vertex buffer or &ppVB[0].vecPos. Remember that ppVB is a buffer of vertex structures.
    OK. I understand that part. Now how would I get that address from my LPD3DXMESH?
    Frogblast the ventcore!

  4. #4
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Code:
    VertexPNT1 *pVerts = 0;
    
    m_pMesh->LockVertexBuffer(0, (void **)&pVerts);
    
    
    D3DXComputeBoundingSphere(&pVerts[0].vecPos,
                                  m_pMesh->GetNumVertices(),
                                  sizeof(VertexPNT1),
                                  &m_BSphere.m_vecPos,
                                  &m_BSphere.m_Radius);
    
    m_pMesh->UnlockVertexBuffer();
    Where pVerts is the type of vertex in the mesh. You should know this if you have cloned the mesh to a vertex type of your own choosing. vecPos is the D3DXVECTOR3 structure element representing the position of the vertex. m_BSphere here is a bounding sphere structure with a position and a radius.

  5. #5
    Registered User Vick jr's Avatar
    Join Date
    May 2009
    Location
    Galifray
    Posts
    27
    Quote Originally Posted by Bubba View Post
    Code:
    VertexPNT1 *pVerts = 0;
    
    m_pMesh->LockVertexBuffer(0, (void **)&pVerts);
    
    
    D3DXComputeBoundingSphere(&pVerts[0].vecPos,
                                  m_pMesh->GetNumVertices(),
                                  sizeof(VertexPNT1),
                                  &m_BSphere.m_vecPos,
                                  &m_BSphere.m_Radius);
    
    m_pMesh->UnlockVertexBuffer();
    Where pVerts is the type of vertex in the mesh. You should know this if you have cloned the mesh to a vertex type of your own choosing. vecPos is the D3DXVECTOR3 structure element representing the position of the vertex. m_BSphere here is a bounding sphere structure with a position and a radius.
    I didn't make my vertex structure of buffer. I used the function to load the mesh from a .x file. That results in a LPD3DXMESH. How do u use this to find the address I need to pass to the function?
    Frogblast the ventcore!

  6. #6
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    First, you must read the SDK.

    Second, you must clone the mesh with the vertex structure you want and then you can use D3DXComputeBoundingSphere().

  7. #7
    Registered User Vick jr's Avatar
    Join Date
    May 2009
    Location
    Galifray
    Posts
    27
    Quote Originally Posted by Bubba View Post
    First, you must read the SDK.

    Second, you must clone the mesh with the vertex structure you want and then you can use D3DXComputeBoundingSphere().
    I've read the MSDN articles on all these functions.

    I don't think i should have to clone anything. When I load my mesh from the .x file, Directx automatically creates a vertex buffer of the appropriate vertex structure. I can obtain a pointer to this vertex buffer using the function ID3DXBaseMesh::GetVertexBuffer.
    I don't think i should need to even know they vertex format being used, since I can get the step size, and that's theD3DXComputeBoundingSphere needs. (They even say "Use GetNumBytesPerVertex, D3DXGetFVFVertexSize, or D3DXGetDeclVertexSize to get the vertex stride").

    If vertex buffers are arrays of verteces, then shouldn't the address of the buffer be equivalent to the address of the first vertex in the array? if this is the case, then I should be able to dereference the pointer to the pointer to the vertex buffer to get the pointer to the start position?
    Frogblast the ventcore!

  8. #8
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    What I said to do will work. When you load the mesh initially you are relying on ID3DXMesh's default vertex type which may not be the type you want. It is most likely not the type you want. To alleviate this you clone the mesh. You can get away with using the default type until you try to do more advanced things with the mesh like you are trying to do. All D3DXComputeBoundingSphere is doing is finding the min and max vertex positions, computing center off of that, and then computing radius from that as well. In order to do that it must have an array of D3DXVECTOR3 vectors so it can compute correctly. In order to get these you must provide a vertex type and stride.

    You should take notice what D3DXComputeBoundingSphere does. It computes a bounding sphere for the 'mesh' not for a specific ID3DXMesh. In other words it has nothing to do with ID3DXMesh.

  9. #9
    Registered User Vick jr's Avatar
    Join Date
    May 2009
    Location
    Galifray
    Posts
    27
    Quote Originally Posted by Bubba View Post
    What I said to do will work. When you load the mesh initially you are relying on ID3DXMesh's default vertex type which may not be the type you want. It is most likely not the type you want. To alleviate this you clone the mesh. You can get away with using the default type until you try to do more advanced things with the mesh like you are trying to do. All D3DXComputeBoundingSphere is doing is finding the min and max vertex positions, computing center off of that, and then computing radius from that as well. In order to do that it must have an array of D3DXVECTOR3 vectors so it can compute correctly. In order to get these you must provide a vertex type and stride.

    You should take notice what D3DXComputeBoundingSphere does. It computes a bounding sphere for the 'mesh' not for a specific ID3DXMesh. In other words it has nothing to do with ID3DXMesh.
    I need only provide the address of the vertex in the buffer to start computing with, the number of verteces to compute, and the size of each vertex. I can get all of this information directly from my mesh as follows (using code from Using the ID3DXMesh Class)...

    Code:
    void Mesh::getBoundingRadius(float* pBoundingRadius){
    	
    	D3DXVECTOR3 center;
    	LPDIRECT3DVERTEXBUFFER9 pVBuf;//pointer to vertex buffer
    	if (SUCCEEDED(g_pMesh->GetVertexBuffer(&pVBuf))) {//get the address
    		D3DXVECTOR3* pVert;//pointer to first vertex in buffer
    		if (SUCCEEDED(pVBuf->Lock(0,0,(void **) &pVert,D3DLOCK_READONLY))) {
    			//compute bounding radius
    			D3DXComputeBoundingSphere(
    				  pVert,			
    				  g_pMesh->GetNumVertices(),		
    				  g_pMesh->GetNumBytesPerVertex(),	
    				  &center,							
    				  pBoundingRadius					
    			);
    			//add the largest component of the center vect to the radius so the center can be 0 and the radius will encompas entire mesh
    			*pBoundingRadius+=max(max(abs(center.x),abs(center.y)),abs(center.z));
    			pVBuf->Unlock();
    		}else{
    			MessageBox( NULL, L"could not lock vertex buffer", L"getBoundingSphere", MB_OK );
    		}
    	}else{
    		MessageBox( NULL, L"error getting vertex buffer address", L"getBoundingSphere", MB_OK );
    	}
    }
    I've tried it and the above code works perfectly for getting the bounding radius (I'm not sure if the rest of my math is working though). An even better way would be to use the mesh's LockVertexBuffer method, which locks the vertex buffer and returns a pointer to it. I'll try that next.
    Frogblast the ventcore!

  10. #10
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Pretty much the same thing I said. I wouldn't rely on the default vertex type for ID3DXMesh.

Popular pages Recent additions subscribe to a feed

Tags for this Thread