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

What am I doing wrong?!?!?

Started by Synex Jan 3, 2004 at 2:03 PM 3 replies 850+ views
Original Post
Synex
Synex
Here's my code: It displays a 2D Ortho output on top of a 3D output. I'm trying to get Picking working... I've tried everything and i can't get it reliably working... Here is the code:
/* Base Code for a Windows Application */

#pragma comment(lib,"d3d8.lib")
#pragma comment(lib,"d3dx8.lib")
#pragma comment(lib,"dxguid.lib")
#pragma comment(lib,"dxerr8.lib")
#pragma comment(lib,"dinput8.lib")
#pragma comment(lib,"winmm.lib")

#include <windows.h>
#include <d3d8.h>
#include <dinput.h>
#include <stdio.h>
#include "cfont.h"
#include "cmouse.h"
#include "gui_window.h"
#include "parray.h"

// Globals


// Structures


	struct D3DVERTEX
	{
		D3DXVECTOR3 p;
		D3DXVECTOR3 n;
		FLOAT       tu, tv;
	};

	struct INTERSECTION
	{
		DWORD dwFace;                 // mesh face that was intersected

		FLOAT fBary1, fBary2;         // barycentric coords of intersection

		FLOAT fDist;                  // distance from ray origin to intersection

		FLOAT tu, tv;                 // texture coords of intersection

	};


	// A structure for our custom vertex type

	struct CUSTOMVERTEX
	{
		FLOAT x, y, z; // The transformed position for the vertex

		DWORD color;        // The vertex color

	};

	// Our custom FVF, which describes our custom vertex structure

	#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)


IDirect3D8					   *D3D; // Pointer to Direct3D

IDirect3DDevice8			*D3DDevice; // Pointer to the Direct3D device


LPDIRECTINPUT8  DInput; // Pointer to DirectInput Device

LPDIRECTINPUTDEVICE8  DInputKeyB; // Pointer to Keyboard


int							g_iX		 = 1024;
int							g_iY		 = 768;
LPDIRECT3DVERTEXBUFFER8		g_pVB        = NULL; // Buffer to hold vertices



FontEngine					   Font;
CMouse						   DIMouse;

gui_main						GUI;

// Global Windows Stuff


HANDLE						    g_hMouseEvent = NULL;
HRESULT						   result;
HWND						    hWnd;
static TCHAR				   szAppName[] = TEXT("D3DApp");
bool							   done=false;
bool							   g_bActive=true;

// Function Definitions


LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
bool D3DInit();
void D3DCleanup();
void D3DRender();
HRESULT InitVB();
bool DIInit();
bool DIInitKeyB();
bool DIInitMouse();
HRESULT DIPick2D();
HRESULT DIPick3D();

