Direct3D立體顯示實現

 

這是根據上篇文章而寫的基於Direct3D的立體顯示:

// include the basic windows header files and the Direct3D header file

#include <windows.h>

#include <windowsx.h>

#include <d3d9.h>

#include <d3dx9.h>

 

// include the Direct3D Library files

#pragma comment (lib , "d3d9.lib" )

#pragma comment (lib , "d3dx9.lib" )

 

// define the screen resolution and keyboard macros

#define SCREEN_WIDTH 640

#define SCREEN_HEIGHT 480

#define KEY_DOWN (vk_code ) ((GetAsyncKeyState (vk_code ) & 0x8000) ? 1 : 0)

#define KEY_UP (vk_code ) ((GetAsyncKeyState (vk_code ) & 0x8000) ? 0 : 1)

 

// global declarations

LPDIRECT3D9 d3d ;    // the pointer to our Direct3D interface

LPDIRECT3DDEVICE9 d3ddev ;    // the pointer to the device class

 

// mesh declarations

LPD3DXMESH meshSpaceship ;    // define the mesh pointer

D3DMATERIAL9 * material ;    // define the material object

LPDIRECT3DTEXTURE9 * texture ;    // a pointer to a texture

DWORD numMaterials ;    // stores the number of materials in the mesh

 

double StereoCameraOffset ; // half the overall camera separation

double Xrange ;//the horizontal range of the scene along the plane of zero parallax

// adjust the strength of the stereo effect to suit their preference.

double UserOffsetAdjustment = 1.0; 

double ZeroParallaxDistance = 7.0;   // zero parallax distance

double n_over_d ;  // NearClipDistance / ZeroParallaxDistance;

double UserBalanceAdjustment = 1.0; // adjust the parallax balance to their liking

double FrustumAsymmetry ; // the desired amount of frustum asymmetry

// are the arguments of the original symmetric frustum projection

double FrustumLeft = -0.5;

double FrustumRight = 0.5;

double NearClipDistance = 1.0;

double FarClipDistance = 100.0;

double FrustumBottom = -0.5;

double FrustumTop = 0.5;

double ObjectDistance = ZeroParallaxDistance ;

 

float g_fSpinX     = 0.0f;

float g_fSpinY     = 0.0f;

 

// function prototypes

void initD3D (HWND hWnd );    // sets up and initializes Direct3D

void render_frame (void );    // renders a single frame

void cleanD3D (void );    // closes Direct3D and releases memory

void init_graphics (void );    // 3D declarations

 

// the WindowProc function prototype

LRESULT CALLBACK WindowProc (HWND hWnd , UINT message , WPARAM wParam , LPARAM lParam );

// the entry point for any Windows program

int WINAPI WinMain (HINSTANCE hInstance ,

                   HINSTANCE hPrevInstance ,

                   LPSTR lpCmdLine ,

                   int nCmdShow )

{

    HWND hWnd ;

    WNDCLASSEX wc ;

    ZeroMemory (&wc , sizeof (WNDCLASSEX ));

 

    wc .cbSize = sizeof (WNDCLASSEX );

    wc .style = CS_HREDRAW | CS_VREDRAW ;

    wc .lpfnWndProc = (WNDPROC )WindowProc ;

    wc .hInstance = hInstance ;

    wc .hCursor = LoadCursor (NULL , IDC_ARROW );

    wc .lpszClassName = L "WindowClass1" ;

 

    RegisterClassEx (&wc );

 

    hWnd = CreateWindowEx (NULL ,

        L "WindowClass1" ,

        L "Our Direct3D Program" ,

        WS_EX_TOPMOST | WS_POPUP ,

        0, 0,

        SCREEN_WIDTH , SCREEN_HEIGHT ,

        NULL ,

        NULL ,

        hInstance ,

        NULL );

 

    ShowWindow (hWnd , nCmdShow );

 

    // set up and initialize Direct3D

    initD3D (hWnd );

    // enter the main loop:

    MSG msg ;

    while (TRUE )

    {

        DWORD starting_point = GetTickCount ();

 

        if (PeekMessage (&msg , NULL , 0, 0, PM_REMOVE ))

        {

            if (msg .message == WM_QUIT )

                break ;

            TranslateMessage (&msg );

            DispatchMessage (&msg );

        }

        render_frame ();

        // check the 'escape' key

        if (KEY_DOWN (VK_ESCAPE ))

            PostMessage (hWnd , WM_DESTROY , 0, 0);

 

        while ((GetTickCount () - starting_point ) < 25);

    }

    // clean up DirectX and COM

    cleanD3D ();

    return msg .wParam ;

}

// this is the main message handler for the program

LRESULT CALLBACK WindowProc (HWND hWnd , UINT message , WPARAM wParam , LPARAM lParam )

