Color from different PRT Data Stream?

Not necessarily just color just this example.

Is it possible to get a channel from another PRT Stream?

ie Color from PRT Loader 1 to PRT Loader 2 + KCM Color(PRT Loader 1) to Blend with Color (PRT Loader 2) to Color Channel Out.

Right now, there is no way to pipe data between PRT streams using KCMs. KCMs only operate on the particle stream coming up the stack.
It is of course possible to use MAXScript to read two streams and combine into a new one to write to disk, but it will be a bit slow.
Also, it would be good if both streams contain matching particle counts / IDs.

Ok. Thanks, slow not really an issue, if it is going to take an hour it mine as well take 10 hours. Since once it is written it is written.

So a PRT blending script huh. hmm, might take me a bit to figure that one. Grab channel from loader a and write to spare channel in loader b?

No, grab all channels from Loaders A and B, combine the data and write to a new PRT file sequence.
Basically some code from the PDV combined with some code from the Hair saver example script.
In theory, if the two streams have the same particle counts per frame, you can copy the channels from the second loader into new uniquely-named channels of the new PRT and thus combine the data of both into a single PRT file. Then use a KCM to blend between the one channel and the secondary channel. E.g. have Color and Color2 channels and use a Blend operator to output to Color with any control you like.

Here is an excessive example:

ResetMaxFile #noprompt

--Create two objects to use as sources
Obj1 = Teapot radius:40.528 name:"Teapot01"
Obj2 = Cylinder radius:15.0 height:300 heightsegs:20 pos:[200,0,0] name:"Cylinder01"
addModifier Obj2 (Bend Angle:180)

--Convert both to PRT Volumes
select #(obj1, obj2)
macros.run "Krakatoa" "PRTVolume"
PRTV1 = $PRTVolume_Teapot01_01
PRTV2 = $PRTVolume_Cylinder01_01
PRTV1.VoxelLength = PRTV2.VoxelLength = 1
PRTV1.JitterSamples = PRTV2.JitterSamples = true

--Define a temp, PRT file to output to:
theFile = getDir #temp + "\\_TestCombineChannels.prt"
theOutStream =  KrakatoaParticleOStream theFile #("Position float32[3]", "Color float16[3]", "Position2 float32[3]", "Color2 float16[3]")

--Grab the input streams from both PRT Volumes
theStream1 = FranticParticles.GetPRTObjectIStream PRTV1
theStream2 = FranticParticles.GetPRTObjectIStream PRTV2

--Get the Channel Layouts of both Streams
theChannels1 = theStream1.GetChannels()
theChannels2 = theStream2.GetChannels()

--Find where the Position and Color channels are inside the definitions of both
posIndex1 = findItem (for i in theChannels1 collect i[1]) "Position"
posIndex2 = findItem (for i in theChannels2 collect i[1]) "Position"

colorIndex1 = findItem (for i in theChannels1 collect i[1]) "Color"
colorIndex2 = findItem (for i in theChannels2 collect i[1]) "Color"

--Loop until one of the objects runs out of particles
done = false
while not done do
(
	theData1 = theStream1.readParticle() --get a particle from both streams
	theData2 = theStream2.readParticle()
	if theData1 == undefined or theData2 == undefined then --if either one is empty, stop looping
	(
		done = true
	)
	else --if both are still vald, get the position and color values from both and write to the PRT file
	(
		thePos1 = theData1[posIndex1]
		thePos2 = theData2[posIndex2]
		theColor1 = theData1[colorIndex1]
		theColor2 = theData2[colorIndex2]		
		theOutStream.writeParticle #(thePos1, theColor1, thePos2, theColor2)
	)
)

--Close all in and out streams
theStream1.close()
theStream2.close()
theOutStream.close()

--Zoom extents, then hide the sources and the PRT Volumes
max tool zoomextents
hide #(obj1, obj2, PRTV1, PRTV2)

--Create a PRT Loader and load the file
thePRTLoader = KrakatoaPRTLoader()
thePRTLoader.fileList = #(theFile)
thePRTLoader.fileListFlags = #(3)
thePRTLoader.loadSingleFrame = true
thePRTLoader.percentViewport = 100
select thePRTLoader

--Add a KCM and build a flow to blend the Position channels of both PRT Volumes based on a Float control
macros.Run "Krakatoa" "ChannelModifier"
FranticParticleRenderMXS.openMagmaFlowEditor thePRTLoader.modifiers[1]
KrakatoaChannelEditor_DisplayNodeTreeData[1][3] = #("Position", "float32", 3)
KrakatoaChannelEditor_DisplayNodeTreeData[2][3] = #("Channel", "Position")
KrakatoaChannelEditor_DisplayNodeTreeData[2][4][8] = "Position1"
KrakatoaChannelEditor_DisplayNodeTreeData[2][4][3] = true --selected
KrakatoaChannelsEditor_Functions.updateParentModifier()
KrakatoaChannelNodeEditor_Rollout.addNewOperator type:"Blend" 
KrakatoaChannelNodeEditor_Rollout.addNewInput type:#channel channelName:"Position2" creationType:#keyboard
KrakatoaChannelNodeEditor_Rollout.addNewInput type:#value valueType:#float defaultValue:0.0 creationType:#keyboard
KrakatoaChannelsEditor_Functions.updateParentModifier()

--Animate the Float Input between 0 and 1.0
theController = execute (KrakatoaChannelEditor_DisplayNodeTreeData[5][3][3]+"[2].controller")
theKey = addNewKey theController[1].controller 100
theKey.value = 1
theKey = addNewKey theController[1].controller 0
theKey.value = 0

--A Bend modifier is needed to break the validity, otherwise "Load Single Frame" causes the PRT not to update
theBend = bend()
addModifier thePRTLoader theBend

--Drag the time slider and watch the Teapot turn into a Bent Cylinder!

Very cool! :nerd: Thank you! I like excessive examples :smiley:

Just FYI while I was messing around:
‘ShowInterfaces KrakatoaPRTloader’ only shows:

  Interface: IMtlRender_Compability_MtlBase
   Properties:
   Methods:
   Actions:
OK

also ‘Show KrakatoaPRTLoader’ returns:

No Info Found on: KrakatoaPRTLoader
OK

but select a PRT Loader and ‘Show $’ returns what you would expect (a parameter list).

Something funky is going on:

I had to use:

PRT_Volume pos:[-30,0,0] name:"PRTVolume_Teapot01_01" isSelected:on TargetNode:$Teapot01
PRT_Volume pos:[30,0,0] name:"PRTVolume_Cylinder01_01" isSelected:on TargetNode:$Cylinder01

To get it to function, ‘macros.run “Krakatoa” “PRTVolume”’ seemed to leave the variables PRTV1, PRTV2 ‘undefined’ for some reason ?

Max2011 x64 - Krakatoa 1.6.0.43192

KrakatoaPRTloader does not expose interfaces. It is a Scripted Plugin extending the real PRT Loader. That’s why “show” does not work well on it until you make an instance, so “show $” is the way to go once you make one.

Max 2011 adds 3 digits to the object names by default, so calling macros.run “Krakatoa” “PRTVolume” would have created “PRTVolume_Teapot01_001” instead of “PRTVolume_Teapot01_01”. I forgot people are actually using 2011 :wink:

Aah, ok, I understand.

Max 2011 adds 3 digits to the object names by default

Haha, old habits, it is tough to get used to that! Going to be a lot more try()catch()'s in peoples scripts to keep them backward compatible it seems.

I forgot people are actually using 2011

LOL, somebodies gotta do it, obviously need to use it more to get used to the 3 digits :smiley: My 2010 still has FumeFX 1.2.