Cant get transformations working.

Hi,

I have been going through tutorials trying to simple draw a quad apply a texture and then rotate the quad.  It was bad enough just finding tutorials to draw a quad, the sdk examples jump from drawing a triangle to drawing a cylinder ! 

Anyway!  I set up my quad and am using index buffering to display my triangle strip.  I managed to get a quad up an apply a texture, eventually.  My problem now is I can't figure out how to apply any transformations.  Everything i do has no effect.  I expect it is something pretty dumb, it's been a lot of fun moving to managed direct x so I hoping I progress a bit futher with it.  Perhaps I am making things a little hard for myself using index buffering but it made more sense to me creating a quad using 4 vertexes.

I am using managed direct x 9 and C#.

As you can see i robbed the sdk tutorial code for the transformation part.  I actually tried altering tutorial 3 ("Direct3D Tutorial 3 - Matrices") of the SDK examples to just add my quad but then that just displays a blank screen.

I hope it isnt a problem posting all my code, i was worried that it might be a problem with the way i am setting up the app.

Cheers for any help at all!

code:



using System;

using System.Drawing;

using System.Windows.Forms;

using Microsoft.DirectX;

using Microsoft.DirectX.Direct3D;

namespace Augur

{

public class Entry : Form

{

// Global variables for this project

Device device = null; // Rendering device

VertexBuffer vertexBuffer = null;

IndexBuffer indexBuffer = null;

Texture texture = null;

PresentParameters presentParams = new PresentParameters();

CustomVertex.TransformedTextured[] verts = null;

public Entry()

{

// Set the initial size of our form

this.ClientSize = new System.Drawing.Size(400,600);

// And it's caption

this.Text = "Augur";

}

// Application entry point

static void Main()

{

using (Entry frm = new Entry())

{

if(!frm.InitGraphics())

{

MessageBox.Show("Could not initialise Direct3D.");

return;

}

frm.Show();

// While the form is still valid, render and process messages

while(frm.Created)

{

frm.Render();

Application.DoEvents();

}

}

}

private bool InitGraphics()

{

//

// Initialise Graphics Window

//

try

{

PresentParameters presentParams = new PresentParameters();

presentParams.Windowed=true; // We don't want to run fullscreen

presentParams.SwapEffect = SwapEffect.Discard; // Discard the frames

presentParams.EnableAutoDepthStencil = true; // Turn on a Depth stencil

presentParams.AutoDepthStencilFormat = DepthFormat.D16; // And the stencil format

device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentParams); //Create a device

device.DeviceReset += new System.EventHandler(this.OnResetDevice);

this.OnCreateDevice(device, null);

this.OnResetDevice(device, null);

return true;

}

catch (DirectXException)

{

return false;

}

}

public void OnCreateDevice(object sender, EventArgs e)

{

Device dev = (Device)sender;

// Now Create the VB

vertexBuffer = new VertexBuffer(typeof(CustomVertex.TransformedTextured), 4, dev, Usage.WriteOnly, CustomVertex.TransformedTextured.Format, Pool.Default);

vertexBuffer.Created += new System.EventHandler(this.OnCreateVertexBuffer);

this.OnCreateVertexBuffer(vertexBuffer, null);

}

public void OnResetDevice(object sender, EventArgs e)

{

Device dev = (Device)sender;

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

dev.RenderState.CullMode = Cull.None;

// Turn off D3D lighting

dev.RenderState.Lighting = false;

// Turn on the ZBuffer

dev.RenderState.ZBufferEnable = true;

//load texture

texture = TextureLoader.FromFile(dev, Application.StartupPath + @"\..\..\gfx\ship1.bmp");

}

public void OnCreateVertexBuffer(object sender, EventArgs e)

{

verts = new CustomVertex.TransformedTextured[4];

verts[0] = new CustomVertex.TransformedTextured(100.0f, 200.0f, 1.0f, 1, 0.0f, 0.0f);

verts[1] = new CustomVertex.TransformedTextured(150.0f, 200.0f, 1.0f, 1, 1.0f, 0.0f);

verts[2] = new CustomVertex.TransformedTextured(100.0f, 250.0f, 1.0f, 1, 0.0f, 1.0f);

verts[3] = new CustomVertex.TransformedTextured(150.0f, 250.0f, 1.0f, 1, 1.0f, 1.0f);

// Fill index buffer

ushort[] indices = { 0, 1, 2, 3 };

indexBuffer = new IndexBuffer(typeof(ushort), 4, device, Usage.WriteOnly, Pool.Managed);

indexBuffer.SetData(indices, 0, 0);

}

private void SetupMatrices()

{

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

// 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.

int iTime = Environment.TickCount % 1000;

float fAngle = iTime * (2.0f * (float)Math.PI) / 1000.0f;

device.Transform.World = Matrix.RotationY(fAngle);

// 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.

device.Transform.View = Matrix.LookAtLH(new Vector3(0.0f, 3.0f, -5.0f), new Vector3(0.0f, 0.0f, 10.0f), new Vector3(0.0f, 1.0f, 0.0f));

// 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).

device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, 1.0f, 1.0f, 5000.0f);

}

