Applying density adjustments per PRT sequence

I have exported (from Houdini) two particle simulations and made multiple instances of them (I forget the Krakatoa terminology for this, is it “partitioning”?), for example:

dust_0.<frames 1-100>.prt
dust_1.<frames 1-100>.prt
dust_2.<frames 1-100>.prt
dust_3.<frames 1-100>.prt
smoke_0.<frames 1-100>.prt
smoke_1.<frames 1-100>.prt
smoke_2.<frames 1-100>.prt

…I’m rendering those together. One thing I’ve found is that if I want to tweak the density of only one of them, I have to regenerate all the prt files (since the global density scale/exponent affects all particles). Is there a way to do this that require reexporting? A feature to load a prt files with applied density controls would be great. Something like:

ri.PointsFile( "dust_0.1.prt", density=2, density_exponent=-1 ) ri.PointsFile( "dust_1.1.prt", density=2, density_exponent=-1 ) ri.PointsFile( "smoke_0.1.prt" )

What would be the recommended workflow at this point? My Krakatoa renders are super fast, but the exporting is slow and I’d love to not have to reexport just to adjust density. Thanks a lot.

To answer your question, no, there is no way to currently scale density on a per-PRT file basis.

The effect you ask for can be achieved in our 3ds Max plugin using our Magma Flow particle manipulation tools (which is part of Krakatoa MX). We are hoping to eventually support Magma Flow inside of Krakatoa SR, however this is not a very high priority and I don’t see it happening very soon.

However, there is one solution that would be simple enough to do. I do not like the solution, but it could be done. I could add an option such as:
ri.Option( “channels”, “DensityScale”, 0.5 )
that would apply to individual groups of particles. I don’t like this idea because it would eventually be deprecated and discarded once Magma has been implemented, and it would be specific only to the “Density” channel. However, if need be I can include this as an (undocumented) option for you if it would help you out a lot.

What are your thoughts?

-Conrad

Actually, we already have channel options such as:
“OverrideColor”
“OverrideEmissionColor”
“OverrideAbsorptionColor”

I would be more inclined to write an “OverrideDensity” (instead of a “ScaleDensity”). Would that be sufficient? It would reset the values in the “Density” channel instead of scaling them.

Krakatoa MX DOES have several ways to SCALE the incoming density of PRT files that does not require Magma.
They are kind of sketchy, but people like them, so I believe strongly that KSR should have the same ability.

First, the Visibility track of the PRT object (PRT Loader, PRT Volume etc) is used as a Scale. Every scene object in 3ds Max has a visibility value and it defaults to 1.0, so it does not change anything by default. It is also animatable, so it is possible to animate the Density scale over time. It is also not limited to the range from 0.0 to 1.0, so Negative Density or Density > 1.0 is possible if the Visibility is keyframed directly in TrackView.

Second, Krakatoa MX uses the Opacity channel of the shader assigned to the object (if any) as a Density Scale. By default the 3ds Max Standard Material has an Opacity of 100% (1.0), so it does not affect the particles unless changed. Note that in early Krakatoa MX versions (around v1.0), that scaling was optional, but we decided to remove the checkbox from the Main Controls UI and make it the default behavior. The beauty of this approach is that in Max, it is also controllable via a texture map or any map tree assigned to the Opacity slot.

Obviously Krakatoa SR does not allow for some of these options, but having both a local Channel Override and a Density Scale would be useful.

Regarding the overrides, I think we were discussing a more general approach where the function would be something like “channelOverride” with a second argument the name of the channel (e.g. “Color”, “Emission”, “Density”, “Absorption”, “Velocity”, “Normal” etc.), and the third argument would be the new value. Like

ri.options ("channelOverride", "Density", 0.123)

This would give us a standard way to specify ANY channel once for all following particles in the given scope in case they don’t have one. Also note that a BIN or PRT file saved from RealFlow can contain a Density channel with a value of 0.0 under certain circumstances, and having a way to override the Density to 1.0 would be vital in that case!

My 2 cents.

After an internal discussion, we feel that we should provide in Krakatoa SR some form of generalized channel operations to cover at least the basics of what Magma can be used for in Krakatoa MX, or mimic some of the above-mentioned Max-specific features.

These operations are:
*Default channel value
*Override channel value
*Copy channel value
*Scale channel value

Default channel value: Normally, when a an external particle stream is missing a channel, Krakatoa assumes a reasonable factory default value. For example, if no Color channel is provided, the default would be [1,1,1]. If no Density is found, the default is 1.0. For Velocity it is [0,0,0] and so on.
The new option would allow you to specify a different default value for the following particle stream(s) than the factory default. We have a special operation right now for providing a default color, but in the future this would be generalized to specify the default for any named channel, so you could make particles without default Velocity default to [0,0,1] instead of [0,0,0] for example.

