Maths trigonometry problems scripting RezObject()

Recommended Posts

Posted (edited)

I have a script which was functioning no I changed orientation of the object it doesn't work is this because i script thinks in local pos not Global pos what do I need to do to correct it to place the object at the orientation angle of the particle emitter please have i got trigonometry wrong:

Badly drawn image ,  llRezObject at black ball head might move but emitter will move with it. emitter at yellow green distance needed to be calculated to rez object fire.(see test script below )

```integer fire_emitter;
integer smoke_emitter;

fire()
{
if (armed)
{
smoke();

flames();

llPlaySound(burn, 0.3);
//llSleep(3.0);
llSleep(4);
rot = llGetRot();
vel = <0.0,3.50,0.0>;
vector  a1 = llRot2Euler(rot); a1 *= RAD_TO_DEG;
float angle_top = a1.z;
float zhieght = pos.z+size.z;
float Xhoriz =llTan(90-angle_top)*zhieght;
pos = llGetPos();
pos.y += (Xhoriz-1.8);
pos.z -=zhieght;
pos.x -=.7;
llRezObject("Fireball(llDie)", pos, vel , rot , 0);

}```

Edited by VirtualKitten
Share on other sites
Posted (edited)

Edited by Profaitchikenz Haiku
Share on other sites
Posted (edited)

Hi @Profaitchikenz Haiku PI/2 uhu how do you get that please

`float Xhoriz =llTan(PI/2-angle_top)*zhieght; ?????`

I think

pos = llGetPos();
pos.y -= (Xhoriz-1.8);
pos.z -=zhieght;
pos.x -=.7;

Needs different addition and subtraction depending on objects orientation How do i get this  please?

Edited by VirtualKitten
Share on other sites
2 minutes ago, VirtualKitten said:

Hi @Profaitchikenz Haiku PI/2 uhu how do you get that please

```
float Xhoriz =llTan(PI/2-angle_top)*zhieght; ?????```
`float Xhoriz =llTan(PI_BY_TWO-angle_top)*zheight;`

• 1
Share on other sites

@Jenna Huntsman Hi thanks I think

pos = llGetPos();
pos.y -= (Xhoriz-1.8);
pos.z -=zhieght;
pos.x -=.7;

Needs different addition and subtraction depending on objects orientation How do i get this  please?

Share on other sites
4 minutes ago, VirtualKitten said:

@Jenna Huntsman Hi thanks I think

pos = llGetPos();
pos.y -= (Xhoriz-1.8);
pos.z -=zhieght;
pos.x -=.7;

Needs different addition and subtraction depending on objects orientation How do i get this  please?

It's likely that the pos.x is what you need to look at, along with pos.z.  pos.y is already accounting for the rotation (thanks to Xhoriz).

Share on other sites

+yes but think the - change to + and the axis changes when it rotates to different angle

Share on other sites

If this is a particle effect, why not just set the target as the particle sink? failing that, it wouldn't be too hard ot convert the vector from the source to the target to a rotation(quaternion) do some magic to make the axis point in the correct direction, then divide by root rotation.

• 1
Share on other sites

I don't understand sorry

Share on other sites
Posted (edited)

point 1. particles can be made to end up at a target prim by adding PSYS_PART_TARGET_POS_MASK to the particle flags, and PSYS_SRC_TARGET_KEY, target_key to the parameter list, so for example

```llParticleSystem(
[PSYS_PART_FLAGS,
/* other flags*/ |
0,
/* other particle parameters */
PSYS_SRC_TARGET_KEY, target_key]);```

still having a play with the rotation thing. not sure if llRotLookAt() works well for linked prims. the wiki has an example for llLookAt for linked prims :http://wiki.secondlife.com/wiki/LlLookAt

Edited by Quistessa
• 1
Share on other sites
Posted (edited)

@Quistessa I still need to get location of the object the emitter is in and rotated too to do my calculation offset angles . The test only works Y axis I need this to work 360  in Y and 360 Z  and X 360  and any combination there in . Does that make it clear i hope it does . Even if i make a if statement to test location i don't think this will work in between Y+ or X+ or X- or there between I think it needs more complicated math's can you please help? as clearly the emitter can change its location 3d and only create a fire when it hits tangible object like floor thing. i can do some coding but the math's with quaternions is hard to understand in this matter. I am hopeful of some good rotational advice with this trigonometry. I understand I can use llCastRay to identify objects but this has not got this far yet and is not needed at this point as the rotational mathematics is hard to start with I would be grateful of any help other than posting links on wiki as i can find these but they are not much help  unless you work for NASA.

