[.net] Please help in converting small mesh DirectX function from C++ to C#

Started by
2 comments, last by paulecoyote 19 years ago
Hi, Happy Easter all... I'm dabbling with managed DirectX with C#, and have come across a slight lack of documentation regarding use of the Mesh object. In C++ there is an excellent article by an MVP here (http://www.mvps.org/directx/articles/scalemesh.htm) that I'm trying to convert for use in C#. However because of the cheating way it goes about going through the vertex array - expecting position data to be the first three parts of the structure then just advancing x amount of memory more for each iteration in that for loop. I can't get my head around how to do the same thing using a vertex type I might not know about in advance in C#. For completeness here is the function from that article that is giving me the headache, in C++

HRESULT ScaleMesh(ID3DXMesh *pMesh, float scale, D3DXVECTOR3 *offset=NULL)
{
	BYTE *ptr=NULL;
	HRESULT hr;
	D3DXVECTOR3 vOff;

	// return failure if no mesh pointer set
	if (!pMesh)
		return D3DERR_INVALIDCALL;

	// select default or specified offset vector
	if (offset)
		vOff=*offset;
	else
		vOff=D3DXVECTOR3(0.0f,0.0f,0.0f);

	// get the face count
	DWORD numVerts=pMesh->GetNumVertices();

	// get the FVF flags
	DWORD fvf=pMesh->GetFVF();

	// calculate vertex size
	DWORD vertSize=D3DXGetFVFVertexSize(fvf);

	// lock the vertex buffer
	if (FAILED(hr=pMesh->LockVertexBuffer(0,&ptr)))
	
		// return on failure
		return hr;

	// loop through the vertices
	for (DWORD i=0;i<numVerts;i++) {

		// get pointer to location
		D3DXVECTOR3 *vPtr=(D3DXVECTOR3 *) ptr;

		// scale the vertex
		*vPtr+=vOff;
		vPtr->x*=scale;
		vPtr->y*=scale;
		vPtr->z*=scale;

		// increment pointer to next vertex
		ptr+=vertSize;
	}

	// unlock the vertex buffer
	if (FAILED(hr=pMesh->UnlockVertexBuffer()))

		// return on failure
		return hr;
		
	// return success to caller
	return S_OK;
}


... now surely there is a C# way I can do this by just reflecting the type held in the vertex buffer somehow?
Anything posted is personal opinion which does not in anyway reflect or represent my employer. Any code and opinion is expressed “as is” and used at your own risk – it does not constitute a legal relationship of any kind.
Advertisement
Well, you can get the vertex format from the Mesh.VertexFormat property, and you can lock the vertex buffer using Mesh.LockVertexBuffer.

Beyond that, I'm wondering why you wouldn't just set the scale matrix before using DrawSubset instead of manually scaling the verts...
Michael Russell / QA Manager, Ritual EntertainmentI used to play SimCity on a 1:1 scale.
All that pointer hackyness, though usualy possible in C#, is probably not worth your time. In managed land, If we don't know much about the vertex type, instead of locking into a generic memeoy pointer we we can lock into a GraphicsStream. The GraphicsStream allows us to read and write various types, be they complete verts or just portions of verts, to and from the VB data.

So to scale you would:

Lock the VB into a graphics stream then:
read a Vector3 from mthe stream.
multiply it by some value.
write it back to the stream.
read and write the rest of the vert bytes from and to the stream.
repeat.

Use Mesh.NumberBytesPerVertex and Mesh.NumberVertices to keep track of where you are, to figure out how much stuff follows the position and to know when to stop.

If you are using planning on using Declarations for any of your meshes, you cannot be sure that the position data will be first thing in the vert, but you probably don't need to worry about that right now.

Quote:
Beyond that, I'm wondering why you wouldn't just set the scale matrix before using DrawSubset instead of manually scaling the verts...


Yes you can set the world matrix, but I imagine that this is just a precursor for more involved vert by vert operations. If it is not then you are probably wasting your time.
Quote:Original post by turnpast
All that pointer hackyness, though usualy possible in C#, is probably not worth your time. In managed land, If we don't know much about the vertex type, instead of locking into a generic memeoy pointer we we can lock into a GraphicsStream. The GraphicsStream allows us to read and write various types, be they complete verts or just portions of verts, to and from the VB data.

So to scale you would:

Lock the VB into a graphics stream then:
read a Vector3 from mthe stream.
multiply it by some value.
write it back to the stream.
read and write the rest of the vert bytes from and to the stream.
repeat.

Use Mesh.NumberBytesPerVertex and Mesh.NumberVertices to keep track of where you are, to figure out how much stuff follows the position and to know when to stop.

If you are using planning on using Declarations for any of your meshes, you cannot be sure that the position data will be first thing in the vert, but you probably don't need to worry about that right now.

Quote:
Beyond that, I'm wondering why you wouldn't just set the scale matrix before using DrawSubset instead of manually scaling the verts...


Yes you can set the world matrix, but I imagine that this is just a precursor for more involved vert by vert operations. If it is not then you are probably wasting your time.


Thanks I will try that. This is a precursor to trying out more complex mesh manipulation later down the line, but I wanted to figure out what was possible.

As for the scaling matrix, I have thought of that, but if possible I wanted to scale the mesh once rather then in each world transform.

Rating +++++ for both of u though for replying!
Anything posted is personal opinion which does not in anyway reflect or represent my employer. Any code and opinion is expressed “as is” and used at your own risk – it does not constitute a legal relationship of any kind.

This topic is closed to new replies.

Advertisement