Sign in to follow this  
dave

D3DXComputeTangent() Problem

Recommended Posts

In my previous thread i was trying to work out why my tangent space normal mapping wasn't working, focussed on my shader. Well i took a step back and made sure that D3DXComputeTangent() was actually creating the tangents and binormals, it isn't. However, it returns S_OK and D3D reports no errors. Here is the code for creating thenew declaration, cloning and calculation:
	D3DXMesh	pMesh( pNewModel->GetMesh() );

	D3DVERTEXELEMENT9	EndElement = {0xFF,0,D3DDECLTYPE_UNUSED,0,0,0};

	D3DVERTEXELEMENT9 CurrentDeclaration[MAX_FVF_DECL_SIZE];

	pMesh->GetDeclaration(&CurrentDeclaration[0]);

	//	Find the end of the declaration and insert space for tangents.
	UInt32 EndIndex( 0 );

	for ( UInt32 Index( 0 ); Index < MAX_FVF_DECL_SIZE; ++Index )
	{
		if ( CurrentDeclaration[ Index ].Type == D3DDECLTYPE_UNUSED )
		{
			EndIndex = Index;
			break;
		}
	}

	CurrentDeclaration[ EndIndex + 2 ] = EndElement;

	D3DVERTEXELEMENT9& rTangentElement( CurrentDeclaration[EndIndex] );
	D3DVERTEXELEMENT9& rBiNormalElement( CurrentDeclaration[EndIndex+1] );
	D3DVERTEXELEMENT9& rPreviousElement( CurrentDeclaration[EndIndex-1] );

	rTangentElement.Offset = rPreviousElement.Offset + 12;
	rTangentElement.Method = D3DDECLMETHOD_DEFAULT;
	rTangentElement.Stream = rPreviousElement.Stream;
	rTangentElement.Type = D3DDECLTYPE_FLOAT3;
	rTangentElement.Usage = D3DDECLUSAGE_TEXCOORD;
	rTangentElement.UsageIndex = 1;

	rBiNormalElement.Offset = rTangentElement.Offset + 12;
	rBiNormalElement.Method = D3DDECLMETHOD_DEFAULT;
	rBiNormalElement.Stream = rPreviousElement.Stream;
	rBiNormalElement.Type = D3DDECLTYPE_FLOAT3;
	rBiNormalElement.Usage = D3DDECLUSAGE_TEXCOORD;
	rBiNormalElement.UsageIndex = 2;

	D3DXMesh NewMesh;

	HRESULT Result = pMesh->CloneMesh( D3DXMESH_VB_MANAGED | D3DXMESH_IB_MANAGED, &CurrentDeclaration[0], m_Device, &NewMesh );

	pNewModel->SetMesh( NewMesh );

	DWORD* pCharBuffer( new DWORD[3 * NewMesh->GetNumFaces()] );
	NewMesh->GenerateAdjacency( 0.0f, pCharBuffer );


	D3DXCleanMesh( D3DXCLEAN_BOWTIES , NewMesh, pCharBuffer, &NewMesh, pCharBuffer, NULL );
	D3DXCleanMesh( D3DXCLEAN_BACKFACING , NewMesh, pCharBuffer, &NewMesh, pCharBuffer, NULL );

	static UInt32 TexStage(0);
	static UInt32 TangentStage(0);
	static UInt32 BinormalStage(0);

	Result = D3DXComputeTangent( pNewModel->GetMesh(), TexStage, TangentStage, D3DX_DEFAULT, TRUE, pCharBuffer );
	pNewModel->SetMesh( NewMesh );

	if ( Result == D3DERR_INVALIDCALL )
		Result = Result;
	else if ( Result == D3DXERR_INVALIDDATA )
		Result = Result;

	NewMesh->GetDeclaration(&CurrentDeclaration[0]);


	void*	pData( NULL );
	NewMesh->LockVertexBuffer( 0, &pData );

	if ( pData != NULL )
	{

	}

	NewMesh->UnlockVertexBuffer();

Here is the .x file, a quad:
xof 0303txt 0032


template VertexDuplicationIndices { 
 <b8d65549-d7c9-4995-89cf-53a9a8b031e3>
 DWORD nIndices;
 DWORD nOriginalVertices;
 array DWORD indices[nIndices];
}
template XSkinMeshHeader {
 <3cf169ce-ff7c-44ab-93c0-f78f62d172e2>
 WORD nMaxSkinWeightsPerVertex;
 WORD nMaxSkinWeightsPerFace;
 WORD nBones;
}
template SkinWeights {
 <6f0d123b-bad2-4167-a0d0-80224f25fabb>
 STRING transformNodeName;
 DWORD nWeights;
 array DWORD vertexIndices[nWeights];
 array float weights[nWeights];
 Matrix4x4 matrixOffset;
}

Frame RootFrame {

  FrameTransformMatrix {
    1.000000,0.000000,0.000000,0.000000,
    0.000000,-0.000000,1.000000,0.000000,
    0.000000,1.000000,0.000000,0.000000,
    0.000000,0.000000,0.000000,1.000000;;
  }
Frame Plane {

  FrameTransformMatrix {
    1.000000,0.000000,0.000000,0.000000,
    0.000000,-0.000000,1.000000,0.000000,
    0.000000,-1.000000,-0.000000,0.000000,
    0.000000,0.000000,0.000000,1.000000;;
  }
Mesh {
4;
1.000000; 1.000000; 0.000000;,
-1.000000; 1.000000; 0.000000;,
-1.000000; -1.000000; 0.000000;,
1.000000; -1.000000; 0.000000;;
1;
4; 0, 3, 2, 1;;
  MeshMaterialList {
    0;
    1;
    0;;
    }  //End of MeshMaterialList
  MeshNormals {
4;
    0.000000; 0.000000; 1.000000;,
    0.000000; 0.000000; 1.000000;,
    0.000000; 0.000000; 1.000000;,
    0.000000; 0.000000; 1.000000;;
1;
4; 0, 3, 2, 1;;
}  //End of MeshNormals
MeshTextureCoords {
4;
1.000000;-1.000000;,
0.000000;-1.000000;,
0.000000;-0.000000;,
1.000000;-0.000000;;
}  //End of MeshTextureCoords
 }
}
}

Here is a screenshot of the pre vertex shader input from PIX: Any suggestions for why this is happening? EDIT: On posting realised this PIX output was for a more complicated model, but the same principle applies. Thanks in advance.

Share this post


Link to post
Share on other sites
I believe that function expects that you have D3DUSAGE_BINORMAL and D3DUSAGE_TANGENT elements in your vertex declaration, but you don't. Any particular reason why you're using TEXCOORD's instead of BINORMAL and TANGENT?

D3DXComputeTangentFrameEx lets you specify what semantic you want the binormal and tangent data to be output to, and that function is recommended anyway (D3DXComputeTangent is a legacy function).

Share this post


Link to post
Share on other sites
Meh, i've done a full circle of debugging. I actually had it with those originally and it wasn't working. The reason i changed to use multiple indexes of TEXCOORD was because PIX didn't seem to be picking up TANGENT and BINORMAL as the vertex shader input.

Any idea why that might be?

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