Programatically create sphere

Started by
17 comments, last by KRIGSSVIN 14 years, 11 months ago
Does anyone have an algorithm for creating the vertices for a sphere with a given a radius and another variable controlling how many triangles it is made of? How about texture coordinates to go along with those? My Google search is fairing well on this one. I can go in circles with sin and cos, but I'm not really sure how to actually make triangles with them, or how to get texture coords since I've never really understood spherical texture mapping.
Advertisement
Moving to Graphics Programming and Theory.

Have you tried Google? There seems to be a lot of reasonable results there - in particular, this and this (OpenGL, but the theory is the same as D3D).
My code to generate sphere, everything is obvious nevertheless there are some my structs.

static void R_CreateSphere(lightShape_t *shape, float radius, int slices, int stacks) {	float		sinI[MAX_SHAPE_SEGMENTS], cosI[MAX_SHAPE_SEGMENTS];	float		sinJ[MAX_SHAPE_SEGMENTS], cosJ[MAX_SHAPE_SEGMENTS];	vec3_t		normal;	shadowVert_t	*vertex;	index_t		*index;	index_t		rowA, rowB;	int			i, j;	// validate parameters	radius = max(radius, 0.f);	slices = Q_clamp(slices, 2, MAX_SHAPE_SEGMENTS);	stacks = Q_clamp(stacks, 2, MAX_SHAPE_SEGMENTS);	// setup the shape	shape->numIndices = 6 * (stacks - 1) * slices;	shape->indices = R_StaticAlloc(shape->numIndices * sizeof(index_t));	shape->numVertices = (stacks - 1) * slices + 2;	shape->vertexBuffer = R_VB_Alloc(VBT_STATIC, shape->numVertices * sizeof(shadowVert_t));	// create sin/cos cache	for (i = 0; i < slices; i++)		Q_sincos(2.f * Q_PI * (float)i / (float)slices, &sinI, &cosI);	for (j = 0; j < stacks; j++)		Q_sincos(Q_PI * (float)j / (float)stacks, &sinJ[j], &cosJ[j]);	// generate vertices	vertex = R_VB_Map(shape->vertexBuffer, VBA_WRITE_ONLY);	// positive Z pole	vertex->xyz[0] = 0.f;	vertex->xyz[1] = 0.f;	vertex->xyz[2] = radius;	vertex++;	// stacks	for (j = 1; j < stacks; j++) {	        for (i = 0; i < slices; i++) {			normal[0] = sinI * sinJ[j];			normal[1] = cosI * sinJ[j];			normal[2] = cosJ[j];			vertex->xyz[0] = normal[0] * radius;			vertex->xyz[1] = normal[1] * radius;			vertex->xyz[2] = normal[2] * radius;			vertex++;		}	}	// negative Z pole	vertex->xyz[0] = 0.f;	vertex->xyz[1] = 0.f;	vertex->xyz[2] = -radius;	vertex++;	R_VB_Unmap(shape->vertexBuffer);	GL_BindVB(NULL);	// generate indices	index = shape->indices;	// positive Z pole	rowA = 0;	rowB = 1;	for(i = 0; i < slices - 1; i++) {		index[0] = rowA;		index[1] = rowB + i + 1;		index[2] = rowB + i;		index += 3;	}	index[0] = rowA;	index[1] = rowB;	index[2] = rowB + i;	index += 3;	// interior stacks	for (j = 1; j < stacks - 1; j++) {		rowA = 1 + (j - 1) * slices;		rowB = rowA + slices;		for (i = 0; i < slices - 1; i++) {			index[0] = rowA + i;			index[1] = rowA + i + 1;			index[2] = rowB + i;			index += 3;			index[0] = rowA + i + 1;			index[1] = rowB + i + 1;			index[2] = rowB + i;			index += 3;        	}		index[0] = rowA + i;		index[1] = rowA;		index[2] = rowB + i;		index += 3;		index[0] = rowA;		index[1] = rowB;		index[2] = rowB + i;		index += 3;	}	// negative Z pole	rowA = 1 + (stacks - 2) * slices;	rowB = rowA + slices;	for (i = 0; i < slices - 1; i++) {		index[0] = rowA + i;		index[1] = rowA + i + 1;		index[2] = rowB;		index += 3;	}	index[0] = rowA + i;	index[1] = rowA;	index[2] = rowB;}

I created four video tutorials that show how you can create a sphere programatically and also how to apply a texture over it. You can get the video's here: http://www.marek-knows.com/downloadSection.php?Topic=Physics&pg=1#Physics4
it's probably not what you're after,
but i have a simple demo showing non-realtime generation of a sphere with exactly N vertices here: http://elenzil.com/progs/separate
(essentially using a simple electrostatic repulsion method to relax an initial random distribution)
and a demo of efficiently uniformly distributing random points on a sphere here: http://elenzil.com/progs/randompoints

both include DirectX 9 source.

(sorry, new to the forum, not sure how to markup links yet)
Quote:Original post by mmakrzem
I created four video tutorials that show how you can create a sphere programatically and also how to apply a texture over it. You can get the video's here: http://www.marek-knows.com/downloadSection.php?Topic=Physics&pg=1#Physics4


Site will not send an email to allow me to register in order to watch the video.

EDIT:
I finally got an email and logged in. Your website is so set up to make money.
The user is forced to watch videos in sequence and is only given a few free downloads. Before I am even able to get to the sphere video, which is the only one that interests me, I am told I need to purchase download slots.

Everyone has to make a buck, but I am not going to contribute to something that leaves such a sour taste in my mouth.

Maybe I'll try again in 4 days when I am allowed another free download from your site.




[Edited by - brekehan on May 28, 2009 2:56:38 AM]
Quote:Original post by KRIGSSVIN
My code to generate sphere, everything is obvious nevertheless there are some my structs.


It isn't so obvious :(

I tired drawing on paper what is going on and I am failing to visualize it.
I tried stepping through the code and my first vertex ends up being (0, very close to 0, very close to 0)... like e-19 close.

I used a radius of 1, 4 stacks, 4 slices, in order to know what the trig valus should be.

I can't visualize the iteration of the vertices. Where is the first point supposed to be after you do a pole?




An easy algorithm with great results and without singularities at the poles is to create 6 planes, with normals to the left, right, top, bottom, front, back. You triangulate those planes, and then normalise all vertex positions, and finally multiply them by some radius. While still not a perfect mapping, it is also easy to texture that sphere with a cubemap.
Quote:Original post by phresnel
An easy algorithm with better results and without singularities at the poles is to create 6 planes, with normals to the left, right, top, bottom, front, back. You triangulate those planes, and then normalise all vertex positions, and finally multiply them by some radius. While still not a perfect mapping, it is also easy to texture that sphere with a cubemap.


That sounds like a good idea.

I can probably use that for some spheres, but I have a special case where I need to generate my sphere to have particular triangles for proper texture mapping.

I want to end up with a sphere as I would if I created it in 3ds max.


This is built of rectangles, except for the stack next to the poles.
I imagine I can just split those rectangles into triangles if I can get an algorithm to get this far.

The reason I like this is that it makes texture mapping so easy. I can visualize the way the texture fits as if I took a knife and cut down the sphere from pole to pole on one side. It then unwraps to look like this:



So I can predict what my texture is going to look like as if I took a sheet of paper and wrapped it around a drinking glass. Of course there is some distortion near the poles because it is spherical, but I can still visualize it.

I am in fact trying to generate spheres in my engine in order to replace spheres that were exported from max as models for things like background, star field, planets, and moons. Each of those has multiple layers that are also spheres, so loading all these models from files seems silly, when I know my engine could do it instead.

EDIT:
I can easily see that sin and cos can be taken around the unit circle in the xz plane and the same for the yz plane. It is just a matter of using that to make the actual vertices. It's been a long time since trig class. I'll eventually get it if I draw enough pictures :P


brekehan

This function gives you a sphere identical to 3DSMax one.
It consists of three parts: top cap, central part, and bottom cap.

Output is a triangle mesh, there are 3 indices per triangle.

Anyway, this is a sample from DXSDK adapted to my engine. They have normals there too.

This topic is closed to new replies.

Advertisement