Override channel value: This would allow you to specify a new value for the incoming particles in the current and nested scopes even if the channel already exists. Right now we provide dedicated Color, Emission and Absorption overrides, the new generalized operation would apply to any arbitrary named channel, including Density (which was the original topic :wink: )

Copy channel value: This would allow you to copy the content of one channel into another. This can be very useful if a channel has a wrong and thus unsupported name, e.g. you have a channel called “Data1” but it actually contains a Color value, so you can specify “Data1” and “Color” as arguments and a new “Color” channel will be created using the values from the “Data1” channel. Another useful case is when you want to do some basic “wiring” of values, for example copy the “Normal” channel into “Color” in order to colorize the particles based on their orientation (an otherwise typical case for a Magma operation).

Scale channel value: This would apply a multiplication with a scalar or vector to the values in an existing channel. This operation would be performed after the above operations, so it would scale the values regardless of their source. In other words, whether the “Color” channel came from the PRT file, from a Default, from an Override or was copied from another channel, it will be multiplied by the given value. So if you wanted to express “Color”=“Normal”*0.5, you could use a Copy channel operation first to clone the Normals into Color, then do a Scale channel by 0.5…

These basic operations would be too primitive compared to the power of the Magma system, but would cover a number of cases that are currently easily solved with Magma in Krakatoa MX but require resaving of particles in Krakatoa SR. We hope that this will be a useful interim solution while working on getting Magma into Krakatoa SR…

Great, thanks for all the thought on this. Your most recent post, Bobo, sounds like it would do what is needed. One question, how would that apply to specific particle sets? Right now I’m doing something like this:

ri.AttributeBegin() ri.PointsFile("dust_0.1.prt") ri.PointsFile("dust_1.1.prt") ri.PointsFile("dust_2.1.prt") ri.PointsFile("smoke_0.1.prt") ri.PointsFile("smoke_1.1.prt") ri.PointsFile("smoke_2.1.prt") ri.AttributeEnd()

Is there a better way to do that? Perhaps with multuple AttributeBegin/End blocks? Or is the above fine? Thanks again.

David

The above is valid, but you can also use multiple Attribute blocks if you want to apply different settings, for example separate transforms, separate color overrides and so on. Each AttributeBegin/End block could be seen as an entity and the channel / transforms etc. apply to the scope of the current block. I assume that in the future you would do something like

ri.AttributeBegin() ri.Option("ChannelScale", "Density", 0.1) ri.PointsFile("dust_0.1.prt") ri.PointsFile("dust_1.1.prt") ri.PointsFile("dust_2.1.prt") ri.AttributeEnd() ri.AttributeBegin() ri.Option("ChannelScale", "Density", 0.5) ri.PointsFile("smoke_0.1.prt") ri.PointsFile("smoke_1.1.prt") ri.PointsFile("smoke_2.1.prt") ri.AttributeEnd()
The above would scale the Density of the dust particles to 1/10th of their original value, and the Smoke to half of the original value. If the file had no Density channel to start with, this will multiply 1.0 by 0.1 and 0.5 respectively, in other words it would be equivalent to a “ChannelOverride” with the same values. But if your PRT files did contain a “Density” channel with a unique per-particle value, it will be scaled correctly per cloud type similar to how the Global Density controls work.

Ah, okay! That makes sense now. :slight_smile: That seems like it would work great.

Hmmm… Makes me want to be able to render to .prt now.

So read in .prts, set/modify/swizzle channels, return new .prts.

You can!

ri.Display( "+output_particles.prt", "file", "points", "LightParticles", True )

Adds a PRT file output. This saves out all the transformed and combined particles after processing to a PRT file. If “LightParticles” is set to True, then it will also compute all the lighting for the particles and include that channel in the output PRT data. The particles will also be in sorted order based on distance to the viewing plane. “LightParticles” is optional parameter which is true by default.

Just a warning that what I posted is our internal plan and is not implemented yet. So don’t try it just yet :wink:

I just built a new version of Krakatoa SR (available here http://forums.thinkboxsoftware.com/viewforum.php?f=116 ).

This version contains commands that will allow you to adjust the “Density” channel on a per-PRT file basis. It also allows you to do a bunch of other channel modifications.

Example of increasing the particle’s Density channel:

ri.AttributeBegin()
ri.ChannelOperation( "Multiply", "Density", 2.5 )
ri.PointsFile( "myparticles.prt" )
ri.AttributeEnd()

Example of using the “Normal” channel as the “Color” channel (Useful for debugging or renaming channels):

ri.AttributeBegin()
ri.ChannelOperation( "Copy", "Color", "Normal" )
ri.PointsFile( "myparticles.prt" )
ri.AttributeEnd()

Example of setting all the particle’s Color channel to red:

ri.AttributeBegin()
ri.ChannelOperation( "Set", "Color", (1,0,0) )
ri.PointsFile( "myparticles.prt" )
ri.AttributeEnd()