| Downloaded from www.biorust.com on Thu Feb 09, 2012 08:03:39 |
![]() | |
| Xpresso Tutorial - Mall Doors Tutorial Author - Elentor (http://forums.biorust.com/member.php?u=314) |
Hi there people! Here I am again, this time with a walkthrough of one of the coolest Cinema 4D functions ever: XPresso! What is XPresso, you ask? Well, it's a visual programming tool that enables you to make cool scripts for your animations. Unlike competing solutions (such as COFFEE), it is also completely visual and removes the need for overly explicit coding. So, with that explained, lets get started!
Section 1 - Introduction
This tutorial is very advanced, and, unlike the
Meteor tutorial, expects that you are already competent with the modelling
and interface basics of Cinema 4D. Just in case you don't know what XPresso looks like,
then you can check for the final result of our tutorial below:
Looks complicated, huh? Well, to be perfectly honest, is *IS* complicated, and
takes some considerable time to master. Many people say that learning
Xpresso is easy. Well, just to put the record straight I will repeat
myself - It's NOT that easy! In
fact, I sometimes think that using Xpresso is even more complicated than programming,
although I cannot confirm this statement with absolute certainty, because the biggest program I ever made was a baskara equation and
matrixes calculator. Whilst we are on the subject of
programming experience, I am happy to report that you will not need any prior
knowledge at all to start using Xpresso, although experience with logical
process creation would be handy. Once you get past the basics, though, things get
a lot easier, and if you have difficulties at the beginning you shouldn't worry
- after all, its natural when starting in a new language, especially
if you never programmed before.
So then, what are we going to create in this tutorial? Well, the idea is to make a little script to
open a set double
doors (just like those pesky automatic doors in shopping centers) when an object
gets close to them, and then have them close automatically after it moves away. Just to
summarize, here's a little movie clip to show you what I mean:
|
When something gets close to the door, it opens.
When there's nothing near the door, it closes. Simple! |
The above clip is easily explained in the following terms: There is an "area" around the door. When an object enters it, the right door
will move constantly to the right, whilst the left door moves to the left.
After these doors reach a certain point, they stop.
After the object leaves the area, they will go back to their former position.
This explanation needs to be embellished with a little programming logic.
How is this done? Well, after deciding the
objective of the script, you will need to re-write your plan using clearer
logic. Thus, the complete logical sequence in programming/xpresso terms is
as follows:
There is an area (a box) around the door. If an object collides with this box, the right door will move constantly to the right, whilst the left door will move to the left. There is an object hidden in the scene, whose purpose is to block the door movement. If they are colliding, the door will stop moving. Also, if they are colliding, switch 1 will be set. For a switch I will use a hidden lighting spot brightness value. If Switch 1 is set and the there is no object inside the area, the doors will close. After the doors collide, switch 1 turns off.
Now it starts to get 'exciting'... and by 'exciting' I mean 'headache-inducing'. Because this is a tutorial and not a show-off, please keep in mind that I will introduce some logical pathways and connections in a way that could be done much simpler. The sole purpose of this method is not to confuse you, but to teach you some new nodes and different methods of logic. So then, what will you need before starting this tutorial?
And what will you learn?
Sounds cool doesn't it? Well, lets get right onto the action then!
This is how I laid out my scene. Arrange it the way you want, though. It's your scene!

If you just want a bland generic scene to complete the tutorial and learn Xpresso basics without all the needless fluff, arrange it like this:

If your doors are made up of different objects like mine, group them together to
one object, preferably a Null. Assign ALL objects you will want to "open" the
door to a Null object too, in case you want to use multiple objects.
The Door Blockers are not seen since they are inside the walls.
The Area Box must be invisible. To do this, either create a material with no color, no specular and 100% transparency and
assign it to the box, or simply disable the object
from being seen in the final render. Either way works, though I prefer the first (so
its optionally transparent in the view port too).
The Switch is a lighting spot, which can be problematic because it emits an
unwanted light in your scene. To correct this, go into the attributes window of the
Light object, find the General tab, and mark the "No Light Radiation" box.
We are done here. Moving on....
Section 3 - Making Doors Open When Something Comes Close
The first thing we will need to do is to create an XPresso function. You can assign
it to any object, but let's assign it to the Area Box for now. Right click your
Area Box in the Object Manager, select New Expression and click XPresso
Expression. Double click it. It will open the XPresso window, which should
look a little like this:

Your clean XPresso Window!
From this point onwards, I will work with a single door, and teach you how to clone the
properties to the other one later. This will make things much simpler for us in
the long term.
For our first step we will need to make the door open when something gets near
it. Do to this, all we need to do is define logic so that when the object
(called Sphere from now on to keep things simple) collides with the invisible
area box, the right door moves to the
right side.
To do this, drag-and-drop the Sphere and the Area Box to the XPresso window. It will
show nodes of them. Right click in the window, and select New Node > XPresso >
General > Collision. This is a node that, if a collision happens between the
"Inputs", will give an output of "True". If no collision happens,
the Output will be "false". Simple logic really.
We will need to connect these Object nodes to the Collision Inputs. So click on the
red button (which I will call the Output button, and the blue button the Input button) in
the upper-right of the sphere node. An array of inputs will now be made
available to you and the node that you just clicked. Select "object",
and do the same for the Area Box Node.
An Object output should appear with a red spot. Click and hold the left button
on that red spot and move it. A line will appear, allowing you to connect with an
input. Drag the line to Input 1, and a connection will appear. Do the same
for the other object but with Input 2. This sets up a simple logical
configuration - i.e. when those two objects collide, the output of Collision
node will be "1", or "True". If they are not colliding, it will be "0", or
"False". Simple, huh?

PS: If your "colliding" object is in fact a group of many objects, check
"Include Children" in the Node tab of the Collision's attributes in the
attribute window.
Now the logic gets a little more complex. We need to make it so that when they collide, the door will move to the right. Sooo.... how do we calculate this move to the right? Well, in my scene, the path the door moves is in the X Axis (check yours separately). The door's movement, therefore, in programming terms, can be described as:
X Axis (final) = X Axis (start) + Value where value is the rate of the movement
or, more simply:
X Axis = X Axis + y
We will need to make nodes that calculate this equation. Drag and drop the Right
Door into the scene. We will need to get it's X Position, then add a value (y) to
give the final output. Since we will be getting it's X Position, click in
the Output button and select Coordinates > Position > Position.X (or whatever
axis are you using). We now need to add the Y value to it. Right click in the XPresso window and choose
New Node > XPresso >
Calculate > Math. Ah-hah! We have a Math operator now! This is how it works - It
will catch the value of the first input and add it to the second input. It's
value will be then sent to the Output.
You can leave the second input blank, as you can manually set it to a value.
With this explained, click on the Math node and, in the attributes window's
parameter tab, type a
number in Input (2). The number you set here varies greatly with your preference
and the scene scale, so I really can't help you. My advice is to start with a
value of 1, and adjust it later if your doors open too slowly or quickly. In the Node Tab you
can adjust the Function but, since we are merely adding adding values, leave it
as add. Now connect the Position.X of the Right Door with the Math:Add
Input 1.
We want the output of this little equation to be sent directly back to the Right Door's position X
(thereby allowing additive movement along the X axis), so drag-and-drop another
Right Door node, and connect as Position.X input. Connect the Math's output with it.
Your XPresso screen should now look a little something like this:

To summarize what we have done so far: The X-axis position of the Right Door is
retrieved (node 1), added to an arbitrary
value of your choice (node 2), and then assigned back to the Right Door X-axis
position, changing it permanently (node
3).
We have now to connect both series of nodes, so that the door will only move to
the right if the sphere is colliding with the area box. Thankfully, there is an input called "On",
which ensures that nodes are only enabled if they are receiving an input of
'true'. With this in mind, click on the Input box of the last
Right-Door Node and create the 'ON' node, then connect it to the Collision Output.
You should now have something like this:

Save the Scene, and try moving the sphere inside the Area Box. If you have done
everything correctly, the right door should move to the right. If the door
absolutely won't move at all, check it all again, as you must have done
something very wrong. This is also the ideal time to check the movement speed of
your door and tweak it a little before the coding gets too hefty.
Section 4 - Making Doors Stop When They Hit The Blocker Object
The Logic behind this step is actually in reverse - The doors won't "stop" when they hit the
Blocker, they just move when they are NOT hitting the blocker. I know it sounds
confusing, but you will understand it soon enough...
The first thing we need to do is create the collision between the right door and the blocker
object. So, insert both objects' nodes and a collision node and connect them just
like the first. You should get something like this:

Now things are starting to get serious - How are we going to make the door stop
moving when it is colliding with the blocker? The answer is simple - we'll use Boolean
functions! A Boolean function is one that plays with
True and False values. We will configure the scene so that when the Area-Object Collision is True and Door-Blocker is False, the door moves, and if Area-Object is True and Door-Blocker True too, the door won't move. If Area-Object collision is false, independently of the Door-Blocker, the door won't
move either.
Of course, we could just add a Dynamics module into the scene and be lazy, but
what would be the fun of it? It is also unfortunate that this little cheat would make
our scene MUCH slower to render!
Our boolean functions should IDEALLY look like this:
| Area Box Collision | Blocker Collision | Movement |
| 1 (TRUE) | 1 (TRUE) | 0 (FALSE) |
| 1 (TRUE) | 0 (FALSE) | 1 (TRUE) |
| 0 (FALSE) | 1 (TRUE) | 0 (FALSE) |
| 0 (FALSE) | 0 (FALSE) | 0 (FALSE) |
If this were possible, movement would only occur if Input 1 is 1 and Input 2 is 0. Unfortunately such Boolean functionality does not exist. But what if we 'invert' the Blocker Collision values? The table would then look like this:
| Area Box Collision | Blocker Collision | Movement |
| 1 (TRUE) | 0 (FALSE) | 0 (FALSE) |
| 1 (TRUE) | 1 (TRUE) | 1 (TRUE) |
| 0 (FALSE) | 0 (FALSE) | 0 (FALSE) |
| 0 (FALSE) | 1 (TRUE) | 0 (FALSE) |
As you can see, this function would only work if both collision values are true
(i.e. 1). Such a function
exists - It's the Boolean AND function.
But how can we make Blocker Collision's values change? There are two ways
actually, but for now, we will be using another Boolean function, XOR. XOR
means "Exclusive OR". To understand XOR, you need to understand OR. The OR
function results a true if at least one of the inputs are true. The XOR
results true if ONLY ONE of the inputs are true - If both are true then it
will result false. Such a big meanie!
OR Table:
| Area Box Collision | Blocker Collision | Movement |
| 1 (TRUE) | 1 (TRUE) | 1 (TRUE) |
| 1 (TRUE) | 0 (FALSE) | 1 (TRUE) |
| 0 (FALSE) | 1 (TRUE) | 1 (TRUE) |
| 0 (FALSE) | 0 (FALSE) | 0 (FALSE) |
XOR Table:
| Area Box Collision | Blocker Collision | Movement |
| 1 (TRUE) | 1 (TRUE) | 0 (FALSE) |
| 1 (TRUE) | 0 (FALSE) | 1 (TRUE) |
| 0 (FALSE) | 1 (TRUE) | 1 (TRUE) |
| 0 (FALSE) | 0 (FALSE) | 0 (FALSE) |
If we add a Boolean XOR between the Blocker Collision and a "1" value, we will effectively invert the value. i.e. 1 (TRUE) will become 0 (FALSE) and vice versa. The Final Result would be:
| Blocker Result | Area Box | Result |
| 1 (TRUE) | 1 (TRUE) | 1 (TRUE) |
| 0 (FALSE) | 1 (TRUE) | 0 (FALSE) |
| 1 (TRUE) | 0 (FALSE) | 0 (FALSE) |
| 0 (FALSE) | 0 (FALSE) | 0 (FALSE) |
Since the last node On value is only enabled by a True condition, the only true
condition of this situation would be with the Blocker Collision off and the Area
Box Collision on, which is what we need! If the Area Collision ceases, the
movement will stop, and if the Blocker collision happens, the movement will also
stop.
Still keeping up? Finding this a little confusing? If case your brain is getting hot,
try
some C.O.F.F.E.E.! Yeah that was a nasty, evil joke. Sorry. ;)
Now back to the tutorial. Right click the window and select New Node > XPresso >
Bool > Bool. Create two Booleans, as one will be the XOR and the other will be
AND. Connect the XOR first input with the Blocker Collision node output. Now
connect the AND first node with the Area Box Collision, and the second with the XOR boolean output. Connect it's output with the last Right Door Node On Input.
Now, you will need to create a value to XOR with the Blocker Collision. Right
click and select New Node > XPresso > Calculate > Absolute. Leave it's input alone and
connect the Output with the XOR Boolean's second input.
Now on the attribute window. Click on the Absolute node and set it's value to
1, as it will input to the XOR as a true value. Click the XOR Boolean and, in the Node tab,
choose XOR as a function (naturally). Do the same for the AND Boolean, but
selecting the AND Value (obviously). All your hard work and patience with this
section should have left you with an XPresso screen like this:

