check if entity is within rotated box

Posted By: Reconnoiter

check if entity is within rotated box - 09/28/16 16:02

Hello,

I know its easy to check if an entity's center is within a (large) box by comparing its xyz position with the box position + box size. But how to do this if I rotate the box by e.g. 45 degrees?
Posted By: txesmi

Re: check if entity is within rotated box - 09/28/16 17:02

Hi,
you might calculate the offset from the cube to the entity, rotate it the inverse rotation of the cube and check if it is inside the unrotated cube bounds.

Salud!
Posted By: Reconnoiter

Re: check if entity is within rotated box - 09/28/16 19:08

That sounds like a good plan, I am going to try that out. However before I try, I want to draw the box and rotate it. However in the test code below the vec_rotate doesn't rotate the quad (just for testing) properly:

Code:
vec_fill(vMin, -200);
vec_fill(vMax, 200);
vec_rotate(vMin, vector(camera.pan, 0, 0));
vec_rotate(vMax, vector(camera.pan, 0, 0));
draw_line3d(vector(vMin.x, vMin.y, vMin.z),NULL,100);  
draw_line3d(vector(vMax.x, vMin.y, vMin.z),drawcolor_vec,100);
draw_line3d(vector(vMax.x, vMax.y, vMin.z),drawcolor_vec,100); 
draw_line3d(vector(vMin.x, vMax.y, vMin.z),drawcolor_vec,100); 
draw_line3d(vector(vMin.x, vMin.y, vMin.z),drawcolor_vec,100);



I am probably making some math error.
Posted By: txesmi

Re: check if entity is within rotated box - 09/29/16 14:22

yes you are grin

In the case your cubes are perfect, there is a simplified way to compute vertex positions.

Code:
90 degrees rotation
x' = -y;
y' = x;



so you should draw your square as follows

Code:
draw_line3d(vector(vMax.x, vMax.y, vMin.z),NULL,100);  
draw_line3d(vector(-vMax.y, vMax.x, vMin.z),drawcolor_vec,100);
draw_line3d(vector(-vMax.x, -vMax.y, vMin.z),drawcolor_vec,100); 
draw_line3d(vector(vMax.y, -vMax.x, vMin.z),drawcolor_vec,100); 
draw_line3d(vector(vMax.x, vMax.y, vMin.z),drawcolor_vec,100);



Salud!
Posted By: Reconnoiter

Re: check if entity is within rotated box - 09/29/16 15:55

Okay I am almost there grin , tnx so far, but its now always draws an square-like cube, but I want to allow a rectangle-like cube too. How to change this? Here is the code by the way but an example will do to (please note that vec is the position the cube is in the map):

Code:
vec_lerp(vec, vMin, vMax, 0.5);
draw_point3d(vec, COLOR_RED, 100, 50);

vec_sub(vMin, vec);
vec_sub(vMax, vec);
vec_rotate(vMin, vector(camera.pan, 0, 0));
vec_rotate(vMax, vector(camera.pan, 0, 0));

//bottom
draw_line3d(vector(vec.x + vMax.x, vec.y + vMax.y, vec.z + vMin.z),NULL,100);  
draw_line3d(vector(vec.x + -vMax.y, vec.y + vMax.x, vec.z + vMin.z),drawcolor_vec,100);
draw_line3d(vector(vec.x + -vMax.x, vec.y + -vMax.y, vec.z + vMin.z - k),drawcolor_vec,100); 
draw_line3d(vector(vec.x + vMax.y, vec.y + -vMax.x, vec.z + vMin.z),drawcolor_vec,100); 
draw_line3d(vector(vec.x + vMax.x, vec.y + vMax.y, vec.z + vMin.z),drawcolor_vec,100);
//top
draw_line3d(vector(vec.x + vMax.x, vec.y + vMax.y, vec.z + vMax.z),drawcolor_vec,100);
draw_line3d(vector(vec.x + -vMax.y, vec.y + vMax.x, vec.z + vMax.z),drawcolor_vec,100);
draw_line3d(vector(vec.x + -vMax.x, vec.y + -vMax.y, vec.z + vMax.z),drawcolor_vec,100); 
draw_line3d(vector(vec.x + vMax.y, vec.y + -vMax.x, vec.z + vMax.z),drawcolor_vec,100); 
draw_line3d(vector(vec.x + vMax.x, vec.y + vMax.y, vec.z + vMax.z),drawcolor_vec,100);
//other lines
draw_line3d(vector(vec.x + -vMax.y, vec.y + vMax.x, vec.z + vMin.z),NULL,100);  
draw_line3d(vector(vec.x + -vMax.y, vec.y + vMax.x, vec.z + vMax.z),drawcolor_vec,100);
draw_line3d(vector(vec.x + -vMax.x, vec.y + -vMax.y, vec.z + vMin.z),NULL,100);  
draw_line3d(vector(vec.x + -vMax.x, vec.y + -vMax.y, vec.z + vMax.z),drawcolor_vec,100);
draw_line3d(vector(vec.x + vMax.y, vec.y + -vMax.x, vec.z + vMin.z),NULL,100);  
draw_line3d(vector(vec.x + vMax.y, vec.y + -vMax.x, vec.z + vMax.z),drawcolor_vec,100);

