Feedback

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

Saturday, 24 March 2012

LScript - Modeler_Jitter


LScript (Modeler) to offsets vertices based on chosen parameters such as noise and Brownian motion.

Changes

  • Seeded noise
  • Seeded fractal Brownian motion
  • Added control reset
  • Realtime Preview

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 - Jitter

    Modeler_Jitter.ls

*/

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

    // Title
    sTitle = "*Jitter";

    // Version
    sVersion = "v2.0";
 
    bDone = false; // Done
    bChange = false; // Change
    bPreview; // Preview
    iType;
    bAxisX;
    bAxisY;
    bAxisZ;
    nAmplitude;
    iOctaves;
    nPersistence;
    vScale;
    iSeed;
    iInterpolation;
   
    ctrl_c0,ctrl_c1,ctrl_c2,ctrl_c3,ctrl_c4,ctrl_c5,ctrl_c6,ctrl_c7,ctrl_c8,ctrl_c9;
    ctrl_res0;
    ctrl_prev0;

main
{

    // Recall
    bPreview = recall("bPreview",true);
    iType = recall("iType",2);
    bAxisX = recall("bAxisX",true);
    bAxisY = recall("bAxisY",true);
    bAxisZ = recall("bAxisZ",true);
    nAmplitude = recall("nAmplitude",0.1);
    iOctaves = recall("iOctaves",3);
    nPersistence = recall("nPersistence",0.25);
    vScale = recall("vScale",<1.0,1.0,1.0>);
    iSeed = recall("iSeed",1);
    iInterpolation = recall("iInterpolation",3);

    reqbegin(sTitle + " " + sVersion);

    // Reset / Preview
    ctrl_res0 = ctlbutton("Reset",50,"button_reset"); // Button Reset
    ctrl_prev0 = ctlcheckbox("Preview",bPreview); // Preview
    ctlsep();

    // Control
    ctrl_c0 = ctlchoice("Type",iType,@"Noise","fBm"@); // Type
    ctrl_c1 = ctlcheckbox("X",bAxisX); // X
    ctrl_c2 = ctlcheckbox("Y",bAxisY); // Y
    ctrl_c3 = ctlcheckbox("Z",bAxisZ); // Z
    ctrl_c4 = ctldistance("Amplitude",nAmplitude); // Amplitude
    ctrl_c5 = ctlslider("Octaves",iOctaves,1,64); // Octaves
    ctrl_c6 = ctlnumber("Persistence",nPersistence); // Persistence
    ctrl_c7 = ctlvector("Scale",vScale); // Scale
    ctrl_c8 = ctlinteger("Seed",iSeed); // Seed
    ctrl_c9 = ctlchoice("Interpolation",iInterpolation,@"None","Linear","Cosine"@); // Interpolation

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

    process(); // Process

    // Refresh
    ctlrefresh(ctrl_prev0,"refresh");
    ctlrefresh(ctrl_c0,"refresh");
    ctlrefresh(ctrl_c1,"refresh");
    ctlrefresh(ctrl_c2,"refresh");
    ctlrefresh(ctrl_c3,"refresh");
    ctlrefresh(ctrl_c4,"refresh");
    ctlrefresh(ctrl_c5,"refresh");
    ctlrefresh(ctrl_c6,"refresh");
    ctlrefresh(ctrl_c7,"refresh");
    ctlrefresh(ctrl_c8,"refresh");
    ctlrefresh(ctrl_c9,"refresh");

    if (!reqpost())
    {
        // Cancel

        if(bDone){undo();} // Undo

        return;
    }
    else
    {
        // Ok

        if(!bDone || bChange) // Process
        {
        values(); // Values
        process(); // Process
        }

        // Store
        store("bPreview",bPreview);
        store("iType",iType);
        store("bAxisX",bAxisX);
        store("bAxisY",bAxisY);
        store("bAxisZ",bAxisZ);
        store("nAmplitude",nAmplitude);
        store("iOctaves",iOctaves);
        store("nPersistence",nPersistence);
        store("vScale",vScale);
        store("iSeed",iSeed);
        store("iInterpoltation",iInterpolation);
    }

    reqend();
}

