RaycastHit Scene::raycastClosestShape(const Ray& ray, Enums::ShapesType type, unsigned int group, Real maxDistance, unsigned int hintFlags, RaycastCache cache) const { NxRay inRay; Functions::XYZ<Vec3, NxVec3>(ray.mDirection, inRay.dir); Functions::XYZ<Vec3, NxVec3>(ray.mOrigin, inRay.orig); NxRaycastHit hit; NxShape* nxShape = mScene->raycastClosestShape(inRay, NxShapesType(int(type)), hit, group, maxDistance, hintFlags, 0, cache); RaycastHit out; out.mDistance = hit.distance; out.mFaceID = hit.faceID; out.mFlags = hit.flags; out.mInternalFaceID = hit.internalFaceID; out.mMaterialIndex = hit.materialIndex; out.mU = hit.u; out.mV = hit.v; Functions::XYZ<NxVec3, Vec3>(hit.worldImpact, out.mWorldImpact); Functions::XYZ<NxVec3, Vec3>(hit.worldNormal, out.mWorldNormal); if (nxShape) { PhysXPointer* shapePointer = pointer_cast(nxShape->userData); out.mShape = shapePointer->get<Shape>(); out.mRigidBody = shapePointer->getParent<RigidBody>(); } else { out.mShape = 0; out.mRigidBody = 0; } return out; }
bool Scene::raycastAnyShape(const Ray& ray, Enums::ShapesType type, unsigned int groups, Real maxDistance, RaycastCache cache) const { NxRay inRay; Functions::XYZ<Vec3, NxVec3>(ray.mDirection, inRay.dir); Functions::XYZ<Vec3, NxVec3>(ray.mOrigin, inRay.orig); return mScene->raycastAnyShape(inRay, NxShapesType(int(type)), groups, maxDistance, 0, cache); }
unsigned int Scene::raycastAllBounds(const Ray& ray, Callback* callback, Enums::ShapesType type, unsigned int group, Real maxDistance, unsigned int hintFlags) const { NxRay inRay; Functions::XYZ<Vec3, NxVec3>(ray.mDirection, inRay.dir); Functions::XYZ<Vec3, NxVec3>(ray.mOrigin, inRay.orig); PhysXRaycastReport report(callback); return mScene->raycastAllBounds(inRay, report, NxShapesType(int(type)), group, maxDistance, hintFlags); }
bool Scene::raycastAnyBounds(const Ray& ray, Enums::ShapesType type, int4 groupsMask, Real maxDistance) const { NxRay inRay; Functions::XYZ<Vec3, NxVec3>(ray.mDirection, inRay.dir); Functions::XYZ<Vec3, NxVec3>(ray.mOrigin, inRay.orig); NxGroupsMask mask; mask.bits0 = groupsMask.w; mask.bits1 = groupsMask.x; mask.bits2 = groupsMask.y; mask.bits3 = groupsMask.z; return mScene->raycastAnyBounds(inRay, NxShapesType(int(type)), -1, maxDistance, &mask); }
unsigned int Scene::raycastAllBounds(const Ray& ray, Callback* callback, Enums::ShapesType type, int4 groupsMask, Real maxDistance, unsigned int hintFlags) const { NxRay inRay; Functions::XYZ<Vec3, NxVec3>(ray.mDirection, inRay.dir); Functions::XYZ<Vec3, NxVec3>(ray.mOrigin, inRay.orig); NxGroupsMask mask; mask.bits0 = groupsMask.w; mask.bits1 = groupsMask.x; mask.bits2 = groupsMask.y; mask.bits3 = groupsMask.z; PhysXRaycastReport report(callback); return mScene->raycastAllBounds(inRay, report, NxShapesType(int(type)), -1, maxDistance, hintFlags, &mask); }
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; }