Jump to content
Emilee Edenflower

Moving/zooming/focusing a camera to another avatar

Recommended Posts

Hi all! Ok so I'm trying to figure this out and have been going in circles for ages now, searching all of the forums and the interwebs to no avail.

Basic outline of my script: I scan a region, detect an avatar, grab their UUID and use that to get their details and location.

Then I want to use that info to move MY camera to the detected avi so I can see where they are (possibly even track them if they move would be the better outcome of this).

But this script I've made so far does all of that, gets the correct vector location (I also use llMapDestination to open the map to show me the detected avi, and the coordinates are right), but when the camera tries to find them, it just moves backwards from my av and then kinda springs back and gets stuck in a weird position and I can't reset it to default without removing the item from with the the script in it.

Camera scripting is new to me so I'm not too sure what is going wrong. Any help would be grand! :) 

PS, I know the list building a vector thing looks weird (and maybe pointless) considering i get the same result from targetPos variable. I just did that to make sure it was all returning the same thing.

 

//data = an avatars UUID within the same region as myself 
//detectedKey = owners UUID

/* --- SNIP [other code here etc] --- */

list detPos = llGetObjectDetails(data, ([OBJECT_NAME, OBJECT_DESC,
                            OBJECT_POS, OBJECT_ROT, OBJECT_VELOCITY,
                            OBJECT_OWNER, OBJECT_GROUP, OBJECT_CREATOR]));
                            
            vector currentPos = llGetPos();
            vector lookAt = ZERO_VECTOR;
            list getDistance = [llRound(llVecDist(currentPos,
                            llList2Vector(llGetObjectDetails(data, [OBJECT_POS]), 0))),data];
            targetPos = llList2Vector(detPos, 2);
            targetRot = llList2Vector(detPos, 3);

llRequestPermissions(detectedKey, PERMISSION_CONTROL_CAMERA);

run_time_permissions(integer perm)
    {
        if ( perm & PERMISSION_CONTROL_CAMERA )
        {
            vector lookAtPos = llGetPos() + (targetPos * llGetRot());
            
            string x;
            string y;
            string z;
            list xyz = llCSV2List((string)targetPos);
            string xvector = llList2String(xyz,0);
                x = llGetSubString(xvector,1,3);
                y = llGetSubString(xvector,12,14);
                z = llGetSubString(xvector,22,24);
                integer x_fin = llFloor((integer)x);
                integer y_fin = llFloor((integer)y);
                integer z_fin = llFloor((integer)z);
                vector newVec = <x_fin,y_fin,z_fin>;
            
            llClearCameraParams(); // reset camera to default
            llSetCameraParams([
                CAMERA_ACTIVE, TRUE, // (TRUE or FALSE)
                CAMERA_FOCUS, newVec, // region relative position
                CAMERA_FOCUS_LOCKED, FALSE, // (TRUE or FALSE)
                CAMERA_POSITION, lookAtPos, // region relative position
                CAMERA_POSITION_LOCKED, FALSE // (TRUE or FALSE)
            ]);
        }
    }

 

Share this post


Link to post
Share on other sites

See if this gets you any closer:


            llSetCameraParams([
                CAMERA_ACTIVE, TRUE,
                CAMERA_FOCUS, targetPos,
                CAMERA_FOCUS_LOCKED, TRUE,
                CAMERA_POSITION, targetPos + llVecNorm(llGetPos()-targetPos),
                CAMERA_POSITION_LOCKED, TRUE
                ]);

 

Share this post


Link to post
Share on other sites

To get those params to follow a moving target, you'd have to keep updating targetPos in real time, but that ought to work.  You may need to llClearCameraParams first.

Share this post


Link to post
Share on other sites

Just had a breakthrough :) When adding in the other camera parameters I found elsewhere, it works! The only small issue now is that it focuses on the persons hips, rather than higher up, but it's a start! Maybe something to do with the offset? or the Z positioning of the targetPos vector?

