 |
 |
|
 |
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Hunted around on the net and found something for 2D, but I think I got
something wrong trying to do the 3D. Actually, I am semi-sure I know
what I screwed up, but not how to fix it. lol But, I figured I would
maybe, instead, ask here instead, on the chance there is a better solution.
Basically though, I have an object, its position, and its rotation, and
I want to create a "test box" in which to work out where someone is,
but I want it to still work, regardless of whether or not the object is
say, rotated 35 degrees in all directions, placing my "test box" some
place other than at nice 90 angles from the normal axis.
Now the method I had tried was:
main(){
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>;
if (isInsideBox(bbox1, bbox2, bbox3, bbox4))
//do other stuff, or, else, the stuff you do if they are "not" in
the box.
}
integer triangleArea(vector A, vector B, vector C)
{
//This is where I am screwing up.. I need to test A.z, B.z and C.z,
//for one of the planes, but I am testing x and y in both cases, which
//won't work.
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));
}
I am 99% sure that what I failed to think about is that since one of the
"sides" is vertical, I am testing its x and y in both cases, and thus,
stupidly, not testing the z. Otherwise, the code works, supposedly,
because, if your test point isn't "inside the box", one or more of the
area calculations will end up with a negative sign.
In any case, I need to redo the code, if I want to do this, and simplify
things a lot at well.
But, what I was wondering is.. is there some other way to do this? Some
way that takes into account the rotation, and what amounts to a sort of
"is this inside of the bounding box" calculation, without having to
rotation/unrotate various things, to get the same result? Because, as
things stand, either I need to reposition the object I am testing, or I
need to reposition the corner of my invisible box, which I am testing
for them to be in. And, while one is less annoying than the other.. they
are still both annoying. lol
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Le 04/08/2013 23:50, Patrick Elliott a écrit :
> Hunted around on the net and found something for 2D, but I think I got
> something wrong trying to do the 3D. Actually, I am semi-sure I know
> what I screwed up, but not how to fix it. lol But, I figured I would
> maybe, instead, ask here instead, on the chance there is a better solution.
>
> Basically though, I have an object, its position, and its rotation, and
> I want to create a "test box" in which to work out where someone is, but
> I want it to still work, regardless of whether or not the object is say,
> rotated 35 degrees in all directions, placing my "test box" some place
> other than at nice 90 angles from the normal axis.
Why would you want to handle such box, when the interest of such code is
precisely to reduce the workload by looking only at the axes.
>
> Now the method I had tried was:
>
> main(){
> 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>;
> if (isInsideBox(bbox1, bbox2, bbox3, bbox4))
> //do other stuff, or, else, the stuff you do if they are "not" in the
> box.
> }
>
> integer triangleArea(vector A, vector B, vector C)
> {
> //This is where I am screwing up.. I need to test A.z, B.z and C.z,
> //for one of the planes, but I am testing x and y in both cases, which
> //won't work.
> 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;
> }
>
Did you understand how it is supposed to work in 2D ? I mean the
previous two functions are using oriented triangles and area computation
(signed result) to know if P is inside ABCD.
When P is inside ABCD, ABP, BCP, CDP, DAP all have the same sign for
their area. As soon as P is outside the square, one area at least has a
negative result.
The nice thing about it is that the four points A,B,C & D only need to
be ordered in the rotating order and can be anywhere in the plane (it
does not have to be an axis-aligned square).
But it only works in 2D.
> 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));
> }
>
I do not understand the expectation here. You seems to transform the box
as two parallel to Z plane squares (axis-aligned), and then check if the
projection of P is inside the projections of both these squares.
There is plenty of situations where it will provide false positives, as
well as false negatives.
>
> I am 99% sure that what I failed to think about is that since one of the
> "sides" is vertical, I am testing its x and y in both cases, and thus,
> stupidly, not testing the z. Otherwise, the code works, supposedly,
> because, if your test point isn't "inside the box", one or more of the
> area calculations will end up with a negative sign.
signed area calculation is only good for 2D. The extension in 3D would
need to compute the volume of a pyramid (with a triangle base) and the
maths are not to be friendly
>
> In any case, I need to redo the code, if I want to do this, and simplify
> things a lot at well.
>
> But, what I was wondering is.. is there some other way to do this? Some
> way that takes into account the rotation, and what amounts to a sort of
> "is this inside of the bounding box" calculation, without having to
> rotation/unrotate various things, to get the same result? Because, as
> things stand, either I need to reposition the object I am testing, or I
> need to reposition the corner of my invisible box, which I am testing
> for them to be in. And, while one is less annoying than the other.. they
> are still both annoying. lol
If you do not intend to limit yourself to a axis-aligned box, why not
instead use a sphere ?
you transform only 1 point (the center)(if you only have rotation and
translation), and then just compute the distance of the center to P (to
compare against the radius). And to avoid slow squared root, compare the
squared distance (euclidian) to the squared radius.
If you have more than rotation & translation (such as scaling and
shearing), you might need to transform the radius too (at which point,
it's better to consider 1 center and the 8 corners of the box, to
finally only kept as radius the distance from the center to the most
faraway corner)
(the box is originally the box that encloses the minimal sphere. at the
end, the radius is the radius of the sphere that encloses the
transformed box. Thus, it is bigger than the strict covering sphere, but
it is safe)
--
Just because nobody complains does not mean all parachutes are perfect.
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
> 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>;
Do you mean "pos.x + right" in that last line?
> 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>;
If you substitute in your values for bbox1-4 from above you get the
following (I left out the pos.x,pos.y,pos.z):
A1 = <-left , boxlen , -bottom>
B1 = < right , boxlen , -bottom>
C1 = < right , boxlen , -bottom>
D1 = <-left , boxlen , -bottom>
A2 = <-left , boxlen+length , -bottom>
B2 = < right , boxlen+length , -bottom>
C2 = < right , boxlen+length , -bottom>
D2 = <-left , boxlen+length , -bottom>
Is this really what you are expecting?
If you are trying to see if a point is inside a box, then it might be
simpler to think of the box as being bounded by 6 infinite planes (one
for each face), then testing which side of each plane the point is on.
If it's on the "inside" of all 6 planes then it's inside the box.
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On 8/5/2013 12:52 AM, Le_Forgeron wrote:
> Le 04/08/2013 23:50, Patrick Elliott a écrit :
>> Hunted around on the net and found something for 2D, but I think I got
>> something wrong trying to do the 3D. Actually, I am semi-sure I know
>> what I screwed up, but not how to fix it. lol But, I figured I would
>> maybe, instead, ask here instead, on the chance there is a better solution.
>>
>> Basically though, I have an object, its position, and its rotation, and
>> I want to create a "test box" in which to work out where someone is, but
>> I want it to still work, regardless of whether or not the object is say,
>> rotated 35 degrees in all directions, placing my "test box" some place
>> other than at nice 90 angles from the normal axis.
>
> Why would you want to handle such box, when the interest of such code is
> precisely to reduce the workload by looking only at the axes.
>
>
Yeah, well. I kind of thought maybe there was some way that I just
wasn't seeing.
>>
>> Now the method I had tried was:
>>
>> main(){
>> 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>;
>> if (isInsideBox(bbox1, bbox2, bbox3, bbox4))
>> //do other stuff, or, else, the stuff you do if they are "not" in the
>> box.
>> }
>>
>> integer triangleArea(vector A, vector B, vector C)
>> {
>> //This is where I am screwing up.. I need to test A.z, B.z and C.z,
>> //for one of the planes, but I am testing x and y in both cases, which
>> //won't work.
>> 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;
>> }
>>
>
> Did you understand how it is supposed to work in 2D ? I mean the
> previous two functions are using oriented triangles and area computation
> (signed result) to know if P is inside ABCD.
>
> When P is inside ABCD, ABP, BCP, CDP, DAP all have the same sign for
> their area. As soon as P is outside the square, one area at least has a
> negative result.
>
> The nice thing about it is that the four points A,B,C & D only need to
> be ordered in the rotating order and can be anywhere in the plane (it
> does not have to be an axis-aligned square).
>
> But it only works in 2D.
>
Umm. Not sure how to explain this, but, yeah, I did. I just.. screwed up
on the coordinates. lol Umm. Let me put it this way. You are looking at
two boxes one is laying flat, along the XY, the other is lying flat on
the XZ (or the YZ, which I don't think necessarily matters). So.. in one
case if the location of the thing being tested was <1,2,3>, then P
"should be" <1,2>, and for the other plane, it should be <1,3>, with the
corners of the two boxes, on those planes, taken from the XY, or the XZ,
as needed.
Or, that was what I envisioned in my own head. lol Obviously, I screwed
up from the very start.
>
>> 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));
>> }
>>
>
> I do not understand the expectation here. You seems to transform the box
> as two parallel to Z plane squares (axis-aligned), and then check if the
> projection of P is inside the projections of both these squares.
>
> There is plenty of situations where it will provide false positives, as
> well as false negatives.
>
Yeah, as I said, I fowled up. In actuality, what happens, due to the
code being wrong, is that P is *never* inside the box.
>>
>> I am 99% sure that what I failed to think about is that since one of the
>> "sides" is vertical, I am testing its x and y in both cases, and thus,
>> stupidly, not testing the z. Otherwise, the code works, supposedly,
>> because, if your test point isn't "inside the box", one or more of the
>> area calculations will end up with a negative sign.
>
> signed area calculation is only good for 2D. The extension in 3D would
> need to compute the volume of a pyramid (with a triangle base) and the
> maths are not to be friendly
>
No doubt.
>>
>> In any case, I need to redo the code, if I want to do this, and simplify
>> things a lot at well.
>>
>> But, what I was wondering is.. is there some other way to do this? Some
>> way that takes into account the rotation, and what amounts to a sort of
>> "is this inside of the bounding box" calculation, without having to
>> rotation/unrotate various things, to get the same result? Because, as
>> things stand, either I need to reposition the object I am testing, or I
>> need to reposition the corner of my invisible box, which I am testing
>> for them to be in. And, while one is less annoying than the other.. they
>> are still both annoying. lol
>
> If you do not intend to limit yourself to a axis-aligned box, why not
> instead use a sphere ?
>
The reason is that I need the specific shape. Ok, I will attach an
example. There is a safe, against a wall, and a counter, which is green,
the transparent box is the "valid" area for someone to be able to access
the safe, with the guy inside it being "allowed", and the two "red"
figures not. There is no way to use a sphere, without detecting as
"valid" people standing in the wrong places. Its the precise reason why
I didn't just use the simpler method of figuring out, "Is this person
standing in the +X direction, and within N meters of the object. That
method would have failed to detect people, in the safe where, instead, a
garage door, for example, if they stood at the "edge" of the door, since
they might not be "close enough", without making the detection range
much larger than I wanted (i.e., a 15 meter door, should detect 5 meters
"in front of" the door, no matter where on the door, but since is using
"center of the door", it would fail to detect someone standing against
it, but 7 meters from the center).
However... I occurs to me that I might be able to use one plane, and a
distance.. So, as long as the position was rotated, to match a plane
that is align to XY (or, actually, due to how the world works, XZ), then
I can test if its in "that" box, and then merely do:
float dist = llVecDist(llGetPos(), P);
if (dist < maxdist & dist > mindist)
{
//Rest of the code.
}
Thus, only testing "one" box, and only on that single plane.
Then again, I screwed up the last idea so badly... lol
Post a reply to this message
Attachments:
Download 'example.png' (22 KB)
Preview of image 'example.png'

