The FranticParticles Interface

Available in Krakatoa v1.0.0 and higher

Overview

  • The Krakatoa Renderer does not use the same approach to store properties as most other renderers
  • MAXScript can be used to access all Krakatoa properties, but this requires a better understanding of the underlying properties starage system.

General Krakatoa Renderer Properties

  • Since the Krakatoa Renderer does not use Parameter Blocks to store the majority of its non-animatable settings but a custom string-based system developed by Prime Focus Software, using the standard showProperties() MAXScript inspector methods returns little information.
  • For example:
 renderers.current
 Krakatoa:Krakatoa
 showProperties renderers.current
   .ColorOverrideTexmap : texturemap
   .AbsorptionOverrideTexmap : texturemap
   .EmissionOverrideTexmap : texturemap
   .DensityOverrideTexmap : texturemap
 false
 showInterfaces renderers.current
 OK
  • The texturemap properties returned by the ShowProperties() call represents parameter block tracks used to store the maps assigned to the Global Render Values overrides.
  • To get to all Krakatoa Renderer properties, you will have to use the same methods employed by the Krakatoa Renderer GUI
  • These methods are exposed by the FranticParticles interface available when Krakatoa is assigned as the current renderer.

The FranticParticles Interface Properties and Methods

  • The Krakatoa Renderer exposes a Function Publishing Interface called “FranticParticles” which provides Properties and Methods that can be used to access the renderer via MAXScript.
  • The following is the description of all currently available Properties and Methods - you can call ‘showInterface FranticParticles’ to list them in the MAXScript Listener.

Interface: FranticParticles

Properties:

.RenderOutputFiles : value : Read

  • Returns the render output file based on the file name specified in the 3ds Max Render Scene Dialog.

.Version : value : Read

  • Returns the version string of the current Krakatoa plug-in, for example “1.1.0.31392” The first digit is the major release number, followed by a minor version number and update number. The last 5 digit number is the internal version control system iteration. This iteration number is shared among all Thinkbox applications, so based on it is possible to tell whether a version of Krakatoa was built before or after a specific version of Deadline for example.

.KrakatoaHome : value : Read

  • Returns the home (installation) directory of Krakatoa,
  • for example

“C:Program Files (x86)ThinkboxKrakatoa”

NOTE: The home directory of Krakatoa is resolved by the MaxKrakatoa.dlr plug-in as follows:

  • The plug-in queries the path it was loaded from, then moves up two folders and returns the result as the KrakatoaHome path.
  • So if the plug-in was loaded from “C:Program FilesThinkboxKrakatoa MX3dsMax2015”, the path is resolved as the root of this path minus the last folder, “C:Program FilesThinkboxKrakatoa MX”.
  • If you want to move your Krakatoa MX installation into another directory structure, you should still make sure that the MaxKrakatoa.dlr file is located one directory deeper than the folder containing the Icons and Scripts sub-folders!

.MaxDebuggerIterations : integer : Read|Write

  • Get/set the number of Magma Debugger iterations.
  • This value is exposed in the Debug menu of the Magma Editor and defaults to 10,000.

.PopupLogWindowOnMessage : bool : Read|Write

  • Get/set whether the Log Window will automatically pop up when a message is output to it.
  • Default is false.

.LogWindowVisible : bool : Read|Write

  • Get/set whether the Log Window is currently open.
  • Default is false.
  • Setting this property to true opens the Log Window, setting it to false closes it.

Methods:

<void> AddProperty <value>PropertyName <value>Value

  • This method adds a new property with the given name and initial value to the Krakatoa Renderer. You can add any number of uniquely named properties to the Krakatoa Renderer, even if the Renderer itself would not understand them. These properties can contain arbitrary values and will be stored in the Renderer object with the Max scene.

<void> SetProperty <value>PropertyName <value>Value

  • This method sets the value of an already defined property with the given name to the specified value.
  • The value will be converted to a string internally.

