locked
Problem rotating a triangle

    Question

  • I am using the Direct X 9.0 Framework and following one of the tutorials in the Direct X help.  However,  the tutorial in question is supposed to rotate a triangle.  When I run the example, this works great.  When I try to implement this with the framework, the triangle just sits there staring at me and not turning in circles.  Here is most of the code, but with much of the framework that I have not touched cut out.  Please point out my stupid mistake as this is very frustrating.  Thanks. =)

    Direct3DVertexBuffer9 *g_pVB = NULL;

    struct CUSTOMVERTEX

    {

    float x, y, z, rhw;

    DWORD color;

    };

    #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)

    CUSTOMVERTEX vertices[] =

    {

    { 150.0f, 50.0f, 0.5f, 1.0f, 0xffff0000, },

    { 250.0f, 250.0f, 0.5f, 1.0f, 0xff00ff00, },

    { 50.0f, 250.0f, 0.5f, 1.0f, 0xff00ffff, },

    };

    //

    // Forward Declarations

    //

    void PrintError(LPCWSTR);

    BOOL GameInit();

    void UpdateMatrices(IDirect3DDevice9 *);

    //

    // D3D9 Callbacks

    //

     

    //--------------------------------------------------------------------------------------

    // Render the scene

    //--------------------------------------------------------------------------------------

    void CALLBACK OnD3D9FrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )

    {

    HRESULT hr;

    // Clear the render target and the zbuffer

    V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 45, 50, 170), 1.0f, 0) );

    // Render the scene

    if( SUCCEEDED( pd3dDevice->BeginScene() ) )

    {

    UpdateMatrices(pd3dDevice);

    pd3dDevice->SetStreamSource(0, g_pVB, 0, sizeof(CUSTOMVERTEX));

    pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);

    pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);

    V( pd3dDevice->EndScene() );

    // pd3dDevice->Present(NULL, NULL, NULL, NULL);

    }

    }

    //--------------------------------------------------------------------------------------

    // Handle messages to the application

    //--------------------------------------------------------------------------------------

    LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,

    bool* pbNoFurtherProcessing, void* pUserContext )

    {

    switch(uMsg)

    {

    case WM_COMMAND:

    switch(LOWORD(wParam))

    {

    case ID_FILE_EXIT:

    PostQuitMessage(0);

    return 0;

    case ID_OPTIONS_VIDEOSETTINGS:

    return 0;

    }

    return 0;

    case WM_KEYDOWN:

    }

    return 0;

    }

    void UpdateMatrices(IDirect3DDevice9 *pD3DDevice)

    {

    // For our world matrix, we will just rotate the object about the y-axis.

    D3DXMATRIXA16 matWorld;

    // Set up the rotation matrix to generate 1 full rotation (2*PI radians)

    // every 1000 ms. To avoid the loss of precision inherent in very high

    // floating point numbers, the system time is modulated by the rotation

    // period before conversion to a radian angle.

    UINT iTime = timeGetTime() % 1000;

    FLOAT fAngle = (float)iTime * (2.0f * D3DX_PI) / 1000.0f;

    D3DXMatrixRotationY( &matWorld, fAngle );

    pD3DDevice->SetTransform( D3DTS_WORLD, &matWorld );

    // Set up our view matrix. A view matrix can be defined given an eye point,

    // a point to lookat, and a direction for which way is up. Here, we set the

    // eye five units back along the z-axis and up three units, look at the

    // origin, and define "up" to be in the y-direction.

    D3DXVECTOR3 vEyePt( 0.0f, 3.0f,-5.0f );

    D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );

    D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );

    D3DXMATRIXA16 matView;

    D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );

    pD3DDevice->SetTransform( D3DTS_VIEW, &matView );

    // For the projection matrix, we set up a perspective transform (which

    // transforms geometry from 3D view space to 2D viewport space, with

    // a perspective divide making objects smaller in the distance). To build

    // a perpsective transform, we need the field of view (1/4 pi is common),

    // the aspect ratio, and the near and far clipping planes (which define at

    // what distances geometry should be no longer be rendered).

    D3DXMATRIXA16 matProj;

    D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4.0f, 1.0f, 1.0f, 100.0f );

    pD3DDevice->SetTransform( D3DTS_PROJECTION, &matProj );

    }

    BOOL GameInit()

    {

    IDirect3DDevice9 *g_pD3DDevice = NULL;

    g_pD3DDevice = DXUTGetD3D9Device();

    // Turn off culling, so we see the front and back of the triangle

    g_pD3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );

    // Turn off D3D lighting, since we are providing our own vertex colors

    g_pD3DDevice->SetRenderState( D3DRS_LIGHTING, FALSE );

    if(g_pD3DDevice == NULL)

    return E_FAIL;

    if( FAILED( g_pD3DDevice->CreateVertexBuffer(3 * sizeof(CUSTOMVERTEX),

    0,

    D3DFVF_CUSTOMVERTEX,

    D3DPOOL_DEFAULT,

    &g_pVB,

    NULL )))

    return E_FAIL;

    VOID *pVertices;

    if( FAILED( g_pVB->Lock(0, sizeof(vertices), (void**)&pVertices, 0)))

    return E_FAIL;

    memcpy(pVertices, vertices, sizeof(vertices));

    g_pVB->Unlock();

    SAFE_RELEASE(g_pD3DDevice);

    PrintError(L"Game Inititalized.");

    return TRUE;

    }

    //--------------------------------------------------------------------------------------

    // Initialize everything and go into a render loop

    //--------------------------------------------------------------------------------------

    INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, int )

    {

    // Enable run-time memory check for debug builds.

    #if defined(DEBUG) | defined(_DEBUG)

    _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

    #endif

    //g_deviceInfo = new CEnumDeviceInfo;

    // Set the d3d9 callback functions

    DXUTSetCallbackD3D9DeviceCreated( OnD3D9CreateDevice );

    DXUTSetCallbackD3D9DeviceReset( OnD3D9ResetDevice );

    DXUTSetCallbackD3D9DeviceLost( OnD3D9LostDevice );

    DXUTSetCallbackD3D9DeviceDestroyed( OnD3D9DestroyDevice );

    DXUTSetCallbackD3D9FrameRender( OnD3D9FrameRender );

    DXUTSetCallbackD3D9DeviceAcceptable( IsD3D9DeviceAcceptable );

    // Set the d3d10 callback functions

    #ifdef STARTWITHD3D10

    DXUTSetCallbackD3D10DeviceAcceptable( IsD3D10DeviceAcceptable );

    DXUTSetCallbackD3D10DeviceCreated( OnD3D10CreateDevice );

    DXUTSetCallbackD3D10SwapChainResized( OnD3D10ResizedSwapChain );

    DXUTSetCallbackD3D10SwapChainReleasing( OnD3D10ReleasingSwapChain );

    DXUTSetCallbackD3D10DeviceDestroyed( OnD3D10DestroyDevice );

    DXUTSetCallbackD3D10FrameRender( OnD3D10FrameRender );

    #endif

    DXUTSetCallbackMsgProc( MsgProc );

    DXUTSetCallbackDeviceChanging( ModifyDeviceSettings );

    DXUTSetCallbackFrameMove( OnFrameMove );

    // TODO: Perform any application-level initialization here

    // Initialize DXUT and create the desired Win32 window and Direct3D device for the application

    DXUTInit( true, true ); // Parse the command line, and show msgboxes on error

    DXUTSetCursorSettings( true, true ); // Show the cursor and clip it when in full screen

    DXUTCreateWindow( L"DirectX Project",

    NULL,

    NULL,

    LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU1)));

    DXUTCreateDevice( true, 640, 480 );

    GameInit();

    // Start the render loop

    DXUTMainLoop();

    // TODO: Perform any application-level cleanup here

    return DXUTGetExitCode();

    }

     

    //Utility functions

    void PrintError(LPCWSTR printString)

    {

    OutputDebugString(printString);

    OutputDebugString(L"\n");

    }

    Wednesday, January 18, 2006 7:12 AM

