Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Need some help with Vectors

Cyrus Odets
Registered User
Join date: 5 Oct 2005
Posts: 51
04-26-2006 00:53
Greets!

I'm having some problems trying to figure out exactly 'how' to work with the positional functions to determine something, and I'm having a heck of a time with it. Hoping for some help or advice.

Here goes...

What I'm trying to code for is probably relatively simple...I just need a bit of help. Let me try and describe this.

I'm creating a 'door' that will simply slide open when touched. Simple enough. However, I need to code one set of 'stuff' to happen if the person who touches the door is on ONE side of the door (Outside of the room and wishing to open the door and enter), and another set of 'stuff' to happen if the person who touches the door is on the OTHER side of the door (Inside of the room, and wish to exit).

The trick is that I don't want to 'hard code' the position settings. The other trick is that the door won't necessarily be aligned with the world's x plane or y plane. In other words, I can't just record the door's x position and say..."If the touching avatar's x coordinate is higher than the door's x coordinate, then they are 'outside' the room and if it is lower than the door's x coordinate than they are 'inside' the room.

The problem that presents itself, and that I'm having trouble with...is what happens if someone takes this door and sticks rotates it 45 degrees. If I were to draw a line parallel to the door...off into infinity....this is the line that, depending on which side of the 'line' the avatar is on...would determine which side of the door they are on.

So I'm guessing I need to do some vector math to determine what coordinates this line passes through....and which side of that line the avatar's position is.

So, if I have this door...rotated 45 degrees (Or any other 'odd' rotation that doesn't fall on the compass cardinal points)....how can the door determine which side the avatar who is wishing to open it is standing on?

Please forgive me if thats a silly question...I'm working on learning vectors, rotations, and working through tutorials so this little 'door' thing is helping me to learn.

Thanks!

--
Cy
Cross Lament
Loose-brained Vixen
Join date: 20 Mar 2004
Posts: 1,115
04-26-2006 01:28
I hope the following makes sense. I'm half asleep, and at the best of times I'm not so great at explaining things. I did test this though, it it works. I'm sure someone else will come along and provide a much simpler answer though. :D

This is a good place to use something like a vector dot product, which I just recently remembered about. The dot product of two vectors, A dot B, returns a float value that is the length of the projection of A on B. Put another way, if A is exactly parallel to B, then A dot B is equal to 1. If A is exactly perpendicular to B, then the result is 0. If A is antiparallel to B (ie. parallel, but pointing in the opposite direction), the result is -1.

When trying to find the direction of one of an object's axes when it's been rotated off the world axes, simply multiply the axis you're looking for by the object's global rotation. For example, to find which way an object's y-axis is pointing in the world, you'd compute < 0, 1, 0 > * llGetRot() in a script on the object.

In this case, let's assume that for the door, the inside is the object's +y direction, and the outside is the object's -y direction (ie. the green axis when you set the editor to local coordinates):

CODE
// This sets the axis which defines the 'inside' and 'outside'
// of the door, in this example we're using the door's y-axis.

vector dooraxis = < 0, 1, 0 > ;

// This function returns the dot product of A dot B, which is
// the scale of the projection of vector A onto vector B.

float dotproduct( vector a, vector b )
{
a = llVecNorm( a ) ;
b = llVecNorm( b ) ;

return a.x*b.x + a.y*b.y + a.z*b.z ;
}

default
{
state_entry()
{
}

touch_start( integer num )
{
vector mypos = llGetPos() ; // Get the current global location of the door.
rotation myrot = llGetRot() ; // Get the current global rotation of the door.
vector targetpos = llDetectedPos( 0 ) ; // Get the global location of the toucher.

// Get the normalized vector pointing towards the toucher.

vector targetvector = llVecNorm( targetpos - mypos ) ;

// This returns the dot product of the vector pointing at the toucher
// and the +y-axis of the door, adjusted for the rotation of the door.

float dotprod = dotproduct( targetvector, dooraxis * myrot ) ;

// If the dot product is a positive number, they're on the +y side of the door.
if( dotprod > 0.0 )
{
// Do 'touching from inside' stuff here!
}

// If the dot product is a negative number, they're on the -y side of the door.
else if( dotprod < 0.0 )
{
// Do 'touching from outside' stuff here!
}

else
{
// Somehow, miraculously, they are aligned exactly with the edge of the door!
// This is so unlikely as to probably be completely unnecessary to account for. :)
}
}
}
_____________________
- Making everyone's day just a little more surreal -

Teeple Linden: "OK, where did the tentacled thing go while I was playing with my face?"
Eloise Pasteur
Curious Individual
Join date: 14 Jul 2004
Posts: 1,952
04-26-2006 02:42
Cross' solution (I've not checked the code) should work I think.

