Jump to content

Is there a more precise way to reset the scale of a linked object than this?


w1zard
 Share

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

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

Recommended Posts

Is there a more precise way to reset the scale of a linked object than this?

I have this script inside every prim in the linked object.

 

default {
    link_message(integer sender_num, integer num, string str, key id) {
        float scale; // size factor
        list    primparams;
        
        scale = (float)str;
        
        primparams = [];
        
        primparams += [PRIM_SIZE, llGetScale() * scale]; // resize
        
        if (llGetLinkNumber() > 1) { // only move if we're not the root object
            primparams += [PRIM_POSITION, llGetLocalPos() * scale]; // reposition
        }
        
        llSetPrimitiveParams(primparams);
    }
}

 and this is the master script which will try to reset the scale

 

// rescales the linked set by the specified factor. factor > 1 makes it larger, < 1 smaller
// example: "/9 2.5"
Resize(float scale) {
    integer num_prims = llGetNumberOfPrims();
    integer i;

    for (i = 1; i <= num_prims; i++) { // first prim in a linked set is 1
        llMessageLinked(i, 0, (string)scale, NULL_KEY);
    }
    
}

integer a = 0;

vector DEFAULT_MAINPRIM_SCALE = <0.30032,0.30032,0.83893>;

reset2DefaultScale()
{
    vector currentScale = llGetScale();
    if(currentScale!=DEFAULT_MAINPRIM_SCALE) //is not the original size as first recorded
    {
        llOwnerSay("Current Scale Differs from default by the following:");
        //get percentage difference between all 3 values and average them for the scale which should be the original scale
        float xScale = (1.0/DEFAULT_MAINPRIM_SCALE.x) * currentScale.x;
        float yScale = (1.0/DEFAULT_MAINPRIM_SCALE.y) * currentScale.y;
        float zScale = (1.0/DEFAULT_MAINPRIM_SCALE.z) * currentScale.z;
        float averageScale = (xScale+yScale+zScale)/3;
        llOwnerSay("<"+(string)xScale+","+(string)yScale+","+(string)zScale+"> average scale of: "+(string)averageScale);
        //Work out the original scale difference
        float difference = 0.0;
        if(averageScale>1.01)
        {
            difference = 1.0/averageScale;
            Resize(difference);
            llOwnerSay("New Calculation: 1.0/"+(string)(averageScale));
        }
        else if(averageScale<0.99)
        {
            difference = averageScale*10.0;
            Resize(difference);
            llOwnerSay("New Calculation: 1.0*"+(string)(averageScale));
        }
        llOwnerSay("Difference to reach original scale: "+(string)difference);
    }
    else
        llOwnerSay("Current Scale matches Default SCale");
}

default {
    state_entry() {
        reset2DefaultScale();
        llListen(9, "", llGetOwner(), "");
        //llSetTimerEvent(5.0);
        
        float pauseInSeconds = 2.0;
        
        while(1==1)
        {
        
            llSleep(pauseInSeconds);
            Resize(1.25);                       // L
            
            llSleep(pauseInSeconds);
            reset2DefaultScale();
            Resize(1.5);                        // XL
            
            llSleep(pauseInSeconds);
            reset2DefaultScale();
            Resize(1.25);                       // L
            
            llSleep(pauseInSeconds);
            reset2DefaultScale();               // M
    
            llSleep(pauseInSeconds);
            reset2DefaultScale();
            Resize(0.75);                       // S
            
            llSleep(pauseInSeconds);
            reset2DefaultScale();
            Resize(0.5);                        // XS
            
            llSleep(pauseInSeconds);
            reset2DefaultScale();
            Resize(0.75);                       // S

            llSleep(pauseInSeconds);
            reset2DefaultScale();               // M
                        
        }
    }
    
    listen(integer channel, string name, key id, string message) {
        float scale;
        
        scale = (float)message;
        if ( scale == 0.0 ) return; // we don't resize by factor 0.0

        llSay(0, "Resizing by factor " + (string)scale);

        Resize(scale);
        llSay(0,(string)llGetScale());
    }
    
    timer()
    {
        if(a==0)
        {
            a=1;
            Resize(0.5);
        }
        else if(a==1)
        {
            a=0;
            Resize(2.0);
        }
    }
}

 The problem I have is, I cannot get it to return to the exact original size, which means over time, its possible that the size changes (larger or smaller) this is because I am having problems calculating the resize float pecisley i.e 1.0 = original, 2.0 = double size, 0.5 = half, 

