Jump to content

Determining if an AV is within a specific "box", without the box..


Kagehi Kohn
 Share

You are about to reply to a thread that has been inactive for 3910 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

Ok, seems like trying to get help in-world can be a pain with some of this stuff, and I don't have an immediate need to fix this, so, will ask here.

I resently created a script for a safe, which lets you drop cards in, or remove them, as a means of tracking what gets put in by faction members, or, if someone gets the code/figured it out, steals from inside of it. However, while I have some script sitting some place that can say.. tell "which side" of the resulting object they are on (I used it in a door design), and how close they are, I want something more precise for this, since its behind a counter, and, I want it to work even if I later re-orient the safe, to point a different direction. So.. here was what I was thinking, as psuedo code:

 

vector pos = llGetPos();
integer left = 0;
integer right = 2;
integer length = 5;
integer top = 1.5;
integer bottom = 1.5;

//Assuming that the "front" is in the Y direction.
//  integer boxlen = llGetScale().y / 2;
//  vector bbox1 = <pos.x - left, pos.y + boxlen, pos.z - bottom>;
//  vector bbox2 = <pos.x + right, pos.y + boxlen, pos.z + top>;
//  vector bbox3 = <pos.x - left, pos.y + boxlen + length, pos.z - bottom>;
//  vector bbox4 = <pos.x - right, pos.y + boxlen + length, pos.z + top>;
//  cpos = llDetectedPos(0);
//  {stuff to figure out if cpos is actually in the box formed by bbox1, bbox2, bbox3, and bbox4,
// even if its bloody rotated 32.5356 degrees, or something..}

 I mean, I know how you go about it, if the thing is at a nice 90 degree angle, or something, but.. how do you manage it if its not? Well, other than the near insanity of, say.. normalizing all the variabled into a form in which all of them, including the AV location, are oriented so they all line up with such a nice, neat, direction? lol This is, definitely, a bit more complicated that just going, "Are they in front of the thing, and close enough to be opening it, since, well. for consistency, I don't want them doing that, if they are a) on the right side, b) close enough, but, c) on the wrong damn side of the counter. ;) And, that is assuming I don't end up having to move it, and messing up all of the resulting assumptions about where the places you can't be are.


Heck, in all honesty, its also, logically, a problem with, say, a door, in a hallway. And detecting them in an "arc" of the door, means the closer you are to the door, and the wider the door, the more of a "gap" you have, where they could be standing practically on top of said door, and still be "not in the arc". So.. testing a script defined bounding box would be better, if I can work out how to do that.

Link to comment
Share on other sites

Try this ...

default{    touch_start(integer total_number)    {        llSensor("","",AGENT_BY_LEGACY_NAME,10.0,PI);    }        sensor( integer num)    {        vector Pos = llDetectedPos(0);        string Name = llDetectedName(0);        rotation RotX = llRotBetween( <1.0,0.0,0.0>*llGetRot(), llVecNorm(llGetPos()-Pos) );        rotation RotY = llRotBetween( <0.0,1.0,0.0>*llGetRot(), llVecNorm(llGetPos()-Pos) );        if ( llRot2Angle(RotX) *RAD_TO_DEG > 90.0)        {            llSay(0,Name + " is on the local +X side of this object.");        }        else        {            llSay(0,Name + " is on the local -X side of this object.");        }        if (llRot2Angle(RotY) *RAD_TO_DEG > 90.0)        {            llSay(0,Name + " is on the local +Y side of this object.");        }        else        {            llSay(0,Name + " is on the local -Y side of this object.");        }    }}

 

Link to comment
Share on other sites

Umm. Think you missed most of my point. That will detect which side they are not, not "if they are in the box".


I.e., it is "one part" of the problem. Maybe an image would help.. The guy with the blue head is "in" the detection box. The two red guys are a) and the wrong side of the counter (green), in one case, and b) not in the detection box, in the other case, but, all three are on the "correct side", and "close enough to be in range".

So, only the blue guy should actually "be" allowed to access the safe.

