Skip to main content
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

Copy to clipboard
#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

Copy to clipboard
#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!