The CollisionSolid is the fundamental object of the collision system. CollisionSolids represent special invisible geometry that is created solely for the purpose of performing collision tests; these CollisionSolids are stored in the scene graph alongside the normal visible geometry.
The CollisionSolids are specifically optimized for performing collision tests quickly. Collisions can be performed against visible geometry as well, but this is more expensive since visible geometry is not optimized for this sort of thing.
You can create CollisionSolids interactively in program code, or you can construct them in your modeling package and load them up from an egg or bam file along with the rest of your scene.
When you create a CollisionSolid interactively, you must also create a CollisionNode to hold the solid. (When you load your CollisionSolids in from an egg file, the CollisionNodes are created for you.) Often, a CollisionNode will be used to hold only one solid, but in fact a CollisionNode can contain any number of solids, and this is sometimes a useful optimization, especially if you have several solids that always move together as a unit.
cs = CollisionSphere(0, 0, 0, 1)
cnodePath = avatar.attachNewNode(CollisionNode('cnode'))
cnodePath.node().addSolid(cs)
|
CollisionNodes are hidden by default, but they may be shown for debugging purposes:
Note: Be aware that the collision algorithm has only limited awareness of scaling transforms applied to CollisionSolids. If unequal scaling is applied between a from collider and an into collider, unexpected results may occur. In general, strive to have as few scaling transforms applied to your collision solids as possible.
There are several kinds of CollisionSolids available.
CollisionSphere
The sphere is the workhorse of the collision system. Spheres are the fastest primitives for any collision calculation; and the sphere calculation is particularly robust. If your object is even vaguely spherical, consider wrapping a sphere around it.
Also, a sphere is a particularly good choice for use as a "from object", because a sphere can reliably be tested for collision with most of the other solid types. The "from objects" are the objects that are considered the active objects in the world; see Collision Traversers. A sphere is usually the best choice to put around the player's avatar, for instance. The sphere also makes a good "into object"; it is the only object type that is a good choice for both "from" and "into" objects.
A sphere is defined in terms of a center and a radius. Note that, like any object, the sphere's coordinates are defined in the sphere's own coordinate space, so that often the center is (0, 0, 0).
sphere = CollisionSphere(cx, cy, cz, radius)
|
CollisionTube
A "tube" is a cylinder with hemispherical endcaps. This shape is sometimes called a capsule in other collision systems.
The tube is good as an "into object", for objects that are largely cylindrical. It is not a very good choice for a "from object", because not many intersection tests have been written from tubes into other shapes.
A tube is defined with its two endpoints, and the cylindrical radius.
tube = CollisionTube(ax, ay, az, bx, by, bz, radius)
|
CollisionInvSphere
The inverse sphere is a special-purpose solid that is rarely used, but occasionally it is very useful. It is an inside-out sphere: the solid part of the sphere is on the outside. Any object that is on the outside of the sphere is considered to be colliding with it; any object on the inside is not colliding.
Think of the inverse sphere as a solid mass that fills the whole universe in all directions, except for a bubble of space in the middle. It's useful for constraining an object within a particular space, since nothing can get out of an inverse sphere.
inv = CollisionInvSphere(cx, cy, cz, radius)
|
CollisionPlane
The CollisionPlane is an infinite plane extending in all directions. It is not often used, but it can be useful in certain cases, for instance as a trigger placed below the ground to detect when an avatar has accidentally slipped through a crack in the world. You can also build a box out of six planes to keep objects perfectly constrained within a rectangular region, similar to an inverse sphere; such a box is much more reliable than one constructed of six polygons.
The plane actually divides the universe into two spaces: the space behind the plane, which is all considered solid, and the space in front of the plane, which is all empty. Thus, if an object is anywhere behind a plane, no matter how far, it is considered to be intersecting the plane.
A CollisionPlane is constructed using a Panda3D Plane object, which itself has a number of constructors, including the A, B, C, D plane equation, or a list of three points, or a point and a normal.
plane = CollisionPlane(Plane(Vec3(0, 0, 1), Point3(0, 0, 0)))
|
CollisionPolygon
A CollisionPolygon is the most general of the collision solids, since it is easy to model any shape with polygons (especially using a modeling package). However, it is also the most expensive solid, and the least robust--there may be numerical inaccuracies with polygons that allow collisions to slip through where they shouldn't.
Like a plane and a tube, a CollisionPolygon is only a good choice as an "into object". It doesn't support collision tests as a "from object".
In general, if you must use CollisionPolygons to model your shape, you should use as few polygons as possible. Use quads instead of triangles if possible, since two triangles take twice as much time to compute as a single quad. This does mean that you need to ensure that your quads are perfectly coplanar.
You can also make higher-order polygons like five-sided and six-sided polygons or more, but you cannot make concave polygons. If you create a concave or non-coplanar CollisionPolygon in your modeling package, Panda will automatically triangulate it for you (but this might result in a suboptimal representation, so it is usually better to subdivide a concave polygon by hand).
Unlike a plane, a CollisionPolygon is infinitely thin; an object is only considered to be colliding with the polygon while it is overlapping it.
When you create a CollisionPolygon interactively, you can only create triangles or quads (the higher-order polygons can only be loaded from an egg file). Simply specify the three or four points to the constructor, in counter-clockwise order.
quad = CollisionPolygon(Point3(0, 0, 0), Point3(0, 0, 1),
Point3(0, 1, 1), Point3(0, 1, 0))
|
CollisionRay
The ray, line, and segment (below) are special collision solids that are useful only as a "from" object; since these objects have no volume, nothing will collide "into" a ray.
The CollisionRay represents an infinite ray that begins at a specific point, and stretches in one direction to infinity.
It is particularly useful for picking objects from the screen, since you can create a ray that starts at the camera's point of view and extends into the screen, and then determine which objects that ray is intersecting. (In fact, there is a method on CollisionRay called setFromLens() that automatically sets up the ray based on a 2-d onscreen coordinate; this is used by the "picker". See Clicking on 3D Objects.)
The CollisionRay is also useful in conjunction with the CollisionHandlerFloor; see Collision Handlers.
A CollisionRay is created by specifing an origin point, and a direction vector. The direction vector need not be normalized.
ray = CollisionRay(ox, oy, oz, dx, dy, dz)
|
CollisionLine
This is essentially the same as a CollisionRay, except it extends to infinity in both directions. It is constructed with the same parameters, an origin point and a direction vector.
line = CollisionLine(ox, oy, oz, dx, dy, dz)
|
CollisionSegment
Finally, a segment is another variant on the CollisionRay that does not extend to infinity, but only goes to a certain point and stops. It is useful when you want to put a limit on how far the CollisionRay would otherwise reach.
A CollisionSegment is constructed by specifying the two end points.
segment = CollisionSegment(ax, ay, az, bx, by, bz)
|
|