IntersectTriangle( const D3DXVECTOR3& orig,
                                       const D3DXVECTOR3& dir, D3DXVECTOR3& v0,
                                       D3DXVECTOR3& v1, D3DXVECTOR3& v2,
                                       FLOAT* t, FLOAT* u, FLOAT* v )
{
    // Find vectors for two edges sharing vert0

    D3DXVECTOR3 edge1 = v1 - v0;
    D3DXVECTOR3 edge2 = v2 - v0;

    // Begin calculating determinant - also used to calculate U parameter

    D3DXVECTOR3 pvec;
    D3DXVec3Cross( &pvec, &dir, &edge2 );

    // If determinant is near zero, ray lies in plane of triangle

    FLOAT det = D3DXVec3Dot( &edge1, &pvec );

    D3DXVECTOR3 tvec;
    if( det > 0 )
    {
        tvec = orig - v0;
    }
    else
    {
        tvec = v0 - orig;
        det = -det;
    }

    if( det < 0.0001f )
        return FALSE;

    // Calculate U parameter and test bounds

    *u = D3DXVec3Dot( &tvec, &pvec );
    if( *u < 0.0f || *u > det )
        return FALSE;

    // Prepare to test V parameter

    D3DXVECTOR3 qvec;
    D3DXVec3Cross( &qvec, &tvec, &edge1 );

    // Calculate V parameter and test bounds

    *v = D3DXVec3Dot( &dir, &qvec );
    if( *v < 0.0f || *u + *v > det )
        return FALSE;

    // Calculate t, scale parameters, ray intersects triangle

    *t = D3DXVec3Dot( &edge2, &qvec );
    FLOAT fInvDet = 1.0f / det;
    *t *= fInvDet;
    *u *= fInvDet;
    *v *= fInvDet;

    return TRUE;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	

	MSG				 msg;
	WNDCLASS	wndclass;

	wndclass.style = CS_HREDRAW | CS_VREDRAW;
	wndclass.lpfnWndProc = WndProc;
	wndclass.cbClsExtra = 0;
	wndclass.cbWndExtra = 0;
	wndclass.hInstance = hInstance;
	wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION);
	wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
	wndclass.hbrBackground = (HBRUSH) GetStockObject (BLACK_BRUSH);
	wndclass.lpszMenuName = NULL;
	wndclass.lpszClassName = szAppName;

	if(!RegisterClass(&wndclass))
	{
		MessageBox(NULL, TEXT("Cannot Register Window Class"), szAppName, MB_ICONERROR);
		return 0;
	};

	hWnd = CreateWindow (szAppName,
										TEXT("Broken Glass GUI Test"),
										WS_OVERLAPPEDWINDOW,
										CW_USEDEFAULT,
										CW_USEDEFAULT,
										g_iX,
										g_iY,
										NULL,
										NULL,
										wndclass.hInstance,
										NULL);

	if(!D3DInit())
	{
		MessageBox(NULL, TEXT("Direct3D Init Error"), szAppName, MB_ICONERROR);
		return 0;
	};

	DIInit();
	InitVB();

	Font.Initialize((HFONT)GetStockObject(SYSTEM_FONT),D3DCOLOR_XRGB(255,255,0));

	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);

	while(!done)									// Loop That Runs While done=FALSE

	{
		if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))	// Is There A Message Waiting?

		{
			if (msg.message==WM_QUIT)				// Have We Received A Quit Message?

			{
				done=TRUE;							// If So done=TRUE

			}
			else									// If Not, Deal With Window Messages

			{
				TranslateMessage(&msg);				// Translate The Message

				DispatchMessage(&msg);				// Dispatch The Message

			}
		}
		else										// If There Are No Messages

		{
		// Draw The Scene.

		if (D3DDevice) D3DRender();
		GUI.RenderGUI();
		DIMouse.Refresh();
		}
	}


	return msg.wParam;

}

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

	HDC						hDC;
	PAINTSTRUCT		 ps;
	RECT					rect;

	switch(msg)
	{
	case WM_PAINT:
		
		hDC = BeginPaint(hWnd, &ps);
			GetClientRect(hWnd, ▭);
		EndPaint(hWnd, &ps);

		return 0;

	case WM_DESTROY:

		PostQuitMessage(0);
		D3DCleanup();
		return 0;

	case WM_ACTIVATE:
            if( WA_INACTIVE == wParam )
                g_bActive = FALSE;
            else
                g_bActive = TRUE;

            // Set exclusive mode access to the mouse based on active state

            DIMouse.SetAcquire();
         return 0;


	};

	return DefWindowProc(hWnd, msg, wParam, lParam);
}

bool D3DInit()
{
	D3D=Direct3DCreate8(D3D_SDK_VERSION); // Create Direct3D

	if (D3D==NULL) // Check if it succeeded, if it didn't, return failure

	{
		MessageBox(NULL, TEXT("D3DInit - Direct3D Object Creation Error"), szAppName, MB_ICONERROR);
		return false;
	}

	D3DDISPLAYMODE d3ddm;
	if( FAILED( D3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ) ) )
	{
		MessageBox(NULL, TEXT("D3DInit - Error Getting Adapter Display Mode"), szAppName, MB_ICONERROR);
		return false;
	};

	D3DPRESENT_PARAMETERS d3dpp; 
	memset(&d3dpp, 0, sizeof(D3DPRESENT_PARAMETERS)); // We need to fill it with 0's first

	d3dpp.Windowed   = TRUE;
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	d3dpp.BackBufferFormat = d3ddm.Format; // The color format

	
	// Create the device

	result=D3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
												D3DCREATE_SOFTWARE_VERTEXPROCESSING,
												&d3dpp, &D3DDevice ); 

	if (FAILED(result)) // If it failed, return failure

	{
		MessageBox(NULL, TEXT("D3DInit CreateDevice Error"), szAppName, MB_ICONERROR);
		return false;
	}

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

    D3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );

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

    D3DDevice->SetRenderState( D3DRS_LIGHTING, FALSE );

	return true;


};

