[Aportes indexados] Camara y Terreno 3D DX9

Estado
Cerrado para nuevas respuestas.

Mannakia

Programador
Ex-Staff
Bueno, basicamente lo que les vengo a aportar es un proyecto en VC++ 2008. Pero como me da paja subir(y como no usa resource) voy a aportarle el codigo.

Esta base será para los siguientes aportes que voy a hacer(aun esto no está comentado).
Lo hice hoy y apurado por ver resultados. Es poreso que no está comentado.

Deben tener configurado los directorios de includes y libs hacia el SDK de dx9. Y luego linkear las siguientes librerías.
d3d9.lib
d3dx9.lib
dinput8.lib
dxguid.lib

A continuacion dejo los headers( .h file's).
cApp.h
C++:
#ifndef _H_APP
#define _H_APP
    #include "main.h"
    #include "cTerrain.h"
    #include "cCamera.h"
    #include "cInput.h"
    #include "cTime.h"
 
    class cApp{
        public:
            cApp(HWND hWnd, unsigned int width, unsigned int height);
            ~cApp();
            
            void nextFrame();
            bool ending(){return m_end;};
            void exit(){ m_end = true;};
 
            cTerrain *getTerrain(){return mTerrain;};
            cCamera *getCamera(){return mCamera;};
            cInput *getInput(){return mInput;};
            cTime *getTime(){return mTime;};
 
 
        private:
            HWND m_hwnd;
            unsigned int m_width, m_height;
 
            LPDIRECT3D9 d3d;
            LPDIRECT3DDEVICE9 d3ddev;
 
            cTerrain *mTerrain;
            cCamera *mCamera;
            cInput *mInput;
            cTime *mTime;
            
            bool m_end;
 
    };
 
#endif
cTime.h
C++:
#ifndef _H_TIME
#define _H_TIME
    #include "main.h"
 
    class cTime{
        public:
            cTime(){
                LARGE_INTEGER li;
                QueryPerformanceFrequency(&li);
                m_PCFreq = double(li.QuadPart)/1000.0;
            };
 
            void refresh(){
                LARGE_INTEGER li;
                QueryPerformanceCounter(&li);
                m_ElapsedTime = double(li.QuadPart-m_CounterStart)/m_PCFreq;
 
                m_CounterStart = li.QuadPart;
                m_TicksDouble += m_ElapsedTime;
                m_Ticks = static_cast<int>(m_TicksDouble);
                m_GameTime = static_cast<float>(m_ElapsedTime) * 0.2f;
            };
 
            int getTimeTick(){return m_Ticks;};
            double getTimeElapsed(){ return m_ElapsedTime;};
            float getGameTime(){return m_GameTime;};
 
        private:
            double m_PCFreq;
            __int64 m_CounterStart;
            double m_ElapsedTime;
            int m_Ticks;
            double m_TicksDouble;
            float m_GameTime;
 
            int m_fps, m_fpsTick;
    };
#endif
cCamera.h
C++:
#ifndef _H_CAMERA
#define _H_CAMERA
    #include "main.h"
    
    class cCamera{
        public:
            cCamera(LPDIRECT3DDEVICE9 d3ddev);
            ~cCamera();
            
            void update();
 
        private:
            float m_x,m_y,m_z;
            float m_angle, m_angleconv, m_pitch;
 
            LPDIRECT3DDEVICE9 d3ddev;
            D3DXMATRIX matBillboardMatrix;
 
    };
#endif
 
cInput.h
C++:
#ifndef _H_INPUT
#define _H_INPUT
    #include "main.h"
    #include <dinput.h>
 
    class cInput{
        public:
            cInput(HWND hwnd);
            ~cInput();
 
            void refresh();
            bool isPressed(int k);
            
            float getVarX();
            float getVarY();
 
        private:
            LPDIRECTINPUT8 m_DI;
            LPDIRECTINPUTDEVICE8 m_DIDK;
            LPDIRECTINPUTDEVICE8 m_DIDM;
 
            DIMOUSESTATE2        m_mouse;
            char m_keys[256];
            
    };
#endif
main.h
C++:
#ifndef _H_MAIN
#define _H_MAIN
    #include <d3d9.h>
    #include <d3dx9.h>
    #include <windows.h>
    #include <windowsx.h>
#endif

Ahora los sources
main.cpp
C++:
#include "cApp.h"
 
cApp *mApp;
 
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600
 
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
 
 
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 = WindowProc;
    wc.hInstance = hInstance;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.lpszClassName = L"WindowClass";
 
    RegisterClassEx(&wc);
 
    hWnd = CreateWindowEx(NULL, L"WindowClass", L"Directx9 Test!!",
                          WS_OVERLAPPEDWINDOW, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT,
                          NULL, NULL, hInstance, NULL);
 
    ShowWindow(hWnd, nCmdShow);
 
    mApp = new cApp(hWnd, SCREEN_WIDTH, SCREEN_HEIGHT);
 
    MSG msg;
 
    while(!(mApp->ending()))
    {
        while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
 
        if(msg.message == WM_QUIT)
            break;
 
        mApp->nextFrame();
 
        if (mApp->getInput()->isPressed(DIK_ESCAPE)) mApp->exit();
    }
    
    delete mApp;
 
    return msg.wParam;
}
 
 
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
        case WM_DESTROY:
            {
                PostQuitMessage(0);
                return 0;
            } break;
    }
 
    return DefWindowProc (hWnd, message, wParam, lParam);
}
 