We're done here (finally). The next part won't be so hard, I promise!
;)
Section 5 - Turning On The Switch When The Door Stops
Moving
Well, do you remember what I said about the Lightspot being a Switch? Yep, we're
going to need a Switcher to make the door go back to its original position. The
idea is that when the door collides with the Blocker, a switch is set. If this
switch is on and there is no object in area box, then the door will return. When
both doors collide, the switch turns off. Thus, if the switch is off and there is no object in the area
box, the door will stop. If the switch is on and there is an object in the area
box the doors
will be stopped (they might be just colliding with the blocker in this case).
If switch is off and the object is in the area box, then the door will move in
the direction of the blocker until it collides with it.
This part is easy. If the Blocker collision is true, then the Switch will be
turned on.
With that overly verbose explanation over, let's begin with the fun:
Firstly, drag-and-drop the Switch to XPresso. Add an On node and a Brightness
node
to it. The On node's function is obvious - It will be activated if the Collision is true. The
Brightness is the value we'll use as the On/Off. Now, keep in mind that the
Brightness works as a percentage - and we're working with real values. Thus 100%
= 1 and 0% = 0. Perfect for a true/false statement. There are many "Brightness" inputs in the Lightspot
object, but we are using the one in the General tab, so always use the General > Brightness input. Make sure
this is correct, as it will not work if you use the wrong one!
Now onto the juicy stuff! Firstly, connect the On value with the Blocker
Collision. This way if they
collide the node will be enabled. Then, connect the Brightness with the
Absolute
value we have created previously for the XOR Boolean node. Since you connect an
output to various inputs, there will be no problem. Just connect it's output
with the Lightspot Brightness input. You should end up with something like this:

