Generate 3D Cone Primitive

Started by
4 comments, last by v71_2 16 years, 10 months ago
I want to programmatically generate 3d cones using only triangles, no quads. The cones do not have to come to a point - they can have both top and bottom caps. The generation function should take number of sides and height segments into consideration. Please someone point me towards a good resource, textboox, etc. that covers this particular algorithm? Pseudo code or c++ would be helpful. Examples of cones to generate:
game development is liek a state of mind man.. it's liek when you liek... think... and then you liek make it fun++

- Yes I'm drunk.
Advertisement
Both of these shapes can be created straightforwardly with a little trig and vector math. It's probably easiest to create them with a default position and orientation (e.g. centered at the origin and built around the z axis) and then transform them as desired. Alternatively, you can construct them manually 'in place' given a starting and ending point.

Let me know what exactly you need help with and I can give you some tips (or maybe just post an example - I have plenty of source code for this sort of thing lying around).
I would like to build it centered at the origin and built around an axis.

jyk I am familiar with code you have posted on gamedev where your cone function:

template <class T> void Mesh<T>::MakeCone(T r, T l, const Vector3<T>& axis, unsigned int lod)

I have not compiled or tested this code but it seems to create a cone out of triangles with a single bottom cap and no height segments. If we could modify this function to support top caps, where r2 > 0, and add "height segments" then that's exactly what I need. How to do this mathematically is beyond me at the moment.

I would appreciate some examples and source, but I would also like to learn how this works so titles of papers written on these algorithms or books that cover this topic would be greatly appreciated.
game development is liek a state of mind man.. it's liek when you liek... think... and then you liek make it fun++

- Yes I'm drunk.
I can't think of any particular papers or references off the top of my head, but basically what you want is a GLUT-style 'make cylinder' function, with added support for specifying the top and bottom radii separately.

I have code for creating a cylinder mesh, but it's set up a little differently (for example, as you noted, there is no subdivision along the length). Rather than try to adapt that code for you, it'd probably be easier to just go over the algorithm here in this post.

To build your cone/cylinder, you first need to be able to generate the vertices of a unit circle, something like:
for (int i = 0; i < numRadialSubdivisions; ++i) {    float angle = TWO_PI * ((float)i / (float)numRadialSubdivisions);    float s = sin(angle);    float c = cos(angle);    verts[index++].set(c, s, 0.f);}
For n vertical subdivisions, you'll want to generate n+1 of these circles, spaced appropriately along the z axis. Also, you'll want to scale the radius of each circle (the value by which to scale can be computed by interpolating between the values of the top and bottom radii, based on which 'step' you're at along the z axis).

Once you have the vertices in place, you can set the triangle indices. This is just bookkeeping, and involves nothing more than a little integer math.

Again, except for the differing radii this is essentially the algorithm used by GLUT to create a cylinder mesh, so if you can find some example code for that (Mesa?) you should be good to go.

Otherwise, just post back if you have any trouble implementing the algorithm I described above, and I'll try and help with the details.
Thanks Jesse

I had very little trouble getting this to work. I just have vertices at the moment but rendering triangles should be a walk in the park. I had a look at the free glut geometry source. It will make an excellent reference.

_Neil
game development is liek a state of mind man.. it's liek when you liek... think... and then you liek make it fun++

- Yes I'm drunk.
Taken from my engine:

bool CreateCylinder( CMesh *Mesh,
int Size,
float Height,
float Radius,
float Radius1,
int Mode )
{

if ( Radius < 0 ) Radius = -Radius;
if ( Radius1 < 0 ) Radius1 = -Radius1;
if ( Size < 0 ) Size = -Size;
if ( Height < 0 ) Height=-Height;
if ( Size < 4 || Size==0 ||
Radius == 0.0f || Radius1==0.0f ||
Height ==0 ) return false;

float minorStep ;
float x[3],y[3];
float a,du;
int i;

////////////////////////////////////////

Mesh->Reset();

///////////////////////////////////////
// allocate vertex list

if ( Mesh->ReserveVertexBuffer( Size )==false )
return false;
// allocating proper sized texcoords list
if ( Mesh->ReserveTexCoordBuffer( Size )==false )
return false;

//////////////////////////////////////////
// allocating surfaces

if ( Mesh->ReserveSurfaceBuffer( Size )==false )
return false;

/////////////////////////////////////////
// adding vertices

du=(1.0f/(float)Size);

minorStep = 2.0F * __PI *du;

a=0.0f;

for (i=0; i<Size; i++)
{
y[0] = Radius * FastCos(a);
x[0] = Radius * FastSin(a);

Mesh->AddVertex( x[0],-Height,y[0]);

y[1] = Radius1 * FastCos(a);
x[1] = Radius1 * FastSin(a);

Mesh->AddVertex( x[1], Height,y[1]);

a+=minorStep;
}


for ( i=0; i<Size*2-2; i+=2 )
{
Mesh->AddSurface( i+1,i,i+2 );
Mesh->AddSurface( i+3,i+1,i+2 );
}

Mesh->AddSurface( Size*2-1,Size*2-2,0 );
Mesh->AddSurface( 1,Size*2-1,0 );


//////////////////////////////////////////////////////////
// capping

switch ( Mode )
{

case _VT_CAPBOTH_ :

Mesh->AddVertex( 0,-Height,0);

for ( i=0; i<Size*2-2; i+=2 )
Mesh->AddSurface( Size*2,i+2,i );
Mesh->AddSurface( Size*2,0,Size*2-2 );

Mesh->AddVertex( 0,Height,0);

for ( i=0; i<Size*2-2; i+=2 )
Mesh->AddSurface( Size*2+1,i+1,i+2+1 );
Mesh->AddSurface( Size*2+1,Size*2-1,1 );

break;

case _VT_CAPTOP_ :

Mesh->AddVertex( 0,Height,0);

for ( i=0; i<Size*2-2; i+=2 )
Mesh->AddSurface( Size*2,i+2,i );
Mesh->AddSurface( Size*2,0,Size*2-2 );

break;

case _VT_CAPBOTTOM_ :

Mesh->AddVertex( 0,-Height,0);

for ( i=0; i<Size*2-2; i+=2 )
Mesh->AddSurface( Size*2,i+2,i );

Mesh->AddSurface( Size*2,0,Size*2-2 );

break;

}

//////////////////////////////////////////////

//////////////////////////////////////////////

Mesh->Finalize();

return true;
}

This topic is closed to new replies.

Advertisement