Also, since its detecting touch, the sensor really isn't necessary. Its going to be using the detected position, from the toucher (or, if needed, by getting that info some other way than by sensor, which is.. kind of redundant, since I know who I am looking for already).


EXAMPLE.png

Link to comment
Share on other sites

Oh.  But that part is the easy part.   You really only need to know where they are within an angular range of "forward", and how far away.  I don't care what "side" the av is on.  I just put those four if tests there to show you one way to use the information to get the "side" if that's what you wanted.  My little snippet tells you exactly where the detected av is with respect to your object's +X (or +Y) axis -- reported as the angle between the av and the chosen axis -- and llVecDist tells you how far.    You don't have to define a whole box.  All you need to ask is whether the detected av is within the right angular spread and the right range.  It's the same sort of information you get if you fire a sensor with a well-defined cone and ask if there's anyone in the detection cone within the right range.

And yes, it doesn't make any difference how you detect the av (collision, sensor, touch, llGetAgentList ....).  Whatever method you use will give you the av's regional position, and that's all you need.

Link to comment
Share on other sites

Well, actually, I want this to be more universal, so I can borrow it for, say, doors. If you have something the size of, say, a garage door, or bigger, then an "arc", is going to leave areas on either edge of the door, which will fail the test. That is why I was looking at using a bounding box type test.

I think.. If I had the vector and distance to the av, and the rotation of the object running the test, then I could "normalize" the result, by rotation, into a state where, in effect, everything is exactly lined up, as though it had no rotation at all, then the bounding test is simple. Its only complex, if/when you have the prim you are testing against at an angle. Just.. my understanding of rotation stuff in SL sucks, like.. more than anything else I know how to do (or rather, don't). lol

Link to comment
Share on other sites

Hrrm.. Not sure if this works, but.. it does with a square, and by testing two sides. It "may" work with any orientation, but.. I would still need to compute the correct locations for my box corners, which since those will have to be ralated to the prims rotation, while the psuedo code I have, assumes the thing is at a known angle.

 

integer triangleArea(vector A, vector B, vector C){  return(C.x*B.y-B.x*C.y)-(C.x*A.y-A.x*C.y)+(B.x*A.y-A.x*B.y);}integer isInsideSquare(vector A, vector B, vector C, vector D, vector P){  if(triangleArea(A,B,P)>0 || triangleArea(B,C,P)>0 || triangleArea(C,D,P)>0 || triangleArea(D,A,P)>0)      return FALSE;    else      return TRUE;}integer isInsideBox(vector bbox1, vector bbox2, vector bbox3, vector bbox4){  vector P = llDectectedPos(0);  vector A1 = <bbox1.x,bbox2.y,bbox1.z>;  vector B1 = <bbox2.x,bbox2.y,bbox1.z>;  vector C1 = <bbox2.x,bbox1.y,bbox1.z>;  vector D1 = <bbox1.x,bbox1.y,bbox1.z>;  vector A2 = <bbox3.x,bbox4.y,bbox3.z>;  vector B2 = <bbox4.x,bbox4.y,bbox3.z>;  vector C2 = <bbox4.x,bbox3.y,bbox3.z>;  vector D2 = <bbox3.x,bbox3.y,bbox3.z>;  return (isIntegerSquare(A1, B1, C1, D1, P) & isIntegerSquare(A2, B2, C2, D2));}

 Apparently, this is supposed to work because if P is "inside" of the squares, the result of each area calculation will be positive. If its "not" inside the squares, and thus, not inside the box, you end up with a negative result. Or, at least according to http://www.emanueleferonato.com/2012/03/09/algorithm-to-determine-if-a-point-is-inside-a-square-with-mathematics-no-hit-test-involved/ where I adapted this code from.

So, assuming it does work, I just need some way to figure out where bbox1, bbox2, bbox3 and bbox4 "should be" based on the proper rotation. ;) Hmm. Multiply them by the vector normal, for the direction maybe? Only.. wouldn't that, in some cases, result in multiplying some of the numbers by zero, and losing the result? Like I said, rotation stuff is "not" what I am good at. lol Might be easier to figure out what the "unrotated" locations would be, for the av, and prim, then compute the above?