Nothing else to see here! Moving on....
Section 6 - Breaktime
By now you can appreciate how awesomely tiresome it can be to learn a programming
pseudo-class and remain a dedicated artist. I have, therefore, decided to include this chapter,
which has the sole
purpose of getting you to relax or take a break (if you haven't had one
already). It may be a bit ridiculous, but
I've been studying psychology and this is a technique that sounded interesting to
me. It gives your brain a bit of relaxation, and can restore clearer thinking. So, have your
break time and let's move on!
Section 7 - Making The Door Return
Just to add to the confusion a little, we are now going to create a different
series of nodes. Remember the Switch? Well, we will make a script
that responds to
the "True" condition by moving the right door to the left.
So, without further ado, add the Lightspot node, and insert a Brightness output. Now, add two Right Door nodes
and a Math node. We're going to do the opposite of what we've done before.
Create a Position.X Output in the first node and a Position.X with an
On Input on
the last node. Connect this On node with the Switch Brightness.
Set the Math function to subtract and enter the same value in Input 2 that
you used in the first Math function. Connect Input 1 to the Position.X
Output of the first Right Door node, and the Output to the Position.X Input of
the second door node. You should end up with a separate little node trail
looking like this:

The door must stop when both the right and left doors collide. We can do this by disabling the Brightness Switch. To do this, simply insert both Right and Left Door and connect them with a Collision node. Connect the output of this Collision node with an On input in a new Switch node, and connect an absolute node with value 0 with the brightness input of the Switch. This way, when they collide, the brightness will be reduced to 0, and thus the doors will stop. Your full, unadulterated screen in XPresso should now look like this:
Now, copy and paste all these nodes, and invert all the Right Door values to Left
Door values, Right Blocks to Left Blocks, the Maths subtract to add functions, and vice-versa,
thus cloning the code onto the left door.
And that is it - You're done! Congratulations! By learning these basics of
XPresso you will make future projects much easier to manage. If you feel
suitably enthusiastic, you should now go try new methods of getting the same
door movement. There are tons of different routes. Almost anything you can
imagine is possible here. Oh, and remember, if you have any feedback or
further questions, you can
send me an e-mail over at kaliath@-idontlikespam-uol.com.br (where -idontlikespam-
is removed). See ya!