Jump to content

Camera rotating linked object script problem


darkstylerz
 Share

You are about to reply to a thread that has been inactive for 2553 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

Hello, I have been working on the script that moves the linked object where the camera is pointing. For use in vehicles, for turret or something. Could you help me with it?

Using the standard one I found somewhere is is a mess, and objects tend to stand to the side:

//Camera Follower Script
//llGetCameraPos & llGetCameraRot Example
//By Nika Rugani
 
integer perm_track = 0x400;
float second_check = 0.1;
 
vector object_offset = <0,0,2>; //Offset of the cameras position where the object will set itself
 
integer die_channel = 0;
string die_command = "/die";
 
quickPosRot(vector pos, rotation rot)
{//This way you don't have the 0.2 second sleeps from llSetPos and llSetRot
    llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_POSITION, pos, PRIM_ROTATION, rot]);
}
 
default
{
    on_rez(integer a)
    {
        llResetScript();
    }
    state_entry()
    {
        llRequestPermissions(llGetOwner(), perm_track);
    }
    run_time_permissions(integer permission)
    {
        if(permission == perm_track)
        {
            llSetTimerEvent(second_check);
            llListen(die_channel, "", llGetOwner(), "");
        }
        else
        {
            //llResetScript(); //Remove comment to loop the process of requesting permissions if user deny's permission
            //llDie(); //Remove comment to kill the object if user deny's it
        }
    }
    listen(integer channel, string name, key id, string str)
    {
        str = llToLower(str);
        if(str == die_command)
        {
            llDie();
        }
    }
    timer()
    {
        vector c_pos = llGetCameraPos(); //Get Users Camera Position
        rotation c_rot = llGetCameraRot(); //Get Users Camera Rotation
        c_pos = (c_pos+object_offset*c_rot); //Apply the offset to the position
        quickPosRot(c_pos, c_rot); //EXECUTE ORDER!
    }
}

 So I modified it to have something like this at the timer section.

 timer()
    {


vector rotated = <0, 0, 0>;
vector rotated2 = <0, 0, 1>;
rotation rot;
rotation rot2;
 rotated *= DEG_TO_RAD;
        rot = llEuler2Rot( rotated );
        rot2 = llEuler2Rot( rotated2 );
        rotation c_rot = llGetCameraRot()+rot2 - llGetCameraRot()+rot;

//llSetLocalRot(true);
vector c_pos = llGetCameraPos();

        quickPosRot(c_pos, c_rot); //EXECUTE ORDER!
    }

 What it does, it turns the object towards the direction vehicle is turning, one axis wise. But it is working poorly and not constant.

On the other one I have that script:

rotation rot_xyzq;


default
{

    state_entry() {
        llListen(-80001,"", NULL_KEY, "");
    }

    listen(integer channel, string name, key id, string message) {
        if (message == "turret left") {

        // speak out loud!
         vector xyz_angles = <0,0,3>; // This is to define a 1 degree change
        vector angles_in_radians = xyz_angles*DEG_TO_RAD; // Change to Radians
        rot_xyzq = llEuler2Rot(angles_in_radians); // Change to a Rotation
        llSetLocalRot(llGetLocalRot()*rot_xyzq); //Do the Rotation...

        }
         if (message == "turret right") {

        // speak out loud!
         vector xyz_angles = <0,0,-3>; // This is to define a 1 degree change
        vector angles_in_radians = xyz_angles*DEG_TO_RAD; // Change to Radians
        rot_xyzq = llEuler2Rot(angles_in_radians); // Change to a Rotation
        llSetLocalRot(llGetLocalRot()*rot_xyzq); //Do the Rotation...

        }
    }

}

 I took it from somewhere and edited for my needs, and it turns turret with correspondent gestures. Do you know any way to make cannon move smoothly and aim where I want it?  I will give the finished tank model to anyone who can guide me well. Thank you for help.

Link to comment
Share on other sites

I tried to come up with a sensibel answer but found that I don't know the question

  1. Do you want to rotate a turret (on a tank)? A turret is bound to a local rotation plane
  2. Do you want to rotate a gun so it aim at a given point? A gun on a tank would rotate within local limits
  3. The script example is a camera follower that makes a prim follow the camera where it goes and where it looks.
    Is this what you want?

I am not going to answer all three

  • Like 1
Link to comment
Share on other sites

rotation a = llGetCameraRot()/llGetRootRotation();vector LEFT = llRot2Left( a);vector UP = <0.0, 0.0, 1.0>;a = llAxes2Rot( LEFT%UP, LEFT, UP);llSetLinkPrimitiveParamsFast( child_prim_number, [PRIM_ROT_LOCAL, a]);

 This snippet will rotate a child prim around the root prims Z-axis and child prim's X-axis will be forward