I already have target acquiring in my movement program  script  walking and flying that is not the issue here . This is a mathematical issue i need to understand

Hugs
D x

Edited by VirtualKitten
Share on other sites
Posted (edited)

Okay, I dug through some of my old scripts to find the solution that I made for this.

```RezBall(float radial) //Offset in meters.
{
//This will rez the object at (offset) meters in front of the root.

vector v_rootPos = llGetPos(); //Info about the root prim
rotation r_rootRot = llGetRot();
vector finPos = v_rootPos + (<radial,0,0>*r_rootRot); //radial*rootRot to get the correct offset relative to the root (accounting for rotation) then add the region coords.

llRezObject("fireball",finPos,ZERO_VECTOR,r_rootRot,0);
}```

I changed some of it so it's more relevant to what you're doing, and added comments about the math so you can understand better.

It's on you to integrate that into whatever you're doing though!

This page is pretty useful when working out which trigonomic functions to use when working in 3D space (e.g. SL): https://mathworld.wolfram.com/SphericalCoordinates.html

Edited by Jenna Huntsman
Updated some of the terminology used to the mathematically correct words
• 1
Share on other sites
Posted (edited)
1 hour ago, VirtualKitten said:

The test only works Y axis I need this to work 360  in Y and 360 Z  and X 360  and any combination there in

It might be worth looking back at an older thread (ETA Stepper-motors) where you were asking about rotations and MollyMews demonstrated why Eulers get things wrong where quarternions get them right. I know they're harder to learn initially than old-fashioned trig, but as was demonstrated in that thread, particularly with regard to the Y-axis, Eulers require a load of defensive coding to be sure they always work where quarternions don't need anything extra.

Having done that, you then go to the wiki and look at the case for rotating an object about a point that is not it's centre, which is what I think you're trying to do.

Finally, anytime you call one of the trig functions you must convert any variables holding amounts in degrees into radians, otherwise the actual amounts you will get back from the functions will represent an angle, in radians, modulo Pi, in other words if you ask for llSin(90), what it will give you is Sin(90 % PI) or Sin(2.024) which in radians is somewhere up around 115 degrees (I would be more precise but amazingly, the Scientific calculator in the Raspberry Pi doesn't give me a button for the actual value of Pi, how weird is that?). Anyway, that 115 degrees will look close to the 90 degrees you were anticipating but that's just luck of the modulus-draw. Pick a different number and you'd end up with 5 degrees, or 160 degrees,... And don't forget those angles I'm quoting are just the input to the Sin function, which is then going to give you positive or negative results, basically you're lost.

ETA found it, there's a constants button for Pi and e

so 90 % Pi = 2.035, which in radians is the equivalent of 116 degrees, for which Sin will still be positive but decreasing and the actual angle will be 180 - 116 or 64 degrees, so the returned value of Sin(90 radians) in this case will be 0.894, instead of 1. I think. It's late here :)

Edited by Profaitchikenz Haiku
• 1
Share on other sites
Posted (edited)

nods I forgot about Radians too and yes Molly is great teacher silly kitten

12 hours ago, Jenna Huntsman said:

RezBall(float radial) //Offset in meters. { //This will rez the object at (offset) meters in front of the root. vector v_rootPos = llGetPos(); //Info about the root prim rotation r_rootRot = llGetRot(); vector finPos = v_rootPos + (<radial,0,0>*r_rootRot); //radial*rootRot to get the correct offset relative to the root (accounting for rotation) then add the region coords. llRezObject("fireball",finPos,ZERO_VECTOR,r_rootRot,0); }

I tried Jenna Huntsman routine above but the ball  was no where in site.

I used  this to call it the other commented red one works idk the explanation about radians was perfect Prof but unsure why Jennas puts it out of sight :

rot = llGetRot();
vel = <0.0,3.50,0.0>;
vector  a1 = llRot2Euler(rot); a1 *= RAD_TO_DEG;
float angle_top = a1.z;
float zhieght = pos.z+size.z;
float Xhoriz =llTan(PI_BY_TWO-angle_top)*zhieght;
pos = llGetPos();
pos.y -= Xhoriz;
pos.z -=zhieght;
pos.x -=.7;

//llRezObject("Fireball(llDie)", pos, vel , rot , 0);  // does work only when aligned with Y axis

RezBall(pos.y); // Places ball as pictured

Edited by VirtualKitten
Share on other sites

it might be best if you explain in more precise detail what it is that you wanting to do

it can be difficult to understand what you are meaning sometimes

going off your last post this is what I understand:

1) You are a dragon avatar