<value> GetProperty <value>PropertyName

  • This method returns the value stored in the given named property as a string.
  • For example:
 FranticParticles.getProperty "MotionBlurSegments"
 "3"
 FranticParticles.getProperty "UseDepthMaps"
 "true"

<integer> GetIntProperty <value>PropertyName

  • This method returns the value stored in the given named property as an integer, assuming the value stored in it was an integer.
  • If the value was not an integer, a runtime error will be reported.
  • For example:
 FranticParticles.getIntProperty "MotionBlurSegments"
 3
 FranticParticles.getIntProperty "UseDepthMaps"
 -- Runtime error: Integer Property "UseDepthMaps" had invalid value "true"

<float> GetFloatProperty <value>PropertyName

  • This method returns the value stored in the given named property as a float.
  • If the stored value is an integer, it will be converted and returned as float.
  • If it was not an integer or a float, a runtime error will be reported.
  • For example:
 FranticParticles.getFloatProperty "DepthOfFieldSampleRate" --this is a float value
 0.1
 FranticParticles.getFloatProperty "MotionBlurSegments" --this is an integer value
 3.0
 FranticParticles.getFloatProperty "UseDepthMaps" --this is a boolean value
 -- Runtime error: Float Property "UseDepthMaps" had invalid value "true"

<bool> GetBoolProperty <value>PropertyName

  • This method returns the value stored in the given named property as a boolean value, assuming the value stored in the property is a boolean value.
  • Otherwise, a runtime error will be reported.
  • For example:
 FranticParticles.getBoolProperty "UseDepthMaps"
 true
 FranticParticles.getBoolProperty "MotionBlurSegments"
 -- Runtime error: Bool Property "MotionBlurSegments" had invalid value "3"

<bool> HasProperty <value>PropertyName

  • This method returns true if the given named property exists in the renderer.

<void> InvalidateParticleCache ()

  • This method invalidates the Particle Cache and the Lighting Cache and releases the memory used by both.

<void> InvalidateLightingCache ()

  • This method clears the Lighting Cache only.
  • The memory is not released because the Particle Cache always allocates both caches.

<float> GetCacheSize ()

  • This method returns the Particle Cache size in Megabytes.

<value> GetPRTObjectIStream <node>PRTObject

  • This method returns the Particle Stream from the top of the specified object’s stack.
  • The stream will represent the render-time particle data after applying all modifiers, transforms and world space modifiers.

<value> CreateParticleOStream <value>Filename <value>Channels

  • Updated in v2.2: This method creates a Particle Output Stream.
  • The file name extension will determine the file type to be written - PRT, CSV or BIN.
  • The returned KrakaotaParticleOStream MixinInterface provides methods for writing particle data and closing the stream.

<bool> SaveParticleObjectsToFile <node array>Nodes <value>Filename <value>Channels

  • This method saves the particle objects specified by the first argument to the file name specified by the second argument.
  • The third argument defines the channels to be saved. If it passed as empty array #(), all channels available in the particle objects will be saved automatically.
  • When specifying channels, each element of the array is a string containing the name of the channel and its type and arity, e.g. “Position float32[3]”
FranticParticles.SaveParticleObjectsToFile #($PRT_Hair001) "c:\\temp\\somehair_0000.prt" #("Position float32[3]","Normal float16[3]","Tangent float16[3]")
true

<value> ReplaceSequenceNumberWithHashes <value>FileName

  • This method replaces a sequence number with #### in the file name passed as argument and returns a new file name.
  • For example:
FranticParticles.ReplaceSequenceNumberWithHashes "c:\\temp\\test0001.tga"
"c:\temp\test####.tga"

<value> ReplaceSequenceNumber <value>FileName <integer>Frame

  • This method replaces a sequence number with the correct sequence number based on the given frame and returns a new file name.
  • If the file does not contain a frame number yet, it will be added.
  • If it contains an existing frame number, the existing format will be preserved.
  • For example:
 FranticParticles.ReplaceSequenceNumber "c:\\temp\\test0001.tga" 4
 "c:\temp\test0004.tga"
 FranticParticles.ReplaceSequenceNumber "c:\\temp\\test_.prt" 42
 "c:\temp\test_0042.prt"
 FranticParticles.ReplaceSequenceNumber "c:\\temp\\test_00000.bin" 123
 "c:\temp\test_00123.bin"