llSetCameraParams([
                CAMERA_ACTIVE, 1 //1 is active, 0 is inactive
                ,CAMERA_BEHINDNESS_ANGLE, 0.0 //(0 to 180) degrees
              //,CAMERA_BEHINDNESS_LAG, 0.05 //(0 to 3) seconds
                ,CAMERA_DISTANCE, 0.0 //(0.5 to 10) meters
                ,CAMERA_FOCUS, targetPos //Region-relative
                ,CAMERA_FOCUS_LAG, 0.05 //(0 to 3) seconds
                ,CAMERA_FOCUS_LOCKED, TRUE //(TRUE or FALSE)
                ,CAMERA_FOCUS_THRESHOLD, 0.0 //(0 to 4) meters
                ,CAMERA_POSITION, targetPos + llVecNorm(llGetPos()-targetPos) //Region-relative position
                ,CAMERA_POSITION_LAG, 0.05 //(0 to 3) seconds
                ,CAMERA_POSITION_LOCKED, TRUE //(TRUE or FALSE)
                ,CAMERA_POSITION_THRESHOLD, 0.0 //(0 to 4) meters
                ,CAMERA_FOCUS_OFFSET, ZERO_VECTOR //<-10,-10,-10> to <10,10,10> meters
            ]);

 

Share this post


Link to post
Share on other sites

Did you llClearCameraParams first?  Sometimes that helps.  It's like typing ESC to clear the camera focus before you look at something new.  As for the target position .... You are kind to refer to it as your target's "hips."  More accurately, the default camera target when you are aimed at a person is the crotch.  You should be able to add an arbitrary Z offset to beat that one.

Share this post


Link to post
Share on other sites

I have a feeling we're going to need to see the rest of the script. Are you sure you're always assigning the desired avatar's position to targetPos, or could something else be getting in there?

As for the Z positioning, yeah, maybe just add <0,0,1> to the position as a starting point... but also you may want to pull back a little further than the 1 meter supplied by the llVecNorm() that I suggested.

That suggestion was intended to preserve an orientation of the cam from the direction of your own avatar (but much closer to the target). I thought that direction would be most intuitive, but wherever the cam is positioned there's always a risk of plopping it directly behind a wall or something else separating it from the target.

Share this post


Link to post
Share on other sites

I've had the script llSay the coordinates at various points to make sure it's always the same, which it is. Although one may round up the decimal places but that shouldn't interfere much at all. 

Before this part of the script in just looking up an avatar UUID by username and passing that to the part quoted in the OP. So it all appears to be consistent

Share this post


Link to post
Share on other sites

Sorry I can't get in-world to try to replicate the problem -- kind of grasping at straws here: any chance there's more than one script operating on your cam at the same time?

Share this post


Link to post
Share on other sites

Without knowing what your physical setup is, it's hard to do much more debugging.  However, you might consider whether either of these notes from the Caveats in the LSL wiki apply to your situation:

  • The PERMISSION_CONTROL_CAMERA permission is automatically revoked when the avatar stands up from or detaches the object, and any scripted camera parameters are automatically cleared.
  • Camera control currently (server 1.38) only supported for attachments and objects on which you are sitting. An attempt otherwise will result in an error being shouted on DEBUG_CHANNEL.

Share this post


Link to post
Share on other sites

Using CAMERA_FOCUS_OFFSET, <0.0, 0.0, 0.5> (ish) will get your camera pointing at the target's boobs.

Share this post


Link to post
Share on other sites
8 hours ago, Rolig Loon said:

Without knowing what your physical setup is, it's hard to do much more debugging.  However, you might consider whether either of these notes from the Caveats in the LSL wiki apply to your situation:

  • The PERMISSION_CONTROL_CAMERA permission is automatically revoked when the avatar stands up from or detaches the object, and any scripted camera parameters are automatically cleared.
  • Camera control currently (server 1.38) only supported for attachments and objects on which you are sitting. An attempt otherwise will result in an error being shouted on DEBUG_CHANNEL.

I'm wearing the item so the permissions should be fine. Though I only got the permission prompt dialog once and never again, despite detaching the item and updating the script. Is that normal?

