1
votes

I have just begun my directx c++ tutorial and I finally drew triangle, but whenever I try to transform it, by any matrix, that never works although I followed the tutorial step by step and I also looked for it in the MSDN tutorial, but I didn't figure out the problem, here's the full code:

main.cpp:

        #include <windows.h>
        #include <d3d9.h>
        #include <d3dx9.h>
        #include "define.h"

        LRESULT WINAPI WndProc( HWND, UINT, WPARAM, LPARAM );

        int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow )
        {

                HICON icon;
                icon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_APP_ICON));

                WNDCLASS wc;
                wc.cbClsExtra = 0;
                wc.cbWndExtra = 0;
                wc.hbrBackground = (HBRUSH)NULL;
                wc.hCursor = LoadCursor(hInst, IDC_ARROW);
                wc.hIcon = icon;
                wc.hInstance = hInst;
                wc.lpfnWndProc = WndProc;
                wc.lpszClassName = "Window Class";
                wc.lpszMenuName = NULL;
                wc.style = CS_VREDRAW | CS_HREDRAW;

                RegisterClass( &wc );

                HWND hWnd = CreateWindow("Window Class", "D3D Tutorial 01: CreateDevice",
                                       WS_OVERLAPPEDWINDOW, 0, 0, 1440, 900,
                                      NULL, NULL, hInst, NULL );


                ShowWindow( hWnd, SW_NORMAL);
                initD3D(hWnd);
                initGraphics();
                Render();

                MSG msg;
          // Check to see if any messages are waiting in the queue

                while(GetMessage(&msg, NULL, 0, 0))
                {
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }

                return 0;
        }

        LRESULT WINAPI WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
        {
            switch( msg )
            {

                case WM_KEYDOWN:
                    {
                        if(wParam == 0x51)
                            PostQuitMessage(1);
                            return 0;
                            break;
                    }

                case WM_DESTROY:
                    {
                    PostQuitMessage(0);
                    clearD3D();
                    return 1;
                    break;
                    }

            default:
            {
                return DefWindowProc( hWnd, msg, wParam, lParam );
            }
        }
        }

        void initD3D(HWND hwnd)
        {

        d3d = Direct3DCreate9(D3D_SDK_VERSION);

        D3DPRESENT_PARAMETERS d3dparams;

        ZeroMemory(&d3dparams, sizeof(D3DPRESENT_PARAMETERS));
        d3dparams.hDeviceWindow = hwnd;
        d3dparams.Windowed = FALSE;
        d3dparams.BackBufferFormat = D3DFMT_A8R8G8B8;
        d3dparams.BackBufferHeight = 900;
        d3dparams.BackBufferWidth = 1440;
        d3dparams.SwapEffect = D3DSWAPEFFECT_FLIP;

        d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_NOWINDOWCHANGES, &d3dparams, &d3ddevice);

        d3ddevice->SetRenderState(D3DRS_LIGHTING, FALSE);

        }

        void Render()
        {

            // clear the window to a deep blue
            d3ddevice->Clear(NULL, 0, D3DCLEAR_TARGET, D3DCOLOR_ARGB(255, 20, 40, 100), 1.0f, 0);

            d3ddevice->BeginScene();    // begins the 3D scene

            // do 3D rendering on the back buffer here

            d3ddevice->SetFVF(FVFcode);

            D3DXMatrixIdentity(&matrix);
            D3DXMatrixTranslation(&matrix, 900, 0, 0);
            d3ddevice->SetTransform(D3DTS_WORLD, &matrix);

            D3DXMATRIX out;
            D3DXVECTOR3 eye(2,3,3);
            D3DXVECTOR3 Lat(0,0,0);
            D3DXVECTOR3 up(0,1,0);
            D3DXMatrixLookAtLH(&out, &eye, &Lat, &up);

            d3ddevice->SetTransform(D3DTS_VIEW, &out);

            D3DXMATRIX pro;

            D3DXMatrixPerspectiveFovLH(&pro,
                                       D3DXToRadian(45),    // the horizontal field of view
                                       (FLOAT)1440 / (FLOAT)900, // aspect ratio
                                       1.0f,    // the near view-plane
                                       100.0f);    // the far view-plane

            d3ddevice->SetTransform(D3DTS_PROJECTION, &pro);


            d3ddevice->SetStreamSource(0, v_buffer, 0, sizeof(vertex));
            d3ddevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);


            d3ddevice->EndScene();    // ends the 3D scene

            d3ddevice->Present(NULL, NULL, NULL, NULL);   // displays the created frame on the screen
        }

        void initGraphics()
        {

        vertex v [] =
            {{320.0f, 50.0f, 1.0f, 1.0f, D3DCOLOR_XRGB(0, 0, 255)},
            {520.0f, 400.0f, 1.0f, 1.0f, D3DCOLOR_XRGB(0, 255, 0)},
            {120.0f, 400.0f, 1.0f, 1.0f, D3DCOLOR_XRGB(255, 0, 0)},
        };
        d3ddevice->CreateVertexBuffer( 3*sizeof(vertex), 0, FVFcode, D3DPOOL_DEFAULT, &v_buffer, NULL );

        VOID* pVoid;
        v_buffer->Lock(0, 0, (void**)&pVoid, 0);
        CopyMemory(pVoid, v, sizeof(v));
        v_buffer->Unlock();

        }