<value> MakePartitionFilename <value>Filename <integer>Index <integer>Count

  • This method adds the Particle Partition signature used by Krakatoa to the filename provided as first argument.
  • The second argument is the partition number, the third argument is the total partitions count.
  • For example:
FranticParticles.MakePartitionFilename "c:\\temp\\test0001.tga" 3 10
"c:\temp\test_part3of10_0001.tga"

<int array> GetPartitionFromFilename <value>Filename

  • This method returns a two-element array containing the partition number and the total partitions count according to the Particle Partition signature in the file name.
  • If the signature is missing, the array will contain two zero values.
  • For example:
 FranticParticles.GetPartitionFromFilename "c:\\temp\\test_part3of10_0001.tga"
 #(3, 10)
 FranticParticles.GetPartitionFromFilename "c:\\temp\\test0001.tga"
 #(0, 0)

<value> ReplacePartitionInFilename <value>Filename <integer>Index

  • This method replaces the partition number in the file name signature with a new number, provided the Partition signature exists.
  • Otherwise, the file name will not be modified.
  • For example:
 FranticParticles.ReplacePartitionInFilename "c:\\temp\\test_part3of10_0001.tga" 5
 "c:\temp\test_part5of10_0001.tga"
 FranticParticles.ReplacePartitionInFilename "c:\\temp\\test0001.tga" 5
 "c:\temp\test0001.tga"

<value> GetFileParticleChannels <value>File

  • This method returns all channels saved in the specified particle file (PRT, CSV or BIN file).

<value> GetFileParticleCount <value>File

  • Returns the number of particles saved in the given file.
  • Returns -1 if the file is of CSV type since the count cannot be queried directly.
  • Returns undefined if the file cannot be read or does not exist.
  • For example:
 FranticParticles.GetFileParticleCount "c:\\temp\\nonexistentfile.prt"
 undefined
 FranticParticles.GetFileParticleCount "c:\\temp\\test100K_0001.prt"
 100000
 FranticParticles.GetFileParticleCount "c:\\temp\\test10K_00001.bin"
 10000
 FranticParticles.GetFileParticleCount "c:\\temp\\test10K_0001.csv"
 -1

<value> GetRenderParticleChannels ()

  • This method returns the particle channels currently required by the Renderer to perform the desired rendering operations as an array of arrays where each sub-array consists of the channel name, type and arity.
  • For example:
 franticParticles.GetRenderParticleChannels()
 #(#("Position", "float32", 3), #("Color", "float16", 3),
 #("Lighting", "float16", 3), #("Density", "float16", 1))

<value> GetCachedParticleChannels ()

  • This method returns the particle channels currently in the particle cache as an array of arrays where each sub-array consists of the channel name, type and arity.
  • If a channel returned by GetRenderParticleChannels() is NOT in the resulting array, Krakatoa will have to rebuild the cache even if it is enabled (yellow state)

<integer> GetCachedParticleCount ()

  • This method returns the number of particles currently in the cache.

<value> DebugEvalKCM <node>Node <maxObject>Modifier <value>TestParticle

  • This method evaluates the MagmaFlow defined in the specified scene node and its modifier using the particle data provided by the third argument.
  • The particle data is an array of arrays where each sub-array defines a particle data channel and a value type.

<void> LogError <value>Msg

  • Outputs the message string given as argument as an Error to the Krakatoa Log Window.

<void> LogWarning <value>Msg

  • Outputs the message string given as argument as a Warning to the Krakatoa Log Window.

<void> LogProgress <value>Msg

  • Outputs the message string given as argument as a Progress info to the Krakatoa Log Window.

