Jump to content

Curves Toy


Quistess Alpha
 Share

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

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

Recommended Posts

So, this is one of the worst ways to go about this (1 object+script per point adds up fast) But it's quite fun anyway.

Bezier_002.png.788f93f8c19ec7c28a076d08b77ad42a.png

// general vars:
integer gChan = 297;
integer DEBUG = FALSE;

vector gPos; // where is the point?

string gName;
string gDesc;

// interpolated variables:
vector gPointA; // location of point 'A'
string gCodePA; // actual letter may not be 'A'
vector gTangentA1; // location of tangent point
vector gPointB; // location of point 'B'
string gCodePB; // actual letter may not be 'B'
vector gTangentB0; // location of tangent point.
float gPercent; // percent of the way between 'A' and 'B'
// tangent variables:

// gCodePA ; will be overused as the point the tangent line passes through.
// gPointA ; similarly the position that point is at.
integer gTangentNum; // either 0 or 1, which tangent point is this.
integer gIgnore; // we need to ignore some messages to prevent an infinite back and forth.

// curve_end variables:
    // none specific.

set_interpolation()
{
    float x = gPercent;
    float nx = 1-gPercent;
    llSetRegionPos(nx*nx*nx*gPointA + 3*x*nx*nx*gTangentA1 + 3*x*x*nx*gTangentB0 + x*x*x*gPointB);
}

particle_line(key Target)
{
    llParticleSystem([
        PSYS_PART_FLAGS,
            PSYS_PART_TARGET_LINEAR_MASK|
            PSYS_PART_EMISSIVE_MASK,
        PSYS_SRC_TARGET_KEY, Target,
        PSYS_PART_START_SCALE, <0.1,0.1,0.1>,
        PSYS_PART_START_COLOR, <0.9,0.9,0.0>,
        PSYS_SRC_BURST_RATE, 0.2,
        PSYS_PART_MAX_AGE, 3.0
    ]);
}