refresh:value
{
    bChange = true; // Change
    values(); // Values
    if(bPreview){process();} // Process
}

values
{
    bPreview = getvalue(ctrl_prev0); // Preview
    iType = getvalue(ctrl_c0); // Type
    bAxisX = getvalue(ctrl_c1); // X
    bAxisY = getvalue(ctrl_c2); // Y
    bAxisZ = getvalue(ctrl_c3); // Z
    nAmplitude = getvalue(ctrl_c4); // Amplitude
    iOctaves = getvalue(ctrl_c5); // Octaves
    nPersistence = getvalue(ctrl_c6); // Persistence
    vScale = getvalue(ctrl_c7); // Scale
    iSeed = getvalue(ctrl_c8); // Seed 
    iInterpolation = getvalue(ctrl_c9); // Interpolation
}

button_reset
{
    setvalue(ctrl_c0,2); // Type
    setvalue(ctrl_c1,true); // X
    setvalue(ctrl_c2,true); // Y
    setvalue(ctrl_c3,true); // Z
    setvalue(ctrl_c4,0.1); // Amplitude
    setvalue(ctrl_c5,3); // Octaves
    setvalue(ctrl_c6,0.25); // Persistence
    setvalue(ctrl_c7,<1.0,1.0,1.0>); // Scale
    setvalue(ctrl_c8,1); // Seed
    setvalue(ctrl_c9,3); // Interpolation
}