VOID SetupMatrices()
{
    // For our world matrix, we will just rotate the object about the y-axis.

    D3DXMATRIX matWorld;
    D3DXMATRIX matView;
	D3DXMATRIX matProj;
	D3DXMATRIX matIdentity;
    
	D3DXMatrixIdentity(&matIdentity);
	D3DXMatrixRotationY( &matWorld, timeGetTime()/300.0f );
    D3DXMatrixLookAtLH( &matView, &D3DXVECTOR3( 0.0f, 0.0f, -5.0f ),
                                  &D3DXVECTOR3( 0.0f, 0.0f, 0.0f ),
                                  &D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) );
	D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 1000.0f );
    	
	D3DDevice->SetTransform( D3DTS_VIEW, &matView );    
	D3DDevice->SetTransform( D3DTS_PROJECTION, &matProj );
	D3DDevice->SetTransform( D3DTS_WORLD, &matIdentity );
}

VOID SetupMatrices2D()
{
    
    D3DXMATRIX matOrtho; 
    D3DXMATRIX matIdentity;
	D3DXMATRIX matView;
    D3DXMATRIX matTrans;
	D3DXMATRIX matScale;
	D3DXMATRIX matWorld;
    //Setup the orthogonal projection matrix and the default world/view matrix

    D3DXMatrixOrthoLH(&matOrtho, 100.0f, 100.0f, 0.0f, 1.0f);
    D3DXMatrixIdentity(&matIdentity);
	D3DXMatrixScaling(&matScale, 10.0f, 10.0f, 1.0f);
	D3DXMatrixTranslation(&matTrans, -30.0f, 0.0f, 0.0f);

    D3DXMatrixLookAtLH( &matView, &D3DXVECTOR3( 0.0f, 0.0f,-5.0f ),
                                  &D3DXVECTOR3( 0.0f, 0.0f, 0.0f ),
                                  &D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) );

	D3DXMatrixMultiply(&matWorld, &matScale, &matTrans);

//    D3DDevice->SetTransform(D3DTS_PROJECTION, &matOrtho);

//    D3DDevice->SetTransform(D3DTS_WORLD, &matWorld);

//    D3DDevice->SetTransform(D3DTS_VIEW, &matIdentity);


    D3DDevice->SetTransform(D3DTS_PROJECTION, &matOrtho);
    D3DDevice->SetTransform(D3DTS_WORLD, &matWorld);
    D3DDevice->SetTransform(D3DTS_VIEW, &matIdentity);

    //Make sure that the z-buffer and lighting are disabled

    D3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
    D3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
}

void D3DCleanup()
{
	
    if( D3DDevice != NULL)
        D3DDevice->Release();
    if( D3D != NULL)
        D3D->Release();
};

void DICleanup()
{
    if (DInput) 
    { 
        if (DInputKeyB) 
        { 
        // Always unacquire device before calling Release(). 

            DInputKeyB->Unacquire(); 
            DInputKeyB->Release();
            DInputKeyB = NULL; 
        } 
        DInput->Release();
        DInput = NULL; 
    } 

};

bool DIInit()
{

	DIInitKeyB();
	DIInitMouse();

	return true;

};

bool DIInitMouse()
{

	#ifdef _WIN64
		HINSTANCE hInstance = (HINSTANCE) GetWindowLongPtr( hWnd, GWLP_HINSTANCE );
	#else
		HINSTANCE hInstance = (HINSTANCE) GetWindowLong( hWnd, GWL_HINSTANCE );
	#endif

		LPDIRECTINPUT di = NULL; 

		// Create DInput Object

		if (FAILED(DirectInput8Create(hInstance, DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**)&di, NULL)))	{ 
			MessageBox(NULL, TEXT("DInput CreateDevice Error"), szAppName, MB_ICONERROR);	
			return false;  
		};

		// Init Mouse Object

		if(FAILED(DIMouse.Init(di)))	{	
			MessageBox(NULL, TEXT("Mouse Initialization Error"), szAppName, MB_ICONERROR);	
			return false;	
		};

		return S_OK;

};