Share this post


Link to post
Share on other sites

I retested this on other sims completely naked to make sure I had no attachments etc interfering, but I still have the same weird issue with the camera. So I'm not really sure what to do now.

Share this post


Link to post
Share on other sites
4 hours ago, Emilee Edenflower said:

Though I only got the permission prompt dialog once and never again, despite detaching the item and updating the script. Is that normal?

Permissions remain a bag of mysteries to me, even after all these years. Still, PERMISSION_CONTROL_CAMERA is supposed to be granted silently.  I'm surprised that you ever got a permission dialog box, unless you were requesting other permissions at the same time that were not silent ones.

At least for now, I'm out of ideas.

Share this post


Link to post
Share on other sites

I don't know how to help other than to just toss out a simple script that seems to work for me.  This is far from a finished product, but just something to get us moving forward, maybe:

key trackedAV = NULL_KEY;

default
{
    state_entry()
    {
        llRequestPermissions(llGetOwner(), PERMISSION_CONTROL_CAMERA);
    }
    attach(key av)
    {
        if (NULL_KEY != av)
            llResetScript();
    }
    run_time_permissions(integer perms)
    {
        if (PERMISSION_CONTROL_CAMERA & perms)
            llSetTimerEvent(0.1);   // just to start
    }
    timer()
    {
        vector avSize = llGetAgentSize(trackedAV);
        if (ZERO_VECTOR == llGetAgentSize(trackedAV))
        {
            llClearCameraParams();
            trackedAV = NULL_KEY;
            list regionAVs = llGetAgentList(AGENT_LIST_REGION, []);
            integer avIdx = llGetListLength(regionAVs);
            while ((0 <= --avIdx) && (NULL_KEY == trackedAV))
            {
                key testAV = llList2Key(regionAVs, avIdx);
                if (llGetOwner() != testAV)
                    trackedAV = testAV;
            }
            if (NULL_KEY == trackedAV)
            {
                llOwnerSay("No other agents in region");
                llSetTimerEvent(15.0);  // suspend a while before resampling region
                return;
            }
            llSetTimerEvent(1.0);   // actual tracking frequency
            avSize = llGetAgentSize(trackedAV);
        }
        list avData = llGetObjectDetails(trackedAV, [OBJECT_POS, OBJECT_NAME]);
        vector targetPos = llList2Vector(avData, 0) + <0.0, 0.0, avSize.z*0.4>;
        // llOwnerSay("tracking "+llList2String(avData, 1)+" at position "+(string)targetPos);
        llSetCameraParams([
                CAMERA_ACTIVE, TRUE,
                CAMERA_FOCUS, targetPos,
                CAMERA_FOCUS_LOCKED, TRUE,
                CAMERA_POSITION, targetPos + llVecNorm(llGetPos()-targetPos),
                CAMERA_POSITION_LOCKED, TRUE
                ]);
    }
}

 

Share this post


Link to post
Share on other sites

There are a few camera control reform feature requests out there. One would allow scripted camera focus on an agent or object with local offset. This would allow smooth tracking without having to constantly clear and reapply camera params which is the only way you can currently track someone other than your own avatar. Sadly it results in choppy motion.

Share this post


Link to post
Share on other sites
16 hours ago, Qie Niangao said:

I don't know how to help other than to just toss out a simple script that seems to work for me.  This is far from a finished product, but just something to get us moving forward, maybe

Thanks, I'll give it a try and see how it works :)

Share this post


Link to post
Share on other sites
Posted (edited)

here is my 2 cents... as close as i could get with as little jumpyness as possible for a moving target...

( TRG is set for a test prim of mine, change that for your tests)

 

// MOD of Follow Camera by Ariane Brodie
// MODED by Xiija


key owner;
integer permissions;
vector target;
string trgName;
key  TRG; 
vector TRG_pos;
rotation TRG_rot;
vector myVec;
integer k = 1;