cTerrain.cpp
C++:
#include "cTerrain.h"
 
struct CUSTOMVERTEX {FLOAT X, Y, Z;};
#define CUSTOMFVF (D3DFVF_XYZ)
 
cTerrain::cTerrain(LPDIRECT3DDEVICE9 dev, int wx, int hz){
    
    CUSTOMVERTEX *v_vterrain;
    v_vterrain = new CUSTOMVERTEX[wx * hz];
 
    CUSTOMVERTEX *vertex;
    int indexOffset;
    int s = 1;
    short int   *pIndices;
    unsigned int    Index;
    float yz;
 
    x_terrain = wx;
    z_terrain = hz;
 
    d3ddev = dev;
        
    d3ddev->CreateVertexBuffer(wx * hz * sizeof(CUSTOMVERTEX),
                               0,
                               CUSTOMFVF,
                               D3DPOOL_MANAGED,
                               &v_terrain,
                               NULL);
 
 
    v_terrain->Lock(0, 0, (void**)&v_vterrain, 0);
 
        for (int z = 0; z < hz; z++){
            for (int x = 0; x < wx;x++){
                indexOffset = x + (z * wx);
                vertex = &(v_vterrain[indexOffset]);
                
                
                vertex->X = static_cast<float>(x * s);
                yz = static_cast<float>(z) - 10.0f;
                
                vertex->Y = (yz * yz) / 50.0f;
                vertex->Z = static_cast<float>(z * s);
            }
        }
 
    v_terrain->Unlock();
 
    ni_terrain = ((wx * 2) + 2) * (hz - 1);
    np_terrain = ( (x_terrain + 1) * (z_terrain - 1) * 2 ) - 2;
    nv_terrain = wx * hz;
 
    indexOffset = 0;
    
    d3ddev->CreateIndexBuffer(ni_terrain * sizeof(short int),
                              0,
                              D3DFMT_INDEX16,
                              D3DPOOL_MANAGED,
                              &i_terrain,
                              NULL);
 
    i_terrain->Lock( 0, 0,  (void**)&pIndices, 0 );
 
    int iMax = 0;
 
    for( int z = 0; z < hz - 1; z++ ){
        for( int x = 0; x < wx; x++ )
        {
            Index = x + ( z * x_terrain ); 
            pIndices[indexOffset] = (WORD)Index;
            indexOffset++;
            Index = x +( (z+1) * x_terrain ); 
            pIndices[indexOffset] =(WORD)Index;
            indexOffset++;
        }
 
        pIndices[indexOffset] =(WORD)Index;
        indexOffset++;
 
        Index = 0 + ( (z+1) * x_terrain );
        pIndices[indexOffset] = (WORD)Index;
        indexOffset++;
    }
 
    i_terrain->Unlock();
}
 
void cTerrain::render(){
    d3ddev->SetFVF(CUSTOMFVF);
    d3ddev->SetStreamSource( 0, v_terrain,0, sizeof(CUSTOMVERTEX) );
    d3ddev->SetIndices(i_terrain);
 
    d3ddev->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP, 0, 0, nv_terrain, 0, np_terrain);
}
 
