Here’s the result of my endeavor last week–its a scene with cells populated by lipids. In reality, each cell has about 5 billion on the surface, but here each cell is 50K lipids. There are 25 cells in this scene. RAM usage was around 4GB. Rendertime was about 20min/frame. Heavy use of Krakatoa to populate and clone.
I want to implement the multi material to get some lipid variation. Also plan on getting them to spin on their pole axis.
The big green shapes or D2 receptors and proteins would need to lock and dock to. Is there maxscript access to get the position of a PRT particle that I could put into a position expression on a dummy object?
It’ll also be interesting to do a single cell and see how many lipids I can cram on there. I’m saving to PRT via keep apart and with that many particles it takes a while to save out. dynamic_lipid_surface.mp4 (1.78 MB)
Is there scripting capability to retrieve the position of a particle loaded from a PRT loader? Something like PRTLOader.getParticlePos int
I need to link a dummy to a particle.
There is particle data access from both PRT files, and PRT objects (all of them, not just PRT Loader). However, due to the streaming nature of the beast, the access is not random, but sequential. However, there is a function to skip to particle N, so if you are interested in the Nth by index, it would be rather fast. But looking for a particle with a specific ID would require looping through all particles until you find it, and it would be rather slow.
The alternative would be to bake keyframes for your object instead of doing it dynamically.
I just set up a scripted controller in an object that moves two (or any number of) other objects to specific indices in the particle cloud. It works. but if you prefer to just run a script once that bakes the position to keyframes, and you don’t change the underlying motion often, that would be even easier to script.
macroScript BakeObjectTransformsFromPRT category:"Krakatoa Tools"
(
global BakeObjectTransformsFromPRT_Rollout
try(destroyDialog BakeObjectTransformsFromPRT_Rollout)catch()
rollout BakeObjectTransformsFromPRT_Rollout "Bake Object Transforms To PRT"
(
local thePRTTarget = undefined
local theSourceObject = undefined
fn pickPRT obj = (
local theInt = FranticParticles.GetPRTObjectIStream obj false false
if theInt != undefined then
(
theInt.close()
true
)
else false
)
pickbutton btn_PRTSystem "Target PRT Object" width:200 align:#center filter:pickPRT autoDisplay:true
pickbutton btn_objectToBake "Source Object To Bake" width:200 align:#center autoDisplay:true
spinner spn_targetIndex "Target Index:" range:[1,1000,1] type:#integer fieldwidth:50 align:#right
checkbox chk_orientByNormal "Align Z to Normal" checked:false
button btn_bake "BAKE!" width:200 height:30 align:#center
on btn_PRTSystem picked obj do
(
if obj != undefined do
(
thePRTTarget = obj
local theInt = FranticParticles.GetPRTObjectIStream thePRTTarget true false
spn_targetIndex.range = [1,theInt.getCount(),spn_targetIndex.value]
theInt.close()
)
)
on btn_objectToBake picked obj do if obj != undefined do theSourceObject = obj
on btn_bake pressed do
(
local theInt = FranticParticles.GetPRTObjectIStream thePRTTarget true false
local theChannels = theInt.getChannels()
local posIndex = 0
for i = 1 to theChannels.count where matchPattern theChannels[i] pattern:"Position *" do posIndex = i
local normalIndex = 0
for i = 1 to theChannels.count where matchPattern theChannels[i] pattern:"Normal *" do normalIndex = i
theInt.close()
if posIndex > 0 do
(
local targetParticleIndex = spn_targetIndex.value
for t = animationRange.start to animationRange.end do
(
at time t with animate on
(
local theInt = FranticParticles.GetPRTObjectIStream thePRTTarget true false
if targetParticleIndex <= theInt.getCount() do
(
theInt.skipParticles (targetParticleIndex-1)
local theParticle = theInt.readParticle()
theSourceObject.pos = theParticle[posIndex]
if chk_orientByNormal.checked and normalIndex > 0 do
(
local theNormal = theParticle[normalIndex]
local upVector = [0,0,1]
if theNormal == [0,0,1] do upVector = [1,0,0]
theX = normalize (cross theNormal upVector )
theY = normalize (cross theX theNormal)
theSourceObject.transform = matrix3 theX theY theNormal theParticle[posIndex]
)
)
theInt.close()
)
)
)
)
)--end rollout
createDialog BakeObjectTransformsFromPRT_Rollout 220 140
)--end script
I could expand it to work by ID if you want, should be trivial, but it will make it slower as it would have to loop through all particles until it finds the ID. Now it just skips the first N-1 particles and reads the Nth.