Jump to content
  • Advertisement
Sign in to follow this  
31337

Drawing an Interface on top of a 3D Scene

This topic is 5129 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am trying to render a 3D scene in the background behind an interface of 2D buttons. I also want to be able to hit test the boxes vs the mouse very easily. What is the easiest way to do this? I was thinking that I could just change the projection, viewing, and world matrices after having rendered the perspective scene to fitting an orthographic projection but this doesn't seem to work. For some reason I can't get the second set of stuff to render. Basically my current approach is rendering like this: *Setup perspective cam* *Render perspective background scene* *Setup orthographic cam* *Render orthographic interface scene* Is there anything else I need to do to get this to work? How am I going to hit test the buttons? I'm setting my matricies with this function:
[SOURCE]
D3DXMATRIX mPerspective, mView, mWorld;
	D3DXVECTOR3 vEye, vAt, vUp;

	vEye.x = 0.0;
	vEye.y = 0.0;
	vEye.z = 0.0;

	vAt.x  = 0.0;
	vAt.y  = 0.0;
	vAt.z  = 1.0;

	vUp.x  = 0.0;
	vUp.y  = 1.0;
	vUp.z  = 0.0;

	D3DXMatrixOrthoLH(&mPerspective, 10.0f, 10.0f, 1.0, 10.0);
	CBase::m_pDevice->SetTransform(D3DTS_PROJECTION, &(D3DMATRIX)mPerspective);
	
	D3DXMatrixIdentity(&mWorld);
	CBase::m_pDevice->SetTransform(D3DTS_WORLD, &(D3DMATRIX)mWorld);

	D3DXMatrixLookAtLH(&mView, &vEye, &vAt, &vUp);
	CBase::m_pDevice->SetTransform(D3DTS_VIEW, &(D3DMATRIX)mView);
[/SOURCE]
and I'm trying to render a sample box with this setup code:
[SOURCE]
if(FAILED(CBase::m_pDevice->CreateVertexBuffer(sizeof(TextureVertex_t)*6, D3DCREATE_HARDWARE_VERTEXPROCESSING, 
												   D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1, D3DPOOL_DEFAULT, 
												   &m_pButton, NULL))) {
		return false;
	}
    TextureVertex_t *pVertices;
	if(FAILED(m_pButton->Lock(0, 0, (void **)&pVertices, 0))) {
		return false;
	}
	pVertices[0].x = 0.0f;
	pVertices[0].y = 0.0f;
	pVertices[0].z = 0.0f;
	pVertices[0].u = 0.0f;
	pVertices[0].v = 0.0f;

	pVertices[1].x = BUTTON_SIZEX;
	pVertices[1].y = 0.0f;
	pVertices[1].z = 0.0f;
	pVertices[1].u = 1.0f;
	pVertices[1].v = 0.0f;

	pVertices[2].x = 0.0f;
	pVertices[2].y = BUTTON_SIZEY;
	pVertices[2].z = 0.0f;
	pVertices[2].u = 0.0f;
	pVertices[2].v = 1.0f;

	pVertices[3].x = 0.0f;
	pVertices[3].y = BUTTON_SIZEY;
	pVertices[3].z = 0.0f;
	pVertices[3].u = 0.0f;
	pVertices[3].v = 1.0f;

	pVertices[4].x = BUTTON_SIZEX;
	pVertices[4].y = 0.0f;
	pVertices[4].z = 0.0f;
	pVertices[4].u = 1.0f;
	pVertices[4].v = 0.0f;

	pVertices[5].x = BUTTON_SIZEX;
	pVertices[5].y = BUTTON_SIZEY;
	pVertices[5].z = 0.0f;
	pVertices[5].u = 1.0f;
	pVertices[5].v = 1.0f;

	for(int i=0; i<6; i++) {
		pVertices.dDiffuse = D3DCOLOR_ARGB(125, 0, 255, 255);
	}
	if(FAILED(m_pButton->Unlock())) {
		return false;
	}
[/SOURCE]
and then I'm rendering that vertex buffer with this code:
[SOURCE]
//CBase::m_pDevice->SetTexture(0, NULL);
	CBase::m_pDevice->SetStreamSource(0, m_pButton, 0, sizeof(TextureVertex_t));
	CBase::m_pDevice->SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);
	CBase::m_pDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);
[/SOURCE]
Does it have something to do with me not giving it a texture to put on it? I'm sort of stuck. Thanks for the help in advance.

Share this post


Link to post
Share on other sites
Advertisement
The easiest is to use XYZRHW coordinates for your 2D parts. This makes x and y specified in pixels, z needs to be between 0 and 1, and w should be 1.0f. You can disable Z temporarily to ensure your 2D parts remain on top of everything else, or try using a 0 (or near 0...maybe some cards discard 0 depth) for Z.

To hit test, just get the mouse coord and test vs. your box, since they're both in pixels, it's easy.

Share this post


Link to post
Share on other sites
Quote:
Original post by 31337
I am trying to render a 3D scene in the background behind an interface of 2D buttons. I also want to be able to hit test the boxes vs the mouse very easily. What is the easiest way to do this?


There is code in the latest SDK (9.0c - Summer Update 2004) which does exactly what you want, which is part of the new sample framework.

You can use push buttons, radio buttons, check boxes, edit controls, combo boxes etc.

All hit testing and message handling is done for you.

