Jump to content

Multi-prim animator (very smooth)


Nikkesa
 Share

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

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

Recommended Posts

So, this script is the base proof-of-concept for a linkset-based animation system.

It precaches rotations and positions of a linkset, (the only limit being memory)...

An idea is to have it print off the calculations for the user to save into a text-file, or to send to a server which generates a notecard or something for you to drag into a script... The object could have multiple scripts to load different sections of the animation, but it would be more work, and I'm more about the how than the do anyways...

This script is mainly written for a tail, so if you already have a tail segment done, play around with it and you'll have something smooth and animated you can wear ^_^

You are free to do whatever you want with this script; sell it, mod it, use it anything.

integer timer_on = 0;

list newPositions; //the list of positions to apply to the segments
list newRotations; //the list of rotations to apply to the segments

float curve_location_x = 360; //the position we are on the curve... 

float distance_between_segments = 0.1; //the distance between each segment

vector segment_size = <0.01,0.1,0.1>;
//let's start setting this **bleep**...
//Note: may want to incorporate support for different types of segments, such as if we had 3 different cones per segment...

integer number_of_segments;

list command_list;

integer i;

float counter = 0;
//setup
vector position_offset;
//part 1
float myAngle1; //the new angle thingy... used later
//part 3
rotation rotation_between; //the rotation between two segments...
vector childPos1;
vector childPos2;
vector newValue;

////////////////////////////

list position_cache;
list rotation_cache;

integer toggle_building_setting = 0;

///////////////////////////

vector childPos(integer segment_id){
    return llList2Vector( llGetLinkPrimitiveParams(segment_id, [PRIM_POSITION] ), 0 );
}

rotation childRot(integer segment_id){
    return llList2Rot(llGetLinkPrimitiveParams(segment_id, [PRIM_ROT_LOCAL]), 0);
}

vector childPosLocal(integer segment_id){
    return llList2Vector(llGetLinkPrimitiveParams(segment_id,[PRIM_POSITION]), 0) - llGetPos();
}

vector buildPositionOffset(rotation rotation_amount, vector current_position, vector axis_position, rotation base_rotation){
    //builds the position offset relative to the rotation_amount relative to the base_rotation (which should be the root prims rotation)
    return ((axis_position - current_position) - ((axis_position - current_position) * rotation_amount)) * base_rotation;
    //this will return the amount we have to move :D
}

list fix_position_offsets(list myList, float limit_distance){
    //in here we want to basically scale the distance between segments so that it's always the same...
    list newList = myList;
    integer j=1;
    vector segmentPos1;
    vector segmentPos2;
    vector vector_between;
    float distance_between;
    
    for (;j < llGetListLength(myList);j++){
        segmentPos2 = llList2Vector(newList, j);
        segmentPos1 = llList2Vector(newList, j-1);
        vector_between = segmentPos2 - segmentPos1;
        distance_between = llVecMag(vector_between); //get the distance between the segments...
        if (distance_between != limit_distance) {
            //here we scale the distance between the segments
            vector_between = vector_between * (limit_distance / distance_between); //I suspect this is where the math error is coming from.
            //and apply it to the list.
            newList = llListReplaceList(newList, [segmentPos1 + vector_between], j, j);
        }
    }
    return newList;
}

//for a rotation: 
//[((childPos(segment_id) -  llGetPos()) / llGetLocalRot()) + (buildPositionOffset(llEuler2Rot(llRot2Euler(rotation_amount)*segment_id/10), childPos(segment_id), llGetPos() ) * childRot(segment_id))];
//offset_rotaton = llAtan2(llSin(new_curve_mod), new_curve_mod)

integer sign(float input){
    if (input > 0) return 1;
    if (input < 0) return -1;
    return 0;
}

/*
    OKAY, NEW PLAN 
    --------------
    We are going to pre-cache all of the positions and rotations for the animation sequence,
    and apply them over the animation sequence!
    so yeah, whatever. 
    
*/

