interpolation/Spline/Vectors

From Second Life Wiki
Jump to navigation Jump to search

Summary

Function: vector pSpline( list v, float t, integer Loop );

B-Spline Interpolation between four vector points in a list of vectors that define a path.
Returns a vector

• list v
• float t Ranges between [0, 1]
• integer Loop Whether the list is a curved line or loops into a closed shape.

Specification

<lsl>vector pSpline(list v, float t, integer Loop) {

   integer l = llGetListLength(v); t *= l-1;
   integer f = llFloor(t); t -= f;
   float t2 = t * t; float t3 = t2 * t;
   return (
     ( (-t3 + (3.*t2) - (3.*t) + 1.) * llList2Vector(v, pIndex(f-1,l,Loop)) )
   + ( ((3.*t3) - (6.*t2) + 4.) * llList2Vector(v, pIndex(f,l,Loop)) )
   + ( ((-3.*t3) + (3.*t2) + (3.*t) + 1.) * llList2Vector(v, pIndex(f+1,l,Loop)) )
   + ( t3 * llList2Vector(v, pIndex(f+2,l,Loop)) )
   ) / 6.0;

} integer pIndex( integer Index, integer Length, integer Loop) {

   if(Loop) return Index % Length;
   if(Index < 0) return 0;
   if(Index > --Length) return Length;
   return Index;

} // Released into public domain. By Nexii Malthus.</lsl>

Examples

<lsl> //Quick Dirty Example By To-mos Codewarrior (tomos.halsey) integer LINK_cube;integer LINK_1; integer LINK_2; integer LINK_3; integer LINK_4; integer LINK_5; integer LINK_6; integer LINK_7;

vector pos_1;vector pos_2; vector pos_3;vector pos_4; vector pos_5;vector pos_6; vector pos_7;

getlinks() {

   integer total=llGetNumberOfPrims()+1;
   string name;
   while((total--)-1)
   {
       name=llGetLinkName(total);
       if(name == "Cube")LINK_cube = total;
       if(name == "1")   LINK_1 = total;
       if(name == "2")   LINK_2 = total;
       if(name == "3")   LINK_3 = total;
       if(name == "4")   LINK_4 = total;
       if(name == "5")   LINK_5 = total;
       if(name == "6")   LINK_6 = total;
       if(name == "7")   LINK_7 = total;
   }

}

getPositions() {

   pos_1 = llList2Vector(llGetLinkPrimitiveParams(LINK_1, [PRIM_POS_LOCAL]), 0);
   pos_2 = llList2Vector(llGetLinkPrimitiveParams(LINK_2, [PRIM_POS_LOCAL]), 0);
   pos_3 = llList2Vector(llGetLinkPrimitiveParams(LINK_3, [PRIM_POS_LOCAL]), 0);
   pos_4 = llList2Vector(llGetLinkPrimitiveParams(LINK_4, [PRIM_POS_LOCAL]), 0);
   pos_5 = llList2Vector(llGetLinkPrimitiveParams(LINK_5, [PRIM_POS_LOCAL]), 0);
   pos_6 = llList2Vector(llGetLinkPrimitiveParams(LINK_6, [PRIM_POS_LOCAL]), 0);
   pos_7 = llList2Vector(llGetLinkPrimitiveParams(LINK_7, [PRIM_POS_LOCAL]), 0);

}

vector bSpline(list v, float t, integer Loop) {

   integer l = llGetListLength(v); t *= l-1;
   integer f = llFloor(t); t -= f;
   float t2 = t * t; float t3 = t2 * t;
   vector out=(
     ( (-t3 + (3.*t2) - (3.*t) + 1.) * llList2Vector(v, pIndex(f-1,l,Loop)) )
   + ( ((3.*t3) - (6.*t2) + 4.) * llList2Vector(v, pIndex(f,l,Loop)) )
   + ( ((-3.*t3) + (3.*t2) + (3.*t) + 1.) * llList2Vector(v, pIndex(f+1,l,Loop)) )
   + ( t3 * llList2Vector(v, pIndex(f+2,l,Loop)) )
   ) / 6.0;
   llSetText(
       "time: "+(string)t+"\n"+
       "vector pos: "+(string)out
   ,<1.0,1.0,1.0>,1.0);
   return out;

} integer pIndex( integer Index, integer Length, integer Loop) {

   if(Loop) return Index % Length;
   if(Index < 0) return 0;
   if(Index > --Length) return Length;
   return Index;

}

interpolate() {

   getPositions();
   
   float t;
   for(t = 0; t < 1; t += 0.001)
   {
       llSetLinkPrimitiveParamsFast(LINK_cube, [PRIM_POS_LOCAL,bSpline([pos_1,pos_2,pos_3,pos_4,pos_5,pos_6,pos_7,pos_7,pos_7],t,0)]);
   }

}

default {

   state_entry()
   {getlinks();}
   
   touch_start(integer num)
   {interpolate();}

}

</lsl>