Since the rotation is bound to the root prim it can not obtain the camera direction in general, but compass bearings are the same for prim and camera

Also note that prim and camera may 'look' at different targets if the camera is not in same position as the prim

This may be ignored if they are not too far apart

:smileysurprised::):smileyvery-happy:

  • Like 1
Link to comment
Share on other sites

Thank you for answer. I tried the script, and it works well, but child prims still rotate around their own prims, not using the root prim. Also if other prim uses the same script (cannon barrel) it swings aimlessly in all directions.

 

 

Thank you

Link to comment
Share on other sites

This works better, it rotates child prims around the prims Z-axis parallel to the roots Z-axis

rotation a = llGetCameraRot();vector LEFT = llRot2Left( a);vector UP = < .0, .0, 1.0 >;a = llAxes2Rot( LEFT%UP, LEFT, UP);llSetLinkPrimitiveParamsFast( 2, [PRIM_ROT_LOCAL, a]);

This doesn't change the prims local position
If you wan't another pivot point you have to rotate the local position as well as the rotation

This is harder but doable

ETA: snippet is not all right yet, I will return when it is :)

  • Like 1
Link to comment
Share on other sites

Better still:

rotation a = llGetCameraRot()/llGetRootRotation();
vector FWD = llRot2Fwd( a);
vector UP = < .0, .0, 1.0 >;
vector LEFT = llVecNorm( UP%FWD);
a = llAxes2Rot( LEFT%UP, LEFT, UP);
llSetLinkPrimitiveParamsFast( 2, [PRIM_ROT_LOCAL, a]);

 :smileysurprised::):smileyvery-happy:

ETA: all vectors for llAxes2Rot must be normalized. LEFT wasn't before, it is now

  • Like 1
Link to comment
Share on other sites

http://puu.sh/gQKTa.jpg basically yeah, like this. I am already trying to make main cannon move up down too, I think I will use the same script you are writing, but first will be using the root rot once ready + limited (still no idea how) self prim rot.

Orange shows root prim and it's center.

I have seen cannon done way so game gives it local prim somewhere in the middle:

http://puu.sh/gQLc6.png

But is it possible for such object to listen 2 commands at once?

Link to comment
Share on other sites

First see the correction I made to the snippet I posted lately.

Next: you are right to make the canon in a way it will rotate about it's position, that makes scripting easier and rotates smoother

You need two calls to llSetLinkPrimitiveParamsFast one for each child prim

:smileysurprised::):smileyvery-happy:

  • Like 1
Link to comment
Share on other sites

The snippet for both turret and gun may look like this:

rotation a = llGetCameraRot()/llGetRootRotation();vector FWD = llRot2Fwd( a);vector UP = < .0, .0, 1.0 >;vector LEFT = llVecNorm( UP%FWD);a = llAxes2Rot( LEFT%UP, LEFT, UP);llSetLinkPrimitiveParamsFast( 2, [PRIM_ROT_LOCAL, a]); // turreta = llAxes2Rot( FWD, LEFT, FWD%LEFT);llSetLinkPrimitiveParamsFast( 3, [PRIM_ROT_LOCAL, a]); // gun

 Both prims are rotated about their position and both have X pointing forward

:smileysurprised::):smileyvery-happy:

  • Like 1
Link to comment
Share on other sites

Thank you, it works, but still I would like to know if child prims can be rotated around center of root prim. Maybe I am doing something wrong, but all they do is they spin around. Taking the dual cannon behavior it must be a way to make it move independently in both axis?

 

EDIT:

default{    state_entry() {        llSetTimerEvent(0.2);    }    timer() { llRequestPermissions(llGetOwner(),PERMISSION_TRACK_CAMERA);      rotation a = llGetCameraRot()/llGetRootRotation();vector LEFT = llRot2Left( a);vector UP = <0, 0.0, 0.0001>;a = llAxes2Rot( LEFT%UP, LEFT, UP);llSetLinkPrimitiveParamsFast( LINK_THIS, [PRIM_ROT_LOCAL, a]);    }}

 I made it like this, and it acts like it should.

The only concern left is that I can't make cannon wiggle up and down, archieving it's rotation around as well. It causes cannon eaither shake if I use 2 of your scripts, or wildly go around.

I have learned that items need to be done properly. But for some reason they are not having quite same axles as they do in 3DSmax.

Are there any ways to limit the cannon travel? Turn to some degree and stop?

Link to comment
Share on other sites


darkstylerz wrote:

Thank you, it works, but still I would like to know if child prims can be rotated around center of root prim. Maybe I am doing something wrong, but all they do is they spin around. Taking the dual cannon behavior it must be a way to make it move independently in both axis?

There is. You need lists for local centers and offsets and a matching list with the prim numbers