Answers

  • It appears that your vertices are Transformed, which means they are in screen space already and will not be affected by the World Matrix.

    If you remove the rhw from the vertex structure and from your FVF, then your World matrix will affect it.  Of course this means that your vertices will no longer be in screen space so you'll need to adjust the coordinates of your vertices so they're on-screen.

     

    Wednesday, January 18, 2006 10:54 PM
  • There is a simple pattern to follow.
    If you want to rotate a triangle you would simply tell the device that it needs to use the following transformation matrix and then you render your object. This will push your vertices through the transformation pipeline and the transformation matrix you have set will then transform your vertices.

    With that said.
    You could follow this pattern for rotating a triangle

    //Some variables to help with the rotation
    static int iRotationDegrees = 0; //variable that will hold the degrees
    D3DXMATRIX matRotation; //rotation matrix
    D3DXMatrixRotationX(&matRotation,D3DXToRadian(iRotationDegrees));
    g_pDevice->SetTransform(D3DTS_WORLD, &matRotation); //set the device's world transformation matrix
    iRotationDegrees++;
    if(iRotationDegrees == 360)
            iRotationDegrees = 0;

    //Render your triangle
    g_pDevice->SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE);
    g_pDevice->DrawPrimitiveUP(....);

    I hope this helps
    Take care.

    PS: Check out Ken's post as it is exactly what's wrong here ;)
    Thursday, January 19, 2006 4:04 AM

All replies

  • It appears that your vertices are Transformed, which means they are in screen space already and will not be affected by the World Matrix.

    If you remove the rhw from the vertex structure and from your FVF, then your World matrix will affect it.  Of course this means that your vertices will no longer be in screen space so you'll need to adjust the coordinates of your vertices so they're on-screen.

     

    Wednesday, January 18, 2006 10:54 PM
  • There is a simple pattern to follow.
    If you want to rotate a triangle you would simply tell the device that it needs to use the following transformation matrix and then you render your object. This will push your vertices through the transformation pipeline and the transformation matrix you have set will then transform your vertices.

    With that said.
    You could follow this pattern for rotating a triangle

    //Some variables to help with the rotation
    static int iRotationDegrees = 0; //variable that will hold the degrees
    D3DXMATRIX matRotation; //rotation matrix
    D3DXMatrixRotationX(&matRotation,D3DXToRadian(iRotationDegrees));
    g_pDevice->SetTransform(D3DTS_WORLD, &matRotation); //set the device's world transformation matrix
    iRotationDegrees++;
    if(iRotationDegrees == 360)
            iRotationDegrees = 0;

    //Render your triangle
    g_pDevice->SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE);
    g_pDevice->DrawPrimitiveUP(....);

    I hope this helps
    Take care.

    PS: Check out Ken's post as it is exactly what's wrong here ;)
    Thursday, January 19, 2006 4:04 AM
  • Right you are, thank you so much. I stared at this thing forever and missed that little piece.  Thanks bunches.
    Saturday, January 21, 2006 5:34 AM