Feedback

Please leave feedback and comments. I am always interested to hear how people get on using these LScripts!

Monday, 18 February 2013

LScript - Generic_Blueprint


LScript (Layout) to quickly setup a scene to produce a blueprint look.

Please be aware this script overrides objects surfaces settings.

Compatible with Newtek LightWave 9.6 and above.

// LScript Generic - www.StephenCulley.co.uk
//
// web   address: http://www.stephenculley.co.uk
// email address: email@stephenculley.co.uk

/*  
    LScript Generic - Blueprint

    Generic_Blurprint.ls

*/

@version 2.2
@warnings
@script generic
@name *Blurprint

    sTitle = "*Blueprint";
    sVersion = "v1.0";    

generic
{
    reqbegin(sTitle + " " + sVersion);

    ctrl_c0 = ctlcolor("Background",<60,100,200>);
    ctrl_c1 = ctlcolor("Lines",<255,255,255>);
    ctrl_c2 = ctlnumber("Opacity",0.2);
    ctrl_c3 = ctlchoice("Show",1,@ "Edge","All" @,false);

    // Developer
    ctlsep();
    ctrl_dev0 = ctltext("","developer: Stephen Culley","http://www.stephenculley.co.uk");

    return if !reqpost();   

    vBackgroundColor = getvalue(ctrl_c0);
    vLineColor = getvalue(ctrl_c1) * (1/255);
    nOpacity = getvalue(ctrl_c2);
    if(getvalue(ctrl_c3) == 2){iPolygonEdgeFlag = 31;}else{iPolygonEdgeFlag = 15;}
    
    // Background Color
    if(Scene().backdroptype == GRADIENT){CommandInput("GradientBackdrop");}
    CommandInput("BackdropColor " +  (vBackgroundColor.x * (1/255)) + " " + (vBackgroundColor.y * (1/255)) + " " + (vBackgroundColor.z * (1/255)));

    // Item
    Item = Mesh();
    while(Item)
      {

      if(Item.isMesh())
        {
        SelectItem(Item.id);
        CommandInput("PolygonEdgeFlags " + iPolygonEdgeFlag);
        CommandInput("PolygonEdgeThickness 1 1 1 1 1");
        CommandInput("PolygonEdgeColor " + vLineColor.x + " " + vLineColor.y + " " + vLineColor.z);

        // Surface
        Surface = Surface();
        while(Surface)
          {
          Surface.setValue(SURFCOLR,vBackgroundColor); // Color
          Surface.setValue(SURFLUMI,1.0); // Luminosity
          Surface.setValue(SURFDIFF,0.0); // Diffuse
          Surface.setValue(SURFSPEC,0.0); // Specularity
          Surface.setValue(SURFREFL,0.0); // Reflection
          Surface.setValue(SURFTRAN,nOpacity); // Transparency
          Surface.setValue(SURFTRNL,0.0); // Translucency
          Surface.setValue(SURFBUMP,0.0); // Bump
          Surface.setValue(SURFSIDE,1); // Sided
          Surface = Surface.next();
          }

        }

      Item = Item.next();
      }

    info(sTitle + " " + sVersion + " - developer: Stephen Culley - http://www.stephenculley.co.uk");
}


All scripts available at my Google Drive at
https://drive.google.com/open?id=1cR_q2GVUAJHumic1-A3eXV16acQnVTWs

LScript - Generic_BoxRig (v1.1)

LScript (Layout) to rig a box so that it can pivot upon its edges and corners. This script sets up the hiearchy and expressions required ready for animation upon any selected objects.

Use "Parent" null to position and rotate box and "Control" null to animate using the rig.

Problem
  • Under LightWave 11 Item Shape is broken due to changes in comring
Changes
  • Fixed parenting (v1.1)
  • Objects require pivot to be resting on ground and centre of object
  • Does not work on clones due to expressions
  • Fixed getting correct boundingbox extents from layers
  • Fixed Parent in Place issues
  • Fixed offset when pivot not at bottom of object
Compatible with Newtek LightWave 9.6 up and prior to 11.0.

// LScript Generic - www.StephenCulley.co.uk
//
// web   address: http://www.stephenculley.co.uk
// email address: email@stephenculley.co.uk

/*  
    LScript Generic - BoxRig

    Generic_BoxRig.ls

*/

@version 2.2
@warnings
@script generic
@name *Box Rig
  
    // Title
    sTitle = "*Box Rig";

    // Version
    sVersion = "v1.1";    