default
{
    state_entry()
    {
        if(DEBUG) llSay(0,"Boot up");
        // set_state();
        gName = llGetObjectName();
        if      (!llSubStringIndex(gName,"Point"))
        {   state curve_end;
        }else if(!llSubStringIndex(gName,"Tangent"))
        {   state tangent;
        }else if(!llSubStringIndex(gName,"Interpolated"))
        {   state interpolated;
        }else
        {   llSay(0,"Name not recognised");
        }
    }
}
state curve_end
{   state_entry()
    {   //llListen(gChan,"","","");
        llParticleSystem([]);
        llSetColor(<0,1,0>,0);
        llSetScale(<0.2,0.2,0.2>);
        llSetText(gName,<0,1,0>,1.0);
    }
    touch_end(integer n)
    {   // set_state();
        if(gName!=llGetObjectName())
        {   llResetScript();
        }
        vector pos = llGetPos();
        if(gPos!=pos)
        {   llSay(gChan,(string)pos);
            gPos=pos;
        }
    }
}
state tangent
{   state_entry()
    {   llParticleSystem([]);
        llListen(gChan,"","","");
        llSetColor(<0.9,0.9,0>,0);
        llSetScale(<0.15,0.15,0.15>);
        llSetText(gName,<1,1,0>,1.0);
        gCodePA = llGetSubString(gName,-2,-2);
        gTangentNum = (integer)llGetSubString(gName,-1,-1);
        llSensor("Point "+gCodePA, "", PASSIVE|SCRIPTED, 12.0, PI);
    }
    on_rez(integer i)
    {   llSensor("Point "+gCodePA, "", PASSIVE|SCRIPTED, 12.0, PI);
    }
    sensor(integer n)
    {   if(n==1)
        {   gPointA = llDetectedPos(0);
            particle_line(llDetectedKey(0));
            if(DEBUG) llSay(0,"Found point: "+gCodePA);
        }else
        {   llSay(0,"Error, duplicate points found: "+gCodePA);
        }
    }
    no_sensor()
    {   llSay(0,"Error, Point not found: "+gCodePA);
    }
    touch_start(integer n)
    {   if(gName!=llGetObjectName())
        {   llResetScript();
        }
        vector pos = llGetPos();
        if(gPos!=pos)
        {   llSay(gChan,(string)(gPos=pos));
            gIgnore = TRUE;
            vector X = llVecNorm(gPointA-llGetPos());
            llSetRot(llRotBetween(<0,0,1>,X));
        }
    }
    listen(integer Channel, string Name, key ID, string Text)
    {
        if(Name=="Point "+gCodePA)
        {   vector pos = ((vector)Text);
            llSetRegionPos(gPos = (llGetPos()+ pos - gPointA));
            llSay(gChan,(string)gPos);
            gIgnore = TRUE;
            gPointA = pos;
            vector X = llVecNorm(gPointA-llGetPos());
            llSetRot(llRotBetween(<0,0,1>,X));
        }else if(Name=="Tangent "+gCodePA+(string)(!gTangentNum))
        { // ^^ could be more efficient by precalculating that as a global variable.
            if(gIgnore)
            {   gIgnore=FALSE;
            }else
            {
                vector pos2 = (vector)Text;
                vector norm = llVecNorm(gPointA-pos2);
                float dist = llVecDist(llGetPos(),gPointA);
                vector gPos = gPointA+(norm*dist);
                llSetRegionPos(gPos);
                llSay(gChan,(string)gPos);
            }
        }
    }
}
state interpolated
{   state_entry()
    {   llParticleSystem([]);
        llListen(gChan,"","","");
        llSetColor(<0.2,0.2,0.2>,0);
        llSetScale(<0.1,0.1,0.1>);
        
        gDesc = llGetObjectDesc();
        
        gCodePA = llGetSubString(gName,-2,-2);
        gCodePB = llGetSubString(gName,-1,-1);
        llSetText(gCodePA+gCodePB,<0.1,0.1,0.1>,1.0);
        list parsed = llParseString2List(llGetObjectDesc(),["/"," "],[]);
        gPercent = (float)llList2String(parsed,0) / (float)llList2String(parsed,1);
        llSensor("Point "+gCodePA, "", PASSIVE|SCRIPTED, 12.0, PI);

    }
    on_rez(integer i)
    {   llSensor("Point "+gCodePA, "", PASSIVE|SCRIPTED, 12.0, PI);
    }
    touch_start(integer n)
    {   if(gName!=llGetObjectName() || gDesc!=gDesc)
        {   llResetScript();
        }
    }
    sensor(integer n)
    {   while(~--n)
        {   string name = llDetectedName(n);
            if(name == "Point "+gCodePA)
            {   gPointA = llDetectedPos(n);
                llSensor("Point "+gCodePB, "", PASSIVE|SCRIPTED, 12.0, PI);
            }else if(name == "Point "+gCodePB)
            {   gPointB = llDetectedPos(n);
                llSensor("Tangent "+gCodePA+"1", "", PASSIVE|SCRIPTED, 12.0, PI);
            }else if(name == "Tangent "+gCodePA+"1")
            {   gTangentA1 = llDetectedPos(n);
                llSensor("Tangent "+gCodePB+"0", "", PASSIVE|SCRIPTED, 12.0, PI);
            }else if(name == "Tangent "+gCodePB+"0")
            {   gTangentB0 = llDetectedPos(n);
                set_interpolation();
            }
            if(DEBUG) llSay(0,"Found: "+name);
        }
    }
    no_sensor()
    {   llSay(0,"Not found");
    }
    listen(integer Channel, string name, key ID, string Text)
    {
        vector pos = (vector)Text;
        integer change = FALSE;
        if(name == "Point "+gCodePA)
        {   gPointA = pos;
            change = TRUE;
        }else if(name == "Point "+gCodePB)
        {   gPointB = pos;
            change = TRUE;
        }else if(name == "Tangent "+gCodePA+"1")
        {   gTangentA1 = pos;
            change = TRUE;
        }else if(name == "Tangent "+gCodePB+"0")
        {   gTangentB0 = pos;
            change = TRUE;
        }
        if(change)
        {   set_interpolation();
        }
    }
}

It's a bit of a pain to set up (need to type in a lot of repetitive names and descriptions) and to use (need to touch after moving the points or tangents to register a change) but it's workable. Edit-> move a point or 'tangent' then touch it and everything else falls into place in a 'natural' way.

You can see it live (I even left move permissions on, so anyone can move the colored points) in my sandbox http://maps.secondlife.com/secondlife/Gilgamesh/36/167/2012 until I decide I need the LI back. (should be a week or two at least)

  • Like 2
Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 896 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...