--- /dev/null
+/********************************************************************
+ *
+ * Parts of the DirectX code are from a tutorial by Microsoft
+ * which can be found in the Microsoft DirectX SDK June 2010.
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ *
+ *
+ * The rest of the code is COPYRIGHT PARROT 2010
+ *
+ ********************************************************************
+ * PARROT - A.R.Drone SDK Windows Client Example
+ *-----------------------------------------------------------------*/
+/**
+ * @file directx_rendering.h
+ * @brief Module rendering the drone video stream on a textured Direct3D polygone.
+ *
+ * @author Stephane Piskorski <stephane.piskorski.ext@parrot.fr>
+ * @date Sept, 8. 2010
+ *
+ *******************************************************************/
+
+\r
+\r
+//-----------------------------------------------------------------------------\r
+// Display manager for the Win32 SDK Demo application\r
+// Based on the Microsoft DirectX SDK tutorials\r
+//-----------------------------------------------------------------------------\r
+\r
+#include <custom_code.h>\r
+#include "directx_rendering.h"\r
+\r
+\r
+//-----------------------------------------------------------------------------\r
+// Global variables\r
+//-----------------------------------------------------------------------------\r
+LPDIRECT3D9 g_pD3D = NULL; // Used to create the D3DDevice\r
+LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; // Our rendering device\r
+LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; // Buffer to hold vertices\r
+LPDIRECT3DTEXTURE9 g_pTexture = NULL; // Our texture\r
+\r
+static int videoWidth = DRONE_VIDEO_MAX_WIDTH;\r
+static int videoHeight = DRONE_VIDEO_MAX_HEIGHT;\r
+\r
+\r
+\r
+//-----------------------------------------------------------------------------\r
+// Name: InitD3D()\r
+// Desc: Initializes Direct3D\r
+//-----------------------------------------------------------------------------\r
+HRESULT InitD3D( HWND hWnd )\r
+{\r
+ // Create the D3D object.\r
+ if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )\r
+ return E_FAIL;\r
+\r
+ // Set up the structure used to create the D3DDevice. Since we are now\r
+ // using more complex geometry, we will create a device with a zbuffer.\r
+ D3DPRESENT_PARAMETERS d3dpp;\r
+ ZeroMemory( &d3dpp, sizeof( d3dpp ) );\r
+ d3dpp.Windowed = TRUE;\r
+ d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;\r
+ d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;\r
+ d3dpp.EnableAutoDepthStencil = TRUE;\r
+ d3dpp.AutoDepthStencilFormat = D3DFMT_D16;\r
+\r
+ // Create the D3DDevice\r
+ if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,\r
+ D3DCREATE_SOFTWARE_VERTEXPROCESSING,\r
+ &d3dpp, &g_pd3dDevice ) ) )\r
+ {\r
+ return E_FAIL;\r
+ }\r
+\r
+ // Turn off culling\r
+ g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );\r
+\r
+ // Turn off D3D lighting\r
+ g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );\r
+\r
+ // Turn on the zbuffer\r
+ g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );\r
+\r
+ return S_OK;\r
+}\r
+\r
+\r
+\r
+\r
+//-----------------------------------------------------------------------------\r
+// Name: InitGeometry()\r
+// Desc: Create the textures and vertex buffers\r
+//-----------------------------------------------------------------------------\r
+HRESULT InitGeometry()\r
+{\r
+ if( FAILED( D3DXCreateTexture(g_pd3dDevice,\r
+ TEXTURE_WIDTH,TEXTURE_HEIGHT,\r
+ D3DX_DEFAULT,\r
+ D3DUSAGE_DYNAMIC,\r
+ D3DFMT_X8R8G8B8,\r
+ D3DPOOL_DEFAULT,\r
+ &g_pTexture)))\r
+ {\r
+ MessageBox( NULL, L"Could not create texture for video rendering", L"Bad news...", MB_OK );\r
+ return E_FAIL;\r
+ }\r
+\r
+ // Create the vertex buffer.\r
+ if( FAILED( g_pd3dDevice->CreateVertexBuffer( 4 * 2 * sizeof( CUSTOMVERTEX ),\r
+ 0, D3DFVF_CUSTOMVERTEX,\r
+ D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )\r
+ {\r
+ return E_FAIL;\r
+ }\r
+\r
+ // Fill the vertex buffer. We are setting the tu and tv texture\r
+ // coordinates, which range from 0.0 to 1.0\r
+ CUSTOMVERTEX* pVertices;\r
+ if( FAILED( g_pVB->Lock( 0, 0, ( void** )&pVertices, 0 ) ) )\r
+ return E_FAIL;\r
+ \r
+ // Create four points coordinates to form a quad\r
+\r
+ pVertices[0].position = D3DXVECTOR3( -1.0f , 1.0 , 0.0f );\r
+ pVertices[1].position = D3DXVECTOR3( 1.0f , 1.0 , 0.0f );\r
+ pVertices[2].position = D3DXVECTOR3( -1.0 , -1.0f , 0.0f );\r
+ pVertices[3].position = D3DXVECTOR3( 1.0f , -1.0f , 0.0f );\r
+\r
+ for(int i=0;i<4;i++) { pVertices[i].color=0xffffffff; }\r
+\r
+ float scaleFactorW = (float)(videoWidth) /(float)(TEXTURE_WIDTH);\r
+ float scaleFactorH = (float)(videoHeight)/(float)(TEXTURE_HEIGHT);\r
+\r
+ pVertices[0].tu = 0.0f; pVertices[0].tv = 0.0f; \r
+ pVertices[1].tu = scaleFactorW; pVertices[1].tv = 0.0f; \r
+ pVertices[2].tu = 0.0f; pVertices[2].tv = scaleFactorH; \r
+ pVertices[3].tu = scaleFactorW; pVertices[3].tv = scaleFactorH;\r
+\r
+ g_pVB->Unlock();\r
+\r
+ return S_OK;\r
+}\r
+\r
+\r
+unsigned char videoFrame[TEXTURE_WIDTH*TEXTURE_HEIGHT*4];\r
+\r
+\r
+//-----------------------------------------------------------------------------\r
+// Name: D3DChangeTexture()\r
+// Desc: Loads the texture from an external RGB buffer\r
+//-----------------------------------------------------------------------------\r
+extern "C" void D3DChangeTexture(unsigned char* rgbtexture)\r
+{\r
+ int i,j;\r
+ \r
+ unsigned char*rgb_src=rgbtexture;\r
+ unsigned char*xrgb_dest=videoFrame;\r
+ \r
+ for(i=0;i<videoHeight;i++){\r
+ xrgb_dest = videoFrame+i*TEXTURE_WIDTH*4;\r
+ rgb_src = rgbtexture+i*DRONE_VIDEO_MAX_WIDTH*3;\r
+ for (j=0;j<videoWidth;j++){\r
+ char r = *(rgb_src++);\r
+ char g = *(rgb_src++);\r
+ char b = *(rgb_src++);\r
+\r
+ *(xrgb_dest++)=b;\r
+ *(xrgb_dest++)=g;\r
+ *(xrgb_dest++)=r;\r
+ *(xrgb_dest++)=255; /* unused channel */\r
+ }}\r
+}\r
+\r
+extern "C" void D3DChangeTextureSize(int w,int h)\r
+{\r
+ /*\r
+ Makes sure the 3D object was built.\r
+ It might not be, since this function is called by the video pipeline\r
+ thread which can start before the Direct3D thread.\r
+ */\r
+ if (g_pVB==NULL) return;\r
+\r
+ if (w!=videoWidth || h!=videoHeight)\r
+ {\r
+ videoWidth = min(w,DRONE_VIDEO_MAX_WIDTH);\r
+ videoHeight = min(h,DRONE_VIDEO_MAX_HEIGHT);\r
+\r
+ /* \r
+ Change the texture coordinates for the 3D object which renders the video.\r
+ The texture buffer has a fixed and large size, but only part of it is filled \r
+ by D3DChangeTexture.\r
+ */\r
+ CUSTOMVERTEX* pVertices;\r
+ if( !FAILED( g_pVB->Lock( 0, 0, ( void** )&pVertices, 0 ) ) )\r
+ {\r
+ float scaleFactorW = (float)(videoWidth) /(float)(TEXTURE_WIDTH);\r
+ float scaleFactorH = (float)(videoHeight)/(float)(TEXTURE_HEIGHT);\r
+\r
+ pVertices[0].tu = 0.0f; pVertices[0].tv = 0.0f; \r
+ pVertices[1].tu = scaleFactorW; pVertices[1].tv = 0.0f; \r
+ pVertices[2].tu = 0.0f; pVertices[2].tv = scaleFactorH; \r
+ pVertices[3].tu = scaleFactorW; pVertices[3].tv = scaleFactorH;\r
+\r
+ g_pVB->Unlock();\r
+ }}\r
+}\r
+\r
+\r
+//-----------------------------------------------------------------------------\r
+// Name: Cleanup()\r
+// Desc: Releases all previously initialized objects\r
+//-----------------------------------------------------------------------------\r
+VOID Cleanup()\r
+{\r
+ if( g_pTexture != NULL )\r
+ g_pTexture->Release();\r
+\r
+ if( g_pVB != NULL )\r
+ g_pVB->Release();\r
+\r
+ if( g_pd3dDevice != NULL )\r
+ g_pd3dDevice->Release();\r
+\r
+ if( g_pD3D != NULL )\r
+ g_pD3D->Release();\r
+}\r
+\r
+\r
+\r
+//-----------------------------------------------------------------------------\r
+// Name: SetupMatrices()\r
+// Desc: Sets up the world, view, and projection transform matrices.\r
+//-----------------------------------------------------------------------------\r
+VOID SetupMatrices()\r
+{\r
+ // Set up world matrix\r
+ D3DXMATRIXA16 matWorld;\r
+ D3DXMatrixIdentity( &matWorld );\r
+ D3DXMatrixRotationX( &matWorld, 0.0f );\r
+ g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );\r
+\r
+ // Set up our view matrix. A view matrix can be defined given an eye point,\r
+ // a point to lookat, and a direction for which way is up. Here, we set the\r
+ // eye five units back along the z-axis and up three units, look at the\r
+ // origin, and define "up" to be in the y-direction.\r
+ D3DXVECTOR3 vEyePt( 0.0f, 0.0f,-2.0f );\r
+ D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );\r
+ D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );\r
+ D3DXMATRIXA16 matView;\r
+ D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );\r
+ g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );\r
+\r
+ // For the projection matrix, we set up a perspective transform (which\r
+ // transforms geometry from 3D view space to 2D viewport space, with\r
+ // a perspective divide making objects smaller in the distance). To build\r
+ // a perpsective transform, we need the field of view (1/4 pi is common),\r
+ // the aspect ratio, and the near and far clipping planes (which define at\r
+ // what distances geometry should be no longer be rendered).\r
+ D3DXMATRIXA16 matProj;\r
+ D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI / 4, 1.0f, 1.0f, 100.0f );\r
+ g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );\r
+}\r
+\r
+\r
+\r
+\r
+//-----------------------------------------------------------------------------\r
+// Name: Render()\r
+// Desc: Draws the scene\r
+//-----------------------------------------------------------------------------\r
+VOID Render()\r
+{\r
+ // Clear the backbuffer and the zbuffer\r
+ g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,\r
+ D3DCOLOR_XRGB( 0, 0, 255 ), 1.0f, 0 );\r
+\r
+ \r
+ D3DLOCKED_RECT locked;\r
+ if(g_pTexture->LockRect(0, &locked, NULL, /*D3DLOCK_DISCARD*/0)==D3D_OK)\r
+ { \r
+ memcpy(locked.pBits, videoFrame, TEXTURE_WIDTH*TEXTURE_HEIGHT*3);\r
+ g_pTexture->UnlockRect(0);\r
+ }\r
+\r
+ // Begin the scene\r
+ if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )\r
+ {\r
+ // Setup the world, view, and projection matrices\r
+ SetupMatrices();\r
+\r
+ // Setup our texture. Using textures introduces the texture stage states,\r
+ // which govern how textures get blended together (in the case of multiple\r
+ // textures) and lighting information. In this case, we are modulating\r
+ // (blending) our texture with the diffuse color of the vertices.\r
+ g_pd3dDevice->SetTexture( 0, g_pTexture );\r
+ g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );\r
+ g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );\r
+ g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );\r
+ g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE );\r
+\r
+ // Render the vertex buffer contents\r
+ g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) );\r
+ g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );\r
+ // Draws two triangles (makes a quad that will support our drone video picture)\r
+ g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );\r
+\r
+ // End the scene\r
+ g_pd3dDevice->EndScene();\r
+ }\r
+\r
+ // Present the backbuffer contents to the display\r
+ g_pd3dDevice->Present( NULL, NULL, NULL, NULL );\r
+}\r
+\r
+\r
+\r
+\r
+//-----------------------------------------------------------------------------\r
+// Name: MsgProc()\r
+// Desc: The window's message handler\r
+//-----------------------------------------------------------------------------\r
+LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )\r
+{\r
+ switch( msg )\r
+ {\r
+ case WM_DESTROY:\r
+ Cleanup();\r
+ PostQuitMessage( 0 );\r
+ return 0;\r
+ }\r
+\r
+ return DefWindowProc( hWnd, msg, wParam, lParam );\r
+}\r
+\r
+\r
+\r
+\r
+//-----------------------------------------------------------------------------\r
+//-----------------------------------------------------------------------------\r
+DEFINE_THREAD_ROUTINE(directx_renderer_thread, data)
+{\r
+ // Register the window class\r
+ WNDCLASSEX wc =\r
+ {\r
+ sizeof( WNDCLASSEX ), CS_CLASSDC, MsgProc, 0L, 0L,\r
+ GetModuleHandle( NULL ), NULL, NULL, NULL, NULL,\r
+ L"A.R.Drone Video", NULL\r
+ };\r
+ RegisterClassEx( &wc );\r
+\r
+ // Create the application's window\r
+ HWND hWnd = CreateWindow( L"A.R.Drone Video", L"A.R.Drone Video",\r
+ WS_OVERLAPPEDWINDOW, 100, 100, 640, 480,\r
+ NULL, NULL, wc.hInstance, NULL );\r
+\r
+ // Initialize Direct3D\r
+ if( SUCCEEDED( InitD3D( hWnd ) ) )\r
+ {\r
+ // Create the scene geometry\r
+ if( SUCCEEDED( InitGeometry() ) )\r
+ {\r
+ // Show the window\r
+ ShowWindow( hWnd, SW_SHOWDEFAULT );\r
+ UpdateWindow( hWnd );\r
+\r
+ // Enter the message loop\r
+ MSG msg;\r
+ ZeroMemory( &msg, sizeof( msg ) );\r
+ while( msg.message != WM_QUIT )\r
+ {\r
+ if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )\r
+ {\r
+ TranslateMessage( &msg );\r
+ DispatchMessage( &msg );\r
+ }\r
+ else\r
+ Render();\r
+ }\r
+ }\r
+ }\r
+\r
+ UnregisterClass( L"A.R.Drone Video", wc.hInstance );\r
+\r
+ /* Tells ARDRoneTool to shutdown */\r
+ signal_exit();\r
+\r
+ return 0;\r
+}\r
+\r
+\r
+\r