cammit()
{  
     llSetCameraParams([
        CAMERA_ACTIVE, 1,   // 1 is active, 0 is inactive---TRUE FALSE ?
        CAMERA_FOCUS,TRG_pos,               
        CAMERA_BEHINDNESS_ANGLE, 90.0, // (0 to 180) degrees...df 2.0
        CAMERA_BEHINDNESS_LAG, 3.0, // (0 to 3) seconds ......df 0.2
        CAMERA_DISTANCE, 5.0, // ( 0.5 to 10) meters       
        CAMERA_FOCUS_LAG, 3.0 , // (0 to 3) seconds
        CAMERA_FOCUS_LOCKED, FALSE, // (TRUE or FALSE)
        CAMERA_FOCUS_THRESHOLD, 4.0, // (0 to 4) meters
        CAMERA_PITCH, 80.0, // (-45 to 80) degrees       
        CAMERA_POSITION, TRG_pos + <-3.5,0.0,2.0>, // region relative position
        CAMERA_POSITION_LAG, 3.0, // (0 to 3) seconds
        CAMERA_POSITION_LOCKED,FALSE, // (TRUE or FALSE)
        CAMERA_POSITION_THRESHOLD, 4.0, // (0 to 4) meters
        CAMERA_FOCUS_OFFSET, <-4.0,0,0> // <-10,-10,-10> to <10,10,10> meters
    ]);
}
default
{
    state_entry()
    {   owner=llGetOwner();
        myVec = llGetPos();
        TRG = "25bd1856-b55e-0c5a-8783-f4b4b94eeb0b";       
        llRequestPermissions(llGetOwner(), PERMISSION_CONTROL_CAMERA);        
    }
    run_time_permissions(integer perm)
    {
        permissions = perm;
        if (PERMISSION_CONTROL_CAMERA)
         {   llClearCameraParams(); 
             llReleaseCamera(owner);
             llSetCameraParams([CAMERA_ACTIVE, 0]);
             llSetCameraParams([CAMERA_ACTIVE, TRUE]);
             llOwnerSay("Tracking TRG: " );
             llSetTimerEvent(0.02);
        }
    }
    touch_start(integer total_number)
    {   if( k = !k)
        {   llOwnerSay("Tracking TRG: " );
            llSetTimerEvent(0.02);
        }  
        else
        {    llClearCameraParams(); 
             llReleaseCamera(owner);
             llSetCameraParams([CAMERA_ACTIVE, 0]);
             llSetTimerEvent(0.0);
             llOwnerSay("OFF");
        }
    }    
    timer()
    {    list details = llGetObjectDetails( TRG, ([ OBJECT_POS, OBJECT_ROT ]) );
         TRG_pos = llList2Vector( details,0);    
         TRG_rot =  llList2Rot( details,1);
         cammit();
    } 
}

 

Edited by Xiija

Share this post


Link to post
Share on other sites
On 11/08/2018 at 10:02 PM, Qie Niangao said:

I don't know how to help other than to just toss out a simple script that seems to work for me.  This is far from a finished product, but just something to get us moving forward, maybe:


key trackedAV = NULL_KEY;

default
{

So far this script has been the one that has worked (mostly). It seems to freak out if the target is quite far away -- are there distance limits to the camera being moved by a script?

Share this post


Link to post
Share on other sites
16 minutes ago, Emilee Edenflower said:

So far this script has been the one that has worked (mostly). It seems to freak out if the target is quite far away -- are there distance limits to the camera being moved by a script?

I never encountered any problems with camera scripts.

But the viewer can set limits for the camera movement and a script will not change that limits.

And of course you can override any settings by moving the camera manually. If you did - you need to press <esc> before the script tries to move your camera.

Share this post


Link to post
Share on other sites

OK so after putting the camera script here into my own script, then it goes weird, so it's possibly something I'm doing interfering. 

This is what I've been trying to give some proper context -- you type an avi username on the listening channel to look them up in the region, then have the camera move to see them (once working, I'd make that an option via a dialog button):

integer listenHandle;
key name_key_query;
string region;
key    detectedKey;
vector agent;
vector targetPos;
vector targetRot;
integer uniqChannel;