2) The dragon breathes particle fire from its mouth/nostrils in the direction of some target

3) You want to rez an object at the target. Near or at the end of the particle dragon fire breath

4) The object on rez at the target position will start some kind of particle fire inferno

5) The effect is that the dragon has set the target on fire

is this correct ?

if so then can you confirm this. And if is not correct then can you explain in numbered steps what it is you are wanting to do

when you detail more precisely what it is that you want to do then we can help you. We can't help when you ask for answers to questions that are phrased in a way that only you can understand

• 1
Share on other sites
Posted (edited)
7 hours ago, VirtualKitten said:

rot = llGetRot();
vel = <0.0,3.50,0.0>;
vector  a1 = llRot2Euler(rot); a1 *= RAD_TO_DEG;
float angle_top = a1.z;
float zhieght = pos.z+size.z;
float Xhoriz =llTan(PI_BY_TWO-angle_top)*zhieght;
pos = llGetPos();
pos.y -= Xhoriz;
pos.z -=zhieght;
pos.x -=.7;

vector  a1 = llRot2Euler(rot); a1 *= RAD_TO_DEG;  // so we're in degrees

float angle_top = a1.z; // still in degrees

float Xhoriz =llTan(PI_BY_TWO-angle_top)*zhieght; // NO! And again, I say NO NO!

PI_BY_TWO is in radians BUT angle_top is still in degrees, Lord knows what llTan is going to make of radians - degrees,  I'll just ask him. Ok, he says 3.14159/2.0 - 90 = 1.57079 - 90 = -88.4292, tangent of that is -0.50120278338 so it will tuck up out of sight for certain.

it needs to be

float Xhoriz =llTan(  PI_BY_TWO - (angle_top*DEG_TO_RAD) ) * zheight; // Now the value inside llTan( ) is pure radians, not a hybrid

Stop using degrees. Cease and desist

Edited by Profaitchikenz Haiku
too many NOs
• 1
Share on other sites
Posted (edited)
3 hours ago, VirtualKitten said:

nods I forgot about Radians too and yes Molly is great teacher silly kitten

I tried Jenna Huntsman routine above but the ball  was no where in site.

I used  this to call it the other commented red one works idk the explanation about radians was perfect Prof but unsure why Jennas puts it out of sight :

rot = llGetRot();
vel = <0.0,3.50,0.0>;
vector  a1 = llRot2Euler(rot); a1 *= RAD_TO_DEG;
float angle_top = a1.z;
float zhieght = pos.z+size.z;
float Xhoriz =llTan(PI_BY_TWO-angle_top)*zhieght;
pos = llGetPos();
pos.y -= Xhoriz;
pos.z -=zhieght;
pos.x -=.7;

//llRezObject("Fireball(llDie)", pos, vel , rot , 0);  // does work only when aligned with Y axis

RezBall(pos.y); // Places ball as pictured

Couple things:

pos.y is a region coordinate. This will probably break (The offset value is how many meters in front of the origin that the ball will spawn) - but llRezObject does have a max distance, so you need to feed it a 'known' low value (position is almost always not a good option for this, as it can be a high value).

Try feeding it (zhieght/2), which should then spawn the ball with an offset of half the object's height.

Also, note that the RezBall code treats the root prim as the origin, so whichever prim you have set as the 'emitter' is likely to be part of the linkset, not the root prim. You can add another value to the rezball code to specify the link number of the emitter, so v_rootPos and r_rootRot will be relative to the emitter instead of the root.

The RezBall code uses the rotation (in Rads) as a multiplier for the radial (offset), then adds the position of the root - so it avoids using specific functions (e.g. llSin or llCos) which I (personally) find cumbersome when working in 3D space. YMMV though (My trigonometry knowledge is usually pretty rusty, so I usually have to do research before using it).

Note that in my implementation the radial (offset) is only using one axis. You can use more to adjust the position (e.g. height relative to the root, left/right shift relative to root), but for simplicity only one axis is used.

Edited by Jenna Huntsman
Share on other sites
Posted (edited)
9 minutes ago, Jenna Huntsman said:

llSin or llCos) which I (personally) find cumbersome when working in 3D space.

This I think is where existing knowledge can be misleading. I'm old-fashioned and still mostly think inside my head using trig, which is why I often do what VK is doing here and use trig functions to prototype, and THEN when I have got an idea of what's going on, I'll rewrite in quaternions. The whole root of the problem that's being discussed here is mixing up radians and degrees. Because of the way the trig functions are implemented here (and in almost all other maths packages), the input to any trig function must be in radians, not degrees UNLESS you want Sin/Cos/Tan of 0, that's the only place where the two systems align.

