Sign in to follow this  

help with ui mouse intersection

This topic is 4355 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

hi, i have one problem with my UI and that problem is this. i think i am caluclating my intersection wrong. when i have a button in my window, i cant click everywhere on that button. only half of that button i can click on.

void UIControl::getAbsPos(D3DXVECTOR2 *position)
{
	position->x += this->getX();
	position->y += this->getY();

	if(this->parent)
		this->parent->getAbsPos(position);
}

bool UIControl::cursorIntersection(int x, int y)
{
	D3DXVECTOR2 cabs;
	cabs.x = 0;
	cabs.y = 0;

	this->getAbsPos(&cabs);

	if((x >= cabs.x) && (x <= (cabs.x + this->getWidth())))
		if((y >= cabs.y) && y <= ((cabs.y + this->getHeight())))
			return true;

	return false;
}

//in a message loop
if(this->cursorIntersection(LOWORD(lParam), HIWORD(lParam))
{
   //code
}


please help me thanks in advanced

Share this post


Link to post
Share on other sites
Quote:
Original post by 31337noob
when i have a button in my window, i cant click everywhere on that button. only half of that button i can click on.

To investigate the problem furthur...:

What half is active, and where is the button located than?

How does the active area change if you re-locate the button a little bit?

Where is the origin of the co-ordinate system in use (left top, left bottom, middle of the window), and is the origin of the x,y parameters the same?

(I assume the following to play no role, since most often a control is missed totally if this would be wrong.) To what direction do the co-ordinates grow? (Say, do your pointer co-ordinates grow in the same direction as the control's co-ordinates do?)

Quote:
Original post by 31337noob
i think i am caluclating my intersection wrong.

The snippet you've posted seems me correct. I expect the problem to be caused elsewhere.

Share this post


Link to post
Share on other sites
Quote:
Original post by haegarr
Quote:
Original post by 31337noob
when i have a button in my window, i cant click everywhere on that button. only half of that button i can click on.

To investigate the problem furthur...:

What half is active, and where is the button located than?

How does the active area change if you re-locate the button a little bit?

Where is the origin of the co-ordinate system in use (left top, left bottom, middle of the window), and is the origin of the x,y parameters the same?

(I assume the following to play no role, since most often a control is missed totally if this would be wrong.) To what direction do the co-ordinates grow? (Say, do your pointer co-ordinates grow in the same direction as the control's co-ordinates do?)

Quote:
Original post by 31337noob
i think i am caluclating my intersection wrong.

The snippet you've posted seems me correct. I expect the problem to be caused elsewhere.



How does the active area change if you re-locate the button a little bit?
it does change but still doesnt get the whole button

Where is the origin of the co-ordinate system in use (left top, left bottom, middle of the window), and is the origin of the x,y parameters the same?

top-left

Share this post


Link to post
Share on other sites
Quote:
Original post by 31337noob
How does the active area change if you re-locate the button a little bit?
it does change but still doesnt get the whole button

Ok, but the question is _how_ does it change. E.g. if you shift the button to the right / bottom (say you increase the value of getX() / getY()), does the active area grow or shrink? Does it grow / shrink exactly by the amount of the shift? So you can determine whether there is an absolute or a relative border.

Is the active area always to the right / bottom? Is the button totally active if you shift it far enough into one of the quadrants? Then you may have a sign resp. origin problem.

Since the posted code isn't IMHO sufficient to locate the problem, I suggest you to do the following: Restrict the UIControl to have none or at most one parent. Locate it so that it is in (0,0) and covers the whole window area. Set a breakpoint into UIControl::cursorIntersection, and investigate the values of x,y and cabs for various clicks. Then you should follow the questions above. From the results you could determine the cause of the problem.

Share this post


Link to post
Share on other sites
ok, here is what i know so far.

i put the parent window at (0,0) and the button at (0,0)

when i move the window to the bottom of the screen, i can go below the picture of the button and it can be clicked on. how can that happen if i am not even on the button. ok, now if i move the window to the top left, i can click on the very top of the button but i cant click on the bottom of the button or the right part of the button. now if i move the window to the right, i still cant click on the right part of the button.

i do know why it doesnt register the right part though. the width and height is a little off.

so i think the problem is the absoulte function.

so what do you think?

please help.


what do i do next?

i bet if we get the abs thing working the whole thing will be working.

Share this post


Link to post
Share on other sites
Quote:
ok, this is werider. i just found out it doesnt do this werid problem when its in fullscreen. ok so how can i deal with it when its not in fullscreen.

Just a quick glance at your post..

in fullscreen mode, dx screen coordinates are same as windows screen coordinate, whereas, in windowed mode, dx screen coord. are not equal to windows screen coord. you might be missing clicking on button just because of that.

Share this post


Link to post
Share on other sites
In fullscreen screen mode the mouse co-ordinates and the window co-ordinates are the same. This let me think that the co-ordinates you use may be related to the screen and not to the window. (EDIT: Ahem, Taha Ansari was quicker in stating this :)

Please consider this:

(1) In UIControl::cursorIntersection do a cout on x and y. Position the button in the upper left corner of the window. Compile, run, and move the window to the upper left corner of the screen. Click in the upper left corner of the button. Are the printed co-ordinates near at zero, or else are their values in the range of the border thicknesses of the window? If so, you have first to subtract the window's border thicknesses from x and y. (You said, 0,0 is in the upper left corner, right?)

(2) Now click in the lower right corner of the button. If you subtract the printed values from those printed earlier at clicking in the upper left corner, are the differences as big as the size of the button?

(3) The window being in the upper left corner. Click on the center of the button and remember the printed values. Then move the window to the lower right corner of the screen. Click again on the center of the button. Do the printed values change significantly (say more than a few pixels)? If so, then the mouse co-ordinates are screen related, and not window related, and you have to subtract the window position from x and y.

(4) Please post more of the code that is related to the problem.

Share this post


Link to post
Share on other sites
ok, i have a picture thats 100,50 and i did what you said. i put my mouse at the upper left hand corner and i get 0,0 and then i move my mouse the lower right of the button and i get 127,61. i think directx just drawn the sprite a little bigger then 100,50. its the same in fullscreen the width is bigger and so is the height

Share this post


Link to post
Share on other sites
Quote:
Original post by 31337noob
ok, i have a picture thats 100,50 and i did what you said. i put my mouse at the upper left hand corner and i get 0,0 and then i move my mouse the lower right of the button and i get 127,61. i think directx just drawn the sprite a little bigger then 100,50. its the same in fullscreen the width is bigger and so is the height

That sounds that not the mouse is the problem (at least not alone) but the projection set-up. Please post that piece of code (also of interest is the VIEW matrix set-up). Good would be an orthogonal projection with a widht/height equally to the width/height of the window, so that you could work with pixel co-ordinates directly. But I expect your set-up being something other, independent on the window size.

[Edited by - haegarr on December 21, 2005 1:03:12 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by haegarr
Quote:
Original post by 31337noob
ok, i have a picture thats 100,50 and i did what you said. i put my mouse at the upper left hand corner and i get 0,0 and then i move my mouse the lower right of the button and i get 127,61. i think directx just drawn the sprite a little bigger then 100,50. its the same in fullscreen the width is bigger and so is the height

That sounds that not the mouse is the problem (at least not alone) but the projection set-up. Please post that piece of code (also of interest is the VIEW matrix set-up). Good would be an orthogonal projection with a widht/height equally to the width/height of the window, so that you could work with pixel co-ordinates directly. But I expect your set-up being something other, independent on the window size.


do you mean this?


D3DXMATRIX projMatrix;
D3DXMatrixPerspectiveFovLH( &projMatrix, D3DX_PI / 4, (float)d3dpp.BackBufferWidth / (float)d3dpp.BackBufferHeight, 1.0f, 5000.0f);
this->pDevice->SetTransform( D3DTS_PROJECTION, &projMatrix );

Share this post


Link to post
Share on other sites
Quote:
Original post by 31337noob
do you?

Yes, in part. (Sorry, I was busy yesterday.)

Perhaps I lack enough knowledge of what you are doing with your app. However, I assume you are making a GUI, maybe a kind of 2D overlay or something similar?

You set-up a perspective projection. As you'll already know, perspective projections do a depth scaling; there is only one specific distance where the depth scaling is 1. Now it depends: Either you want to have your GUI element like a bill board integrated into the scene. That is, it faces always the camera, but it should be hidden by "normal" 3D scene elements (say, a tree trunk in front of the button should hide it). Then using perspective transformation is ok. However, in this case you have to consider perspective depth shortening also for your mouse click, since the click occurs onto the plane where depth shortening is 1 but does track all depth values on a straight line _not_ perpendicular to the screen! In other words, in such a case you have to scale your click co-ordinates depending on the GUI element's depth value before comparing them with the button co-ordinates.

Or (the more likely case): Your GUI is always in front of the 3D scene, like an overlay (e.g. a HUD) or a GUI even without 3D in behind. Your wish is to draw 2D GUI elements with pixel accuracy. (All of the following belongs to this case).

In such case I suggest not to use the perspective projection at all (also it is possible, too), but to use the orthogonal projection. This kind of projection has the advantage that it does not show any depth scaling. You could set it up using the D3DXMatrixOrthoLH function. Without proven, I assume something like
D3DXMatrixOrthoLH(&projMatrix,widhtInPixels,heightInPixels,-1,1);
should be possible (you could also take into account of using the "OffCenter" variant of this routine).

However, in the case of ortho projection you also have to set-up a suitable view matrix. I suggest the view matrix to do 2 things (you have to ignore the second thing if you use the "OffCenter" variant of projection): mirror the y axis since you want the y co-ordinate system of the GUI to grow from top to bottom, right?
D3DXMatrixScaling(&viewScale,1,-1,1);
computes such a matrix. But notice that doing so will probably require texture co-ordinates to be adapted, too). You also wants the origin to be located in the upper left corner, instead of the center of the screen, so you also have to translate the view by
D3DXMatrixTranslation(&viewTranslate,widhtInPixels/2,0.5f*heightInPixels/2,0);
(please notice that I write this from mind, not copying it from a tested app).

After setting up the view matrix from the proper product of those stuff above, it should be possible to push GUI geometry in a co-ordinate system (0,0,0) in the upper left and (widht-1,height-1,0) in the lower right corner. Render the GUI elements without depth test and in back to front order to get the overlapping right.

[Edited by - haegarr on December 23, 2005 4:15:35 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by 31337noob
so, what is the difference between projection and ortho?

Your question isn't totally correct: Projection is the general term, and "ortho" projection is just a special kind of projection. In the given sense projection means to reduce the dimensionality of 3 (the scene) downto 2 (the screen). Think of a ray racer: All locations of the 3D scene hit by a particular ray are mapped onto the same pixel of the screen, where simply the nearest hit hides the other ones.

There are many different kinds of projections. Usually the _perspective_ projection is used to display 3D scenes. Perspective projection does the depth shortening, so that more distant objects appear smaller than nearer objects does. The projectors (a name of the aforementioned rays) emanate at a single origin, namely the location of the camera, and spread out into the scene. This could be expressed in principle (although more complicated in the APIs) by scaling the x,y co-ordinates by the depth value (after transformation into the camera space):
x' := x/z
y' := y/z
In this example only at z=1 there is no scaling; all other z values will grwo/shrink the co-ordinates.

The _orthogonal_ projection uses projectors that are parallel and orthogonal to the screen (so they don't have a common origin). The scaling could be expressed by
x' := x
y' := y
and hence any size is depth independent. That makes the orthogonal projection more suitable for normal (i.e. pixel accurate) GUI rendering.

[Edited by - haegarr on December 25, 2005 8:47:10 AM]

Share this post


Link to post
Share on other sites

This topic is 4355 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this