# 3D Sphere drawing algorithm

This topic is 3488 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I think its about time we get a good thread on this. I've searched the internets for this for some time now, and I have'nt been able to find a good, definitive thread on the creation of the perfect 3d body, so here goes. I know there is a simple solution for this in the form of D3DX library, and its meshes that do the job for me completely, but thats not the point. What i am building is a program for my graduation thesis that does not rely on this kind of help in an effort to gain a greater understanding of 3d graphics. What i have come to understand is that the placement of the vertices is not a big deal, and a basic understanding of math for this is simple. Turns out, placing the vertices in the right order into the vertex buffer and the index buffer is a bit tricky, to say the least! This is the general code for the placement of vertices in 3d space:
int meridians;  //
int parallels;  //

for(float theta=0;theta &lt; D3DX_PI ;theta = theta + D3DX_PI/meridians ){	//0-PI
for(float phi=0;phi &lt; 2*D3DX_PI;phi= phi + 2*D3DX_PI/parallels){	//0-2PI

verts[index].x = cosf(theta)* sinf(phi);
verts[index].y = sinf(theta)* sinf(phi);
verts[index].z = cosf(phi);

}
}


(and yes i know i use d3dx for PI, its not a biggie:) So, some explanations for the index calculations or some references(in case i cant use the net) would be much appreciated, also the entire code would be awesome! thanks. [Edited by - avion85 on May 20, 2009 1:13:45 PM]

