No tags yet.
Hey everyone. My first post here, I'm just getting into rigging though, so I'll probably be posting here quite a bit from now on.
SO... I have a locator, and a sphere in my scene. I'm trying to write an expression that will make the sphere constantly travel towards the locator. And depending on the distance between the locator and the sphere, the speed at which the sphere is traveling will change.
So, when the sphere is really close to the locater, it will very slowly creep towards the locator. But when the locator is moved far away the speed of the sphere will ramp up, until it hits a max speed.
Hope this isn't too complicated. I've been toying around for hours trying to get it to work.
Any help will be greatly appreciated.
You could calculate the vector between the ball and the locator in the expression and then use the direction of the vector to always move the ball towards or away from the locator. With that you could then use the length of the vector to derive the speed. When the vector length is small the ball is close to the locator, the larger it gets the further away the ball is.
This should get you going in the right direction,(no pun intended!) if you'd like I'd be happy to elaborate on how this would be written as well.
Alright, first off. What's the vector? I'm really new to all this rigging stuff.
If you could help show me how it's written, that would be great. I think I have a pretty decent idea on how to do what I want to do. I just don't know any of the coding to get it done.
Thanks
nvm, I found out what vectors in Maya are. Still no idea how I'd calculate it though...
This is more math stuff than rigging, however, the vector is a line between 2 points with a direction and length(magnitude) expressed as an (x,y,z) value. In this case the locator and the sphere are the 2 points. If you take the position of the sphere and subtract the position of the locator you'll get a vector starting at the locator and ending at the sphere. I'll run through an example of this quick.
first, some arbitrary values to work with.
sphere position = (12,5,8)
locator position = (5,19,2)
theVector = sphere.pos - locator.pos = (12,5,8) - (5,19,2) = (7,-14,6)
To visualize the vector you can think of it's starting point as being (0,0,0), and ending point being theVector, which as we see above is (7,-14,6). This gives us a value that if you subtract theVector from sphere.pos you'll get locator.pos, and if you add theVector to locator.pos you'll get sphere.pos.
The length of a vector is defined as sqrt(x^2 + y^2 + z^2)
theVecLength = sqrt(7^2 + -14^2 + 6^2) = sqrt(49 + 196 + 36) = sqrt(281) = 16.763
Finally if you normalize a vector you get a vector who's length is 1, but is still pointing in the same direction. A normalized vector is a lot easier to work with. To normalize a vector you just divide x, y, and z by the length.
theNormVector = (theVector.x/theVecLength, theVector.y/theVecLength, theVector.z/theVecLength,)
theNormVector = (7/16.763, -14/16.763, 6/16.763) = (0.4176, -0.8352, 0.3579)
If you subtract theNormVector from sphere.pos you get a new position that is 1 unit closer to the locator. If you add you move 1 unit away from the locator.
So, now you can use the vector length to know how far away the sphere is from the locator, and the normalized vector to move towards and away from it.
I hope all of this helps!
awesome man! you've really been an amazing help. I hate to ask you to do any more for me, but I'd really appreciate just a little more help.
So... this is what I got so far:
vector $sphere_pos=getAttr sphere.translate
;
vector $locator_pos=getAttr loc.translate
;
vector $vector1=$sphere_pos-$locator_pos;
float $mag=mag($sphere_pos-$locator_pos);
vector $normalvector= <<($vector1.x/$mag), ($vector1.y/$mag), ($vector1.z/$mag)>>;
sphere.translateX = ($normalvector.x - $sphere.x)*(frame*-1);
sphere.translateY = ($normalvector.y - $sphere.y)*(frame*-1);
sphere.translateZ = ($normalvector.z - $sphere.z)*(frame*-1);
I wasn't exactly sure how to do that last bit. and it kind of works... until the sphere starts to catch up to the locator. And then it starts spazzing out all over the place.
To be perfectly honest, I have no clue what a normalized vector is, so I don't really get what I'm playing with here. Which is probably why that code doesn't work.
Anyways, do you know how I would go about adjusting the speed. I was thinking of having the sphere travel halfway between where the sphere currently is, and where the locator is. So it divides the distance between the two in half on each frame. That way it'll never reach the locator, but it should give a nice smooth change in speed. What do you think?
That was an awesome math lesson.
Vectors, dot and cross products are used a lot when you need to get a bit deeper into rigging. It's good to know them.
In my example above theVector is 16.763 units long. When you normalize it you cut it off so that it's 1 unit long. It's still pointing in the same direction, it's just smaller.
If you divide theVector by 2 you'll get a position 1/2 way between the sphere and the locator. In your case you may not even need the normalized vector, but it's still handy to know since it lets you work with exactly 1 unit.
Using your code now.
vector $sphere_pos=getAttr sphere.translate;
vector $locator_pos=getAttr loc.translate;
vector $vector1=$sphere_pos-$locator_pos;
// Since we aren't normalizing we dont' need the magnitude
// float $mag=mag($sphere_pos-$locator_pos);
// Instead of normalizing the vector divide by 2, this will constantly give
// you the 1/2 way point between the sphere and the locator.
vector $halfVector= <<($vector1.x/2), ($vector1.y/2), ($vector1.z/2)>>;
sphere.translateX = ($halfVector.x - $sphere.x)*(frame*-1);
sphere.translateY = ($halfVector.y - $sphere.y)*(frame*-1);
sphere.translateZ = ($halfVector.z - $sphere.z)*(frame*-1);
hmmm, this isn't working for me... lol I had no idea this was gonna be so complicated.
is it possible to simplify things... like...
have... uhmm
ok, how about something like this:
int $offsetvalueX = sphere.translateX at frame - 1 (I don't know how to properly code this, but is it possible to get the value of something from the previous frame?)
sphere.tx = ($offsetvalueX+locator.translateX)/2
and then, repeat for Y and Z.
It's working in my head lol... probably won't actually function properly though.
Basically, it would work fine if, when the frame count goes up by one, the sphere moves from the previous sphere's location... to halfway between that location and the current location of the locator... I hope that makes sense.
Of course I could also just keep working on it by using the vectors. Just two different methods to get the same end result. I just don't know what I'm doing wrong here.
There may be some problems with the following code. Sorry I didn't really look through all of the code last time, I was on the way out and just replaced the normalized vector with the halfVector.
sphere.translateX = ($halfVector.x - $sphere.x)*(frame*-1);
sphere.translateY = ($halfVector.y - $sphere.y)*(frame*-1);
sphere.translateZ = ($halfVector.z - $sphere.z)*(frame*-1);
With how the vector is calculated you need to do sphere - vector to move the sphere closer to the locator. By doing vector - sphere you're starting at the mid point, then moving the sphere away from that point. I'm also not sure what the *(frame*-1) is for. Just from the code all I see it doing is throwing the sphere in the opposite direction by taking a negative frame and at a greater and greater rate as the frame increases.
To simplify it a bit you could work with 1 variable at a time, and what you described sounds like it will work. The mean between 2 values will give you a value halfway between them.
You could also use the same principles of the vector math. (sphere.translateX - locator.translateX)/2 to find the how far you'd have to move to reach the point between the sphere and the locator on the x axis. Then subtract that from the sphere to move it to the halfway point. Your method there is a little quicker and easier to find the value since the vector math is first finding the offset to reach the mid point and then finds the mid point by using that.
On a side note you can use getAttr to get the attribute at a specific time. Check out the MEL command reference for more info, but the basic syntax is getAttr -time (time in frames) (attribute)
okay, I'll continue working on it. I really don't know how to thank you mzahmbie. You've been a huge help. I'm clearly in way over my head here. So, i appreciate it man. You're a genius.
I'll post something up when I finally get it working properly.
Glad I could help out, keep working at it and I'm sure you'll get it going. Vector math can be a bit intimidating when you're just starting out but it's not bad once you get into it and becomes useful in so many ways with setting up some advanced rig systems.
You must log in to post.