help needed with particle instancing based on poly normal direction.


#22

UGH! SO DUMB! I guess this happens when we stare at the screen for too long! Forgot to turn per-particle on! Well, i have the variables working, but not getting the behavior i want yet…


#23

ok. cool. I was going to say, “Wait why can’t you add them?”

Glad you solved it


#24

So far so good. Using the solution outlined by YDP, has anyone been able to generate random rotations about the normal vector? Stimuli’s solution breaks all other rotations, and since i’m attaching instanced objects to a deforming sphere, I have to keep aligned with the surface normal.


#25

I tried doing a mix between YDP’s solution and the vector2rot script mentioned by Derek Wolfe.
Occasionally I was getting some very abrupt changes in aim direction when using the closestPointOnMesh node, especially on a deforming mesh.
So I tried comparing results with the nearestPointOnMesh command, and using the same input position here’s what I got, :

normal from closestPointOnMesh
// Result: -0.323307 0.709912 -0.625698 //

normal from nearestPointOnMesh
// Result: -0.33909 0.776836 -0.530607 //

Odd!

Anyway, using the command nearestPointOnMesh (remember to first load the plugin nearestPointOnMesh.mll) here’s a way to align particle instances to surface normals and having a random rotation around the alignment axis. In this case I’m aligning the instances X-axis, so the original instance object should be pointing along the X-axis on the grid (with transforms frozen) for this to look right.

add two custom per particle attr’s:
rotationPP (vector)
randomRotationX (float)

in the instancer section of the particleShape tab, go to Rotation Options and set Rotation to be rotationPP.

Creation expression:

// random start position
   particleShape1.goalU = rand(0.1,0.9);
   particleShape1.goalV = rand(0.1,0.9);
   
   //random rotation for X axis
   particleShape1.randomRotationX = rand(180);
   

Runtime expression:

// define a variable with the particle position
   vector $p = particleShape1.position;
   
   // get surface normal at particle position
   vector $normal = `nearestPointOnMesh -ip ($p.x) ($p.y) ($p.z) -normal -q pPlane1`;
   
   // define worldUp
   vector $worldUp = <<0,1,0>>;
   
   // calculate normalized directions by which to align the y and z axis of the instance object
   vector $directionOfZaxis = unit(cross( $normal, $worldUp ));
   vector $directionOfYaxis = unit(cross( $directionOfZaxis, $normal ));
   
   // solve each angle, result in degrees
   float $rotZ = rad_to_deg(( atan2( ($normal.y), ($normal.x) ) ));
   float $rotY = rad_to_deg(( asin( -($normal.z) ) ));
   
   // feed result into the rotationPP attribute
   particleShape1.rotationPP = << particleShape1.randomRotationX, $rotY, $rotZ >>;
   

Optionally you can add the runtime expressions in the creation too.
Also, notice the “pPlane1”, which should be corrected to match the name your poly object.


#26

… I just noticed I’d pasted some lines in there that were not needed for this case.
So these lines are redundant, as you might have noticed too :smiley:


 // calculate normalized directions by which to align the y and z axis of the instance object
 vector $directionOfZaxis = unit(cross( $normal, $worldUp ));
 vector $directionOfYaxis = unit(cross( $directionOfZaxis, $normal ));
 

Cheers.


#27

Ah CTP!

You beat me to it. After stepping away for a few day I just started to dissect the commands and vector math.

I created a script similar to yours, no need to post it. The only difference was that i used closetPointOnMesh. I didn’t experience the abrupt changes in direction you did, and the behavior seemed better.

Glad you posted your solution!

DCW

Oh!! What i think helps with the with this script and the deforming surface is to create a geoCache of the surface.


#28

This thread might be dug up a few times in searches later on, so I thought it would be worth putting an extra note in here…

If you want the Y-axis of the instance object to align with the surface normal, it will work with these lines:

float $rotX = rad_to_deg( atan2( ($normal.z), ($normal.y) ) );
float $rotZ = rad_to_deg( asin( -($normal.x) ) );