|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On 8/5/2013 1:44 AM, scott wrote:
>> 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>;
>
> Do you mean "pos.x + right" in that last line?
>
>> 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>;
>
> If you substitute in your values for bbox1-4 from above you get the
> following (I left out the pos.x,pos.y,pos.z):
>
> A1 = <-left , boxlen , -bottom>
> B1 = < right , boxlen , -bottom>
> C1 = < right , boxlen , -bottom>
> D1 = <-left , boxlen , -bottom>
>
> A2 = <-left , boxlen+length , -bottom>
> B2 = < right , boxlen+length , -bottom>
> C2 = < right , boxlen+length , -bottom>
> D2 = <-left , boxlen+length , -bottom>
>
> Is this really what you are expecting?
>
> If you are trying to see if a point is inside a box, then it might be
> simpler to think of the box as being bounded by 6 infinite planes (one
> for each face), then testing which side of each plane the point is on.
> If it's on the "inside" of all 6 planes then it's inside the box.
>
lol What part of, "I know I screwed up the math.", did people miss. ;)
Seriously though, Le_Fogeron says it wouldn't work anyway... :p
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On 8/5/2013 2:15 AM, Patrick Elliott wrote:
> However... I occurs to me that I might be able to use one plane, and a
> distance.. So, as long as the position was rotated, to match a plane
> that is align to XY (or, actually, due to how the world works, XZ), then
> I can test if its in "that" box, and then merely do:
>
> float dist = llVecDist(llGetPos(), P);
> if (dist < maxdist & dist > mindist)
> {
> //Rest of the code.
> }
>
> Thus, only testing "one" box, and only on that single plane.
>
> Then again, I screwed up the last idea so badly... lol
And, speaking of which.. again, I forget that the "distance" won't work
for objects wider, or taller, than the distance... Sigh...
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
>> Thus, only testing "one" box, and only on that single plane.
>>
>> Then again, I screwed up the last idea so badly... lol
>
> And, speaking of which.. again, I forget that the "distance" won't work
> for objects wider, or taller, than the distance... Sigh...
Make your bounding box the value of "distance" bigger than the bounding
box of the object's geometry. That way you are checking for people
within "distance" from the *edge* of the object, not from the centre.
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On 05/08/2013 10:17, Patrick Elliott wrote:
> On 8/5/2013 1:44 AM, scott wrote:
>>> 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>;
>>
>> Do you mean "pos.x + right" in that last line?
>>
>>> 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>;
>>
>> If you substitute in your values for bbox1-4 from above you get the
>> following (I left out the pos.x,pos.y,pos.z):
>>
>> A1 = <-left , boxlen , -bottom>
>> B1 = < right , boxlen , -bottom>
>> C1 = < right , boxlen , -bottom>
>> D1 = <-left , boxlen , -bottom>
>>
>> A2 = <-left , boxlen+length , -bottom>
>> B2 = < right , boxlen+length , -bottom>
>> C2 = < right , boxlen+length , -bottom>
>> D2 = <-left , boxlen+length , -bottom>
>>
>> Is this really what you are expecting?
>>
>> If you are trying to see if a point is inside a box, then it might be
>> simpler to think of the box as being bounded by 6 infinite planes (one
>> for each face), then testing which side of each plane the point is on.
>> If it's on the "inside" of all 6 planes then it's inside the box.
>>
> lol What part of, "I know I screwed up the math.", did people miss. ;)
I was really having trouble trying to understand what you actually
wanted to do! I don't know which parts of the above are math screw ups
or what you actually want to do...
There are much easier, well documented, ways for doing bounding box
tests, you don't need to go into splitting it up to squares and
triangles and measuring areas as you seem to have done. If that's what
you want to do?
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Le 05/08/2013 11:17, Patrick Elliott a écrit :
> On 8/5/2013 1:44 AM, scott wrote:
>>> 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>;
>>
>> Do you mean "pos.x + right" in that last line?
>>
>>> 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>;
>>
>> If you substitute in your values for bbox1-4 from above you get the
>> following (I left out the pos.x,pos.y,pos.z):
>>
>> A1 = <-left , boxlen , -bottom>
>> B1 = < right , boxlen , -bottom>
>> C1 = < right , boxlen , -bottom>
>> D1 = <-left , boxlen , -bottom>
>>
>> A2 = <-left , boxlen+length , -bottom>
>> B2 = < right , boxlen+length , -bottom>
>> C2 = < right , boxlen+length , -bottom>
>> D2 = <-left , boxlen+length , -bottom>
>>
>> Is this really what you are expecting?
>>
>> If you are trying to see if a point is inside a box, then it might be
>> simpler to think of the box as being bounded by 6 infinite planes (one
>> for each face), then testing which side of each plane the point is on.
>> If it's on the "inside" of all 6 planes then it's inside the box.
That's a good idea.
>>
> lol What part of, "I know I screwed up the math.", did people miss. ;)
>
> Seriously though, Le_Fogeron says it wouldn't work anyway... :p
The test against 6 planes would work, and is easy if it is axis aligned.
If it is rotated, you have "just" to apply the same maths, it's just the
formula which become a bit harder (a plane equation is ax+by+cz+d = 0,
one side of the plane is wherer ax+by+cz+d > 0, and the other side is <0)
There is an infinity of 4D vector <a,b,c,d> to match a single plane
(indeed, if V is such vector, k.V is also another vector)
(also notice that if V is such vector, -V is the same plane but with the
inversion of the sides)
So, instead of thinking "corner of box" (8) to be grouped in
squares/side, you should have to think "plane's equation" (6).
Notice that scaling & shearing leaves plane as plane, so even if you
were to use a sheared box (such as a truncated pyramid), it would still
works.
What I said was that extending the "smart" 2D triangle-based-tests to 3D
are to be a nightmare.
--
Just because nobody complains does not mean all parachutes are perfect.
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On 8/5/2013 4:35 AM, scott wrote:
>>> Thus, only testing "one" box, and only on that single plane.
>>>
>>> Then again, I screwed up the last idea so badly... lol
>>
>> And, speaking of which.. again, I forget that the "distance" won't work
>> for objects wider, or taller, than the distance... Sigh...
>
> Make your bounding box the value of "distance" bigger than the bounding
> box of the object's geometry. That way you are checking for people
> within "distance" from the *edge* of the object, not from the centre.
Only, then it detecting them too far away, when standing directly in
front of it. If I want someone to be able to open a door from 5 meters,
it should be 5 meters, regardless of where they are, when they do it.
Or, in the specific case that led me to hunt for a solution, they can't
be a) on the wrong side of a counter, b) farther than 3 meters from the
safe, c) outside the building (i.e., behind the thing), or d) standing
on the other side of the wall, near the safe (SL lets you pan you camera
through things, with some of its controls, so you can't stop them
clicking the thing, through a wall. This means a very narrow range of
"usable" space, and distance. And the "alley" I need to test, is not
much wider than the safe itself.
I could have gotten by with a fairly simple "angle" test, and distance,
to see if they where close enough, in this specific case. But, not so
with something bigger, like my hypothetical garage door.
Hmm. There is a possibility though..
avPos = llDetectedPos(0);
cPos = llGetPos(0);
ab = llGetAngleBetween(avPos, cPos);
TestDistance = ???(ab) * 5;
I.e., make the angle determine the "distance" so that every point in the
detection range will "always" be the same distance from the object. Ur..
What would be the math for drawing a straight line, using a string,
attached to a immobile peg exactly? lol
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On 8/5/2013 4:38 AM, scott wrote:
> There are much easier, well documented, ways for doing bounding box
> tests, you don't need to go into splitting it up to squares and
> triangles and measuring areas as you seem to have done. If that's what
> you want to do?
>
Yeah, basically. What I searched google for was, basically, "Find if
point is in a box". And, well, adding "in 3D" didn't seem to help much.
lol I completely forgot to search on "bounding box". :p
My actual theory here though, if its more understandable, was like.. If
you had an aquarium, which you could look into, from any two sides, and
a 90 degree angle from each other, but you couldn't get around to any of
the other sides, and you needed to "prove" mathematically, that an
object in it was "actually" in the aquarium, and not outside.
So, logically, you take two sides, that are at 90 degrees from each
other, than mathematically test of you can "see" the object from those
two sides, "inside" of the rectangle each side represented.
In principle, this should work. What I screwed up with was that I need
two sets of calculations. One set is other original, from here (if your
mouse is in the box, the box turns red):
http://www.emanueleferonato.com/2012/03/09/algorithm-to-determine-if-a-point-is-inside-a-square-with-mathematics-no-hit-test-involved/
Then, completely screwed up, by trying to reuse the same exact
equations, for both sides (or, rather, the same "components" of the
vectors).
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On 8/5/2013 4:43 AM, Le_Forgeron wrote:
>
> The test against 6 planes would work, and is easy if it is axis aligned.
> ...
> What I said was that extending the "smart" 2D triangle-based-tests to 3D
> are to be a nightmare.
>
Still not seeing why two planes wouldn't, see my "is it in the aquarium"
explanation from my reply to scott.
But, in any case, I think there may be a simpler solution, which, like
my original thought, only requires "adjusting" the location of the
object being tested for, by canceling its apparent rotation (or, rather,
getting it lined up so its where the box would be, if the box wasn't
rotated either), and, it doesn't require a box at all, just an angle
test, and a distance (which depends on the angle). It does require some
checking, to make sure they are actually within the allowed angles, but..
Hmm. Actually, now that I think of it, that also have issues.. I am
thinking I need to check the distance, as per "directly in front" of
something, like a big door, but the "center" might be, itself, several
meters over the ground, so.. I need draw a "wall" with a piece of chalk,
on string, attached to a fixed "center point", not just a line... Sigh..
Why does 3D have to get so complicated? lol
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On 8/5/2013 9:00 PM, Patrick Elliott wrote:
> avPos = llDetectedPos(0);
> cPos = llGetPos(0);
> ab = llGetAngleBetween(avPos, cPos);
> TestDistance = ???(ab) * 5;
Range = 5;
TestDistance = (Range - x * cos(ab)))/sin(ab);
So.. How do I get that to make a "wall" instead of just a 2D line? Use z
in a second one, then check both?
Uh, coordinate system they use is Z = up.
No, wait, that just give me a plain, without telling me if its inside
the box on that plane.. Sigh.. Right back to having to test if its in
the box... Suppose, combining the two..
:head-> desk, head-> desk, head-> desk, head-> desk, head-> desk, ouch!: lol
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
Le 06/08/2013 06:20, Patrick Elliott a écrit :
> On 8/5/2013 4:43 AM, Le_Forgeron wrote:
>>
>> The test against 6 planes would work, and is easy if it is axis aligned.
>> ...
>> What I said was that extending the "smart" 2D triangle-based-tests to 3D
>> are to be a nightmare.
>>
> Still not seeing why two planes wouldn't, see my "is it in the aquarium"
> explanation from my reply to scott.
the "Aquarium" is using projections (2) and has hidden implication (the
projections are at 90° angle).
you could as well use only 1 projections and an additional "distance
from point to its projection".
Your main issue so far is projecting on arbitrary rotated plane/square.
and it won't be easy.
>
> But, in any case, I think there may be a simpler solution,
Simpler than evaluating the sign of 6 first-degree equations ?
P(x,y,z) the point to test,
Vn(An,Bn,Cn,Dn) [n:1 to 6], the 4D vector representing the planes of
the box (oriented so that inside is >0)
are all signs of x.An+y.Bn+z.Cn+Dn positive ?
the plane XY at height z=10 is <0,0,1,-10> (or in the opposite direction
<0,0,-1,10> ), where is the difficulty ?
--
Just because nobody complains does not mean all parachutes are perfect.
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
> Or, in the specific case that led me to hunt for a solution, they can't
> be a) on the wrong side of a counter, b) farther than 3 meters from the
> safe, c) outside the building (i.e., behind the thing), or d) standing
> on the other side of the wall, near the safe (SL lets you pan you camera
> through things, with some of its controls, so you can't stop them
> clicking the thing, through a wall. This means a very narrow range of
> "usable" space, and distance. And the "alley" I need to test, is not
> much wider than the safe itself.
Sounds to me like you just have to bite the bullet and define a custom
bounding box (or group of bounding boxes if the shape you want isn't a
box) for each object.
FWIW most 3D games work like this, each object has the geometry, and
then also some form of bounding object (far less complex than the
geometry) for the purposes of collision detection. It looks like you
want something similar, a bounding object that defines the space within
which you can interact with the object.
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On 8/6/2013 3:19 AM, scott wrote:
>> Or, in the specific case that led me to hunt for a solution, they can't
>> be a) on the wrong side of a counter, b) farther than 3 meters from the
>> safe, c) outside the building (i.e., behind the thing), or d) standing
>> on the other side of the wall, near the safe (SL lets you pan you camera
>> through things, with some of its controls, so you can't stop them
>> clicking the thing, through a wall. This means a very narrow range of
>> "usable" space, and distance. And the "alley" I need to test, is not
>> much wider than the safe itself.
>
> Sounds to me like you just have to bite the bullet and define a custom
> bounding box (or group of bounding boxes if the shape you want isn't a
> box) for each object.
>
> FWIW most 3D games work like this, each object has the geometry, and
> then also some form of bounding object (far less complex than the
> geometry) for the purposes of collision detection. It looks like you
> want something similar, a bounding object that defines the space within
> which you can interact with the object.
>
>
Yeah, that was.. kind of what I thought I was doing, just.. really
badly. lol
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On 8/5/2013 11:16 PM, Le_Forgeron wrote:
> Le 06/08/2013 06:20, Patrick Elliott a écrit :
>> On 8/5/2013 4:43 AM, Le_Forgeron wrote:
>>>
>>> The test against 6 planes would work, and is easy if it is axis aligned.
>>> ...
>>> What I said was that extending the "smart" 2D triangle-based-tests to 3D
>>> are to be a nightmare.
>>>
>> Still not seeing why two planes wouldn't, see my "is it in the aquarium"
>> explanation from my reply to scott.
>
> the "Aquarium" is using projections (2) and has hidden implication (the
> projections are at 90° angle).
>
> you could as well use only 1 projections and an additional "distance
> from point to its projection".
> Your main issue so far is projecting on arbitrary rotated plane/square.
> and it won't be easy.
>
>>
>> But, in any case, I think there may be a simpler solution,
>
> Simpler than evaluating the sign of 6 first-degree equations ?
> P(x,y,z) the point to test,
> Vn(An,Bn,Cn,Dn) [n:1 to 6], the 4D vector representing the planes of
> the box (oriented so that inside is >0)
> are all signs of x.An+y.Bn+z.Cn+Dn positive ?
>
> the plane XY at height z=10 is <0,0,1,-10> (or in the opposite direction
> <0,0,-1,10> ), where is the difficulty ?
>
Ah, I see. Your looking at 'ax + by + cz - d = 0' It should be - for the
last term, right, to be correct, or is it + because of what you are
trying to do with it? The dots, instead of * threw me there, for a second.
Hmm.. I need to work out "where" the planes are, to test them, and that
means the vector normal for it, which is dependent on the object
rotation, right? So.. Which, if I am right, means I don't need to even
know where the corners are (which was a "big") problem, when the thing
was rotated.
norm = llVecNorm(<1,0,0> * llGetRot() * dist);
would give me "one" plane, and I can get another from that too, with a
farther/shorter distance, where the results are <norm.x, norm.y, norm.z,
dist> and <norm.x2, norm.y2, norm.z2, dist2>, but the I need to find the
vector normals for the other four sides.
Mind, such a test could handle even non-box results, like trapezoids,
but requires.. Ah, I know.. I need to just add in a rotation for the
axis I want to test my other "sides" against, which are at:
llVecNorm(<1,0,0> * llGetRot() * <90,0,0> * dist3);
llVecNorm(<1,0,0> * llGetRot() * <90,90,0> * dist4);
llVecNorm(<1,0,0> * llGetRot() * <90, 180,0> * dist5);
llVecNorm(<1,0,0> * llGetRot() * <90,270,0> * dist6);
(or the quaternion equivalent, since Euler will go batshit if I try to
rotate two axis at once, using their conversion functions...)
Realizing that,
dist1 = from the door/object.
dist2 = length of bounding box.
dist3 = left distance, from center of bounding box.
dist4 = up distance, from center of bounding box.
dist5 = right distance, from center of bounding box.
dist6 = down distance, from center of bounding box.
Or.. which ever directions those are.. ;) It doesn't matter though,
since its still going to be right, I think. Unless I got the 90 degree
angle I need to also twist around wrong, somehow). Yeah, that is doable,
I think.
Hmm. Wait, that gives me planes, but.. how does the test happen?
Actually, I think you may have really lost me, or I missed something, or
you assumed I had a clue about something I didn't, or.. something.. lol
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
> Mind, such a test could handle even non-box results, like trapezoids,
> but requires.. Ah, I know.. I need to just add in a rotation for the
> axis I want to test my other "sides" against, which are at:
Indeed, the multiple-planes approach can handle any convex object. If
you want a concave object (eg an "L" shape) you need to split it up in
to multiple boxes and test each one separately.
> Hmm. Wait, that gives me planes, but.. how does the test happen?
> Actually, I think you may have really lost me, or I missed something, or
> you assumed I had a clue about something I didn't, or.. something.. lol
Once you've got the equations for your planes (ie Ax+By+Cz+D=0) then you
plug in your point position for xyz and evaluate the result.
If the result is 0 then the point is exactly on the plane, if it's >0
it's on one side, <0 the other side.
So for example suppose your "right" plane is at a distance 5 along the X
axis, your plane equation would be 1*x + 0*y + 0*z - 5
Now you can take some points and plug it into that equation:
P=(0,1,2) gives 1*0 + 0*1 + 0*2 -5 = -5 (negative, so on left of plane)
P=(10,5,4) gives 1*10 + 0*5 + 0*4 -5 = 5 (positive, so on right of plane)
You just need to check that your point is on the "inside" of each of the
6 planes that make up your box, then you know for sure it is inside the box.
Your other plane equations for the box might be:
-1*x + 0*y + 0*z - 3 (left plane)
0*x + 1*y + 0*z - 2 (top plane)
0*x - 1*y + 0*z - 0 (bottom plane)
0*x + 0*y + 1*z - 4 (front plane)
0*x + 0*y - 1*z - 1 (back plane)
Slightly off-topic I know, but those are the same numbers you can use in
the POV "plane" object :-)
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|  |
|
 |