generic
{

    // Item Select
    Items = Scene().getSelect();  
    if(Items == nil)
      {
      info("Select an object.");
      return;
      }

    // Parent in Place
    bParentInPlace = Scene().generalopts[3];
    if(bParentInPlace){ParentInPlace();}

    for(i = 1; i <= Items.size(); i++)
      {

      if(Items[i].genus == MESH && !Items[i].null)
        {

        GoToFrame(0);

        SelectItem(Items[i].id);
 
        // Box Item
        BoxItem = Mesh(0); // Get Box
        BoxItem_Parent = BoxItem.parent; // Parent
        vPivot = BoxItem.getPivot(0.0);
        vPosition = BoxItem.getPosition(0.0); // Position
        vRotation = BoxItem.getRotation(0.0); // Rotation
        vScaling = BoxItem.getScaling(0.0); // Scaling
        aBoundingBox = BoxItem.position(getlayernumber(BoxItem)); // Bounding Box
        aBoundingBox[1] -= vPivot; 
        aBoundingBox[2] -= vPivot;

        sName = BoxItem.name; // Name

        // Reset Box
        Position(0.0,-aBoundingBox[1].y,0.0);
        Rotation(0.0,0.0,0.0);
        Scale(1.0,1.0,1.0);
        CreateKey(0);

        // Parent Item
        AddNull(sName + "_Parent");
        ParentItem = Mesh(sName + "_Parent"); // Assign to a var       
        ItemColor(12); // Color Dark Red
        Position();
        Rotation(vRotation);
        Scale(vScaling);
        CreateKey(0);
        if(BoxItem_Parent != nil){ParentItem(BoxItem_Parent.id);} // Parent

        // Pivot Item
        AddNull(sName + "_Pivot");
        PivotItem = Mesh(sName + "_Pivot"); // Assign to a var
        ItemColor(5); // Color Dark Red
        ParentItem(ParentItem.id); // Parent

        // Shift Item
        AddNull(sName + "_Shift");
        ShiftItem = Mesh(sName + "_Shift"); // Assign to a var
        ItemColor(5); // Color Dark Red
        ParentItem(PivotItem.id); // Parent
        MoveTool();
        EnableXH();
        EnableYP();
        EnableZB();
        RotateTool();
        EnableXH();
        EnableYP();
        EnableZB();
        SquashTool();
        EnableXH();
        EnableYP();
        EnableZB();

        // Box Item
        BoxItem.select();
        ParentItem(ShiftItem.id); // Parent
        ItemColor(7); // Color Brown
        MoveTool();
        EnableYP();
        RotateTool();
        EnableYP();
        EnableZB();
        SquashTool();
        EnableXH();
        EnableYP();
        EnableZB();

        // Extent Item
        AddNull(sName + "_Extent");
        ExtentItem = Mesh(sName + "_Extent"); // Assign to a var
        ItemColor(5); // Color Dark Red
        ParentItem(ParentItem.id); // Parent
        Position(aBoundingBox[2].x,0.0,aBoundingBox[2].z);
        CreateKey(0);
        MoveTool();
        EnableYP();
        RotateTool();
        EnableXH();
        EnableYP();
        EnableZB();
        SquashTool();
        EnableXH();
        EnableYP();
        EnableZB();

        // Control Item
        AddNull(sName + "_Control");
        ControlItem = Mesh(sName + "_Control"); // Assign to a var
        ItemColor(12); // Color Red
        ParentItem(ParentItem.id); // Parent
        MoveTool();
        EnableYP();
        RotateTool();
        EnableYP();
        EnableZB();
        SquashTool();
        EnableXH();
        EnableYP();
        EnableZB();

        // Custom
        customshape(ParentItem,nil,0,nil,"Parent");
        customshape(PivotItem,ParentItem,8,nil,"Pivot");
        customshape(ShiftItem,ParentItem,8,nil,"Shift");
        customshape(BoxItem,ParentItem,8,nil,"");
        customshape(ExtentItem,ParentItem,8,nil,"Extent");
        customshape(ControlItem,ParentItem,6,0.15,"Control");

    // EXPRESSIONS

        // Shift_X
        createexpression(sName + "_Shift_X","max(min((( - ([" + sName + "_Control.Position.X] * 1000) ) * (1 / 5)) * (  [" + sName + "_Extent.Position.X]  ),[" + sName + "_Extent.Position.X]),-[" + sName + "_Extent.Position.X])");
        ShiftItem.select();
        attachexpression(sName + "_Shift_X",sName + "_Shift.Position.X");

        // Shift_Z
        createexpression(sName + "_Shift_Z","max(min((( - ([" + sName + "_Control.Position.Z] * 1000) ) * (1 / 5)) * (  [" + sName + "_Extent.Position.Z]  ),[" + sName + "_Extent.Position.Z]),-[" + sName + "_Extent.Position.Z])");
        ShiftItem.select();
        attachexpression(sName + "_Shift_Z",sName + "_Shift.Position.Z");

        // Pivot_X
        createexpression(sName + "_Pivot_X","min(max((( - ([" + sName + "_Control.Position.X] * 1000) ) * (1 / 5)) * (  -[" + sName + "_Extent.Position.X]  ),-[" + sName + "_Extent.Position.X]),[" + sName + "_Extent.Position.X])");
        PivotItem.select();
        attachexpression(sName + "_Pivot_X",sName + "_Pivot.Position.X");

        // Pivot_Z
        createexpression(sName + "_Pivot_Z","min(max((( - ([" + sName + "_Control.Position.Z] * 1000) ) * (1 / 5)) * (  -[" + sName + "_Extent.Position.Z]  ),-[" + sName + "_Extent.Position.Z]),[" + sName + "_Extent.Position.Z])");
        PivotItem.select();
        attachexpression(sName + "_Pivot_Z",sName + "_Pivot.Position.Z");

        // Pivot_H
        createexpression(sName + "_Pivot_H","[" + sName + "_Control.Rotation.H]");
        PivotItem.select();
        attachexpression(sName + "_Pivot_H",sName + "_Pivot.Rotation.H");

        // Pivot_P
        createexpression(sName + "_Pivot_P","mapRange([" + sName + "_Control.Position.Z],0.000,[" + sName + "_Extent.Position.Z],0.000,90.000)");
        PivotItem.select();
        attachexpression(sName + "_Pivot_P",sName + "_Pivot.Rotation.P");

        // Pivot_B
        createexpression(sName + "_Pivot_B","- mapRange([" + sName + "_Control.Position.X],0.000,[" + sName + "_Extent.Position.X],0.000,90.000)");
        PivotItem.select();
        attachexpression(sName + "_Pivot_B",sName + "_Pivot.Rotation.B");

    //

        // Control
        ControlItem.select();
        MoveTool();

        }

      }

    // Parent in Place
    if(bParentInPlace){ParentInPlace();}

    info(sTitle + " " + sVersion + " - developer: Stephen Culley - http://www.stephenculley.co.uk");
}

