Jump to content
Sign in to follow this  
UNN

setVector Function Request

Recommended Posts

Anyone able to write a function(s) that would ensure an object attached to an aircraft, will always point north with 0 pitch and bank?

Afraid my maths isn't up to it :(

Share this post


Link to post
Share on other sites

Have a play with this... but it would take repeated calls to keep it oriented the way you want.

Along the lines of setpositioning it every 0.05 seconds or less. Might cause some stress on the system and in a MP game not sure how this would look.

fn_orientObject.sqf:-

/*

[b]call with:[/b] nul = [object,direction,angle,pitch] call fn_orientObject

*/

private ["_obj","_dir","_ang","_pit","_vecdx","_vecdy","_vecdz","_vecux","_vecuy","_vecuz"];

_obj = _this select 0;
_dir = _this select 1;
_ang = _this select 2;
_pit = _this select 3;

_vecdx = sin(_dir) * cos(_ang);
_vecdy = cos(_dir) * cos(_ang);
_vecdz = sin(_ang);

_vecux = cos(_dir) * cos(_ang) * sin(_pit);
_vecuy = sin(_dir) * cos(_ang) * sin(_pit);
_vecuz = cos(_ang) * cos(_pit);

_obj setVectorDirAndUp [[_vecdx,_vecdy,_vecdz],[_vecux,_vecuy,_vecuz]];

true

In your init.sqf:-

fn_orientObject = compile preprocessFileLineNumbers "fn_orientObject.sqf";

Share this post


Link to post
Share on other sites
Might cause some stress on the system and in a MP game not sure how this would look.

Yeah, usually repeated use of setPos, setDir, setVelocity and other stuff like that results in some ugly stuttering in MP.

Share this post


Link to post
Share on other sites

I'm frightened that UNN is asking something. :eek: Every time I've come across something totally obscure and magical it's usually been a UNN post that's provided the answer! :)

Share this post


Link to post
Share on other sites

Hi,

Thanks for the replies so far. Setting the vector of an object is easy enough thanks to the many functions already available, that's not the problem. The problem I have is setting the vector of an object that's attached to another object.

In this case I want to keep the child (the attached object) orientated so it always points north and always stays horizontal along both axis. Let me explain in more detail.

If the parent object is pointing 90 degrees (East) , then the child's direction has to be set to 0-90.

If the parent object has its nose pointing down by 20 degrees, then the child's nose has to point up by -20 degrees.

All this sounds straight forward until you start dealing with attached objects. When the parent is pointing East with it's nose down by 20 degrees, the child object orientated to point north now has it's wings angled to 20 not its nose.

Set the parents direction back to 0 degrees (North) then the child now has it's nose pointing down again.

What I described above is quite simple compared to when the parent object is orientating along all three axis.

Think of it another way, I want a set vector function with an additional parameter. The parameter is "Relative (True\False)". So I could call the following:

_child attachTo [_parent,[0,20,0];

[_child,0,0,0,false] call _function;

When "Relative" is false, the function would ignore the orientation of the object the child is attached to. Instead it would always be pointing north, in a straight and level direction. Hence the [0,0,0] array being passed.

I've made an example mission which will hopefully communicate this problem better than I can.

http://www.freefilehosting.net/unnorientateattachedutes

Thanks

Edited by UNN

Share this post


Link to post
Share on other sites

If I understand correctly you would like to attach an object that behaves like water. Always leveled and in your case always facing north.

So the script would constantly need to calculate the correct pitch and bank relative to the parents object and execute some setVector statement. Why not use a simple setDir and then a loop of setPos with a position relative to the parent object instead? Both approaches require to be run every 0.01 seconds to provide best results anyway.

Or do you think attachTo + setVector causes less delay in positioning compared to setPos when in MP? In SP there's never an issue usually, in MP there can be delays even with attachTo objects, as I have observed a couple of times during MP games. And if you're concerned about the parent object crashing into the child object during movement you could still execute "enableSimulation false" on the child object as long as attached to the parent.

Just my 2 cents,

VictorFarbau

Share this post


Link to post
Share on other sites

If I understand correctly you would like to attach an object that behaves like water

That’s exactly the effect I want to achieve.

Why not use a simple setDir and then a loop of setPos with a position relative to the parent object instead?

That’s what I was doing and it work well enough, even in MP. But since patch 1.60 all thats changed. It looks awful now, even in single player. Guess they introduced some sort of script interrupt.

Share this post


Link to post
Share on other sites

Yep, clear. After attaching a child to a parent object the child will assume the parent as its coordinate system and north means being straight aligned with the parent. As I see it the calculation would be:

1. Calculate delta of parent's vector and real world [0,0,1]

2. Apply inverted delta to the child object

Surely enough quite annoying to calculate :) Post 2 shows the translation from degrees to vector which is needed for step 2. Haven't wrapped my head around step 1 yet and it shouldn't be rocket science but I saw many people giving up on setVector so I won't talk too big.

