• Advertisement

Archived

This topic is now archived and is closed to further replies.

Snap to grid problem!

This topic is 5191 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 all! I''m creating an editor for my game. The editor has several modes including line drawing mode and polygon mode (like MSPaint''s polygon mode). Anyway, I''m allowing the user the option to use snap-to-grid, which snaps the endpoint of the line (that the user drew) to the nearest gridpoint. Here''s my grid drawing function:

//DrawGrid

void CObliteration::DrawGrid()
{
	int offsetX = -(editorScreenX%16);
	int offsetY = -(editorScreenY%16);

	for (int x=0;x<38;x++)
	{
		for (int y=0;y<38;y++)
		{
		//	RECT dest = {(x*32)-1+offsetX,(y*32)-1+offsetY,

				//(x*32)+1+offsetX,(y*32)+1+offsetY};


		//	SpriteIndex[SI_PIXEL].Draw(dest,COL_BLACK,0);

			DrawPixel((x*16)+offsetX,(y*16)+offsetY,COL_BLACK);

		}
	}

}
and here is my snap to grid function:

//snap to grid

void CObliteration::SnapToGrid(POINT2D* p)
{
	if (!editorSnapToGrid)
		return;


	int dx = p->x%16;
	int dy = p->y%16;
	
	int ex = editorScreenX%16;
	int ey = editorScreenY%16;


	p->x -= dx;
	p->y -= dy;

	if (dx >= 8 && ex < 8)	
		p->x += 16;
	if (dy >= 8 && ey < 8)
		p->y += 16;



}
editorScreenX and editorScreenY are the coordinates of the "camera" of the editor (current position in the editor world). POINT2D* p is the mouse position, (relative to the client, not yet transformed in world space) The problem is, at editorScreenX and editorScreenY coords like (360,-276), it snaps the POINT2D not to the nearest gridpoint, but to the greater gridpoint (for example if the point is close to point 1 on the left, it snaps to point 2 on the right, whereas it is supposed to snap to point 1, because it is closer to it). Thanx in advance! Ciph

Share this post


Link to post
Share on other sites
Advertisement
I''m in a very big rush so I could not read your entire post, nor do I know if this will help you but..

If I want to take a point and snap it to a grid, I simply do this (psuedo-code):


X = int(mouseX / tileWidth) * tileWidth
Y = int(mouseY / tileHeight) * tileHeight

Share this post


Link to post
Share on other sites
that''s the quick and easy way - but it doesn''t snap a point to the nearest tile - it only snaps it to the next lowest "integer" tile.

For example, two gridpoints with points (0,0), and (32,0)

It would snap (28,0) to (0,0), not (32,0), as it should.

Share this post


Link to post
Share on other sites
Simply add tileWidth/2 like this.

X = int((mouseX / tileWidth)+tileWidth/2) * tileWidth
Y = int((mouseY / tileHeight))+tileHeight/2) * tileHeight

This will round at 0.0 to 0.49999 -> inferior and 0.5 to 0.9999 ->superior


[edited by - ph0ngwh0ng on August 15, 2003 3:13:56 PM]

Share this post


Link to post
Share on other sites

p->x = int((p->x + 8) / 16) * 16; // add half a square, then round down

p->y = int((p->y + 8) / 16) * 16; // ditto



will snap 'p' to the nearest grid point (assuming gridsize = 16)
for other size grids, adjust the 8 and 16.

EDIT:
Following the brackets through:
first, add half a tile in each direction. if x = 3, it will become 11, let the int function/cast round it down, it ends up as 0, the nearest point
if x = 10, it becomes 18, and int will round it to 16, the next grid point.

HTH


[edited by - blacksheep on August 15, 2003 4:43:42 PM]

Share this post


Link to post
Share on other sites
First of all I don''t see the point of the whole ex & ey part - why should the camera position affect where to snap the point? Normally the grid is an absolute thing, not relative to the current view position.

Anyway I think your problem comes from the sometimes unintuitive results of using % with negative numbers. Take for example the point (0,-28). It should be snapped to (0,-32) since that''s the closest multiple of 16. With your algorithm here''s what happens:

int dy = -28 % 16; // the result will be -12 not 4
p->y -= dy; // the result will be -16 not -32

if (dy >= 8) ... // not true since dy == -12

So now it has snapped to the higher point (0,-16) instead of the closer point (0,-32).

Share this post