Firstly there is a problem resetting the object to its original size when it's scale is less than the original scale (DEFAULT_MAINPRIM_SCALE) so I guess ignore that problem as its just something I need to fix, unless anyone can shed some light on that too!

It works fine if you make the object bigger, then reset the script and it will go back to the original size.

Link to comment
Share on other sites

Ok here is the refactored code. What am I doing wrong here?

 

//Master Resize Scriptlist defaultPrimParams = [];default{    state_entry()    {        llOwnerSay("My current params are is: ");        //for each prim        integer primCount = llGetNumberOfPrims();        integer currentPrim = llGetLinkNumber();        integer p = 0;        string output="list defaultPrimParams = [";                for(;p<primCount+1;p++)        {            output+="\"";                        output+=(string)p+"|"; //primID            output+=(string)llList2Vector(llGetLinkPrimitiveParams(p,[PRIM_SIZE]),0)+"|"; //Scale            output+=(string)(llGetPos()-llList2Vector(llGetLinkPrimitiveParams(p,[PRIM_POSITION]),0));//Position Distance from currentPrim                        output+="\"";            if(p!=primCount)                output+=",";        }        output+="];";        llOwnerSay(output);    }    touch_start(integer total_number)    {        //Resets to default size        integer prims = llGetListLength(defaultPrimParams);        integer p = 0;        for(;p<prims+1;p++)        {            string paramsString = llList2String(defaultPrimParams,p);            list paramsList = llParseString2List(paramsString,["|"],[]);            integer primID = llList2Integer(paramsList,0);            vector primScale = llList2Vector(paramsList,1);            vector primPositionDistance = llList2Vector(paramsList,2);                        llSetLinkPrimitiveParamsFast(primID,[PRIM_SIZE,primScale]);            llSetLinkPrimitiveParamsFast(primID,[PRIM_POSITION,llGetPos()+primPositionDistance]);        }    }}

 

+ 1 Kudos to the Guru that knows their $%*7

Link to comment
Share on other sites

thats not the problem, I am only using 5 prims to test the script and the output is fairly small.

 

Build 5 cubes (Into an X pattern), link them, drop the script in. 

When the script is placed inside and it will give you the default position array.

Edit the script with the lsl code that was output, save it, then resize the object and when you click it its supposed to go back to its original scale (the root position wont change).

 

The problem is that it doesnt change the positions, and the scale of each prim is set to the minimum value.

 

I think that I might be providing the wrong primID's to setprimitiveparams and also get primitiveparams.


Maybe someone could tell me how I can get all ID's for all the prims in the linked object. With that I could ensure that the right ID's are being used.

 

When the script starts it should say something like:

 

My current size is:
list defaultPrimParams = ["0|<0.00000, 0.00000, 0.00000>|<183.26640, 236.83130, 29.26685>","1|<0.50000, 0.50000, 0.50000>|<0.00000, 0.00000, 0.00000>","2|<0.50000, 0.50000, 0.50000>|<0.00000, 0.51840, 0.48844>","3|<0.50000, 0.50000, 0.50000>|<0.00000, 0.51840, -0.51371>","4|<0.50000, 0.50000, 0.50000>|<0.00000, -0.50829, -0.51371>","5|<0.50000, 0.50000, 0.50000>|<0.00000, -0.51425, 0.52073>"];

 

Which is what you can use to update the default param array at the top of the script

 

PrimID | Size | Local Position

 

As you may realise the values look odd, I think iv hit the nail on the head with the problem because  LINK_ROOT = 1;

 

I can get the amount of prims in the linked object, but where do their ID's start? at 2?

 

Would really appreachiate it if anyone finds the time to drop it into a basic object with more than 1 prim such as the one described above, only takes 10 seconds.

Link to comment
Share on other sites

Yes, it looks like the problem is your loops.  Link IDs start at 1 (for the root prim) and go up.  Start your loops at 1, not 0.

 