bool DIInitKeyB()
{

		HRESULT         hr; 

	#ifdef _WIN64
		HINSTANCE hInst = (HINSTANCE) GetWindowLongPtr( hWnd, GWLP_HINSTANCE );
	#else
		HINSTANCE hInst = (HINSTANCE) GetWindowLong( hWnd, GWL_HINSTANCE );
	#endif

		hr = DirectInput8Create(hInst, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&DInput, NULL); 
		if FAILED(hr) 
		{ 
			MessageBox(NULL, TEXT("Cannot create DirectInput Device"), szAppName, MB_ICONERROR);
			return false;
			// DirectInput not available; take appropriate action 

		} 

		hr = DInput->CreateDevice(GUID_SysKeyboard, &DInputKeyB, NULL); 
		if FAILED(hr) { 
			DICleanup(); 
			MessageBox(NULL, TEXT("Cannot create DirectInput Keyboard"), szAppName, MB_ICONERROR);
			return FALSE; 
		} 

		hr = DInputKeyB->SetDataFormat(&c_dfDIKeyboard); 
 
		if FAILED(hr) { 
			DICleanup(); 
			MessageBox(NULL, TEXT("Cannot set Keyboard Data Format"), szAppName, MB_ICONERROR);
			return FALSE; 
		} 

		// Set the cooperative level 

		hr = DInputKeyB->SetCooperativeLevel(hWnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE); 
 
		if FAILED(hr) { 
			DICleanup(); 
			MessageBox(NULL, TEXT("Cannot set Keyboard Behaviour"), szAppName, MB_ICONERROR);
			return FALSE; 
		} 

		if (DInputKeyB) DInputKeyB->Acquire(); 

		return true;

};

HRESULT InitVB()
{
     // Initialize three vertices for rendering a triangle

    CUSTOMVERTEX g_Vertices[] =
    {
        { -0.5f, -0.5f, 0.0f, 0xffff0000, },
        {  0.5f, 0.5f, 0.0f, 0xff00ff00, },
        {  0.5f, -0.5f, 0.0f, 0xff0000ff, },
		{ -0.5f, -0.5f, 0.0f, 0xffff0000, },
		{ -0.5f, 0.5f, 0.0f, 0xff0000ff, },
		{  0.5f, 0.5f, 0.0f, 0xff00ff00, }
    };

    // Create the vertex buffer.

    if( FAILED( D3DDevice->CreateVertexBuffer( 6*sizeof(CUSTOMVERTEX),
                                                  0, D3DFVF_CUSTOMVERTEX,
                                                  D3DPOOL_DEFAULT, &g_pVB ) ) )
    {
        return E_FAIL;
    }

    // Fill the vertex buffer.

    VOID* pVertices;
    if( FAILED( g_pVB->Lock( 0, sizeof(g_Vertices), (BYTE**)&pVertices, 0 ) ) )
        return E_FAIL;
    memcpy( pVertices, g_Vertices, sizeof(g_Vertices) );
    g_pVB->Unlock();

    return S_OK;
}

void D3DRender()
{

   // Set up the cursor

    POINT ptCursor;
    GetCursorPos( &ptCursor );
    ScreenToClient( hWnd, &ptCursor );
    D3DDevice->SetCursorPosition( ptCursor.x, ptCursor.y, 0L );

    // Clear the backbuffer and the zbuffer

    D3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );
    
    // Begin the scene

    D3DDevice->BeginScene();

		// Do Spinning Plane	

		SetupMatrices();

		D3DDevice->SetStreamSource( 0, g_pVB, sizeof(CUSTOMVERTEX) );
		D3DDevice->SetVertexShader( D3DFVF_CUSTOMVERTEX );
		D3DDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 2 );

		DIPick3D();

		// Do 2D Static Plane


		SetupMatrices2D();

		D3DDevice->SetStreamSource( 0, g_pVB, sizeof(CUSTOMVERTEX) );
		D3DDevice->SetVertexShader( D3DFVF_CUSTOMVERTEX );
		D3DDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 2 );

		// DIPick2D();


		// Draw Text


		TCHAR szText[50] = "Press F1 for Stats";
		CPoint P;
		P = DIMouse.GetAbsPosition();
		sprintf(szText, "Position : %d, %d", P.x, P.y );
		Font.OutputText(szText,10,10);

		if(DIMouse.GetButton(0)) { Font.OutputText("Button 1 down!", 10, 25); };
		if(DIMouse.GetButton(1)) { Font.OutputText("Button 2 down!", 10, 40); };
		if(DIMouse.GetButton(2)) { Font.OutputText("Button 3 down!", 10, 55); };

	D3DDevice->EndScene();

	// Present the backbuffer contents to the display

    D3DDevice->Present( NULL, NULL, NULL, NULL );

};

HRESULT DIPick2D()
{


	return S_OK;

};

