Game Programming and Development Tools

C# DirectX Mesh Question – mr_friend

mr_friend

Member

Posts: 17
From: Bonner Springs, KS, USA
Registered: 06-19-2005
Detailed programming question.

Given: Ok I know how to load a mesh from a (.X) file, I know how to manually create a VertexBuffer for simple geometry like is in the DX 3D tutorial section.

Goal: In C# to use a detection algorithm that looks at the 3 vertexes per triangle and compares them to a sphere, for a collision detection pass.

Issue: When I load a (.X) mesh structure the vertex’s are stored into a vertexBuffer, and I haven’t found any way to directly access this memory for the collision detection algorithm. I have also come to realize that this memory buffer could be memory stored on the graphics card itself. So my question is would it be advisable to keep 2 copies of the mesh data? One in the Graphics card memory for fast rendering, and one copy in system memory for collision detection or is there a better way?


References:
C# (free compiler, the one I use): http://www.icsharpcode.net/OpenSource/SD/

Sample (.X) Mesh Loader: DirectX\ Samples\Managed\Direct3D\Tutorials\Tutorial6

Collision detection algorithm sample: http://www.peroxide.dk/download/tutorials/tut10/pxdtut10.html

Gary

------------------
"Holy, holy, holy is the Lord God Almighty, who was, and is, and is to come."(rev. 4:8)

HanClinto

Administrator

Posts: 1828
From: Indiana
Registered: 10-11-2004
You did a great job of laying out the background, thanks!

What about the vertexBuffer can't you access?

From looking at the MSDN page, it seems like you should be able to do something like:

myVertexBuff[0].Position = new Vertex3(0.1f, 0.0f, 2.0f);

and be able to access that information in the same way.

You're saying that you're trying to access the memory directly? Or can you do it with the public members of the vertices that are stored in your vertexBuffer?

Hrm -- perhaps a small paste of code showing what you're trying to do? 3D isn't my specialty, but C# is -- so I'll see what I can do.

Respectfully,
clint

------------------
http://www.includingjudas.com/christiangame.html

mr_friend

Member

