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 : "====================================================================="
'--------------------------------------------------------------- ' 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 : "====================================================================="
'--------------------------------------------------------------- ' 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 : "====================================================================="
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