getlayernumber: item
{
    if(item.totallayers == 1){return(1);}
    sTokens = parse(":",item.name);
    iLayer = 0;
    if (strleft(sTokens[2],5)=="Layer")
      {
      iLayer = integer(sTokens[2]);
      }
    else
      {
      iTotal = item.totallayers;
      for(i = 1; i <= iTotal; i++)
        {
        if(item.layerVisible(i) == 1)
          {
          if(item.layerName(i) == sTokens[2])
            {
            iLayer = i;
            break;
            }
          }
        else
          {
          iTotal++;
          }
        }
      }
  return iLayer;
}

createexpression: name, expression
{
    CommandInput("GE_CreateExpression " + "\"" + name + "\"" + " " + "\"" + expression + "\"");
} 

attachexpression: name,channel
{
    CommandInput("GE_OpenWindow");
    CommandInput("GE_SetEnv " + "\"" + channel);
    CommandInput("GE_AttachExpression " + "\"" + channel + "\"" + name);
}

customshape: item,linkto,shape,scale,label
{
    SelectItem(item.id);
    ApplyServer("CustomObjHandler","LW_ItemShape");

    // ItemShapeData structure
    aItemShapeData = @"p",                // ctxt
                      "p","p",            // self, linkTo
                      "d","d","d",        // time, level, scale
                      "i","i","i","i",    // axis, fill, shape, flags
                      "f","f","f",        // clrA
                      "f","f","f",        // clrB
                      "f","f","f",        // clrT
                      "d","d","d",        // linkPos
                      "s:120",            // label
                      "s:100",            // desc
                      "p",                // alreadylist
                      "s:256",            // selfname
                      "s:256",            // linktoname
                      "i"@;               // justify
                    
    comringattach("ItemShapeComRing", "shapecomring");
    aDataBlob = comringencode(aItemShapeData,
                              0,
                              item.id, 0,
                              0.0, 0.0, 0.0,
                              0, 0, 0, 0,
                              0.0, 0.0, 0.0,
                              0.0, 0.0, 0.0,
                              0.0, 0.0, 0.0,
                              0.0, 0.0, 0.0,
                              "",
                              "",
                              0,
                              "",
                              "",
                              0);

    comringmsg("ItemShapeComRing", 100, aDataBlob);
    aItemShape = comringdecode(aItemShapeData, aDataBlob);
    if(linkto != nil){aItemShape[3] = linkto.id;}    // linkto
    if(scale != nil){aItemShape[6] = scale;}    // Scale
    aItemShape[7] = 1;    // Axis
    aItemShape[9] = shape;    // Shape
    aItemShape[23] = label; // Label
    if(linkto != nil)
        aItemShape[27] = linkto.name;  // linkto name
    aDataBlob = comringencode(aItemShapeData,
                                aItemShape[1],
                                aItemShape[2],aItemShape[3],
                                aItemShape[4],aItemShape[5],aItemShape[6],
                                aItemShape[7],aItemShape[8],aItemShape[9],aItemShape[10],
                                aItemShape[11],aItemShape[12],aItemShape[13],
                                aItemShape[14],aItemShape[15],aItemShape[16],
                                aItemShape[17],aItemShape[18],aItemShape[19],
                                aItemShape[20],aItemShape[21],aItemShape[22],
                                aItemShape[23],
                                aItemShape[24],
                                aItemShape[25],
                                aItemShape[26],
                                aItemShape[27],
                                aItemShape[28]);
    comringmsg("ItemShapeComRing", 200, aDataBlob);
    comringdetach("ItemShapeComRing");
}

