Direct3D立体显示实现

来源:互联网 发布:java string isempty 编辑:程序博客网 时间:2024/06/09 23:58

 

这是根据上篇文章而写的基于Direct3D的立体显示:

// include the basic windows header files and the Direct3Dheader 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 toour Direct3D interface

LPDIRECT3DDEVICE9 d3ddev;    // the pointer tothe device class

 

// mesh declarations

LPD3DXMESH meshSpaceship;    // define themesh pointer

D3DMATERIAL9* material;    // define thematerial object

LPDIRECT3DTEXTURE9* texture;    // a pointer to atexture

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

 

double StereoCameraOffset ; // half the overall camera separation

double Xrange ;//the horizontal range of the scene along the plane of zeroparallax

// adjust the strength of the stereo effect to suit theirpreference.

double UserOffsetAdjustment =1.0; 

double ZeroParallaxDistance =7.0;  // zeroparallax 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 frustumprojection

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 andinitializes 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(HWNDhWnd, UINTmessage, WPARAMwParam, LPARAMlParam);

// the entry point for any Windows program

int WINAPI WinMain(HINSTANCEhInstance,

                   HINSTANCEhPrevInstance,

                   LPSTR lpCmdLine,

                   int nCmdShow)

{

    HWNDhWnd;

    WNDCLASSEXwc;

    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);

 

    // setup and initialize Direct3D

    initD3D(hWnd);

    //enter the main loop:

    MSGmsg;

    while(TRUE)

    {

        DWORDstarting_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();

    returnmsg.wParam;

}

// this is the main message handler for the program

LRESULT CALLBACK WindowProc(HWNDhWnd, UINTmessage, WPARAMwParam, LPARAMlParam)

{

    staticPOINT ptLastMousePosit;

    staticPOINT ptCurrentMousePosit;

    staticbool bMousing;

 

    switch(message)

    {

    caseWM_DESTROY:

        {

            PostQuitMessage(0);

            return0;

        } break;

    caseWM_KEYDOWN:

        {

            switch(wParam)

            {

            caseVK_F1:

                if (UserOffsetAdjustment<= 2.0)

                {

                    UserOffsetAdjustment += 0.1;

                }

                break;

            caseVK_F2:

                if (UserOffsetAdjustment> 0.0)

                {

                    UserOffsetAdjustment -= 0.1;

                }

                break;

            caseVK_F3:

                if (UserBalanceAdjustment<= 2.0)

                {

                    UserBalanceAdjustment += 0.1;

                }

                break;

            case VK_F4:

                if (UserBalanceAdjustment> 0.0)

                {

                    UserBalanceAdjustment -= 0.1;

                }

                break;

            caseVK_UP:

                ObjectDistance += 0.1;

                break;

            caseVK_DOWN:

                ObjectDistance -= 0.1;

                break;

            }

        }

        break;

    caseWM_LBUTTONDOWN:

        {

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

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

            bMousing= true;

        }

        break;

 

    caseWM_LBUTTONUP:

        {

            bMousing= false;

        }

        break;

 

    caseWM_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;

    }

 

    returnDefWindowProc (hWnd,message, wParam,lParam);

}

// this function initializes and prepares Direct3D for use

void initD3D(HWND hWnd)

{

    d3d= Direct3DCreate9(D3D_SDK_VERSION);

 

    D3DPRESENT_PARAMETERSd3dpp;

    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;    // automaticallyrun 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 thefunction 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);

 

    D3DXMATRIXmatProjection;    // the projectiontransform matrix

    D3DXMATRIXmatLeftTrans;    // the left-eyetransform matrix

    D3DXMATRIXmatRightTrans; //the right-eye transform matrix

    D3DXMATRIXmatRot;      //the rotation matrix

    D3DXMATRIXmatScale;   //thescale 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 theprojection

 

    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);

    // drawthe 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 hasa texture (if texture is not NULL)

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

        meshSpaceship->DrawSubset(i);    // draw thesubset

    }

// 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 theprojection

 

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

    // drawthe 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 thesubset

    }

    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 videoRAM

void init_graphics(void)

{

    LPD3DXBUFFERbufShipMaterial;

    D3DXLoadMeshFromX(L"airplane2.x",    // load this file

        D3DXMESH_SYSTEMMEM,    // load the meshinto system memory

        d3ddev,    // the Direct3DDevice

        NULL,    // we aren'tusing adjacency

        &bufShipMaterial,    // put thematerials here

        NULL,    // we aren'tusing effect instances

        &numMaterials,    // the number ofmaterials in this model

        &meshSpaceship);    // put the meshhere

    //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 thematerial 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 notexture, set the texture to NULL

    }

    return;

}


当然需要带上红绿眼镜才能看得到立体效果哦~~

 

原创粉丝点击