ArDrone SDK 1.8 added
[mardrone] / mardrone / ARDrone_SDK_Version_1_8_20110726 / Examples / Win32 / sdk_demo / Sources / UI / directx_rendering.cpp
diff --git a/mardrone/ARDrone_SDK_Version_1_8_20110726/Examples/Win32/sdk_demo/Sources/UI/directx_rendering.cpp b/mardrone/ARDrone_SDK_Version_1_8_20110726/Examples/Win32/sdk_demo/Sources/UI/directx_rendering.cpp
new file mode 100644 (file)
index 0000000..75e8b67
--- /dev/null
@@ -0,0 +1,390 @@
+/********************************************************************
+ *
+ *  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