HTH,
Cambo_frog

Share this post


Link to post
Share on other sites
that's the new gui system isn't it?

anyway, why not use sprites, blit to screen coordinates (with or without alpha). Then to test mouseover use 2d mouse position, to test a click check for mouseover and a click. Simple as that...
In fact, if you don't need transparency, you could use a surface and call a copyrect...

Share this post


Link to post
Share on other sites
Thanks for the help guys. I am most interested in:

The easiest is to use XYZRHW coordinates for your 2D parts. This makes x and y specified in pixels, z needs to be between 0 and 1, and w should be 1.0f. You can disable Z temporarily to ensure your 2D parts remain on top of everything else, or try using a 0 (or near 0...maybe some cards discard 0 depth) for Z.[/QUOTE]

What do I do for my matrices? Since I'm setting 1.0 to W does that make it so that its already transformed? What exactly are XYZRHW coordinates? Do I use hardware vertex processing for the vertex buffer or software? Thanks for the help.

Share this post


Link to post
Share on other sites
XYZRHW is used for pre-transformed vertices. Not just transformed by world,view,proj, but divided by W and run through the viewport scaling matrix too... which means, they're exact pixel locations. Your world,view,proj matrices should not matter, as the vertex will not be transformed again.

RHW stands for Reciprocal of Homogenous W. I don't pretend to know what that means (except maybe it implies dividing by W).

Use whatever vertex processing you're already using for everything else.

Share this post


Link to post
Share on other sites
Ok so I've tried getting the already transformed polygons to work so that they will appear on top, and I have this major problem. For some reason the polygons pop up for like the first frame and then disappear, and only when I render the buttons for the interface (2D) FIRST, but when I render it second I don't even see anything. What am I doing that's messing this up? I've posted by loading code below for the 2D:

[SOURCE]if(FAILED(CBase::m_pDevice->CreateVertexBuffer(sizeof(ColorVertexW_t)*6, 0,
D3DFVF_XYZRHW | D3DFVF_DIFFUSE, D3DPOOL_DEFAULT, &m_pButton, NULL))) {
return false;
}
ColorVertexW_t *pVertices;
if(FAILED(m_pButton->Lock(0, 0, (void **)&pVertices, 0))) {
return false;
}
pVertices[0].x = 0.0f;
pVertices[0].y = 0.0f;
pVertices[0].z = 0.5f;
//pVertices[0].u = 0.0f;
//pVertices[0].v = 0.0f;

pVertices[1].x = BUTTON_SIZEX;
pVertices[1].y = 0.0f;
pVertices[1].z = 0.5f;
//pVertices[1].u = 1.0f;
//pVertices[1].v = 0.0f;

pVertices[2].x = 0.0f;
pVertices[2].y = BUTTON_SIZEY;
pVertices[2].z = 0.5f;
//pVertices[2].u = 0.0f;
//pVertices[2].v = 1.0f;

pVertices[3].x = 0.0f;
pVertices[3].y = BUTTON_SIZEY;
pVertices[3].z = 0.5f;
//pVertices[3].u = 0.0f;
//pVertices[3].v = 1.0f;

pVertices[4].x = BUTTON_SIZEX;
pVertices[4].y = 0.0f;
pVertices[4].z = 0.5f;
//pVertices[4].u = 1.0f;
//pVertices[4].v = 0.0f;

pVertices[5].x = BUTTON_SIZEX;
pVertices[5].y = BUTTON_SIZEY;
pVertices[5].z = 0.5f;
//pVertices[5].u = 1.0f;
//pVertices[5].v = 1.0f;

for(int i=0; i<6; i++) {
pVertices.w = 1.0;
pVertices.dDiffuse = D3DCOLOR_XRGB(255, 255, 255);
}
if(FAILED(m_pButton->Unlock())) {
return false;
}
return true;[/SOURCE]


Below this is the drawing code:
[SOURCE]
CBase::m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true);

CBase::m_pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
CBase::m_pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

CBase::m_pDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
CBase::m_pDevice->SetRenderState(D3DRS_FOGENABLE, (DWORD)false);
//CBase::m_pDevice->SetRenderState(D3DRS_FOGCOLOR, (DWORD)ARGB(255, 0, 0, 0));
//CBase::m_pDevice->SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
//CBase::m_pDevice->SetRenderState(D3DRS_FOGSTART, (*(DWORD *)&fValue));
//fValue = 10.0;
//CBase::m_pDevice->SetRenderState(D3DRS_FOGEND, (*(DWORD *)(&fValue)));

CBase::m_pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
CBase::m_pDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
//CBase::m_pDevice->SetTexture(0, NULL);
CBase::m_pDevice->SetStreamSource(0, m_pButton, 0, sizeof(ColorVertexW_t));
CBase::m_pDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
CBase::m_pDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);
[/SOURCE]

Share this post


Link to post
Share on other sites
I made it so that it stopped rendering the 3D scene in the background and now it works... why??

Share this post


Link to post
Share on other sites
Some render state must be getting set that's interfering. Try adding in little sections of the code until it breaks.

Eventually you should be able to narrow down what's causing the problem, at which point you'll probably say "D'oh! Why didn't I think of that sooner"...

Share this post


Link to post
Share on other sites
Yah I figured it out, it kinda makes me angry but it was that I had a texture set and wasn't giving it u v coordinates. Doh! Thanks for the help.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!