View Full Version : how to determine how an attr. went from one state to another??
dougie0047 08-03-2009, 03:09 PM Hello. I have a simple setup, with a corridor with lights, where the lights are controlled by an expression. When a locator is inside the volume of that corridor, the visibility of some lights is set to 1, when it is outside, the visibility is set to 0. So it acts like a switch, where, say a character could move through a corridor, and the lights would be automated.
so, to what I want to do next: When the visibility of the lights are set to 1 I want to linstep their intensity from 0 to max value over, say 1 sec., but when the lights go off again, I want to linstep from max. value to 0 over a longer period, say 3 sec.
EDIT: just realized - when the light's visibility is set to 0, there is no point in linstepping down the intensity of the lights, of course :-) So, I will have to anticipate it somehow, like stepping forward in time, or perhaps setting things up by using distance between nodes (when the character moves outside the corridor, then lights starts to dim down, when he goes back in, they dim up again)
My issue is this: How can I, in my expression, determine if the light's visibility went from 0 to 1, or if it went from 1 to 0? Because, if I can figure this out, then I can of course use an if-else statement to set up the different linstep scenarios. Is this a simple thing to do, or is it more involved?
can anyone help?
thanks
Doug
|
|
dbiggs
08-05-2009, 10:06 AM
You could add another attribute to store the state of the light. The way I see it your lights have 4 states, 'Off', 'Turning On', 'On', 'Turning Off'.
When the expression turns on the light, set the state to 'Turning On' if it's currently 'Off'. If it's already 'Turning on', then bump up the intensity, and of course do the opposite to turn it off.
dougie0047
08-05-2009, 09:13 PM
Nice! I like this idea! Thanks dbiggs, I'll give that strategy a try for sure.
thanks
Doug
uiron
08-05-2009, 10:01 PM
in general, in a dependency graph there is no way to tell if attribute "has just changed value". there's just no such thing, unless you use some caching. maya graph is a stateless thingie. you can ask for an attribute's value, but you can't ask "is this the same value you just had?". when is that value for "few moments ago" ? one frame behind? ten frames? previous time slider value, which could be anything? "previous value" is a pretty undefined thing.
you can approach your task in a stateless way, still, say.. implementing a smooth formula for a light intensity. this is a linear approach to that:
if distance>distanceForLightToTurnOff: intensity 0.0
if distance<distanceForLightToReachMaximum: inensity 1.0
otherwise: intensity = 1-(distance-distanceForLightToReachMaximum)/(distanceForLightToTurnOff-distanceForLightToReachMaximum)
this way you get smooth transition from 0 to 1.0 as distance changes, but your CURRENT light intensity depends only on CURRENT distance from your char to your light.
dougie0047
08-06-2009, 11:00 PM
thanks for your reply uiron.
I see what you're saying... I think. So I dumped the "time based" idea I had, and instead I've added a couple of "zones" in front of the corridor, using (or a least attempting to :) dbiggs's idea of setting up 4 states. Now I have the corridor, immediately in front of that, I have a "turning-on" zone, and behind that a "turning-off " zone (sorry, can't think of a better name for it).
So far so good. It is of course a WIP still, but things are actually working. If anyone wants to have a look, I have attached the test scene file and the WIP script, the way they are just now.
What I would like to try next is to offset the time (or frame alternatively), so that my linstep function starts at "time-0". I have done this now using frame, and subtracting the frame where the locator enters the "turning on space". So as long as I know exactly at what frame I should start to ramp up the intensity, its no big deal. But, ideally I would want to have this happen automatically, so that no matter at what time/frame the locator enters the space where the intensity should start to rise, that time would be subtraced from the current time (so that "time" starts at 0 again). But, and this is important, this should only happen one time! Therefore, I cannot simply subtract time, because it will constantly update, and so I will always stay at 0 intensity.
How can one deal with this if at all? Also, I'm wondering if one could use the frameCache node here. I'm not sure at all how it works and what it is useful for, so if someone would care to enlighten me I would be a happy camper (the help files didn't really help me much).
@ uiron: I'll have a better look at your smooth formula when I'm not quite as tired as right now :-)
PS! Sorry it the expression is clumsily written. As you've probably guessed, I'm not an expert.
Thanks again for your replies.
EDIT: it seems that one cannot upload maya scenefiles here. But at least the script is up...
Doug
NateH
08-07-2009, 02:58 PM
Actually, you can query what a value "was" using getAttr -time in mel
int $frame = `currentTime -query`;
float $oldZ = `getAttr -time ($frame-1) pSphere1.translateZ`;
it would be easy from there to say:
if last frame was 0, and this frame is 1, i am "turning on"
if last frame was 1, and this frame is 0, i am "turning off"
if both frames are the same, i am that state
if you wanted the transition to be smoother, you could check for a greater number of frames back, and spread your transition across more frames. you can also check either where you were, or where you are going. keyframes are static (during evaluation), so you can query the future of the objects location, and not just it's past.
uiron
08-07-2009, 03:31 PM
the fact that you can specify time and get graph state at that time doesn't mean it's a good idea to use it for setting up graph connections. using getAttr in expressions is against all rules how node architecture is organized and can break graph evaluation sequence big time. for one who's rather new to rigging, that's a very bad advice.
KarlErlandsen
08-07-2009, 10:55 PM
Hey Doug,
I've got to agree with other comments regarding "getAttr -t"; it's very limited and only works for objects with simple animCurve connections coming in - nothing more than that. If you try to use "getAttr -t" on an attribute which is controlled by an expression for example, you'll run into all sorts of pain really quickly :sad:. Also, using getAttr within an expression is generally considered bad practice - you're sidestepping the dag, and sooner or later it'll catch up with you. The only foolproof way to get an attribute's value at a particular time in MEL is to use "currentTime" first (which is something you definitely don't want to do in an expression!! ;) )
I haven't used this for anything beyond simple demos, but the "frameCache" node might possibly be of some use to you. Using it is very simple; "createNode frameCache", then connect the attribute you want to monitor to the "frameCache1.stream" attribute, and connect "frameCache1.past[1]" to something else like a cube's translation or whatever... It's worked well in simple demos for me (even with expressions driving the input attribute, which is already a plus over getAttr -t!). And it does have the advantage that it integrates with the dag (although how, I have honestly no idea...).
Hope this helps!
Karl
dougie0047
08-09-2009, 03:49 PM
thanks for your replies gentlemen!
Your answers/recommendations (even if this is probably something that may seem like a trivial problem to you) helps me lots in getting to know MEL/expressions in maya better, and so I appreciate it. :-)
So, I will use the getAttr command only if I absolutely have to from now on. Point taken :-)
And, I'll have a closer look at the frameCache node. Hopefully it can help me in some way.
Also, isn't there another command that will do similar things to what the getAttr does? xform or something like that? If yes, does the same caution apply to this command also?
thanks again
Doug
KarlErlandsen
08-10-2009, 09:53 AM
Yep; the "xform" command is a nice easy way to query an objects transformation in local/object/world space. It's great for normal MEL scripts, but using "xform" and "getAttr" in expressions are both generally no-nos. The reason for this is that if you make an expression like "pCube1.translateX = pSphere1.rotateY" in Maya, then behind the scenes Maya will create a connection from "pSphere1.rotateY" to your expression node, and another connection from your expression node to "pCube1.translateX" (see the hypergraph if you don't believe me). This means that as pSphere1.rotateY changes, these changes are automatically passed through the dag to the expression node and then to pCube1 as appropriate.
This doesn't happen if you use xform or getAttr however, and so the results are undefined - sometimes they'll work and give you the data you want, but sometimes they'll give you complete garbage. When using expressions you should only use "float $myInput = someObject.someAttribute" or similar, and in MEL scripts you should only use getAttr or xform. Stick to this simple rule, and Maya will play along nicely :)
dougie0047
08-11-2009, 10:07 PM
I'll try my best to stick to the rules, if that will give me less headaches :-) Any other good rules?
Doug
CGTalk Moderation
08-11-2009, 10:07 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.
vBulletin v3.0.5, Copyright ©2000-2012, Jelsoft Enterprises Ltd.