Archived

This topic is now archived and is closed to further replies.

Texturing a sphere

This topic is 5002 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''ve created a sphere using the method below and loaded a texture using the method below. How can I texturize the sphere correctly? D3DXCreateSphere(g_pd3dDevice,2.8f,20,20,&sphere,&ppAdjacency); D3DXCreateTextureFromFileExA(g_pd3dDevice,"ball.jpg",D3DX_DEFAULT,D3DX_DEFAULT,0,0,D3DFMT_A8R8G8B8,D3DPOOL_DEFAULT,D3DX_DEFAULT,D3DX_DEFAULT,0,NULL,NULL, &g_Texture); // draw the textured sphere? g_pd3dDevice->SetTexture(0,g_Texture); sphere->DrawSubset(0);

Share this post


Link to post
Share on other sites
This is how I did it :


  
HRESULT MakeSphere ( LPDIRECT3DDEVICE8 pd3dDevice , LPDIRECT3DVERTEXBUFFER8 * ppVB , int nRings , int nSegments, float m_fSize )
{
signed int ring;
signed int seg;

// get vertex count

DWORD dwVertices = 2 * nRings * ( nSegments + 1 ) ;

// Create the vertex buffer

if( FAILED ( pd3dDevice->CreateVertexBuffer(
dwVertices * sizeof ( STDVERTEX ),
D3DUSAGE_WRITEONLY, D3DFVF_STDVERTEX,
D3DPOOL_MANAGED, ppVB ) ) )
return E_FAIL;

// Lock the vertex buffer

STDVERTEX * pVertex ;
( * ppVB )->Lock( 0, 0, (BYTE**) & pVertex , 0 );

// Establish constants used in sphere generation

FLOAT fDeltaRingAngle = ( D3DX_PI / nRings );
FLOAT fDeltaSegAngle = ( 2.0f * D3DX_PI / nSegments );

// Generate the group of rings for the sphere

for(ring = 0; ring < nRings; ring++ )
{
FLOAT r0 = sinf ( (ring+0) * fDeltaRingAngle );
FLOAT r1 = sinf ( (ring+1) * fDeltaRingAngle );
FLOAT y0 = cosf ( (ring+0) * fDeltaRingAngle );
FLOAT y1 = cosf ( (ring+1) * fDeltaRingAngle );

// Generate the group of segments for the current ring

for(seg = 0; seg < ( nSegments + 1 ) ; seg++ )
{
FLOAT x0 = r0 * sinf( seg * fDeltaSegAngle );
FLOAT z0 = r0 * cosf( seg * fDeltaSegAngle );
FLOAT x1 = r1 * sinf( seg * fDeltaSegAngle );
FLOAT z1 = r1 * cosf( seg * fDeltaSegAngle );

// Add two vertices to the strip which makes up the sphere

pVertex->x = x0;
pVertex->y = y0;
pVertex->z = z0;

pVertex->nx = 0.0f;
pVertex->ny = 0.0f;
pVertex->nz = 0.0f;

pVertex->color = 0xffffffff ;
pVertex->tu = -((FLOAT)seg) / nSegments;
pVertex->tv = (ring+0) / (FLOAT) nRings;

pVertex->x *= m_fSize ;
pVertex->y *= m_fSize ;
pVertex->z *= m_fSize ;

pVertex ++;

pVertex->x = x1;
pVertex->y = y1;
pVertex->z = z1;

pVertex->nx = 0.0f;
pVertex->ny = 0.0f;
pVertex->nz = 0.0f;

pVertex->color = 0x00ffffff;

pVertex->tu = -((FLOAT)seg)/ nSegments;
pVertex->tv = (ring+1)/(FLOAT) nRings;

pVertex->x *= m_fSize ;
pVertex->y *= m_fSize ;
pVertex->z *= m_fSize ;

pVertex ++ ;
} ; // end for seg


} // end for ring


// Create Vertex Normals


// Finished creation, unlock vertex buffer


( * ppVB )->Unlock();

// Create Vertex Normals


// get vertex count

debug("SPHERE: Generating normals. # Vertices = ",dwVertices);

// Lock the vertex buffer

( * ppVB )->Lock( 0, 0, (BYTE**) & pVertex , 0 );

// Generate the group of rings for the sphere

for(ring = 0; ring < nRings; ring++ )
{
// Generate the group of segments for the current ring

for(seg = 0; seg < ( nSegments + 1 ) ; seg++ )
{
pVertex->nx = pVertex->x;
pVertex->ny = pVertex->y;
pVertex->nz = pVertex->z;

pVertex ++;

pVertex->nx = pVertex->x;
pVertex->ny = pVertex->y;
pVertex->nz = pVertex->z;

pVertex ++ ;
} ; // end for seg


} // end for ring


// Finished normal generation, unlock vertex buffer


( * ppVB )->Unlock();

return S_OK ;
}


