[Closed] Change Particle material ID by bitmap
Hi, I’m trying to set the pflow particles Material ID by using a black and white map. The pflow setup is simple, just a position object, shape and a Material static.
This script checks the bitmap’s pixel base on its position. If the pixel color is black it will assign it to particleIndex 1 . And after that setParticleMtlIndex for particleIndex 1 to material ID 1. But I can’t seem to get it to work.
on ChannelsUsed pCont do
(
pCont.usePosition = true
pCont.useMtlIndex = true
)
on Init pCont do
(
)
on Proceed pCont do
(
count = pCont.NumParticles()
theBitmap =openBitmap $Plane01.material.diffusemap.filename --get emitter's diffusemap
for i in 1 to count do
(
AAA = pCont.particlePosition.x as integer
BBB = pCont.particlePosition.y as integer
thePixels =getPixels theBitmap [AAA ,(theBitmap.height- BBB)] 1
if thePixels != undefined then
(
if thePixels [1] ==(color 255 255 255) then pCont.particleIndex = 1
else if thePixels [1] ==(color 0 0 0) then pCont.particleIndex = 2
else pCont.particleIndex = 3
)
pCont.setParticleMtlIndex 1 1
pCont.setParticleMtlIndex 2 2
pCont.setParticleMtlIndex 3 3
)
)
on Release pCont do
(
)
Any idea what’s wrong with it? Thanks in advance for any reply
I am not sure I can follow.
particleIndex is used to determine which particle you are dealing with. The for loop is supposed to go through all particles in your system and execute the pixel check for each one of them. But you never do that. You are actually asking for the position of the particle before telling the system WHICH particle you want to work with. You would have to set
pCont.particleIndex = i
before calling pCont.particlePosition in order to get the position of the particle with index i.
Am I missing something in your logic?
http://www.scriptspot.com/bobo/
Have a look at Bobo’s inherit emmitter colour script. His script doesn’t look at the bitmap value as such, but uses the UVs instead, which is useful for when you want to change the bitmap.
You may be able to use his code to make yours work, the problem with your code lies in not having a co-ords system linking the two. Particleposition.x and y are going to be in World space, not linked to your bitmap. You might be best to work on Bobo’s principle of having a plane to do an intersection test on, then if you really want, apply the GetPixel code to get the RGB value, would be interested if you get this to work.
Hi Dave,
Thanks for your reply, I have seen Bobo’s inherit emmitter colour script before I wrote my code but i choose to write it this way because
a) I need to change the material ID or the particles not the color from the diffuse slot only.
b) The scene is quite big and the particles are all instance shape of mid res poly objects. I think that creating a temp Editable_Mesh and caculating the rays will slow down the scene a lot.
I know that using world space position to calculate local space bitmap is not the best idea but the emitter objects is a plane and the main thing I require is speed. I did get the script to work in a box array so I think changing to work on particles shouldn’t be a problem just that I’m not sure how particleIndex and setParticleMtlIndex works.
Works only on Box with Material modefier array. Array must be placed in positive world space
theBitmap =openBitmap $Plane01.material.diffusemap.filename
for o in $Box* do
(
AAA = o.pos.x as integer
BBB = o.pos.y as integer
thePixels =getPixels theBitmap [AAA ,(theBitmap.height- BBB)] 1
print thePixels [1]
if thePixels != undefined then
(
if thePixels [1] == (color 0 0 0) then o.modifiers[#Material].materialID = 1
else o.modifiers[#Material].materialID = 2
)
)
Ok I see what you’re doing now, but even if you position the object so the corner is at 0,0,0 the particle’s positions are in world space, which might not equal pixels? Or have you got it set up so say if you image is 500pixels wide the object is 500 units wide? If so you might need to round up to an integer for this to work?
Can you upload a test scene so I can attempt to get it to work?
Yes, the array total size is based on the image’s size. Essentially it will look like a pixel art effect. Currently the position is already changed to integer and its working in “Change ObjMatID.max” but i need to transfer the same effect onto particles.
http://www.adamleecg.com/images/Change%20MatID.zip
Thanks for your help!
Makes sense to me! Bobo is right you’ve got an i loop for the count but don’t choose which particle you want to affect.
Here is the fixed script:
on ChannelsUsed pCont do
(
pCont.usePosition = true
pCont.useMtlIndex = true
)
on Init pCont do
(
)
on Proceed pCont do
(
count = pCont.NumParticles() --get particle count
theBitmap =openBitmap $Plane01.material.diffusemap.filename --get diffuse map
for i in 1 to count do --loop through all particles
(
pCont.particleIndex = i --set current particle
thePos = pCont.particlePosition --get particle position
--get the pixel under the particle
thePixels = getPixels theBitmap [thePos.x as integer, (theBitmap.height - (thePos.y as integer))] 1
if thePixels[1] != undefined then --if the 1st VALUE is undefined (not thePixels itself)
(
if thePixels[1].v > 200 then --if pixel value is more than 200 (change if you want!)
pCont.setParticleMtlIndex i 1 --use first sub-material
else
pCont.setParticleMtlIndex i 2 --otherwise use second
)
else
pCont.setParticleMtlIndex i 3 --if particle outside of image, use third sub-material
)--end i loop
)--end on
on Release pCont do
(
)
Damnit Bobo I thought I was going to be the first one who solved it for once!.. 🙁
Here’s my solution based on your code.
on ChannelsUsed pCont do
(
pCont.usePosition = true
pCont.useMtlIndex = true
)
on Init pCont do
(
)
on Proceed pCont do
(
count = pCont.NumParticles()
theBitmap =openBitmap $Plane01.material.diffusemap.filename --get emitter's diffusemap
for i in 1 to count do
(
pCont.particleIndex = i
AAA = pCont.particlePosition.x as integer
BBB = pCont.particlePosition.y as integer
thePixels =getPixels theBitmap [AAA ,(theBitmap.height- BBB)] 1
if thePixels != undefined then
(
if thePixels [1] ==(color 255 255 255) then pCont.setParticleMtlIndex i 1
else if thePixels [1] ==(color 0 0 0) then pCont.setParticleMtlIndex i 2
else pCont.setParticleMtlIndex i 3
)
)
)
on Release pCont do
(
)
You are welcome… not.
Next time you have a problem you want to solve yourself, don’t post on public forums.
Next time I see you have a problem, I will not waste 10 minutes of my weekend.
Sorry Bobo, that comment was meant as a joke, not to cause offense, your time is always most appreciated here, I only solved Monotoner’s problem after your pointer, just happens I posted my solution 10mins after yours, not having seen your reply until after I’d posted, hence the edit.
Sorry, I overreacted.
Of course it was not your problem, but Monotoner’s.
Next time you are joking, please use and not “Damnit” 🙁
Sorry for the misunderstanding Bobo, dave is only trying to help me out. I thought that particleIndex can be used on a group of particles instead of each individual particle. Thanks for adding the comments in your script to explain what each line is doing.
Thank you both for for taking your time to help me solve this
Its a bit late but here’s the final animation using the above script to create the pixel art stop motion animation effect .
The Click Five -Summertime Music Video for Animax Asia LaMB OST
http://www.youtube.com/watch?v=_yqEUysUHXE (from 0.27 onwards)
*pls click “watch in high quality” on lower right *
Enjoy!