I cheated for a sliding door. I set up a situation with a means to record a "open" position and a "closed" position and just slide between them. It requires a little setting up to look right - but if you get the door right in your wall set "closed" slide it to the right place (local edit arrows help) and go from there - the maths is a lot nicer!
Cross Lament
Loose-brained Vixen
Join date: 20 Mar 2004
Posts: 1,115
04-26-2006 09:15
Okay, this is why you don't answer scripting questions when you're half asleep at 4am in the morning. My first solution works, but is utterly and totally silly and overengineered. :o

The easy way to do this is to find the normalized (aka unit) vector pointing from the door to the person touching it, then unrotate this by the door's rotation. This aligns things back onto the world axes, making comparisons much easier. Once this is done, you can simply check the y-axis values of the resulting vector: if it's positive, the toucher is on the +y side of the door, if it's negative, the toucher is on the -y side of the door (I'm just using the y-axis as an example, it will work with any of the axes).

Just for fun, I made this into a working 'one-way door' script. It'll only open and close for people on the +y side of the door. :)

CODE
// FALSE means the door is closed!
integer doorstate = FALSE ;

// Lets have the door slide 3m on its x-axis when it opens/closes.
vector dooroffset = < 3, 0, 0 > ;

default
{
state_entry()
{

}

touch_start(integer total_number)
{
// Get the door's position.
vector mypos = llGetPos() ;

// Get the door's rotation.
rotation myrot = llGetRot() ;

// Find the normalized vector (unit vector) pointing from the door to the toucher.
vector targetvector = llVecNorm( llDetectedPos( 0 ) - mypos ) ;

// UNROTATE this vector by the door's rotation; sort of creating a 'what if'
// scenario of where the door is aligned with the world axes, for comparison purposes.
targetvector = targetvector / myrot ;

// Check if you're on the +y side...
if( targetvector.y > 0 )
{
// Do +y side of door things here!

// Door is already open...
if( doorstate )
{
doorstate = FALSE ;

// The new position of the door, adjusted for the door's rotation.
vector newpos = mypos - ( dooroffset * myrot ) ;

// Move the door!
llSetPos( newpos ) ;
}

// Door is already closed...
else
{
doorstate = TRUE ;

// The new position of the door, adjusted for the door's rotation.
vector newpos = mypos + ( dooroffset * myrot ) ;

// Move the door!
llSetPos( newpos ) ;
}
}

// Check if you're on the -y side...
else if( targetvector.y < 0 )
{
// Do -y side of door things here!
llWhisper( 0, "One-way door, sucker!" ) ;
}
}
}
_____________________
- Making everyone's day just a little more surreal -

Teeple Linden: "OK, where did the tentacled thing go while I was playing with my face?"
Cyrus Odets
Registered User
Join date: 5 Oct 2005
Posts: 51
04-26-2006 12:07
Howdy again!

heh! Looks like this is tougher than I thought ;)

I tried your script....made perfect sense to me!!! Thanks!! I though this would be 'easy'...silly me ;)

Still no dice though. Try this with your script.

Build a door and throw it in the world with the rotations on the edit pane at 0, 0, 0.

Then set the "z" rotation to 45 in the edit pane.

Now this door is 'canted' and doesn't line up right on the x or y axis.

Now...stand directly in front of the door and touch it. It works correct! If you're on the 'wrong' side it says 'wrong side sucker' and if you're on the 'right' side it opens.

