D3DXComputeTangentFrameEx problem

Started by
11 comments, last by cozzie 10 years ago

Hi ~

D3DXComputeTangentFrameEx() is hard to use.

I use Full Vertex Model.

Let's see source...

D3DXCleanMesh()... hr = S_OK

D3DXValidMesh()... hr = S_OK

HRESULT hr =

D3DXComputeTangentFrameEx( pMeshClean,
D3DDECLUSAGE_TEXCOORD, 0,
D3DDECLUSAGE_BINORMAL, 0,
D3DDECLUSAGE_TANGENT, 0,
0, 0,
D3DXTANGENT_GENERATE_IN_PLACE,
pAdjacencyClean,
0.01f, 0.25f, 0.01f,
&pMeshAfter,
0 );
hr is S_FALSE;

So...
I don't use "D3DXTANGENT_GENERATE_IN_PLACE" of option is hr = S_OK.
But vertex data is changed.
ex) -9.776716,0.000000,-9.890399 > 0.000000, -1.000000, 000000
How do I use exactly ?
Advertisement

Just noting the hr != S_OK isn't enough information. Are you compiling with DEBUG? What errors are you getting? In the dx control panel, set the error reporting to maximum.

If D3DXTANGENT_GENERATE_IN_PLACE doesn't work, it's likely that the data generated won't fit in the input mesh. So, don't use that option! Generate the new mesh, release the old mesh and use the new one.

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.

while i don't use d3dx libs, I'll give this a shot based on this doc.

Your U and V are in the wrong order, and should be swapped. dwUPartialOutSemantic [in] should be tangent, while dwVPartialOutSemantic [in] should be binormal. Also push both tangent and normal and binormal to the same index.

if your vertex format is something like this position, normal, tangent, bitangent, texcoords. then your call to compute tangent frame ex should reflect that. the indices should reflect the offset from the start of the vertex to the semantic location. you are using 0, so everything is overwrighting the position data. I would assume that indices should be 8 for tangent, 12 for bitangent, and 16 for normal based on the vertex format i described above. Read the doc I linked above and try to understand the meaning of each of the functions inputs.


then your call to compute tangent frame ex should reflect that. the indices should reflect the offset from the start of the vertex to the semantic location.

That's not correct.

Be careful, Burnt_Fyr. That parameter is NOT the vertex declaration offset, it is the SEMANTIC index. If he has a single D3DDECLUSAGE_TANGENT, then the index is 0.

However, you're likely correct about the common usage order.

The examples I've seen (and used) are, in order in the D3DXComputeTangentFrameEx call:

D3DDECLUSAGE_TEXCOORD, 0,

D3DDECLUSAGE_TANGENT, 0,

D3DDECLUSAGE_BINORMAL, 0,

D3DDECLUSAGE_NORMAL, 0

EDIT: @AquaMacker - if you have the June 2010 SDK, take a look at the D3D9 examples LocalDeformablePRT and ParallaxOcclusionMapping for using D3DXComputeTangentFrameEx.

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.


then your call to compute tangent frame ex should reflect that. the indices should reflect the offset from the start of the vertex to the semantic location.

That's not correct.

Be careful, Burnt_Fyr. That parameter is NOT the vertex declaration offset, it is the SEMANTIC index. If he has a single D3DDECLUSAGE_TANGENT, then the index is 0.

However, you're likely correct about the common usage order.

Good call, this is why I should not attempt to help anyone before morning coffee.

Thanks, Buckeye, Burnt_Fyr, I appreciate it.

Thanks very much smile.png smile.png smile.png

You're welcome. Did you get the problem fixed? If so, share the results! smile.png

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.

D3DXComputeTangentFrameEx( pMesh,
D3DDECLUSAGE_TEXCOORD, 0,
D3DDECLUSAGE_TANGENT, 0,
D3DDECLUSAGE_BINORMAL, 0,
D3DDECLUSAGE_NORMAL, 0,
0,
pAdjacency,
-1.01f,-0.01f,-1.01f,
&pMeshAfter,
0 );
this method DONE.

And
Vertex data error is my fault. ??;
But
ComputeTangent is well done but tangent value is not confirm yet.

Hi.

Not sure if you still have the problem, but here's my use case (Which works including tangents :))

1. load the mesh using D3DXLoadMeshFromX

2. create temporary mesh and optimize loaded mesh to it

3. swap meshes, release temporary mesh

4. check for existance of normals, binormals and tangents in the mesh

(by getting the vertexdeclaration from the loaded mesh)

5. if no binormals or tangents are there, generate them as followed:

A. create temporary mesh

B. clone loaded/ optimized mesh to temporary mesh

Important note: this is needed using your wanted vertex declaration, including binormals and tangents