Also, you don't have to do all the funky string stuff (lists can be cast to strings directly):

...list primscale = [];list primpos = [];integer p = 1;  // This gets us to start our loop at LINK_ROOT, not at unlinked!integer numprims = llGetNumberOfPrims();for(; p <= numprims; ++p){    primscale += llList2Vector(llGetLinkPrimitiveParams(p,[PRIM_SIZE]),0);    primpos += llList2Vector(llGetLinkPrimitiveParams(p,[PRIM_POSITION]),0);}llOwnerSay("Output Positions = [" + (string)primpos + "]");llOwnerSay("Output Scales = [" + (string)primscale + "]");...

 Each element should be in order, so storing the link IDs isn't really necessary.  BUT, remember that the lists index at ZERO, not 1.  So llList2Vector(primscale,0) is the value for prim 1....not prim 0.

Now that you have stored the initial scales & positions (save the above lists to globals somewhere instead of local variables), to restore them somewhere, just do:

...integer p = 1;integer numprims = llGetNumberOfPrims();for(; p <= numprims; ++p){    llSetLinkPrimitiveParamsFast(p,[PRIM_SIZE, llList2Vector(primscale,p-1), PRIM_POSITION, llList2Vector(primpos,p-1)]);}...

 

 

If what you want is a script that when you click the object it goes back to it's initial position:

 

list prim_sizes = [];list prim_positions = [];integer numprims;default{    state_entry()    {        integer p;        numprims = llGetNumberOfPrims();        for(p=1; p <= numprims; ++p)        {            prim_sizes += llList2Vector(llGetLinkPrimitiveParams(p,[PRIM_SIZE]),0);            prim_positions += llList2Vector(llGetLinkPrimitiveParams(p,[PRIM_POSITION]),0);        }    }    touch_start(integer num_detected)    {        llOwnerSay("Touched!  Reverting to initial position and size!");        integer p;        for(p=1; p <= numprims; ++p)            llSetLinkPrimitiveParamsFast(p, [PRIM_SIZE, llList2Vector(prim_sizes,p-1), PRIM_POSITION, llList2Vector(prim_positions, p-1)]);    }}

 

Now, this stores the values at rez/startup.  From then on, whenever it is clicked on, it will revert the prims back to their original stored positions/sizes.

Note, whenever the script is reset, it will re-store the current scale/position values!

 

Link to comment
Share on other sites

Hi Helium,

Thanks for posting your script. When I put it in my test object, this is what I see:

1.png

1) Original Object on Left & Right.

2.png

2) I scale up the object on the Right.
3.png 

3) When I click the object on the right, it does not revert back to its original positions or scales as shown in image 1

Link to comment
Share on other sites

when saving sizes, you only need a single float for each independently sized object if you are scaling the whole object.

I usually use the x axis of the size of any prim in the set (the root's quickest)

then you can figure you percentage based on that number every time, and always get the correct result and there are no noticeable rounding errors.

this works because the relationship of axis sizes are linear for all axes.

simply take the current value divided by the original to give you the current percentage. there are multiple paths you can take from there, but at that point you have enough to modify it linearly so that a step up and a step down are the same amount. (for instance, divide one by the current percentage to reset to original)

  • Like 1
Link to comment
Share on other sites

There are already several resizer scripts in the LSL library

ETA: Response to below ...

I seem to have been exaggerating when I said 'several' - I see three in the forum.  In order of age:

Void Singer's Zen Resizer; http://community.secondlife.com/t5/LSL-Library/v7-D-Zen-Resizer-lite-Builders-Package/m-p/711557/message-uid/711557#U711557

Dora Gustafson's Basic Resizer; http://community.secondlife.com/t5/LSL-Library/Basic-Resizer/m-p/713675/message-uid/713675#U713675

Indeterminate Schism's Selectable-Axis Resizer; http://community.secondlife.com/t5/LSL-Library/Selectable-axis-Resizer/m-p/872705/message-uid/872705#U872705

...  however, we all applaud someone doing it for themselves :-)  Good luck

Link to comment
Share on other sites

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

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

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
 Share

×
×
  • Create New...