PDA

View Full Version : Orientate particles by face normal....AGAIN!


thethule
10-02-2010, 11:02 PM
Hi guys...im sorry i know this has been asked many times, but i have been through every answer and none of them do what i want.

In a nutshell,

I want to get the particles that i create to be rotated as each poly is rotated. I managed to get one particle to be placed at the centre of each poly, but they are all rotated in the same direction. I tired the speed by object/rotate hack, to no avail. This is a personal project, so i would rather not buy box3, so if anyone has any bright ideas, im all ears. The image below shows the emitter object. I need each particles (they are buildings) to be rotated in the same way as each poly is here. Cheers guys

Marc

HornBerger
10-03-2010, 09:30 AM
here is a basic scripted approach, it works for polygonal objects that have animation applied to there controllers but not there mesh, for example : animated noise modifier

the setup:
http://img190.imageshack.us/img190/3804/setupdo.jpg

the birth script:
on ChannelsUsed pCont do
(
pCont.useTM = true
)

on Init pCont do
(

)

on Proceed pCont do
(
currentTick = pcont.gettimeend() as float

at time currentTime
global polymesh = $sphere

fn computeTM currentTime faceID =
(
uV = polymesh.dir
zV = polyop.getfacenormal polymesh faceID
yV = normalize (cross zV uV)
xV = normalize (cross yV zV)
matrix3 xV yV zV (polyop.getfacecenter polymesh faceID)
)

if currentTick == 0 then
(
for i = 1 to (polymesh.getnumfaces()) do
(
pcont.addparticle()
pcont.particleindex = pcont.numparticles()
pcont.particletm = computeTM (pcont.gettimeend()) pcont.particleID
)
)

else
(
for i = 1 to pcont.numparticles() do
(
pcont.particleindex = i
pcont.particletm = computeTM (pcont.gettimeend()) pcont.particleID
)
)
)

[attached max 2010 File]

cheers! :)

PsychoSilence
10-03-2010, 02:52 PM
the search is your friend :)

http://forums.cgsociety.org/showthread.php?f=206&t=665369

JohnnyRandom
10-03-2010, 06:49 PM
That is really cool Hornberger but I think you are making this overly complex.

