Jump to content
  • Advertisement
Sign in to follow this  
avion85

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.

If you intended to correct an error in the post then please contact us.

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 < D3DX_PI ;theta = theta + D3DX_PI/meridians ){	//0-PI	
   for(float phi=0;phi < 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 this post


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

Share this post


Link to post
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 this post


Link to post
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 this post


Link to post
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:)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!