Code:
#include "CSkySphere.h"
#include "d:\vc6gamelibs\3dlibs\engine\d3dUtility.h"
const DWORD SkySphereVertex::FVF=D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;
#define PI 3.14159
#define DEGTORAD(x) ((float)x*PI/180.0f)
void CSkySphere::Create(IDirect3DDevice9 *device,float radius,unsigned long faces)
{
//Radius of sphere
Radius=radius;
//Number of facets - or faces per 360 degrees on x and y
Facets=faces;
//Pointer to device - IDirect3DDevice9
Device=device;
//Angle increment for sphere to have correct number of faces
float angleinc=360.0f/faces;
//x and y angles
float alpha=0.0f;
float beta=-90.0f;
int vertexnum=0;
//Each row and column have 1 extra vertex
NumVertexes=(faces+1)*(faces+1);
//Compute number of faces and number of tri's or primitives
NumFaces=(faces*faces);
NumTris=NumFaces*2;
//New coordinates of vertex after spherical change
float newx,newy,newz=0.0f;
//Current u and v texture coordinates
float cur_u=0.0f;
float cur_v=0.0f;
//Texture increment for number of faces in a 1024x1024 bitmap
float textureinc=1024.0f/faces;
//Create the vertex buffer
Device->CreateVertexBuffer(NumVertexes*sizeof(SkySphereVertex),
D3DUSAGE_WRITEONLY,
SkySphereVertex::FVF,
D3DPOOL_MANAGED,
&VB,
0);
//Lock it for writing
SkySphereVertex *Vertexes;
VB->Lock(0,0,(void **)&Vertexes,0);
//Sphere generation code
do
{
do
{
//Equation of a sphere - spherical coordinates
newx=cos(DEGTORAD(alpha))*sin(DEGTORAD(beta))*Radius;
newy=sin(DEGTORAD(alpha))*sin(DEGTORAD(beta))*Radius;
newz=cos(DEGTORAD(beta))*Radius;
//Compute normalized u and v
float u=cur_u/1024.0f;
float v=cur_v/1024.0f;
//Save vertex in buffer
Vertexes[vertexnum]=SkySphereVertex(newx,newy,newz,u,v);
//Move to next vertex
vertexnum++;
//Increment texture u coord accordingly
cur_u+=textureinc;
//Increment y angle
beta+=angleinc;
} while (beta<=90.0f);
//To account for last vertex on row
vertexnum++;
//Reset y angle to top of sphere
beta=-90.0f;
//Increase X angle - longitude
alpha+=angleinc;
//Reset texture u coord
cur_u=0.0f;
//Increment current v texture coord accordingly
cur_v+=textureinc;
} while (alpha<=360.0f);
//Unlock vertex buffer
VB->Unlock();
//Lock index buffer and create it
WORD *indices=0;
//6 indexes per face - 1 textured quad=2 tris=6 indexes
WORD numindices=NumFaces*6;
Device->CreateIndexBuffer(NumFaces*sizeof(WORD),
D3DUSAGE_WRITEONLY,
D3DFMT_INDEX16,
D3DPOOL_MANAGED,
&IB,0);
IB->Lock(0,0,(void **)&indices,0);
int curvertex=0;
//Generate indexes for tris
for (int i=0;i<(numindices-6);i+=6)
{
//First tri
indices[i] = curvertex;
indices[i+1]= curvertex+1;
indices[i+2]= curvertex+faces;
//Second tri
indices[i+3]= curvertex+faces;
indices[i+4]= curvertex+1;
indices[i+5]= curvertex+faces+1;
curvertex++;
}
//Unlock buffer
IB->Unlock();
}
void CSkySphere::Render(D3DXVECTOR3 &PlayerPos)
{
//Translate sphere to always be centered around camera location
D3DXMATRIX trans;
D3DXMatrixTranslation(&trans,PlayerPos.x,PlayerPos.y,PlayerPos.z);
Device->SetTransform(D3DTS_WORLD,&trans);
//Set cull mode to none for testing - later will be D3DCULL_CW
//since camera is inside of the sphere thus reversing winding order
Device->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
//Set texture to our current backdrop texture
Device->SetTexture(0,Backdrop);
//Set material for sphere
D3DMATERIAL9 mtrl;
mtrl.Ambient=d3d::RED*.8f;
mtrl.Diffuse=d3d::WHITE*.8f;
mtrl.Specular=d3d::WHITE*.2f;
mtrl.Emissive=d3d::BLACK;
mtrl.Power=4.0f;
Device->SetMaterial(&mtrl);
//Set stream source, index buffer, and FVF
Device->SetStreamSource(0,VB,0,sizeof(SkySphereVertex));
Device->SetIndices(IB);
Device->SetFVF(SkySphereVertex::FVF);
//Draw the thing
Device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,
NumVertexes,0,NumTris);
//Set cull mode back to counter-clockwise winding order
Device->SetRenderState(D3DRS_CULLMODE,D3DCULL_CCW);
}