You can then assign a random rotation to the Y-axis.

NOTE: In this case, rotation order must be set to YXZ, on the instancer node.

C


#29

Is this what you mean?

In your particles go to add dynamic attribute > general. Give it a name(like particle_rotate), make sure its a vector (for x,y,z), and check per particle array.

Rightclick your new attribute and runtime expressions before dynamics and type this in :

nameofparticlesParticleShape.particle_rotate = rand (<<0,0,0>>,<<360,360,360>>) ;

What this line does is bascially give them a random rotation of 0 and 360 degrees in x y z. You could ofc if you just wanted it to be in one angle change it to 0,360,360 or something.
Then under rotation options choose particle_rotate.

Remember tho that the will randomly rotate every single frame now, if you just want to create some randomness and have your geometry be still, you can scrub in the timeline untill you find a frame youre happy with and then just put // in front of the expression or delete it.


#30

glad this thread is still open - consider me subscribed - I’m trying to run through some of the examples and get my head around the expressions!


#31

Just wanted to say a massive thanks to all who contributed to this thread.

Massive help!


#32

Hi everyone,

How do i then offset the particles along the surface normal (and possibly animate it over time)?

Thanks
F


#33

goal offset attribute in particle shape.


#34

can you do that with nparticles the same way?
i do not get the instance normal alignment working…


#35

There’s some great information here, I have something I’ve been trying to do related to this.

I’m trying to create an enormous flock of bats that can be dynamically influenced. One problem I’m having is getting the direction of the individual bats and awareness of the other bats around it.

Anybody have ideas?


#36

Trying to keep this little kick ass thread alive.

I have bugs crawling along skin and I’ve got them rotating around based on the normals which is great. And random Y rotation is easy enough.

I am however trying to figure out how I can get the Y rotation to aim in the direction that the particles are moving.

Any ideas?


#37

Bringing this one back.

Anyone have a solution for the above post.

I’m working on something similar and can’t seem to get the insects to aim in the direction of the velocity and have them orient to the surface normal.


#38

Figured it out like 2 minutes later and thought I’d post the solution in case anyone else needs it.

Aim Direction : Velocity
Aim World Up: goalWorldNormal0PP

With that setup in the instancer, the particles will aim toward their velocity and still be oriented correctly on the surface.


#39

Hey guys,

I don’t know what i’m doing wrong…
I guess that when it comes to scripting I get lost most of the times… :banghead:

Anyways, could someone help me figure out why this is not working for me? All I wanted is for the instances make a kind of grid with crosses, using the sphere as a dome with a cross on each vertex…

I used YDP scene file as a start and copied the expressions…

I uploaded my scene.
please, guys… :slight_smile:
Thanks a lot!!!


#40

Ok…hmm

I managed to constrain the instances to the sphere’s normals. :slight_smile:


#41

ctp,

I’m trying a variation of yours but i can’t seem to get it right! I work with the Z up and thus i’m attempting to modify your code for one with the Z up.

This is the expression that i’m creating:

// sets the orient axis for the instance
particleShape1.aimUp = <<0,0,1>>;

// get surface normal at particle position
vector $particlePos = particleShape1.position;
vector $normal = nearestPointOnMesh -ip ($particlePos.x) ($particlePos.y) ($particlePos.z) -nr -q pPlane1;

// orient the instance
particleShape1.aimDir = $normal;

// random rotation for Z axis
particleShape1.randomRotationZ = rand(360);

//solve each angle, convert to degrees
float $rotX = rad_to_deg( atan2( ($normal.y), ($normal.z) ) );
float $rotY = rad_to_deg( asin( -($normal.x) ) );

// asign random rotation in Z
particleShape1.rotationPP = << $rotX, $rotY, particleShape1.randomRotationZ >>;

any help with this will be greatly appreciated, i’ve attached my file for your reference.

Thanks,

-G