The first thing I would do is detach that poly object into separate objects (use Soulburns objectDetacher (http://www.neilblevins.com/soulburnscripts/soulburnscripts.htm) script). Then in the Birth Script iterate through the individual objects and match their transforms.


on Init pCont do
(
global theArray = $plane* as array
)

on Proceed pCont do
(
for i = 1 to theArray.count do
(
pCont.addParticle()
pCont.particleindex = pCont.numParticles()
pCont.particleTM = theArray[i].transform
)
)


http://4rand.com/TEST/ParticleFlow/Misc/PF_AlignToObj.png

Oh and I think the second vector you are looking for is the one between to verts. Just a guess.

thethule
10-03-2010, 08:03 PM
Anselm, i saw that post, i tried everything that i found in the search results...but it didnt work. but thanks for the reply. Maybe i did something wrong.

Hornberger and J.Random, i will try out your suggestions tonight and let you know, thanks for the replies.

HornBerger
10-04-2010, 02:37 PM
The first thing I would do is detach that poly object into separate objects (use Soulburns objectDetacher (http://www.neilblevins.com/soulburnscripts/soulburnscripts.htm) script). Then in the Birth Script iterate through the individual objects and match their transforms.

:thumbsup: thats a good idea! (will give it a shot) its better than computing the local transformation matrices of the polygons.


Oh and I think the second vector you are looking for is the one between to verts. Just a guess.

hmm yea! for rectangular polygons one could do that infact i posted a script in this thread that does exactly that! (it finds the TM of a polygon irrespective of the transformations applied to the polygon and the object) given the polygon is rectangular and coplanar ofcourse
http://forums.cgsociety.org/showthread.php?f=98&t=920357 (see post #14)

for a general case, one vector is the normal vector the other one could be the difference between the face-center of the polygons at index (i+1) and (i) this would be the vector indicating the flow of the polygon but using it for computing transformation matrix will work best if the angle between the polygons is minimum! here's a snap (sphere with 64 segments,with animated noise modifier applied to it):

http://img836.imageshack.us/img836/9251/upvvspolyflow.jpg
image on the left uses the "polygon flow direction" vector and image on the right uses the direction vector of the sphere to compute the transformation matrices of the particles.

cheers! :)

JohnnyRandom
10-04-2010, 04:45 PM
its better than computing the local transformation matrices of the polygons. Maybe not better just simpler, simpler = better with particles in my experience, I really like what you did though that is notable for sure ;)


(see post #14)
Cool :) Yeah I could see that, it would be difficult to get your direction without a close to 90 angle. Then again you have to pick the right direction too, hopefully the object pivot/transform is correct in the representation of what you are doing

Your snapshot is missing :(

thethule
10-04-2010, 10:15 PM
That is really cool Hornberger but I think you are making this overly complex.

The first thing I would do is detach that poly object into separate objects (use Soulburns objectDetacher (http://www.neilblevins.com/soulburnscripts/soulburnscripts.htm) script). Then in the Birth Script iterate through the individual objects and match their transforms.


on Init pCont do
(
global theArray = $plane* as array
)

on Proceed pCont do
(
for i = 1 to theArray.count do
(
pCont.addParticle()
pCont.particleindex = pCont.numParticles()
pCont.particleTM = theArray[i].transform
)
)


http://4rand.com/TEST/ParticleFlow/Misc/PF_AlignToObj.png

Oh and I think the second vector you are looking for is the one between to verts. Just a guess.


Hi mate,

I tried what you suggested, but the script separated the elements alright, but didn't align the
axis perpendicular to the poly, they are all in the same direction. See image attached... Any ideas?

The blue squares are the detached objects, the red cubes are the particles

HornBerger
10-05-2010, 03:50 PM
Hi mate,

I tried what you suggested, but the script separated the elements alright, but didn't align the
axis perpendicular to the poly, they are all in the same direction. See image attached... Any ideas?

The blue squares are the detached objects, the red cubes are the particles

hmm.. i tried out the soulburn scripts (cool stuff! :thumbsup:) in particular the object detach script, i created a sphere broke all the vertices and then ran the soulburn detach script this gave me 512 planes (or detached polygons, which is a nightmare if you do it by hand btw) sadly,if you check the world transformations of the detached polygons they do not contain any rotation data and the direction vector of each polygon is [0,0,1] and not the normal of the polygon. Therefore when you assign the particles the transformation matrices of these polygons they will all point & align themselves in the same direction. if you want to use this script, you would need to first detach the polygons then apply transformations to them (instead of applying transformations to the polygons first then detaching them) after that you could use jhonny's birth script.

cheers! :)

JohnnyRandom
10-05-2010, 09:07 PM
Hey Marc

Sorry totally brain-farted that step, try this script, use function2, it will realign the bounding box and reset the local transform. (well the local transform is off by 90 degrees Z but still it will work for this :) )

AlignBBox.ms (http://4rand.com/scripts/AlignBBox/AlignBBox.ms)

thethule
10-05-2010, 11:06 PM
Hi JohnyRandom


That bbox script is great and worked a treat...but the particles are still not aligning. See image.

Thank you so much for your help by the way, can i send you a max file? If you can get it working im happy to pay you a little for your time or i can build you a big city for you to usewhen i get this stupid thing working. As my way of saying thanks.

thethule
10-05-2010, 11:09 PM
hmm.. i tried out the soulburn scripts (cool stuff! :thumbsup:) in particular the object detach script, i created a sphere broke all the vertices and then ran the soulburn detach script this gave me 512 planes (or detached polygons, which is a nightmare if you do it by hand btw) sadly,if you check the world transformations of the detached polygons they do not contain any rotation data and the direction vector of each polygon is [0,0,1] and not the normal of the polygon. Therefore when you assign the particles the transformation matrices of these polygons they will all point & align themselves in the same direction. if you want to use this script, you would need to first detach the polygons then apply transformations to them (instead of applying transformations to the polygons first then detaching them) after that you could use jhonny's birth script.

cheers! :)


Im sorry Hornberger, im not sure i understand what you mean by apply transforms before the script. I had my object, detached the elements then ran Johnys script....where do i apply transformations? Sorry to be dense... i thought i was good at 3dsmax, but i have never done anything like this.

JohnnyRandom
10-05-2010, 11:38 PM
My bad once again, I didn't include the channels section in the script so the Transform Channel has not yet been initialized in particle flow. Mental note not to be lazy and take short copy/pastes :)

The whole snippet is below.


on ChannelsUsed pCont do
(
pCont.useTM = true--initialize the channel for use
)

on Init pCont do
(
global theArray = $plane* as array --create an array, objects you want to align particles too
)

on Proceed pCont do
(
for i = 1 to theArray.count do --iterate through every object in the array
(
pCont.addParticle() --Add 1 particle
pCont.particleindex = pCont.numParticles() --Assign the particle an index number
pCont.particleTM = theArray[i].transform --Match the particles transform to the object
)
)

HornBerger
10-06-2010, 04:48 AM
Im sorry Hornberger, im not sure i understand what you mean by apply transforms before the script. I had my object, detached the elements then ran Johnys script....where do i apply transformations? Sorry to be dense... i thought i was good at 3dsmax, but i have never done anything like this.

here's the concept. consider a plane with 1 length and width segment converted to an editable polygon. When you move,rotate,scale this plane you are applying "transformations" to it, these are stored in the position,rotation,scale controllers of that plane in the form of keys. But when you enter the polygon sub-object mode and rotate,scale the one polygon which makes up this plane, these transformations will not be stored in any controller. these transformations (rotation and scale) you apply to the polygon are stored as vertex position inside the editable polygon oh and it also stores the normal of the polygon which is actually a vector perpendicular to the plane containing the polygon.

here's a picture, it shows the local pivot point of the plane (notice the orientation of the pivot point)
In the left image 45 degree rotation about the z-axis was applied to the polygon, in the right image the same rotation was applied to the plane object
http://img190.imageshack.us/img190/3097/polygoni.jpg
and here is another picture showing what happens when you align boxes to these planes :


http://img217.imageshack.us/img217/9477/polygon2.jpg

the challenge is to use the information stored in the editable polygon to derive the correct transformation matrix for a particular polygon

which i hope jhonny's script will do for you once you have done as he said in his last post

hope i made the concept clear.

cheers! :)

thethule
10-06-2010, 10:45 PM
My bad once again, I didn't include the channels section in the script so the Transform Channel has not yet been initialized in particle flow. Mental note not to be lazy and take short copy/pastes :)

The whole snippet is below.


on ChannelsUsed pCont do
(
pCont.useTM = true--initialize the channel for use
)

on Init pCont do
(
global theArray = $plane* as array --create an array, objects you want to align particles too
)

on Proceed pCont do
(
for i = 1 to theArray.count do --iterate through every object in the array
(
pCont.addParticle() --Add 1 particle
pCont.particleindex = pCont.numParticles() --Assign the particle an index number
pCont.particleTM = theArray[i].transform --Match the particles transform to the object
)
)




Can i just say that i love you....i really really love you. Success! You're script worked....

No, let me adapt it and use it for its purpose and ill post some result.

Thank you very much. Like i said, ill give you a nice big city to use when im done as thanks.


Hpefully, nothing else will crop up, this is hopefully the final hurdle..

Horneberger and others, also a huge thanks to you for contributing. Man im happy. :thumbsup:

thethule
10-06-2010, 10:47 PM
Ah..actually ONE more thing. I have noticed that more than one particle gets placed on each face..any way of getting just one per poly?

HornBerger
10-07-2010, 08:47 AM
Ah..actually ONE more thing. I have noticed that more than one particle gets placed on each face..any way of getting just one per poly?

the only problem i noticed is particle population explosion on scrubing the time slider (the pcont.addparticle() method keeps adding particles at every integration step) the birth script below solves this problem. Other than the script works fine for me there is only 1 particle / plane

on ChannelsUsed pCont do
(
pCont.useTM = true
)

on Init pCont do
(
global theArray = $plane* as array --create an array, objects you want to align particles too
)

on Proceed pCont do
(
currentTick = pcont.gettimeend() as float
if currentTick == 0 then
(
for i = 1 to theArray.count do --iterate through every object in the array
(
pCont.addParticle() --Add 1 particle
pCont.particleindex = pCont.numParticles() --Assign the particle an index number
pCont.particleTM = theArray[i].transform --Match the particles transform to the object
)
)
else
(
for i = 1 to pcont.numparticles() do --iterate through every object in the array
(
pCont.particleindex = i --Assign the particle an index number
pCont.particleTM = theArray[pcont.particleid].transform --Match the particles transform to the object
)
)
)

on Release pCont do
(

)


cheers! :)

thethule
10-09-2010, 01:47 AM
the only problem i noticed is particle population explosion on scrubing the time slider (the pcont.addparticle() method keeps adding particles at every integration step) the birth script below solves this problem. Other than the script works fine for me there is only 1 particle / plane

on ChannelsUsed pCont do
(
pCont.useTM = true
)

on Init pCont do
(
global theArray = $plane* as array --create an array, objects you want to align particles too
)

on Proceed pCont do
(
currentTick = pcont.gettimeend() as float
if currentTick == 0 then
(
for i = 1 to theArray.count do --iterate through every object in the array
(
pCont.addParticle() --Add 1 particle
pCont.particleindex = pCont.numParticles() --Assign the particle an index number
pCont.particleTM = theArray[i].transform --Match the particles transform to the object
)
)
else
(
for i = 1 to pcont.numparticles() do --iterate through every object in the array
(
pCont.particleindex = i --Assign the particle an index number
pCont.particleTM = theArray[pcont.particleid].transform --Match the particles transform to the object
)
)
)

on Release pCont do
(

)


cheers! :)