process
{
    // Undo
    if(bDone){undo();}
    undogroupbegin();

    // Process

    // Selection - Point (DIRECT)
    selmode(DIRECT);
    iPointCount = pointcount();
    if(iPointCount < 1) error("No points selected.");

    noiseseed(iSeed); // Noise Seed

    for(iO = 1; iO <= 3; iO++)
      {
      aOffset[iO] = ;
      }

    editbegin();

        if((iType == "1") && (iInterpolation == 1)) // Noise
          {
          moninit(iPointCount,"Processing...");  // Progress Monitor
          for(iCurrentPoint = 1; iCurrentPoint <= iPointCount; iCurrentPoint++)
            {
            vOffset = <0.0,0.0,0.0>;
            vPoint = pointinfo(points[iCurrentPoint]) * vScale;
            if(bAxisX){vOffset.x = noise3D(vPoint + aOffset[1]);}
            if(bAxisY){vOffset.y = noise3D(vPoint + aOffset[2]);}
            if(bAxisZ){vOffset.z = noise3D(vPoint + aOffset[3]);}
            pointmove(points[iCurrentPoint],pointinfo(points[iCurrentPoint]) + (vOffset * nAmplitude)); // Move point  
            monstep(); // Progress Monitor
            }
          monend(); // Progress Monitor
          } 

        else if((iType == "1") && (iInterpolation == 2)) // Linear Noise
          {
          moninit(iPointCount,"Processing...");  // Progress Monitor
          for(iCurrentPoint = 1; iCurrentPoint <= iPointCount; iCurrentPoint++)
            {
            vOffset = <0.0,0.0,0.0>;
            vPoint = pointinfo(points[iCurrentPoint]) * vScale;
            if(bAxisX){vOffset.x = linearnoise3D(vPoint + aOffset[1]);}
            if(bAxisY){vOffset.y = linearnoise3D(vPoint + aOffset[2]);}
            if(bAxisZ){vOffset.z = linearnoise3D(vPoint + aOffset[3]);}
            pointmove(points[iCurrentPoint],pointinfo(points[iCurrentPoint]) + (vOffset * nAmplitude)); // Move point  
            monstep(); // Progress Monitor
            }
          monend(); // Progress Monitor
          }

        else if((iType == "1") && (iInterpolation == 3)) // Cosine Noise
          {
          moninit(iPointCount,"Processing...");  // Progress Monitor
          for(iCurrentPoint = 1; iCurrentPoint <= iPointCount; iCurrentPoint++)
            {
            vOffset = <0.0,0.0,0.0>;
            vPoint = pointinfo(points[iCurrentPoint]) * vScale;
            if(bAxisX){vOffset.x = cosinenoise3D(vPoint + aOffset[1]);}
            if(bAxisY){vOffset.y = cosinenoise3D(vPoint + aOffset[2]);}
            if(bAxisZ){vOffset.z = cosinenoise3D(vPoint + aOffset[3]);}
            pointmove(points[iCurrentPoint],pointinfo(points[iCurrentPoint]) + (vOffset * nAmplitude)); // Move point  
            monstep(); // Progress Monitor
            }
          monend(); // Progress Monitor
          }  

        else if((iType == "2") && (iInterpolation == 1)) // fBm Noise
          {
          moninit(iPointCount,"Processing...");  // Progress Monitor
          for(iCurrentPoint = 1; iCurrentPoint <= iPointCount; iCurrentPoint++)
            {
            vOffset = <0.0,0.0,0.0>;
            vPoint = pointinfo(points[iCurrentPoint]) * vScale;
            if(bAxisX){vOffset.x = fBmnoise3D(vPoint + aOffset[1],iOctaves,nPersistence);}
            if(bAxisY){vOffset.y = fBmnoise3D(vPoint + aOffset[2],iOctaves,nPersistence);}
            if(bAxisZ){vOffset.z = fBmnoise3D(vPoint + aOffset[3],iOctaves,nPersistence);}
            pointmove(points[iCurrentPoint],pointinfo(points[iCurrentPoint]) + (vOffset * nAmplitude)); // Move point  
            monstep(); // Progress Monitor
            }
          monend(); // Progress Monitor
          }  

        else if((iType == "2") && (iInterpolation == 2)) // Linear fBm Noise
          {
          moninit(iPointCount,"Processing...");  // Progress Monitor
          for(iCurrentPoint = 1; iCurrentPoint <= iPointCount; iCurrentPoint++)
            {
            vOffset = <0.0,0.0,0.0>;
            vPoint = pointinfo(points[iCurrentPoint]) * vScale;
            if(bAxisX){vOffset.x = linearfBmnoise3D(vPoint + aOffset[1],iOctaves,nPersistence);}
            if(bAxisY){vOffset.y = linearfBmnoise3D(vPoint + aOffset[2],iOctaves,nPersistence);}
            if(bAxisZ){vOffset.z = linearfBmnoise3D(vPoint + aOffset[3],iOctaves,nPersistence);}
            pointmove(points[iCurrentPoint],pointinfo(points[iCurrentPoint]) + (vOffset * nAmplitude)); // Move point  
            monstep(); // Progress Monitor
            }
          monend(); // Progress Monitor
          }

        else if((iType == "2") && (iInterpolation == 3)) // Cosine fBm Noise
          {
          moninit(iPointCount,"Processing...");  // Progress Monitor
          for(iCurrentPoint = 1; iCurrentPoint <= iPointCount; iCurrentPoint++)
            {
            vOffset = <0.0,0.0,0.0>;
            vPoint = pointinfo(points[iCurrentPoint]) * vScale;
            if(bAxisX){vOffset.x = cosinefBmnoise3D(vPoint + aOffset[1],iOctaves,nPersistence);}
            if(bAxisY){vOffset.y = cosinefBmnoise3D(vPoint + aOffset[2],iOctaves,nPersistence);}
            if(bAxisZ){vOffset.z = cosinefBmnoise3D(vPoint + aOffset[3],iOctaves,nPersistence);}
            pointmove(points[iCurrentPoint],pointinfo(points[iCurrentPoint]) + (vOffset * nAmplitude)); // Move point  
            monstep(); // Progress Monitor
            }
          monend(); // Progress Monitor
          }

    editend();

    // Undo
    undogroupend();

    bChange = false; // Change

    // Done
    bDone = true;
}

// INTERPOLATION

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);     
}

// NOISE

_noiseseed = 1;
_noiseresolution = 512;
_noise = nil;
_noiseoffset = nil;
_noiseperm = nil;

noiseinit
{  
    randomseed(_noiseseed); // Random Seed
    for(iN = 1; iN <= _noiseresolution; iN++)
      {
      _noise[iN] = (random() * 2) - 1; // -1.0..1.0
      _noiseperm[iN] = wrap(1,_noiseresolution,integer(random() * _noiseresolution));
      }

    for(iO = 1; iO <= 64; iO++)
      {
      _noiseoffset[iO] = ;
      }
}

