SuperEllipsoid         Using super ellipsoid for creating simple 3d primitives

Code for creating a super ellipsoid. Using a super ellipsoid makes it easy to create simple 3d primitives such as cube, cylinder, sphere etc. To use this class use the approach lined out in http://www.ogre3d.org/wiki/index.php/ManualSphereMeshes to make a genuine Mesh, or subclass SimpleRenderable and make use of writeData method.

SuperEllipsoid.h

#ifndef _SUPERELLIPSOID_H_
 #define _SUPERELLIPSOID_H_
 
 #include <Ogre.h>
 
 class SuperEllipsoid
 {
 public:
     typedef enum Shape {CUBE, ROUNDED_CUBE, CYLINDER, SPHERE};
     
     SuperEllipsoid();
     SuperEllipsoid(int samples, float n1, float n2, float scale = 1.0);
     SuperEllipsoid(Shape shape, int samples = 60, float scale = 1.0);
     ~SuperEllipsoid();
 
     void createSuperEllipsoid(int samples, float n1, float n2, float scale = 1.0);
     void createSuperEllipsoid(Shape shape, int samples = 60, float scale = 1.0);
     int getNumVertices();
     float *getPointerToVertexData() const;
     Ogre::Vector3 getMaxPoint();
     Ogre::Vector3 getMinPoint();
 
 
 private:
     float *vertexData;
     size_t vertexDataSize;
     Ogre::Vector3 maxPoint, minPoint;
 
     std::vector<Ogre::Vector3> vertices;
     std::vector<Ogre::Vector3> normals;
     Ogre::Vector3 sampleSuperEllipsoid(float phi, float beta, float n1, float n2,
         float scaleX=1.0, float scaleY=1.0, float scaleZ=1.0);
     Ogre::Vector3 calculateNormal(float phi, float beta, float n1, float n2,
         float scaleX, float scaleY, float scaleZ);
     Ogre::Vector3 calculateNormal(Ogre::Vector3 p1, Ogre::Vector3 p2, Ogre::Vector3 p3);
     void copyVertexDataToArray();
 };
 
 #endif

SuperEllipsoid.cpp