Posted By: txesmi

Re: check if entity is within rotated box - 09/30/16 05:13

As far as I know there is no a so simplified way to rotate rectangles. Do you want to rotate them around the Z axis (pan) only?
Posted By: Reconnoiter

Re: check if entity is within rotated box - 09/30/16 08:53

Yes I only want to rotate the box around the pan. I there perhaps some vector function I can use?
Posted By: txesmi

Re: check if entity is within rotated box - 10/01/16 06:17

No special functions, but in that case you only need to rotate two vertex to complete the shape.

Code:
#include <acknex.h>

#define PRAGMA_POINTER

void vec2d_rotate ( VECTOR *_v, var angle )
{
	var x = fcos(angle,_v->x) - fsin(angle,_v->y);
	_v->y = fsin(angle,_v->x) + fcos(angle,_v->y);
	_v->x = x;
}

void main ()
{
	wait(1);
	level_load ( "" );
	
	VECTOR vPoint;
	vec_set ( &vPoint, vector(300,240,100) );
	
	VECTOR vMax, vMin;
	vec_set ( &vMax, vector(400,200,200) );
	vec_set ( &vMin, vector(0,0,0) );
	
	VECTOR vCenter, vBounds;
	vec_lerp ( &vCenter, &vMax, &vMin, 0.5 );
	vec_diff ( &vBounds, &vMax, &vCenter );
	
	while ( !key_esc )
	{
		camera->pan = ang ( camera->pan + mickey.x * 0.3 );
		camera->tilt = clamp ( camera->tilt + mickey.y * 0.3, -85, 85 );
		vec_for_angle ( &camera->x, &camera->pan );
		vec_scale ( &camera->x, -1000 );
		VECTOR vMove;
		vec_set ( &vMove, vector(key_force.y,-key_force.x,0) );
		vec_normalize ( &vMove, 10*time_step );
		vec2d_rotate ( &vMove, camera->pan );
		vec_add ( &vPoint, &vMove );
		vec_add ( &camera->x, &vPoint );
		
		var nRotation = total_ticks * 2;
		
		VECTOR vOffset;
		vec_diff ( &vOffset, &vPoint, &vCenter );
		vec2d_rotate ( &vOffset, -nRotation );
		COLOR colCube;
		if ( ( abs(vOffset.x) < abs(vBounds.x) ) && ( abs(vOffset.y) < abs(vBounds.y) ) && ( abs(vOffset.z) < abs(vBounds.z) ) )
			vec_set ( &colCube, COLOR_GREEN );
		else
			vec_set ( &colCube, COLOR_RED );
		
		VECTOR vP1, vP2;
		vec_set ( &vP1, &vBounds );
		vec_set ( &vP2, vector(vBounds.x,-vBounds.y,-vBounds.z) );
		vec2d_rotate ( &vP1, nRotation );
		vec2d_rotate ( &vP2, nRotation );
		
		draw_point3d ( &vPoint, COLOR_WHITE, 100, 16 );
		
		draw_line3d ( vector ( vCenter.x+vP1.x, vCenter.y+vP1.y, vCenter.z+vP1.z), NULL,     100 );  
		draw_line3d ( vector ( vCenter.x+vP2.x, vCenter.y+vP2.y, vCenter.z+vP1.z), &colCube, 100 );
		draw_line3d ( vector ( vCenter.x-vP1.x, vCenter.y-vP1.y, vCenter.z+vP1.z), &colCube, 100 ); 
		draw_line3d ( vector ( vCenter.x-vP2.x, vCenter.y-vP2.y, vCenter.z+vP1.z), &colCube, 100 ); 
		draw_line3d ( vector ( vCenter.x+vP1.x, vCenter.y+vP1.y, vCenter.z+vP1.z), &colCube, 100 );
		draw_line3d ( vector ( vCenter.x+vP1.x, vCenter.y+vP1.y, vCenter.z+vP2.z), &colCube, 100 );
		
		draw_line3d ( vector ( vCenter.x-vP1.x, vCenter.y-vP1.y, vCenter.z+vP2.z), NULL,     100 ); 
		draw_line3d ( vector ( vCenter.x-vP2.x, vCenter.y-vP2.y, vCenter.z+vP2.z), &colCube, 100 ); 
		draw_line3d ( vector ( vCenter.x+vP1.x, vCenter.y+vP1.y, vCenter.z+vP2.z), &colCube, 100 );
		draw_line3d ( vector ( vCenter.x+vP2.x, vCenter.y+vP2.y, vCenter.z+vP2.z), &colCube, 100 );
		draw_line3d ( vector ( vCenter.x-vP1.x, vCenter.y-vP1.y, vCenter.z+vP2.z), &colCube, 100 ); 
		draw_line3d ( vector ( vCenter.x-vP1.x, vCenter.y-vP1.y, vCenter.z+vP1.z), &colCube, 100 ); 
		
		draw_line3d ( vector ( vCenter.x+vP2.x, vCenter.y+vP2.y, vCenter.z+vP2.z), NULL,     100 );
		draw_line3d ( vector ( vCenter.x+vP2.x, vCenter.y+vP2.y, vCenter.z+vP1.z), &colCube, 100 );
		
		draw_line3d ( vector ( vCenter.x-vP2.x, vCenter.y-vP2.y, vCenter.z+vP2.z), NULL,     100 );
		draw_line3d ( vector ( vCenter.x-vP2.x, vCenter.y-vP2.y, vCenter.z+vP1.z), &colCube, 100 );
		
		wait(1);
	}
	
	sys_exit ( NULL );
}



