Diff for "MishaKoshelev"

Differences between revisions 10 and 11

Deletions are marked like this. Additions are marked like this.
Line 33: Line 33:
This is taken, with some modifications, from [www.directxtutorial.com www.directxtutorial.com], specifically from [http://www.directxtutorial.com/Tutorial9/B-Direct3DBasics/dx9B7.aspx Direct3D Basics Lesson 7: Simple Modeling]. This is taken, with some modifications, from http://www.directxtutorial.com, specifically from [http://www.directxtutorial.com/Tutorial9/B-Direct3DBasics/dx9B7.aspx Direct3D Basics Lesson 7: Simple Modeling].
Line 208: Line 208:
Line 285: Line 284:
== Texts ==

I (MishaKoshelev) highly recommend the following free online book
= References =

== Books ==

I (["MishaKoshelev"]) highly recommend the following free online book
Line 290: Line 291:
Additional resources I (MishaKoshelev) have used are: Additional resources I (["MishaKoshelev"]) have used are:

Index

1. Objectives

This page aims to be a concise introduction for those wishing to start D3DX9 development with Wine.

2. Getting started

2.1. Download and unzip the DirectX SDK

This is available from the DirectX Developer Center.

As of July 28th, 2010, the EXE file downloaded is a self-extracting executable compressed in the CAB format.

To extract this file to the dxsdk subdirectory within the current directory:

mkdir dxsdk
cd dxsdk
cabextract /path/to/DXSDK_Jun10.exe

2.2. Download and install the mingw32 compiler

This compiler is readily available on some systems, such as Ubuntu 10.04 amd64. On this operating system, you can install as follows:

sudo aptitude install mingw32

2.3. Create a tester program

This is taken, with some modifications, from http://www.directxtutorial.com, specifically from Direct3D Basics Lesson 7: Simple Modeling.

Type:

gedit tester.cpp

then copy and paste the following into the window that appears:

// include assert.h for easy debugging
#include <assert.h>

// include the basic windows header files and the Direct3D header file
#include <windows.h>
#include <windowsx.h>
#include <d3d9.h>
#include <d3dx9.h>

// define the screen resolution
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600

// include the Direct3D Library files
#pragma comment (lib, "d3d9.lib")
#pragma comment (lib, "d3dx9.lib")

// global declarations
LPDIRECT3D9 d3d;
LPDIRECT3DDEVICE9 d3ddev;
// !!! Declare any relevant global variables (meshes, etc.) here

// function prototypes
void initD3D(HWND hWnd);
void render_frame(void);
void cleanD3D(void);
void init_graphics(void);

// 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 = WindowProc;
    wc.hInstance = hInstance;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.lpszClassName = "WindowClass";

    RegisterClassEx(&wc);

    hWnd = CreateWindowEx(NULL, "WindowClass", "Our Direct3D Program",
                          WS_OVERLAPPEDWINDOW, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT,
                          NULL, NULL, hInstance, NULL);

    ShowWindow(hWnd, nCmdShow);

    initD3D(hWnd);

    MSG msg;

    while(TRUE)
    {
        while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        if(msg.message == WM_QUIT)
            break;

        render_frame();
    }

    cleanD3D();

    return msg.wParam;
}

// this is the main message handler for the program
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);
}

// 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 = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.hDeviceWindow = hWnd;
    d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
    d3dpp.BackBufferWidth = SCREEN_WIDTH;
    d3dpp.BackBufferHeight = SCREEN_HEIGHT;
    d3dpp.EnableAutoDepthStencil = TRUE;
    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;

    d3d->CreateDevice(D3DADAPTER_DEFAULT,
                      D3DDEVTYPE_HAL,
                      hWnd,
                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                      &d3dpp,
                      &d3ddev);

    init_graphics();

    d3ddev->SetRenderState(D3DRS_LIGHTING, FALSE);    // turn off the 3D lighting
    d3ddev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);    // turn off culling
    d3ddev->SetRenderState(D3DRS_ZENABLE, TRUE);    // turn on the z-buffer
}

