Archived

This topic is now archived and is closed to further replies.

Telamon

Simple C# DX Question - Please Help!

Recommended Posts

I posted a couple days ago about texture mapping a sphere with DX9 in C#, but I am unable to view past posts (the site just hangs) in this forum and it looks like something may gone wrong with it, since it doesn''t show up in the forum search. Any way, I''m almost done my Perlin Noise demo - which creates some really neat effects - but I need to be able to take the texture and map it on to a sphere. The sooner I figure out how to do this, the sooner I can release something of value to the community (so maybe helping me figure out what I''m doing wrong will benefit other people too). Onto the code... The basic problem I''m having is that the sphere returned by the Mesh.Sphere function doesn''t seem to have texture coords. This is a known issue with the equivalent unmanaged C++ function (D3DX::CreateSphereMesh). I have found a workaround that works in C++ from elsewhere on this forum, but now I need to convert it into C#. Problem is, I''m having trouble mapping the unmanaged C++ DX functions to their C# counterparts - partly because the managed DX docs are so poor, partly because I''m a noob who has never used D3D before. Below is my attempt to create a function that returns a sphere mesh with texture coords. At the moment it doesn''t even compile. Below that is the C++ version of the function that I''m using as a template. It''s very frustrating because I know it''s just a one or two line fix. Please help! private Mesh CreateMappedSphere(Device dev, float radius, int slices, int stacks) { Mesh sphere; Mesh texSphere; sphere = Mesh.Sphere(dev, radius, slices, stacks); MeshFlags flags; flags = sphere.Options.Use32Bit ? MeshFlags.Use32Bit : 0; // if(sphere.VertexFormat & VertexFormats.Texture0 == 0) // { texSphere = sphere.Clone(flags | MeshFlags.Managed, sphere.VertexFormat | VertexFormats.Texture0, dev); sphere.Dispose(); sphere = texSphere; // } else { // return sphere;} CustomVertex.PositionNormalTextured[] verts = (CustomVertex.PositionNormalTextured[])sphere.LockVertexBuffer(CustomVertex.PositionNormalTexture,LockFlags.None, 0); int numVerts = sphere.NumberVertices; for(int i = 0; i < numVerts; i++) { verts.Tu = Math.Asin(verts[i].Nx)/3.1415627 +0.5f; verts[i].Tv = Math.Asin(verts[i].Ny)/3.1415626 +0.5f; } sphere.UnlockVertexBuffer(); return sphere; } That''s what my attempt looks like. It doesn''t work. Now here is code that does work. I think most of my problem centers around the functions involving the vertex buffer. Vertex buffers are new to me, since I never had to explicitely use them in OpenGL. LPD3DXMESH CreateMappedSphere(LPDIRECT3DDEVICE8 pDev,float fRad,UINT slices,UINT stacks) { // create the sphere LPD3DXMESH mesh; if (FAILED(D3DXCreateSphere(pDev,fRad,slices,stacks,&mesh,NULL))) return NULL; // create a copy of the mesh with texture coordinates, // since the D3DX function doesn''t include them LPD3DXMESH texMesh; if (FAILED(mesh->CloneMeshFVF(D3DXMESH_SYSTEMMEM,FVF_VERTEX,pDev,&texMesh))) // failed, return un-textured mesh return mesh; // finished with the original mesh, release it mesh->Release(); // lock the vertex buffer LPVERTEX pVerts; if (SUCCEEDED(texMesh->LockVertexBuffer(0,(BYTE **) &pVerts))) { // get vertex count int numVerts=texMesh->GetNumVertices(); // loop through the vertices for (int i=0;itu=asinf(pVerts->norm.x)/D3DX_PI+0.5f; pVerts->tv=asinf(pVerts->norm.y)/D3DX_PI+0.5f; // go to next vertex pVerts++; } // unlock the vertex buffer texMesh->UnlockVertexBuffer(); } // return pointer to caller return texMesh; } Thank you so much! ---------------------------------------- Let be be finale of seem, seems to me. ---------------------------------------- Coding: http://www.stanford.edu/~jjshed/coding Miscellany: http://www.stanford.edu/~jjshed

Share this post


Link to post
Share on other sites
Here ya go:


private Mesh CreateMappedSphere(Device dev, float radius, int slices, int stacks)
{
Mesh sphere;
Mesh texSphere;

sphere = Mesh.Sphere(dev, radius, slices, stacks);

MeshFlags flags;
flags = sphere.Options.Use32Bit ? MeshFlags.Use32Bit : 0;

texSphere = sphere.Clone(flags | MeshFlags.Managed, sphere.VertexFormat | VertexFormats.Texture0, dev);
sphere.Dispose();
sphere = texSphere;

CustomVertex.PositionNormalTextured[] verts = (CustomVertex.PositionNormalTextured[]) sphere.VertexBuffer.Lock(0,0);

int numVerts = sphere.NumberVertices;
for(int i = 0; i < numVerts; i++)
{
verts[ i ].Tu = Math.Asin(verts[ i ].Nx)/3.1415627 +0.5f;
verts[ i ].Tv = Math.Asin(verts[ i ].Ny)/3.1415626 +0.5f;
}

sphere.UnlockVertexBuffer();
return sphere;
}


PositionNormalTexture <- forgot "d" at the end on the LockVertexBuffer, I totally changed it so that isn't even in there anymore

verts.Tu <- the code block removed the [ i ] :/

I also changed the Lock function to the way that I do it (it works without much fuss)


It compiles... I just hope it does what you want it to...

[edited by - Nypyren on July 28, 2003 1:22:42 PM]

Share this post


Link to post
Share on other sites
Hmmm... It does compile, but it crashed when I try to use it. I get "NullArguement Not Accepted" on the VertexBuffer locking step. I poked around with the debugger a little bit and it turns out that the BaseMesh.VertexBuffer.length field of the "sphere" variable at that point is equal to zero. It seems to me that if the sphere was cloned properly this would be a non-zero value. Is there something wrong with the way I''m cloning the sphere? I just gathered from the docs that that''s how you add more fields to the vertex information. I basically am looking for a C# substitute for the mesh->CloneMeshFVF function. Please help - I feel I''m very close, and having to deal with this low level stuff to just draw a simple sphere is very frustrating.

Share this post


Link to post
Share on other sites