Link to post
Share on other sites
I use a function called RInt (Round Int) to make sure that it snaps to the right grid point. This is it:

int RInt(float u)
{

int i = (int)u;
float f = u - i;
if(f >= 0.5) i++;
return(i);

}
This is my code for snapping to the grid:

void SnapToGrid(vec3_t v1, float fGridSize)
{

v1[0] = RInt(v1[0] / fGridSize) * fGridSize;
v1[1] = RInt(v1[1] / fGridSize) * fGridSize;
v1[2] = RInt(v1[2] / fGridSize) * fGridSize;

}
v1 can be any point, but I usually get my points from OpenGL with gluUnProject(). You could also get points by adding the camera movement on to the mouse position.

It works like this:
 |      |     |      |
-0------0- -0------0-
| * | | |
| | | |
| | | * |
-0------0- -0------0-
| | | |
The asterisks are mouse clicks. Without RInt, both points are snapped to the grid point in the top left hand corner. RInt compensates for the fact that integer casting doesn't round down...



Coding Stuff ->  [ iNsAn1tY Games | DarkVertex | How To Do CSG | Direct3D Vs. OpenGL | Google ]
Fun Stuff    ->  [ Evil T-Shirts | Stick-Based Comedy | You're Already Here | The Best Film Reviews ]


[edited by - iNsAn1tY on August 15, 2003 5:26:08 PM]

Share this post


Link to post
Share on other sites
yeah i removed the ex and ey part. so i should take the abs of dx and dy when comparing then to 8?

Share this post


Link to post
Share on other sites
Cipher:

If all you want is to get the SnapToGrid function to work, just replace the main body of the function (after the IF check) with the two lines I originally posted.


Insanity:
Your code is essentially the same as mine, although I think yours is slower due to the overhead from calling RInt(). Also, RInt is inefficient because of the unnecessary if(). Try this:


int RInt(float u)
{
int i = int(u + 0.5);
return(i);
}

// or this, which saves stack space by not creating ''i''

int RInt(float u)
{
return int(u + 0.5); // may give compiler warning

}

Share this post


Link to post
Share on other sites
Yes - I fixed it. Thanks to all of you who gave me insight into this!

Special thanx to dobbs - who was the catalyst for my solution (man this feels like da grammys).

And thanks to...

Anyway, yeah.
Insanity - your solution didn''t work, although it supposed to...maybe it doesn''t fit into my engine. thanx anyways


//snap to grid

void CObliteration::SnapToGrid(POINT2D* p)
{
if (!editorSnapToGrid)
return;


int dx = p->x%16;
int dy = p->y%16;

if (dx < 0)
{
//inverse and take the absolute value at the same time

dx = abs(dx);
dx = 16-dx;
}
if (dy < 0)
{
dy = abs(dy);
dy = 16-dy;
}

p->x -= dx;
p->y -= dy;


if (dx >= 8)
p->x += 16;
if (dy >= 8)
p->y += 16;



}


OH yeah, does anybody know whats the cylces of a % operation compared to a mul or div?
Thanx,

Ciph


Time to move on.

Share this post


Link to post
Share on other sites
Glad to see you've got it working, Cipher. BlackSheep, thanks for the optimization tip. I'm still in the writing stage, and haven't done much optimization yet. Probably wouldn't have caught that one anyway ...



Coding Stuff ->  [ iNsAn1tY Games | DarkVertex | How To Do CSG | Direct3D Vs. OpenGL | Google ]
Fun Stuff    ->  [ Evil T-Shirts | Stick-Based Comedy | You're Already Here | The Best Film Reviews ]


[edited by - iNsAn1tY on August 16, 2003 6:49:47 AM]

Share this post


Link to post
Share on other sites
gridstepping==gridspacing


void CKernel::SnapToGrid(int &x,int &y,CViewInfo cInfo)
{
float xdiv=(float)x/(float)cInfo.m_iGridStepping;
float ydiv=(float)y/(float)cInfo.m_iGridStepping;
float xmed=floor(xdiv);
float ymed=floor(ydiv);
if(xdiv<=(xmed+0.5))
x=(int)(cInfo.m_iGridStepping*xmed);
else
x=(int)(cInfo.m_iGridStepping*(xmed+1));

if(ydiv<=(ymed+0.5))
y=(int)(cInfo.m_iGridStepping*ymed);
else
y=(int)(cInfo.m_iGridStepping*(ymed+1));
}

Share this post


Link to post
Share on other sites

  • Advertisement