The big advantage to prototyping using trig functions is you can do what I've been doing, throw numbers into a calculator and get positions back to see where things are gong. You can't do that qith quarternions (although I admit it does make more sense to make a test harness inworld with a script using rots and vectors.)

Edited by Profaitchikenz Haiku
• 1
Share on other sites
13 minutes ago, Profaitchikenz Haiku said:

This I think is where existing knowledge can be misleading. I'm old-fashioned and still mostly think inside my head using trig, which is why I often do what VK is doing here and use trig functions to prototype, and THEN when I have got an idea of what's going on, I'll rewrite in quaternions. The whole root of the problem that's being discussed here is mixing up radians and degrees. Because of the way the trig functions are implemented here (and in almost all other maths packages), the input to any trig function must be in radians, not degrees UNLESS you want Sin/Cos/Tan of 0, that's the only place where the two systems align.

The big advantage to prototyping using trig functions is you can do what I've been doing, throw numbers into a calculator and get positions back to see where things are gong. You can't do that qith quarternions (although I admit it does make more sense to make a test harness inworld with a script using rots and vectors.)

Yeah, agreed. It's one of those things where you just have to do whatever works best for you, my brain works better in quaternions 😂

That being said, there's a set of great interactive learning tools which help you understand quaternions (and exactly what formula is used to calculate them) here: https://eater.net/quaternions

It helped me a lot when I was stuck with trig a couple months back!

Share on other sites

Thanks for the link, that looks interesting.

That said, I do understand why VK uses trig in this way because (when prototyping) I do too, since spreadsheets and calculators don't offer quarternions. If I'm working on something that's more than just mildly complicated I'll use a calculator or for more complex problems a spreadsheet, so I can chuck in positions and calculate new positions based on the angles involved, and then get the test harness to chat out what it's derived from the expressions for comparison against tthe pre-calculated figures.

The fundamental problem which I've been trying to draw attention to is that everything going into a trig function has to be in radians. Given that llRot2Euler already provides a vector comprising radians, I think VK's stumbling block is using RAD_TO_DEG for intermediate products. This is counter-productive as they are going to have to be converted back into radians before anything useful can be done with them. The only time to use RAD_TO_DEG is for an llOwnerSay diagnostic output, at all other times the contents of vectors and floats should remain in radians. If literals are used which are required to be in degrees for readability, they should be converted to radians immediately (such as 45*DEG_TO_RAD).

Share on other sites
Posted (edited)
7 hours ago, VirtualKitten said:

( I made a tweak, see below)

I realised with all my pontificating we had lost sight of the OP's original problem.

```// amended to work purely in Radians

rot = llGetRot();
vel = <0.0,3.50,0.0>;
vector  a1 = llRot2Euler(rot); // is in radians, so following NOT NECESSARY a1 *= RAD_TO_DEG;
float angle_top = a1.z; // in radians
float zhieght = pos.z+size.z;
float Xhoriz =llTan(PI_BY_TWO-angle_top)*zhieght; // both PI_BY_TWO and angle_top are in radians so give the required angle
pos = llGetPos();
pos.y -= Xhoriz;
pos.z -=zhieght;
pos.x -=.7;

// try that```

@VirtualKitten - try the above script, and see what it gives you.

As you said earlier, this will only give you a displacement along the Y axis. I'm guessing at what you want to achieve but I think it's this:

The dragon is facing a spot at which it is to breathe fire and set something alight. This position is to be a certain distance ahead and a certain distance below the dragon's mouth/nostrils

So your calculated Xhoriz is the distance along the Dragon's forward vector

in order to calculate the X and Y of where the hypotenuse strikes the ground, you then have to calculate a NewX and NewY based on xHoriz being the hypotenuse of a triangle on the ground plane, the hypotenuse is along the dragon's forward vector

you have to get Sin and Cos of the angle Theta between the base forward vector (as if the Dragon was pointing towards X)  and the dragon's forward vector

don't assign Xhoriz to y as you are currently doing, instead:

calculate the remaining two sides of the triangle using Sin and Cos of theta times Xhoriz  , and add the two values to pos.x and pos.y, and that should be the point on the ground no matter which way the dragon is pointing.

It's probably easier to do this using RayCasting, but just because something is more difficult doesn't mean it shouldn't be attempted/

Edited by Profaitchikenz Haiku
Share on other sites
2 hours ago, Profaitchikenz Haiku said:

I realised with all my pontificating we had lost sight of the OP's original problem.

