Game Development Community

PickSector?

by Teck Lee Tan · in Torque Game Builder · 09/16/2005 (12:58 am) · 11 replies

I'm looking for a way to be able to pick a sector, instead of a simple circle/ellipse (think vision cones a la Commandos, for example). Looking at the code, I think I know where to add/modify, but the problem is... I don't know what or how. Being rather new to C++, I honestly can't tell if some of the parameters are commands, built in classes, add-on Torque classes, or whatever. :( I'll probably try to set aside some time to look through the source, but if anyone has a re-built solution, or can actually read the source in question and give a rough breakdown, that would be fantastic.

From FXSceneGraph2D.cc:
// Pick Radius.
const char* fxSceneGraph2D::pickRadius( fxVector2D pickPoint, fxVector2D radii, U32 groupMask, U32 layerMask, bool showInvisible )
{
	// Check Radii.
	if ( radii.mX <= 0.0f || radii.mY <= 0.0f )
	{
		// Warn.
		Con::warnf("fxSceneGraph2D::pickRadius() - Radii must be greater than 0! (%f,%f)", radii.mX, radii.mY);
		return NULL;
	}

	// Clear Pick-List.
	clearPickList();

[b]	// Calculate Pick Area.
	RectF pickRect(pickPoint.mX-radii.mX, pickPoint.mY-radii.mY, radii.mX*2.0f, radii.mY*2.0f);[/b]

	// Pick Objects.
	U32 pickCount = getSceneContainer().pickArea( pickRect, layerMask, groupMask, showInvisible, findLayeredObjectsCallback, &mLayeredPickList );

The bit in bold is what I gather needs modification/addition, but I can't make heads or tails of what those parameters are (mX-radii.mx, etc). Come to think of it... Why is it using pickRect? FXSceneGraph2D.h has pickRadius defined already. Great. Now I'm even more confused than before I posed my question. :\

edit: for the time being I'll probably just use the standard pickRadius and cull out whatever's not in the desired arc post-picklist.

#1
09/16/2005 (9:26 am)
RectF pickRect(pickPoint.mX-radii.mX, pickPoint.mY-radii.mY, radii.mX*2.0f, radii.mY*2.0f);

A quick evaluation


pickPoint is the vector of where you are "picking"... so something like "10 15"

radii is the vector of the radius you want... so something like "5 5"


RectF pickRect(10-5 = 5, 15-5 = 10, 5 * 2 = 10.0, 5 * 2 = 10.0)

so RectF pickRect(5.0, 10.0, 10.0, 10.0);
#2
09/16/2005 (9:33 am)
Using this form of RectF

RectF(const F32 in_left,  const F32 in_top,
         const F32 in_width, const F32 in_height);
#3
09/16/2005 (9:39 am)
This is where you will probably want to look as well

fxPhysics2D pickAreaPhysics;
	// Do a dummy initialisation.
	pickAreaPhysics.initialise( 0, "" );
	// Setup the Position.
	pickAreaPhysics.setPosition( pickPoint );
	// Set the poly count to the best approximation of a circle we can do.
	// NOTE:- This is probably overkill but if we're using large radii then it might become important.
	pickAreaPhysics.setCollisionPolyPrimitive( fxPhysics2D::MAX_COLLISION_POLY_VERTEX );
	// Setup the area.
	pickAreaPhysics.setSize( radii * 2.0f );
#4
09/16/2005 (9:50 am)
Not sure if you need this but this seems to be the way the pickRadius command works...


you pass it two vectors... pick location and radius... using the example above you get a rectf called pickRect of 5 10 10 10

then it does a quick pickArea to find out if there are any object within the rectF

U32 pickCount = getSceneContainer().pickArea( pickRect, layerMask, groupMask, showInvisible, findLayeredObjectsCallback, &mLayeredPickList );


next it initiates a special "pick" physics object and sets its center position

// Setup Physics Model to check against.
	fxPhysics2D pickAreaPhysics;
	// Do a dummy initialisation.
	pickAreaPhysics.initialise( 0, "" );
	// Setup the Position.
	pickAreaPhysics.setPosition( pickPoint );

Now it defines a high poly (to get the circle pick) primitive

// Set the poly count to the best approximation of a circle we can do.
	// NOTE:- This is probably overkill but if we're using large radii then it might become important.
	pickAreaPhysics.setCollisionPolyPrimitive( fxPhysics2D::MAX_COLLISION_POLY_VERTEX );
	// Setup the area.
	pickAreaPhysics.setSize( radii * 2.0f );

it then uses this special pick physics primitive to check collision against the ellipse/circle its placing to find the objects to return
#5
09/16/2005 (9:55 am)
Yup, definitely lost. :p
I may come back to this later, since I'm working on some other, slightly more accessible code for now. :p
#6
09/16/2005 (10:20 am)
Let me see if I can break this down a bit easier, lol my above thoughts were very scattered



ok... so you have a game screen and say you wanted to do a pickRadius on the center... 0,0... and you wanted the radius in each direction to be 5...

your pickPoint vector would be
"0 0"

and your radius vector would be
"5 5"

so you call a pickRadius passing it that and whatever group/layer masks you need


when you get to this function pickPoint.mX would equal 0 and pickPoint.mY would equal 0... while radii.mX would equal 5 and radii.mY would equal 5

in the function call you can see "fxVector2D pickPoint"

and fxVector2D is just a 2D vector holder that stores the x and y values

pickPoint is just a holder for the x and y (represented as mX and mY ... m stands for "member" for a member variable)...

pickPoint.mX = 0
pickPoint.mY = 0
radii.mX = 5
radii.mY = 5

ok now we are introduced with the rectF object... it really is just a holder for certain values

from the source code

RectF(const F32 in_left,  const F32 in_top,         const F32 in_width, const F32 in_height);

basically a rectF object stores the left, top, width, and height

so when you see

RectF pickRect(...........);

it really is creating the object pickRect of RectF type and passing it certain values to insert into it... those values are the following

RectF pickRect(pickPoint.mX-radii.mX, pickPoint.mY-radii.mY, radii.mX*2.0f, radii.mY*2.0f);

now if we break this down to be a bit more readable
RectF pickReck(pickPointX - radiusX, pickPointY - radiusY, radiusX * 2, radiusY * 2);

so it sets the in_top value to the pickPointX minus the radiusX, in this case would equal -5 (0 - 5)
so it sets the in_left value to the pickPointY minus the radiusY, in this case would equal -5 (0 - 5)
so it sets the in_width value to the radiusX multipled by 2 (which makes sense since its a radius and you'd double it to get the full width), in this case would equal 10 (5 * 2)
so it sets the in_height value to the radiusY multipled by 2 (which makes sense since its a radius and you'd double it to get the full height), in this case would equal 10 (5 * 2)

in the end with this line

RectF pickRect(pickPoint.mX-radii.mX, pickPoint.mY-radii.mY, radii.mX*2.0f, radii.mY*2.0f);

in our example we just created a pickRect object with the following values

pickRect.in_top = -5;
pickRect.in_left = -5;
pickRect.in_width = 10;
pickRect.in_height = 10;

which is the dimensions of a rectangle version of our radius pick... now we start with this rectangle so we can do a quick rectangle check to see if there are any object in it at all with this code

U32 pickCount = getSceneContainer().pickArea( pickRect, layerMask, groupMask, showInvisible, findLayeredObjectsCallback, &mLayeredPickList );

which as you see it just shoves the count into pickCount... we then do

if ( pickCount == 0 )
		return NULL;

wish (as you can probably see) just ends the funciton if there are no objects in that rectangle... why go through the trouble of doing a radius check if there are no objects possible :) as you can see we don't use pickCount or pickRect again, its just for an initial check for efficiency
#7
09/16/2005 (10:20 am)
Now we create a new fxPhysics2D object

// Setup Physics Model to check against.
	fxPhysics2D pickAreaPhysics;

as the name implies this will become our special collision check for our pick

// Do a dummy initialisation.
	pickAreaPhysics.initialise( 0, "" );
	// Setup the Position.
	pickAreaPhysics.setPosition( pickPoint );

these simply initialize it and set its position to the point we're checking (centers it there)

ok this part isn't really anyting too complicated though it might look like it... think of when you create a static sprite and can set a poly Primite... say to 4, and it creates a four sided collision poly around your object... well this just sets the primitive to the max in the physics system, so the most round we can get... it then just sets its size to double what the radius is (as we know the radius is half the size of a circle/elipse in each direction)

// Set the poly count to the best approximation of a circle we can do.
	// NOTE:- This is probably overkill but if we're using large radii then it might become important.
	pickAreaPhysics.setCollisionPolyPrimitive( fxPhysics2D::MAX_COLLISION_POLY_VERTEX );
	// Setup the area.
	pickAreaPhysics.setSize( radii * 2.0f );

now beyond this point seems to be the same for whatever pick function we do... as you can see we just created a special physics object that has a very round collision poly, the rest just uses that poly to check for collision, which returns the results of whats in that area... so if you wanted to create a new one you would want to change the collision poly
#8
09/16/2005 (10:22 am)
If you look at the ::pickRect function you will see

[code]
pickAreaPhysics.setCollisionPolyPrimitive( 4 );
// Setup the area.
pickAreaPhysics.setSize( fxVector2D(pickRect.len_x(), pickRect.len_y()) );
[/code

which sets the collision primitive to 4 (four sides for a rectangle... and in the set size it just uses the x and y length)
#9
09/16/2005 (11:04 am)
Ah, so the pickRect is simply the equivalent of the broad phase collision detection, so to speak, so that the more expensive circle isn't wasted if there's nothing there. Gotcha. A little clearer now. I guess I initially got confused, then lost. And the lack of sleep isn't helping, either. :p

So there doesn't seem to be a real quick and easy way to define arcs in which to focus the search, then, at least not to my untrained eyes. Well, I guess at least I can simply knock out whatever isn't within a certain arc after the radius pick has been done.

Thanks again for your patience, Matt. You're just as insane as you were in the beginning. :)
#10
09/16/2005 (11:13 am)
@ first paragraph, yup tats what I'm getting from it at least

no wouldn't think there'd be a quick and easy way to define arcs, guess it would just take a bunch of math... now I'm a bit tired too so not quite getting what your trying to do (been a while since I've played commandos too)... are you trying to do a pick arc, or pick cones ?

lol the insanity is still there, it had just lay dormant :)
#11
09/16/2005 (11:46 am)
Sorry, arc was a poor choice of terms. :p Sector is what I meant (as in, sector of a circle). Cone would work, too.

Script is going to be my easy way out. I pretty much have it worked out in my head, though I'm a little braindead to actually work on it right now. It's also quite likely to be messy and inefficient as hell (never let an artist code!). :p