<void> LogStats <value>Msg

  • Outputs the message string given as argument as a Statistics entry to the Krakatoa Log Window.

<void> LogDebug <value>Msg

  • Outputs the message string given as argument as a Debug message to the Krakatoa Log Window.

<bool> SaveHairFile <bool>SaveWholeSceneHairAndFur <node>SaveSingleObjectSplineNode <value>Filename <integer>FrameStart <integer>FrameEnd

  • This method saves the the spline definition of a single object or all Hair objects in the scene to a file based on the PRT specification.
  • The fourth and fifth arguments define the start and end time to export.
  • This is meant mainly for hair export to Krakatoa SR (Stand-alone) which can generate particles on the fly the same way PRT Hair works in 3ds Max.
  • Thus, a small file describing the splines can be passed to the external renderer and generate any number of particles on the fly, thus reducing disk space usage.
  • When the first argument is true (saving all Hair splines), the second argument should be passed as undefined.
 FranticParticles.SaveHairFile true undefined "c:\\temp\\hairdata.prt" animationRange.start animationRange.end
 OK
 FranticParticles.SaveHairFile false $Circle001 "c:\\temp\\circledata.prt" 0 0
 OK

Examples

Switching Krakatoa To Save Mode

  • The following code switches Krakatoa to Save Particles To File Sequence mode, sets the output path to a custom location, sets the time range and calls the renderer:
 FranticParticles.SetProperty "ParticleMode" "Save Particles To File Sequence" --switch to save particles mode
 FranticParticles.SetProperty "ParticleFiles" "c:\\temp\\particles\\myParticles_.prt" --set the save path
 renderSceneDialog.close() --close the render scene dialog to be able to make changes to it
 rendTimeType = 2 --switch to Active Time Segment mode
 max quick render --"press" the Render button to start rendering

Saving Sub-Frames From Particle Flow

  • The following script performs sub-sampling of the scene particles, producing more frames than the current segment contains.
  • It uses the ability of the 3ds Max renderer to accept floating point times as sub-frame samples, saves particle files to disk and then renames them to a custom counter.
  • In this particular example, the script saves 4 frames per frame from 0.0 to 100.0, thus producing actual files from 0 to 400 that contain a time-scaled version of the particle animation.
  • The final result is slightly more precise than rescaling a regular 101 frames animation using PRT Loader’s Playback Graph because each sub-sample will contain a more precise position and velocity value based on actual Particle Flow data.
(
 local start = 0.0 --this is the first frame
 local end = 100.0 --this is the last frame
 local step = 4 --this is the number of samples per frame
 local cnt = start as integer --this is the counter for the current frame number
 local theParticleFileName =  (FranticParticles.GetProperty "ParticleFiles") --get the output PRT file name
 FranticParticles.SetProperty  "Presets:SaveRenderHistory" "false" --disable history saving to speed it up
 for t = start to end by (1.0/step) do --loop from start frame to end frame with the given step
 (
   --figure out what the saved file will be called:
   local theFileName = FranticParticles.ReplaceSequenceNumber theParticleFileName ((floor t) as integer)
   deleteFile theFileName --make sure it does not exist yet
   render frame:t vfb:off --call the renderer at a sub-frame to save a PRT with full frame
   if doesFileExist theFileName do --if it was found,
   (
     --grab the base file name, then build the new file name with suffix SubFrame_ :
     local theBaseFile = (getFileNameFile theFileName)
     local targetFilename = getFileNamePath theFileName
     targetFilename += substring theBaseFile 1 (theBaseFile.count-4)
     targetFilename += "SubFrame_" + getFileNameType theFileName
     --set the target frame number based on the integer counter stored in cnt:
     targetFilename = FranticParticles.ReplaceSequenceNumber targetFilename cnt
     deleteFile targetFilename --make sure it does not exist before saving over it
     renameFile theFileName targetFilename --rename the saved file to the new file name
   )
   cnt+=1 --increment the integer frame counter by one
 )--end t loop
)--end script