Sign in to follow this  
AntonyCoder

[.net] Can you spot anything wrong in this code that wraps ODE TriMeshes in C#?

Recommended Posts

We're wrapping a dll which it's self is a wrap of the ODE physics library. So far we've wrapped it in bmax(The language it's self was wrote for) and C# (Using a wrapper I wrote) And although it works perfectly with boxes and plane primitive geoms, when I use tri mesh in C# it doesn't work, the boxes fall through bits of geo they shouldn't and it eventually crashes. But I can be sure it's not a problem with the ode dll as it works perfectly in bmax. Here's the tri mesh class I wrote in C# that constructs the buffers and sends them to the dll. Am I doing something wrong with the pointers? Are pointers produced using fixed only valid as long as they're in context/scope?
public class TriMesh
    {
        public static ArrayList tmeshes = new ArrayList();
        public int meshdata, mesh;
        public float[] vertb;
        public int[] trib;
        public TriMesh(Space space, String MeshFile, AuroraC.Pivot parent)
        {
            
            AuroraC.Pivot pivot = AuroraC.SceneManager.CreatePivot();

            if(!(parent==null))
            {
                pivot.Position(parent.X(), parent.Y(), parent.Z());
                pivot.Rotate(parent.GetPitch(), parent.GetYaw(), parent.GetRoll());

            }
            AuroraC.MeshData md = pivot.CreateMeshData(MeshFile);
            float[] Verts = new float[md.Triangles() * 3*4+1];
            Console.WriteLine("");
            Console.WriteLine(md.Triangles() * 3 *3 +1);
            Console.WriteLine(md.Triangles());
            int offset = 0;
            int cnt=0;
            vertb = Verts;
            for (int t = 0; t < md.Triangles(); t++)
            {
                
                for (int v = 0; v < 3; v++)
                {
                    int vert = md.GetTriIndex(t, v);
                    md.GetVertex(vert);
                    Verts[offset] = md.VertexX();
                    Verts[offset + 1] = md.VertexY();
                    Verts[offset + 2] = md.VertexZ();
                    offset += 4;
                    cnt++;
                }
            }
            int[] Tris = new int[ md.Triangles()*3 ];
            offset=0;
            trib = Tris;
            int vrt=0;
            int ntris = ((cnt) / 3);
            int nverts = md.Triangles() * 3;
            nverts = cnt - 1;
            for(int i=0;i<ntris;i++)
            {
                Tris[offset] = vrt; 
                Tris[offset+1] = vrt+1;
                Tris[offset + 2] = vrt + 2;
                offset += 3;
                vrt += 3;
            }
            meshdata = ODE.odeGeomTriMeshDataCreate();

            unsafe
            {
                fixed (float * pVerts = Verts)
                {
                    fixed (int* pTris = Tris)
                    {
                        byte* ppVerts = (byte*)pVerts;
                        byte* ppTris = (byte*)pTris;
                        ODE.odeGeomTriMeshDataBuildSimple(meshdata, ppVerts, nverts, ppTris, ntris);
                    }
                }
            }
            mesh = ODE.odeCreateTriMesh(space.id, meshdata);
            TriMesh.tmeshes.Add(this);
        }
    }
    /*

Using this it eventually crashes at the OdeSpaceCollide fnuction ode. (Which takes space, world and a contact group if you're familar with ode) Here's the dll import section. Notice I use the unsafe keyword due to it having a byte pointer (byte *) type parameter. This compiles ok but I'm not sure if it's valid.
 [DllImport("jv.dll", EntryPoint = "_odeGeomTriMeshDataBuildSimple@20", ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static unsafe extern void odeGeomTriMeshDataBuildSimple(int trimesh,byte * vbank,int numverts,byte *tbank,int elements);
        [DllImport("jv.dll", EntryPoint = "_odeCreateTriMesh@8", ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern int odeCreateTriMesh(int trispace,int meshdata);
        [DllImport("jv.dll", EntryPoint = "_odeGeomTriMeshDataCreate@0", ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern int odeGeomTriMeshDataCreate();

For reference, here is our trimesh class wrote in bmax, which works perfectly. Can you spot where i've gone wrong in converting this code to C#?
 Type oTrimesh
	Field mesh
	Field Vertbank:TBank
	Field tribank:TBank
	Field trimeshdata:Int
	
	'Function CreateTriMesh:Int(trispace:Int,xscale:Float=1.0,yscale:Float=1.0,zscale:Float=1.0)
	Function CreateTriMesh:oTrimesh(trispace:Int,Meshfile$,parent:tentity=Null,x=0,y=0,z=0,doit=1)
	
		Local xscale:Float = 1.0 , yscale:Float = 1.0 , zscale:Float = 1.0
		Local Pivot:tpivot = TPivot.Create()

		If parent<>Null Then
			pivot.position(parent.x() , parent.y() , parent.z() )
			pivot.rotate(parent.getpitch(),parent.getyaw(),parent.getroll())
		EndIf

		If FileType("media\"+meshfile$)<>1 Then RuntimeError "Oh no! "+meshfile$
		Local md:tmeshdata = pivot.CreateMeshData(meshfile$)
		If MD.TRIANGLES()>0 Then
			
			Local vertexlistx#[(md.triangles() * 3)+1]
			Local vertexlisty#[(md.triangles() * 3)+1]
			Local vertexlistz#[(md.triangles() * 3)+1]
			Local cnt=0,vrt
			Local ntris = md.triangles()
			Local nverts=ntris*3
						
			For Local j=0 To md.triangles()-1
				For Local v=0 To 2 
					Local vert = md.getTriIndex( j,v ) 
					md.GetVertex( vert ) 
					vertexlistx[cnt] = md.x() 
					vertexlisty[cnt] = md.y() 
					vertexlistz[cnt] = md.z() 
					cnt = cnt + 1
				Next 
			Next



			Local tribank:TBank=CreateBank(NTris*3*4)
			Local Vertbank:TBank=CreateBank(NVerts*4*4)
			Local Offset:Int=0
			Local TriOffset:Int=0
			
			Local tm:oTrimesh = New oTrimesh
			tm.tribank=tribank
			tm.Vertbank=Vertbank
			ListAddFirst(Trimeshlist,tm:oTrimesh)
			
			For Local v=0 To cnt-1
 				PokeFloat(Vertbank,Offset,vertexlistx[v])
 				Offset:+4
 				PokeFloat(Vertbank,Offset,vertexlisty[v])
 				Offset:+4
 				PokeFloat(Vertbank,Offset,vertexlistz[v])
 				Offset:+ 8
 			Next
			ntris = ((cnt) / 3)-1
			nverts=cnt-1
			For Local v = 0 To NTRIS'(cnt - 1) / 3
				DebugLog trioffset+"   "+BankSize(tribank)
 				PokeInt(tribank,TriOffset,vrt)
				TriOffset:+4
 				PokeInt(tribank,TriOffset,vrt+1)
 				TriOffset:+4
 				PokeInt(tribank,TriOffset,vrt+2)
 				TriOffset:+ 4
				vrt=vrt+3
			Next
			
				Local trimeshdata:Int=dGeomTriMeshDataCreate()
				dGeomTriMeshDataBuildSimple(trimeshdata , BankBuf(Vertbank) , NVerts , BankBuf(tribank) , NTris * 3)
				tm.mesh = dCreateTriMesh(trispace , trimeshdata)
				tm.trimeshdata=trimeshdata
			
			Return tm
		EndIf
	End Function

Share this post


Link to post
Share on other sites
Not sure if this is your problem or not. But the casting of a float to a byte could be a huge problem...essentially you are taking a very large number, possibly 3.4 * 10^38 and truncating it to a range of 0-255. Essentially collapsing 8 bytes into 1 byte.

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