cTerrain::~cTerrain(){
    i_terrain->Release();
    v_terrain->Release();
}
cApp.cpp
C++:
#include "cApp.h"
 
cApp::cApp(HWND hWnd, unsigned int width, unsigned int height){
    d3d = Direct3DCreate9(D3D_SDK_VERSION);
    m_hwnd = hWnd;
    m_width = width;
    m_height = height;
 
    D3DPRESENT_PARAMETERS d3dpp;
 
    ZeroMemory(&d3dpp, sizeof(d3dpp));
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.hDeviceWindow = hWnd;
    d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
    d3dpp.BackBufferWidth = width;
    d3dpp.BackBufferHeight = height;
    d3dpp.EnableAutoDepthStencil = TRUE;
    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
 
    d3d->CreateDevice(D3DADAPTER_DEFAULT,
                      D3DDEVTYPE_HAL,
                      hWnd,
                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                      &d3dpp,
                      &d3ddev);
 
    mTerrain = new cTerrain(d3ddev, 30,30);
    mCamera = new cCamera(d3ddev);
    mInput = new cInput(hWnd);
    mTime = new cTime();
 
    d3ddev->SetRenderState(D3DRS_LIGHTING, FALSE);    // turn on the 3D lighting
    d3ddev->SetRenderState(D3DRS_ZENABLE, TRUE);
    d3ddev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
    d3ddev->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
 
    m_end = false;
}
 
cApp::~cApp(){
    d3ddev->Release();
    d3d->Release();
    delete mTerrain;
    delete mCamera;
    delete mInput;
    delete mTime;
}
 
void cApp::nextFrame(){
    static int ma = 32;
 
    d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
    d3ddev->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
 
    d3ddev->BeginScene();
        mTime->refresh();
        mInput->refresh();
 
        mCamera->update();
 
        mTerrain->render();
 
    d3ddev->EndScene(); 
 
    d3ddev->Present(NULL, NULL, NULL, NULL);
}
cInput.cpp
C++:
#include "cInput.h"
 
cInput::cInput(HWND hWnd){
    m_DI = NULL;
 
    DirectInput8Create(GetModuleHandle(NULL),
                             DIRECTINPUT_VERSION,
                             IID_IDirectInput8,
                             (void**)&m_DI,
                             NULL);
 
    m_DI->CreateDevice(GUID_SysKeyboard,
                             &m_DIDK,
                             NULL);
    
    m_DIDK->SetDataFormat(&c_dfDIKeyboard);
    m_DIDK->SetCooperativeLevel(hWnd,DISCL_BACKGROUND | DISCL_NONEXCLUSIVE);
    m_DIDK->Acquire();
 
    m_DI->CreateDevice(GUID_SysMouse,
                        &m_DIDM, NULL);
    m_DIDM->SetDataFormat(&c_dfDIMouse2);
    m_DIDM->SetCooperativeLevel(hWnd,DISCL_BACKGROUND | DISCL_NONEXCLUSIVE);
    m_DIDM->Acquire();
}
 
cInput::~cInput(){
    if (!(m_DIDK == NULL)){
        m_DIDK->Acquire();
        m_DIDK->Release();
        m_DIDK = NULL;
    }
 
    if (!(m_DIDM == NULL)){
        m_DIDM->Acquire();
        m_DIDM->Release();
        m_DIDM = NULL;
    }
 
    if (!(m_DI == NULL)){
        m_DI->Release();
        m_DI = NULL;
    }
}
 
void cInput::refresh(){
    m_DIDK->GetDeviceState(sizeof(m_keys), (LPVOID)&m_keys);
    m_DIDM->GetDeviceState(sizeof(m_mouse),(LPVOID)&m_mouse);
}
 
bool cInput::isPressed(int k){
    if (m_keys[k] & 0x80)
        return true;
    else
        return false;
}
 
float cInput::getVarX(){
    return static_cast<float>(m_mouse.lX);
}
 
float cInput::getVarY(){
    return static_cast<float>(m_mouse.lY);
}
cCamera.cpp
C++:
#include "cApp.h"
#include "cCamera.h"
#include <math.h>
 
