Coding the Particle Simulation Workflow

' Start off with a fresh scene
NewScene, false

dim oEmitter ' the emitter object
dim oEParams ' for emitter parameters

dim oPCloud ' particle cloud
dim oStack ' for the cloud's construction history
dim o     ' for particle operator while enumerating
dim oPParams ' for the particle operator parameters

dim sBilly ' to store the parameter string expression for the billboard shader
dim sPammy ' to store the parameter string expression for the color shader



'==============================================================================
'
'  HELPER FUNCTIONS & SUBROUTINES
'
'==============================================================================
sub updateParamValue( in_obj, in_val )
   ' Fix the name
   dim sName
   sName = prettyUpTheName( in_obj )

   ' Check to see whether the parameter object was passed in.
   if TypeName( in_obj ) = "Parameter" then
       ' Print the value for this parameter as is
       LogMessage sName & " = " & in_obj.Value & " (before)"

       ' Set the new value for this parameter
       in_obj.Value = in_val

       ' Reprint the new value just to verify that it was changed
       LogMessage sName & " = " & in_obj.Value & " (after)"
   else
       ' If not, it must be a particle type parameter so use a
       ' string expression instead.
       LogMessage sName & " = " & GetValue( in_obj ) & " (before)"

       ' Set the new value for this parameter
       SetValue in_obj, in_val

       ' Reprint the new value just to verify that it was changed
       LogMessage sName & " = " & GetValue( in_obj ) & " (after)"
   end if

   LogMessage "==============================================================="
end sub


function prettyUpTheName( in_obj )
   ' This manipulation is cosmetic only: it's easier to read the simple
   ' parameter name than the whole path
   dim sRawName ' to hold name
   dim aPcs ' array for string manipulation

   ' Check to see whether the parameter object was passed in. If so,
   ' get its FullName. Otherwise, use the parameter string expression
   if TypeName( in_obj ) = "Parameter" then
       sRawName = in_obj.FullName
   else
       sRawName = in_obj
   end if

   aPcs = Split( sRawName, ".", -1, vbTextCompare )
   prettyUpTheName = aPcs( UBound( aPcs ) )
end function

Set up the particle cloud and the emitter

'---------------------------------------------------------------
' STEP 1: Select an emitter object and create a particle cloud
'---------------------------------------------------------------
' Create a grid that will be the emitter
set oEmitter = ActiveSceneRoot.AddGeometry( "Grid", "MeshSurface", _
       "ParticleEmitter" )

' Create the particle cloud
CreateParticleCloud

' You can find an existing particle cloud in the scene by using
' the FindChild method on the scene root and then asking it to look
' for the first instance of a member of the particle family.
' Alternatively, if you know the cloud is selection, you can get
' it from the Selection object (ie., set oPCloud = Selection(0) )
set oPCloud = ActiveSceneRoot.FindChild( ,, siParticleFamily )

' Set the grid as the emitter object
AddParticleEmitter oPCloud, oEmitter

' Now that the particle cloud is set up, tweak some values on
' the particle operator itself. Notice that you can use the construction
' history to get at the particle op from the selected cloud
set oStack = oPCloud.ActivePrimitive.ConstructionHistory

' Enumerate through the construction history to find the particle operator
for each o in oStack
   if o.name = "ParticlesOp" then
       ' Grab the parameter collection from one I want when I find it
       ' and exit the loop
       set oPParams = o.Parameters
       exit for
   end if
next

' Now you can use the parameter collection to access the particular
' parameter you want to get or set
updateParamValue oPParams( "Duration" ), 70
updateParamValue oPParams( "Offset" ), 2
updateParamValue oPParams( "ExecMode" ), 1
updateParamValue oPParams( "Seed" ), 7
updateParamValue oPParams( "numberofinterframe" ), 3