Salud!
Posted By: Reconnoiter

Re: check if entity is within rotated box - 10/06/16 13:20

Tnx txesmi, can vec2d_rotate also be changed so that it doesn't change the position of the vector and only the angle of the drawed selection box? I am using now for an 3d selection box too, where I already have the right the min/max vectors so vec2d_rotate messes up the position.

Through some dirty Acknex code grin I did manage to get 1 of the vectors right I think, but can't get the other one right:

Code:
VECTOR vOldP1, vDiff;
vec_set(vOldP1, vP1); //store
vec2d_rotate (vP1, camera.pan); //same as before
vec2d_rotate (vP2, camera.pan); //-
vec_diff(vDiff, vP2, vP1);
vec_set(vP1, vOldP1);
vec_set(vP2, vP1);
vec_add(vP2, vDiff); //now we have the correct vP2 XD

Posted By: txesmi

Re: check if entity is within rotated box - 10/07/16 05:05

I am sorry but I don't get your question.

vec2d_rotate rotates a two-dimensional vector from its origin (x:0,y:0), same as vec_rotate does on a three-dimensional vector.
Code:
vec2d_rotate(v,ang) === vec_rotate(v,vector(ang,0,0))



In my last code example I computed the center and the bounds of a rectangular prism from two world space vectors considering the prism aligned to carthesian planes, then I rotate two simmetrical bounds vectors, been their origin the center of the prism.

Code:
VECTOR vMax, vMin;
vec_set ( &vMax, vector(400,200,200) );
vec_set ( &vMin, vector(0,0,0) );

VECTOR vCenter, vBounds;
vec_lerp ( &vCenter, &vMax, &vMin, 0.5 );
vec_diff ( &vBounds, &vMax, &vCenter );

...

VECTOR vP1, vP2;
vec_set ( &vP1, &vBounds );
vec_set ( &vP2, vector(vBounds.x,-vBounds.y,-vBounds.z) );
vec2d_rotate ( &vP1, nRotation );
vec2d_rotate ( &vP2, nRotation );

Posted By: Reconnoiter

Re: check if entity is within rotated box - 10/07/16 10:06

I think I can explain this the best way through images. The grid shows how the camera.pan is. The red/yellow/green lines are my drawed boxes. Green mouse cursors are the begin and end points of my mouse selection. (note that boxes are 2d on the images but 3d in my game)

First one without your vec2d_rotate function:


Second is with your vec2d_rotate function:


Third, this is with your vec2d_rotate function and with the tweak I posted in my previous post (only 1 of the 2 vectors are correct):


Fourth, this is what I want:
Posted By: txesmi

Re: check if entity is within rotated box - 10/07/16 16:12

Ok, I got it!

The only difference with my previous example is that you need to convert the bounds vector to that pseudo view space before computing the symmetric point of the rectangle.