shapecomring: code, data
{
}


All scripts available at my Google Drive at
https://drive.google.com/open?id=1cR_q2GVUAJHumic1-A3eXV16acQnVTWs

LScript - Generic_StackIt (v1.2)

LScript (Layout) to stack an object upon another while parenting them. Select item to stack and then item to stack upon.

Changes
  • Now stacks multiple objects (v1.2)
  • Fixed pivot offset (v1.1)
  • Fixed getting correct boundingbox extents from layers
  • Fixed issue requiring pivot to always be at objects lowest extent
Compatible with Newtek LightWave 9.6 and above.

// LScript Generic - www.StephenCulley.co.uk
//
// web   address: http://www.stephenculley.co.uk
// email address: email@stephenculley.co.uk

/*  
    LScript Generic - StackIt

    Generic_StackIt.ls

*/

@version 2.2
@warnings
@script generic
@name *Stack It

    sTitle = "*Stack It";
    sVersion = "v1.2";    

generic
{

    // Parent in Place
    bParentInPlace = Scene().generalopts[3];
    if(bParentInPlace){ParentInPlace();}

    // Item Select
    Items = Scene().getSelect();  
    if(Items == nil || Items.size() < 2)
      {
      info("Select an object to stack, then select object to stack upon.");
      return;
      }

    for(i = 1; i <= (Items.size() - 1);++i)
      {
      if(Items[i].genus == MESH && !Items[i].null && Items[i + 1].genus == MESH && !Items[i + 1].null)
        {
        GoToFrame(0); // Go To Frame 0
        vPivot1 = Items[i].getPivot(0.0);
        vPivot2 = Items[i + 1].getPivot(0.0);
        aBoundingBox1 = Items[i].position(getlayernumber(Items[i])); // Bounding Box      
        aBoundingBox2 = Items[i + 1].position(getlayernumber(Items[i + 1])); // Bounding Box      
        aBoundingBox1[1] -= vPivot1; 
        aBoundingBox1[2] -= vPivot1; 
        aBoundingBox2[1] -= vPivot2; 
        aBoundingBox2[2] -= vPivot2; 
        Items[i + 1].select();
        Position(vPivot1.x,aBoundingBox1[2].y - aBoundingBox2[1].y + vPivot1.y,vPivot1.z);
        CreateKey(0);    
        ParentItem(Items[i].id); // Parent
        }
      else
        {
        error("Only objects can be stacked."); 
        }
      }

    // Parent in Place
    if(bParentInPlace){ParentInPlace();}

    info(sTitle + " " + sVersion + " - developer: Stephen Culley - http://www.stephenculley.co.uk");
}

getlayernumber: item
{
    if(item.totallayers == 1){return(1);}
    sTokens = parse(":",item.name);
    iLayer = 0;
    if (strleft(sTokens[2],5)=="Layer")
      {
      iLayer = integer(sTokens[2]);
      }
    else
      {
      iTotal = item.totallayers;
      for(i = 1; i <= iTotal; i++)
        {
        if(item.layerVisible(i) == 1)
          {
          if(item.layerName(i) == sTokens[2])
            {
            iLayer = i;
            break;
            }
          }
        else
          {
          iTotal++;
          }
        }
      }
  return iLayer;
}


