0
votes

I'm trying to draw a sphere which did work with the following code using C++ and DirectX:

struct Vertex
{
D3DXVECTOR3 position; //float x, y, z;
DWORD color; 
};


void myApp::createAndFillVertexBuffer(){
int radius = 1;
float slices = 50;
float stacks = 50;
float sliceStep = 2*D3DX_PI / slices;
float stackStep =  D3DX_PI / stacks;
int vertexCount = slices * (stacks - 1) + 2;
primitiveCount = slices * (stacks - 1) * 2;

m_D3DDev->CreateVertexBuffer(
sizeof(Vertex)*vertexCount,
D3DUSAGE_WRITEONLY, 
D3DFVF_M_VERTEX,                
D3DPOOL_DEFAULT, 
&m_VB,            
NULL);

Vertex *m_MVB;
HRESULT hRes = m_VB->Lock(0,0,(void**)&m_MVB,0);
if (hRes == D3D_OK)
{ 
   int currentVertex = 0;
   m_MVB[currentVertex++].position = D3DXVECTOR3( 0.0f, -radius, 0.0f );
   float stackAngle = D3DX_PI - stackStep;

    for (int i = 0; i < stacks - 1; i++)
    {
            float sliceAngle = 0;
            for (int j = 0; j < slices; j++)
            {

                float x = (float)(radius * sinf(stackAngle) * cosf(sliceAngle));
                float y = (float)(radius * cosf(stackAngle));
                float z = (float)(radius * sinf(stackAngle) * sinf(sliceAngle));
                m_MVB[currentVertex].position = D3DXVECTOR3(x,y,z);
                m_MVB[currentVertex].color = D3DCOLOR_XRGB(255,200,100);
                currentVertex++;
                sliceAngle += sliceStep;
        }
        stackAngle -= stackStep;
    }
    m_MVB[currentVertex++].position = D3DXVECTOR3( 0.0f, radius, 0.0f );
    m_VB->Unlock();
}
}

I create a sphere using vertex, and I should do it only using vertex, not D3DXCreateSphere() method. I got the strange results shown below. What am I doing wrong?

Current 1Current 2

Here's the result I want:

Wanted

UPDATE:

I tried a few more samples, but it working wrong. I tried to add indexBuffer to my algorithm. Here result algorithm, but it working wrong too:

int number_of_vertices, number_of_faces;
int slices= 20;
int stacks = 20;
float phi_step, phi_start;
float theta_step, theta, sin_theta, cos_theta;
int vertex, face;
int slice, stack;
number_of_vertices = 2 + slices * (stacks-1);
number_of_faces = 2 * slices + (stacks - 2) * (2 * slices);

primitiveCount = number_of_faces;

m_D3DDev->CreateVertexBuffer(
    sizeof(Vertex)*number_of_vertices,
    D3DUSAGE_WRITEONLY, 
    D3DFVF_M_VERTEX,                
    D3DPOOL_DEFAULT, 
    &m_VB,            
    NULL);

m_D3DDev->CreateIndexBuffer(sizeof(int) * number_of_faces*3, 
    D3DUSAGE_WRITEONLY, 
    D3DFMT_INDEX32, 
    D3DPOOL_DEFAULT, 
    &pIbuf, 
    NULL);

