Exemplo n.º 1
0
void SweepTest::FindTouchedCCTs(	NxU32 nb_boxes, const NxExtendedBounds3* boxes, const void** box_user_data,
									NxU32 nb_capsules, const NxExtendedCapsule* capsules, const void** capsule_user_data,
									const NxExtendedBounds3& world_box)
{
	NxExtendedVec3 Origin;	// Will be TouchedGeom::mOffset
	world_box.getCenter(Origin);

	// Find touched boxes, i.e. other box controllers
	for(NxU32 i=0;i<nb_boxes;i++)
	{
		if(!world_box.intersect(boxes[i]))
			continue;

		TouchedUserBox* UserBox = (TouchedUserBox*)reserve(mGeomStream, sizeof(TouchedUserBox)/sizeof(NxU32));
		UserBox->mType		= TOUCHED_USER_BOX;
		UserBox->mUserData	= box_user_data[i];
		UserBox->mOffset	= Origin;
		UserBox->mBox		= boxes[i];
	}

	// Find touched capsules, i.e. other capsule controllers
	NxExtendedVec3 Center;
	NxVec3 Extents;
	world_box.getCenter(Center);
	world_box.getExtents(Extents);
	NxMat33 Idt;
	Idt.id();
	for(NxU32 i=0;i<nb_capsules;i++)
	{
		// Do a quick AABB check first, to avoid calling the SDK too much
		const NxF32 r = capsules[i].radius;
		if((capsules[i].p0.x - r > world_box.max.x) || (world_box.min.x > capsules[i].p1.x + r)) continue;
		if((capsules[i].p0.y - r > world_box.max.y) || (world_box.min.y > capsules[i].p1.y + r)) continue;
		if((capsules[i].p0.z - r > world_box.max.z) || (world_box.min.z > capsules[i].p1.z + r)) continue;

		// Do a box-capsule intersect, or skip it? => better to skip it, not really useful now
/*		NxCapsule tmp;
		tmp.radius = capsules[i].radius;
		tmp.p0.x = float(capsules[i].p0.x);
		tmp.p0.y = float(capsules[i].p0.y);
		tmp.p0.z = float(capsules[i].p0.z);
		tmp.p1.x = float(capsules[i].p1.x);
		tmp.p1.y = float(capsules[i].p1.y);
		tmp.p1.z = float(capsules[i].p1.z);
		float d2 = gUtilLib->NxSegmentOBBSqrDist(tmp, NxVec3(float(Center.x), float(Center.y), float(Center.z)), 
											Extents, 
											Idt, NULL, NULL);
		if(d2<capsules[i].radius*capsules[i].radius)*/
		{
			TouchedUserCapsule* UserCapsule = (TouchedUserCapsule*)reserve(mGeomStream, sizeof(TouchedUserCapsule)/sizeof(NxU32));
			UserCapsule->mType		= TOUCHED_USER_CAPSULE;
			UserCapsule->mUserData	= capsule_user_data[i];
			UserCapsule->mOffset	= Origin;
			UserCapsule->mCapsule	= capsules[i];
		}
	}
}
void CCTDebugData::addAABB(const NxExtendedBounds3& bounds, NxU32 color)
{
	NxExtendedVec3 center;
	NxVec3 extents;
	bounds.getCenter(center);
	bounds.getExtents(extents);

	NxBounds3 tmp;
	tmp.setCenterExtents(NxVec3((float)center.x, (float)center.y, (float)center.z), extents);

	addAABB(tmp, color, false);
}
Exemplo n.º 3
0
bool FindTouchedGeometry(
	void* user_data,
	const NxExtendedBounds3& worldBounds,		// ### we should also accept other volumes

	TriArray& world_triangles,
	TriArray* world_edge_normals,
	IntArray& edge_flags,
	IntArray& geom_stream,

	NxU32 group_flags,
	bool static_shapes, bool dynamic_shapes, const NxGroupsMask* groupsMask)
	{
	NX_ASSERT(user_data);
	NxScene* scene = (NxScene*)user_data;

	NxExtendedVec3 Origin;	// Will be TouchedGeom::mOffset
	worldBounds.getCenter(Origin);

	// Reserve a stack buffer big enough to hold all shapes in the world. This is a lazy approach that is
	// acceptable here since the total number of shapes is limited to 64K anyway, which would "only" consume
	// 256 Kb on the stack (hence, stack overflow is unlikely).
	// ### TODO: the new callback mechanism would allow us to use less memory here
//	NxU32 total = scene->getNbStaticShapes() + scene->getNbDynamicShapes();
	NxU32 total = scene->getTotalNbShapes();
	NxShape** buffer = (NxShape**)NxAlloca(total*sizeof(NxShape*));

	// Find touched *boxes* i.e. touched objects' AABBs in the world
	// We collide against dynamic shapes too, to get back dynamic boxes/etc
	// TODO: add active groups in interface!

	NxU32 Flags = 0;
	if(static_shapes)	Flags |= NX_STATIC_SHAPES;
	if(dynamic_shapes)	Flags |= NX_DYNAMIC_SHAPES;

	// ### this one is dangerous
	NxBounds3 tmpBounds;	// LOSS OF ACCURACY
	tmpBounds.min.x = (float)worldBounds.min.x;
	tmpBounds.min.y = (float)worldBounds.min.y;
	tmpBounds.min.z = (float)worldBounds.min.z;
	tmpBounds.max.x = (float)worldBounds.max.x;
	tmpBounds.max.y = (float)worldBounds.max.y;
	tmpBounds.max.z = (float)worldBounds.max.z;
	NxU32 nbTouchedBoxes = scene->overlapAABBShapes(tmpBounds, NxShapesType(Flags), total, buffer, NULL, group_flags, groupsMask);

	// Early exit if no AABBs found
	if(!nbTouchedBoxes)	return false;
	NX_ASSERT(nbTouchedBoxes<=total);	// Else we just trashed some stack memory

	// Loop through touched world AABBs
	NxShape** touched = buffer;
	while(nbTouchedBoxes--)
		{
		// Get current shape
		NxShape* shape = *touched++;

		// Filtering

		// Discard all CCT shapes, i.e. kinematic actors we created ourselves. We don't need to collide with them since they're surrounded
		// by the real CCT volume - and collisions with those are handled elsewhere. We use the userData field for filtering because that's
		// really our only valid option (filtering groups are already used by clients and we don't have control over them, clients might
		// create other kinematic actors that we may want to keep here, etc, etc)
		if(size_t(shape->userData)=='CCTS')
			continue;

		// Discard if not collidable
		// PT: this shouldn't be possible at this point since:
		// - the SF flag is only used for compounds
		// - the AF flag is already tested in scene query
		// - we shouldn't get compound shapes here
		if(shape->getFlag(NX_SF_DISABLE_COLLISION))
			continue;

		// Ubi (EA) : Discarding Triggers :
		if ( shape->getFlag(NX_TRIGGER_ENABLE) )
			continue;

		// PT: here you might want to disable kinematic objects.

		// Output shape to stream
		NxShapeType type = shape->getType();
				if(type==NX_SHAPE_SPHERE)		outputSphereToStream((NxSphereShape*)shape, shape, geom_stream, Origin);
		else	if(type==NX_SHAPE_CAPSULE)		outputCapsuleToStream((NxCapsuleShape*)shape, shape, geom_stream, Origin);
		else	if(type==NX_SHAPE_BOX)			outputBoxToStream((NxBoxShape*)shape, shape, geom_stream, Origin);
		else	if(type==NX_SHAPE_MESH)			outputMeshToStream((NxTriangleMeshShape*)shape, shape, geom_stream, world_triangles, world_edge_normals, edge_flags, Origin, tmpBounds);
		else	if(type==NX_SHAPE_HEIGHTFIELD)	outputHeightFieldToStream((NxHeightFieldShape*)shape, shape, geom_stream, world_triangles, world_edge_normals, edge_flags, Origin, tmpBounds);
		else	if(type==NX_SHAPE_CONVEX)		outputConvexToStream((NxConvexShape*)shape, shape, geom_stream, world_triangles, world_edge_normals, edge_flags, Origin, tmpBounds);
		}

	return true;
	}