The D3DXCreateSphere function doesn''t return any texture coordinates. If my memory serves me correctly, you can generate texture coordinates using normals, but it looks a bit strange at the poles of the sphere.

Hope this helps,

Stoo.

Share this post


Link to post
Share on other sites
Hi,

I have improved this sphere code so that less vertices are created and an Index Buffer is generated on the fly.

The mesh generated by CreateSphere is optimal. It generates the minimum number of vertices but it makes texturing tricky.So that''s why I use "my" sphere... This sphere can be drawn in a single DIP call.


Here is some code :


HRESULT CSphere::MakeSphere ( LPDIRECT3DDEVICE8 pd3dDevice ,
LPDIRECT3DVERTEXBUFFER8 * ppVB ,
LPDIRECT3DINDEXBUFFER8 * ppIB ,
int nRings , int nSegments )
{
// set vertex count and index count
DWORD dwVertices = ( nRings + 1 ) * ( nSegments + 1 ) ;
DWORD dwIndices = 2 * nRings * ( nSegments + 1 ) ;

// Create the vertex buffer
if( FAILED ( pd3dDevice->CreateVertexBuffer(
dwVertices * sizeof ( BUMPSPHEREVERTEX ),
D3DUSAGE_WRITEONLY, D3DFVF_BUMPSPHEREVERTEX,
D3DPOOL_DEFAULT, ppVB ) ) )
return E_FAIL;

// Create the index buffer
if( FAILED ( pd3dDevice->CreateIndexBuffer(
dwIndices * 2 ,
D3DUSAGE_WRITEONLY, D3DFMT_INDEX16,
D3DPOOL_DEFAULT, ppIB ) ) )
return E_FAIL;

// Lock the vertex buffer
BUMPSPHEREVERTEX * pVertex ;
( * ppVB )->Lock( 0, 0, (BYTE**) & pVertex , 0 );

// lock the index buffer
WORD * pIndices;
if( FAILED ( ( * ppIB )->Lock( 0, dwIndices, ( BYTE * * ) & pIndices, 0 ) ) )
return E_FAIL;

// Establish constants used in sphere generation
FLOAT fDeltaRingAngle = ( D3DX_PI / nRings );
FLOAT fDeltaSegAngle = ( 2.0f * D3DX_PI / nSegments );

WORD wVerticeIndex = 0 ;
// Generate the group of rings for the sphere
for( int ring = 0; ring < nRings + 1 ; ring++ )
{
FLOAT r0 = sinf ( ring * fDeltaRingAngle );
FLOAT y0 = cosf ( ring * fDeltaRingAngle );

// Generate the group of segments for the current ring
for( int seg = 0; seg < nSegments + 1 ; seg++ )
{
FLOAT x0 = r0 * sinf( seg * fDeltaSegAngle );
FLOAT z0 = r0 * cosf( seg * fDeltaSegAngle );

// Add one vertices to the strip which makes up the sphere
pVertex->p = D3DXVECTOR3(x0,y0,z0); // normalized
pVertex->n = pVertex->p ;
pVertex->color = 0xffffffff ;
pVertex->tu = (FLOAT) seg / (FLOAT) nSegments;
pVertex->tv = (FLOAT) ring / (FLOAT) nRings;

pVertex ++;

// add two indices except for last ring
if ( ring != nRings )
{
* pIndices = wVerticeIndex ;
pIndices ++ ;
* pIndices = wVerticeIndex + ( WORD ) ( nSegments + 1 ) ;
pIndices ++ ;
wVerticeIndex ++ ;
} ;

} ; // end for seg

} // end for ring

( * ppIB )->Unlock();

( * ppVB )->Unlock();

return S_OK ;
}