All scripts available at my Google Drive at
https://drive.google.com/open?id=1cR_q2GVUAJHumic1-A3eXV16acQnVTWs

Sunday, 17 February 2013

Library - Random

The Library is where code samples, building blocks of scripts will be shared.

_randomseed = 0; // n Seed

randomseed: seed
{
    _randomseed = seed;
}

random // n
{
    n = (_randomseed * 214013 + 2531011) % 2^^24;
    _randomseed = n;
    n /= 2^^24; // 0..1
    return(n);
}

gaussianrandom // n
{
    n1 = random();
    n2 = random();
    if(n1 == 0.0){n1 = 0.01;}
    return(sqrt(-2.0 * log(n1)) * cos(2.0 * 3.1415926535 * n2));
}

Library - Matrix

The Library is where code samples, building blocks of scripts will be shared.

matrixworld: item,time // m
{
    // call before matrixtransformworld()
    vnRight = item.getRight(time); // Right
    m[1][1] = vnRight.x;
    m[1][2] = vnRight.y;
    m[1][3] = vnRight.z;
    m[1][4] = 0.0;
    vnUp = item.getUp(time); // Up
    m[2][1] = vnUp.x;
    m[2][2] = vnUp.y;
    m[2][3] = vnUp.z;
    m[2][4] = 0.0;
    vnForward = item.getForward(time); // Forward
    m[3][1] = vnForward.x;
    m[3][2] = vnForward.y;
    m[3][3] = vnForward.z;
    m[3][4] = 0.0;
    vWorldPosition = item.getWorldPosition(time); // World Position
    m[4][1] = vWorldPosition.x;
    m[4][2] = vWorldPosition.y;
    m[4][3] = vWorldPosition.z;
    m[4][4] = 1.0;
    return(m);
}

matrixinverseworld: item,time // m
{
    // call before matrixtransformlocal()
    vnRight = item.getRight(time); // Right
    m[1][1] = vnRight.x;
    m[1][2] = vnRight.y;
    m[1][3] = vnRight.z;
    m[1][4] = 0.0;
    vnUp = item.getUp(time); // Up
    m[2][1] = vnUp.x;
    m[2][2] = vnUp.y;
    m[2][3] = vnUp.z;
    m[2][4] = 0.0;
    vnForward = item.getForward(time); // Forward
    m[3][1] = vnForward.x;
    m[3][2] = vnForward.y;
    m[3][3] = vnForward.z;
    m[3][4] = 0.0;
    vWorldPosition = item.getWorldPosition(time); // World Position
    m[4][1] = -vWorldPosition.x;
    m[4][2] = -vWorldPosition.y;
    m[4][3] = -vWorldPosition.z;
    m[4][4] = 1.0;
    return(m);
}

matrixtransformworld: v,m // v
{
    // call after matrixworld()
    _v = <0.0,0.0,0.0>;
    _v.x = m[1][1] * v.x + m[2][1] * v.y + m[3][1] * v.z + m[4][1];
    _v.y = m[1][2] * v.x + m[2][2] * v.y + m[3][2] * v.z + m[4][2];
    _v.z = m[1][3] * v.x + m[2][3] * v.y + m[3][3] * v.z + m[4][3];
    return(_v);
}

matrixtransformlocal: v,m // v
{
    // call after matrixinverseworld()
    _v = <0.0,0.0,0.0>;    
    v.x += m[4][1];
    v.y += m[4][2];
    v.z += m[4][3];
    _v.x = m[1][1] * v.x + m[2][1] * v.y + m[3][1] * v.z;
    _v.y = m[1][2] * v.x + m[2][2] * v.y + m[3][2] * v.z;
    _v.z = m[1][3] * v.x + m[2][3] * v.y + m[3][3] * v.z;
    return(_v);
}

Library - Interpolation

The Library is where code samples, building blocks of scripts will be shared.

linear1D: n1,n2,i // i = interpolation point (0-1)
{
    return(n1 * (1 - i) + n2 * i);     
}

cosine1D: n1,n2,i // i = interpolation point (0-1)
{
    i2 = (1 - cos(i * 3.1415926535)) * 0.5;
    return(n1 * (1 - i2) + n2 * i2);     
}

bicubic1D: n1,n2,n3,n4,i // i = interpolation point (0-1)
{
    i2 = i * i;
    n_01 = n4 - n3 - n1 + n2;
    n_02 = n1 - n2 - n_01;
    n_03 = n3 - n1;
    n_04 = n2;
    return(n_01 * i * i2 + n_02 * i2 + n_03 * i + n_04);
}