```
// amended to work purely in Radians

rot = llGetRot();
vel = <0.0,3.50,0.0>;
vector  a1 = llRot2Euler(rot); // is in radians, so following NOT NECESSARY a1 *= RAD_TO_DEG;
float angle_top = a1.z; // in radians
float zhieght = pos.z+size.z;
float Xhoriz =llTan(PI_BY_TWO-angle_top)*zhieght; // both PI_BY_TWO and angle_top are in radians so give the required angle
pos = llGetPos();
pos.y -= Xhoriz;
pos.z -=zhieght;
pos.x -=.7;

// try that```

@VirtualKitten - try the above script, and see what it gives you.

As you said earlier, this will only give you a displacement along the Y axis. I'm guessing at what you want to achieve but I think it's this:

The dragon is facing a spot at which it is to breathe fire and set something alight. This position is to be a certain distance ahead and a certain distance below the dragon's mouth/nostrils

So your calculated Xhoriz is the distance along the Dragon's forward vector

in order to calculate the X and Y of where the hypotenuse strikes the ground, you then have to calculate a NewX and NewY based on xHoriz being the hypotenuse of a triangle on the ground plane, the hypotenuse is along the dragon's forward vector

you have to get Sin and Cos of the angle Theta between the base forward vector (as if the Dragon was pointing towards X)  and the dragon's forward vector

don't assign Xhoriz to y as you are currently doing, instead:

calculate the remaining two sides of the triangle using Sin and Cos of theta times Xhoriz  , and add the two values to pos.x and pos.y, and that should be the point on the ground no matter which way the dragon is pointing.

It's probably easier to do this using RayCasting, but just because something is more difficult doesn't mean it shouldn't be attempted/

Just to add some info about how the RezBall code can use this:

Essentially, the Radial (/ offset) is the length of the Hypotenuse - so using the code from @Profaitchikenz Haiku to calculate the hypotenuse between the emitter and the ground plane, you can feed the resulting hypotenuse into RezBall and it will then always rez the fireball on the ground.

If you're calculating using coordinates, you can actually simplify the calculation a lot if you already know the coords of the destination using llVecDist, which will return a float value (in meters) of the non-negative distance between your emitter and the destination. (This is *kind of* a cheat to find the hypotenuse without using the real functions!)

Share on other sites
Posted (edited)

hmm Prof said in order to calculate the X and Y of where the hypotenuse strikes the ground, you then have to calculate a NewX and NewY based on xHoriz being the hypotenuse of a triangle on the ground plane, the hypotenuse is along the dragon's forward vector . I m not sure what he meant .? axes seem  to change and + and - change as well when rotating dragon . How do I wroite around this prof please?

Edited by VirtualKitten
Share on other sites
Posted (edited)

Now see what you made me do...

The blue triangle is aligned such that the two sides adjoining the right-angle lie along X and Y, the yellow triangle is aligned with the dragon's forward vector. (In fact the point where the triangles intersect closest to the dragon is really supposed to be the centre of the link set but that wouldn't have made such a lovely picture, the triangles will be congruent anyway so it's a trivial point).

You have solved the length of the base of the yellow triangle, now use it as the hypotenuse of the blue triangle; it is a radius R and has an angle theta at the dragon's head (well, one of them anyway),  and so R sin(theta) and R cos(theta) give a pair of deltas to add to the global coordinates of the dragon's head (well, one of them anyway). Oh, and don't forget, RADIANS.

The way Sin and Cos change signs as theta goes from 0 to 360 degrees (2*PI radians) means the calculated deltas will likewise change sign and give the correct final position assuming you always take the base forward X vector as your reference point. (Rezz a prim, it's X-axis will be aligned with the base forward vector X axis when the rotation of the Z axis is 0 (either degrees or radians)).

It would be ever so much easier to do all of this with quarternions and the helpful functions, but as you've stipulated you can't abide them I've shown how to do this using basic trig (again, spherical Trig would actually be slightly easier here as well).

Sorry I couldn't get Snap's head up higher but he's a real slouch even when he's been fed, (he likes furries best of all by the way so don't ask to come and meet him, after a fast of several years I suspect he'd become uncontrollable).

Edited by Profaitchikenz Haiku
• 1
Share on other sites
Posted (edited)
9 hours ago, Profaitchikenz Haiku said:

It would be ever so much easier to do all of this with quarternions and the helpful functions, but as you've stipulated you can't abide them I've shown how to do this using basic trig (again, spherical Trig would actually be slightly easier here as well).

Definitely, I think my brain fried while reading that! 😅

Edited by Jenna Huntsman
• 1