   3D Sphere drawing algorithm
  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]
  68 views and no replies?:(Ill have a go at it, ill post some solutions when i get there...   ;  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).   ;  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;};  OK, its done!Here we go:class Sphere : public Entity{public:IDirect3DVertexBuffer9* SphereVertexBuffer;IDirect3DIndexBuffer9*  SphereIndexBuffer;int parallels;int meridians;float theta;// od 0 do pifloat phi;//od 0 to 2piint 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 piphi=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 kutfor(int j=0;j<2*parallels+1;j++){//ili phi, ve&#263;i kut od 0-2piif(j==0 || j == parallels ){phi=phi+(D3DX_PI*2 / parallels)/2;//uvjeti za kapicej++;}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 ilitiindex++;v[index]=VertexPos(0,0,-1);//127SphereVertexBuffer->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, prednjak[++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 putak[++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 trokutk[++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 trokutk[++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, suprotnik[++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:)