Friday, 15 February 2013

Crackle - Roughnecks: Starship Troopers Chronicles

Over at Crackle they are currently showing Roughnecks : Starship Chronicles. It was one of the first LightWave television series and is based on Starship Troopers.

For a bit of nostalgia visit http://www.crackle.com/c/roughnecksstarshiptrooperschroniclesfullepisodes 

Stephen

Monday, 11 February 2013

LightWave Plugin Database

Ken over at the LightWave Plugin Database has been hard at work improving his website that is a trove of resources for users and artists. Check out his site - http://www.lwplugindb.com

Stephen

Monday, 4 February 2013

LScript - Motion_VolumeTrick

LScript (Layout) for motion values based on position during motion blur used to fake volume effects.

Compatible with Newtek LightWave 9.6 and above.

// LScript Item Animation - www.StephenCulley.co.uk
//
// web   address: http://www.stephenculley.co.uk
// email address: email@stephenculley.co.uk

/*  
    LScript Item Animation - VolumeTrick

    Motion_VolumeTrick.ls

*/

@version 2.2
@warnings
@script motion
@name *Volume Trick

    // Title
    sTitle = "*Volume Trick";

    // Version
    sVersion = "v1.1";

    // Item
    Item;

    // Variable
    aChannel = @"X","Y","Z","H","P","B","S","SX","SY","SZ"@; 
    iChannel = 1;
    nMin = 0.0;
    nMax = 1.0;

create : id
{
    // Description
    setdesc(sTitle);
 
    // Info
    info("*Volume Trick - Motion blur must be enabled.");

    // Items
    Item = id; // Item
}

destroy
{
}

process: ma, frame, time
{     
    // Variables
    vPosition = ma.get(POSITION,time);
    vRotation = ma.get(ROTATION,time);
    vScaling = ma.get(SCALING,time);

    if(Camera().blurLength(time) <> 0.0)
      {
      // Map Range
      n01 = maprange01(frame * (1 / Scene().fps),(frame + 1) * (1 / Scene().fps),time);

        switch(iChannel)
        {

          case 1: // X
                  vPosition.x = linear1D(vPosition.x + nMin,vPosition.x + (nMax * (1 / Camera().blurLength(time))) - nMin,n01);
                  break;
  
          case 2: // Y
                  vPosition.y = linear1D(vPosition.y + nMin,vPosition.y + (nMax * (1 / Camera().blurLength(time))) - nMin,n01);
                  break;

          case 3: // Y
                  vPosition.z = linear1D(vPosition.z + nMin,vPosition.z + (nMax * (1 / Camera().blurLength(time))) - nMin,n01);
                  break;

          case 4: // H
                  vRotation.x = linear1D(vRotation.x + nMin,vRotation.x + (nMax * (1 / Camera().blurLength(time))) - nMin,n01);
                  break;

          case 5: // P
                  vRotation.y = linear1D(vRotation.y + nMin,vRotation.y + (nMax * (1 / Camera().blurLength(time))) - nMin,n01);
                  break;

          case 6: // B
                  vRotation.z = linear1D(vRotation.z + nMin,vRotation.z + (nMax * (1 / Camera().blurLength(time))) - nMin,n01);
                  break;

          case 7: // S
                  vScaling.x = linear1D(vScaling.x + nMin,vScaling.x + (nMax * (1 / Camera().blurLength(time))) - nMin,n01);
                  vScaling.y = linear1D(vScaling.y + nMin,vScaling.y + (nMax * (1 / Camera().blurLength(time))) - nMin,n01);
                  vScaling.z = linear1D(vScaling.z + nMin,vScaling.z + (nMax * (1 / Camera().blurLength(time))) - nMin,n01);
                  break;

          case 8: // SX
                  vScaling.x = linear1D(vScaling.x + nMin,vScaling.x + (nMax * (1 / Camera().blurLength(time))) - nMin,n01);
                  break;

          case 9: // SY
                  vScaling.y = linear1D(vScaling.y + nMin,vScaling.y + (nMax * (1 / Camera().blurLength(time))) - nMin,n01);
                  break;

         case 10: // SZ
                  vScaling.z = linear1D(vScaling.z + nMin,vScaling.z + (nMax * (1 / Camera().blurLength(time))) - nMin,n01);
                  break;
      

        }      


      } 

// ma

  ma.set(POSITION,vPosition);
  ma.set(ROTATION,vRotation);
  ma.set(SCALING,vScaling);

}