private void InitializeComponent()

{

this.SuspendLayout();

//

// Entry

//

this.ClientSize = new System.Drawing.Size(292, 266);

this.Name = "Entry";

this.Load += new System.EventHandler(this.Entry_Load);

this.ResumeLayout(false);

}

protected override void OnKeyPress(System.Windows.Forms.KeyPressEventArgs e)

{

if ((int)(byte)e.KeyChar == (int)System.Windows.Forms.Keys.Escape)

this.Close(); // Esc was pressed

}

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)

{

this.Render(); // Render on painting

}

//render scene

private void Render()

{

//if (device == null) return;

//Clear the backbuffer to a blue color

device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, System.Drawing.Color.Blue, 1.0f, 0);

device.VertexFormat = CustomVertex.TransformedTextured.Format;

//Begin the scene

device.BeginScene();

SetupMatrices();

device.SetTexture(0, texture);

SetupMatrices();

// Rendering of scene objects can happen here

vertexBuffer.SetData(verts, 0, 0);

device.SetStreamSource( 0, vertexBuffer, 0);

device.Indices = indexBuffer;

device.DrawIndexedPrimitives(PrimitiveType.TriangleStrip, 0, 0, 4, 0, 2);

//End the scene

device.EndScene();

device.Present();

}

private void Entry_Load(object sender, EventArgs e)

{

}

}

}

 



Answer this question

Cant get transformations working.

  • The Enforcer

    aha! I was thinking it was going to be something along those lines.  Thats cleared that up for me :)

    Damn, that's really dumb in hindsight..

    This is what I am liking about managed directx though. I can spend more time understanding the actual graphical concepts rather than worrying and getting confused by the code like I did when i was coding in C++.

    Thanks a lot! :D

    edit: Yay! it works :D

  • Mike Dimmick

    Currently you are using the CustomVertex.TransformedTextured which states the the primitives your are rendering using this format have already been transformed and that you are specifying them in screen space. What you will want to do is something in the lines of this tutorial I wrote here.
    It basically takes a triangle and spins it.

    Some of the code looks like this.
    Setting up the triangle
    CustomVertex.PositionColored[] triangle = new CustomVertex.PositionColored[3];

    triangle[0] = new CustomVertex.PositionColored(-1.0f, 0.0f, 0.0f, Color.Red.ToArgb());
    triangle[1] = new CustomVertex.PositionColored(-1.0f, 2.0f, 0.0f, Color.Blue.ToArgb());
    triangle[2] = new CustomVertex.PositionColored( 1.0f, 0.0f, 0.0f, Color.Yellow.ToArgb());

    vb = new VertexBuffer(typeof(CustomVertex.PositionColored), 3, renderer.Device, Usage.WriteOnly, CustomVertex.PositionColored.Format, Pool.Managed);

    vb.SetData(triangle, 0, LockFlags.None);

    And then rendering it will look like this.
    Rendering
    Device.Transform.World = Matrix.Translation(0.0f, 0.0f, 0.0f) * Matrix.RotationX(angle);
    Device.SetStreamSource(0, vb, 0);
    Device.VertexFormat = CustomVertex.PositionColored.Format;            Device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 1);

    I hope this helps.
    Take care.


  • Don Griest

    Let's pretend that someone else has the exact same problem but with the unmanaged C++ version.

    Why doesn't this rotate or do anything!  Note: I cut out all the stuff from the framework that I didn't touch.

     

    #include "DXUT.h"

    #include "resource.h"

    //TODO: Comment this out to start as a D3D9 app

    #define STARTWITHD3D10

    namespace D3D10

    {

    ID3D10DepthStencilView *g_pDSV = NULL;

    ID3D10Texture2D* g_pDepthStencil = NULL;

    };

    CEnumDeviceInfo g_deviceInfo;

    IDirect3DVertexBuffer9 *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

    BOOL GameInit();

    BOOL GameShutdown();

    void UpdateMatrices(IDirect3DDevice9 *);

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

    // 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;

    }

    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();

    }

     


  • Cant get transformations working.