Notice
Recent Posts
Recent Comments
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- 자료구조
- Deque
- set
- 운영체제
- directx
- LineTracer
- 아두이노
- C언어
- Algorithm
- c++
- Arduino
- queue
- 컴퓨터 그래픽스
- 아두이노 컴파일러
- 통계학
- stl
- 수광 소자
- 시스템프로그래밍
- map
- priority_queue
- WinAPI
- Array
- Stack
- arduino compiler
- vector
- Visual Micro
- 아두이노 소스
- 라인트레이서
- html
- list
Archives
- Today
- Total
Kim's Programming
[다이렉트SDK 예제]DirectX Tutorial5 - Meshes 본문
이번 포스팅에서는 Meshes에 대해서 포스팅 하겠습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 | //----------------------------------------------------------------------------- // File: Meshes.cpp // // Desc: For advanced geometry, most apps will prefer to load pre-authored // Meshes from a file. Fortunately, when using Meshes, D3DX does most of // the work for this, parsing a geometry file and creating vertx buffers // (and index buffers) for us. This tutorial shows how to use a D3DXMESH // object, including loading it from a file and rendering it. One thing // D3DX does not handle for us is the materials and textures for a mesh, // so note that we have to handle those manually. // // Note: one advanced (but nice) feature that we don't show here is that // when cloning a mesh we can specify the FVF. So, regardless of how the // mesh was authored, we can add/remove normals, add more texture // coordinate sets (for multi-texturing), etc. // // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- #include <Windows.h> #include <mmsystem.h> #include <d3dx9.h> #pragma warning( disable : 4996 ) // disable deprecated warning #include <strsafe.h> #pragma warning( default : 4996 ) struct CUSTOMVERTEX { D3DXVECTOR3 position; // The 3D position for the vertex D3DXVECTOR3 normal; // The surface normal for the vertex }; //----------------------------------------------------------------------------- // Global variables //----------------------------------------------------------------------------- LPDIRECT3D9 g_pD3D = NULL; // Used to create the D3DDevice LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; // Our rendering device //////////////////////////////////////////////////////////////////////////// 이부분을 여러개 하면 모델이 여러개 나옴. LPD3DXMESH g_pMesh = NULL; // Our mesh object in sysmem D3DMATERIAL9* g_pMeshMaterials = NULL; // Materials for our mesh LPDIRECT3DTEXTURE9* g_pMeshTextures = NULL; // Textures for our mesh DWORD g_dwNumMaterials = 0L; // Number of mesh materials //동적 할당을 위해서 //////////////////////////////////////////////////////////////////////////// BOOL RIGHT = FALSE; BOOL LEFT = FALSE; BOOL UP = FALSE; BOOL DOWN = FALSE; BOOL SPACE = FALSE; FLOAT left_rotation = 0; FLOAT right_rotation = 0; //----------------------------------------------------------------------------- // Name: InitD3D() // Desc: Initializes Direct3D //----------------------------------------------------------------------------- HRESULT InitD3D( HWND hWnd ) { // Create the D3D object. if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) return E_FAIL; // Set up the structure used to create the D3DDevice. Since we are now // using more complex geometry, we will create a device with a zbuffer. D3DPRESENT_PARAMETERS d3dpp; ZeroMemory( &d3dpp, sizeof( d3dpp ) ); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; d3dpp.EnableAutoDepthStencil = TRUE; d3dpp.AutoDepthStencilFormat = D3DFMT_D16; // Create the D3DDevice if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice ) ) ) { return E_FAIL; } // Turn on the zbuffer g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE ); // Turn on ambient lighting g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0xffffffff ); return S_OK; } //----------------------------------------------------------------------------- // Name: InitGeometry() // Desc: Load the mesh and build the material and texture arrays //----------------------------------------------------------------------------- HRESULT InitGeometry() { LPD3DXBUFFER pD3DXMtrlBuffer; // Load the mesh from the specified file if( FAILED( D3DXLoadMeshFromX( L"heli.x", D3DXMESH_SYSTEMMEM, g_pd3dDevice, NULL, &pD3DXMtrlBuffer, NULL, &g_dwNumMaterials, &g_pMesh ) ) )//X 파일로 부터 불러옴. Vertex 버퍼가 없는데 얘가 다 만들어줌. { // If model is not in current folder, try parent folder if( FAILED( D3DXLoadMeshFromX( L"..\\heli.x", D3DXMESH_SYSTEMMEM, g_pd3dDevice, NULL, &pD3DXMtrlBuffer, NULL, &g_dwNumMaterials, &g_pMesh ) ) ) { MessageBox( NULL, L"Could not find tiger.x", L"Meshes.exe", MB_OK ); return E_FAIL; } } // We need to extract the material properties and texture names from the 텍스처는 따로뺌. 최적화를 위해서 // pD3DXMtrlBuffer D3DXMATERIAL* d3dxMaterials = ( D3DXMATERIAL* )pD3DXMtrlBuffer->GetBufferPointer(); g_pMeshMaterials = new D3DMATERIAL9[g_dwNumMaterials]; if( g_pMeshMaterials == NULL ) return E_OUTOFMEMORY; g_pMeshTextures = new LPDIRECT3DTEXTURE9[g_dwNumMaterials]; if( g_pMeshTextures == NULL ) return E_OUTOFMEMORY; for( DWORD i = 0; i < g_dwNumMaterials; i++ ) { // Copy the material g_pMeshMaterials[i] = d3dxMaterials[i].MatD3D; // Set the ambient color for the material (D3DX does not do this) g_pMeshMaterials[i].Ambient = g_pMeshMaterials[i].Diffuse; g_pMeshTextures[i] = NULL; if( d3dxMaterials[i].pTextureFilename != NULL && lstrlenA( d3dxMaterials[i].pTextureFilename ) > 0 ) { // Create the texture if( FAILED( D3DXCreateTextureFromFileA( g_pd3dDevice, d3dxMaterials[i].pTextureFilename, &g_pMeshTextures[i] ) ) ) { // If texture is not in current folder, try parent folder const CHAR* strPrefix = "..\\"; CHAR strTexture[MAX_PATH]; strcpy_s( strTexture, MAX_PATH, strPrefix ); strcat_s( strTexture, MAX_PATH, d3dxMaterials[i].pTextureFilename ); // If texture is not in current folder, try parent folder if( FAILED( D3DXCreateTextureFromFileA( g_pd3dDevice, strTexture, &g_pMeshTextures[i] ) ) ) { MessageBox( NULL, L"Could not find texture map", L"Meshes.exe", MB_OK ); } } } } // Done with the material buffer pD3DXMtrlBuffer->Release(); return S_OK; } //----------------------------------------------------------------------------- // Name: Cleanup() // Desc: Releases all previously initialized objects //----------------------------------------------------------------------------- VOID Cleanup() { if( g_pMeshMaterials != NULL ) delete[] g_pMeshMaterials; if( g_pMeshTextures ) { for( DWORD i = 0; i < g_dwNumMaterials; i++ ) { if( g_pMeshTextures[i] ) g_pMeshTextures[i]->Release(); } delete[] g_pMeshTextures; } if( g_pMesh != NULL ) g_pMesh->Release(); if( g_pd3dDevice != NULL ) g_pd3dDevice->Release(); if( g_pD3D != NULL ) g_pD3D->Release(); } //----------------------------------------------------------------------------- // Name: SetupMatrices() // Desc: Sets up the world, view, and projection transform matrices. //----------------------------------------------------------------------------- VOID SetupMatrices() { static float a = 0; static float b = 0; static float c = 0; static float d = 0; if (left_rotation < -4) left_rotation = 0; if (right_rotation > 4) right_rotation = 0; //if (a >4) // a = 0; //if (c > 4) // c = 0; //if (b > 4) // b = 0; left_rotation =-90; right_rotation = 90; // Set up world matrix D3DXMATRIXA16 matWorld; D3DXMATRIXA16 Rotation; D3DXMATRIXA16 Moving; D3DXMATRIXA16 Rotation_RIGHT; //D3DXMatrixRotationY(&Rotation,270); D3DXMatrixTranslation(&matWorld, 0,0,0); //D3DXMatrixMultiply(&matWorld, &matWorld, &Moving); //D3DXMatrixMultiply(&matWorld, &matWorld ,&Rotation); //D3DXMatrixMultiply(&matWorld, &matWorld, &PrevPosition); //D3DXMatrixRotationX(&matWorld, -90); if (UP) { a += 0.1; D3DXMatrixTranslation(&matWorld, b, a, 0); //D3DXMatrixTranslation(&PrevPosition, b, a, 0); } else if (DOWN) { a -= 0.1; D3DXMatrixTranslation(&matWorld, b, a, 0); //D3DXMatrixTranslation(&PrevPosition, 0, a, 0); } else if(RIGHT) { b += 0.1; D3DXMatrixTranslation(&matWorld, b,a,0); //D3DXMatrixTranslation(&PrevPosition, b, 0, 0); } else if (LEFT) { b -= 0.1; D3DXMatrixTranslation(&matWorld, b, a, 0); //D3DXMatrixTranslation(&PrevPosition, b, 0, 0); } else if (SPACE) { D3DXMatrixTranslation(&matWorld, b, a, 0); } //D3DXMatrixRotationY( &matWorld, timeGetTime() / 1000.0f ); g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld ); // Set up our view matrix. A view matrix can be defined given an eye point, // a point to lookat, and a direction for which way is up. Here, we set the // eye five units back along the z-axis and up three units, look at the // origin, and define "up" to be in the y-direction. D3DXVECTOR3 vEyePt( -30.0f, 0.0f,-30.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 ); // For the projection matrix, we set up a perspective transform (which // transforms geometry from 3D view space to 2D viewport space, with // a perspective divide making objects smaller in the distance). To build // a perpsective transform, we need the field of view (1/4 pi is common), // the aspect ratio, and the near and far clipping planes (which define at // what distances geometry should be no longer be rendered). D3DXMATRIXA16 matProj; D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI / 4, 1.0f, 1.0f, 100.0f ); g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj ); } //----------------------------------------------------------------------------- // Name: Render() // Desc: Draws the scene //----------------------------------------------------------------------------- VOID Render() { // Clear the backbuffer and the zbuffer g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB( 0, 0, 255 ), 1.0f, 0 ); // Begin the scene if( SUCCEEDED( g_pd3dDevice->BeginScene() ) ) { // Setup the world, view, and projection matrices SetupMatrices(); // Meshes are divided into subsets, one for each material. Render them in // a loop ///////////////////////////////////////////////////////////////////////////////그리는 부분; for( DWORD i = 0; i < g_dwNumMaterials; i++ ) { // Set the material and texture for this subset g_pd3dDevice->SetMaterial( &g_pMeshMaterials[i] ); g_pd3dDevice->SetTexture( 0, g_pMeshTextures[i] ); // Draw the mesh subset g_pMesh->DrawSubset( i ); } /////////////////////////////////////////////////////////////////////////////// // End the scene g_pd3dDevice->EndScene(); } // Present the backbuffer contents to the display 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; case WM_KEYDOWN: switch (wParam) { case VK_LEFT: RIGHT = FALSE; LEFT = TRUE; UP = FALSE; DOWN = FALSE; SPACE = FALSE; break; case VK_RIGHT: RIGHT = TRUE; LEFT = FALSE; UP = FALSE; DOWN = FALSE; SPACE = FALSE; break; case VK_UP: RIGHT = FALSE; LEFT = FALSE; UP = TRUE; DOWN = FALSE; SPACE = FALSE; break; case VK_DOWN: RIGHT = FALSE; LEFT = FALSE; UP = FALSE; DOWN = TRUE; SPACE = FALSE; break; case VK_SPACE: RIGHT = FALSE; LEFT = FALSE; UP = FALSE; DOWN = FALSE; SPACE = TRUE; break; } } return DefWindowProc( hWnd, msg, wParam, lParam ); } //----------------------------------------------------------------------------- // Name: WinMain() // Desc: The application's entry point //----------------------------------------------------------------------------- INT WINAPI wWinMain( HINSTANCE hInst, HINSTANCE, LPWSTR, INT ) { UNREFERENCED_PARAMETER( hInst ); // Register the window class WNDCLASSEX wc = { sizeof( WNDCLASSEX ), CS_CLASSDC, MsgProc, 0L, 0L, GetModuleHandle( NULL ), NULL, NULL, NULL, NULL, L"D3D Tutorial", NULL }; RegisterClassEx( &wc ); // Create the application's window HWND hWnd = CreateWindow( L"D3D Tutorial", L"D3D Tutorial 06: Meshes", WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, NULL, NULL, wc.hInstance, NULL ); // Initialize Direct3D if( SUCCEEDED( InitD3D( hWnd ) ) ) { // Create the scene geometry if( SUCCEEDED( InitGeometry() ) ) { // Show the window ShowWindow( hWnd, SW_SHOWDEFAULT ); UpdateWindow( hWnd ); // Enter the message loop 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; } | cs |
이번에는 geometry를 더 확장해서 대부분의 프로그램들은 파일로부터 메쉬들을 불러오는걸 선호하게 됩니다. 메쉬를 사용할 때 D3DX는 버텍스 버퍼를 생성하고 Geometry파일을 파싱해야합니다.
전역변수
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | //----------------------------------------------------------------------------- // Global variables //----------------------------------------------------------------------------- LPDIRECT3D9 g_pD3D = NULL; // Used to create the D3DDevice LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; // Our rendering device //////////////////////////////////////////////////////////////////////////// 이부분을 여러개 하면 모델이 여러개 나옴. LPD3DXMESH g_pMesh = NULL; // Our mesh object in sysmem D3DMATERIAL9* g_pMeshMaterials = NULL; // Materials for our mesh LPDIRECT3DTEXTURE9* g_pMeshTextures = NULL; // Textures for our mesh DWORD g_dwNumMaterials = 0L; // Number of mesh materials //동적 할당을 위해서 //////////////////////////////////////////////////////////////////////////// BOOL RIGHT = FALSE; BOOL LEFT = FALSE; BOOL UP = FALSE; BOOL DOWN = FALSE; BOOL SPACE = FALSE; FLOAT left_rotation = 0; FLOAT right_rotation = 0; | cs |
메쉬를 사용하기 위해서는 전역변수에 LPD3DXMESH, D3DMATERIAL9, LPDIRECT3DTEXTURE9, DWORD가 더 추가되었습니다. 이부분은 메쉬를 이용하기 위한 부분입니다. 메쉬를 하나가 아니라 여러개를 하기 위해서는 이부분에 대해서 더 추가 해주시면 됩니다.
InitGeometry()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | //----------------------------------------------------------------------------- // Name: InitGeometry() // Desc: Load the mesh and build the material and texture arrays //----------------------------------------------------------------------------- HRESULT InitGeometry() { LPD3DXBUFFER pD3DXMtrlBuffer; // Load the mesh from the specified file if( FAILED( D3DXLoadMeshFromX( L"heli.x", D3DXMESH_SYSTEMMEM, g_pd3dDevice, NULL, &pD3DXMtrlBuffer, NULL, &g_dwNumMaterials, &g_pMesh ) ) )//X 파일로 부터 불러옴. Vertex 버퍼가 없는데 얘가 다 만들어줌. { // If model is not in current folder, try parent folder if( FAILED( D3DXLoadMeshFromX( L"..\\heli.x", D3DXMESH_SYSTEMMEM, g_pd3dDevice, NULL, &pD3DXMtrlBuffer, NULL, &g_dwNumMaterials, &g_pMesh ) ) ) { MessageBox( NULL, L"Could not find tiger.x", L"Meshes.exe", MB_OK ); return E_FAIL; } } // We need to extract the material properties and texture names from the 텍스처는 따로뺌. 최적화를 위해서 // pD3DXMtrlBuffer D3DXMATERIAL* d3dxMaterials = ( D3DXMATERIAL* )pD3DXMtrlBuffer->GetBufferPointer(); g_pMeshMaterials = new D3DMATERIAL9[g_dwNumMaterials]; if( g_pMeshMaterials == NULL ) return E_OUTOFMEMORY; g_pMeshTextures = new LPDIRECT3DTEXTURE9[g_dwNumMaterials]; if( g_pMeshTextures == NULL ) return E_OUTOFMEMORY; for( DWORD i = 0; i < g_dwNumMaterials; i++ ) { // Copy the material g_pMeshMaterials[i] = d3dxMaterials[i].MatD3D; // Set the ambient color for the material (D3DX does not do this) g_pMeshMaterials[i].Ambient = g_pMeshMaterials[i].Diffuse; g_pMeshTextures[i] = NULL; if( d3dxMaterials[i].pTextureFilename != NULL && lstrlenA( d3dxMaterials[i].pTextureFilename ) > 0 ) { // Create the texture if( FAILED( D3DXCreateTextureFromFileA( g_pd3dDevice, d3dxMaterials[i].pTextureFilename, &g_pMeshTextures[i] ) ) ) { // If texture is not in current folder, try parent folder const CHAR* strPrefix = "..\\"; CHAR strTexture[MAX_PATH]; strcpy_s( strTexture, MAX_PATH, strPrefix ); strcat_s( strTexture, MAX_PATH, d3dxMaterials[i].pTextureFilename ); // If texture is not in current folder, try parent folder if( FAILED( D3DXCreateTextureFromFileA( g_pd3dDevice, strTexture, &g_pMeshTextures[i] ) ) ) { MessageBox( NULL, L"Could not find texture map", L"Meshes.exe", MB_OK ); } } } } // Done with the material buffer pD3DXMtrlBuffer->Release(); return S_OK; } | cs |
이부분에서는 파일을 불러오게 됩니다. 파일 확장자는 *.x 형태의 파일을 가지게 되는데 파일을 우선 루트를 한번 찾아보고 없다면 그 상위 풀더를 한번 뒤져보고서 없으면 에러를 리턴합니다. 메모리 정상적으로 할당 되었는지 확인을 하며 확인이 되었다면 Material을 따로 처리한 다음 Texture를 생성해 줍니다. Texture와 메쉬를 분리 한 이유는 최적화를 위함입니다.
다음 영상은 이 소스의 결과를 보여줍니다.
추가로 x파일은 다음과 같은 형태로 되어있습니다.
앞에서 일일이 다 입력해주었던 내용들이 여기에서는 직접 모두 다 처리 되어있습니다. x 파일은 3DMax 같은 프로그램에 플러그인을 이용 뽑아 낼 수 있습니다.
'Programming > DirectX' 카테고리의 다른 글
[다이렉트SDK 예제]DirectX Tutorial4 - Lighting (0) | 2016.04.15 |
---|---|
[다이렉트SDK 예제]DirectX Tutorial3 - Matrices (0) | 2016.04.15 |
[다이렉트SDK 예제]DirectX Tutorial2 - Vertices (0) | 2016.04.15 |
[다이렉트SDK 예제]DirectX Tutorial1 - CreateDevice (0) | 2016.04.14 |
다이렉트 X 예제 알아보기 - DirectX Sample Browser (0) | 2016.04.14 |