Adding second set of position coordinates to mesh

Started by
3 comments, last by MikeWW 18 years, 4 months ago
Basically I load a mesh and give it some extra information with this:

D3DVERTEXELEMENT9 elements[] =
	{
		{ 0, sizeof( float ) * 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
		{ 0, sizeof( float ) * 3, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 1 },
		{ 0, sizeof( float ) * 6, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 },
		{ 0, sizeof( float ) * 9, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
		{ 0, sizeof( float ) * 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0 },
		{ 0, sizeof( float ) * 15, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL, 0 },
		D3DDECL_END()
	};
	LPD3DXMESH temp;
	WaterMesh->CloneMesh( D3DXMESH_MANAGED, elements, D3D.D3DDevice, &temp );
	
	WaterMesh->Release();
	WaterMesh = temp;
	void* pData;
	WaterMesh->LockVertexBuffer(D3DLOCK_DISCARD, &pData);
	WaterMesh->UnlockVertexBuffer();
	D3DXComputeTangentFrame(WaterMesh, 0);

I give the mesh two sets of position coordinates, but I do not know how to fill the second set with data, how would I go about doing this? -Chris
Advertisement
Just lock the meshes vertex buffer (ID3DXBaseMesh::LockVertexBuffer) and fill in the data you want and unlock.

If speed is of importance (i.e. the VB is dynamic and updated per frame) make sure you write to every element of the locked vertex buffer in order (even if you are just writing what is already there) as otherwise, due to the way caches work, just writing 12 bytes every 72 bytes (for example) may end up as a read-modify-write instead of just a write. If the VB is dynamic use the NOOVERWRITE/DISCARD flag.

Also if you could reduce your vertex size to 64 bytes (calculate the binormal or tangent in a vertex shader maybe?) you may get better performance of many gfx cards (for slightly different cache reasons).

Hope this helps. Not the clearest I admit...!

Mike.
I tried locking the vertex buffer and copying the entire thing over and setting the second position to equal the first, but it only copied over the first and set all of the second ones to zero. I am not exactly sure what I am doing wrong because I read in the position from the first mesh into a D3DXVECTOR3, then set both the first and second position to the position I read in, but the second set gets set to zero somehow.

-Chris
Here is the code that I am using to add a second set of positions:

ID3DXMesh* AddMeshInfo(IDirect3DDevice9* D3DDevice , ID3DXMesh* Mesh){	typedef struct {	D3DXVECTOR3 Position1;	D3DXVECTOR3 Position2;	D3DXVECTOR3 Normal;	D3DXVECTOR3 TexCoord;	D3DXVECTOR3 Tangent;	D3DXVECTOR3 Binormal;	} TexCopyVertex;	D3DVERTEXELEMENT9 elements[] =	{		{ 0, sizeof( float ) * 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },		{ 0, sizeof( float ) * 3, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 1 },		{ 0, sizeof( float ) * 6, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 },		{ 0, sizeof( float ) * 9, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },		{ 0, sizeof( float ) * 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0 },		{ 0, sizeof( float ) * 15, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL, 0 },		D3DDECL_END()	};	ID3DXMesh* TempMesh;	char *MeshPtr, *TempMeshPtr;	Mesh->CloneMesh(NULL, elements, D3DDevice, &TempMesh);	Mesh->Release();	Mesh = TempMesh;	DWORD MeshSize = D3DXGetFVFVertexSize(Mesh->GetFVF());	DWORD TempMeshSize = D3DXGetFVFVertexSize(TempMesh->GetFVF());	Mesh->LockVertexBuffer(D3DLOCK_READONLY, (void**)&MeshPtr);	TempMesh->LockVertexBuffer(0, (void**)&TempMeshPtr);	for(DWORD i=0; i < Mesh->GetNumVertices(); i++)	{		TexCopyVertex *MeshVertex = (TexCopyVertex*)MeshPtr;		TexCopyVertex *TempMeshVertex = (TexCopyVertex*)TempMeshPtr;		D3DXVECTOR3 PositionTemp = MeshVertex->Position1;		TempMeshVertex->Position1 = PositionTemp;		TempMeshVertex->Position2 = PositionTemp;		TempMeshVertex->Normal = MeshVertex->Normal;		TempMeshVertex->TexCoord = MeshVertex->TexCoord;		TempMeshVertex->Tangent = MeshVertex->Tangent;		TempMeshVertex->Binormal = MeshVertex->Binormal;		MeshPtr     += MeshSize;		TempMeshPtr += TempMeshSize;	}	Mesh->UnlockVertexBuffer();	TempMesh->UnlockVertexBuffer();	D3DXComputeTangentFrame(TempMesh, 0);	return TempMesh;}


It works fine except that all of the positions in the second set of positions are set to zero.

-Chris
Hi,

I'm suprised that that code works other than setting the second position element as you are referring to vertex elements in both the original and new mesh vertex buffers by casting them both to pointer of the same type (TexCopyVertex). Remember that the original mesh does not have the second position element in it so you will need a separate struct for that.

Also you may want to use a pragma to ensure that the structs use no alignment padding.

For example:
#pragma pack(push, 1)struct sOriginalVertex {    D3DXVECTOR3 m_pos;    D3DXVECTOR3 m_normal;    D3DXVECTOR3 m_texCoord;    D3DXVECTOR3 m_tangent;    D3DXVECTOR3 m_binormal;};struct sNewVertex {    D3DXVECTOR3 m_pos;    D3DXVECTOR3 m_pos2;    D3DXVECTOR3 m_normal;    D3DXVECTOR3 m_texCoord;    D3DXVECTOR3 m_tangent;    D3DXVECTOR3 m_binormal;};#pragma pack(pop)


Also, CloneMesh should have copied the vertex data for you so if you ignore my "If speed is of importance..." advice from my earlier reply you can simply do this:

	sNewVertex *newVerts;	TempMesh->LockVertexBuffer(0, (void**)&newVerts);	for(DWORD i=0; i < TempMesh->GetNumVertices(); i++)	{		newVerts->m_pos2 = newVerts->m_pos;		newVerts++;	}	TempMesh->UnlockVertexBuffer();


Now, this should work as far as I can see. I haven't had to do exactly this before but I don't see why it wouldn't work. (I typically just use ID3DXMeshes as a quick way of loading X files from disk - I then copy them into custom structures).

Hope this helps,

Mike.

[Edited by - Muhammad Haggag on December 6, 2005 8:05:32 AM]

This topic is closed to new replies.

Advertisement