Here you go:
Code:
#include <acknex.h>

void vec2d_rotate ( VECTOR *_v, var angle )
{
	var x = fcos(angle,_v->x) - fsin(angle,_v->y);
	_v->y = fsin(angle,_v->x) + fcos(angle,_v->y);
	_v->x = x;
}

void mouseOnZ0 ( VECTOR *_v )
{
	vec_set ( _v, &mouse_dir3d );
	vec_scale ( _v, -camera->z/_v->z );
	vec_add ( _v, &camera->x );
}

void onMouseLeft ()
{
	VECTOR vStart, vEnd;
	mouseOnZ0 ( &vStart );
	
	while ( mouse_left )
	{
		mouseOnZ0 ( &vEnd );
		
		VECTOR vCenter, vBounds;
		vec_lerp ( &vCenter, &vStart, &vEnd, 0.5 );
		vec_diff ( &vBounds, &vStart, &vCenter );
		vec2d_rotate ( &vBounds, -camera->pan );
		
		VECTOR vP1, vP2;
		vec_set ( &vP1, &vBounds );
		vec_set ( &vP2, vector(vBounds.x,-vBounds.y,-vBounds.z) );
		vec2d_rotate ( &vP1, camera->pan );
		vec2d_rotate ( &vP2, camera->pan );
		
		draw_line3d ( vector ( vCenter.x+vP1.x, vCenter.y+vP1.y, 0), COLOR_RED, 0 );  
		draw_line3d ( vector ( vCenter.x+vP1.x, vCenter.y+vP1.y, 0), COLOR_RED, 100 );  
		draw_line3d ( vector ( vCenter.x+vP2.x, vCenter.y+vP2.y, 0), COLOR_RED, 100 );
		draw_line3d ( vector ( vCenter.x-vP1.x, vCenter.y-vP1.y, 0), COLOR_RED, 100 ); 
		draw_line3d ( vector ( vCenter.x-vP2.x, vCenter.y-vP2.y, 0), COLOR_RED, 100 ); 
		draw_line3d ( vector ( vCenter.x+vP1.x, vCenter.y+vP1.y, 0), COLOR_RED, 100 );
		draw_line3d ( vector ( vCenter.x+vP1.x, vCenter.y+vP1.y, 0), COLOR_RED, 0 );
		
		wait(1);
	}
}

void main ()
{
	video_mode = 10;
	mouse_mode = 4;
	wait(1);
	level_load ( "" );
	camera->tilt = -30;
	camera->pan = 30;
	
	on_mouse_left = onMouseLeft;
	
	while ( !key_esc )
	{
		camera->pan += key_force.x * 10 * time_step;
		vec_for_angle ( &camera->x, &camera->pan );
		vec_scale ( &camera->x, -1000 );
		
		// World space axis
		draw_line3d ( vector(1000,0,0), COLOR_WHITE, 0 );
		draw_line3d ( vector(1000,0,0), COLOR_WHITE, 100 );
		draw_line3d ( vector(-1000,0,0), COLOR_WHITE, 100 );
		draw_line3d ( vector(-1000,0,0), COLOR_WHITE, 0 );
		draw_line3d ( vector(0,1000,0), COLOR_WHITE, 0 );
		draw_line3d ( vector(0,1000,0), COLOR_WHITE, 100 );
		draw_line3d ( vector(0,-1000,0), COLOR_WHITE, 100 );
		draw_line3d ( vector(0,-1000,0), COLOR_WHITE, 0 );
		
		wait(1);
	}
	
	sys_exit ( NULL );
}



Salud!


edited______________

a bit faster version
Code:
VECTOR vCenter, vBounds;
vec_lerp ( &vCenter, &vStart, &vEnd, 0.5 );
vec_diff ( &vBounds, &vStart, &vCenter );

VECTOR vP1, vP2;
vec_set ( &vP1, &vBounds );
vec_set ( &vP2, &vBounds );
vec2d_rotate ( &vP2, -camera->pan );
vP2.y *= -1;
vP2.z *= -1;
vec2d_rotate ( &vP2, camera->pan );


Posted By: Reconnoiter

Re: check if entity is within rotated box - 10/08/16 11:53

Works like a charm now, tnx! laugh For others; if anyone has now problems with selecting entities within the bounds add this line before comparing if the enitity's vOffset is within/below the selectionbox's vBounds:

vec2d_rotate (vBounds, -camera.pan);
Posted By: txesmi

Re: check if entity is within rotated box - 10/08/16 15:33

you are welcome smile
© 2024 lite-C Forums