However...now go stand in front of the door...way off to the left or right. Standing in front, but off to the far left or right of the door. On one side (the far left or far right, while still in 'front' of the door) it will work. On the opposite side it won't.

Now do the same thing standing on the 'wrong' side of the door....stand on the wrong side...but not directly in front...stand off to the far left or right. Same thing as above will happen.

Problem is....if I have the door aligned on the world x axis and do a:

llRot2Fwd(llGetRot())

It will give a <1, 0, 0>, indicating the 'forward' vector of the door.

Simple enough...I can test against the x axis.

If I align the door on the world y axis and do a:

llRot2Fwd(llGetRot())

It will give a <0, 1, 0>, so I can test against the y axis.

However...if that door is rotated 45 degrees on the z axis from the edit pane...and I do a:

llRot2Fwd(llGetRot())

I'll get <0.70711, .0.70711, 0>

I'm trying to figure how to use those numbers in my test.
Cyrus Odets
Registered User
Join date: 5 Oct 2005
Posts: 51
04-26-2006 13:41
I'll add this to clarify a bit...

If we have a line as below, (A line that is aligned with the x or y axis). One side of the line designates "Outside" and the other side designates "Inside". The "X" indicates the point in space that our avatar is at. It is a simple matter to compare the avatar's x coordinate to determine if its greater than the x-coordinate of the x-axis...if its greater...he is "Inside". If its not greater, he is "Outside"

Same goes for the y-axis. Its easy when the "line" I need to test against is aligned with the world x or y axis.

x-axis or y-axis
OUTSIDE INSIDE
...................................|
...................................|
..............X...................|
...................................|
...................................|
...................................|
...................................|
...................................|
...................................|

But what if our "line" looks like below and is NOT lined up with the world axis:

OUTSIDE INSIDE
........................................x
....................................x
................................x
...........X...............x
........................x
....................x
................x
............x
........x
....x
x


In the above example, where the "line" doesn't line up on the world x or y axis....how do you determine if the coordinates of the avatar (Indicated by "X";) is on the "Outside" side of the line or the "Inside" side of the line?
Cross Lament
Loose-brained Vixen
Join date: 20 Mar 2004
Posts: 1,115
04-27-2006 02:46
From: Cyrus Odets
I'll add this to clarify a bit...

If we have a line as below, (A line that is aligned with the x or y axis). One side of the line designates "Outside" and the other side designates "Inside". The "X" indicates the point in space that our avatar is at. It is a simple matter to compare the avatar's x coordinate to determine if its greater than the x-coordinate of the x-axis...if its greater...he is "Inside". If its not greater, he is "Outside"

Same goes for the y-axis. Its easy when the "line" I need to test against is aligned with the world x or y axis.

x-axis or y-axis
OUTSIDE INSIDE
...................................|
...................................|
..............X...................|
...................................|
...................................|
...................................|
...................................|
...................................|
...................................|

But what if our "line" looks like below and is NOT lined up with the world axis:

OUTSIDE INSIDE
........................................x
....................................x
................................x
...........X...............x
........................x
....................x
................x
............x
........x
....x
x


In the above example, where the "line" doesn't line up on the world x or y axis....how do you determine if the coordinates of the avatar (Indicated by "X";) is on the "Outside" side of the line or the "Inside" side of the line?


Well, this is exactly what I was doing with the door script above, actually. In the second case here, where you want to compare position X with the rotated line, you take the vector pointing from the center of the line towards position X, then unrotate it by the line's rotation. This creates a situation where it's as if you'd grabbed the whole scenario and rotated it back into alignment with the world axes (basically, transforming your bottom example back into your top example). This allows you to compare the new, unrotated vector with the standard world axes. The two situations are functionally equivalent.

As far as I can tell, both the scripts I posted (though the first one is just silly! :)) should do this correctly... though I've been wrong before. :D I'll try to catch you in-world; it might be easier for me to demonstrate what I'm talking about there. :)
_____________________
- Making everyone's day just a little more surreal -

Teeple Linden: "OK, where did the tentacled thing go while I was playing with my face?"