define.h:

        #ifndef DEFINE_H_INCLUDED
        #define DEFINE_H_INCLUDED

        #define     IDI_APP_ICON    1
        #define     FVFcode         (D3DFVF_DIFFUSE | D3DFVF_XYZRHW)

        //all the declarations and prototypes:

        //Dx functions:

        void initD3D (HWND);
        void clearD3D (void);
        void Render(void);
        void initGraphics(void);

        //constants:

        LPDIRECT3D9 d3d;
        D3DXMATRIX matrix;
        LPDIRECT3DVERTEXBUFFER9 v_buffer = NULL;
        LPDIRECT3DDEVICE9 d3ddevice;




        //Vertices Structure:

        struct vertex
        {

        float x, y,z, rhw;
        DWORD color;

        };


        void clearD3D ()
        {

        d3d->Release();
        d3ddevice->Release();
        v_buffer->Release();

        }


        #endif // DEFINE_H_INCLUDED

and I just have another resource file where I just imported the app icon, I know the code is so long and will take time to read, but I am so sorry I can't find any other solution for this. I also have another question, do I have to set the three matrices, world view and projection, to be able to make an effect like changing the triangles place using world matrix, do I have to set the other two matrices, to change it or only world?? Lastly, thanks for any replier so much, thanks fr his effort and time.


EDIT

The relevant parts/ parts related to transforms from the whole code -coz it is too long- are:

        d3ddevice->BeginScene();    // begins the 3D scene

        // do 3D rendering on the back buffer here

        d3ddevice->SetFVF(FVFcode);

        D3DXMATRIX matrix;
        D3DXMatrixIdentity(&matrix);
        D3DXMatrixTranslation(&matrix, 900, 0, 0);
        d3ddevice->SetTransform(D3DTS_WORLD, &matrix);

        D3DXMATRIX out;
        D3DXVECTOR3 eye(2,3,3);
        D3DXVECTOR3 Lat(0,0,0);
        D3DXVECTOR3 up(0,1,0);
        D3DXMatrixLookAtLH(&out, &eye, &Lat, &up);

        d3ddevice->SetTransform(D3DTS_VIEW, &out);

        D3DXMATRIX pro;

        D3DXMatrixPerspectiveFovLH(&pro,
                                   D3DXToRadian(45),    // the horizontal field of view
                                   (FLOAT)1440 / (FLOAT)900, // aspect ratio
                                   1.0f,    // the near view-plane
                                   100.0f);    // the far view-plane

        d3ddevice->SetTransform(D3DTS_PROJECTION, &pro);


        d3ddevice->SetStreamSource(0, v_buffer, 0, sizeof(vertex));
        d3ddevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);


        d3ddevice->EndScene();    // ends the 3D scene
2
which matrix are you transforming: world or projection?Bruno Ferreira
right now I am transforming the three world, view and projection but nothing actually workeduser3674628
Mind cleaning the code, posting only the relevant parts?Bruno Ferreira
sure, edit it? or do it in new answer?user3674628
You should always edit.Bruno Ferreira

2 Answers

2
votes

So lets start with the basics:

The world matrix

Defined here

D3DXMATRIX matrix;
D3DXMatrixIdentity(&matrix);
D3DXMatrixTranslation(&matrix, 900, 0, 0);
d3ddevice->SetTransform(D3DTS_WORLD, &matrix);

This matrix defines the transformation from the origin that the vertices will have. In this case, you are translating the vertices 900 units to the positive X axis. I.e, if you render its position as (0,0,0), it will be actually at (900,0,0).

This matrix is used when you need to efficiently transform a static mesh, so you don't have to mess with the vertex buffer, only with a single matrix, which is much more efficent. This is the matrix that you should be look at in order to translate, rotate and skew.

The view matrix

Defined here:

D3DXMATRIX out;
D3DXVECTOR3 eye(2,3,3);
D3DXVECTOR3 Lat(0,0,0);
D3DXVECTOR3 up(0,1,0);
D3DXMatrixLookAtLH(&out, &eye, &Lat, &up);

d3ddevice->SetTransform(D3DTS_VIEW, &out);

This matrix defines the transformation that will take place in order to transform the vertex from world space into view space. That is, the relative position of the vertex to the camera. If all you want is rotate or translate the camera, this is where you should change.

The projection matrix

D3DXMATRIX pro;

D3DXMatrixPerspectiveFovLH(&pro,
                           D3DXToRadian(45),    // the horizontal field of view
                           (FLOAT)1440 / (FLOAT)900, // aspect ratio
                           1.0f,    // the near view-plane
                           100.0f);    // the far view-plane

d3ddevice->SetTransform(D3DTS_PROJECTION, &pro);

This matrix defines how the vertices will be projected to screen space. Look at this image:

Projection Matrix

Objects closer to the camera than the near view plane or farther than the far view plane will not be shown. In the image, the green sphere will not be shown, since it is out of bounds.

The FOV angle in practice, means a "zoom" (not quite, but you can think like that).

This matrix is changed when you need some artifacts, like zooming, PIP and such.

In your case, it seems that you want to change just the world matrix. A good start would be using the D3DXMatrixTransformation function.

1
votes

The basic problem is here:

#define     FVFcode         (D3DFVF_DIFFUSE | D3DFVF_XYZRHW)

D3DFVF_XYZRHW indicates the vertex has transformed positions and therefore the world, view and projection transforms should not be applied.

To fix, you'll need to change that D3DFVF_XYZRHW to D3DFVF_XYZ. Then the vertex structure needs the rhw dropped:

struct vertex
{
    float x, y, z;
    DWORD color;
};

and the initialization of v must be altered:

vertex v [] =
    {{320.0f, 50.0f, 1.0f, D3DCOLOR_XRGB(0, 0, 255)},
    {520.0f, 400.0f, 1.0f, D3DCOLOR_XRGB(0, 255, 0)},
    {120.0f, 400.0f, 1.0f, D3DCOLOR_XRGB(255, 0, 0)},
};

That should get DirectX to apply the transformations. I haven't checked to see if there are additional problems with the math of the transformations.