touch_start(integer num_detected)
    {
        
        detectedKey   = llDetectedKey(0);
        string name = llGetDisplayName(detectedKey);
        //Create unique channel for avi
        //uniqChannel = (integer)("0xF" + llGetSubString(llGetOwner(),0,4));
        uniqChannel = (integer)(llFrand (99.0) + 1.0);
     
        listenHandle = llListen(uniqChannel, "", detectedKey, "");
     
        llOwnerSay("Type the USERNAME (not display name) of the person you want to track down.");
        llOwnerSay("Listening now to '" + name + "' on channel " + (string)uniqChannel);
        

        
    //    llOwnerSay((string)owner);
    
   
        }
 
    listen(integer channel, string name, key id, string message)
    {
        if (channel == uniqChannel){
            llOwnerSay("Searching for target...");
            llOwnerSay("Searching for... " + message);
            name_key_query = llRequestUserKey(message);
            }

 
        remove_listen_handles();
    }
    
    dataserver(key queryid, string data) 
   {
       if ( name_key_query == queryid )
       {
            //llSay(0, "The key for this user is : " + data);
            region = llGetRegionName();
            string username = llGetDisplayName(data);
            agent = llGetAgentSize(data);
            //list detPos = llGetObjectDetails(data, ([OBJECT_NAME, OBJECT_DESC, OBJECT_POS, OBJECT_ROT, OBJECT_VELOCITY, OBJECT_OWNER, OBJECT_GROUP, OBJECT_CREATOR]));
			list detPos = llGetObjectDetails(data, [OBJECT_POS, OBJECT_NAME]);
			
                            
            vector currentPos = llGetPos();
            vector lookAt = ZERO_VECTOR;
            list getDistance = [llRound(llVecDist(currentPos,
                            llList2Vector(llGetObjectDetails(data, [OBJECT_POS]), 0))),data];
            //targetPos = llList2Vector(detPos, 2);
            //targetRot = llList2Vector(detPos, 3); 
			
			targetPos = llList2Vector(detPos, 0) + <0.0, 0.0, agent.z*0.4>;
           
          
          if(agent) {
            //uuid is an avatar in the region
            llOwnerSay("Target found!");
            llOwnerSay(username + " is in the region: " + region + " and is " + (string) llList2Integer(getDistance, 0) + "m away from you.");

            //Open map to add pointer to the target
            llMapDestination(region, targetPos, lookAt);

            //llOwnerSay("Do you want to see your target?");
            //llRequestPermissions(detectedKey, PERMISSION_CONTROL_CAMERA);
        

            } else {
                llOwnerSay("Target is not within " + region);
            //uuid is not an avatar in the region
            }
    
            if (llGetAgentSize (data) == ZERO_VECTOR)
            {
                // person_of_interest is no longer in the region, so kill the script or whatever
            }
       }
   }
   
    
   run_time_permissions(integer perm)
    {
        if ( perm & PERMISSION_CONTROL_CAMERA )
        {
		
        llOwnerSay("tracking "+llList2String(detPos, 1)+" at position "+(string)targetPos);
        llSetCameraParams([
                CAMERA_ACTIVE, TRUE,
                CAMERA_FOCUS, targetPos,
                CAMERA_FOCUS_LOCKED, FALSE,
                CAMERA_POSITION, targetPos + llVecNorm(llGetPos()-targetPos),
                CAMERA_POSITION_LOCKED, FALSE
                ]);
		
        } else {
            llClearCameraParams();
        }
    }

 

Share this post


Link to post
Share on other sites

I assume that the llRequestPermissions line has only temporarily been commented out.  When you actually get the camera issues sorted out, I assume that you will also use a llTextBox for input instead of gathering user input in chat. Those details aside, I would expect your script to work as is. 

 

Share this post


Link to post
Share on other sites
17 minutes ago, Rolig Loon said:

I assume that the llRequestPermissions line has only temporarily been commented out.

oh yes! Forgot to fix that before pasting it here. I was just trying to debug things earlier. Is llTextBox better than a listener channel?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×