// INTERPOLATION

linear1D: n1,n2,i // i = interpolation point (0-1)
{
    return(n1 * (1 - i) + n2 * i);     
}

// MAP RANGE

maprange01: n1,n2,i

{    
    if(n2-n1 == 0.0){return(0.0);}
  else
    {return((1/(n2-n1)) * (i-n1));}
}

load: what,io
{
    if(what == SCENEMODE)   // processing an ASCII scene file
    {
        sHeader = io.read().asStr();

        if(sHeader == sTitle + " " + sVersion)
            {
            iChannel = io.read().asInt();
            nMin = io.read().asNum(); // Min
            nMax = io.read().asNum(); // Max
            break;
            }

        if(sHeader == sTitle + " " + sVersion) // v1.0 Compatibility
            {
            iChannel = io.read().asInt();
            nMin := 0.0; // Min
            nMax = io.read().asNum(); // Max          
            break;
            }
    }
}

save: what,io
{
    if(what == SCENEMODE)
    {
        // Header
        io.writeln(sTitle + " " + sVersion);
        io.writeln(iChannel);
        io.writeln(nMin); // Min
        io.writeln(nMax); // Max
    }
}

options
{
    if(reqisopen())
        {
        reqend();
        return;
        }

    reqbegin(sTitle + " " + sVersion);

    ctrl_c0 = ctlchoice("Channel",iChannel,@"X","Y","Z","H","P","B","S","SX","SY","SZ"@);
    ctrl_c1 = ctlnumber("Min",nMin);   
    ctrl_c2 = ctlnumber("Max",nMax);   

    // Developer
    ctlsep();
    ctrl_dev0 = ctltext("","developer: Stephen Culley","http://www.stephenculley.co.uk");

    // Refresh
    ctlrefresh(ctrl_c0,"refresh_c0"); // Channel
    ctlrefresh(ctrl_c1,"refresh_c1"); // Min
    ctlrefresh(ctrl_c2,"refresh_c2"); // Max

    reqopen();
}

refresh_c0:value // Channel
{
    iChannel = value;
}

refresh_c1:value // Min
{
    nMin = value;
}

refresh_c2:value // Max
{
    nMax = value;
}


All scripts available at my Google Drive at
https://drive.google.com/open?id=1cR_q2GVUAJHumic1-A3eXV16acQnVTWs

LScript - Channel_VolumeTrick

LScript (Layout) to shift channel values based on motion position during motion blur used to fake volume effects.

Compatible with Newtek LightWave 9.6 and above.

// LScript Channel Filter - www.StephenCulley.co.uk
//
// web   address: http://www.stephenculley.co.uk
// email address: email@stephenculley.co.uk

/* 
    LScript Channel Filter - Volume Trick

    Channel_VolumeTrick.ls

*/

@version 2.2
@warnings
@script channel
@name *Volume Trick

    // Title
    sTitle = "*Volume Trick";

    // Version
    sVersion = "v1.1";

    // Variable
    nMin = 0.0;
    nMax = 1.0;

create: channel
{
    setdesc(sTitle);

    // Info
    info("*Volume Trick - Motion blur must be enabled.");
}

destroy
{
    // take care of final clean-up activities here
}

process: ca, frame, time
{
    nValue = ca.get(time);

    if(Camera().blurLength(time) <> 0.0)
      {
      // Map Range
      n01 = maprange01(frame * (1 / Scene().fps),(frame + 1) * (1 / Scene().fps),time);
      nValue = linear1D(nValue + nMin,nValue + (nMax * (1 / Camera().blurLength(time))) - nMin,n01);
      }

    // ca    
    ca.set(nValue);
}

// INTERPOLATION

linear1D: n1,n2,i // i = interpolation point (0-1)
{
    return(n1 * (1 - i) + n2 * i);     
}

// MAP RANGE

maprange01: n1,n2,i

{    
    if(n2-n1 == 0.0){return(0.0);}
  else
    {return((1/(n2-n1)) * (i-n1));}
}

load: what,io
{
    if(what == SCENEMODE)   // processing an ASCII scene file
    {
        if(io.read().asStr() == sTitle + " " + sVersion)
            {
            nMin = io.read().asNum(); // Min
            nMax = io.read().asNum(); // Max
            }
    }
}

save: what,io
{
    if(what == SCENEMODE)
    {
        // Header
        io.writeln(sTitle + " " + sVersion);
        io.writeln(nMin); // Min
        io.writeln(nMax); // Max
    }
}


