Directx 에서 지원하는 Sphere함수를 구현해보았습니다.
Slices는 나누어질 삼각형의 갯수 이며 Stack은 사진에서 Y축으로 나누어질 갯수 입니다.
Radius는 반지름의 값이며 Slices Stack Radius 의 값을 조정하시면 그 값에 맞게 Sphere가 그려집니다.
그리는 방식은 Vertices로 각 위치의 Point를 찍어주며 이것을 index buffer르 사용하여 사과의 껍질을 벗겨내는 형식으로
각포인트를 이어서 삼각형을 만들어 주시면 됩니다.
#include <mmsystem.h>
#include <d3dx9.h>
//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------
LPDIRECT3D9 g_pD3D = NULL;
LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;
LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL;
LPD3DXMESH g_pMesh = NULL;
LPDIRECT3DINDEXBUFFER9 g_pIndexVB = NULL;
struct CUSTOMVERTEX
{
FLOAT x, y, z;
DWORD color;
};
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)
struct INDEX
{
WORD _0, _1, _2;
};
int Slices = 6;
int Stack = 4;
int numvertex = (Slices+1)*2+((Stack-3)*Slices);
int numface = (Slices*2)+((Stack-2)*2)*Slices;
//-----------------------------------------------------------------------------
// Name: InitD3D()
//-----------------------------------------------------------------------------
HRESULT InitD3D( HWND hWnd )
{
if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
return E_FAIL;
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof( d3dpp ) );
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &g_pd3dDevice ) ) )
{
return E_FAIL;
}
g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
g_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME );
g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: InitGeometry()
//-----------------------------------------------------------------------------
HRESULT InitGeometry()
{
D3DXCreateSphere( g_pd3dDevice, 2.0f, 5, 4, &g_pMesh, NULL );
float Radius = 2.0f;
CUSTOMVERTEX *g_Vertices = new CUSTOMVERTEX[numvertex];
g_Vertices[0].x = 0.0f;
g_Vertices[0].y = Radius;
g_Vertices[0].z = 0.0f;
g_Vertices[0].color = 0xffffffff;
for( int i=0+1, k=1; i<Stack; ++i )
{
D3DXVECTOR3 tmp( 0.0f, Radius * cosf( ( D3DX_PI / Stack ) * i ), Radius * sinf( ( D3DX_PI / Stack ) * i ));
for( int j=0; j<Slices; ++j, ++k )
{
float temp = Radius - ( Radius - tmp.z );
g_Vertices[k].x = temp * cosf(D3DXToRadian( (360/Slices) * j ));
g_Vertices[k].y = tmp.y;
g_Vertices[k].z = temp * sinf(D3DXToRadian( (360/Slices) * j ));
g_Vertices[k].color = 0xffffffff;
}
}
g_Vertices[numvertex-1].x = 0.0f;
g_Vertices[numvertex-1].y = -Radius;
g_Vertices[numvertex-1].z = 0.0;
g_Vertices[numvertex-1].color = 0xffffffff;
if( FAILED( g_pd3dDevice->CreateVertexBuffer( numvertex * sizeof( CUSTOMVERTEX ),
0, D3DFVF_CUSTOMVERTEX,
D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )
{
return E_FAIL;
}
VOID* pVertices;
if( FAILED( g_pVB->Lock( 0, sizeof( g_Vertices ), ( void** )&pVertices, 0 ) ) )
return E_FAIL;
memcpy( pVertices, g_Vertices, sizeof( CUSTOMVERTEX ) * numvertex);
g_pVB->Unlock();
int j=0;
int z=0;
INDEX *index = new INDEX[numface];
for(z=0; z<Slices; ++z)
{
index[z]._0 = 0;
index[z]._1 = z+1;
index[z]._2 = z+2-j;
if( z == Slices - 2 )
{
j = Slices;
}
}
int t = z;
int tmp = 0;
int tmp2 = 0;
int a = 0;
for( int i=0; i<Stack - 2; ++i )
{
tmp = (Slices + 1) + ( i * Slices );
tmp2 = 2 + ( i * Slices );
for( int j=0; j<Slices; ++j )
{
if( j == (Slices - 1) )
{
a = Slices;
}
index[t]._0 = tmp2 + j - a;
index[t]._1 = tmp2 + j - 1;
index[t]._2 = tmp2 + j + Slices - a;
index[t+1]._0 = tmp + j + 1 - a;
index[t+1]._1 = tmp + j - ( Slices );
index[t+1]._2 = tmp + j;
t+=2;
}
a = 0;
}
int b;
b = t;
int q = 0;
for( int i=0; i<Slices; ++i )
{
index[b]._0 = tmp + i;
index[b]._1 = tmp + Slices;
index[b]._2 = tmp + i + 1 - q;
if( i == Slices - 2 )
{
q = Slices - i;
}
b++;
}
if( FAILED( g_pd3dDevice->CreateIndexBuffer( numface * sizeof(INDEX), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &g_pIndexVB, NULL ) ) )
{
return E_FAIL;
}
VOID* pIndices;
if( FAILED( g_pIndexVB->Lock( 0, sizeof(INDEX)*numface, (void**)&pIndices, 0 ) ) )
return E_FAIL;
memcpy( pIndices, index, sizeof(INDEX)*numface );
g_pIndexVB->Unlock();
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: Cleanup()
//-----------------------------------------------------------------------------
VOID Cleanup()
{
if( g_pIndexVB != NULL )
g_pIndexVB->Release();
if( g_pMesh != NULL )
g_pMesh->Release();
if( g_pVB != NULL )
g_pVB->Release();
if( g_pd3dDevice != NULL )
g_pd3dDevice->Release();
if( g_pD3D != NULL )
g_pD3D->Release();
}
//-----------------------------------------------------------------------------
// Name: SetupMatrices()
//-----------------------------------------------------------------------------
VOID SetupMatrices()
{
D3DXMATRIXA16 matWorld;
UINT iTime = timeGetTime() % 9000;
FLOAT fAngle = iTime * ( 2.0f * D3DX_PI ) / 9000.0f;
D3DXMatrixRotationY( &matWorld, fAngle );
g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
D3DXVECTOR3 vEyePt( 0.0f, 0.0f,-10.0f );
D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );
D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );
D3DXMATRIXA16 matView;
D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );
g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
D3DXMATRIXA16 matProj;
D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI / 4, 1.0f, 1.0f, 100.0f );
g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
}
//-----------------------------------------------------------------------------
// Name: Render()
//-----------------------------------------------------------------------------
VOID Render()
{
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0, 0, 0 ), 1.0f, 0 );
if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
{
SetupMatrices();
g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) );
g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
g_pd3dDevice->SetIndices( g_pIndexVB );
// g_pd3dDevice->DrawPrimitive( D3DPT_POINTLIST, 0, numvertex );
g_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, numvertex, 0, numface );
g_pd3dDevice->EndScene();
}
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}
//-----------------------------------------------------------------------------
// Name: MsgProc()
// Desc: The window's message handler
//-----------------------------------------------------------------------------
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_DESTROY:
Cleanup();
PostQuitMessage( 0 );
return 0;
}
return DefWindowProc( hWnd, msg, wParam, lParam );
}
//-----------------------------------------------------------------------------
// Name: WinMain()
//-----------------------------------------------------------------------------
INT WINAPI wWinMain( HINSTANCE hInst, HINSTANCE, LPWSTR, INT )
{
UNREFERENCED_PARAMETER( hInst );
WNDCLASSEX wc =
{
sizeof( WNDCLASSEX ), CS_CLASSDC, MsgProc, 0L, 0L,
GetModuleHandle( NULL ), NULL, NULL, NULL, NULL,
L"D3D Tutorial", NULL
};
RegisterClassEx( &wc );
HWND hWnd = CreateWindow( L"D3D Tutorial", L"D3D Tutorial 03: Matrices",
WS_OVERLAPPEDWINDOW, 100, 100, 800, 600,
NULL, NULL, wc.hInstance, NULL );
if( SUCCEEDED( InitD3D( hWnd ) ) )
{
if( SUCCEEDED( InitGeometry() ) )
{
ShowWindow( hWnd, SW_SHOWDEFAULT );
UpdateWindow( hWnd );
MSG msg;
ZeroMemory( &msg, sizeof( msg ) );
while( msg.message != WM_QUIT )
{
if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
else
Render();
}
}
}
UnregisterClass( L"D3D Tutorial", wc.hInstance );
return 0;
}
'그래픽스(Graphics) > DirectX9~12' 카테고리의 다른 글
점 그리기 -크기 변환 (0) | 2012.11.02 |
---|---|
점그리기 (0) | 2012.11.02 |
디바이스를 잃었을때의 복구 절차 (0) | 2012.11.02 |
그래픽카드 디바이스. D3D_Device (0) | 2012.11.02 |
Directx3D 에서 2D 점 그리기 (0) | 2012.11.02 |