On 8/7/2013 2:11 AM, scott wrote:
>> Mind, such a test could handle even non-box results, like trapezoids,
>> but requires.. Ah, I know.. I need to just add in a rotation for the
>> axis I want to test my other "sides" against, which are at:
>
> Indeed, the multiple-planes approach can handle any convex object. If
> you want a concave object (eg an "L" shape) you need to split it up in
> to multiple boxes and test each one separately.
>
>> Hmm. Wait, that gives me planes, but.. how does the test happen?
>> Actually, I think you may have really lost me, or I missed something, or
>> you assumed I had a clue about something I didn't, or.. something.. lol
>
> Once you've got the equations for your planes (ie Ax+By+Cz+D=0) then you
> plug in your point position for xyz and evaluate the result.
>
> If the result is 0 then the point is exactly on the plane, if it's >0
> it's on one side, <0 the other side.
>
> So for example suppose your "right" plane is at a distance 5 along the X
> axis, your plane equation would be 1*x + 0*y + 0*z - 5
>
> Now you can take some points and plug it into that equation:
>
> P=(0,1,2) gives 1*0 + 0*1 + 0*2 -5 = -5 (negative, so on left of plane)
>
> P=(10,5,4) gives 1*10 + 0*5 + 0*4 -5 = 5 (positive, so on right of plane)
>
> You just need to check that your point is on the "inside" of each of the
> 6 planes that make up your box, then you know for sure it is inside the
> box.
>
> Your other plane equations for the box might be:
>
> -1*x + 0*y + 0*z - 3 (left plane)
> 0*x + 1*y + 0*z - 2 (top plane)
> 0*x - 1*y + 0*z - 0 (bottom plane)
> 0*x + 0*y + 1*z - 4 (front plane)
> 0*x + 0*y - 1*z - 1 (back plane)
>
> Slightly off-topic I know, but those are the same numbers you can use in
> the POV "plane" object :-)
>
Ah. OK. That make perfect sense. Definitely need, one of these days, to
take more math. lol Though, honestly, I have always had much the same
problem with "equations" as with function calls. Remembering what I want
to do (or, say.. the function name) is the easy part, its all the fiddly
bits, which make it work, like.. the actual written equation, or the
parameters for the call, which screwed me up. lol
Hmm. I do, in this case, since there are "at origin", need to also do:
AVPos = llDetectedPos(0) - llGetPos();
I think, so that the "location" I am testing against is actually based
on where the box is, not some other place. Otherwise, I would have to
"add" that position, to all the values. After all, its not at the
origin, but the equations "assume" that it is.
Post a reply to this message
|
 |
|  |
|  |
|
 |
|
 |
|  |
|
 |