1. I've been reading quite a bit about expression lately and are now familiar with a lot of the particle parameters concerning position, velocity etc.. However, I'm at a loss to how to do this with normal objects. Especially calculating distance between any 2 objects. Can somebody give me a quick example of how to read the positon of 2 nulls and determine their distance as a float in an expression format?
2. I want to assign random pictures onto planes in 3D space that are instanced to particles. I obviously could do this with sprites. However Sprites always auto-orient to camera which I don't want, plus I want the look of software render especially with better motion blur and DOF.
My question is: Would I have to make 40 different planes and texture map each one and write an expression to randomly instance a plane to each particle. Or can I just instance one plane and write an expression to pick from a random texture for each instance?
Thanks for any input.
The answer to your first question lies in the wonderful world of vector mathematics.
The distance between two objects is the magnitude of the vector separating them. The vector separating them is the difference between their position vectors. So to calculate the distance between two objects, we do something like this:
vector $sphere = << sphere1.tX, sphere1.tY, sphere1.tZ >>;
vector $cube = << cube1.tX, cube1.tY, cube1.tZ >>;
vector $separation = ($sphere - $cube);
float $distance = mag($separation);
(Actually, that 'mag' function is unnecessary because when you assign a vector value to a float, Maya automatically calculates the magnitude of it.)
This seems a little ungainly... I'm rusty on my vector expressions so if anyone out there can tighten that code up that would be most welcome.
Hope that's helpful. I'm not sure about your second question, sorry. :(
Thank you Steve. That is priceless info. Not only did I learn the math, but you showed how to get the postion using .tY, etc... Something I had a hard time finding in books. Thanks for your help.
You're welcome, Chris.
Yeah, there are a few real head-scratchers that crop up when you're trying to work with different types of data in Maya. I remember once the only way I could read the attributes I wanted from an object was to export it as an ASCII file, read that text file back in and parse it to obtain the needed floats!! It was a mess and if I never have to do anything like that again, it'll be too soon.
Do a careful search of your Maya docs for stuff about vectors and expressions. Little tidbits (like that fact about Maya converting a vector to its magnitude when you assign it to a float, which I didn't know before) tend to be squirreled away in weird bonus chapters about particles and colour. But there's a lot there if you have the time to hunt it down.
very intersting and clean approach, since you are using a total coordinate approach to doit. Me likes it. I was thinking along the lines of using Pythagoras with distanceBetween as a thrid variable, but your take is much cleaner in operation, although it entails having quite a different head. ;)
As to that: Very interesting mixture of heads now here at the forum. That i likes the best.
I thought about the distanceBetween node too, but in general I try to shy away from adding whole new nodes when a line or two of code will suffice. As for the 'total coordinate approach'... well, I'm lazy, so I let Maya handle the Pythagoras: all I want to worry about is simple vector arithmetic.
High school algebra actually comes in handy for something. Who knew?! ;)
Remember the days when we all cried about having to learn algebra,geomtry, trig? I mean we were never going to use it anyway right? hehe
Is there any more info on the distanceBetween Node anywhere. I found a hint of it as 3dcafe.com but for their VIP members. Don't see much documentation on how to use it in a practical situation.
I'm on a Mac, putzing with a 2-d creature in manner most vile and fun, but if you F1 your Maya you'll get the online help and docums. Go into MEL and search for distanceBetween. It is a node that returns the distance between its inputs once each frame unless it is feeling frisky ;)
Steve's approach went to the jugular in that he actually created the "distanceBetween" node as an ASSUMPTION in his little two-headed code. I found such steamrolling refreshing, like a punchline, so I got sidetracked and did not give much detail: my first answer would have been to drop the node, add the inputs and query the output, or plug it into my process, but that would also add to the mess that the hypergraph turns into. Steve kept the extra hayriness safely hidden away in ASCII.
will using the node create and destroy the node per frame? One of my MEL books cautions about this. When you say query, do you mean use the 'get...' command?
[Chris Smith] " use the 'get...' command?
yes, among others, or assign the result in an operation to something else,
dsitanceBetween(moving.vector, stationary.vector) < limit.distance
or plug the out into whichever node needs the info
Understood. Thanks for your wisdom Kino, and Steve.
using the node doesn't create and destroy when using it for an expression (you wouldn't want to create it inside the expression, then that would create a bunch of the nodes). But once its created and connected it will not be removed unless you tell it to and it will evaluate inside expression quite easily and quickly. And yes it would be a getAttr command if used in a mel script. If used in an expression you just have to do this:
$myDistance = distanceBetween1.distance;
chiming in a tad late here but there is a fundamental problem with this example of the equation (not to step on steve's toes).
As it is, these values would be used in local space and would not work if your objects where parented to another geometry or joint. What would be best is to either use World Matrices to calculate the distance. The world matrix is always the position in world space, not the objects local space (tx, ty, tz always work in local space ie. local to the parent).
Another thing you can do is use command called xform like this: xform -q -ws -t object; which will return the world space values of the translation in an array. But its a mel command and not very well suited for expressions.
However, I've found that the best, easiest and fastest way is to use what kino mentioned, distanceBetween node. It lets you measure from points or from matrices (very nice) and is extremely accurate and extremely fast, faster than vector math in an expression because its build into a node and node evaluation is over 10 times faster than expression evaluation.
to create one type createNode distanceBetween in the shell and it will create the node. Connect world matrix of one object into the worldMatrix1 attr and world matrix of the other into the second world matrix slot. Viola, piping hot fast distance output as a float double that you can evaluate in an expression or plug into any other attribute anywhere else (like depth of field focus distance on a camera).
Anyway, just be carefull about the local/world space difference when doing vector math, it can really bite you if you don't realize it.
Thank you for your further insight into the distanceBetween Node. I already added Steve's way to my project and it works great. To learn and experiment, I am modifying it to use the distanceNode based on your suggestions.
If anyone is curious what the project is:
We are working on a spot where we were asked to have flat square panels (which will be replaced with random product shots) to "rain" down onto a surface. However when they land they fall into a grid like pattern. The camera sweeps down around the grid where it's too close to make out what the order is. In a last shot the camera pulls back to reveal that they fell into a giant mosaic of the Company logo that distributes those products. The Mosaic was made from an EPS of the company logo. I made that Planar using 6000 polygons. Converted that into a softbody making the duplicate soft and the non-soft a goal. Hid the geometry so I just have particles arranged like a grid in the logo shape. Wrote a creation expression for the softparticles that started them all at a point in space 30 units above the ground. Then use a runtime expression that corralates the particleId with time. Once it is the particle's turn, it is given a goalPP whithin a certain random range. Where it zips off to marry up to it's place on the ground.
However, it is currently raining down in order of particleId. Which doesn't look that bad, but I thought what if I could key frame a locater along the ground and trigger a goalPP based on how far the locator was? That way I could "Paint" (by keyframing that locator) the order of the falling squares.
I did a side experiment using Steve's approach. In that whereever the locator got near certain particles, it would trigger them to rise. Almost like moving your straw in Coke and triggering bubbles to rise to the surface. But to make it work in the main project, I have to figure out how to make the association between a locator getting near the goal particles and changing the goalPP of the softparticles up in space.
Hi again Chris.
Just time for a quick reply now; something occurred to me that might be helpful.
[Chris Smith] "Wrote a creation expression for the softparticles that started them all at a point in space 30 units above the ground."
Don't forget that another way to affect when the particles hit the ground is simply to change their initial height. The camera never sees them in their 'holding pattern' up above... so if you just move them to different heights and then let them all fall at the same time, the lowest ones will hit the ground first and the highest ones last.
Might be a quick workaround, depending on what your current setup looks like.
That's a fantastic idea. The challenge is how I could set their initial heights with relative ease. And more importantly be able to change that quickly if needed.
However it did make me realize that instead of making all my softparticles clump to one point in space on the first frame. I could keep the mosaic shape intact high above space, then keyframe my null around that to trigger which ones fall in what order rather than keyframing a null over the version on the ground.
Oooh, I think I've got a good one for you.
Create your poly mosaic plane. Make it a soft body (duplicate, make copy soft, make non-soft a goal). Now use Artisan to paint the goalPP on the plane... just scribble around randomly to test this out.
Now disconnect the particle object from the surfaces, and add this creation expression:
vector $oldPosition = particleShape.position;
vector $newPosition = <<$oldPosition.x, particleShape.goalPP, $oldPosition.z>>;
particleShape.position = $newPosition;
When you hit 'create,' you should see your particles jump to different heights corresponding to their different painted goals. The goal values themselves no longer affect motion because you've disconnected the softbodies. The particles start at different heights but fall uniformly.
There might be shortcuts to this... for example, it might be possible to paint directly to position, rather than copying the values over the way I did. But I'm on my way out the door now so you'll have to experiment yourself!
P.S. Hmmm, come to think of it... you could just sculpt your original poly plane into the hill/valley pattern you want, and not even worry about the rest of this junk!
STEVE: mmm, come to think of it... you could just sculpt your original poly plane into the hill/valley pattern you want, and not even worry about the rest of this junk!
Might I say, Brilliant? Will do.
Man, I hate it when I write a carefully-detailed message, and then a thought strikes me at the last second that makes it all obsolete! :)
If you do use the shape of the poly to produce the appropriate initial particle position, by all means take advantage of the Move Component tool. Specifically I'm thinking the Random (translate Y) setting will work wonders to 'noise up' the shape while retaining the overall structure you created by sculpting.
Thanks, Sean. Those are both really good points: world vs. local space, and speed of evaluation.
The original post asked for 'expression format,' and I guess I just put on the blinders and forgot about other ways of approaching the same task.
I tend to be biased towards using expressions instead of nodes; I feel as though adding extra nodes 'clutters up' the scene. But of course as you point out, the evaluation of an equivalent process is much faster with a built-in node than with a user-written expression. So I've got to shake that habit!
Don't worry about the toes. ;) Helpful input and corrections are always welcome.
Its always good to have more than on way, but in this case your way was best since chris was doing a particle expression. A distance between node isn't very usefull because you can't hook it up to arbitrary particles and you would want to create them in a runtime expression because, well, thats insane. Cheers all around!
how to take the average of that objects distance and that objects distance and make it that object ( mid locater )
create two locaters and point, orient, and even tangent contrain one to each object
create a middle locater and use a expression that says
middle locaterTranslateZ = (locater1TranlateZ + Locater2TranslateZ ) / 2
middle locaterTranslateY = (locater1TranlateY + Locater2TranslateY ) / 2
middle locaterTranslateX = (locater1TranlateX + Locater2TranslateX ) / 2
now you can query the middle locater using more expresiions and the connection editor
I do not know if this helps you but its good to know
Again this is much slower than a distance between node if you look at what happens in the evaluation cycle
1. Evaluate object matrix
2. evaluate point constraint tx ty tz separately
3. evaluate locator position from tx ty tz separately
4. evaluate orient constraint rx ry rz separately
5. evaluate locator rotation from rx ry rz separately
6-10. do it all again for the other object (5 more steps)
11. evaluate expression
12. apply expression to geometry
as opposed to:
1. evaluate object1 matrix
2. evaluate object2 matrix
3. evaluate distance node
4. evaluate expression from distance node
5. apply expression to geometry
In the second case the expression would be the longest evaluation time and it would be minimal
In the first case the constraints would be the longest evaluation and we do it 4 times, twice for each object. Not a big deal when you have only 2 objects. But if this is part of a character rig in which these steps cannot start until a whole other part of the rig has to be evaluated it can slow down a lot
Also come to think of it you could do a mid distance like in this post you could point constrain one object between two masters and that objects position would be the middle distance. It would evaluate faster than the first case and almost as fast as the second case but is much simple to set up
I would never rig a character with what I posted before
the way I rig a character takes fifteen minutes once you know the steps
wow, I wish I could get away with that. Working in film its not often I come across a rig that would take 15 minutes. I rigged a face the other day and even with a heavily script driven build it took a few days to get everything the way we wanted it. But its all the demand. On my shorts i like keeping rigs simple-stupid so they don't break easily since student animators that have less 3d experience can handle them well and rely on talent.
Although distance between is a handy node when doing squash and stretch in dual IK/FK setup. :)
to be more precise, joints, lra, fk liits, ik can be done in minutes
wieghts and influence objects are the bugger