Vertex *vertices;
HRESULT hRes = m_VB->Lock(0,0,(void**)&vertices,0);


 WORD *faces;
 HRESULT hRes2 =  pIbuf->Lock(0, 0, (void**)&faces, 0);

 if (FAILED(hRes2)) {
      return;
 }

 phi_step = -2 * D3DX_PI / slices;
 phi_start = D3DX_PI / 2;

 theta_step = D3DX_PI / stacks;
 theta = theta_step;

 vertex = 0;
 face = 0;
 stack = 0;

 vertices[vertex].position.x = 0.0f;
 vertices[vertex].position.y = 0.0f;
 vertices[vertex].position.z = radius;
 vertices[vertex].color = D3DCOLOR_XRGB(255,200,100);
 vertex++;

 for (stack = 0; stack < stacks - 1; stack++) {
      sin_theta = sinf(theta);
      cos_theta = cosf(theta);

      for (slice = 0; slice < slices; slice++) {
           vertices[vertex].normal.x = sin_theta * cosf(phi_start);
           vertices[vertex].normal.y = sin_theta * sinf(phi_start);
           vertices[vertex].normal.z = cos_theta;
           vertices[vertex].position.x = radius * sin_theta * cosf(phi_start);
           vertices[vertex].position.y = radius * sin_theta * sinf(phi_start);
           vertices[vertex].position.z = radius * cos_theta;
           vertices[vertex].color = D3DCOLOR_XRGB(255,200,100);
           vertex++;

           phi_start += phi_step;

           if (slice > 0){
                if (stack == 0){
                     faces[face++] = 0;
                     faces[face++] = slice + 1;
                     faces[face++] = slice;
                } else {
                     faces[face++] = sphere_vertex(slices, slice-1, stack-1);
                     faces[face++] = sphere_vertex(slices, slice, stack-1);
                     faces[face++] = sphere_vertex(slices, slice-1, stack);

                     faces[face++] = sphere_vertex(slices, slice, stack-1);
                     faces[face++] = sphere_vertex(slices, slice, stack);
                     faces[face++] = sphere_vertex(slices, slice-1, stack);
                }
            }
        }

           theta += theta_step;

           if (stack == 0) {
                faces[face++] = 0;
                faces[face++] = 1;
                faces[face++] = slice;
         }
         else {
           faces[face++] = sphere_vertex(slices, slice-1, stack-1);
           faces[face++] = sphere_vertex(slices, 0, stack-1);
           faces[face++] = sphere_vertex(slices, slice-1, stack);

           faces[face++] = sphere_vertex(slices, 0, stack-1);
           faces[face++] = sphere_vertex(slices, 0, stack);
           faces[face++] = sphere_vertex(slices, slice-1, stack);
        }
 }

  vertices[vertex].position.x = 0.0f;
  vertices[vertex].position.y = 0.0f;
  vertices[vertex].position.z = -radius;
  vertices[vertex].color = D3DCOLOR_XRGB(255,200,100);
  vertices[vertex].normal.x = 0.0f;
  vertices[vertex].normal.y = 0.0f;
  vertices[vertex].normal.z = -1.0f;

  for (slice = 1; slice < slices; slice++){
      faces[face++] = sphere_vertex(slices, slice-1, stack-1);
      faces[face++] = sphere_vertex(slices, slice, stack-1);
      faces[face++] = vertex;
  }

  faces[face++] = sphere_vertex(slices, slice-1, stack-1);
  faces[face++] = sphere_vertex(slices, 0, stack-1);
  faces[face++] = vertex;
  m_VB->Unlock();   
  pIbuf->Unlock(); 

Function spehereVetrex:

static WORD sphere_vertex(UINT slices, int slice, int stack)
{
      return stack*slices+slice+1;
}

Then draw primitives:

m_D3DDev->SetStreamSource(0,m_VB,0,sizeof(Vertex));
m_D3DDev->SetIndices(pIbuf);
m_D3DDev->DrawPrimitive(D3DPT_TRIANGLESTRIP,0,primitiveCount);

Vetrex:

#define D3DFVF_M_VERTEX (D3DFVF_XYZ |D3DFVF_NORMAL| D3DFVF_DIFFUSE)

Vetrex struct:

 struct Vertex
{
 D3DXVECTOR3 position; //float x, y, z;
 D3DXVECTOR3 normal;
 DWORD color; 
};
 IDirect3DDevice9 *m_D3DDev;
 IDirect3DVertexBuffer9 *m_VB; // Vertex Buffer
 IDirect3DIndexBuffer9 *pIbuf;

//config D3DDevice
 m_D3DDev->SetRenderState( D3DRS_LIGHTING, false );
 m_D3DDev->SetRenderState( D3DRS_ZENABLE, TRUE );
 m_D3DDev->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
 m_D3DDev->SetFVF(D3DFVF_M_VERTEX);

Result:

current 1current 2

2
I need to create something like this 2ch.hk/sn/src/1366328787385.pngОлег Сужаев
Can you show your render calls (draw primitives)? It seems that the geometry (the triangles) are not correctly specified. Do you use an index buffer? For this type of shading, you also need to specify a surface normal in the vertex data. Maybe you should follow this tutorial: msdn.microsoft.com/en-us/library/windows/desktop/…cdoubleplusgood
You specified the vertex positions with this code. But you haven't specified how to connect these vertices. You can't use this vertex buffer alone to draw a whole sphere. You would need duplicate vertices. The clean way to go is to use an index buffer and a triangle list.Nico Schertler
@NicoSchertler thanks a lot. You are right. Now i'm using index buffer, but it working incorrectly. Please see my edit about index bufferОлег Сужаев

2 Answers

1
votes

From the screenshot you post, it seems you are using wireframe as fill mode, you should use solid mode, which is D3DFILL_SOLID. and you should give it a white color for your expected result.

Edit:

Try set cull mode to D3DCULL_NONE, this option make sure all triangles will be rendered.

0
votes

I solved this problem I should to use DrawIndexedPrimitive. Not DrawPrimitive.