private static void onCCDContactModify(PxCCDContactModifyCallback * @this, PxContactModifyPair *pairs, uint count) { for (uint i = 0; i < count; i++) { PxRigidActor **actors = (PxRigidActor **)&pairs[i].actor; //BIOQUIRK: Unobvious cast. PxShape ** shapes = (PxShape **)&pairs[i].shape; //BIOQUIRK: Unobvious cast //Search for actors that represent vehicles and shapes that represent wheels. for (uint j = 0; j < 2; j++) { PxRigidActor *actor = actors[j]; if (actor->userData != null && ((ActorUserData *)(actor->userData))->vehicle != null) { PxVehicleWheels *vehicle = ((ActorUserData *)(actor->userData))->vehicle; Debug.Assert(vehicle->getRigidDynamicActor() == actors[j]); PxShape *shape = shapes[j]; if (shape->userData != null && ((ShapeUserData *)(shape->userData))->isWheel) { uint wheelId = ((ShapeUserData *)(shape->userData))->wheelId; Debug.Assert(wheelId < vehicle->mWheelsSimData.getNbWheels()); //Modify wheel contacts. PxVehicleModifyWheelContacts(*vehicle, wheelId, WHEEL_TANGENT_VELOCITY_MULTIPLIER, MAX_IMPULSE, ref pairs[i]); } } } } }
private static void onContactModify(PxContactModifyCallback * @this, PxContactModifyPair *pairs, uint count) { for (uint i = 0; i < count; i++) { //BIOQUIRK: Probably the "more correct" thing to do here is to use the generated constant array type, but these types currently have long confusing names. // A Span<PxRigidActor*> would also be nice, but isn't possible in C# today. // Could be improved by https://github.com/MochiLibraries/Biohazrd/issues/139 PxRigidActor **actors = (PxRigidActor **)&pairs[i].actor; //BIOQUIRK: Unobvious cast. PxShape ** shapes = (PxShape **)&pairs[i].shape; //BIOQUIRK: Unobvious cast //Search for actors that represent vehicles and shapes that represent wheels. for (int j = 0; j < 2; j++) { PxRigidActor *actor = actors[j]; if (actor->userData != null && ((ActorUserData *)(actor->userData))->vehicle != null) { PxVehicleWheels *vehicle = ((ActorUserData *)(actor->userData))->vehicle; Debug.Assert(vehicle->getRigidDynamicActor() == actors[j]); PxShape *shape = shapes[j]; if (shape->userData != null && ((ShapeUserData *)(shape->userData))->isWheel) { uint wheelId = ((ShapeUserData *)(shape->userData))->wheelId; Debug.Assert(wheelId < vehicle->mWheelsSimData.getNbWheels()); //Modify wheel contacts. PxVehicleModifyWheelContacts(*vehicle, wheelId, WHEEL_TANGENT_VELOCITY_MULTIPLIER, MAX_IMPULSE, ref pairs[i]); } } } } }
/** * Creates two example collections: * - collection with actors and joints that can be instantiated multiple times in the scene * - collection with shared objects */ static void createCollections(ref PxCollection *sharedCollection, ref PxCollection *actorCollection, ref PxSerializationRegistry sr) { PxMaterial *material = gPhysics->createMaterial(0.5f, 0.5f, 0.6f); float halfLength = 2.0f, height = 25.0f; PxVec3 offset = new(halfLength, 0, 0); PxRigidActor *prevActor = (PxRigidActor *)PxCreateStatic(ref *gPhysics, new PxTransform(new PxVec3(0, height, 0)), new PxSphereGeometry(halfLength), ref *material, new PxTransform(offset)); //BIOQUIRK: Base cast PxShape *shape = gPhysics->createShape(new PxBoxGeometry(halfLength, 1.0f, 1.0f), *material, false, PxShapeFlags.eVISUALIZATION | PxShapeFlags.eSCENE_QUERY_SHAPE | PxShapeFlags.eSIMULATION_SHAPE); //BIOQUIRK: Missing defaults for (uint i = 1; i < 8; i++) { PxTransform tm = new(new PxVec3((float)(i * 2) * halfLength, height, 0)); PxRigidDynamic *dynamic = gPhysics->createRigidDynamic(tm); dynamic->attachShape(ref *shape); PxRigidBodyExt.updateMassAndInertia(ref *dynamic, 10.0f); PxSphericalJointCreate(ref *gPhysics, prevActor, new PxTransform(offset), dynamic, new PxTransform(offset.operator_Minus())); //BIOQUIRK: Operator overload prevActor = (PxRigidActor *)dynamic; //BIOQUIRK: Base cast } sharedCollection = PxCreateCollection(); // collection for all the shared objects actorCollection = PxCreateCollection(); // collection for all the nonshared objects sharedCollection->add(ref *shape); PxSerialization.complete(ref *sharedCollection, ref sr); // chases the pointer from shape to material, and adds it PxSerialization.createSerialObjectIds(ref *sharedCollection, 77); // arbitrary choice of base for references to shared objects actorCollection->add(ref *prevActor); PxSerialization.complete(ref *actorCollection, ref sr, sharedCollection, true); // chases all pointers and recursively adds actors and joints }
// Not applicable for Mochi-flavored snippet //static void idleCallback() //{ // glutPostRedisplay(); //} static void renderCallback() { stepPhysics(true); SnippetRender.startRender(sCamera.getEye(), sCamera.getDir()); PxScene *scene; PxGetPhysics()->getScenes(&scene, 1); uint nbActors = scene->getNbActors(PxActorTypeFlags.eRIGID_DYNAMIC); if (nbActors != 0) { Vector3 dynColor = new(1.0f, 0f, 1f); Vector3 kinematicColor = new(0f, 1f, 0f); // (Allocating on the heap here is not a good idea performance-wise, we only do it this way to keep close to the original snippet.) fixed(PxRigidActor **actors = new PxRigidActor *[nbActors]) { scene->getActors(PxActorTypeFlags.eRIGID_DYNAMIC, actors, nbActors); for (uint i = 0; i < nbActors; ++i) { PxRigidActor * actor = actors[i]; PxRigidDynamic *dyn; // = actor->is<PxRigidDynamic>(); //BIOQUIRK: No support for is<T> dyn = actor->getConcreteType() == (ushort)PxConcreteType.eRIGID_DYNAMIC ? static_cast <PxRigidDynamic>(actor) : null; if ((dyn->getRigidBodyFlags() & PxRigidBodyFlags.eKINEMATIC) != 0) { SnippetRender.renderActors(&actor, 1, true, kinematicColor); } else { SnippetRender.renderActors(&actor, 1, true, dynColor); } } } } SnippetRender.finishRender(); }
/** * Deserialize shared data and use resulting collection to deserialize and instance actor collections */ public static void deserializeObjects(ref PxInputData sharedData, ref PxInputData actorData) { PxSerializationRegistry *sr = PxSerialization.createSerializationRegistry(ref *gPhysics); PxCollection *sharedCollection = null; { if (gUseBinarySerialization) { void *alignedBlock = createAlignedBlock(sharedData.getLength()); sharedData.read(alignedBlock, sharedData.getLength()); sharedCollection = PxSerialization.createCollectionFromBinary(alignedBlock, ref *sr); } else { sharedCollection = PxSerialization.createCollectionFromXml(ref sharedData, ref *gCooking, ref *sr); } } // Deserialize collection and instantiate objects twice, each time with a different transform PxTransform *transforms = stackalloc PxTransform[2] { new PxTransform(new PxVec3(-5.0f, 0.0f, 0.0f)), new PxTransform(new PxVec3(5.0f, 0.0f, 0.0f)) }; for (uint i = 0; i < 2; i++) { PxCollection *collection = null; // If the PxInputData actorData would refer to a file, it would be better to avoid reading from it twice. // This could be achieved by reading the file once to memory, and then working with copies. // This is particulary practical when using binary serialization, where the data can be directly // converted to physics objects. actorData.seek(0); if (gUseBinarySerialization) { void *alignedBlock = createAlignedBlock(actorData.getLength()); actorData.read(alignedBlock, actorData.getLength()); collection = PxSerialization.createCollectionFromBinary(alignedBlock, ref *sr, sharedCollection); } else { collection = PxSerialization.createCollectionFromXml(ref actorData, ref *gCooking, ref *sr, sharedCollection); } for (uint o = 0; o < collection->getNbObjects(); o++) { //BIOQUIRK: is<T> is not translated https://github.com/MochiLibraries/Mochi.PhysX/issues/11 //PxRigidActor* rigidActor = collection->getObject(o).is<PxRigidActor>(); PxRigidActor *rigidActor = null; { PxBase *obj = collection->getObject(o); //BIOQUIRK: Because PxRigidActor is not concrete, this ends up going down the isKindOf path, which is not publicly accessible. // This is special-cased for this snippet, ideally we should just expose is<T> in a more C#-friendly way. if ((PxConcreteType)obj->getConcreteType() is PxConcreteType.eRIGID_STATIC or PxConcreteType.eARTICULATION_LINK or PxConcreteType.eRIGID_DYNAMIC) { rigidActor = (PxRigidActor *)obj; } } if (rigidActor != null) { PxTransform globalPose = rigidActor->getGlobalPose(); globalPose = globalPose.transform(transforms[i]); rigidActor->setGlobalPose(globalPose); } } gScene->addCollection(*collection); collection->release(); } sharedCollection->release(); PxMaterial *material; gPhysics->getMaterials(&material, 1); PxRigidStatic *groundPlane = PxCreatePlane(ref *gPhysics, new PxPlane(0, 1, 0, 0), ref *material); gScene->addActor(ref *groundPlane); sr->release(); }