noiseseed: seed
{
    _noiseseed = seed;
    noiseinit(); // Init
}

noiseresolution: resolution
{
    _noiseresolution = resolution;
    noiseinit(); // Init 
}

noiseperm1D: n // i
{
// !    if(_noiseperm == nil){noiseinit();} // Init
    return(_noiseperm[wrap(1,_noiseresolution,integer(n))]);
}

noiseperm2D: v // n
{
    return(noiseperm1D(v.y + noiseperm1D(v.x)));
}

noiseperm3D: v // n
{
    return(noiseperm1D(v.z + noiseperm2D(v)));
}

noise3D: v // n
{
// !    if(_noise == nil){noiseinit();} // Init
    return(_noise[noiseperm3D(v)]);
}

linearnoise3D: v // n
{
    v = wrap(1,_noiseresolution,v); 
    vFrac = frac(v);
    vInt = v - vFrac;
    nA1 = noise3D();
    nA2 = noise3D();
    nA3 = noise3D();
    nA4 = noise3D();
    nA = linear1D(linear1D(nA1,nA2,vFrac.x),linear1D(nA3,nA4,vFrac.x),vFrac.z);
    nB1 = noise3D();
    nB2 = noise3D();
    nB3 = noise3D();
    nB4 = noise3D();
    nB = linear1D(linear1D(nB1,nB2,vFrac.x),linear1D(nB3,nB4,vFrac.x),vFrac.z);
    return(linear1D(nA,nB,vFrac.y));
}

cosinenoise3D: v // n
{
    v = wrap(1,_noiseresolution,v); 
    vFrac = frac(v);
    vInt = v - vFrac;
    nA1 = noise3D();
    nA2 = noise3D();
    nA3 = noise3D();
    nA4 = noise3D();
    nA = cosine1D(cosine1D(nA1,nA2,vFrac.x),cosine1D(nA3,nA4,vFrac.x),vFrac.z);
    nB1 = noise3D();
    nB2 = noise3D();
    nB3 = noise3D();
    nB4 = noise3D();
    nB = cosine1D(cosine1D(nB1,nB2,vFrac.x),cosine1D(nB3,nB4,vFrac.x),vFrac.z);
    return(cosine1D(nA,nB,vFrac.y));
}

fBmnoise3D: v,octaves,persistence // octaves = i | persistence = n (0.25) // n
{
// !    if(_noiseoffset == nil){noiseinit();} // Init
    nNoise = 0.0;
    for(iO = 1; iO <= octaves; iO++)
      {
      nNoise += noise3D(<(v.x + _noiseoffset[iO].x) * (2 * iO),(v.y + _noiseoffset[iO].y) * (2 * iO),(v.z + _noiseoffset[iO].z) * (2 * iO)>) * (persistence / iO);
      }
    return(nNoise);
}

linearfBmnoise3D: v,octaves,persistence // octaves = i | persistence = n (0.25) // n
{
// !    if(_noiseoffset == nil){noiseinit();} // Init
    nNoise = 0.0;
    for(iO = 1; iO <= octaves; iO++)
      {
      nNoise += linearnoise3D(<(v.x + _noiseoffset[iO].x) * (2 * iO),(v.y + _noiseoffset[iO].y) * (2 * iO),(v.z + _noiseoffset[iO].z) * (2 * iO)>) * (persistence / iO);
      }
    return(nNoise);
}

cosinefBmnoise3D: v,octaves,persistence // octaves = i | persistence = n (0.25) // n
{
// !    if(_noiseoffset == nil){noiseinit();} // Init
    nNoise = 0.0;
    for(iO = 1; iO <= octaves; iO++)
      {
      nNoise += cosinenoise3D(<(v.x + _noiseoffset[iO].x) * (2 * iO),(v.y + _noiseoffset[iO].y) * (2 * iO),(v.z + _noiseoffset[iO].z) * (2 * iO)>) * (persistence / iO);
      }
    return(nNoise);
}

// RANDOM

_randomseed = 0; // n Seed

randomseed: seed
{
    _randomseed = seed;
}

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

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

// WRAP