Laurent - http://www.lafaqmfc.com/
My little game: http://www.lafaqmfc.com/home/play_starshooter.htm

Share this post


Link to post
Share on other sites

HRESULT CSphere::MakeSphere ( LPDIRECT3DDEVICE8 pd3dDevice ,
LPDIRECT3DVERTEXBUFFER8 * ppVB ,
LPDIRECT3DINDEXBUFFER8 * ppIB ,
int nRings , int nSegments )
{
// set vertex count and index count

DWORD dwVertices = ( nRings + 1 ) * ( nSegments + 1 ) ;
DWORD dwIndices = 2 * nRings * ( nSegments + 1 ) ;

// Create the vertex buffer

if( FAILED ( pd3dDevice->CreateVertexBuffer(
dwVertices * sizeof ( BUMPSPHEREVERTEX ),
D3DUSAGE_WRITEONLY, D3DFVF_BUMPSPHEREVERTEX,
D3DPOOL_DEFAULT, ppVB ) ) )
return E_FAIL;

// Create the index buffer

if( FAILED ( pd3dDevice->CreateIndexBuffer(
dwIndices * 2 ,
D3DUSAGE_WRITEONLY, D3DFMT_INDEX16,
D3DPOOL_DEFAULT, ppIB ) ) )
return E_FAIL;

// Lock the vertex buffer

BUMPSPHEREVERTEX * pVertex ;
( * ppVB )->Lock( 0, 0, (BYTE**) & pVertex , 0 );

// lock the index buffer

WORD * pIndices;
if( FAILED ( ( * ppIB )->Lock( 0, dwIndices, ( BYTE * * ) & pIndices, 0 ) ) )
return E_FAIL;

// Establish constants used in sphere generation

FLOAT fDeltaRingAngle = ( D3DX_PI / nRings );
FLOAT fDeltaSegAngle = ( 2.0f * D3DX_PI / nSegments );

WORD wVerticeIndex = 0 ;
// Generate the group of rings for the sphere

for( int ring = 0; ring < nRings + 1 ; ring++ )
{
FLOAT r0 = sinf ( ring * fDeltaRingAngle );
FLOAT y0 = cosf ( ring * fDeltaRingAngle );

// Generate the group of segments for the current ring

for( int seg = 0; seg < nSegments + 1 ; seg++ )
{
FLOAT x0 = r0 * sinf( seg * fDeltaSegAngle );
FLOAT z0 = r0 * cosf( seg * fDeltaSegAngle );

// Add one vertices to the strip which makes up the sphere

pVertex->p = D3DXVECTOR3(x0,y0,z0); // normalized

pVertex->n = pVertex->p ;
pVertex->color = 0xffffffff ;
pVertex->tu = (FLOAT) seg / (FLOAT) nSegments;
pVertex->tv = (FLOAT) ring / (FLOAT) nRings;

pVertex ++;

// add two indices except for last ring

if ( ring != nRings )
{
* pIndices = wVerticeIndex ;
pIndices ++ ;
* pIndices = wVerticeIndex + ( WORD ) ( nSegments + 1 ) ;
pIndices ++ ;
wVerticeIndex ++ ;
} ;

} ; // end for seg


} // end for ring


( * ppIB )->Unlock();

( * ppVB )->Unlock();

return S_OK ;
}

looks better as source

[edited by - xegoth on April 3, 2004 1:22:36 AM]

Share this post


Link to post
Share on other sites