rotation a = llAxes2Rot( FWD, LEFT, FWD%LEFT);

integer i = llGetListLength( prim_number_list);

while ( i-- )

{

    vector b = llList2Vector( local_centers, i) + llList2Vector( local_offsets, i)*a;

    llSetLinkPrimitiveParamsFast( llList2Integer( prim_number_list, i), [PRIM_ROT_LOCAL, a, PRIM_POS_LOCAL, b]);

}

 assuming same rotation for all prims listed


darkstylerz wrote:

EDIT:
vector UP = <0, 0.0, 0.0001>;

This is not a unit vector as demanded: All three vectors must be mutually orthogonal unit vectors


darkstylerz wrote:

The only concern left is that I can't make cannon wiggle up and down, archieving it's rotation around as well. It causes cannon eaither shake if I use 2 of your scripts, or wildly go around.


You can but not with the < .0, .0, .0001 > vector you have

Add a line in my newest script for each cannon:

llSetLinkPrimitiveParamsFast( 3, [PRIM_ROT_LOCAL, a]); // gun 1

llSetLinkPrimitiveParamsFast( 4, [PRIM_ROT_LOCAL, a]); // gun 2

llSetLinkPrimitiveParamsFast( 5, [PRIM_ROT_LOCAL, a]); // gun 3

etc.


darkstylerz wrote:

I have learned that items need to be done properly. But for some reason they are not having quite same axles as they do in3DSmax.

SL will compute the prim center from the geometry of your mesh/sculpty and not the one you set in you 3D modelling program, so your model must be designed carefully to get the center where you want it


darkstylerz wrote:

Are there any ways to limit the cannon travel? Turn to some degree and stop?

Yes, check and modify 'FWD' like this:

float u = FWD.z;float Hi = llCos( highr_Limit*DEG_TO_RAD);float Lo = llCos( lower_Limit*DEG_TO_RAD);if ( u > Hi ) u = Hi;else if ( u < Lo ) u = Lo;FWD = < llSqrt( 1.0 - u*u), 0.0, u >;

 where highr_ and lower_limit are angles in degrees measured from vertical up

:smileysurprised::):smileyvery-happy:

  • Like 1
Link to comment
Share on other sites

The limit check I gave does not work in your case

I have included one that does in this snippet:

rotation a = llGetCameraRot()/llGetRootRotation();vector FWD = llRot2Fwd( a);vector UP = < .0, .0, 1.0 >;vector LEFT = llVecNorm( UP%FWD);a = llAxes2Rot( LEFT%UP, LEFT, UP);llSetLinkPrimitiveParamsFast( 2, [PRIM_ROT_LOCAL, a]); // turretif ( FWD.z > llCos( upLimit) ) FWD = llVecNorm( LEFT%UP + UP/llTan( upLimit));else if ( FWD.z < llCos( downLimit) ) FWD = llVecNorm( LEFT%UP + UP/llTan( downLimit));a = llAxes2Rot( FWD, LEFT, FWD%LEFT);llSetLinkPrimitiveParamsFast( 3, [PRIM_ROT_LOCAL, a]); // gun

 where upLimit and downLimit are angles in radians measured from vertical up

:smileysurprised::):smileyvery-happy:

  • Like 1
Link to comment
Share on other sites