wrap: min,max,n
{
    n = n - floor((n - min) / (max - min)) * (max - min);
    if(n < 0) n = n + max - min; // error check
    return(n);
}
All scripts available at my Google Drive at
https://drive.google.com/open?id=1cR_q2GVUAJHumic1-A3eXV16acQnVTWs

Wednesday, 14 March 2012

LScript - Motion_SpotlightTrick


LScript (Layout) to anti-aliase shadow maps used on Spotlights. It works by implementing an old school technique of spinning (Spinning Light Trick) a light across a frame time inorder to offset sample positions. It helps reduce glitches and improves overall image quality. Apply it to a Spotlight in its Motion Options, enable motion blur and see what happens when you render.

Changes

  • Must have motionblur enabled with more than 1 pass
  • Attach to a spotlight
  • Enable shadow maps

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 - SpotlightTrick

    Motion_SpotlightTrick.ls

*/

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

    // Title
    sTitle = "*Spotlight Trick";

    // Version
    sVersion = "v1.1";

    // Item
    Item = nil;

    // Variable
    bH = false;
    bP = false;
    bB = true;
    nAmount = 360.0;
    nSoftEdge = 0.0;   

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

    // Item
    Item = id; // Item
}

destroy
{
}

process: ma, frame, time
{     
    // Variables
    vPosition = ma.get(POSITION,time);
    vRotation = ma.get(ROTATION,time);
    vnForward = normalize3D(Item.getForward(time));

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

      // Position
      if(nSoftEdge <> 0.0){vPosition -= vnForward * ((10 / Camera().blurLength(time)) * nSoftEdge * n01);} 

      // Rotation
      nDegree = linear1D(0.0,(1 / Camera().blurLength(time)) * nAmount.0,n01);
      if(bH){vRotation.x += nDegree;} // H
      if(bP){vRotation.y += nDegree;} // P
      if(bB){vRotation.z += nDegree;} // B  
      } 

// ma

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

}

// 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));}
}

// VECTOR 3D

magnitude3D: v // n
{
    // Vector
    return(sqrt((v.x * v.x) + (v.y * v.y) + (v.z * v.z)));
}

normalize3D: v // v
{
    // Vector normalize to 0 - 1
    nMagnitude = magnitude3D(v);
    if(nMagnitude <> 0) nMagnitude = 1 / nMagnitude;
    return(v * nMagnitude);
}

load: what,io
{
    if(what == SCENEMODE)   // processing an ASCII scene file
    {
        if(io.read().asStr() == sTitle + " " + sVersion)
            {
            bH = io.read().asInt(); // H
            bP = io.read().asInt(); // P
            bB = io.read().asInt(); // B
            nAmount = io.read().asNum(); // Amount           
            nSoftEdge = io.read().asNum(); // Soft Edge           
            }
    }
}

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

        io.writeln(bH); // H
        io.writeln(bP); // P
        io.writeln(bB); // B
        io.writeln(nAmount); // Amount
        io.writeln(nSoftEdge); // Soft Edge
    }
}

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

    reqbegin(sTitle + " " + sVersion);

    ctrl_c0 = ctlcheckbox("Spin H", bH);
    ctrl_c1 = ctlcheckbox("Spin P", bP);
    ctrl_c2 = ctlcheckbox("Spin B (Antialiase Shadow Map)", bB);
    ctrl_c3 = ctlangle("Amount",nAmount);   
    ctlsep();
    ctrl_c4 = ctlpercent("Soft Edge",nSoftEdge);   

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

    // Refresh
    ctlrefresh(ctrl_c0,"refresh_c0"); // H
    ctlrefresh(ctrl_c1,"refresh_c1"); // P
    ctlrefresh(ctrl_c2,"refresh_c2"); // B
    ctlrefresh(ctrl_c3,"refresh_c3"); // Amount
    ctlrefresh(ctrl_c4,"refresh_c4"); // Soft Edge

    reqopen();
}

refresh_c0:value // H
{
    bH = value;
}

refresh_c1:value // P
{
    bP = value;
}

refresh_c2:value // B
{
    bB = value;
}

refresh_c3:value // Amount
{
    nAmount = value;
}

refresh_c4:value // Soft Edge
{
    nSoftEdge = value;
}


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