HRESULT DIPick3D()
{
	if(!DIMouse.GetButton(0)) return E_FAIL;

    HRESULT hr;
    D3DXVECTOR3 vPickRayDir;
    D3DXVECTOR3 vPickRayOrig;
	DWORD	    m_dwNumIntersections = 0L;

	// Get the pick ray from the mouse position

    D3DXMATRIX matProj;
    D3DDevice->GetTransform( D3DTS_PROJECTION, &matProj );

    POINT ptCursor;
    GetCursorPos( &ptCursor );
    ScreenToClient(hWnd, &ptCursor );

	// Compute the vector of the pick ray in screen space

    D3DXVECTOR3 v;
    v.x =  ( ( ( 2.0f * ptCursor.x ) / g_iX  ) - 1 ) / matProj._11;
    v.y = -( ( ( 2.0f * ptCursor.y ) / g_iY ) - 1 ) / matProj._22;
    v.z =  1.0f;

    // Get the inverse view matrix

    D3DXMATRIX matView, m;
    D3DDevice->GetTransform( D3DTS_VIEW, &matView );
    D3DXMatrixInverse( &m, NULL, &matView );


    // Transform the screen space pick ray into 3D space

    vPickRayDir.x  = v.x*m._11 + v.y*m._21 + v.z*m._31;
    vPickRayDir.y  = v.x*m._12 + v.y*m._22 + v.z*m._32;
    vPickRayDir.z  = v.x*m._13 + v.y*m._23 + v.z*m._33;
    vPickRayOrig.x = m._41;
    vPickRayOrig.y = m._42;
    vPickRayOrig.z = m._43;

    // Get the picked triangle

    LPDIRECT3DVERTEXBUFFER8		pVB;
	D3DVERTEX*					pVertices;

	pVB = g_pVB;
    pVB->Lock( 0,0,(BYTE**)&pVertices, 0 );

	// Not using D3DX

    DWORD dwNumFaces = 2;
    FLOAT fBary1, fBary2;
    FLOAT fDist;
	INTERSECTION m_IntersectionArray[16];

    for( DWORD i=0; i<dwNumFaces; i++ )
    {
		D3DXVECTOR3 v0 = pVertices[3*i+0].p;
		D3DXVECTOR3 v1 = pVertices[3*i+1].p;
		D3DXVECTOR3 v2 = pVertices[3*i+2].p;

		// Check if the pick ray passes through this point

		if( IntersectTriangle( vPickRayOrig, vPickRayDir, v0, v1, v2,
										   &fDist, &fBary1, &fBary2 ) )
		{
					m_dwNumIntersections = 0;
					m_IntersectionArray[m_dwNumIntersections].dwFace = i;
					m_IntersectionArray[m_dwNumIntersections].fBary1 = fBary1;
					m_IntersectionArray[m_dwNumIntersections].fBary2 = fBary2;
					m_IntersectionArray[m_dwNumIntersections].fDist = fDist;
					m_dwNumIntersections++;
				if( m_dwNumIntersections == 16 )
				break;
		}
    }

	if(m_dwNumIntersections > 0) MessageBox(NULL, TEXT("Intersection Found"), TEXT("Intersection Found"), MB_OK);

	pVB->Unlock();
	pVB->Release();

	return S_OK;

};
It works with the bottom left triangle (3D) but not the top right (3D) - don't worry about the 2D implementation - I can do that... Please please please tell me what the hell I'm doing wrong! Synex Code Monkey [edited by - Synex on January 4, 2004 4:45:41 AM]
SynexCode Monkey
SSJCORY
SSJCORY
for god sake use source brackets. [ source] [ /source]



Favorite Quotes:Gandalf: You shall not pass!|Smeagol: We don''t need you!|Sloth: Hey you guys!|

Favorite Quotes:Gandalf: You cannot pass!|Smeagol: We don't need you!|Sloth: Hey you guys!|
Synex
Synex
quote:
Original post by SSJCORY
for god sake use source brackets. [ source] [ /source]


Hey thanks... I was wondering how to do that!
SynexCode Monkey
Synex
Synex
Ok... I worked out what I was doing wrong and fixed that...

However, I''m having problems with it picking small objects close to the camera.. Is this normal?
SynexCode Monkey
Synex
Synex
Ha ha!

Figured it out!

Never mind...
SynexCode Monkey

Topic Locked

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

Sign in to reply to this topic.