##### Share on other sites
68 views and no replies?:(
Ill have a go at it, ill post some solutions when i get there...

##### Share on other sites
So what are you looking for exactly? The code to generate the triangle indices?

If so, it's fairly trivial - it basically just comes down to bookkeeping. There's more than one way to arrange the data, but a typical approach would be to store the 'rings' of vertices in sequence from top to bottom or bottom to top (the poles have to be handled as special cases), and then triangulate accordingly.

If you're running into specific problems generating the indices, perhaps you could describe them and/or post some code. Also, just FYI, there are a few other ways to generate the mesh geometry for a sphere other than the spherical coordinate approach that you're using (which generates acceptable results in most cases, but creates a less uniform distribution of triangles than other methods).

##### Share on other sites
Just to add that if you're going to want to deform those verts, for example into a planet, a subdivided icosahedron might be more suitable and is pretty easy to get going. Nice point distribution and lots of tutes around on the net.

For a "perfect 3D body", you could do worse than raytrace the thing.

In that case, every 3D object is described by a ray-object intersection test, the sphere's being a trivial case:

bool Sphere::TestIntersection(Ray *ray){	Vector test(position - ray->origin);	double v = test.DotProduct (ray->direction);	double hitDistance = (radius*radius) + v*v - test.x*test.x - test.y*test.y - test.z*test.z;	if (hitDistance < 0) return false; // Early exit test    	hitDistance = v - sqrt(myHitDistance);																			if (myHitDistance < 0) return false;	return true;}

##### Share on other sites
OK, its done!
Here we go:

class Sphere : public Entity{public:	IDirect3DVertexBuffer9* SphereVertexBuffer;	IDirect3DIndexBuffer9*  SphereIndexBuffer;	int parallels;	int meridians;	float theta;	// od 0 do pi	float phi;		//od 0 to 2pi	int num_vertices;	int num_triangles;	void get_ime(){OutputDebugString("banana");};	Sphere(int *idd, std::string iime, int pparallels, int mmeridians, std::list<Entity*> *EEntity_list) : Entity(iime, *idd), parallels(pparallels), meridians(mmeridians){				float x,y,z;		theta=0;	// od 0 do pi		phi=0;						int index=0;		num_vertices=2*(parallels-1)*(meridians)+2;		HR(gd3dDevice->CreateVertexBuffer(num_vertices* sizeof(VertexPos), D3DUSAGE_WRITEONLY,		0, D3DPOOL_MANAGED, &SphereVertexBuffer, 0));		VertexPos *v;		HR(SphereVertexBuffer->Lock( 0, 0, (void**)&v, 0 ))		for(int i=0;i<meridians;i++){	//	iliti theta,manji kut			for(int j=0;j<2*parallels+1;j++){	//	ili phi, ve&#263;i kut od 0-2pi				if(j==0 || j == parallels ){									phi=phi+(D3DX_PI*2 / parallels)/2;			//uvjeti za kapice					j++;				}				if(j==(parallels*2)) break;							x=cosf(theta)*sinf(phi);					if(fabs(x)<0.000001) x=0;										y=sinf(theta)*sinf(phi);					if(fabs(y)<0.000001) y=0;										z=cos(phi);					if(fabs(z)<0.000001) z=0;					v[index] = VertexPos(x,y,z);					index++;					phi=phi+(D3DX_PI*2 / parallels)/2;								}			phi=0;			theta=theta+(D3DX_PI/ meridians);			}				v[index]=VertexPos(0,0,1);	//126 ako je 9, 9, a je//kapice iliti		index++;		v[index]=VertexPos(0,0,-1);	//127			SphereVertexBuffer->Unlock();		//OutputDebugString(index);		HR(gd3dDevice->CreateIndexBuffer(12*meridians*(parallels-1) * sizeof(WORD), D3DUSAGE_WRITEONLY,		D3DFMT_INDEX16, D3DPOOL_MANAGED, &SphereIndexBuffer, 0));		WORD* k = 0;		int brojac=-1;		HR(SphereIndexBuffer->Lock(0, 0, (void**)&k, 0));		for(int i=1;i<meridians+1;i++){					k[++brojac]=num_vertices-2;			(i==meridians) ? (k[++brojac]=2*(parallels-1)-1):(k[++brojac]=i*2*(parallels-1));				//kapica gore, prednja			k[++brojac]=i*2*(parallels-1)-2*(parallels-1);								k[++brojac]=num_vertices-2;			(i==meridians) ? (k[++brojac]=0):(k[++brojac]=i*2*(parallels-1)+2*(parallels-1)-1);			//kapica gore, preko puta			k[++brojac]=i*2*(parallels-1)-1;										for(int j=0;j<parallels-2;j++){								k[++brojac]=i*2*(parallels-1)-2*(parallels-1)+j;				(i==meridians) ? (k[++brojac]=2*(parallels-1)-j-1):(k[++brojac]=i*2*(parallels-1)+j);		//prednji, lijevo gore trokut				k[++brojac]=i*2*(parallels-1)-2*(parallels-1)+j+1;					(i==meridians)?(k[++brojac]=2*(parallels-1)-j-1):(k[++brojac]=i*2*(parallels-1)+j);	//prednji, suprotni				(i==meridians)?(k[++brojac]=2*(parallels-1)-j-2):(k[++brojac]=i*2*(parallels-1)+j+1);				k[++brojac]=i*2*(parallels-1)-2*(parallels-1)+j+1;							k[++brojac]=i*2*(parallels-1)-1-j;				(i==meridians)?(k[++brojac]=j):(k[++brojac]=i*2*(parallels-1)+2*(parallels-1)-1-j);			//stražnji, lijevo gore trokut				k[++brojac]=i*2*(parallels-1)-2-j;								(i==meridians)?(k[++brojac]=j):(k[++brojac]=i*2*(parallels-1)+2*(parallels-1)-1-j);						(i==meridians)?(k[++brojac]=j+1):(k[++brojac]=i*2*(parallels-1)+2*(parallels-1)-2-j);			//stražnji, suprotni				k[++brojac]=i*2*(parallels-1)-2-j;			}						k[++brojac]=num_vertices-1;			k[++brojac]=i*2*(parallels-1)-(parallels-1)-1;													//kapica dolje, prednja			(i==meridians) ? (k[++brojac]=(parallels-1)):(k[++brojac]=i*2*(parallels-1)+(parallels-1)-1);						k[++brojac]=num_vertices-1;			k[++brojac]=i*2*(parallels-1)-(parallels-1);													//kapica dolje, preko puta			(i==meridians) ? (k[++brojac]=(parallels-1)-1):(k[++brojac]=i*2*(parallels-1)+(parallels-1));		}		HR(SphereIndexBuffer->Unlock());			EEntity_list->push_back(this);		++(*idd); //*idd=*idd+1 <-isto kao i navedeno	}			void Render(){		HR(gd3dDevice->SetStreamSource(0, SphereVertexBuffer, 0, sizeof(VertexPos)));		HR(gd3dDevice->SetIndices(SphereIndexBuffer));		HR(gd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST,0,0,num_vertices,0,4*meridians*(parallels-1)));		//HR(gd3dDevice->DrawPrimitive(D3DPT_POINTLIST,0,144));		//HR(gd3dDevice->DrawIndexedPrimitive( D3DPT_POINTLIST,0,0,200,0,288));		}		};

There it is. It creates the points in space needed, and the indices. Have fun!
PS. Ignore the croatian:)

1. 1
2. 2
3. 3
Rutin
15
4. 4
khawk
13
5. 5
frob
12

• 9
• 9
• 11
• 11
• 23
• ### Forum Statistics

• Total Topics
633665
• Total Posts
3013247
×