Why does D3DXGeneratePMesh fail?!?

Started by
4 comments, last by ankhd 16 years, 1 month ago
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.
Advertisement
Hi, try setting the MinValue to a value greater then 1
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?
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);	}		


** 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?
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.

This topic is closed to new replies.

Advertisement