// this is the function used to render a single frame
void render_frame(void)
{
    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();

    // set the view transform
    D3DXMATRIX matView;    // the view transform matrix
    D3DXVECTOR3 camera_position(0.0f, 8.0f, 25.0f),    // the camera position
        camera_lookat_position(0.0f, 0.0f, 0.0f),      // the look-at position
        camera_up_direction(0.0f, 1.0f, 0.0f);    // the up direction
    D3DXMatrixLookAtLH(&matView,
                       &camera_position,
                       &camera_lookat_position,
                       &camera_up_direction);
    d3ddev->SetTransform(D3DTS_VIEW, &matView);    // set the view transform to matView

    // set the projection transform
    D3DXMATRIX matProjection;    // the projection transform matrix
    D3DXMatrixPerspectiveFovLH(&matProjection,
                               D3DXToRadian(45),    // the horizontal field of view
                               (FLOAT)SCREEN_WIDTH / (FLOAT)SCREEN_HEIGHT, // aspect ratio
                               1.0f,   // the near view-plane
                               100.0f);    // the far view-plane
    d3ddev->SetTransform(D3DTS_PROJECTION, &matProjection); // set the projection

    // set the world transform
    static float index = 0.0f; index+=0.03f; // an ever-increasing float value
    D3DXMATRIX matRotateY;    // a matrix to store the rotation for each triangle
    D3DXMatrixRotationY(&matRotateY, index);    // the rotation matrix
    d3ddev->SetTransform(D3DTS_WORLD, &(matRotateY));    // set the world transform

    // !!! DRAWING CODE GOES HERE

    d3ddev->EndScene(); 

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

// this is the function that cleans up Direct3D and COM
void cleanD3D(void)
{
    // !!! Release relevant global variables here
    d3ddev->Release();
    d3d->Release();
}

// this is the function that puts the 3D models into video RAM
void init_graphics(void)
{
    // !!! SET UP FOR DRAWING CODE GOES HERE
    // (e.g., creating index and vertex buffers, creating a mesh, testing a D3DX function, etc.)

    // !!! My personal preference for debugging is to include statements such as
    // if (!SUCCEEDED(D3DX...))
    //    assert(FALSE);
    // that way, you will quickly see where your code fails if it indeed does (you will
    // get a line number).

    // !!! If you do not need a graphics display and are just testing a D3DX function, feel free to
    // uncomment the following line to terminate execution after you have tested your function.
    // 
    // assert(FALSE);
}

Now save the file as tester.cpp and quit. Note that the parts you may wish to modify are marked with triple exclamation points (!!!).

2.4. Compile the tester program

Once you have installed mingw32, you can use the following script to compile the tester.cpp program above.

Again, type:

gedit compile

then copy and paste the following code into the window that appears:

#!/bin/bash
rm tester.exe > /dev/null 2>&1
i586-mingw32msvc-g++ tester.cpp -o tester.exe -fcheck-new -Idxsdk/DXSDK/Include -ld3d9 dxsdk/DXSDK/Lib/x86/d3dx9.lib

Save and quit, then make the file executable:

chmod +x tester

Finally, to compile your program (after you have made appropriate modifications), type:

./compile

2.5. Testing the program in a VMWare installation

This is beyond the scope of this page, but my (MishaKoshelev) personal preference is to test my code on an actual Windows XP system running in VMWare.

I use the "Shared Folders" feature available in some VMWare products to do this. Alternately, one can set up SAMBA sharing and use the free VMWare Server product. However, this is beyond the scope of this tutorial.

Assuming you have Windows running within VMWare on your computer, I (MishaKoshelev) have found some quirks with Virtual Folder caching and prefer to use the following script to run my tester program. Specifically, by removing the tester program on Windows after execution, this makes sure that I am always running the most up-to-date version of my program. Type:

gedit test.bat

copy and paste the following into the window that opens:

@echo off
tester
del tester.exe

Save the file as test.bat and quit.

Now, to test on your Windows virtual machine, you can simply type:

cd \path\to\shared\folder
test

3. References

3.1. Books

I (MishaKoshelev) highly recommend the following free online book The Direct3D Graphics Pipeline by Richard Atwater Thomson.

Additional resources I (MishaKoshelev) have used are:

3.2. Mailing Lists

Two potentially helpful mailing lists for D3DX9 questions, besides, of course, wine-devel are:

  • DIRECTXDEV. Richard Atwater Thomson is very active here, and a great resource.

  • sweng-gamedev. Another list which I was recommended.

MishaKoshelev (last edited 2010-07-28 19:34:05 by MishaKoshelev)