' This section outputs the following to the script editor history pane:
'INFO : "Duration = 99 (before)"
'INFO : "Duration = 70 (after)"
'INFO : "====================================================================="
'INFO : "Offset = 1 (before)"
'INFO : "Offset = 2 (after)"
'INFO : "====================================================================="
'INFO : "ExecMode = 1 (before)"
'INFO : "ExecMode = 1 (after)"
'INFO : "====================================================================="
'INFO : "Seed = 0 (before)"
'INFO : "Seed = 7 (after)"
'INFO : "====================================================================="
'INFO : "numberofinterframe = 2 (before)"
'INFO : "numberofinterframe = 3 (after)"
'INFO : "====================================================================="

Modify the particle emission

'---------------------------------------------------------------
' STEP 2: Set up the way the particles are emitted.
'---------------------------------------------------------------
' Get the emission parameter set and tweak its values, Notice how
' you get the parameter you want from the parameter collection off
' the "ParticleEmitter_emission" property on the emitter object.
' You can find which property and parameter name to ask for by
' using the "Show > Use Script Names" and "All + Animatable Params"
' options in the explorer.
set oEParams = oEmitter.Properties( "ParticleEmitter_emission" )

updateParamValue oEParams.Parameters( "Spread" ), 5
updateParamValue oEParams.Parameters( "SpreadVar" ), 2
updateParamValue oEParams.Parameters( "Generation" ), 4
updateParamValue oEParams.Parameters( "Speed" ), 10
updateParamValue oEParams.Parameters( "SpeedVar" ), 1

' This section outputs the following to the script editor history pane:
'INFO : "Spread = 0 (before)"
'INFO : "Spread = 5 (after)"
'INFO : "====================================================================="
'INFO : "SpreadVar = 0 (before)"
'INFO : "SpreadVar = 2 (after)"
'INFO : "====================================================================="
'INFO : "Generation = 2 (before)"
'INFO : "Generation = 4 (after)"
'INFO : "====================================================================="
'INFO : "Speed = 5 (before)"
'INFO : "Speed = 10 (after)"
'INFO : "====================================================================="
'INFO : "SpeedVar = 0 (before)"
'INFO : "SpeedVar = 1 (after)"
'INFO : "====================================================================="

Create a particle type

'---------------------------------------------------------------
' STEP 3: Define the particles' physical properties
'---------------------------------------------------------------
' Create a new type using the billboard surface shader and adjust
' it. Notice that the type parameters are not accessible through
' the object model so you have to use the SetValue command to
' change its parameter values with a parameter string expression
CreateParticleType siBillboardType, sBilly

updateParamValue sBilly & ".Viscosity", 0.1
updateParamValue sBilly & ".ViscosityCtrl", 1
updateParamValue sBilly & ".SurfTension", 2
updateParamValue sBilly & ".SurfTensionCtrl", 1
updateParamValue sBilly & ".SurfTensionVar", 5
updateParamValue sBilly & ".Red", 0.156

' Now associate the new particle type with the particle cloud
SetParticleType oCloud, sBilly

' This section outputs the following to the script editor history pane:
'INFO : "Viscosity = 0.07 (before)"
'INFO : "Viscosity = 0.1 (after)"
'INFO : "====================================================================="
'INFO : "ViscosityCtrl = 0 (before)"
'INFO : "ViscosityCtrl = 1 (after)"
'INFO : "====================================================================="
'INFO : "SurfTension = 0 (before)"
'INFO : "SurfTension = 2 (after)"
'INFO : "====================================================================="
'INFO : "SurfTensionCtrl = 0 (before)"
'INFO : "SurfTensionCtrl = 1 (after)"
'INFO : "====================================================================="
'INFO : "SurfTensionVar = 0 (before)"
'INFO : "SurfTensionVar = 5 (after)"
'INFO : "====================================================================="
'INFO : "Red = 1 (before)"
'INFO : "Red = 0.156 (after)"
'INFO : "====================================================================="

Apply shaders to the particles

