Skip to main content
GameDev.net gamedev.net
🔒 Locked

Draw Sphere : Matrix problem

Started by nedemon Sep 19, 2005 at 11:43 AM 2 replies 350+ views
Original Post
nedemon
nedemon
Greetings for the third time, gentlemen. Your advice has been really helpful so far, but i regret to bother you to tell that i need help again. It's all about matrices. I draw a sphere and then i need to get it to the center of the screen. I've come to conclusion that the operation should be View Transformation. But it isn't working. The sphere appears in the upper left corner if i don't touch the matrices, but when i do it's not on the screen. Also i should mention, that 30 would be the radius. And i have a clue - maybe it has to do something with the D3DFVF_ formats. I use XYZRHW, because if i don't the sphere doesn't appear. And in examples in sdk they would use either XYZ + Normal or just XYZ. Thanx.

#include <Windows.h>
#include <mmsystem.h>
#include <d3dx9.h>
#include <fstream.h>
LPDIRECT3D9             g_pD3D       = NULL;
LPDIRECT3DDEVICE9       g_pd3dDevice = NULL;
LPDIRECT3DVERTEXBUFFER9 g_pVB        = NULL;
LPDIRECT3DINDEXBUFFER9 g_pIB = NULL;
struct CUSTOMVERTEX
{
    FLOAT x, y, z,rhw;
    DWORD color;
};
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)

HRESULT InitD3D( HWND hWnd )
{
    if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
        return E_FAIL;
    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory(&d3dpp, sizeof(d3dpp));
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
	d3dpp.BackBufferHeight = 200;
	d3dpp.BackBufferWidth = 320;

    if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
                                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                      &d3dpp, &g_pd3dDevice ) ) )
    {
        return E_FAIL;
    }

    g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );

    g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );

    return S_OK;
}

HRESULT InitGeometry()
{
	DWORD i=0;
	DWORD g_Indices[4000];
	CUSTOMVERTEX g_Vertices[4000];
	FLOAT dB = 10, dL = 10, R = 30;
	FLOAT B = -90, L = 0; 
	for(B = -90; B < 90; B+=dB)
		for(L = 0; L < 360; L+=dL)
		{
			g_Vertices.x = R*cosf(B)*sinf(L);
			g_Vertices.y = R*cosf(B)*cosf(L);
			g_Vertices.z = R*sinf(B);
			g_Vertices.rhw = 1.0f;
			g_Vertices.color = D3DCOLOR_XRGB(0,0,255);
			g_Indices = i;
			++i;
			g_Vertices.x = R*cosf(B+dB)*sinf(L);
			g_Vertices.y = R*cosf(B+dB)*cosf(L);
			g_Vertices.z = R*sinf(B+dB);
			g_Vertices.rhw = 1.0f;
			g_Vertices.color = D3DCOLOR_XRGB(0,255,0);
			g_Indices = i;
			++i;
			g_Vertices.x = R*cosf(B)*sinf(L+dL);
			g_Vertices.y = R*cosf(B)*cosf(L+dL);
			g_Vertices.z = R*sinf(B);
			g_Vertices.rhw = 1.0f;
			g_Vertices.color = D3DCOLOR_XRGB(255,0,0);
			g_Indices = i;
			++i;
			g_Vertices.x = R*cosf(B+dB)*sinf(L);
			g_Vertices.y = R*cosf(B+dB)*cosf(L);
			g_Vertices.z = R*sinf(B+dB);
			g_Vertices.rhw = 1.0f;
			g_Vertices.color = D3DCOLOR_XRGB(0,255,255);
			g_Indices = i;
			++i;
			g_Vertices.x = R*cosf(B)*sinf(L+dL);
			g_Vertices.y = R*cosf(B)*cosf(L+dL);
			g_Vertices.z = R*sinf(B);
			g_Vertices.rhw = 1.0f;
			g_Vertices.color = D3DCOLOR_XRGB(255,0,0);
			g_Indices = i;
			++i;
			g_Vertices.x = R*cosf(B+dB)*sinf(L+dL);
			g_Vertices.y = R*cosf(B+dB)*cosf(L+dL);
			g_Vertices.z = R*sinf(B+dB);
			g_Vertices.rhw = 1.0f;
			g_Vertices.color = D3DCOLOR_XRGB(255,255,0);
			g_Indices = i;
			++i;
		}
    if( FAILED( g_pd3dDevice->CreateVertexBuffer( 4000*sizeof(CUSTOMVERTEX),
                                                  0, D3DFVF_CUSTOMVERTEX,
                                                  D3DPOOL_DEFAULT, &g_pVB, NULL)))
    {
        return E_FAIL;
    }
    VOID* pVertices;
    if( FAILED( g_pVB->Lock( 0, sizeof(g_Vertices), (void**)&pVertices, 0 )))
        return E_FAIL;		
    memcpy( pVertices, g_Vertices, sizeof(g_Vertices) );
    g_pVB->Unlock();
//----------------------------------------------------------------------
	g_pd3dDevice->CreateIndexBuffer(4000*sizeof(int), 0, D3DFMT_INDEX16
				,D3DPOOL_DEFAULT, &g_pIB, NULL);
	VOID* pIndices;
	if( FAILED( g_pIB->Lock( 0, 
                      sizeof(g_Indices),
                      &pIndices,
                      0 )))
	    return E_FAIL;

	memcpy( pIndices, g_Indices, sizeof(g_Indices) );
	g_pIB->Unlock();
    return S_OK;
}
VOID Cleanup()
{
    if( g_pVB != NULL )
        g_pVB->Release();

    if( g_pd3dDevice != NULL )
        g_pd3dDevice->Release();

    if( g_pD3D != NULL )
        g_pD3D->Release();
}
VOID SetupMatrices()
{
    D3DXMATRIXA16 matWorld;
    D3DXVECTOR3 vEyePt( -40.0f, -40.0f,4.0f );
    D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );
    D3DXVECTOR3 vUpVec( 0.0f, 4.0f, 0.0f );
    D3DXMATRIXA16 matView;
    D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );
    g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
}
VOID Render()
{
	g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );

    if( SUCCEEDED( g_pd3dDevice->BeginScene()))
    {
        SetupMatrices();
		g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX));
        g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX );
		g_pd3dDevice->SetIndices(g_pIB);
		g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 3888, 0, 1296);//1296..3888
        g_pd3dDevice->EndScene();
    }
    g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch( msg )
    {
        case WM_DESTROY:
            Cleanup();
            PostQuitMessage( 0 );
            return 0;
    }

    return DefWindowProc( hWnd, msg, wParam, lParam );
}
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
	WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
                      GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
                      "D3D", NULL };
    RegisterClassEx( &wc );
    HWND hWnd = CreateWindow( "D3D", "D_3_D",
                              WS_OVERLAPPEDWINDOW, 100, 100, 255, 255,
                              GetDesktopWindow(), NULL, wc.hInstance, NULL );
    
    if( SUCCEEDED( InitD3D( hWnd ) ) )
    {
        if( SUCCEEDED( InitGeometry() ) )
        {
            ShowWindow( hWnd, SW_SHOWDEFAULT );
            UpdateWindow( hWnd );

            MSG msg;
            ZeroMemory( &msg, sizeof(msg) );
            while( msg.message!=WM_QUIT )
            {
                if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
                {
                    TranslateMessage( &msg );
                    DispatchMessage( &msg );
                }
                else
                    Render();
            }
        }
    }

    UnregisterClass( "D3D", wc.hInstance );
    return 0;
}

