Numsgil
27-09-2007 10:13:40
I'm trying to convert a mesh I made with ManualObject to one using buffers. I've done this before in C++, but it's been a while. The code below is my go at it in C# with Mogre.
It's causing all sorts of problems. Various "the data you are trying to read or write to is protected" problems. Trying to uncomment the second set of texture coordinates amplifies the problems further. Tweaking it I've managed to get it to run in OpenGL and verify that the mesh looks right, so it's mostly working. But even then, when I close the program down, it'll throw the old "protected memory" problem again.
I'm guessing it has to do with the VertexData. When it gets disposed it seems to cause the protected memory error.
I'm not even really sure what I'm doing here, or if I'm doing something really wrong. I'd appreciate any insight anyone can offer.
elswhere...
It's causing all sorts of problems. Various "the data you are trying to read or write to is protected" problems. Trying to uncomment the second set of texture coordinates amplifies the problems further. Tweaking it I've managed to get it to run in OpenGL and verify that the mesh looks right, so it's mostly working. But even then, when I close the program down, it'll throw the old "protected memory" problem again.
I'm guessing it has to do with the VertexData. When it gets disposed it seems to cause the protected memory error.
I'm not even really sure what I'm doing here, or if I'm doing something really wrong. I'd appreciate any insight anyone can offer.
public MeshPtr BuildMainPlanetMeshHardwareBuffer(int Face, int Quad)
{
//1. Create the mesh
MeshPtr Mesh = Mogre.MeshManager.Singleton.CreateManual("Planet Mesh " + Face + "," + Quad, "Planet Mesh");
//2. Create a sub mesh
SubMesh SubMesh = Mesh.CreateSubMesh();
//3. Create a shared vertex data?
Mesh.sharedVertexData = new VertexData();
VertexData vertexData = Mesh.sharedVertexData;
//4. define the vertex format
VertexDeclaration VertexDecl = vertexData.vertexDeclaration;
uint currOffset = 0;
// positions
VertexDecl.AddElement(0, currOffset, VertexElementType.VET_FLOAT3, VertexElementSemantic.VES_POSITION);
currOffset += VertexElement.GetTypeSize(VertexElementType.VET_FLOAT3);
// normals
VertexDecl.AddElement(0, currOffset, VertexElementType.VET_FLOAT3, VertexElementSemantic.VES_NORMAL);
currOffset += VertexElement.GetTypeSize(VertexElementType.VET_FLOAT3);
// two dimensional texture coordinates
VertexDecl.AddElement(0, currOffset, VertexElementType.VET_FLOAT2, VertexElementSemantic.VES_TEXTURE_COORDINATES);
currOffset += VertexElement.GetTypeSize(VertexElementType.VET_FLOAT2);
//second texture coordinates
//VertexDecl.AddElement(0, currOffset, VertexElementType.VET_FLOAT2, VertexElementSemantic.VES_TEXTURE_COORDINATES);
//currOffset += VertexElement.GetTypeSize(VertexElementType.VET_FLOAT2);
//5. allocate the vertex buffer
vertexData.vertexCount =
(uint)(Data.Lithosphere.HeightMap.Subdivisions + 1) *
(uint)(Data.Lithosphere.HeightMap.Subdivisions + 1);
HardwareVertexBufferSharedPtr vBuf = HardwareBufferManager.Singleton.CreateVertexBuffer(
VertexDecl.GetVertexSize(0),
vertexData.vertexCount,
HardwareBuffer.Usage.HBU_DYNAMIC_WRITE_ONLY,
false); //No shadow buffer
//6. Bind to "source"?
VertexBufferBinding binding = vertexData.vertexBufferBinding;
binding.SetBinding(0, vBuf);
unsafe
{
float* pVertex = (float*)(vBuf.Lock(HardwareBuffer.LockOptions.HBL_DISCARD));
// allocate index buffer
SubMesh.indexData.indexCount =
(uint)(Data.Lithosphere.HeightMap.Subdivisions) *
(uint)(Data.Lithosphere.HeightMap.Subdivisions) * 2 * 3;
SubMesh.indexData.indexBuffer = HardwareBufferManager.Singleton.CreateIndexBuffer(
HardwareIndexBuffer.IndexType.IT_16BIT,
SubMesh.indexData.indexCount,
HardwareBuffer.Usage.HBU_STATIC_WRITE_ONLY,
false); //don't use shadow buffer
HardwareIndexBufferSharedPtr iBuf = SubMesh.indexData.indexBuffer;
ushort* pIndices = (ushort*)(iBuf.Lock(HardwareBuffer.LockOptions.HBL_DISCARD));
//...
int Size = Data.Lithosphere.HeightMap.Subdivisions;
Vector3[,] Positions = new Vector3[Size + 3, Size + 3];
Vector3[,] Normals = new Vector3[Size + 3, Size + 3];
Iterator<Object> DummyIter = new Iterator<object>(Size, Face, 0, 1);
//Set up initial data
for (int Y = 0; Y <= Size + 2; ++Y)
for (int X = -1; X <= Size + 1; ++X)
{
Positions[X + 1, Y] = Data.Lithosphere.ActualPosition(DummyIter._Set(Face, X + Quad * Size, Y));
Normals[X + 1, Y] = new Vector3(0, 1, 0);
}
//Find normals
for (int Y = 1; Y <= Size + 1; ++Y)
for (int X = -1; X <= Size; ++X)
{
//Foreach tris
//add tris.normal to a, b, c
Vector3 a = Positions[(X + 1) + 1, Y];
Vector3 b = Positions[(X + 1), Y + 1];
Vector3 c = Positions[(X + 1) + 1, Y + 1];
Vector3 d = Positions[(X + 1), Y];
Vector3 NormalBottom = new Geometry.Triangle(d, b, a).Normal();
Vector3 NormalTop = new Geometry.Triangle(a, b, c).Normal();
Normals[(X + 1) + 1, Y] += NormalTop + NormalBottom; //a
Normals[(X + 1), Y + 1] += NormalTop + NormalBottom; //b
Normals[(X + 1) + 1, Y + 1] += NormalTop; //c
Normals[(X + 1), Y] += NormalBottom; //d
}
//Add triangles
for (int Y = 0; Y < Size; ++Y)
for (int X = 0; X < Size; ++X)
{
ushort a = (ushort)((Size + 1) * (Y) + X + 1);
ushort b = (ushort)((Size + 1) * (Y + 1) + X);
ushort c = (ushort)((Size + 1) * (Y + 1) + X + 1);
ushort d = (ushort)((Size + 1) * (Y) + X);
*pIndices++ = c;
*pIndices++ = b;
*pIndices++ = a;
*pIndices++ = a;
*pIndices++ = b;
*pIndices++ = d;
}
for (int Y = 1; Y <= Size + 1; ++Y)
for (int X = 0; X <= Size; ++X)
{
//Update bounding box, etc.
*pVertex++ = Positions[X + 1, Y].x;
*pVertex++ = Positions[X + 1, Y].y;
*pVertex++ = Positions[X + 1, Y].z;
*pVertex++ = Normals[X + 1, Y].NormalisedCopy.x;
*pVertex++ = Normals[X + 1, Y].NormalisedCopy.y;
*pVertex++ = Normals[X + 1, Y].NormalisedCopy.z;
*pVertex++ = (X + Y / 2.0f);
*pVertex++ = Y;
//*pVertex++ = (X + Y / 2.0f) / (float)(Data.Lithosphere.HeightMap.Subdivisions + 1);
//*pVertex++ = Y / (float)(Data.Lithosphere.HeightMap.Subdivisions + 1);
}
Mesh._setBounds(new AxisAlignedBox(-10000,-10000,-10000,10000,10000,10000));
Mesh._setBoundingSphereRadius((float)System.Math.Sqrt(3*10000*10000));
// Unlock
vBuf.Unlock();
iBuf.Unlock();
}//end unsafe
// Generate face list
SubMesh.useSharedVertices = true;
Mesh.Load();
return Mesh;
}
elswhere...
Mogre.MeshPtr mesh = Meshes[0].BuildMainPlanetMeshHardwareBuffer(0, 0);
Mogre.Entity entity = Data.Ogre.OgreManager.SceneManager.CreateEntity("The Planet Sort Of", "Planet Mesh 0,0");
entity.SetMaterialName("TestMaterial");
Data.Ogre.OgreManager.SceneManager.RootSceneNode.CreateChildSceneNode().AttachObject(entity);