'---------------------------------------------------------------
' STEP 4: Apply shaders to create the final look
'---------------------------------------------------------------
' Attach the particle color shader to the input node of the billboard
' particle shader and tweak it
sPammy = sBilly & ".Particle_Billboard"
CopyPaste , "Shaders\Texture\Particle\Particle_Color.Preset", _
       "TransientObjectContainer"
SIConnectShaderToCnxPoint "TransientObjectContainer.Particle_Color", _
       sPammy & ".Particle_Shape.Input"

updateParamValue sPammy & ".Shape", 2
updateParamValue sPammy & ".ColorBurn", 0.582
updateParamValue sPammy & ".AmbientType", 1
updateParamValue sPammy & ".Ambient.red", -5
updateParamValue sPammy & ".Ambient.green", -5
updateParamValue sPammy & ".Ambient.blue", -5

' This section outputs the following to the script editor history pane:
'INFO : "ParTypes.PType1"
'INFO : "ParTypes.PType1.Particle_Billboard"
'INFO : "Shape = 0 (before)"
'INFO : "Shape = 2 (after)"
'INFO : "====================================================================="
'INFO : "ColorBurn = 0 (before)"
'INFO : "ColorBurn = 0.582 (after)"
'INFO : "====================================================================="
'INFO : "AmbientType = 2 (before)"
'INFO : "AmbientType = 1 (after)"
'INFO : "====================================================================="
'INFO : "red = 0.1 (before)"
'INFO : "red = -5 (after)"
'INFO : "====================================================================="
'INFO : "green = 0.1 (before)"
'INFO : "green = -5 (after)"
'INFO : "====================================================================="
'INFO : "blue = 0.1 (before)"
'INFO : "blue = -5 (after)"
'INFO : "====================================================================="

Working without an Emitter

You can also create particle clouds from scratch (without the need of an emitter). The basic workflow is as follows:

1. Create a particle type.

2. Create a new particle cloud based on the type you just created.

3. Add particles to the new particle cloud.

4. Specify values for any parameters on the particles as desired.

Here's a script that creates a "particle lattice" as an example:

sub ParticleLattice( _
          iDimX, iDimY, iDimZ, _
          iSpanX, iSpanY, iSpanZ, _
          iAgeLimit, _
          dDither _
   )
   ' Define a new particle type with the billboard shader applied by default
   set oParTypeCol = CreateParticleType()

   ' Create a new particle cloud based on the type just defined
   set oParticleCloud = ActiveSceneRoot.AddParticleCloud( _
          oParTypeCol, "Number_9" )

   ' Add some particles to it based on the X, Y, Z passed in and using the
   ' same particle type. First we need the cloud's primitive before we can
   ' add particles or get the particles collection
   set oCloudPrimitive = oParticleCloud.ActivePrimitive
   oCloudPrimitive.AddParticles ( iDimX + 1 ) * ( iDimY + 1 ) * ( iDimZ + 1 ), _
          oParTypeCol(0)

   ' Get the collection of particles
   set oParticleCollection = oCloudPrimitive.Particles

   ' Create a SIVector3 (math) object that will hold each particle's position
   set oPosition = XSIMath.CreateVector3

   ' Set the position and age limit for each particle
   for i = 0 to iDimX
       for j = 0 to iDimY
          for k = 0 to iDimZ
              iIndex = i * ( iDimZ + 1 ) * ( iDimY + 1 ) + j * ( iDimZ + 1 ) + k
              set oParticle = oParticleCollection( iIndex )
              oPosition.x = i * iSpanX + ( Rnd( 432227 ) -0.5 ) * 2 * dDither
              oPosition.y = j * iSpanY + ( Rnd( 432227 ) -0.5 ) * 2 * dDither
              oPosition.z = k * iSpanZ + ( Rnd( 432227 ) -0.5 ) * 2 * dDither
              oParticle.Position = oPosition
              oParticle.AgeLimit = iAgeLimit
          next
       next
   next
end sub


' Run the script
ParticleLattice 10, 10, 10, 2, 3, 4, 100, 0.2