#include "Superellipsoid.h"
 #include <cmath>
 
 #define SIGN(r) Ogre::Math::Sign(r)
 
 
 SuperEllipsoid::SuperEllipsoid()
 {
     vertexData = NULL;
     vertexDataSize = 0;
 }
 
 SuperEllipsoid::SuperEllipsoid(int samples, float n1, float n2, float scale)
 {
     vertexData = NULL;
     vertexDataSize = 0;
     createSuperEllipsoid(samples, n1, n2, scale);
 }
 
 SuperEllipsoid::SuperEllipsoid(Shape shape, int samples, float scale)
 {
     vertexData = NULL;
     vertexDataSize = 0;
     createSuperEllipsoid(shape, samples, scale);
 }
 
 SuperEllipsoid::~SuperEllipsoid()
 {
     delete [] vertexData;
 }
 
 void SuperEllipsoid::createSuperEllipsoid(int samples, float n1, float n2, float scale)
 {
     float phi = 0.0, phi2 = 0.0, beta = 0.0;
     Ogre::Vector3 p1, p2, p3;
     
     float dB = Ogre::Math::TWO_PI/samples;
     float dP = Ogre::Math::TWO_PI/samples;
 
     phi = -Ogre::Math::HALF_PI;
 
     for(int j=0; j<=samples/2; j++)
     {
         beta = -Ogre::Math::PI;
 
         for(int i=0; i<=samples; i++)
         {
             //Triangle #1
             vertices.push_back(sampleSuperEllipsoid(phi, beta, n1, n2, scale, scale, scale));
             normals.push_back(calculateNormal(phi, beta, n1, n2, scale, scale, scale));
             vertices.push_back(sampleSuperEllipsoid(phi+dP, beta, n1, n2, scale, scale, scale));
             normals.push_back(calculateNormal(phi+dP, beta, n1, n2, scale, scale, scale));
             vertices.push_back(sampleSuperEllipsoid(phi+dP, beta+dB, n1, n2, scale, scale, scale));
             normals.push_back(calculateNormal(phi+dP, beta+dB, n1, n2, scale, scale, scale));
 
             //Triangle #2
             vertices.push_back(sampleSuperEllipsoid(phi, beta, n1, n2, scale, scale, scale));
             normals.push_back(calculateNormal(phi, beta, n1, n2, scale, scale, scale));
             vertices.push_back(sampleSuperEllipsoid(phi+dP, beta+dB, n1, n2, scale, scale, scale));
             normals.push_back(calculateNormal(phi+dP, beta+dB, n1, n2, scale, scale, scale));
             vertices.push_back(sampleSuperEllipsoid(phi, beta+dB, n1, n2, scale, scale, scale));
             normals.push_back(calculateNormal(phi, beta+dB, n1, n2, scale, scale, scale));
 
             beta += dB;
         }
 
         phi += dP;
     }
 
     copyVertexDataToArray();
 } 
 
 void SuperEllipsoid::createSuperEllipsoid(Shape shape, int samples, float scale)
 {
     float n1, n2;
 
     switch(shape)
     {
     case CUBE:
         n1 = n2 = 0.0;
         break;
     case ROUNDED_CUBE:
         n1 = n2 = 0.2;
         break;
     case CYLINDER:
         n1 = 0.2;
         n2 = 1.0;
         break;
     case SPHERE:
         n1 = n2 = 1.0;
         break;
     }
 
     createSuperEllipsoid(samples, n1, n2, scale);
 } 
 
 int SuperEllipsoid::getNumVertices()
 {
     return (int)vertices.size();
 }
 
 float *SuperEllipsoid::getPointerToVertexData() const
 {
     return vertexData;
 }
 
 Ogre::Vector3 SuperEllipsoid::getMaxPoint()
 {
     return maxPoint;
 }
 
 Ogre::Vector3 SuperEllipsoid::getMinPoint()
 {
     return minPoint;
 }
 
 Ogre::Vector3 SuperEllipsoid::sampleSuperEllipsoid(float phi, float beta, float n1, float n2,
     float scaleX, float scaleY, float scaleZ)
 {
     Ogre::Vector3 vertex;
 
     float cosPhi = cos(phi); float cosBeta = cos(beta);
     float sinPhi = sin(phi); float sinBeta = sin(beta);
     
 
     vertex.x = scaleX * SIGN(cosPhi) * pow(fabs(cosPhi), n1) * SIGN(cosBeta) * pow(fabs(cosBeta), n2);
     vertex.z = scaleY * SIGN(cosPhi) * pow(fabs(cosPhi), n1) * SIGN(sinBeta) * pow(fabs(sinBeta), n2);
     vertex.y = scaleZ * SIGN(sinPhi) * pow(fabs(sinPhi), n1);
 
     return vertex;
 } 
 
 Ogre::Vector3 SuperEllipsoid::calculateNormal(float phi, float beta, float n1, float n2,
     float scaleX, float scaleY, float scaleZ)
 { 
     Ogre::Vector3 normal;
 
     float cosPhi = cos(phi); float cosBeta = cos(beta);
     float sinPhi = sin(phi); float sinBeta = sin(beta);
 
     normal.x = SIGN(cosPhi) * pow(fabs(cosPhi), 2-n1) * SIGN(cosBeta) * pow(fabs(cosBeta), 2-n2) / scaleX;
     normal.z = SIGN(cosPhi) * pow(fabs(cosPhi), 2-n1) * SIGN(sinBeta) * pow(fabs(sinBeta), 2-n2) / scaleY;
     normal.y = SIGN(sinPhi) * pow(fabs(sinPhi), 2-n1) / scaleZ;
 
     normal.normalise();
 
     return normal;
 }
 
 void SuperEllipsoid::copyVertexDataToArray()
 {
     size_t size = vertices.size() * 2 * 3; // vertices + normals
 
     if(vertexData == NULL)
         vertexData = new float[size];
     else if(vertexDataSize != size)
     {
         delete [] vertexData;
         vertexData = new float[size];
     }
 
     vertexDataSize = size;
 
     size_t numVertices = vertices.size();
 
     for(int i=0; i<numVertices; i++)
     {
         vertexData[i*6]   = vertices[i].x;
         vertexData[i*6+1] = vertices[i].y;
         vertexData[i*6+2] = vertices[i].z;
 
         vertexData[i*6+3] = normals[i].x;
         vertexData[i*6+4] = normals[i].y;
         vertexData[i*6+5] = normals[i].z;
 
         if(vertices[i].x < minPoint.x)
             minPoint.x = vertices[i].x;
         if(vertices[i].y < minPoint.y)
             minPoint.y = vertices[i].y;
         if(vertices[i].z < minPoint.z)
             minPoint.z = vertices[i].z;
 
         if(vertices[i].x > maxPoint.x)
             maxPoint.x = vertices[i].x;
         if(vertices[i].y > maxPoint.y)
             maxPoint.y = vertices[i].y;
         if(vertices[i].z > maxPoint.z)
             maxPoint.z = vertices[i].z;
     }        
 }

This code hasnt been fully tested so errors may occur. If you see some errors or enhancements that can be done please let me know!