(the declaration from the loaded mesh won't work because it has no declarations for binormals and tangents)

C. compute tangentframe using temporary/ cloned mesh

D. swap the temporary with the target mesh

E. release temporary mesh

Here's my code:


bool CD3dmesh::LoadXFile(const std::string pXfilename)										   
{
	if(mD3ddev == NULL)
	{
		MessageBox(NULL, err_mesh_d3ddev.c_str(), err_windowtext.c_str(), MB_OK);
		return false;
	}

	if(FAILED(D3DXLoadMeshFromXA(pXfilename.c_str(), 
								 D3DXMESH_MANAGED, //SYSTEMMEM, // DYNAMIC??? SYSTEMMEM FOR DYNAMIC OBJECTS??
								 mD3ddev,
								 &mAdjacencyBuffer,
								 &mMaterialBuffer,
								 NULL,
								 &mNumMaterials,
								 &mMesh))) return false;
	
	LPD3DXMESH tempMesh;
	if(FAILED(mMesh->Optimize(D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_COMPACT | D3DXMESHOPT_VERTEXCACHE, (DWORD*)mAdjacencyBuffer->GetBufferPointer(), (DWORD*)mAdjacencyBuffer->GetBufferPointer(), NULL, NULL, &tempMesh)))	
		return false;

	mMesh = tempMesh;
	tempMesh->Release();

	/** check Mesh vertex declaration for normals, binormals & tangents **/
	/**
	/** Scenario 1: All there, proceed									**/
	/** Scenario 2: No normals, tangents and binormals					**/
	/** Scenario 3: No tangents and binormals							**/

	bool normals = false;
	bool tangents = false;
	bool binormals = false;

	D3DVERTEXELEMENT9 meshDecl[MAX_FVF_DECL_SIZE];
	mMesh->GetDeclaration(meshDecl);
	
	for(unsigned int index=0;index<D3DXGetDeclLength(meshDecl);++index)
	{
		if(meshDecl[index].Usage == D3DDECLUSAGE_NORMAL) normals = true;
		if(meshDecl[index].Usage == D3DDECLUSAGE_TANGENT) tangents = true;
		if(meshDecl[index].Usage == D3DDECLUSAGE_BINORMAL) binormals = true;
	}

	if(!normals) { 
		if(D3D_OK != D3DXComputeNormals(mMesh, NULL)) return false;	}

	if(!tangents || !binormals) CalculateTangentFrame();

	mTempMaterial = (D3DXMATERIAL*)mMaterialBuffer->GetBufferPointer();
	return true;
}

/**************************************************************************************/
/***							CALCULATE TANGENT FRAME								***/
/*** ==> usage: when a mesh doesn't contain tangents and binormals					***/
/*** ==> creates the tangentframe, resulting in a new mesh, same D3DXMESH member	***/
/**************************************************************************************/

bool CD3dmesh::CalculateTangentFrame()
{
	#ifdef _DEBUG
	OutputDebugStringA("Warning: no tangents and/or binormals in mesh, calculating with D3DX!\n");
	#endif
	
	LPD3DXMESH tempMesh;
	mMesh->CloneMesh(D3DXMESH_32BIT | D3DXMESH_MANAGED, Crealysm_dxmath::vtxdecl, mD3ddev, &tempMesh);

	HRESULT hr = D3DXComputeTangentFrameEx(tempMesh,
		 								D3DDECLUSAGE_TEXCOORD, 0,
										D3DDECLUSAGE_BINORMAL, 0,
										D3DDECLUSAGE_TANGENT, 0,
										D3DDECLUSAGE_NORMAL, 0,
										D3DXTANGENT_GENERATE_IN_PLACE,
										(DWORD*)mAdjacencyBuffer->GetBufferPointer(),
										// 0.01f, 0.25f, 0.01f,
										-1.01f, -0.01f, -1.01f,
										NULL,
										NULL);
	if(FAILED(hr))
	{
		#ifdef _DEBUG
		OutputDebugString(DXGetErrorString(hr));
		OutputDebugString(L", ");
		OutputDebugString(DXGetErrorDescription(hr));
		OutputDebugString(L"\n");
		#endif

		MessageBox(NULL, err_tangent_xfile.c_str(), err_windowtext.c_str(), MB_OK);
		return false;
	}
	mMesh = tempMesh;
	tempMesh->Release();
	return true;
}

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me


    LPD3DXMESH tempMesh;
    if(FAILED(mMesh->Optimize(D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_COMPACT | D3DXMESHOPT_VERTEXCACHE, (DWORD*)mAdjacencyBuffer->GetBufferPointer(), (DWORD*)mAdjacencyBuffer->GetBufferPointer(), NULL, NULL, &tempMesh)))    
        return false;

    mMesh = tempMesh;
    tempMesh->Release();

@cozzie: Do you get memory leaks with that code? I'm curious because you keep releasing the temporary meshes you've just created and don't seem to release the original mMesh.

E.g.,

mMesh->Optimize(..., &tmpMesh) creates tmpMesh as the optimized mesh. The sequence after that call should be:


mMesh->Release(); // get rid of the old mesh
mMesh = tmpMesh; // keep the newly created mesh

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