- 最后登录
- 2024-6-3
- 注册时间
- 2009-10-16
- 阅读权限
- 100
- 积分
- 18803
  
- 纳金币
- 17488
- 精华
- 1
|
Summary
This sample project shows how to use the Model.intersect() method exposed to script to write your own collision detection.
Category
Tutorials
Author
Gavin Kistner
Difficulty
Intermediate
Time to Complete
10 Minutes
Downloads
Click Here to download the associated files.
This sample project shows the use of the intersect() method, made available on all Models in Anark Client during at runtime. First, click on picture below to view the sample project, and play with it a bit to see what it does.
![]()
click to view the sample project in action
As you drag the end points of the segment, the model turns orange if the segment is hitting it. Further, a yellow arrow shows exactly where the segment hits the model, and is rotated to show the direction of the 'normal' of the face where that collision occurs.
The intersect() method used for this test lets you check to see if an "ideal" line segment intersects the model that invoked the method. To be clear about this: Anark Client does not support model-on-model collision detection. (At least not in version 3.0 ;)
The 'line' that connects the two end points of the segment in this presentation is actually a long, thin cylinder. This is only a visual representation of the segment being used for collision detection. With careful movements, you can set it up so that an edge of the line is hitting the model, but the infinitely-thin segment being used for collision detection does not. Only the line connecting the centers of the two ends is used for collision.
![]()
The cylinder itself is not being used for collision detection.
Download the AMW file for the sample project, and open it up. The "Watch for Intersection" behavior (inside the "Content Layer") performs the collision detection for this presentation, and is what we want to look at. Double-click this behavior to view its code.
Initialization
At the top of the behavior, even before it gets its onAttach event, we create a few objects. These are created here instead of during onUpdate in order to save memory. By creating them once and then re-using them each time, we save the (small) amount of memory that would be wasted if we created three new vectors every frame.
onAttach
One more custom property is saved during onAttach, just to make things a little bit faster (and easier to type) during the onUpdate call. (A topic for another tutorial is the speed gain achieved by reducing DOM path navigation.)
onUpdate
Here be dragons! Just kidding, don't be scared. This is where the magic happens, but it's really not that many lines.
There are three steps in collision detection:
Calculate the segment which will be used to check for collisions.
Check to see if the segment intersects the model.
If it does intersect, do something useful with the information.
As noted above, the intersect() method tells you whether or not a segment intersects the model. You describe this segment to the method using three values:
The start location of the segment.
This is a Vector object, and must be specified in global space.
The direction that the segment points.
This is also a Vector object, in this case used to indicate a direction, not location. Think of it this way: if you start at 0,0,0 (the global origin) and move towards the point in space indicated by this vector, that's the direction the segment will go.
The length of the segment.
The magnitude of the direction vector is unimportant. This (single number) value is used to tell the intersect() method how far from the start point to look for a hit before it gives up.
There are three other parameters which you must pass to the method, in addition to those mentioned above:
Whether or not to use backfaces of the model.
If the materials on your model are all double-sided, this (boolean) parameter is irrelevant. This only matters when your model is single-sided. If this value is false, AND the segment hits a face of your model that is single-sided, AND the direction the segment is travelling comes from the back side of the face...then the hit will be ignored.
Put another way, leaving this as false will result in slightly better performance, but if your start point is in the inside of a single-side model, you won't get a hit as the segment comes out through a face.
A 'hitSpot' vector.
The values in this vector are ignored. IF you get a hit, then this vector will be modified to represent the exact spot (in global space) where the hit occurred.
A 'hitNormal' vector.
Again, the values of this vector are ignored. IF you get a hit, then this vector will be modified to represent the direction of the normal on the face where the hit occurred.
Armed with this knowledge, the lines of code in the onUpdate section should seem pretty simple. The first two lines create the global direction vector for the segment. The next line calculates how far it is between the start and end points. Then the call to the intersect() method is made.
When a hit occurs (when the call to the method returns a value greater than or equal to zero), the last two vectors passed into the method (hitSpot and hitNormal) are modified to hold the information about the hit. These are then used to move the yellow arrow to the exact spot of the collision, and to rotate it to point out from the face.
Common "Gotchas"
A few things to watch out for when using this method:
Make sure that your start point and ray direction vectors are in global space, not the local transformation coordinates of the model.
The vector indicating ray direction indicates the direction from 0,0,0 (or the offset from the start point), not a location. If you know the end point of your ray, subtract the start point from it to find the global direction offset.
The value returned by the method is the distance from the start point to the hit spot squared. It also may be exactly zero, if your start point is in the plane of the face being hit.
Even if you don't care about the normal of the face where a hit occurs, or even the exact spot of the hit, you must pass vectors in for these parameters. (For better memory usage, re-use the same 'junk' vectors each time.)
Like the start point, the hit location and face normal are in global space.
|
|