VictorFarbau

Share this post


Link to post
Share on other sites

Quite easy, i write down some pseudo code:

a = root object

b = child object

direction b is relative to the orientation of object a. If object a has a heading of 90, object a's heading - 90 returns object b's orientation.

if(dir a <= 180){
  dir b = - dir a;
}else{
  dir b = 360 - dir a
}

Is that what you are looking for?

Example:

dir a = 110

result: dir b= - 110

dir a= 240

result: dir b = + 120

Edited by derdoe

Share this post


Link to post
Share on other sites

Haven't wrapped my head around step 1 yet and it shouldn't be rocket science but I saw many people giving up on setVector

That’s what I find so frustrating, I have a vague idea of what needs to be done. But even regular vectors are beyond my maths skills it seems. Again I can't stress how much I appreciate any help with vectors. It's so demoralizing, having a project stall, when it’s almost near completion.

@derdoe

Unfortunately not, applying this to one axis is easy enough. Combining all three gets much more complicated.

Share this post


Link to post
Share on other sites

If you attach it to an animated Vertices does it still retain the direction of the parent object , was thinking if both objects are available in mlod you could perhaps try to animate the vert to which the object attached to,

I know from experience the attached object does follow the animated vert rather than the parent objects when animated but cant from memory remember if it would also turn with the animation also .

thinking you could create an alternative compass vert and use the Mirror define to set it at - 180 possibly.

Share this post


Link to post
Share on other sites

I almost got it, it needs some finetuning but it should work eventually. It's not only about understanding the applied vector space but also the sequence of commands is essential apparently. When I'm done I'll post it here. If you don't hear back I jumped out of the window.

Cheers,

VictorFarbau

Edited by VictorFarbau

Share this post


Link to post
Share on other sites
If you don't hear back I jumped out of the window.

Same here... ready to jump out the window on this one! LOL!

Share this post


Link to post
Share on other sites

No success and my gut feeling is, even when correctly computed it will still look completely dorky. Here's what I observed during my attempts:

When A is attached to B:

1. setVectorDir alone will just cause unit A to flicker once

2. setVectorDirandUp applies the horizontal position of A correctly (array 1 of 2) but seems to completely ignore the pitch and bank array (array 2 of 2)

3. setVectorUp needs to be applied on A but can only be used in conjuction with a preceding setVectorDirandUp

4. calculation of a identical pitch and bank requires compensation for current vector of B PLUS misalignment between model centers PLUS distance between A and B

So keeping the north orientation through setVectorDirandUp is no problem (sin and cos of parents direction), pitch and bank remains more or less out of control even though I bascially understand how they are supposed to work now. If the desired flat north orientation works then still this looks unnatural as the rotational center of A and B won't match (point 4, downside of attachto).

I already spent 4h with this and the results just look stupid so I will put this idea to rest; maybe attachTo + setVector just doesn't cut it for this requirement. Sorry UNN, it just doesn't work out correctly for me and I can't figure out why. In my opinion a classical 3d vector command [degree left/right, degree up/down, degree forward/backward] would be more helpful compared to this freaky 2 * 2d vector concept.

And guess what, if you had VBS2 you'd solve your problem in 2 minutes (parameter "relative"):

