PDA

View Full Version : Coffee version of the Freeze Node?


Scott Ayers
12-28-2009, 08:31 PM
I love how the Freeze allows you to clamp an object in 3D space dynamically anywhere in the scene. Without needing anything else to clamp it to like a constraint. Or giving it a specific Vector location to go to when the switch is turned on. It's very handy for pinning character controllers.
But how the heck does it do that?

I've tried a few experiments using Get & SetPosition() and Get & Set->Mg()->V0 and I'm not getting anywhere.
I can get an objects position easy enough. But how do you lock those position vectors in place like the freeze node does?

Srek
12-29-2009, 06:02 AM
You have to make sure that your expression is the one with the highest priority, otherwise a succeeding expression can overwrite the results so the pinned parts move again.
Cheers
Björn

Scott Ayers
12-29-2009, 04:29 PM
Yeah. I guess you could say that I'm having a priority issue of sorts srek.
Not in the traditional sense of expression priorities. But in handling my loop structure.

It's easy to assign an object to a specific position with op->SetPosition(vector(x,y,z)).
Or to assign an object's position to another object's position.
But the freeze node is doing something much more clever. It's not comparing an object to any other object. Or using any hand coded vectors as targets.
It's somehow dynamically grabbing the current location of an object. Then somehow re-using those coordinates to lock the object to them.

This is what I've got so far in my COFFEE tag:
main(doc,op)
{
var pget=op->GetPosition(); //Gets the object's postion
var pset=op->SetPosition(pget); //Sets the object's postion to pget

if(op#ID_USERDATA:1==true)
{
pset=pget; // force the object to stay at pget's coordinates
return;
}

}
Even though this compiles without any errors. It doesn't lock the object in place.
Because after the loop sets the object's position with pset=pget;. The loop starts all over again and the object just follows along with the new pget position.

I need a way to tell the loop to skip over the pget variable after the first loop sequence occurs.
Or maybe I'm going about this completely the wrong way?

tcastudios
12-29-2009, 08:03 PM
You need to store your memory value before the main(doc,op)
Something like:


var memory;

main(doc,op)
{
if(!memory) memory = something default; // Like current position
var stuff = make/read some stuff that you need to memorize; // Like current position

if(the condition you want)
{
memory = stuff; return; // your new memory
}
memory = memory; // keep old memory
}

Cheers
Lennart

Scott Ayers
12-29-2009, 09:02 PM
Thanks for the help Lennart,

I tried that but I'm getting a strange problem with it. I must not be using it correctly.
If I execute the coffee tag using the execute button in the coffee tag's editor. It seems to work exactly how I want.
The object stays locked in it's current position until I turn off the User Data boolean switch I created on the object.

That's great and exactly what I wanted to happen.
But if I enable the switch again. It doesn't work anymore.
For some reason it only works if I compile/execute it with the coffee tag's editor.

Here's the code:
var startpos;

main(doc,op)
{
if(!startpos) startpos = op->GetPosition();
var setpos = op->SetPosition(startpos);

if(op#ID_USERDATA:1==false)
{
startpos = setpos; return;
}
else
startpos = startpos;
}

-ScottA

JDP
12-30-2009, 06:24 AM
By using var setpos = op->SetPosition(startpos); you are setting the position of your object unconditionally, the command is executed and setpos is given the boolean value of whether this operation was successful or not. Now startpos and setpos are not compatible as one is a bool value and the other is a vector value. You also need to update startpos when you have switched the freeze off. Also you don't need to update global variables such as setpos every cycle, they will retain their values.

var startpos;

main(doc,op)
{
if(!startpos) startpos = op->GetPosition();
var tg = op->GetFirstTag();

if(tg#ID_USERDATA:1==TRUE)
{
op->SetPosition(startpos);
}
else
startpos = op->GetPosition();
}




In this example I've put the userdata on the expression tag itself, you need to make sure the tag is the first one on the object.

HTH

Scott Ayers
12-30-2009, 03:29 PM
Thank you JDP.
You've rescued me again.:thumbsup:

I knew my loop logic was wrong. But I couldn't picture the solution in my head.
Now that I see a working example. It's so simple and obvious.

-ScottA

CGTalk Moderation
12-30-2009, 03:29 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.