Evil Steve
Evil Steve
D3DFVF_XYZRHW means "I'm giving you the vertex positions in screen (pixel) coordinates, don't apply any matrices to them". So changing the matrices shouldn't affect anything. If you want to move the sphere around, you'll want to use the D3DFVF_XYZ type instead, and include D3DFVF_NORMAL is you want to include normals for lighting too.

The reason nothing appears when you use D3DFVF_XYZ is that you haven't set up a projection matrix, only a view matrix. Try using this code for SetupMatrices():
VOID SetupMatrices(){    D3DXMATRIXA16 matWorld;    D3DXVECTOR3 vEyePt( -40.0f, -40.0f,4.0f );    D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );    D3DXVECTOR3 vUpVec( 0.0f, 4.0f, 0.0f );    D3DXMATRIXA16 matView;    D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );    g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );    D3DXMATRIXA16 matProj;    int w = 320; // Your screen width    int h = 200; // Your screen height    D3DXMatrixPerspectiveFovLH(&matProj, D3DXToRadian(60.0f), (float)w/(float)h, 1.0f, 1000.0f);    g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );}

That code sets up a projection matrix that has a FOV of 60 degrees, and uses an aspect ratio of 1.6 (320/200). You should adjust w and h to be whatever your display resolution is, if it changes.
Armadon
Armadon
Hi there nedemon,
How are you doing?

The Problem
Matrices and Vertex Formats

The Solution
What is XYZ_RHW?
The RHW format specifies that the vertices are already transformed and that transformation matrices do not apply to them.
So, the vertices specified with this format are specified in screen space (Transformed already)

How can I fix this
If you want to use the transformation matrices you must use D3DFVF_XYZ, these vertices are not transformed and are transformed using a combination of a world, view, projection transformation.

Coming to your problem directly.
1) You could push your camera back about 100 units.
e.g. D3DXVECTOR3 vEyePt( -40.0f, -40.0f, -100.0f );
2) Also you should specify a projection transformation matrix.
e.g. D3DXMatrixPerspectiveFovLH(&mat, D3DX_PI/6, 4.0f/3.0f, 1.0f, 1000.0);
pDevice->SetTransform(D3DTS_PROJECTION, &mat);
This is just a matrix that tells the camera how to behave... meaning your
near clipping plane and far clipping plane. Also it controls your field of
view. This gives the illusion of perspective and is used in transforming
your untransformed vertices to screen space


I hope this helps buddy.
take care.

[Edited by - Armadon on September 19, 2005 12:09:28 PM]
nedemon
nedemon
Thanks, gentlemen, that was clear and enlighting.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.