#define g_pi 3.141592653f // PI?? jaja
#define g_90d g_pi / 2 // 90 degrees in radians
#define g_180d g_pi // 180 degrees in radians
#define g_270d (g_pi / 2) * 3 // 270 degrees in radians
#define g_360d g_pi * 2 // 360 degrees in radians
 
extern cApp *mApp;
 
cCamera::cCamera(LPDIRECT3DDEVICE9 dev){
    d3ddev = dev;
    m_x = m_y = m_z = 0.0f;
    m_angle = m_pitch = m_angleconv = 0.0f;
}
 
cCamera::~cCamera(){
 
}
 
void cCamera::update(){
    D3DXMATRIX matView, matRotation, matPitch, matLook, matPos, matProj;
 
    cInput &in = *(mApp->getInput());
    cTime &time = *(mApp->getTime());
    
    m_angle = m_angle - (in.getVarX() * 0.0005f * time.getGameTime());
    m_pitch = m_pitch - (in.getVarY() * 0.0005f * time.getGameTime());
      
    if (m_pitch < -1.5f) m_pitch = -1.5f;
    if (m_pitch > 1.5f) m_pitch = 1.5f;
 
    if (in.isPressed(DIK_W)){
        m_x += (0.01f * sin(m_angleconv) * time.getGameTime());
        m_z += (0.01f * cos(m_angleconv) * time.getGameTime());
    }
 
    if (in.isPressed(DIK_S)){
        m_x -= (0.01f * sin(m_angleconv) * time.getGameTime());
        m_z -= (0.01f * cos(m_angleconv) * time.getGameTime());
    }
 
    if (in.isPressed(DIK_LEFT)){
        m_angle += (g_90d / 180.0f) * time.getGameTime();
        if (m_angle < 0) m_angle = g_360d - (-m_angle);
    }
 
    if (in.isPressed(DIK_RIGHT)){
        m_angle -= (g_90d / 180.0f) * time.getGameTime();
        if (m_angle > g_360d ) m_angle = 0 + (m_angle - g_360d);
    }
 
    if (in.isPressed(DIK_A)){
        m_x += (0.01f * sin(m_angleconv - g_90d) * time.getGameTime());
        m_z += (0.01f * cos(m_angleconv - g_90d) * time.getGameTime());
    }
 
    if (in.isPressed(DIK_D)){
        m_x += (0.01f * sin(m_angleconv + g_90d) * time.getGameTime());
        m_z += (0.01f * cos(m_angleconv + g_90d) * time.getGameTime());
    }
 
    float yz = static_cast<float>(m_z) - 10.0f;
    m_y = (yz * yz) / 50.0f + 1.0f;
 
    m_angleconv = g_360d - m_angle;
 
    D3DXMatrixIdentity(&matView);
    D3DXMatrixIdentity(&matPos);
    D3DXMatrixIdentity(&matRotation);
    D3DXMatrixIdentity(&matLook);
    D3DXMatrixIdentity(&matProj);
    
    D3DXMatrixRotationY(&matRotation, m_angle);
    D3DXMatrixRotationX(&matPitch, m_pitch);
  
    D3DXMatrixMultiply(&matLook, &matRotation, &matPitch);
    D3DXMatrixTranslation(&matPos, -m_x, -m_y, -m_z);
    D3DXMatrixMultiply(&matView, &matPos, &matLook);
 
    d3ddev->SetTransform(D3DTS_VIEW, &matView);
 
    D3DXMatrixRotationY(&matBillboardMatrix, -m_angle);
 
    D3DXMatrixPerspectiveFovLH(&matProj, g_pi / 4.0f,1.0f, 1.0f, 100.0f);
    d3ddev->SetTransform(D3DTS_PROJECTION, &matProj);
 
}

Pocas cosas he extraído de ejemplos, la mayoría recodeado por mi. Fue mas algo que hice en el día para introducirme de nuevo a este area.

Saludos

EDIT: Una pequeña imagen.


Bueno, el terreno con altura es generado con una función cuadratica(parabolica). Fue simplemente de prueba. Luego podría ser heightmap
 
Estado
Cerrado para nuevas respuestas.
Arriba