default
{
    state_entry()
    {
        integer i = 2;
        for (;i<=llGetNumberOfPrims();i++){
            llSetLinkPrimitiveParamsFast(i,[PRIM_POS_LOCAL,<(float)(i-1) * distance_between_segments,0.0,0.0>,PRIM_ROT_LOCAL,ZERO_ROTATION, PRIM_SIZE, segment_size * i/(i+1)]);
        }
        number_of_segments = llGetNumberOfPrims() - 1;
        
        //we want to ignore any avatars,especially in case of attachment and such...
        if (number_of_segments > 1){
            while (llGetAgentSize(llGetLinkKey(number_of_segments))){
                --number_of_segments;
            }
        }
    }
    
    touch_start(integer total_number)
    {
        if (llDetectedKey(0) == llGetOwner()){
            if (timer_on == 0){
                timer_on = 1;
                llSetTimerEvent(0.04);
            } else {
                timer_on = 0;
                llSetTimerEvent(0.0);
                llResetScript();
            }
        }
        
        // let us start the building of the cache.
    }
    
    timer(){
        i = 0;
        counter++;
        
        if (toggle_building_setting == 0)
        {
            curve_location_x = curve_location_x - 12;
            if (curve_location_x <= -1) {
                curve_location_x = 360;
                llOwnerSay("Done Caching... " + (string)counter);
                counter = 0;
                toggle_building_setting = 1;
            }
            command_list = [];
            newPositions = [];
            newRotations = [];
            for (;i < number_of_segments;i++){
                
                //part 1 - set up the new positions for each segment.
                //use i+2
                
                myAngle1 = llSin(( (float)(i+2) * (PI/2 / number_of_segments) )+( curve_location_x*TWO_PI/360 )) * 0.5;
                newValue = (llGetPos() - childPos(i+2));
                //llOwnerSay((string)myAngle1);
                //newPositions += [<(float)(i+2)/(1 / distance_between_segments*0.9),0.0,0.0> + <0.0,llVecMag(newValue) * llSin(myAngle1),0.0>];
                
                newPositions += [<(float)(i+2)/(1 / distance_between_segments),0.0,0.0> + ((newValue) - (newValue * llEuler2Rot( <0.0,0.0,myAngle1> ))) + <0.0,0.0,(llCos((TWO_PI * 3/4) * ((float)1 / (float)26) * (float)i) - 1)/2>];
                
                //newPositions += [<(float)(i+2)/(distance_between_segments),0.0,0.0> + buildPositionOffset(llEuler2Rot( <0.0,myAngle1,myAngle1> ),childPos(i+2), llGetPos(),llGetRot())];
                //newPositions += [<(1/distance_between_segments)*(curve_location_x/360)*i,0.0,0.0>];
                
                //part 3 - set the rotations of the tail segments
                /*
                
                */
                
                //part 4 - build the command list for our setlinkprimparamsfast function
                
                //
                
            }
            newPositions = fix_position_offsets(newPositions, distance_between_segments);
            i = 0;
            for (;i<number_of_segments;i++){
                
                command_list += [PRIM_POS_LOCAL,llList2Vector(newPositions,i),PRIM_LINK_TARGET, i + 3];
                command_list += [PRIM_ROT_LOCAL,llList2Rot(newRotations,i),PRIM_LINK_TARGET, i + 3];
            }
            position_cache += newPositions;
            //rotation_cache += newRotations;
            //apply the new positions
            llSetLinkPrimitiveParamsFast(2, command_list);
            i = 0;
            for (;i<number_of_segments;i++){
                //newValue = (llGetPos() - childPos(i+2));
                childPos2 = childPos(i+2);
                childPos1 = childPos(i+1);
                // get the rotation between the segments...
                rotation_between = llRotBetween(<llVecMag(childPos2 - childPos1),0.0,0.0>, childPos2 - childPos1);
                newRotations += [rotation_between];
            }
            rotation_cache += newRotations;
            
        } else {
            if (counter == 30){
                counter = 0;
            }
            i = 0;
            command_list = [];
            for (;i<number_of_segments;i++){
                
                command_list += [PRIM_POS_LOCAL,llList2Vector(position_cache,(integer)counter * 26 + i), PRIM_ROT_LOCAL,llList2Rot(rotation_cache,(integer)counter * 26 + i),PRIM_LINK_TARGET, i + 3];
            }
           llSetLinkPrimitiveParamsFast(2, command_list);
        }
    }
}

 

  • Like 3
Link to comment
Share on other sites

  • 1 year later...

Thank you so much for helping out, Im trying to make an animated mesh dragon tail using segments but i didnt knwo the logic behind the scripting, Im very new to segmented animations. I could make a hard animated mesh tail using several keyframes but lets face it, they suck, lag alot, and have almost no kind of flexibility in changing variables.

 

Please keep up the work man, Im still trying to understand ahow this works to make a nice segemented tail with slider options! Please post more bro plz plz plz!

Link to comment
Share on other sites

  • 1 year later...
You are about to reply to a thread that has been inactive for 2993 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...