MOGRE ManualSphereMeshes        

C# conversion of ManualSphereMeshes

This code creates a sphere mesh with the given name:

unsafe public void CreateSphere(string strName, float r, int nRings, int nSegments)
{
        MeshPtr pSphere = MeshManager.Singleton.CreateManual(strName, ResourceGroupManager.DEFAULT_RESOURCE_GROUP_NAME);
        SubMesh pSphereVertex = pSphere.CreateSubMesh();

        pSphere.sharedVertexData = new VertexData();
    VertexData vertexData = pSphere.sharedVertexData;

        // 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, 0);
        currOffset += VertexElement.GetTypeSize(VertexElementType.VET_FLOAT2);

        // allocate the vertex buffer
        vertexData.vertexCount = (uint)((nRings + 1) * (nSegments+1));
        HardwareVertexBufferSharedPtr vBuf = HardwareBufferManager.Singleton.CreateVertexBuffer(vertexDecl.GetVertexSize(0), vertexData.vertexCount, HardwareBuffer.Usage.HBU_STATIC_WRITE_ONLY, false);
        VertexBufferBinding binding = vertexData.vertexBufferBinding;
        binding.SetBinding(0, vBuf);
    float* pVertex = (float*)vBuf.Lock(HardwareBuffer.LockOptions.HBL_DISCARD);

        // allocate index buffer
        pSphereVertex.indexData.indexCount = (uint)(6 * nRings * (nSegments + 1));
        pSphereVertex.indexData.indexBuffer = HardwareBufferManager.Singleton.CreateIndexBuffer(HardwareIndexBuffer.IndexType.IT_16BIT, pSphereVertex.indexData.indexCount, HardwareBuffer.Usage.HBU_STATIC_WRITE_ONLY, false);
        HardwareIndexBufferSharedPtr iBuf = pSphereVertex.indexData.indexBuffer;
    ushort* pIndices = (ushort*)iBuf.Lock(HardwareBuffer.LockOptions.HBL_DISCARD);

    float fDeltaRingAngle = (float)(Mogre.Math.PI / nRings);
    float fDeltaSegAngle = (float)(2 * Mogre.Math.PI / nSegments);
        ushort wVerticeIndex = 0 ;

        // Generate the group of rings for the sphere
        for( int ring = 0; ring <= nRings; ring++ ) {
        float r0 = r * Mogre.Math.Sin(ring * fDeltaRingAngle);
        float y0 = r * Mogre.Math.Cos(ring * fDeltaRingAngle);

            // Generate the group of segments for the current ring
            for(int seg = 0; seg <= nSegments; seg++) {
            float x0 = r0 * Mogre.Math.Sin(seg * fDeltaSegAngle);
                float z0 = r0 * Mogre.Math.Cos(seg * fDeltaSegAngle);

                // Add one vertex to the strip which makes up the sphere
                *pVertex++ = x0;
                *pVertex++ = y0;
                *pVertex++ = z0;

                Vector3 vNormal = (new Vector3(x0, y0, z0)).NormalisedCopy;
                *pVertex++ = vNormal.x;
                *pVertex++ = vNormal.y;
                *pVertex++ = vNormal.z;

                *pVertex++ = (float) seg / (float) nSegments;
                *pVertex++ = (float) ring / (float) nRings;

                if (ring != nRings) {
                    // each vertex (except the last) has six indices pointing to it
                    *pIndices++ = (ushort)(wVerticeIndex + nSegments + 1);
                    *pIndices++ = wVerticeIndex;               
                    *pIndices++ = (ushort)(wVerticeIndex + nSegments);
                *pIndices++ = (ushort)(wVerticeIndex + nSegments + 1);
                *pIndices++ = (ushort)(wVerticeIndex + 1);
                    *pIndices++ = wVerticeIndex;
                    wVerticeIndex ++;
                }
            }; // end for seg
        } // end for ring

        // Unlock
        vBuf.Unlock();
        iBuf.Unlock();
        
        // Generate face list
        pSphereVertex.useSharedVertices = true;

        // the original code was missing this line:
        pSphere._setBounds( new AxisAlignedBox( new Vector3(-r, -r, -r), new Vector3(r, r, r) ), false );
        pSphere._setBoundingSphereRadius(r);

    // this line makes clear the mesh is loaded (avoids memory leaks)
    pSphere.Load();
}


The unnamed code is not verifiable by CRL and to compile it you must specify /unsafe compiler option. If you use Microsoft Visual Studio you should set to true 'Allow unsafe code block' option in project property window.

The parameters are

  • strName - The Mesh's name. You'll use this to access it.
  • r - The sphere's radius.
  • nRings - Number of lines of longitude in the sphere. Defaults to 16.
  • nSegments - Number of lines of latitude in the sphere. Also defaults to 16.




Here's an example of how you would use this function and attach the new mesh to a SceneNode:

CreateSphere("MySphere", 10, 64, 64);
    Entity sphereEntity = Main.Instance.SceneManager.CreateEntity("SphereEntity", "MySphere");

    SceneNode sphereNode = sceneManager.RootSceneNode.CreateChildSceneNode();
    sphereEntity.SetMaterialName("material_name_goes_here");
    sphereNode.AttachObject(sphereEntity);


Don't forget to replace "material_name_goes_here" with the name of your material.