• 地形


    d3dUtility.h

    //////////////////////////////////////////////////////////////////////////////////////////////////
    // 
    // File: d3dUtility.h
    // 
    // Author: Frank Luna (C) All Rights Reserved
    //
    // System: AMD Athlon 1800+ XP, 512 DDR, Geforce 3, Windows XP, MSVC++ 7.0 
    //
    // Desc: Provides utility functions for simplifying common tasks.
    //          
    //////////////////////////////////////////////////////////////////////////////////////////////////
    
    #ifndef __d3dUtilityH__
    #define __d3dUtilityH__
    
    #include <d3dx9.h>
    #include <string>
    #include <limits>
    
    namespace d3d
    {
        //
        // Init
        //
        bool InitD3D(
            HINSTANCE hInstance,       // [in] Application instance.
            int width, int height,     // [in] Backbuffer dimensions.
            bool windowed,             // [in] Windowed (true)or full screen (false).
            D3DDEVTYPE deviceType,     // [in] HAL or REF
            IDirect3DDevice9** device);// [out]The created device.
    
        int EnterMsgLoop( 
            bool (*ptr_display)(float timeDelta));
    
        LRESULT CALLBACK WndProc(
            HWND hwnd,
            UINT msg, 
            WPARAM wParam,
            LPARAM lParam);
    
        //
        // Cleanup
        //
        template<class T> void Release(T t)
        {
            if( t )
            {
                t->Release();
                t = 0;
            }
        }
            
        template<class T> void Delete(T t)
        {
            if( t )
            {
                delete t;
                t = 0;
            }
        }
    
        //
        // Colors
        //
        const D3DXCOLOR      WHITE( D3DCOLOR_XRGB(255, 255, 255) );
        const D3DXCOLOR      BLACK( D3DCOLOR_XRGB(  0,   0,   0) );
        const D3DXCOLOR        RED( D3DCOLOR_XRGB(255,   0,   0) );
        const D3DXCOLOR      GREEN( D3DCOLOR_XRGB(  0, 255,   0) );
        const D3DXCOLOR       BLUE( D3DCOLOR_XRGB(  0,   0, 255) );
        const D3DXCOLOR     YELLOW( D3DCOLOR_XRGB(255, 255,   0) );
        const D3DXCOLOR       CYAN( D3DCOLOR_XRGB(  0, 255, 255) );
        const D3DXCOLOR    MAGENTA( D3DCOLOR_XRGB(255,   0, 255) );
    
        const D3DXCOLOR BEACH_SAND( D3DCOLOR_XRGB(255, 249, 157) );
        const D3DXCOLOR DESERT_SAND( D3DCOLOR_XRGB(250, 205, 135) );
    
        const D3DXCOLOR LIGHTGREEN( D3DCOLOR_XRGB( 60, 184, 120) );
        const D3DXCOLOR  PUREGREEN( D3DCOLOR_XRGB(  0, 166,  81) );
        const D3DXCOLOR  DARKGREEN( D3DCOLOR_XRGB(  0, 114,  54) );
    
        const D3DXCOLOR LIGHT_YELLOW_GREEN( D3DCOLOR_XRGB(124, 197, 118) );
        const D3DXCOLOR  PURE_YELLOW_GREEN( D3DCOLOR_XRGB( 57, 181,  74) );
        const D3DXCOLOR  DARK_YELLOW_GREEN( D3DCOLOR_XRGB( 25, 123,  48) );
    
        const D3DXCOLOR LIGHTBROWN(D3DCOLOR_XRGB(198, 156, 109));
        const D3DXCOLOR DARKBROWN( D3DCOLOR_XRGB(115, 100,  87));
    
        //
        // Lights
        //
    
        D3DLIGHT9 InitDirectionalLight(D3DXVECTOR3* direction, D3DXCOLOR* color);
        D3DLIGHT9 InitPointLight(D3DXVECTOR3* position, D3DXCOLOR* color);
        D3DLIGHT9 InitSpotLight(D3DXVECTOR3* position, D3DXVECTOR3* direction, D3DXCOLOR* color);
    
        //
        // Materials
        //
    
        D3DMATERIAL9 InitMtrl(D3DXCOLOR a, D3DXCOLOR d, D3DXCOLOR s, D3DXCOLOR e, float p);
    
        const D3DMATERIAL9 WHITE_MTRL  = InitMtrl(WHITE, WHITE, WHITE, BLACK, 2.0f);
        const D3DMATERIAL9 RED_MTRL    = InitMtrl(RED, RED, RED, BLACK, 2.0f);
        const D3DMATERIAL9 GREEN_MTRL  = InitMtrl(GREEN, GREEN, GREEN, BLACK, 2.0f);
        const D3DMATERIAL9 BLUE_MTRL   = InitMtrl(BLUE, BLUE, BLUE, BLACK, 2.0f);
        const D3DMATERIAL9 YELLOW_MTRL = InitMtrl(YELLOW, YELLOW, YELLOW, BLACK, 2.0f);
    
        //
        // Bounding Objects
        //
    
        struct BoundingBox
        {
            BoundingBox();
    
            bool isPointInside(D3DXVECTOR3& p);
    
            D3DXVECTOR3 _min;
            D3DXVECTOR3 _max;
        };
    
        struct BoundingSphere
        {
            BoundingSphere();
    
            D3DXVECTOR3 _center;
            float       _radius;
        };
    
        //
        // Constants
        //
    
        const float INFINITY = FLT_MAX;
        const float EPSILON  = 0.001f;
    
        //
        // Drawing
        //
    
        // Function references "desert.bmp" internally.  This file must
        // be in the working directory.
        bool DrawBasicScene(
            IDirect3DDevice9* device,// Pass in 0 for cleanup.
            float scale);            // uniform scale 
    
        //
        // Vertex Structures
        //
    
        struct Vertex
        {
            Vertex(){}
            Vertex(float x, float y, float z, 
                float nx, float ny, float nz,
                float u, float v)
            {
                _x  = x;  _y  = y;  _z  = z;
                _nx = nx; _ny = ny; _nz = nz;
                _u  = u;  _v  = v;
            }
            float _x, _y, _z;
            float _nx, _ny, _nz;
            float _u, _v;
    
            static const DWORD FVF;
        };
    
        //
        // Randomness
        //
    
        // Desc: Return random float in [lowBound, highBound] interval.
        float GetRandomFloat(float lowBound, float highBound);
        
    
        // Desc: Returns a random vector in the bounds specified by min and max.
        void GetRandomVector(
            D3DXVECTOR3* out,
            D3DXVECTOR3* min,
            D3DXVECTOR3* max);
    
        //
        // Conversion
        //
        DWORD FtoDw(float f);
    
        //
        // Interpolation
        //
    
        float Lerp(float a, float b, float t);
    }
    
    #endif // __d3dUtilityH__
    View Code

    camera.h

    #ifndef __cameraH__
    #define __cameraH__
    
    #include <d3dx9.h>
    
    class Camera
    {
    public:
        enum CameraType { LANDOBJECT, AIRCRAFT };
    
        Camera();
        Camera(CameraType cameraType);
        ~Camera();
    
        void strafe(float units);
        void fly(float units);
        void walk(float units);
    
        void pitch(float angles);
        void yaw(float angles);
        void roll(float angles);
    
        void getViewMatrix(D3DXMATRIX* V);
        void setCameraType(CameraType cameraType);
        void getPosition(D3DXVECTOR3* pos);
        void setPosition(D3DXVECTOR3* pos);
    
        void getRight(D3DXVECTOR3* right);
        void getUp(D3DXVECTOR3* up);
        void getLook(D3DXVECTOR3* look);
    
    private:
        CameraType  _cameraType;
        D3DXVECTOR3 _right;
        D3DXVECTOR3 _up;
        D3DXVECTOR3 _look;
        D3DXVECTOR3 _pos;
    };
    
    #endif
    View Code

    Terrain.h

    #ifndef    __terrainH__
    #define __terrainH__
    #include "d3dUtility.h"
    #include <string>
    #include <vector>
    class Terrain
    {
    public:
        Terrain(IDirect3DDevice9* device, std::string heightmapFileName, 
            int numVertsPerRow, int numVertsPerCol, int cellSpacing, float heightScale);
        void draw(D3DXMATRIX* world);
        ~Terrain(void);
    
    private:
        IDirect3DDevice9* _device;
        IDirect3DTexture9* _tex;
        IDirect3DVertexBuffer9* _vb;
        IDirect3DIndexBuffer9* _ib;
    
    
        int _numVertsPerRow;
        int _numVertsPerCol;
        int _cellSpacing;
    
        int _numCellsPerRow;
        int _numCellsPerCol;
        int _width;
        int _depth;
        int _numVertices;
        int _numTriangles;
        float _heightScale;
    
        std::vector<int> _heightmap;
    
        bool readRawFile(std::string fileName);
        bool computeVertices();
        bool computeIndices();
        
        struct TerrainVertex
        {
            TerrainVertex(){}
            TerrainVertex(float x, float y, float z, float u, float v)
            {
                _x = x; _y = y; _z = z; _u = u; _v = v;
            }
            float _x, _y, _z;
            float _u, _v;
    
            static const DWORD FVF;
        };
    };
    
    #endif
    View Code

    d3dUtility.cpp

    //////////////////////////////////////////////////////////////////////////////////////////////////
    // 
    // File: d3dUtility.cpp
    // 
    // Author: Frank Luna (C) All Rights Reserved
    //
    // System: AMD Athlon 1800+ XP, 512 DDR, Geforce 3, Windows XP, MSVC++ 7.0 
    //
    // Desc: Provides utility functions for simplifying common tasks.
    //          
    //////////////////////////////////////////////////////////////////////////////////////////////////
    
    #include "d3dUtility.h"
    
    // vertex formats
    const DWORD d3d::Vertex::FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;
    
    
    bool d3d::InitD3D(
        HINSTANCE hInstance,
        int width, int height,
        bool windowed,
        D3DDEVTYPE deviceType,
        IDirect3DDevice9** device)
    {
        //
        // Create the main application window.
        //
    
        WNDCLASS wc;
    
        wc.style         = CS_HREDRAW | CS_VREDRAW;
        wc.lpfnWndProc   = (WNDPROC)d3d::WndProc; 
        wc.cbClsExtra    = 0;
        wc.cbWndExtra    = 0;
        wc.hInstance     = hInstance;
        wc.hIcon         = LoadIcon(0, IDI_APPLICATION);
        wc.hCursor       = LoadCursor(0, IDC_ARROW);
        wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wc.lpszMenuName  = 0;
        wc.lpszClassName = "Direct3D9App";
    
        if( !RegisterClass(&wc) ) 
        {
            ::MessageBox(0, "RegisterClass() - FAILED", 0, 0);
            return false;
        }
            
        HWND hwnd = 0;
        hwnd = ::CreateWindow("Direct3D9App", "Direct3D9App", 
            WS_EX_TOPMOST,
            0, 0, width, height,
            0 /*parent hwnd*/, 0 /* menu */, hInstance, 0 /*extra*/); 
    
        if( !hwnd )
        {
            ::MessageBox(0, "CreateWindow() - FAILED", 0, 0);
            return false;
        }
    
        ::ShowWindow(hwnd, SW_SHOW);
        ::UpdateWindow(hwnd);
    
        //
        // Init D3D: 
        //
    
        HRESULT hr = 0;
    
        // Step 1: Create the IDirect3D9 object.
    
        IDirect3D9* d3d9 = 0;
        d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
    
        if( !d3d9 )
        {
            ::MessageBox(0, "Direct3DCreate9() - FAILED", 0, 0);
            return false;
        }
    
        // Step 2: Check for hardware vp.
    
        D3DCAPS9 caps;
        d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, deviceType, &caps);
    
        int vp = 0;
        if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
            vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
        else
            vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
    
        // Step 3: Fill out the D3DPRESENT_PARAMETERS structure.
     
        D3DPRESENT_PARAMETERS d3dpp;
        d3dpp.BackBufferWidth            = width;
        d3dpp.BackBufferHeight           = height;
        d3dpp.BackBufferFormat           = D3DFMT_A8R8G8B8;
        d3dpp.BackBufferCount            = 1;
        d3dpp.MultiSampleType            = D3DMULTISAMPLE_NONE;
        d3dpp.MultiSampleQuality         = 0;
        d3dpp.SwapEffect                 = D3DSWAPEFFECT_DISCARD; 
        d3dpp.hDeviceWindow              = hwnd;
        d3dpp.Windowed                   = windowed;
        d3dpp.EnableAutoDepthStencil     = true; 
        d3dpp.AutoDepthStencilFormat     = D3DFMT_D24S8;
        d3dpp.Flags                      = 0;
        d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
        d3dpp.PresentationInterval       = D3DPRESENT_INTERVAL_IMMEDIATE;
    
        // Step 4: Create the device.
    
        hr = d3d9->CreateDevice(
            D3DADAPTER_DEFAULT, // primary adapter
            deviceType,         // device type
            hwnd,               // window associated with device
            vp,                 // vertex processing
            &d3dpp,             // present parameters
            device);            // return created device
    
        if( FAILED(hr) )
        {
            // try again using a 16-bit depth buffer
            d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
            
            hr = d3d9->CreateDevice(
                D3DADAPTER_DEFAULT,
                deviceType,
                hwnd,
                vp,
                &d3dpp,
                device);
    
            if( FAILED(hr) )
            {
                d3d9->Release(); // done with d3d9 object
                ::MessageBox(0, "CreateDevice() - FAILED", 0, 0);
                return false;
            }
        }
    
        d3d9->Release(); // done with d3d9 object
        
        return true;
    }
    
    int d3d::EnterMsgLoop( bool (*ptr_display)(float timeDelta) )
    {
        MSG msg;
        ::ZeroMemory(&msg, sizeof(MSG));
    
        static float lastTime = (float)timeGetTime(); 
    
        while(msg.message != WM_QUIT)
        {
            if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
            {
                ::TranslateMessage(&msg);
                ::DispatchMessage(&msg);
            }
            else
            {    
                float currTime  = (float)timeGetTime();
                float timeDelta = (currTime - lastTime)*0.001f;
    
                ptr_display(timeDelta);
    
                lastTime = currTime;
            }
        }
        return msg.wParam;
    }
    
    D3DLIGHT9 d3d::InitDirectionalLight(D3DXVECTOR3* direction, D3DXCOLOR* color)
    {
        D3DLIGHT9 light;
        ::ZeroMemory(&light, sizeof(light));
    
        light.Type      = D3DLIGHT_DIRECTIONAL;
        light.Ambient   = *color * 0.4f;
        light.Diffuse   = *color;
        light.Specular  = *color * 0.6f;
        light.Direction = *direction;
    
        return light;
    }
    
    D3DLIGHT9 d3d::InitPointLight(D3DXVECTOR3* position, D3DXCOLOR* color)
    {
        D3DLIGHT9 light;
        ::ZeroMemory(&light, sizeof(light));
    
        light.Type      = D3DLIGHT_POINT;
        light.Ambient   = *color * 0.4f;
        light.Diffuse   = *color;
        light.Specular  = *color * 0.6f;
        light.Position  = *position;
        light.Range        = 1000.0f;
        light.Falloff      = 1.0f;
        light.Attenuation0 = 1.0f;
        light.Attenuation1 = 0.0f;
        light.Attenuation2 = 0.0f;
    
        return light;
    }
    
    D3DLIGHT9 d3d::InitSpotLight(D3DXVECTOR3* position, D3DXVECTOR3* direction, D3DXCOLOR* color)
    {
        D3DLIGHT9 light;
        ::ZeroMemory(&light, sizeof(light));
    
        light.Type      = D3DLIGHT_SPOT;
        light.Ambient   = *color * 0.4f;
        light.Diffuse   = *color;
        light.Specular  = *color * 0.6f;
        light.Position  = *position;
        light.Direction = *direction;
        light.Range        = 1000.0f;
        light.Falloff      = 1.0f;
        light.Attenuation0 = 1.0f;
        light.Attenuation1 = 0.0f;
        light.Attenuation2 = 0.0f;
        light.Theta        = 0.5f;
        light.Phi          = 0.7f;
    
        return light;
    }
    
    D3DMATERIAL9 d3d::InitMtrl(D3DXCOLOR a, D3DXCOLOR d, D3DXCOLOR s, D3DXCOLOR e, float p)
    {
        D3DMATERIAL9 mtrl;
        mtrl.Ambient  = a;
        mtrl.Diffuse  = d;
        mtrl.Specular = s;
        mtrl.Emissive = e;
        mtrl.Power    = p;
        return mtrl;
    }
    
    d3d::BoundingBox::BoundingBox()
    {
        // infinite small 
        _min.x = d3d::INFINITY;
        _min.y = d3d::INFINITY;
        _min.z = d3d::INFINITY;
    
        _max.x = -d3d::INFINITY;
        _max.y = -d3d::INFINITY;
        _max.z = -d3d::INFINITY;
    }
    
    bool d3d::BoundingBox::isPointInside(D3DXVECTOR3& p)
    {
        if( p.x >= _min.x && p.y >= _min.y && p.z >= _min.z &&
            p.x <= _max.x && p.y <= _max.y && p.z <= _max.z )
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    
    d3d::BoundingSphere::BoundingSphere()
    {
        _radius = 0.0f;
    }
    
    bool d3d::DrawBasicScene(IDirect3DDevice9* device, float scale)
    {
        static IDirect3DVertexBuffer9* floor  = 0;
        static IDirect3DTexture9*      tex    = 0;
        static ID3DXMesh*              pillar = 0;
    
        HRESULT hr = 0;
    
        if( device == 0 )
        {
            if( floor && tex && pillar )
            {
                // they already exist, destroy them
                d3d::Release<IDirect3DVertexBuffer9*>(floor);
                d3d::Release<IDirect3DTexture9*>(tex);
                d3d::Release<ID3DXMesh*>(pillar);
            }
        }
        else if( !floor && !tex && !pillar )
        {
            // they don't exist, create them
            device->CreateVertexBuffer(
                6 * sizeof(d3d::Vertex),
                0, 
                d3d::Vertex::FVF,
                D3DPOOL_MANAGED,
                &floor,
                0);
    
            Vertex* v = 0;
            floor->Lock(0, 0, (void**)&v, 0);
    
            v[0] = Vertex(-20.0f, -2.5f, -20.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f);
            v[1] = Vertex(-20.0f, -2.5f,  20.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
            v[2] = Vertex( 20.0f, -2.5f,  20.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f);
    
            v[3] = Vertex(-20.0f, -2.5f, -20.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f);
            v[4] = Vertex( 20.0f, -2.5f,  20.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f);
            v[5] = Vertex( 20.0f, -2.5f, -20.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f);
    
            floor->Unlock();
    
            D3DXCreateCylinder(device, 0.5f, 0.5f, 5.0f, 20, 20, &pillar, 0);
    
            D3DXCreateTextureFromFile(
                device,
                "desert.bmp",
                &tex);
        }
        else
        {
            //
            // Pre-Render Setup
            //
            device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
            device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
            device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
    
            D3DXVECTOR3 dir(0.707f, -0.707f, 0.707f);
            D3DXCOLOR col(1.0f, 1.0f, 1.0f, 1.0f);
            D3DLIGHT9 light = d3d::InitDirectionalLight(&dir, &col);
    
            device->SetLight(0, &light);
            device->LightEnable(0, true);
            device->SetRenderState(D3DRS_NORMALIZENORMALS, true);
            device->SetRenderState(D3DRS_SPECULARENABLE, true);
    
            //
            // Render
            //
    
            D3DXMATRIX T, R, P, S;
    
            D3DXMatrixScaling(&S, scale, scale, scale);
    
            // used to rotate cylinders to be parallel with world's y-axis
            D3DXMatrixRotationX(&R, -D3DX_PI * 0.5f);
    
            // draw floor
            D3DXMatrixIdentity(&T);
            T = T * S;
            device->SetTransform(D3DTS_WORLD, &T);
            device->SetMaterial(&d3d::WHITE_MTRL);
            device->SetTexture(0, tex);
            device->SetStreamSource(0, floor, 0, sizeof(Vertex));
            device->SetFVF(Vertex::FVF);
            device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);
            
            // draw pillars
            device->SetMaterial(&d3d::BLUE_MTRL);
            device->SetTexture(0, 0);
            for(int i = 0; i < 5; i++)
            {
                D3DXMatrixTranslation(&T, -5.0f, 0.0f, -15.0f + (i * 7.5f));
                P = R * T * S;
                device->SetTransform(D3DTS_WORLD, &P);
                pillar->DrawSubset(0);
    
                D3DXMatrixTranslation(&T, 5.0f, 0.0f, -15.0f + (i * 7.5f));
                P = R * T * S;
                device->SetTransform(D3DTS_WORLD, &P);
                pillar->DrawSubset(0);
            }
        }
        return true;
    }
    
    float d3d::GetRandomFloat(float lowBound, float highBound)
    {
        if( lowBound >= highBound ) // bad input
            return lowBound;
    
        // get random float in [0, 1] interval
        float f = (rand() % 10000) * 0.0001f; 
    
        // return float in [lowBound, highBound] interval. 
        return (f * (highBound - lowBound)) + lowBound; 
    }
    
    void d3d::GetRandomVector(
          D3DXVECTOR3* out,
          D3DXVECTOR3* min,
          D3DXVECTOR3* max)
    {
        out->x = GetRandomFloat(min->x, max->x);
        out->y = GetRandomFloat(min->y, max->y);
        out->z = GetRandomFloat(min->z, max->z);
    }
    
    DWORD d3d::FtoDw(float f)
    {
        return *((DWORD*)&f);
    }
    
    float d3d::Lerp(float a, float b, float t)
    {
        return a - (a*t) + (b*t);
    }
    View Code

    camera.cpp

    //////////////////////////////////////////////////////////////////////////////////////////////////
    // 
    // File: camera.cpp
    // 
    // Author: Frank Luna (C) All Rights Reserved
    //
    // System: AMD Athlon 1800+ XP, 512 DDR, Geforce 3, Windows XP, MSVC++ 7.0 
    //
    // Desc: Defines a camera's position and orientation.
    //         
    //////////////////////////////////////////////////////////////////////////////////////////////////
    
    #include "camera.h"
    
    Camera::Camera()
    {
        _cameraType = AIRCRAFT;
    
        _pos   = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
        _right = D3DXVECTOR3(1.0f, 0.0f, 0.0f);
        _up    = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
        _look  = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
    }
    
    Camera::Camera(CameraType cameraType)
    {
        _cameraType = cameraType;
    
        _pos   = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
        _right = D3DXVECTOR3(1.0f, 0.0f, 0.0f);
        _up    = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
        _look  = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
    }
    
    Camera::~Camera()
    {
    
    }
    
    void Camera::getPosition(D3DXVECTOR3* pos)
    {
        *pos = _pos;
    }
    
    void Camera::setPosition(D3DXVECTOR3* pos)
    {
        _pos = *pos;
    }
    
    void Camera::getRight(D3DXVECTOR3* right)
    {
        *right = _right;
    }
    
    void Camera::getUp(D3DXVECTOR3* up)
    {
        *up = _up;
    }
    
    void Camera::getLook(D3DXVECTOR3* look)
    {
        *look = _look;
    }
    
    void Camera::walk(float units)
    {
        // move only on xz plane for land object
        if( _cameraType == LANDOBJECT )
            _pos += D3DXVECTOR3(_look.x, 0.0f, _look.z) * units;
    
        if( _cameraType == AIRCRAFT )
            _pos += _look * units;
    }
    
    void Camera::strafe(float units)
    {
        // move only on xz plane for land object
        if( _cameraType == LANDOBJECT )
            _pos += D3DXVECTOR3(_right.x, 0.0f, _right.z) * units;
    
        if( _cameraType == AIRCRAFT )
            _pos += _right * units;
    }
    
    void Camera::fly(float units)
    {
        // move only on y-axis for land object
        if( _cameraType == LANDOBJECT )
            _pos.y += units;
    
        if( _cameraType == AIRCRAFT )
            _pos += _up * units;
    }
    
    void Camera::pitch(float angle)
    {
        D3DXMATRIX T;
        D3DXMatrixRotationAxis(&T, &_right,    angle);
    
        // rotate _up and _look around _right vector
        D3DXVec3TransformCoord(&_up,&_up, &T);
        D3DXVec3TransformCoord(&_look,&_look, &T);
    }
    
    void Camera::yaw(float angle)
    {
        D3DXMATRIX T;
    
        // rotate around world y (0, 1, 0) always for land object
        if( _cameraType == LANDOBJECT )
            D3DXMatrixRotationY(&T, angle);
    
        // rotate around own up vector for aircraft
        if( _cameraType == AIRCRAFT )
            D3DXMatrixRotationAxis(&T, &_up, angle);
    
        // rotate _right and _look around _up or y-axis
        D3DXVec3TransformCoord(&_right,&_right, &T);
        D3DXVec3TransformCoord(&_look,&_look, &T);
    }
    
    void Camera::roll(float angle)
    {
        // only roll for aircraft type
        if( _cameraType == AIRCRAFT )
        {
            D3DXMATRIX T;
            D3DXMatrixRotationAxis(&T, &_look,    angle);
    
            // rotate _up and _right around _look vector
            D3DXVec3TransformCoord(&_right,&_right, &T);
            D3DXVec3TransformCoord(&_up,&_up, &T);
        }
    }
    
    void Camera::getViewMatrix(D3DXMATRIX* V)
    {
        // Keep camera's axes orthogonal to eachother
        D3DXVec3Normalize(&_look, &_look);
    
        D3DXVec3Cross(&_up, &_look, &_right);
        D3DXVec3Normalize(&_up, &_up);
    
        D3DXVec3Cross(&_right, &_up, &_look);
        D3DXVec3Normalize(&_right, &_right);
    
        // Build the view matrix:
        float x = -D3DXVec3Dot(&_right, &_pos);
        float y = -D3DXVec3Dot(&_up, &_pos);
        float z = -D3DXVec3Dot(&_look, &_pos);
    
        (*V)(0,0) = _right.x; (*V)(0, 1) = _up.x; (*V)(0, 2) = _look.x; (*V)(0, 3) = 0.0f;
        (*V)(1,0) = _right.y; (*V)(1, 1) = _up.y; (*V)(1, 2) = _look.y; (*V)(1, 3) = 0.0f;
        (*V)(2,0) = _right.z; (*V)(2, 1) = _up.z; (*V)(2, 2) = _look.z; (*V)(2, 3) = 0.0f;
        (*V)(3,0) = x;        (*V)(3, 1) = y;     (*V)(3, 2) = z;       (*V)(3, 3) = 1.0f;
    }
    
    void Camera::setCameraType(CameraType cameraType)
    {
        _cameraType = cameraType;
    }
    View Code

    Terrain.cpp

    #include "Terrain.h"
    
    #include <fstream>
    
    const DWORD Terrain::TerrainVertex::FVF = D3DFVF_XYZ | D3DFVF_TEX1;
    
    Terrain::Terrain(IDirect3DDevice9* device, std::string heightmapFileName, 
        int numVertsPerRow, int numVertsPerCol, int cellSpacing, float heightScale)
    {
        _device = device;
        _numVertsPerRow = numVertsPerRow;
        _numVertsPerCol = numVertsPerCol;
        _cellSpacing = cellSpacing;
    
        _numCellsPerRow = _numVertsPerRow - 1;
        _numCellsPerCol = _numVertsPerCol - 1;
    
        _width = _numCellsPerRow * _cellSpacing;
        _depth = _numCellsPerCol * _cellSpacing;
    
        _numVertices = _numVertsPerRow * _numVertsPerCol;
        _numTriangles = _numCellsPerRow * _numCellsPerCol * 2;
    
        _heightScale = heightScale;
    }
    
    void Terrain::draw(D3DXMATRIX* world)
    {
        _device->SetTransform(D3DTS_WORLD, world);
        _device->SetStreamSource(0,_vb,0,sizeof(TerrainVertex));
        _device->SetFVF(TerrainVertex::FVF);
        _device->SetIndices(_ib);
        _device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
        _device->DrawIndexedPrimitive(
                D3DPT_TRIANGLELIST,
                0,0,_numVertices,0,_numTriangles);
        _device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
    }
    
    bool Terrain::computeVertices()
    {
        HRESULT  hr = 0;
        hr = _device->CreateVertexBuffer(_numVertices * sizeof(TerrainVertex),
            D3DUSAGE_WRITEONLY, TerrainVertex::FVF, D3DPOOL_MANAGED, &_vb, 0);
    
        int startX = -_width / 2;
        int startZ =  _depth / 2;
    
        int endX =  _width / 2;
        int endZ = -_depth / 2;
    
        float uCoordIncrementSize = 1.0f / (float)_numCellsPerRow;
        float vCoordIncrementSize = 1.0f / (float)_numCellsPerCol;
    
        TerrainVertex* v = 0;
        _vb->Lock(0,0,(void**)&v,0);
        int i=0;
        for(int z=startZ;z>=endZ;z-=_cellSpacing)
        {
            int j=0;
          for(int x = startX; x<=endX; x += _cellSpacing)
          {
            int index=i*_numVertsPerRow+j;
              v[index]=TerrainVertex((float)x,
                                 (float)_heightmap[index],
                                 (float)z,
                                 (float)j*uCoordIncrementSize,
                                 (float)i*uCoordIncrementSize);
          
          }
        }
        _vb->Unlock();
        return true;
    }
    
    bool Terrain::computeIndices()
    {
        HRESULT hr = 0;
    
        hr = _device->CreateIndexBuffer(
            _numTriangles * 3 * sizeof(DWORD),
            D3DUSAGE_WRITEONLY,
            D3DFMT_INDEX16,
            D3DPOOL_MANAGED,
            &_ib,
            0);
    
        if(FAILED(hr))
            return false;
    
        WORD* indices = 0;
        _ib->Lock(0,0,(void**)&indices,0);
    
        int baseIndex = 0;
        for(int i=0; i<_numCellsPerCol; i++)
        {
            for(int j=0; j<_numCellsPerRow; j++)
            {
                indices[baseIndex]    =    i * _numVertsPerRow + j;
                indices[baseIndex+1]=    i * _numVertsPerRow + j + 1;
                indices[baseIndex+2]=(i+1) * _numVertsPerRow + j;
                
                indices[baseIndex+3]=(i+1) * _numVertsPerRow + j;
                indices[baseIndex+4]=    i * _numVertsPerRow + j + 1;
                indices[baseIndex+5]=(i+1) * _numVertsPerRow + j + 1;
    
                baseIndex += 6;
            }
        }
    
        _ib->Unlock();
        return true;
    }
    
    bool Terrain::readRawFile(std::string fileName)
    {
        std::vector<BYTE> in(_numVertices);
        std::ifstream inFile(fileName.c_str(), std::ios_base::binary);
        if(inFile == 0)
            return false;
        inFile.read((char*)&in[0], in.size());
        inFile.close();
    
        _heightmap.resize(_numVertices);
        for(int i=0; i<in.size(); i++)
            _heightmap[i] = in[i];
        return true;
    }
    Terrain::~Terrain(void)
    {
    }
    View Code

    demo.cpp

    #include "d3dUtility.h"
    #include "camera.h"
    #pragma comment(lib,"winmm.lib") 
    #pragma comment(lib,"d3d9.lib")
    #pragma comment(lib,"d3dx9.lib")
    #pragma comment(lib, "dinput8.lib") 
    #pragma comment(lib,"dxguid.lib")
    
    //第1步:添加terrain.h头文件
    #include "Terrain.h"
    
    //
    // Globals
    //
    
    IDirect3DDevice9* Device = 0; 
    
    const int Width  = 640;
    const int Height = 480;
    
    Camera   TheCamera(Camera::LANDOBJECT);
    
    //第2步 定义地形对象变量
    Terrain* TheTerrain=0;
    //
    // Framework Functions
    //
    bool Setup()
    {
    
        D3DXVECTOR3 lightDirection(0.0f, 1.0f, 0.0f);
    
        //第3步,实例化地形对象
        TheTerrain=new Terrain(Device,"coastMountain64.raw",64,64,10,0.5f);
        //
        // Set texture filters.
        //
    
        Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
        Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
        Device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
    
        //
        // Set projection matrix.
        //
    
        D3DXMATRIX proj;
        D3DXMatrixPerspectiveFovLH(
                &proj,
                D3DX_PI * 0.25f, // 45 - degree
                (float)Width / (float)Height,
                1.0f,
                1000.0f);
        Device->SetTransform(D3DTS_PROJECTION, &proj);
    
        return true;
    }
    
    void Cleanup()
    {
    
    }
    
    bool Display(float timeDelta)
    {
        //
        // Update the scene:
        //
    
        if( Device )
        {
            if( ::GetAsyncKeyState(VK_UP) & 0x8000f )
                TheCamera.walk(100.0f * timeDelta);
    
            if( ::GetAsyncKeyState(VK_DOWN) & 0x8000f )
                TheCamera.walk(-100.0f * timeDelta);
    
            if( ::GetAsyncKeyState(VK_LEFT) & 0x8000f )
                TheCamera.yaw(-1.0f * timeDelta);
            
            if( ::GetAsyncKeyState(VK_RIGHT) & 0x8000f )
                TheCamera.yaw(1.0f * timeDelta);
    
            if( ::GetAsyncKeyState('N') & 0x8000f )
                TheCamera.strafe(-100.0f * timeDelta);
    
            if( ::GetAsyncKeyState('M') & 0x8000f )
                TheCamera.strafe(100.0f * timeDelta);
    
            if( ::GetAsyncKeyState('W') & 0x8000f )
                TheCamera.pitch(1.0f * timeDelta);
    
            if( ::GetAsyncKeyState('S') & 0x8000f )
                TheCamera.pitch(-1.0f * timeDelta);
    
            D3DXVECTOR3 pos;
            TheCamera.getPosition(&pos);
    
            
            TheCamera.setPosition(&pos);
    
            D3DXMATRIX V;
            TheCamera.getViewMatrix(&V);
            Device->SetTransform(D3DTS_VIEW, &V);
    
            //
            // Draw the scene:
            //
    
            Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff000000, 1.0f, 0);
            Device->BeginScene();
            D3DXMATRIX I;
            D3DXMatrixIdentity(&I);
            TheTerrain->draw(&I);
            Device->EndScene();
            Device->Present(0, 0, 0, 0);
        }
        return true;
    }
    
    //
    // WndProc
    //
    LRESULT CALLBACK d3d::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        switch( msg )
        {
        case WM_DESTROY:
            ::PostQuitMessage(0);
            break;
            
        case WM_KEYDOWN:
            if( wParam == VK_ESCAPE )
                ::DestroyWindow(hwnd);
            break;
        }
        return ::DefWindowProc(hwnd, msg, wParam, lParam);
    }
    
    //
    // WinMain
    //
    int WINAPI WinMain(HINSTANCE hinstance,
                       HINSTANCE prevInstance, 
                       PSTR cmdLine,
                       int showCmd)
    {
        if(!d3d::InitD3D(hinstance,
            Width, Height, true, D3DDEVTYPE_HAL, &Device))
        {
            ::MessageBox(0, "InitD3D() - FAILED", 0, 0);
            return 0;
        }
            
        if(!Setup())
        {
            ::MessageBox(0, "Setup() - FAILED", 0, 0);
            return 0;
        }
    
        d3d::EnterMsgLoop( Display );
    
        Cleanup();
    
        Device->Release();
    
        return 0;
    }
    View Code
  • 相关阅读:
    免费的编程中文书籍索引【转】
    Linux字符集的查看及修改【转】
    expect学习笔记及实例详解【转】
    mycat学习笔记
    Vue-loader 开启压缩后的一些坑
    使用webpack搭建vue开发环境
    基于webpack和vue.js搭建开发环境
    Sublime Text 3 常用插件以及安装方法(vue 插件)
    NodeJS、NPM安装配置步骤(windows版本)
    Https方式使用Git@OSC设置密码的方式
  • 原文地址:https://www.cnblogs.com/szmtjs10/p/16305001.html
Copyright © 2020-2023  润新知