Posts: 17
From: Bonner Springs, KS, USA
Registered: 06-19-2005
I thought in order to get access to the VertexBuffer data, I have to lock the buffer? is this incorrect. something like...
Vector3 temp = mesh.LockVertexBuffer(ect.., besides when I have tried using the mesh.VertexBuffer[0] approach it wouldnt let me use the "[]" saying it cannot apply indexing with "[]" error. If I am messing this up please let me know, Im still getting acustom to C#, from c++.

------------------
"Holy, holy, holy is the Lord God Almighty, who was, and is, and is to come."(rev. 4:8)

Briant

Member

Posts: 742
From: Stony Plain, Alberta, Canada
Registered: 01-20-2001
In C++ (which I am much more familiar with) LockVertexBuffer locks the buffer for you and gives you a pointer to the buffer. In C#, in returns a "GraphicsStream". I found this sample code on msdn:


using System;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

public struct PositionNormalTexVertex
{
public Vector3 Position;
public Vector3 Normal;
public float Tu0, Tv0;
public static readonly VertexFormats FVF = VertexFormats.Position | VertexFormats.Texture1;
}
public class Example
{
public unsafe void GraphicsStreamReadWrite()
{
//Create a vertex buffer in the managed pool
VertexBuffer vb = new VertexBuffer(typeof(PositionNormalTexVertex), 100, device, Usage.None, PositionNormalTexVertex.FVF, Pool.Managed);

//First, fill an array of PositionNormalTexVertex elements with data.
PositionNormalTexVertex[] vertices = new PositionNormalTexVertex[50];
for(int i=0; i<50; i++)
{
//fill the vertices with some data...
vertices[i].Position = new Vector3(3f,4f,5f);
}

//The size of the verticies are 32-bytes each (float3 (12) + float3 (12) + float(4) + float(4))
//To lock 50 verticies, the size of the lock would be 1600 (32 * 50)
GraphicsStream vbData = vb.Lock(0,1600, LockFlags.None);

//copy the vertex data into the vertex buffer
vbData.Write(vertices);

//Unlock the VB
vb.Unlock();


//This time, lock the entire VertexBuffer
vbData = vb.Lock(0, 3200, LockFlags.None);

//Cast the InternalDataPointer (a void pointer) to an array of verticies
PositionNormalTexVertex* vbArray = (PositionNormalTexVertex*) vbData.InternalDataPointer;

for(int i=0; i<100; i++)
{
//perform some operations on the data
vbArray[i].Tu0 = i;
vbArray[i].Tv0 = vbArray[i].Tu0 * 2;

Console.WriteLine(vbArray[i].Tv0.ToString());
}

//Unlock the buffer
vb.Unlock();
vb.Dispose();
}
}

Or you could keep a second copy of the mesh data for your collision detection, but it would probably be cleaner to understand locking and using the vertex buffer instead.

------------------
Brian

mr_friend

Member

Posts: 17
From: Bonner Springs, KS, USA
Registered: 06-19-2005
Brian,

Sorry, it's taken me so long to try to emplemnt the code you posted, but I am having a time trying to get a sample to compile with that code snipit. I looked up the MS reference, they that is the exent of code they post. I guess the hardest part about this for me is I am having a real difficult time finding simple, full complete source code to look at, that I can compile, and tweek until I understand how it all works and fits to gether. I have tried a few simple pieces of code but every time I insert the snipit, I get error of one type or another and my example no longer compiles. I will try to get a stripped out version to post here, but if you come across a compilable example of the graphicsStream, please post it.

Thanks
Gary

------------------
"Holy, holy, holy is the Lord God Almighty, who was, and is, and is to come."(rev. 4:8)

shadowsill
Junior Member

Posts: 1
From:
Registered: 06-28-2005
wow, what are the odds, i just spent the last 5 hours trying to figure out this very question - stumbled across this page while searching for the answer. found all that msdn stuff a while ago, didn't help me much ...

perhaps try this page - h**p://www.developerfusion.co.uk/show/4387/4/

haven't really read through it too much, and i am too tired to now, but will read through it tomorrow and let you know if i have found anything out

best of luck to you, if you figure anything out before i do please post your solution

mr_friend

Member

Posts: 17
From: Bonner Springs, KS, USA
Registered: 06-19-2005
Ok, I think I have caputred the vertex data, safely. but am still working on how to get the index data, so i can correctly create the 3 Vertex triangle to do the collision on. Below is the raw vertex capture.

--Inserted into the Tutoral#6 MS sample

mesh = Mesh.FromFile("tiger.x", MeshFlags.SystemMemory, device, out materials);
//Standard Code above tis point, Inserted into OnResetDevice()
GraphicsStream stm = mesh.VertexBuffer.Lock(0,0,LockFlags.None);
Vector3[] vertices = new Vector3[mesh.NumberVertices];

for (int i = 0; i < mesh.NumberVertices; i++)
{
vertices[i] = (Vector3) stm.Read(typeof(Vector3));
}

mesh.VertexBuffer.Unlock();
// End code insert

------------------
"Holy, holy, holy is the Lord God Almighty, who was, and is, and is to come."(rev. 4:8)

mr_friend

Member

Posts: 17
From: Bonner Springs, KS, USA
Registered: 06-19-2005
PRAISE THE LORD!, PRAISE GOD!!
After looking and not finding, He has provided a way. It's all C# no unsafe code sections, the Vertix points get transfered to Vector3[], and the indexes get transfered to short[]. This would allow loading using the MS .x file loading and then extracting the triangles for a collision detection algoithem. (More then Box, and sphere)
//****
int [] ranks = new int[1];
ranks[0] = mesh.NumberFaces*3; //how many Indices do we have for our triangles
System.Array arr = mesh.LockIndexBuffer(typeof(short), LockFlags.ReadOnly, ranks);
MessageBox.Show("IndexBuffer Type="+mesh.IndexBuffer.Description.ToString());

//Size of short = 2, size of int = 4
short[] indices = new short[mesh.NumberFaces*3];

string snipit = "";
for (int icker = 0; icker < mesh.NumberFaces; icker+=3)
{
indices[icker + 0] = (short) arr.GetValue(icker+0);
indices[icker + 1] = (short) arr.GetValue(icker+1);
indices[icker + 2] = (short) arr.GetValue(icker+2);

if ((10*3) > icker) // Show me the first 10 triangle Cordinates, to see that this is working
snipit += "Triangle ("+indices[icker+0].ToString()+","+indices[icker+1].ToString()+","+indices[icker+2].ToString()+")\r\n";

}

MessageBox.Show(snipit);

GraphicsStream indexList = mesh.IndexBuffer.Lock(0,0, LockFlags.None);
GraphicsStream stm = mesh.VertexBuffer.Lock(0,0,LockFlags.None);
Vector3[] vertices = new Vector3[mesh.NumberVertices];

for (int i = 0; i < mesh.NumberVertices; i++)
{
vertices[i] = (Vector3) stm.Read(typeof(Vector3));
}

mesh.VertexBuffer.Unlock();

//**********


I Left the messageboxes I used. If you looking to understand what I did you can look at the code and message boxes to get a better idea why i used short[] for indices.

Later Gary

------------------
"Holy, holy, holy is the Lord God Almighty, who was, and is, and is to come."(rev. 4:8)