{

    static POINT ptLastMousePosit ;

    static POINT ptCurrentMousePosit ;

    static bool bMousing ;

 

    switch (message )

    {

    case WM_DESTROY :

        {

            PostQuitMessage (0);

            return 0;

        } break ;

    case WM_KEYDOWN :

        {

            switch (wParam )

            {

            case VK_F1 :

                if (UserOffsetAdjustment <= 2.0)

                {

                    UserOffsetAdjustment += 0.1;

                }

                break ;

            case VK_F2 :

                if (UserOffsetAdjustment > 0.0)

                {

                    UserOffsetAdjustment -= 0.1;

                }

                break ;

            case VK_F3 :

                if (UserBalanceAdjustment <= 2.0)

                {

                    UserBalanceAdjustment += 0.1;

                }

                break ;

            case VK_F4 :

                if (UserBalanceAdjustment > 0.0)

                {

                    UserBalanceAdjustment -= 0.1;

                }

                break ;

            case VK_UP :

                ObjectDistance += 0.1;

                break ;

            case VK_DOWN :

                ObjectDistance -= 0.1;

                break ;

            }

        }

        break ;

    case WM_LBUTTONDOWN :

        {

            ptLastMousePosit .x = ptCurrentMousePosit .x = LOWORD (lParam );

            ptLastMousePosit .y = ptCurrentMousePosit .y = HIWORD (lParam );

            bMousing = true ;

        }

        break ;

 

    case WM_LBUTTONUP :

        {

            bMousing = false ;

        }

        break ;

 

    case WM_MOUSEMOVE :

        {

            ptCurrentMousePosit .x = LOWORD (lParam );

            ptCurrentMousePosit .y = HIWORD (lParam );

            if ( bMousing )

            {

                g_fSpinX -= (ptCurrentMousePosit .x - ptLastMousePosit .x );

                g_fSpinY -= (ptCurrentMousePosit .y - ptLastMousePosit .y );

            }

            ptLastMousePosit .x = ptCurrentMousePosit .x ;

            ptLastMousePosit .y = ptCurrentMousePosit .y ;

        }

        break ;

    }

 

    return DefWindowProc (hWnd , message , wParam , lParam );

}

// this function initializes and prepares Direct3D for use

void initD3D (HWND hWnd )

{

    d3d = Direct3DCreate9 (D3D_SDK_VERSION );

 

    D3DPRESENT_PARAMETERS d3dpp ;

    ZeroMemory (&d3dpp , sizeof (d3dpp ));

    d3dpp .Windowed = FALSE ;

    d3dpp .SwapEffect = D3DSWAPEFFECT_DISCARD ;

    d3dpp .hDeviceWindow = hWnd ;

    d3dpp .BackBufferFormat = D3DFMT_X8R8G8B8 ;

    d3dpp .BackBufferWidth = SCREEN_WIDTH ;

    d3dpp .BackBufferHeight = SCREEN_HEIGHT ;

    d3dpp .EnableAutoDepthStencil = TRUE ;    // automatically run the z-buffer for us

    d3dpp .AutoDepthStencilFormat = D3DFMT_D16 ; // 16-bit pixel format for the z-buffer

    // create a device class using this information and the info from the d3dpp stuct

    d3d ->CreateDevice (D3DADAPTER_DEFAULT ,

        D3DDEVTYPE_HAL ,

        hWnd ,

        D3DCREATE_HARDWARE_VERTEXPROCESSING ,

        &d3dpp ,

        &d3ddev );

    // create the z-buffer

    d3ddev ->CreateDepthStencilSurface (SCREEN_WIDTH ,

        SCREEN_HEIGHT ,

        D3DFMT_D16 ,

        D3DMULTISAMPLE_NONE ,

        0,

        TRUE ,

        &z_buffer ,

        NULL );

    init_graphics ();    // call the function to initialize the triangle

   

    d3ddev ->SetRenderState (D3DRS_LIGHTING , FALSE );    // turn on the 3D lighting

    d3ddev ->SetRenderState (D3DRS_ZENABLE , TRUE );    // turn on the z-buffer

    d3ddev ->SetRenderState (D3DRS_AMBIENT , D3DCOLOR_XRGB (50, 50, 50));// ambient light

    return ;

}

// this is the function used to render a single frame

void render_frame (void )

