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); }
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; }