コード例 #1
0
ファイル: ODESimulator.cpp プロジェクト: sub77/hobbycode
		void internal_raycastCollisionCallback(void* data, dGeomID o0,
		                                        dGeomID o1)
		{
			if (dGeomIsSpace(o0) || dGeomIsSpace(o1))
			{
				// Colliding a space with either a geom or another space.
				dSpaceCollide2(o0, o1, data,
					&internal_raycastCollisionCallback);
			}
			else
			{
				// Colliding two geoms.

				// Sometimes we get a case where the ray geom is passed in
				// as both objects, which is stupid.
				if (o0 == o1)
				{
					return ;
				}

				// Get a pointer to the ODESimulator.
				ODESimulator* sim = (ODESimulator*) data;

				// Get pointers to the two geoms' GeomData structure.  One
				// of these (the one NOT belonging to the ray geom)
				// will always be non-NULL.
				GeomData* geomData0 = ((GeomData*) dGeomGetData(o0));
				GeomData* geomData1 = ((GeomData*) dGeomGetData(o1));

				// Find the contact group of the collided Solid.
				unsigned int geomContactGroup = defaults::shape::contactGroup;
				if (geomData0)
				{
					geomContactGroup = geomData0->shape->contactGroup;
				}
				else
				{
					geomContactGroup = geomData1->shape->contactGroup;
				}

				// Check if the two Solids' contact groups generate contacts
				// when they collide.
				bool makeContacts = sim->groupsMakeContacts(
					geomContactGroup, sim->internal_getRayContactGroup());
				if (!makeContacts)
				{
					return ;
				}

				// Now actually test for collision between the two geoms.
				// This is a fairly expensive operation.
				dContactGeom contactArray[defaults::ode::maxRaycastContacts];
				int numContacts = dCollide(o0, o1, 
					defaults::ode::maxRaycastContacts, contactArray,
					sizeof(dContactGeom));

				if (0 == numContacts)
				{
					return ;
				}
				else
				{
					// These two geoms must be intersecting.  We will store 
					// only the closest RaycastResult.
					int closest = 0;
					for (int i = 0; i < numContacts; ++i)
					{
						if (contactArray[i].depth < contactArray[closest].depth)
						{
							closest = i;
						}
					}

					// Only one of the geoms will be part of a Solid we 
					// want to store; the other is the ray.
					Solid* solid = NULL;
					if (geomData0)
					{
						solid = geomData0->solid;
					}
					else
					{
						solid = geomData1->solid;
					}

					Point3r intersection((real) contactArray[closest].pos[0],
						(real) contactArray[closest].pos[1],
						(real) contactArray[closest].pos[2]);
					Vec3r normal((real) contactArray[closest].normal[0],
						(real) contactArray[closest].normal[1],
						(real) contactArray[closest].normal[2]);

					sim->internal_addRaycastResult(solid, intersection, 
						normal, (real) contactArray[closest].depth);
				}
			}
		}