I'll give it a try, thank you very much hornberger. Ill give you a model of a city as well when ive set the steps out and have em working.

JohnnyRandom
10-09-2010, 06:13 AM
Ah yes, I assumed you where doing this for a single frame, the script is written in the form that every int. step will generate a particle per poly, unless you tell it otherwise, the script op runs through the for loop every time it runs through the tree.

thethule
10-14-2010, 10:18 PM
Hi guys..havent had a chance to work on this till now and im starying to build my first city, all good except one thing (as usual)..The pivot points of my particle shapes are all at the bottom of the building, but the script is positioning them at the centre of each particle, so the buildings go through the floor as you can see in the image....any idea why this is happening? Once again thanks guys

HornBerger
10-15-2010, 05:59 PM
works fine for me. here is a screen shot [right click and choose view image to enlarge] :
http://img257.imageshack.us/img257/1597/buildingst.jpg


i used a shape instance operator, and selected a group of "buildings" the building group consists of editable poly objects with there pivots positioned at the bottom.

cheers! :)

thethule
10-19-2010, 10:07 PM
Sorry for the delay in getting back, crazy at work...

Thats so weird. Thats what ive done and they are still going through floor. I have uploaded the file here:


http://rcpt.yousendit.com/971423455/43fb04de96f97d5f078725481aa9ad72


