RubenGarza.com - MaxScript Tutorials  
  E-Mail
Back to Maxscript Home
     
 

Tutorial 03 - Simple Collision Detection

We will create a script that makes a wheel follow over terrain in this tutorial. This script will not have any UI. and will only work for specific objects. Since we already know how to create a UI, I will leave it to you to create a more general form of this script.

 
     
     
 

So, the first step is to create a new script. Open the listener window, and select "New Script..." under the file menu.

We first need to create 3 variables that correspond to objects in our scene.

terrainGeometry = $ground
rayCaster = $WheelGuide
wheel = $wheel

 
     
     
 

The three variables represent or ground, the wheel, and a wheel control object. The wheel itself will have lots of animation applied to it, so to keep things neat, we will parent it to a control object. We will animate the wheel guide over the terrain, and let the script make the wheel geometry follow the ground. Lets take a look at the corresponding max file.

 
     
     
 

Download Max file here.

There are three objects in this file, and they correspond to the three variables in our script. You will see that the wheel is parented to the wheel guide. The wheel guide is just a spline object. The terrain is a plane with noise added to it. The wheel guide has some animation on it. It travels in a straight line over the terrain. Lets create the code to make the wheel follow the terrain.

rayToTerrain = ray rayCaster.pos [0,0,-1]	
Zposition = intersectRay terrainGeometry rayToTerrain	
wheel.pos.z = Zposition.pos.z + rayCaster.radius
Three lines of code and we have it. If you copy and paste the text into a maxscipt and evaluate, the wheel will drop down to the terrain. Lets see why this works.
 
     
     
 

The variable rayToTerrain is the key to this code. In it we are storing a ray. A ray is a line in 3D space that has an origin and a direction. In math terms, it is known as a vector. So, for the wheel to collide with the ground, we shoot this ray from a point above the terrain straight down. So, we use the wheel guide as our starting point, since we know it is above the ground. Instead of typing $WheelGuide we use a variable rayCaster. We do this so we can easily change what is shooting the ray in the top part where we define our variable rather than having to change this name in every instance of our code. So, rayCaster.pos equals the x,y,z position of $WheelGuide.

The number [0,0,-1] represents a point3 value. This is the direction of the vector. We need the value normalized, which means all the numbers add up to one. So, in a point3 variable, the three numbers represent x,y,and z. So, if you wanted to cast a ray onto a wall, you would use the same line of code, but change the point3 value to [1,0,0]

The next variable, Zposition, uses another new maxscript command. intersectRay. This command is formatted intersectRay node ray. So, the node is what object the ray will intersect and the ray is the rayToTerrain variable we set up previously. The output is a point3 value giving the 3D point that the ray hits the geometry of the node.

The last line sets the wheel position. We know the point that the ray intersects the ground, so we just set the wheel's z position (wheel.pos.z) to equal that intersection value that we stored in Zposition. We then add the radius of the wheelGuide circle to push it up off the ground. One fun thing to try is adjusting the radius of the circle and seeing the results if you rerun the script.

 

 
     
     
 

Lets change the code so that we animate the wheel during the course of the animation. Here is the code:

terrainGeometry = $ground
rayCaster = $WheelGuide
wheel = $wheel
disableSceneRedraw() 
with animate on
(
	for currentTime = animationRange.start to animationRange.end do
	(
		slidertime = currentTime
		rayToTerrain = ray rayCaster.pos [0,0,-1]
		Zposition = intersectRay terrainGeometry rayToTerrain
		wheel.pos.z = Zposition.pos.z + rayCaster.radius
	)
)
enableSceneRedraw()
 
     
     
 

All we did here was disable scene redrawing (disableSceneRedraw) to speed up the script. If we don't do this, Max will redraw every change and be a lot slower. We must remember to enableSceneRedraw when we are done, otherwise Max won't update the viewports. Then we create a loop that goes from the first frame to the end frame and moves the wheel down per frame. The other new command we introduce here is with animate on which is just like having the animate button on.

So, if we run the script now, the wheel will animate over the terrain, and follow it as it rises and falls.

 
     
     
  Files:  
 

files/tut_03_wheel.ms
This is the completed Max script

 
  files/tut_03_wheel.max
This is the sample Max file.