Another good question: in Spazz 3D, how do you make something like a door that opens when you click it, then closes when you click it again.
Here are three ways of doing it:
1) A single animation with a toggle.
2) An animated invisible trigger.
Open door1.wrl. If you click the door just once, it will open, remain open for about 4 seconds, then close again. You can also click it to start the animation; then, when it's open, click to stop the animation and keep it open. Click again to start the animation, and (after a short pause) it will close again.
This is the method I use with my Deluxe Recliner.
There is only one animation for reclining - it tilts the chair back, then sets it upright again. In the middle of the animation, I pause for a few seconds. I use a TouchSensor on the handle, and set it as a toggle. When you click the handle, the animation starts, tilting the chair back to its fully reclined position. When you click it again, the animation stops in the current position. This method will work for drawers and other objects that essentially have two positions and animate between them.
Summary:
Open door2.wrl. Click the door, and you'll see the "invisible" trigger appear around the door. Click the invisible trigger, and the door will close again. In this example, I make the Invisible Trigger only half transparent (.5), so that you can see it in action - when you use it on your objects, set the transparency to 1.
I've used this method most recently on the lid to my Happy Homemaker Washing Machine. It uses two triggers - one on the door, the other on an invisible object.
First I make the door, and animations that open and close the door.
I put the door in a group (hint - put the group between the hinges of the door, and animate the group - easier to animate the group at the hinges than to try to animate the rotation of the object from its own center). I add a TouchSensor to the group, and have it trigger the Open animation.
I create a second box named InvisibleTrigger that's slightly larger than the door in all directions. I position it in the exact center of the door. Then, I set its scale to .001, hiding it inside the door. I put the InvisibleTrigger into a group, drag that group into the Door group, and set its Trans to x0, y0, z0 (center it in the door - be sure you add the InvisibleTrigger's group to the door group, so that it moves with the door). I add a TouchSensor to the group, and have it trigger the Close animation.
I go back into the Open animation, and add the InvisibleTrigger to the list of nodes. I animate the scale of the InvisibleTrigger so that when the animation is complete, it is uniformly scaled at 1 (i.e., slightly larger than the door in all directions).
I go back into the Close animation, and add the InvisibleTrigger to the list of nodes. I animate the scale of the InvisibleTrigger so that when the animation is complete, it is back to its tiny .001 size.
Finally, we have to make the InvisibleTrigger invisible. Selecting one of the materials that I'm not using in the object (say, Shiny_Purple), I assign that color to the InvisibleTrigger, and change the Transparency of the material to 1 (making it 100% transparent).
Now, when I click the door, the animation opens it and expands the InvisibleTrigger to cover the door. When I click again, I hit the InvisibleTrigger, rather than the door itself. As the door closes, the InvisibleTrigger shrinks down again, and is hidden inside the door.
Summary:
Here's a simple world where I've modified (by hand) the VRML script produced by Spazz3D to alternately open and close the door.
If you look at the script, all that I'm doing is intercepting the TouchSensor event. I use a Boolean (TRUE/FALSE) variable to remember whether the door should be opened or closed.
The first time, the value is true, and the current time is sent to the openDoor TimeSensor to start its animation. The next time the TouchSensor is clicked, the Boolean variable is changed to false, and the current time is sent to the closeDoor TimeSensor to start its animation. Don't be intimidated by VRML script - it's not much more difficult to learn than HTML,and it gives you much more control over the worlds you create.
#VRML V2.0 utf8
WorldInfo {
title "Spazz3D"
info [
"This VRML World was created with Spazz3D, a VRML 97 authoring tool"
"www.spazz3d.com"
]
}
DEF dad_GROUND Transform {
children [
DEF GROUND Group {
children [
DEF dad_doorGroup Transform {
translation -0.5 0.0 0.0
children [
DEF doorGroup Group {
children [
DEF dad_door Transform {
translation 0.5 0.0 0.0
children [
DEF door Shape {
appearance Appearance {
material DEF Red_mat Material {
ambientIntensity 0.200
shininess 0.200
diffuseColor 1.0 0.0 0.0
}
}
geometry Box {
size 1.0 2.0 0.05
}
}
]
}
DEF Sensor1 TouchSensor {
}
]
}
]
}
]
}
]
}
DEF openDoor TimeSensor {
cycleInterval 2.000
loop FALSE
startTime -1
}
DEF openDoor_rot0 OrientationInterpolator {
key [
0.0 1.0
]
keyValue [
0.0 1.0 0.0 0.0
0.0 1.0 0.0 1.571
]
}
DEF closeDoor TimeSensor {
cycleInterval 2.000
loop FALSE
startTime -1
}
DEF closeDoor_rot0 OrientationInterpolator {
key [
0.0 1.0
]
keyValue [
0.0 1.0 0.0 1.571
0.0 1.0 0.0 0.0
]
}
#theScript
DEF ToggleDoor Script {
field SFBool state FALSE
eventIn SFTime toggle
eventOut SFTime startClose
eventOut SFTime startOpen
url "vrmlscript:
function toggle(curtime) {
state = !state;
if (state) {
startOpen = curtime;
startClose = -1;
}
else
{
startOpen = -1;
startClose = curtime;
}
}
"
}
ROUTE Sensor1.touchTime TO ToggleDoor.toggle
ROUTE ToggleDoor.startClose TO closeDoor.startTime
ROUTE ToggleDoor.startOpen TO openDoor.startTime
ROUTE openDoor.fraction_changed TO openDoor_rot0.set_fraction
ROUTE openDoor_rot0.value_changed TO dad_doorGroup.set_rotation
ROUTE closeDoor.fraction_changed TO closeDoor_rot0.set_fraction
ROUTE closeDoor_rot0.value_changed TO dad_doorGroup.set_rotation
Do you have some better ideas for opening/closing doors? Send them to Epistomolus, and I'll add them to this page.
Back to Creating Objects for Cybertown
Send your comments on this page to Epistomolus.
Updated February 23, 2007