VBS2: http://resources.bisimulations.com/wiki/setVectorDirAndUp

VictorFarbau

Edited by VictorFarbau

Share this post


Link to post
Share on other sites

Sorry UNN, it just doesn't work out correctly for me and I can't figure out why.

No worries, thanks for trying. I didn't rule out the fact that Arma's vector commands could either be wrong or limited in some way. But I wasn't in a position to say.

And guess what, if you had VBS2 you'd solve your problem in 2 minutes (parameter "relative"):

Actually, that param does nothing in the function, it defaults to false.

While it is taking me some time, as it still isn't straight forward, I am making some progress with cfg animations as Thromp suggested. Not by attaching to them, but simple because you can handle each rotation separately, rather than setVector which tries to do everything in one go.

I'm not in a position to say it will work atm, otherwise I would have let you all know sooner. But from the sounds of it, I think setVector is a dead end? Thanks for all your help.

Share this post


Link to post
Share on other sites

Don't forget also , sometimes it is a last resort to make the thing your attaching a Man class and give it an exclusive Crew position, this way you can animate the Cargo proxy.

in recent past I have found when doing any cargo stuff and trying to beat the internal view render showing things outside the vehicle, its simpler to give the cargo a Animal based config inheritance and simply moveincargo the piece and animate it the proxy (forklifts or whatever I am messing with for example.

just another Angle ( pun)

Share this post


Link to post
Share on other sites

Basically, each object has 2 vectors representing where it is facing. 1 represents where the top is facing, and another where the front is facing.

One vector is facing directly north with its top facing directly up, and the other in an arbitrary direction.

Let's start with the facing direction (you can then do the same with the top direction alter). The objects vector you get from getVectorDir (let's call it A), while the other is [0,1,0] (facing north - let's call it B).

The direction around which we need to rotate to counteract the orientation of the root object is U = A x B:

421ca5f44d287bbde0dffa8e3a0608eb.png

1,2,3 would normally correspond to the x,y,z axes, but remember in Arma y -> -y and phi -> -phi in all formulas due to the difference between the conventions of map coordinate systems as opposed to the ones usually used in math formulas such as the ones you would find on wikipedia.

Now that we have the direction of the axis around which we rotate, we need to normalize it so that Ux'^2 + Uy'^2 + Uz'^2 = 1. So the normalized vector U' = U / (Ux^2 + Uy^2 + Uz^2).

The angle at which we rotate is easy:

Theta = arccos ((A dot B)/(|A||B|))

A dot B = A1B1 + A2B2 + A3B3

|A| = sqrt (A1^2 + A2^2 + A3^2)

And same for |B|.

Now the rotation matrix (from wikipedia) would be:

fbaee547c3c65ad3d48112502363378a.png

So now you need to do a simple matrix vector multiplication to get your desired vectorDir. I'll let you look up the formulas for the multiplication. Let's call the result C = R dot A.

As long as you remember to reverse the y coordinates (so [Ax,Ay,Ax] is changed to [Ax,-Ay,Az] and [0,1,0] is changed to [0,-1,0]), and in the end you reverse the y axis of C again (so [Cx,Cy,Cz] is changed to [Cx,-Cy,Cz] before you setVectorDir, it should be good.

Repeat the exact same process with the 2 getVectorUp and set the result with setVectorUP and you *should* be fine if you got all the linear and vector algebra correctly.

Of course, setVectorDir and setVectorUp repeatedly might stutter, as already been mentioned, but at least it'll point in the right direction when the script does get a chance to execute.

Share this post


Link to post
Share on other sites

I spent hours looking at it as Trig rotation and couldn't get it to work. Gave up in the end. Will try to digest the vector math.

Share this post


Link to post
Share on other sites

Thanks galzohar, I would really like to learn this stuff for myself and I would still like a vaector based function as well. Will try plowing through your notes.

in recent past I have found when doing any cargo stuff and trying to beat the internal view render showing things outside the vehicle, its simpler to give the cargo a Animal based config inheritance and simply moveincargo the piece and animate it the proxy (forklifts or whatever I am messing with for example.

Thanks, I used a similar

myself back in the Arma1 days. Not what I need for this task, but I think PhysX in Arma3 should be an improvement, if you want to transport cargo around.

Share this post


Link to post
Share on other sites

I tried doing this lately, I was making a laser designator camera for a plane script. I was trying to attach a turret that would stay level and point in the same direction when the plane moved. The only way I could do it easily was to use visiblepostion:

_plane = plane;
_turret = turret;

while {true} do
{
       _turret setposATL [visiblePosition _plane select 0, visiblePosition _plane select 1, (visiblePosition _plane select 2) + 10];
};

You could use some older code to give it an offset from the model, because modeltoworld doesn't use the visible layer anymore (even though it should). The only problem was that it wigs out if you are in the attached vehicle (at least for static guns). If it is manned by ai then it is ok.

Share this post


Link to post
Share on other sites

By the way, I think I was wrong about flipping the Y axis. It's actually only the angles that are defined differently. X x Y = Z in Arma just like in a standard coordinate system, so you don't need to flip any directions, however the angles are defined differently (which don't matter in this case since you're only using vectors defined by [x,y,z]).

If you're using setPos rather than attachTo, why not just use setPosASL relative to the plane's setPosASL? Sea level is always the same reference point no matter where you are, and at least doesn't seem to give any trouble regarding getting the correct height.

As for lasers, though, the real problem is not so much about keeping them pointed in the same real-world direction, and more about keeping them pointed at the same spot on the ground, which is much more difficult to do with scripting (as you can see, BIS scripts try to do it but don't do it very well at all). Not sure how easy it is to keep a camera pointed at the same spot on the ground with a real UAV/plane, though, I'll have to do some digging about that.

Edited by galzohar

Share this post


Link to post
Share on other sites

//calculate the dot product of 2 3-dimensional vectors
fn_dot=
{
   private ["_vec0", "_vec1", "_vec0X", "_vec1X", "_vec0Y", "_vec1Y", "_vec0Z", "_vec1Z"];
   _vec0 = _this select 0;
   _vec0X = _vec0 select 0;
   _vec0Y = _vec0 select 1;
   _vec0Z = _vec0 select 2;
   _vec1 = _this select 1;
   _vec1X = _vec1 select 0;
   _vec1Y = _vec1 select 1;
   _vec1Z = _vec1 select 2;
   (_vec0X * _vec1X) + (_vec0Y * _vec1Y) + (_vec0Z * _vec1Z)
};

//calculate the cross product of 2 3-dimensional vectors
fn_cross=
{
   private ["_vec0", "_vec1", "_vec0X", "_vec1X", "_vec0Y", "_vec1Y", "_vec0Z", "_vec1Z"];
   _vec0 = _this select 0;
   _vec0X = _vec0 select 0;
   _vec0Y = _vec0 select 1;
   _vec0Z = _vec0 select 2;
   _vec1 = _this select 1;
   _vec1X = _vec1 select 0;
   _vec1Y = _vec1 select 1;
   _vec1Z = _vec1 select 2;
   [
       (_vec0Y * _vec1Z) - (_vec0Z * _vec1Y),
       (_vec0Z * _vec1X) - (_vec0X * _vec1Z),
       (_vec0X * _vec1Y) - (_vec0Y * _vec1X)
   ]
};

//project 3-dim vector _vec onto axes of local coord system of _obj
//"_obj worldToModel _vec" without translation - i.e. rotation only
fn_proj=
{   private ["_obj", "_vec", "_xAxis", "_yAxis", "_zAxis"];
   _vec = _this select 0;
   _obj = _this select 1;

   _yAxis = vectorDir _obj;
   _zAxis = vectorUp _obj;
   _xAxis = [_yAxis, _zAxis] call fn_cross;

   [
       [_vec, _xAxis] call fn_dot,
       [_vec, _yAxis] call fn_dot,
       [_vec, _zAxis] call fn_dot
   ]
};

_child setVectorDirAndUp [[[0,1,0],_parent] call fn_proj,[[0,0,1],_parent] call fn_proj];

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

×