options
{
    if(reqisopen())
        {
        reqend();
        return;
        }

    reqbegin(sTitle + " " + sVersion);

    ctrl_c0 = ctlnumber("Min",nMin);   
    ctrl_c1 = ctlnumber("Max",nMax);   

    // Developer
    ctlsep();
    ctrl_dev0 = ctltext("","developer: Stephen Culley","http://www.stephenculley.co.uk");

    // Refresh
    ctlrefresh(ctrl_c0,"refresh_c0"); // Min
    ctlrefresh(ctrl_c1,"refresh_c1"); // Max

    reqopen();
}

refresh_c0:value // Min
{
    nMin = value;
}

refresh_c1:value // Max
{
    nMax = value;
}
All scripts available at my Google Drive at
https://drive.google.com/open?id=1cR_q2GVUAJHumic1-A3eXV16acQnVTWs

LScript - Channel_GlobalAmbientIntensity

LScript (Layout) to allow access via channel to the global ambient intensity.

Compatible with Newtek LightWave 9.6 and above.

// LScript Channel Filter - www.StephenCulley.co.uk
//
// web   address: http://www.stephenculley.co.uk
// email address: email@stephenculley.co.uk

/* 
    LScript Channel Filter - Global Ambient Intensity

    Channel_GlobalAmbientIntensity.ls

*/

@version 2.2
@warnings
@script channel
@name *Global Ambient Intensity

    // Title
    sTitle = "*Global Ambient Intensity";

    // Version
    sVersion = "v1.0";

create: channel
{
    setdesc(sTitle);
}

destroy
{
    // take care of final clean-up activities here
}

process: ca, frame, time
{
    nValue = ca.get(time);

    Light = Light();
    nValue += Light.ambient(time);

    // ca    
    ca.set(nValue);
}


load: what,io
{
    if(what == SCENEMODE)   // processing an ASCII scene file
    {
    }
}

save: what,io
{
    if(what == SCENEMODE)
    {
    }
}

options
{
    reqbegin(sTitle + " " + sVersion);

    // Developer
//    ctlsep();
    ctrl_dev0 = ctltext("","developer: Stephen Culley","http://www.stephenculley.co.uk");

    reqend();
}
All scripts available at my Google Drive at
https://drive.google.com/open?id=1cR_q2GVUAJHumic1-A3eXV16acQnVTWs

LScript - Modeler_Poke

LScript (Modeler) that replicates poke in Maya to split polygons with an averaged center.

Changes

Compatible with Newtek LightWave 9.6 and above.

// LScript Modeler - www.StephenCulley.co.uk
//
// web   address: http://www.stephenculley.co.uk
// email address: email@stephenculley.co.uk

/*  
    LScript Modeler - Poke

    Modeler_Poke.ls

*/

@version 2.2
@warnings
@script modeler
@name *Poke

    // Title
    sTitle = "*Poke";

    // Version
    sVersion = "v1.1";

main
{
    // Selection - Polygon (DIRECT)
    selmode(DIRECT);
    iPolyCount = polycount();

    if(iPolyCount[1] < 1) error("No polygons selected.");

    undogroupbegin(); // Undo

    editbegin();

    if(iPolyCount[1] >= 1)
      { 
       
      foreach(aPolygon,polygons)
       {
        aPoints = polyinfo(aPolygon); 
        rempoly(aPolygon);
        vAverage = <0.0,0.0,0.0>;
        for(iPointCount = 2; iPointCount <= sizeof(aPoints); iPointCount++)
          {
          vAverage += pointinfo(aPoints[iPointCount]);  
          }
        // Resize by points
        vAverage *= 1 / (sizeof(aPoints) - 1);
        // Make new point
        iAverage = addpoint(vAverage); // Returns ID

        // Add polygons
        for(iPointCount = 2; iPointCount <= sizeof(aPoints) - 1; iPointCount++)
          {
          aNewPolygon[1] = aPoints[iPointCount]; 
          aNewPolygon[2] = aPoints[iPointCount + 1]; 
          aNewPolygon[3] = iAverage; 
          addpolygon(aNewPolygon);  
          }
        aNewPolygon[1] = aPoints[sizeof(aPoints)]; 
        aNewPolygon[2] = aPoints[2]; 
        aNewPolygon[3] = iAverage; 
        addpolygon(aNewPolygon);             
        }

      }

    editend();

    undogroupend(); // Undo

    info(iPolyCount[1]," poly(s) poked.");
}


All scripts available at my Google Drive at
https://drive.google.com/open?id=1cR_q2GVUAJHumic1-A3eXV16acQnVTWs