Link to comment
Share on other sites

Here is a slightly different method that I use a lot.  I am not inworld so I can not test it to make sure it works right, but its the general idea.  The vectors min and max define the box you want to detect in.

 

vector offset;vector min = <1,-1,0>;vector max = <3,1,4>;default{	touch_start(integer total_number)	{		offset = llDetectedPos(0);                offset = (offset - llGetRootPosition()) / llGetRootRotation();        		if(offset.x > min.x && offset.x < max.x &&			offset.y > min.y && offset.y < max.y &&			offset.z > min.z && offset.z < max.z){		             llSay(0,"You are in the square");		}	}}

 edit to clean up formatting of copy/past of code

Link to comment
Share on other sites

Not really. That gives the bounding box for the object. Since I am not sitting on the object, it doesn't include the AV. Since I am only useing a single prim (which is to say that the transparent blue box is not "real" or "attached" to the build, but merely virtual, the bounding box will be the size of the prim, not the size of the detection box.


However, the "isInPrim" code seems to do that same thing that Talia's does, more or less, just using the existing bounding box instead. In principle, its the same thing, just the wrong box. But, I think it gives me two options. One option is to use the math method, and the other, a bloody lot of if/then statements. Hard to say which one is better, in terms of script execution. Way back, when I was dealing with compiled languages, or even interpretted, instead of "run on demand", the math would have been slightly faster. lol

 

In any case, I think this one single line is, in fact, the bit I was missing (and, its much simpler than I imagined it was going to be):

vPos = (vPos - llGetPos()) / llGetRot();
Link to comment
Share on other sites

Ah well, then ... If that's a serious criterion, make your safe a mesh object and include an extension in front of it that you can texture transparent.  Then you should be able to get the object to have a L.I. of 1 even if you include a swinging door -- thus doing the job without increasing the prim count -- and you can use that extension as a collision surface, as Leprekhan suggested.  That's thinking outside the box.  :smileytongue:

 

Link to comment
Share on other sites

Yeah, well. There is that possibility. I had considered making myself one, and may still, but, for now, I am using a prebuilt I got from the market. Strictly speaking, there is no reason to not use the box trick I am trying to do though. It has advantages, in that, if I can make it work right, the "box" can be any orientation, or location, not even "connected" to the prim involved at all. My only worry was that the math method works regardless of which way the box it pointed, but, in this specific case, the problem wasn't "is it in the box?", so much as, "Where are the corners of the box?"

And, in fact, I suppose I could have multiplied the offsets by the rotation, to get my box corners, then tested against that, using the math.

The non-math version, unless you "unrotate" it, I suspect has a different problem, illustrated below. Green is where the actual box you are trying to test is, while red is what you end up with, if you don't "unrotate" the box, and the av location, so they are parallel to the axis you are testing. In other words, unless you object is facing exactly +/-X and +/-Y, without rotation, your "test" is going to be looking at the box that isn't actually the size your corners suggest they are. The math version.. doesn't care how the box it rotated, just if the place you are trying to find is either in/out of the resulting box. But, as I said, in that case, your problem is figuring out where your corners should be, since.. they are not going to be directly on a +/-X and +/-Y, never mind +/-Z axis line either. But.. its probably, thinking on it, as simple as doing "corner = center + (offset * rotation)". I.e., the direct opposite of what is being done in the examples people gave. I think...

Ex2.png

Umm. Note, in the case of useing it for "any" orientation, of course, I need 6 corners. Four for the base, then two more for at least one side. The only reason I can get by with two, otherwise, is that my box isn't rotated.

Link to comment
Share on other sites