{

    n_over_d = NearClipDistance / ZeroParallaxDistance ;

    Xrange = (FrustumRight - FrustumLeft ) / n_over_d ;

    StereoCameraOffset = Xrange * 0.035 * UserOffsetAdjustment ;

 

    FrustumAsymmetry = StereoCameraOffset * UserBalanceAdjustment ;

    FrustumAsymmetry *= n_over_d ;

    d3ddev ->Clear (0, NULL , D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER , D3DCOLOR_XRGB (20, 20, 20), 1.0f, 0);

 

    D3DXMATRIX matProjection ;    // the projection transform matrix

    D3DXMATRIX matLeftTrans ;    // the left-eye transform matrix

    D3DXMATRIX matRightTrans ; // the right-eye transform matrix

    D3DXMATRIX matRot ;       //the rotation matrix

    D3DXMATRIX matScale ;     //the scale matrix

 

    D3DXMatrixScaling (&matScale , 0.4f, 0.4f, 0.4f);

 

    d3ddev ->BeginScene ();

    D3DXMatrixPerspectiveOffCenterLH (&matProjection , FrustumLeft + FrustumAsymmetry , FrustumRight + FrustumAsymmetry , FrustumBottom , FrustumTop , NearClipDistance , FarClipDistance );

    d3ddev ->SetTransform (D3DTS_PROJECTION , &matProjection );    // set the projection

 

    D3DXMatrixRotationYawPitchRoll ( &matRot ,

        D3DXToRadian (g_fSpinX ),

        D3DXToRadian (g_fSpinY ),

        0.0f );

// Draw left eye view

    D3DXMatrixTranslation (&matLeftTrans , StereoCameraOffset , 0.0f, ObjectDistance );

    d3ddev ->SetTransform (D3DTS_WORLD , &(matScale *matRot *matLeftTrans ));

    d3ddev ->SetRenderState (D3DRS_COLORWRITEENABLE ,D3DCOLORWRITEENABLE_RED );

    // draw the spaceship

    for (DWORD i = 0; i < numMaterials ; i ++)    // loop through each subset

    {

        d3ddev ->SetMaterial (&material [i ]);    // set the material for the subset

        if (texture [i ] != NULL )    // if the subset has a texture (if texture is not NULL)

            d3ddev ->SetTexture (0, texture [i ]);    // ...then set the texture

        meshSpaceship ->DrawSubset (i );    // draw the subset

    }

// Draw right eye view

    d3ddev ->Clear (0, NULL ,  D3DCLEAR_ZBUFFER , D3DCOLOR_XRGB (20, 20, 20), 1.0f, 0);    D3DXMatrixTranslation (&matRightTrans , -StereoCameraOffset ,               0.0f,ObjectDistance );

    d3ddev ->SetTransform (D3DTS_WORLD , &(matScale *matRot *matRightTrans ));

 

    D3DXMatrixPerspectiveOffCenterLH (&matProjection , FrustumLeft - FrustumAsymmetry , FrustumRight - FrustumAsymmetry , FrustumBottom , FrustumTop , NearClipDistance , FarClipDistance );

    d3ddev ->SetTransform (D3DTS_PROJECTION , &matProjection );    // set the projection

 

    d3ddev ->SetRenderState (D3DRS_COLORWRITEENABLE , D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE );

    // draw the spaceship

    for (DWORD i = 0; i < numMaterials ; i ++)    // loop through each subset

    {

        d3ddev ->SetMaterial (&material [i ]);    // set the material for the subset

        if (texture [i ] != NULL )   // if the subset has a texture (if texture is not NULL)

            d3ddev ->SetTexture (0, texture [i ]);    // ...then set the texture

        meshSpaceship ->DrawSubset (i );    // draw the subset

    }

    d3ddev ->EndScene ();

    d3ddev ->Present (NULL , NULL , NULL , NULL );

    return ;

}

// this is the function that cleans up Direct3D and COM

void cleanD3D (void )

{

    meshSpaceship ->Release ();    // close and release the spaceship mesh

    d3ddev ->Release ();    // close and release the 3D device

    d3d ->Release ();    // close and release Direct3D

    return ;

}

// this is the function that puts the 3D models into video RAM

void init_graphics (void )

{

    LPD3DXBUFFER bufShipMaterial ;

    D3DXLoadMeshFromX (L "airplane 2.x" ,    // load this file

        D3DXMESH_SYSTEMMEM ,    // load the mesh into system memory

        d3ddev ,    // the Direct3D Device

        NULL ,    // we aren't using adjacency

        &bufShipMaterial ,    // put the materials here

        NULL ,    // we aren't using effect instances

        &numMaterials ,    // the number of materials in this model

        &meshSpaceship );    // put the mesh here

    // retrieve the pointer to the buffer containing the material information

    D3DXMATERIAL * tempMaterials = (D3DXMATERIAL *)bufShipMaterial ->GetBufferPointer ();

 

    // create a new material buffer and texture for each material in the mesh

    material = new D3DMATERIAL9 [numMaterials ];

    texture = new LPDIRECT3DTEXTURE9 [numMaterials ];

 

    for (DWORD i = 0; i < numMaterials ; i ++)    // for each material...

    {

        material [i ] = tempMaterials [i ].MatD3D ;    // get the material info

        material [i ].Ambient = material [i ].Diffuse ;    // make ambient the same as diffuse

        // if there is a texture to load, load it

        if (FAILED (D3DXCreateTextureFromFileA (d3ddev ,

            tempMaterials [i ].pTextureFilename ,

            &texture [i ])))

            texture [i ] = NULL ;    // if there is no texture, set the texture to NULL

    }

    return ;

}


當然需要帶上紅綠眼鏡才能看得到立體效果哦~~

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章