Sign in to follow this  

mouse detection

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

What is the best way to tell what tile the mouse has clicked on in a 3D tile based map? The only thing I could think of was giving a color to each tile and then rendering the colored map and seeing what color was pressed on. Does anyone have better methods? Thanks.

Share this post


Link to post
Share on other sites
Well, if you use the depth buffer you can use something like gluUnProject() (since it seems you're using OpenGL from your other posts). With that you can probably pretty easily map the 3D coordinate to a tile.

Share this post


Link to post
Share on other sites
But even if I find the 3D coordinate for the mouse position, how do I relate that to a certain tile?
Thanks.

Share this post


Link to post
Share on other sites
Seeing as you've said nothing about your tile system it's hard to say. I don't know if you're using square tiles, triangular tiles, hexagonal tiles, rectangular tiles, pentagonal tiles or tesselated cow tiles. I don't know if you have tiles set in a single flat layer, multiple parallel equidistant flat layers, a single layer with sloped tiiles, multiple sloped tile layers or a tile projection as a surface of a klein bottle.

Share this post


Link to post
Share on other sites
I have a 128X128 square tile map, the map is implemented in 3D with a hight map, the x and z coordinates are the coordinates of the actual tiles, and the y axis is the height. I hope that I made myself clear, please ask if I didn't.
Thanks.

Share this post


Link to post
Share on other sites
Think about it. You can use gluUnproject() to get the x, y and z coordinates from the depth buffer and mouse position. Your tiles are defined by their x and z coordinates.

Share this post


Link to post
Share on other sites
So I have to search through all of the tiles untill I find one with the right coordinates? My tiles are represented by an array (map[128*128]). To draw it I'm just getting the y from the height map and the (x,z) by looping through all the rows and multipying the number by a constant. For example, the (x,z) of tile map[5*120] would be (a*5, b*120). Should I de drawing it another way? Sorry for not catching on.
Thanks.

Share this post


Link to post
Share on other sites
What do you get if you divide the x and z of the returned spatial coordinates by the size of your tiles?

Share this post


Link to post
Share on other sites
Oh I see, I should divide the x and z by the constants and then round off to the nearest one? Can you confirm that?
Thanks.

Share this post


Link to post
Share on other sites
Ok, so now I tried the code: (In the test I'm drawing the map along the x,y coords)


GLdouble modelMatrix[16];
GLdouble projMatrix[16];
GLint viewport[4];
GLdouble objx,objy,objz;

glGetDoublev(GL_MODELVIEW_MATRIX,modelMatrix);
glGetDoublev(GL_PROJECTION_MATRIX,projMatrix);
glGetIntegerv(GL_VIEWPORT,viewport);

gluUnProject(
mouse_x,
480-mouse_y,
0,
modelMatrix,
projMatrix,
viewport,
&objx,
&objy,
&objz);



to draw my map from the map[i*j] in 3D I do:


for(i=0;i<MAP_SIZE;i+=1)
for(j=0;j<MAP_SIZE;j+=1)
{
glLoadIdentity();
glTranslatef(-0.55 + 0.01*i, -0.55 + 0.01*j,-1.5f);
Object(0.005,0.005); //draw square
}



but when I put the mouse over for example the (0,0) part (bottomleft) of the map, the mouse coord is (108,29) and for the 3D coord (after adding 0.55 and divideing by 0.01 both the x and y) I get (73.41,73.58,0.5).
First of all, why do I get such big numbers? Also, why 0.5?
And another question - If I call a glLoadMatrix() after drawing the map will it mess things up?
Thanks for your patiance!

Share this post


Link to post
Share on other sites
I tried somemore and it still isn't working. There is something that I don't understand, do I have to call the glUnProject before I do a glLoadIdentity ?
Because I'm calling glLoadIdentity before drawing every tile. Could that be a problem?
Also, can this method be used if there're hills?
Thanks.

[Edited by - daniel_i_l on January 12, 2006 5:49:35 PM]

Share this post


Link to post
Share on other sites
I tried to find the mouse positon with a recursive function. First it draws the map in 4 parts in 4 different colors. I sees what color the mouse is on and the divides that part in four untill the function gets only 4 squares (2X2), then it sees which one one chosen and that is the mouse position. Here's the code:

void PickTile(int bottom_left_x, int bottom_left_y, int top_right_x, int top_right_y)
{
int middle_x, middle_y;
GLint viewport[4];
GLubyte pixel[3];

middle_x = (top_right_x - bottom_left_x) / 2;
middle_y = (top_right_y - bottom_left_y) / 2;

glDisable(GL_DITHER);
//draw colored map
for(i=bottom_left_x;i<top_right_x;i+=1)
for(j=bottom_left_y;j<bottom_left_y;j+=1)
{
glLoadIdentity();
if((i <= middle_x)&&(j <= middle_y))
glColor3ub(1,0,0);
if((i > middle_x)&&(j <= middle_y))
glColor3ub(0,1,0);
if((i > middle_x)&&(j > middle_y))
glColor3ub(0,0,1);
if((i <= middle_x)&&(j > middle_y))
glColor3ub(1,1,1);

glTranslatef(-0.55 + 0.01*i, -0.55 + 0.01*j,-1.5f);
Object(0.005,0.005);

}
glEnable(GL_DITHER);

//read color
glGetIntegerv(GL_VIEWPORT,viewport);
glReadPixels(mouse_x,viewport[3]-mouse_y,1,1,GL_RGB,GL_UNSIGNED_BYTE,(void *)pixel);
//check color

if(top_right_x - bottom_left_x > 2)
{
if((pixel[0] > 100) && (pixel[1] < 100))
PickTile(bottom_left_x, bottom_left_y, middle_x, middle_y);
if((pixel[1] > 100) && (pixel[0] < 100))
PickTile(middle_x, bottom_left_y, top_right_x, middle_y);
if((pixel[2] > 100) && (pixel[1] < 100))
PickTile(middle_x, middle_y, top_right_x, top_right_y);
if((pixel[0] > 100) && (pixel[1] > 100))
PickTile(bottom_left_x, middle_y, middle_x, top_right_y);
}
else
{
if((pixel[0] > 100) && (pixel[1] < 100))
picked_x = bottom_left_x; picked_y = bottom_left_y;
if((pixel[1] > 100) && (pixel[0] < 100))
picked_x = top_right_x; picked_y = bottom_left_y;
if((pixel[2] > 100) && (pixel[1] < 100))
picked_x = top_right_x; picked_y = top_right_y;
if((pixel[0] > 100) && (pixel[1] > 100))
picked_x = bottom_left_x; picked_y = top_right_y;
}
}



When the mouse is pressed I call : PickTile(0,0,128,128);
but the program crashes, why?
Thanks.

Share this post


Link to post
Share on other sites
A few things seem weird in your code:

Quote:
for(j=bottom_left_y;j<bottom_left_y;j+=1)

The lower and upper bound are the same...

Quote:

if((pixel[0] > 100) && (pixel[1] < 100))
picked_x = bottom_left_x; picked_y = bottom_left_y;
if((pixel[1] > 100) && (pixel[0] < 100))
picked_x = top_right_x; picked_y = bottom_left_y;
if((pixel[2] > 100) && (pixel[1] < 100))
picked_x = top_right_x; picked_y = top_right_y;
if((pixel[0] > 100) && (pixel[1] > 100))
picked_x = bottom_left_x; picked_y = top_right_y;

You forgot most surely the {}

Jc

Share this post


Link to post
Share on other sites
Thanks,
I fixed those mistakes and now the program only searches down the bottom_left corner. If I hold the mouse at any other position then the program freezes?!
Thanks.

EDIT: The problem was that I should have added the bottom coordinates to the middle.
Now I have one problem left, the function is a little slow, is there a way to speed it up, or another way at all?
Thanks!

[Edited by - daniel_i_l on January 14, 2006 1:18:19 PM]

Share this post


Link to post
Share on other sites

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