Sigh.. OK, for anyone that didn't see it, like me. my original code doesn't work at all, because I am testing "two planes/sides", while the original math only handled a single plane. I.e., it dealt with only X and Y, not Z. I make the mistake, in directly copying the code, of only used the X and Y of each point, even when I **should be** testing the Z... Need to rethink how to fix that... :(

Link to comment
Share on other sites


Kagehi Kohn wrote:

Sigh.. OK, for anyone that didn't see it, like me. my original code doesn't work at all, because I am testing "two planes/sides", while the original math only handled a single plane. I.e., it dealt with only X and Y, not Z. I make the mistake, in directly copying the code, of only used the X and Y of each point, even when I **should be** testing the Z... Need to rethink how to fix that...
:(

The Z axis is trivial though, unless you plan on tilting your box as well as rotating it. If you determine they are within the XY plane as you've defined it, you then simply do a bounds check by comparing the avatarVector.z with the [boxVector.z - lowerLimit, boxVecter.z + upperLimt]. If they pass that test, they would then be within your 3D box.

 

Whether they are within the XY plane isn't too complicated either. Initially you have the dimensions of your box, the placement of its center and it's orientation in global space. With that information, and a bit of math (which is outside the scope of this forum) you can determine the global coordinates of the points at the corners. You only need to calculate 4 points, either of the top or bottom face. Oh, and you need to calculate the area of the top face, you'll see why in a moment.

 

In fact, since you're not tilting the box (and if you are, I'll wish you all the luck in the world, you'll need it!) and will be using the bounds test for Z as I described in the first paragraph, you can further simplify everything to a 2D problem, which will be a lot less math intensive. We'll just disregard Vector.z entirely in our first calculations.

 

Once you have determined the four XY global coordinates of your corners, you next want to form 4 pairs consisting of two adjacent points. In other words, going clockwise around your top surface, if you labeled them A, B, C and D; then your pairing would be- AB, BC, CD and DA. Now you've initialized everything and can wait for an avatar!

 

When you sense an avatar, you'll get their global position and put it into the variable "avatarVector". Remember we're going to disregard all the Vector.z's in this part. Go ahead and determine the areas of four triangles, using avatarVector for a common point and one of each of the corner point pairs. Simple math, nothing to it.

 

Now, add the areas of those four triangles and compare it to the area of the top of your box. If, and only if, they are the same, is the avatar within your XY plane*. Then just do the Z bounds check and you're done.

 

Or, you could put down a rug... :)

 

*NOTE: Because of all the floating point operations involved in this, you can't expect an explicit equality test to be 100% reliable. In other words, "if (areaOfTriangles == areaOfBoxTop)" may fail because of imprecision injected by the calculations and you need to give it a bit of "wiggle room". Such as "if(areaOfTriangles - x <= areaOfBoxTop && areaOfTriangles + x >= areaOfBoxTop)" (with x being the amount of "wiggle" you find is necessary)

 

[ETA: I just thought of how you can cut out half your math calculations, the ones for determining the coordinates of the four points.

 

Not to worry about prim count, these will all be temporary and deleted in a moment. Rex a box, size it to the size of your desired bounding box. Do NOT rotate it yet.  Now rez four much smaller boxes and center them on the top corners of your big box (very easily done with just a little building knowledge or one could simply eyeball it if it didn't need to be too precise). Now, link the five together and position the big box where you want the volume in question, rotating it as you wish.

 

Once you're satisfied with it's placement, unlink the set and then simply note the centers of the 4 smaller and the large box. Delete them all and you're already half there! ]

Link to comment
Share on other sites

Well, again, the rug doesn't work, it requires another prim, which I need to avoid, if at all possible.


Note, a solution for this might, for a good example of why this is a better solution, be used to test 'where" you are, for a hud, so you can do special manuvers. Right now, for example, not only does SL not support say, making something a climbing surface, scripting every damn things you might want to climb is.. just absurd. But.. Lets say you have a hud, which when you enter the sim, talks to a sever, which hand it a set of places, where specific animations/actions can be chosen, such as, being able to actually climb the ladders... Now.. "Some" things you could use "within x distance from" and which way you are facing, to trigger. Say, instead, you want to be able to "creep" past a location, automatically, like in a stealth game, you create a virtual bounding box, which your hud detects you entering, and leaving, lets you opt to crouch, and "triggers" the animation needed (as well as, say, keeping you moving other the right direction, unless you persist, and then, it lets you stand up, instead.

Also.. All the prior code.. dead.


Here is a different version (it still requires translating the AV, to test, but is much simpler, and actually should work.

No complete code yet, but here is the idea:

 

// Move our AV's location, so that the equations can "assume" that our positions are relative to <0,0,0>.AVPos = llDetectedPos(0) - llGetPos();//Bounding box size = 5, 3, 2, 0, 4, 1, or 8x2x5 meters in size.right = 1*x + 0*y + 0*z - 5;left = -1*x + 0*y + 0*z - 3;top = 0*x + 1*y + 0*z - 2;bottom = 0*x - 1*y + 0*z - 0;front = 0*x + 0*y + 1*z - 4;back = 0*x + 0*y - 1*z - 1;//Note, not tested, so some of these may be testing the wrong "direction". I.e., they might need to check if the sign is +, instead of -, or visa versa.if (right <= 0 & left >= 0 & top <= 0 & bottom >= 0 & front >= 0 & back <= 0)  llOwnerSay("Inside box.");

 

Link to comment
Share on other sites

I'm just joking about the rug. :) But a bounding sphere would be even better! Then you'd just need to compute the distance between the avatar and the center of the sphere and if it was greater than the radius it would be "outside".

OK, I see the algorithm you're wanting to use- which is a 3D extension of the test to see if a point lies between two parallel lines. So you'd be effectively projecting 6 planes out from the sides of the bounding box and seeing if the avatar is on the "correct" side of all of them.

Now that would work, but I feel it is far too complicated for this, since you're not tilting the bounding box (meaning the only rotation you do to it is around the Z axis) and the problem can be much simplified.

Here's the logic of the simplification: Since the bounding box is not tilted, the planes of its top and bottom parallel the global Z axis. So, as I said, that test is trivial and we can do that one first. If the avatar is too high or too low, we'll know immediately that they cannot be in the box and we'd be done.

// Note, nondescriptive naming used for brevity!vector X; // Set to the position of your avatarvector Z; // set to the position of your bounding boxfloat H; // Set to Z dimension of bounding boxif (X.z >= Z.z - H/2 && X.z <= Z.z + H/2)}	// this code will only be entered into if the avatar has met the height requirement} else {	llOwnerSay("Avatar is not in bounding box";}

 

Doing it this way eliminates any need of Vector.z from further considerations and makes the following steps a 2D problem- whether the point is within a rectangle on the XY plane.

There's a number of solutions in geometry for this, any of them which might be used. But your preference should be for the *simplest* solution. In other words, you could do the "crossing test", where if a straight line extending from a point crosses an odd number of sides of a polygon, it would be "inside". But that algorithm is a general case solution for any polygon and is a bit of overkill for a rectangle. Yes?

Your algorithm of determining if a point is "between" planes could be used but, as you pointed out, requires one to determine a consistent "right" and "left" of a line. That can be done with correct ordering of the points throughout the algorithm but why bother when one can take advantage of a much simpler solution?

Consider this diagram:

OutsideInside.jpg

The rectangles represent the top or the bottom of your bounding box. It doesn't matter which you choose since we've eliminated Vector.z from our calculations at this point and they are now equivalent. The only thing we have to consider is the XY locations of the 4 corners and that of the avatar. OK?

I've labeled the four corners as I described, A-D, and drawn in 4 triangles, labeling them as well for the 2 corners each have, with the avatar XY position being common to all. It should be obvious that when the point is within the rectangle the total area of these 4 triangles is exactly the same as the area of the rectangle. And their combined areas will be greater than the area of the rectangle if the avatar is outside the rectangle (Proof left to the reader with time on their hands). Follow me?

Now, the area of a rectangle is easy, X * Y, with X and Y being the dimensions of the top of your bounding box. The formula for the area of a triangle, where a, b and c are the points, is Area = |(a.x(b.y-c.y)+b.x(c.y-a.y)+c.x(a.y-b.y))/2| ( see http://www.mathopenref.com/coordtrianglearea.html), which is straightforward, simple math. But we can even simplify that.

If you double the area of the size of the rectangle, four divisions by 2 can be eliminated, which would give us |a.x(b.y)-a.x(c.y)+b.x(c.y)-b.x(a.y)+c.x(a.y)-c.x(b.y)|. {Edited to remove unnecessary expansion of terms that would result in doubling multiplications]

So, in LSL, this is how it would be written:

// Note, nondescriptive naming used for brevity of code!// Your four corner points, named in clockwise ordervector A = <20.0, 18.0, 0.0>; // set to their global positions, Z values are ignoredvector B = <20.0, 20.0, 0.0>;vector C = <18.0, 20.0, 0.0>;vector D = <18.0, 18.0, 0.0>;vector X; // Set to the position of your avatarvector Z; // Set to the position of your bounding boxfloat H; // Set to Z dimension of bounding boxfloat I; // Set to X dimension of bounding boxfloat J; // Set to Y dimension of bounding boxfloat wiggle = 0.02; // your "wiggle room" to account for possible floating point imprecisionstring message; // Just here for outputif (X.z >= Z.z - H/2 && X.z <= Z.z + H/2){	// this code will only be entered into if the avatar has met the height requirement	float AreaOfBoxTop = I*J; // could have this as a static assignment	float AreaOfTriangles =		// Avatar and points A & B		llFabs(A.x(B.y - X.y) + B.x(X.y - A.y) + X.x(A.y - B.y)) +		// Avatar and points B & C		llFabs(B.x(C.y - X.y) + C.x(X.y - B.y) + X.x(B.y - C.y)) +		// Avatar and points C & D		llFabs(C.x(D.y - X.y) + D.x(X.y - C.y) + X.x(C.y - D.y)) +		// Avatar and points D & A		llFabs(D.x(A.y - X.y) + A.x(X.y - D.y) + X.x(D.y - A.y));
// Edited after rereading my message body and realizing the second half of the following test is unnecessary if (areaOfTriangles - wiggle <= areaOfBoxTop*2 && areaOfTriangles + wiggle >= areaOfBoxTop*2) { message = "Avatar is inside bounding box!"; } else { message = "Avatar is not in bounding box"; } } else { message = "Avatar is not in bounding box";} llOwnerSay(message);

 

This, however, is just the answer to the second half of your problem. You still need to first determine where those four points are in global space. You can either write a geometric solution involving rotations for that or, take the simple road (recommended!), and use the trick I thought of in the ETA at the bottom of my last posting.

Good luck with this and let us know how it goes. But are you sure I can't interest you in this fine second-hand rug?

Link to comment
Share on other sites

OK, so you don't want my ratty old rug, no problem. :) Let's look at the first half of your problem and how you'd determine where those four points are.

This also is simplified since you're not tilting your box and, because this code will only be needed once, during initial placement, we can afford to be a little more math intensive. Which is good, because we'll need to be.

First, let's change the code we have so far and make it into a function that returns TRUE or FALSE, depending on whether the avatar is within the box or not. We'll also use a vector to replace H, I and J (the dimensions of your box) as well as name some variables a bit more readably. I'll also add in some necessary multiplication signs to keep the compiler from complaining. You can add whatever notes you feel is necessary from the previous code example.

// Your four corner points, named in clockwise ordervector A;vector B;vector C;vector D;float theta; //Degrees of rotation around Z axis in radians (used in a bit!)vector sizeOfBox;vector positionOfBox;float wiggle = 0.02; // your "wiggle room" to account for possible floating point imprecision// Takes the vector of the avatar and returns TRUE or FALSEinteger avatarIsInBox (vector X){    if (X.z >= positionOfBox.z - sizeOfBox.z/2 && X.z <= positionOfBox.z + sizeOfBox.z/2)    {        float areaOfTriangles =            llFabs(A.x*(B.y - X.y) + B.x*(X.y - A.y) + X.x*(A.y - B.y)) +            llFabs(B.x*(C.y - X.y) + C.x*(X.y - B.y) + X.x*(B.y - C.y)) +            llFabs(C.x*(D.y - X.y) + D.x*(X.y - C.y) + X.x*(C.y - D.y)) +            llFabs(D.x*(A.y - X.y) + A.x*(X.y - D.y) + X.x*(D.y - A.y));        if (areaOfTriangles - wiggle <= sizeOfBox.x*sizeOfBox.y*2)    return TRUE;    }    return FALSE;}

 

Now, to determine the final placement of the four points (A-D) there are two translations required, the rotation around the Z axis and then the placement of them into global space. And for that we need:
1.) The rotation (in radians) - float theta;
2.) the dimensions of the box - vector sizeOfBox;
3.) the coordinates of its final placement - vector positionOfBox;

To simplify, one first does the rotation around the origin (<0,0>) to get the position of the four points there. Then it's simply a matter of adding the global position to each to arrive at their final placement. And the formula for a rotation around the origin for a single point is:
transformedX = x * cos( theta ) - y * sin( theta )
transformedY = x * sin( theta ) + y * cos( theta )
Where theta is the rotation in radians. (see http://en.wikipedia.org/wiki/Rotation_matrix for details.)

And, since we're at the origin and (again) disregarding the Z axis, determining the initial positions of these four corners is easy.

float startX = sizeOfBox.x/2;float startY = sizeOfBox.y/2;vector startA = <-startX, -startY, 0.0>;vector startB = <-startX, +startY, 0.0>;vector startC = <+startX, +startY, 0.0>;vector startD = <+startX, -startY, 0.0>;

 But, we don't really need those intermediate vectors, except to refer to the signs of X and Y as we go, which gives us, finally:

float startX = sizeOfBox.x/2;float startY = sizeOfBox.y/2;A.x = -startX*llCos(theta) + startY*llSin(theta) + positionOfBox.x;A.y = -startX*llSin(theta) - startY*llCos(theta) + positionOfBox.y;B.x = -startX*llCos(theta) - startY*llSin(theta) + positionOfBox.x;B.y = -startX*llSin(theta) + startY*llCos(theta) + positionOfBox.y;C.x =  startX*llCos(theta) - startY*llSin(theta) + positionOfBox.x;C.y =  startX*llSin(theta) + startY*llCos(theta) + positionOfBox.y;D.x =  startX*llCos(theta) + startY*llSin(theta) + positionOfBox.x;D.y =  startX*llSin(theta) - startY*llCos(theta) + positionOfBox.y;

 

And that's basically all the guts of the math in LSL. You can choose to enter the size, placement and rotation manually in your code or use library calls to obtain it from within a "dummy" box that you'd then remove.

Doing it this way puts all the heavy lifting into the one-time initialization with much lighter math anytime you want to see if the avatar is within the box. If that makes sense to you, try it.

Link to comment
Share on other sites

Hmm. There may be circumstances, like say, flight, where the "door" isn't going to be walked up to, or, for that matter, necessarily, even vertical. Its definitely an interesting problem, which if I can find a good, working, solution for, has a lot of potential for future projects. It doesn't look like, for the original problem, its likely I really need to do anything more complicated at this point than the simple, temporary solution, I dropped in, while seeing if I could find something more versitile.

Note, the interesing one with the planes is.. in principle, you could, if you can figure out where all the needed planes would be, and which normal to test against (i.e., which sign is the right one), actually form a basic outline of some fairly complex shapes to test against.

Link to comment
Share on other sites

First, let's change the code we have so far and make it into a function that returns TRUE or FALSE, depending on whether the avatar is within the box or not.


Yeah, not sure I have the slightest idea what that does. lol Will try to test it out, when I have the chance. Kind of wish I had something, other than SL, to actually drop some of this stuff into and test "see" what is going on though. Especially with some of my own code, where the problem would have been really obvious, if I could have seen what it was actually doing. :P I have, definitely, not had enough math classes for this sort of stuff. ;)

Link to comment
Share on other sites

I hear ya'! My grasp of math is only enough to realize how little I know. :matte-motes-evil-grin:

 

My approach was to put all the "heavy lifting" ( the rotational sine and cosine functions) into the initialization, leaving much simpler math  to be done in the test. The reasoning being that this might be something used in (say) a battle game, where this testing would be somewhat frequent and you wouldn't want to bog the servers down too much. There's other approaches to this one could take, some of which may well be more desirable than mine. This was meant solely to be illustrative of how I would look for simplifications of the algorithm and to show the LSL coding that would result..

 

I do wish to point out that one of the uses for this you put forward would be inappropriate, that of a climbing simulation. I say that because the avatar would definitely "be on a rug" all the time and one would just require coding for collision events. And, a "rug" in front of your safe would not necessarily cost another prim if the safe was mesh, one would just use one of its eight possible material faces for that.

 

Remember, KISS- Keep It Short & Simple.

Link to comment
Share on other sites

Well, no. I fact I was thinking more in term, with the climbing thing, of having an attachment run animations, instead of using sit. Mind, that probably means messing with bouyancy stuff, instead of moving, but.. I am not sure what you can, and can't do with AVs in all cases. The principle idea would be that, instead of having to add scripts to the objects, you just have a single server, to "tell" the attachment where things are, which you an interact with, then actually do the proper "adjustments" to position, facing, animation, etc., **exactly** like you would see in a real game. Right now.. SL pretty much doesn't do this, with "anything", and its really goofy, and unbelievable, because of it.

You can think of it like a swim hud. When in water, Linden just treats it like air, and lets you fall (but, ironically, clients do provide 'swim' AO settings, for when you actually "do" interact with the water...), you have to detect it yourself, then do a bunch of extra things, to make it so you float, or swim, etc, based on being "on/under" the water. Most games have "trigger points" to handle this, and, in fact, some, like the Stalker series, actually went one step farther with the concept, and had terrain points, whose distance would "trigger" changes in behavior, for the NPCs, so being close to a place with a findable artifact would, for example, send the NPC team into the field, to find an artifact. Being near a campsite resulted in them setting up camp for the night, etc.


The point being to try to make things "fluid", instead of, for example, a wall climber, which has no damn clue where the top of the wall is, can't let you peak over, never mind climb over it, and where you can't, possibly, even "get" onto the resulting roof, because it doesn't know you are at it, and the only way it can a) dismount you, and b) make you land on the roof, is if you "jump off", and thus both trigger the end of the climbing animation, *and* maybe, if you time it all right, actually end up on the roof, instead of falling 10 stories, to the ground again.


FSM forbid you wanted to do an "chimney climb", like in some game like Splinter Cell, allowed, or crouch and move between barriers, smoothly, or.. like, anything else that would make it look less like someone trying to do an FPS, using puppets on a string, and more like an actual environment, with believable actions.

I thought about it a lot, and couldn't come up with a real way to manage it, until while working on this, and I realized.. if you an test "where" an AV is, relative to something like a wall, you "can" both a) have them creep along it, without using a mess of ray casts, or sensors, and b), you could have them trigger the actions need to believable go "into" that movement, as well as restrict what they are doing. You can't, at all, do that with, for example, the existing "climbing" methods, because well - 1) they rely on sit, which you can't set a "this is where I get off" on, or 2) they rely on collision tests, and a simple animation setup, which doesn't have a clue what the sim actually looks like, including, where the top of the building is, so, even if you can "climb" with one, you can't animate starting the climb, getting off to the ground, climbing over the wall/edge, to get on/off of it, and the roof, and so on.

But, with a hud, which knows where ladders are, or even enough about the buildings, barriers you can hide behind, and so on... all you then need is a clean way to know where the hell you actually are, which "state" your AV is in, and thus, both how to animate them, and in what ways they movement needs to be contrained, to make it believable.

All stuff that, imho, the damn server should be doing, if only for "water", and nothing else. :P

Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 3910 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...