In case you have a second to look at it, but dont worry if not. Once again i really appreciate the help. Ill go back a few steps to make sure im not being stupid on my end (its been known to happen)

JohnnyRandom
10-20-2010, 01:20 AM
Can't hit that site from our network :(

HornBerger
10-20-2010, 12:22 PM
Sorry for the delay in getting back, crazy at work...

Thats so weird. Thats what ive done and they are still going through floor. I have uploaded the file here:


http://rcpt.yousendit.com/971423455...78725481aa9ad72 (http://rcpt.yousendit.com/971423455/43fb04de96f97d5f078725481aa9ad72)


In case you have a second to look at it, but dont worry if not. Once again i really appreciate the help. Ill go back a few steps to make sure im not being stupid on my end (its been known to happen)
__________________
www.weliketomakethings.com (http://www.weliketomakethings.com/)


i had a look at the scene, And the script is working correctly, only the Z position of all your polygons is below the XY plane just move the polygons up and re-enable the particle flow.
as for the buildings you could run this script to move there pivot to there bottoms (before running the script, reset there xform and collapse them to poly or mesh, it is important that the individual building making up the buildings group is either a mesh or poly object and not a group of objects itself. ) :

(
for o in selection do
(
boundingBox = (nodelocalboundingbox o)
o.pivot.z = boundingBox[1].z
)
)

here is a snap [firefox users can right click and choose view image to enlarge]:
http://img145.imageshack.us/img145/7900/buildingsh.jpg

ps: make sure to remove lamposts from the buildings group ;)

cheers! :)

CGTalk Moderation
10-20-2010, 12:22 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.