default{    state_entry() {        llSetTimerEvent(0.2);    }    timer() { llRequestPermissions(llGetOwner(),PERMISSION_TRACK_CAMERA);      rotation a = llGetCameraRot()/llGetRootRotation();vector FWD = llRot2Fwd( a);vector UP = < .0, .0, 1.0 >;vector LEFT = llVecNorm( UP%FWD);float downLimit = (-80*DEG_TO_RAD);float upLimit = (80);//a = llAxes2Rot( LEFT%UP, LEFT, UP);//llSetLinkPrimitiveParamsFast( 2, [PRIM_ROT_LOCAL, a]); // turretif ( FWD.z > llCos( upLimit) ) FWD = llVecNorm( LEFT%UP + UP/llTan( upLimit));else if ( FWD.z < llCos( downLimit) ) FWD = llVecNorm( LEFT%UP + UP/llTan(downLimit));a = llAxes2Rot( FWD, LEFT, FWD%LEFT);llSetLinkPrimitiveParamsFast( LINK_THIS, [PRIM_ROT_LOCAL, a]); // gun    }}

This is the closest I could get it to work.

It causes however the cannon to snap only to high and low limit:

default{    state_entry() {        llSetTimerEvent(0.2);    }    timer() { llRequestPermissions(llGetOwner(),PERMISSION_TRACK_CAMERA);      rotation a = llGetCameraRot()/llGetRootRotation();vector FWD = llRot2Fwd( a);vector UP = < .0, .0, 1.0 >;vector LEFT = llVecNorm( UP%FWD);float downLimit = (-10);float upLimit = (80);//a = llAxes2Rot( LEFT%UP, LEFT, UP);//llSetLinkPrimitiveParamsFast( 2, [PRIM_ROT_LOCAL, a]); // turretif ( FWD.z > llCos( upLimit) ) FWD = llVecNorm( LEFT%UP + UP/llTan( upLimit));else if ( FWD.z < llCos( downLimit) ) FWD = llVecNorm( LEFT%UP + UP/llTan(downLimit));a = llAxes2Rot( FWD, LEFT, FWD%LEFT);llSetLinkPrimitiveParamsFast( LINK_THIS, [PRIM_ROT_LOCAL, a]); // gun    }}

setting it like this causes cannon to stop at desired high on top, but botom range still goes all way down. And snapping occurs on different hights.

I am currently trying to work out new way of making cannon geometry perfect, will share it in a moment once it is ready.

Link to comment
Share on other sites

You are a very careless scripter! Sorry to say.

  1. You can't request permissions like that and hope to get away with it. See llRequestPermissions() for how it is done
  2. The limit angles are measured from vertical up so upLimit < downLimit
    Furthermore 0 < upLimit < downLimit < π and all angles are measured in radians, not just some of them

A piece of advise: you can have one script in the root prim for all child prim manipulation. Putting small scripts in all child prims is an out of date approach we used when there were no alternative

 

Link to comment
Share on other sites

This is how I made the pivot perfectly fit with not much effort.

http://puu.sh/gRPvO.jpg build a box around object with different material group, so it overlaps main shape of object.

Manipulated vertexes + set pivot to center until satisfied, looking through where the pivot ends up. For such simple objects the SL seems to always hit with no miss. Used scale tool to get the sides equally covered.

Once put in game, set the pink face to transparent:

http://puu.sh/gRPQh.jpg

Link to comment
Share on other sites

rotation a = llGetCameraRot()/llGetRootRotation();vector FWD = llRot2Fwd( a);vector UP = < .0, .0, 1.0 >;vector LEFT = llVecNorm( UP%FWD);float downLimit = (100*DEG_TO_RAD);float upLimit = (80*DEG_TO_RAD);//a = llAxes2Rot( LEFT%UP, LEFT, UP);//llSetLinkPrimitiveParamsFast( 2, [PRIM_ROT_LOCAL, a]); // turretif ( FWD.z > llCos( upLimit) ) FWD = llVecNorm( LEFT%UP + UP/llTan( upLimit));else if ( FWD.z < llCos( downLimit) ) FWD = llVecNorm( LEFT%UP + UP/llTan(downLimit));a = llAxes2Rot( FWD, LEFT, FWD%LEFT);llSetLinkPrimitiveParamsFast( LINK_THIS, [PRIM_ROT_LOCAL, a]); // gun

Thank you, this works perfectly now.

 

EDIT:

Thank you for the 1 prim use advice. But the problem I encountered there is that link changes whenever I detach / attach things to tank, causing chaos in all scripts (example can be track script I wrote, that made textures wreck in whole model, but cannot be used normally, as depends on acceleration / velocity perms. Also some links are moved instead of others, I don't know why. Example is script

    integer righttrack = 18;llSetLinkTextureAnim(righttrack, ANIM_ON | SMOOTH | LOOP, ALL_SIDES,0,0,0.0, 1,2);

This causes link 4(!) to move, even that link 18 is indeed a track.

Little vid of script working:

Would you like a copy of that tank once I finish?

Link to comment
Share on other sites


darkstylerz wrote:

[ .... ] But the problem I encountered there is that link changes whenever I detach / attach things to tank, causing chaos in all scripts (example can be track script I wrote, that made textures wreck in whole model, but cannot be used normally, as depends on acceleration / velocity perms. Also some links are moved instead of others, I don't know why. Example is script
    integer righttrack = 18;llSetLinkTextureAnim(righttrack, ANIM_ON | SMOOTH | LOOP, ALL_SIDES,0,0,0.0, 1,2);

This causes link 4(!) to move, even that link 18 is indeed a track.
[ .... ]


Well, at least that problem is easy to solve.  Don't use hard-coded link numbers if you ever anticipate changing links.  Instead, name all child prims and them refer to links by name.  You can either build a list when the script starts up:

 

integer linknum;while (linknum < llGetNumberOfPrims()){    ++linknum;    if (llGetLinkName(linknum) == "turret")    {        giTurret = i;    }    // and so forth}

or do it as you need the link number in the script

 

if (llGetLinkName(llDetectedLinkNumber(0)) == "Turret"){    // Do something}

 

  • Like 2
Link to comment
Share on other sites

  • 2 years later...
You are about to reply to a thread that has been inactive for 2553 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...