Haravikk Mistral
Registered User
Join date: 8 Oct 2005
Posts: 2,482
|
10-29-2005 10:27
Okay, the problem is relatively simple, but the solution is a difficult one to get my head around. Chances are it's a fairly straightforward maths trick that just isn't obvious to me but anyway:
I have an object at a point, and it is at a given rotation. Now, I want to create a script which can "define" this object as a line running along it's rotation, through the point at which it is located. Once I've done this, I want to then test if an avatar is on one side of this line, or the other.
The example I am working with is a simple cube which has been half cut (so that when it rotates it does so down one edge, ie it's centre had it not been halved. This cube is narrow but long, so can be made to point in a direction (currently random). And from this I wish to test which side of this "pointer" an avatar is on, left or right, or positive or negative.
My current solution takes the door's rotation around the z axis and looks to see if it is one of four quadrants, from this it decides which axis (x or y) to use. But this solution is very poor as it only works correctly in the pointer moves at 90ยบ angles, or else it will make mistakes.
Thanks!
|
Masakazu Kojima
ケロ
Join date: 23 Apr 2004
Posts: 232
|
10-30-2005 13:39
If you have a plane (normal and distance), you can subtract the distance from the dot product of the normal and the position, and the result will be >0 if the position is "outside" and <0 if the position is "inside". You can use a rotation to store a plane as a normal/distance pair. // +X plane, if you use a prism it will point towards the outside, and the plane will be along the base rotation get_x_plane() { vector center = llGetPos(); vector scale = llGetScale(); vector normal; float distance; normal = llVecNorm( llRot2Fwd( llGetRot() ) ); distance = normal * (center + (<scale.x/2, 0, 0> * llGetRot())); return <normal.x, normal.y, normal.z, distance>; } integer is_inside(vector pos, rotation plane) { vector normal = <plane.x,plane.y,plane.z>; float dist = plane.s; if ( (normal * pos) - dist >= 0.0 ) return FALSE; return TRUE; }
default { state_entry() { llSensorRepeat( "", NULL_KEY, AGENT, 10, PI, 5.0 ); }
sensor(integer num) { integer i; string str = ""; rotation plane = get_x_plane(); for ( i = 0; i < num; i++ ) { str += llDetectedName(i) + " - "; if ( is_inside(llDetectedPos(i), plane) ) str += "in"; else str += "out"; str += "\n"; } llSetText( str, <1,1,1>, 1.0 ); } }
|
Ben Bacon
Registered User
Join date: 14 Jul 2005
Posts: 809
|
10-31-2005 05:57
not in world at the mo' - so I can't verify but... llDetectedPos() - llGetPos() is the offset in global terms between the other object and this one. Divide that (i think) by llGetRot() to transform it into this object's frame of reference. Now the sign of each component tells you which side of this object the other one is - looking at that component's axis. in concrete terms, the detected object is somewhere where my red arrow points (technically it is on the positive x-side of my yz-plane) iif vector Offset = (llDetectedPos(i) - llGetPos()) / llGetRot(); if (Offset.x > 0) I'll verify when I get home and repost or edit any corrections. EDIT: Yup - verified
|
Haravikk Mistral
Registered User
Join date: 8 Oct 2005
Posts: 2,482
|
10-31-2005 15:23
Thanks both you for your replies!
I've gone with Ben Bacon's solution as it's a little bit simpler. But if either of you are interested I can give you each a free copy of the item I've created as a result (it's nothing spectacular but quite neat all the same).
|