Sign in to follow this  
PLCMeister

Why does D3DXGeneratePMesh fail?!?

Recommended Posts

Hi, I am trying to create a progressive mesh so that I can decrease the number of vertices in a mesh so that it renders faster. I clean, weld and validate it and there are no errors, but if the number of vertices or faces is greater than a certain amount, it fails to create the progressive mesh. How do I tell what the problem is? According to the MSDN site, the three errors that can occur are D3DXERR_CANNOTATTRSORT, D3DERR_INVALIDCALL and E_OUTOFMEMORY. None of these are occurring. I use the following code:

	hr = D3DXGeneratePMesh(m_pD3DXMesh, (DWORD*)dwAdj1,
		NULL, NULL, 1, D3DXMESHSIMP_VERTEX, &m_pD3DXPMesh);
	if (FAILED(hr))
	{
		MessageBox("Failed to create progressive mesh!", "Oh, snap!");
		m_bPMesh = false;
		if (hr == D3DXERR_CANNOTATTRSORT)
		{
			MessageBox("Attribute sort is not supported", "Error type...");
		}
		if (hr == D3DERR_INVALIDCALL)
		{
			MessageBox("The method call is invalid", "Error type...");
		}
		if (hr == E_OUTOFMEMORY)
		{
			MessageBox("Out of memory", "Error type...");
		}
	}
	else
	{
		m_bPMesh = true;
		m_pD3DXPMesh->TrimByVertices(1000, 1750, NULL, NULL);
		m_pD3DXPMesh->OptimizeBaseLOD(D3DXMESHOPT_VERTEXCACHE, NULL);
		D3DXComputeNormals(m_pD3DXPMesh, NULL);
	}



Is there another way of finding out why it fails? Oh, wait a minute, I just found out about DXGetErrorString9. Hmmm... it says "D3DXERR_INVALIDMESH". How can that be? Just before this code, I do this:

	MessageBox("Validating mesh...", "Progress...");
	if (FAILED(hr = D3DXValidMesh(m_pD3DXMesh, (DWORD*)dwAdj, &ew)))
	{
		MessageBox("Failed to validate mesh!", "Oh, snap!");
		char *chErr = new char[ew->GetBufferSize()];
		int *ptrErr = (int*)ew->GetBufferPointer();
		chErr = (char*)ptrErr;
		MessageBox(chErr, "Oh, snap!"); // Show the errors.
	}



DX9 says it's valid! What gives here? Can someone please save me from this madness? I would appreciate it.

Share this post


Link to post
Share on other sites
Thanks for the tip, but I already tried it. I tried many different values again when I saw your post, but it still fails with the error "D3DXERR_INVALIDMESH". The error suggests that the mesh is invalid, but I used the D3DXValidMesh function and it did not return an error. Is there something that the D3DXGeneratePMesh function requires that the validation function does not?

Share this post


Link to post
Share on other sites
Try a new mesh and see if that works if so the there is somthing wrong with that mesh. fist try setting pVertexAttributeWeights Var to NULL.
The SDK says
If pVertexAttributeWeights is set to NULL, the following values are assigned to the default D3DXATTRIBUTEWEIGHTS structure.

D3DXATTRIBUTEWEIGHTS AttributeWeights;

AttributeWeights.Position = 1.0;
AttributeWeights.Boundary = 1.0;
AttributeWeights.Normal = 1.0;
AttributeWeights.Diffuse = 0.0;
AttributeWeights.Specular = 0.0;
AttributeWeights.Tex[8] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};

This default structure is what most applications should use because it considers only geometric and normal adjustment. Only in special cases will the other member fields need to be modified.


//here is how I did it and It works fine

//-----------------------------------------------------------------
// Optimize for the vertex cache and build attribute table.
DWORD* adj = new DWORD[subMesh->GetNumFaces()*3];
hr = subMesh->GenerateAdjacency(EPSILON, adj);
if(FAILED(hr))
MessageBox(NULL, "Terrain Failed To GenerateAdjacency", "Terrain Class buildSubGridMesh()", MB_OK);

//we will get the new adj with the same data
hr = subMesh->OptimizeInplace(D3DXMESHOPT_VERTEXCACHE|D3DXMESHOPT_ATTRSORT,
adj, adj, 0, 0);
if(FAILED(hr))
MessageBox(NULL, "Terrain Failed To OptimizeInplace", "Terrain Class buildSubGridMesh()", MB_OK);

//delete[] adj;move we need them for pmesh generation



ID3DXBuffer* errors = 0;
hr = D3DXCleanMesh(D3DXCLEAN_SIMPLIFICATION,//D3DXCLEANTYPE CleanType,
subMesh,
adj,//CONST DWORD * pAdjacencyIn,
&subMesh,//LPD3DXMESH * ppMeshOut,
adj,//DWORD * pAdjacencyOut,
&errors);//LPD3DXBUFFER * ppErrorsAndWarnings


if(errors)
MessageBox(0, (char*)errors->GetBufferPointer(), 0, 0);


LPD3DXPMESH pPMesh;
//D3DXATTRIBUTEWEIGHTS w;


//ok we now want a progressive mesh so we can set the lod when viewing far away
//so we need the mesh for now then we must release it
hr = D3DXGeneratePMesh(subMesh,//the subgrid mesh we just created LPD3DXMESH pMesh,
adj,//same we did CONST DWORD * pAdjacency,
NULL,//use defaults CONST D3DXATTRIBUTEWEIGHTS * pVertexAttributeWeights,
NULL,//CONST FLOAT * pVertexWeights,
1,//DWORD MinValue,
D3DXMESHSIMP_FACE,//scale by face DWORD Options,
&pPMesh);//LPD3DXPMESH * ppPMesh


if(FAILED(hr))
MessageBox(NULL, "Failed to Generate PMesh", "Terrain Class buildSubGridMesh()", MB_OK);


if(subcount-1 == 0)
{
//see what levels we can set
sprintf_s(buff, MAX_PATH, "SubMesh[%d] Face LOD Min = %d, Max = %d", (subcount -1),pPMesh->GetMinFaces(), pPMesh->GetMaxFaces() );

ErrorReport.AddErrorMessage(buff, false);
}






Share this post


Link to post
Share on other sites
** sigh **

Please look at my code in the first post in this thread and you will see that I do set the attribute and vertex weights to NULL. Also, it does work fine until the number of vertexes is more than a certain number. The problem is that I get a "D3DXERR_INVALIDMESH" error even though the D3DXValidMesh says that it is valid. Does anyone know why this would happen?

Share this post


Link to post
Share on other sites
How did you make this mesh, how many vertices are there
and does the vertex Declaration get maped correctly or do you need to convert them.

Share this post


Link to post
Share on other sites

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