Пример #1
0
    public static void initPhysics(bool interactive)
    {
        gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, ref gAllocator.Value, ref gErrorCallback.Value);
        gPvd        = PxCreatePvd(ref *gFoundation);
        PxPvdTransport *transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);

        gPvd->connect(ref *transport, PxPvdInstrumentationFlags.eALL);

        gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, ref *gFoundation, new PxTolerancesScale(), true, gPvd);

        PxSceneDesc sceneDesc = new(*gPhysics->getTolerancesScale());

        sceneDesc.gravity       = new PxVec3(0.0f, -9.81f, 0.0f);
        gDispatcher             = PxDefaultCpuDispatcherCreate(2);
        sceneDesc.cpuDispatcher = (PxCpuDispatcher *)gDispatcher; //BIOQUIRK: Base cast
        sceneDesc.filterShader  = PxDefaultSimulationFilterShader;
        gScene = gPhysics->createScene(sceneDesc);
        PxPvdSceneClient *pvdClient = gScene->getScenePvdClient();

        if (pvdClient != null)
        {
            pvdClient->setScenePvdFlag(PxPvdSceneFlags.eTRANSMIT_CONSTRAINTS, true);
            pvdClient->setScenePvdFlag(PxPvdSceneFlags.eTRANSMIT_CONTACTS, true);
            pvdClient->setScenePvdFlag(PxPvdSceneFlags.eTRANSMIT_SCENEQUERIES, true);
        }
        gMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0.6f);

        PxRigidStatic *groundPlane = PxCreatePlane(ref *gPhysics, new PxPlane(0, 1, 0, 0), ref *gMaterial);

        gScene->addActor(ref *groundPlane);

        createKinematics();
        createDynamics();
    }
    /**
     * 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
    }
    public static void initPhysics(bool interactive)
    {
        gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, ref gAllocator.Value, ref gErrorCallback.Value);
        gPvd        = PxCreatePvd(ref *gFoundation);
        PxPvdTransport *transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);

        gPvd->connect(ref *transport, PxPvdInstrumentationFlags.eALL);

        gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, ref *gFoundation, new PxTolerancesScale(), true, gPvd);
        PxInitExtensions(ref *gPhysics, gPvd);

        PxSceneDesc sceneDesc = new(*gPhysics->getTolerancesScale());

        sceneDesc.gravity = new PxVec3(0.0f, -9.81f, 0.0f);

        uint numCores = SnippetUtils.getNbPhysicalCores();

        gDispatcher             = PxDefaultCpuDispatcherCreate(numCores == 0 ? 0 : numCores - 1);
        sceneDesc.cpuDispatcher = (PxCpuDispatcher *)gDispatcher; //BIOQUIRK: Base cast
        sceneDesc.filterShader  = PxDefaultSimulationFilterShader;

#if USE_REDUCED_COORDINATE_ARTICULATION
        sceneDesc.solverType = PxSolverType.eTGS;
#if CREATE_SCISSOR_LIFT
        sceneDesc.filterShader = &scissorFilter;
#endif
#endif

        gScene = gPhysics->createScene(sceneDesc);
        PxPvdSceneClient *pvdClient = gScene->getScenePvdClient();
        if (pvdClient != null)
        {
            pvdClient->setScenePvdFlag(PxPvdSceneFlags.eTRANSMIT_CONSTRAINTS, true);
            pvdClient->setScenePvdFlag(PxPvdSceneFlags.eTRANSMIT_CONTACTS, true);
            pvdClient->setScenePvdFlag(PxPvdSceneFlags.eTRANSMIT_SCENEQUERIES, true);
        }

        gMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0f);

        PxRigidStatic *groundPlane = PxCreatePlane(ref *gPhysics, new PxPlane(0, 1, 0, 0), ref *gMaterial);
        gScene->addActor(ref *groundPlane);

#if USE_REDUCED_COORDINATE_ARTICULATION
        gArticulation = gPhysics->createArticulationReducedCoordinate();
#else
        gArticulation = gPhysics->createArticulation();

        // Stabilization can create artefacts on jointed objects so we just disable it
        gArticulation->setStabilizationThreshold(0.0f);

        gArticulation->setMaxProjectionIterations(16);
        gArticulation->setSeparationTolerance(0.001f);
#endif

#if USE_REDUCED_COORDINATE_ARTICULATION && CREATE_SCISSOR_LIFT
        createScissorLift();
#else
        createLongChain();
#endif
    }
Пример #4
0
    public static PxVehicleDrivableSurfaceToTireFrictionPairs *createFrictionPairs(PxMaterial *defaultMaterial)
    {
        PxVehicleDrivableSurfaceType *surfaceTypes = stackalloc PxVehicleDrivableSurfaceType[1];

        surfaceTypes[0].mType = SURFACE_TYPE_TARMAC;

        PxMaterial **surfaceMaterials = stackalloc PxMaterial *[1];

        surfaceMaterials[0] = defaultMaterial;

        PxVehicleDrivableSurfaceToTireFrictionPairs *surfaceTirePairs =
            PxVehicleDrivableSurfaceToTireFrictionPairs.allocate(MAX_NUM_TIRE_TYPES, MAX_NUM_SURFACE_TYPES);

        surfaceTirePairs->setup(MAX_NUM_TIRE_TYPES, MAX_NUM_SURFACE_TYPES, surfaceMaterials, surfaceTypes);

        for (uint i = 0; i < MAX_NUM_SURFACE_TYPES; i++)
        {
            for (uint j = 0; j < MAX_NUM_TIRE_TYPES; j++)
            {
                surfaceTirePairs->setTypePairFriction(i, j, gTireFrictionMultipliers[i, j]);
            }
        }
        return(surfaceTirePairs);
    }
Пример #5
0
        public static void Main(string[] args)
        {
            Console.WriteLine($"PhysX native runtime build information: '{MochiPhysX.BuildInfo}'...");

            //---------------------------------------------------------------------------------------------------------------------------------------
            Console.WriteLine("Initializing error callback");
            // Switch between these to use PhysX's default error callback or one implemented from C#
            PxDefaultErrorCallback errorCallback = new();

            //PxErrorCallback errorCallback = ErrorCallback.Create();

            //---------------------------------------------------------------------------------------------------------------------------------------
            Console.WriteLine("Initializing allocator callback");
            // Switch between these to use PhysX's default allocator callback or one implemented from C#
            PxDefaultAllocator allocator = new();

            //PxAllocatorCallback allocator = BasicAllocator.Create();
            //PxAllocatorCallback allocator = LoggingAllocator.Create();

            //---------------------------------------------------------------------------------------------------------------------------------------
            Console.WriteLine("Initializing foundation");
            //BIOQUIRK: PhysX owns both of these references, which means both the allocator and error callback must remain pinned for the lifetime of the foundation.
            // (In our case they're stack allocated and implicitly pinned.)
            // This seems somewhat unobvious since C# references don't normally care. Should we emit this function differently to convey the unsafe-ness here?
            PxFoundation *foundation = PxCreateFoundation(PX_PHYSICS_VERSION, ref allocator, ref errorCallback);

            if (foundation == null)
            {
                Console.Error.WriteLine("Failed to create foundation.");
                return;
            }

            //---------------------------------------------------------------------------------------------------------------------------------------
            Console.WriteLine("Initializing Pvd...");
            //BIOQUIRK: This pattern comes up a lot in PhysX. It does technically match how it is in C++ though, not sure if it's a problem.
            // I experimentally enabled having C++ reference returns translate as C# reference returns, but that creates a weird situation when you need to store them.
            PxPvd *pvd = PxCreatePvd(ref *foundation);

            PxPvdTransport *transport;

            byte[] host = Encoding.ASCII.GetBytes("127.0.0.1");
            fixed(byte *hostP = host)
            {
                transport = PxDefaultPvdSocketTransportCreate(hostP, 5425, 10);
            }

            Console.WriteLine("Connecting to Pvd...");
            pvd->connect(ref *transport, PxPvdInstrumentationFlags.eALL);

            //---------------------------------------------------------------------------------------------------------------------------------------
            Console.WriteLine("Initializing physics");
            PxPhysics *physics = PxCreatePhysics(PX_PHYSICS_VERSION, ref *foundation, new PxTolerancesScale(), trackOutstandingAllocations: true, pvd);

            if (physics == null)
            {
                Console.Error.WriteLine("Failed to create physics.");
                return;
            }

            //---------------------------------------------------------------------------------------------------------------------------------------
            Console.WriteLine("Creating dispatcher");
            PxDefaultCpuDispatcher *dispatcher = PxDefaultCpuDispatcherCreate(2, null);

            //---------------------------------------------------------------------------------------------------------------------------------------
            Console.WriteLine("Creating scene");
            PxSceneDesc sceneDescription = new(*physics->getTolerancesScale());

            sceneDescription.gravity = new PxVec3()
            {
                x = 0f, y = -9.81f, z = 0f
            };
            sceneDescription.cpuDispatcher = (PxCpuDispatcher *)dispatcher;
            sceneDescription.filterShader  = PxDefaultSimulationFilterShader;
            PxScene *scene = physics->createScene(sceneDescription);

            //---------------------------------------------------------------------------------------------------------------------------------------
            Console.WriteLine("Configuring scene Pvd client");
            PxPvdSceneClient *pvdClient = scene->getScenePvdClient();

            if (pvdClient != null)
            {
                pvdClient->setScenePvdFlag(PxPvdSceneFlags.eTRANSMIT_CONSTRAINTS, true);
                pvdClient->setScenePvdFlag(PxPvdSceneFlags.eTRANSMIT_CONTACTS, true);
                pvdClient->setScenePvdFlag(PxPvdSceneFlags.eTRANSMIT_SCENEQUERIES, true);
            }

            //---------------------------------------------------------------------------------------------------------------------------------------
            Console.WriteLine("Creating a basic material");
            PxMaterial *material = physics->createMaterial(0.5f, 0.5f, 0.6f);

            //---------------------------------------------------------------------------------------------------------------------------------------
            Console.WriteLine("Adding a ground plane");
            PxPlane planeDescription = new PxPlane()
            {
                n = new PxVec3()
                {
                    x = 0f,
                    y = 1f,
                    z = 0f
                },
                d = 0f
            };
            PxRigidStatic *groundPlane = PxCreatePlane(ref *physics, planeDescription, ref *material);

            scene->addActor(ref *groundPlane, null);

            //---------------------------------------------------------------------------------------------------------------------------------------
            Console.WriteLine("Adding stacks");
            {
                const float   halfExtent       = 2f;
                PxBoxGeometry stackBoxGeometry = new PxBoxGeometry(halfExtent, halfExtent, halfExtent);
                PxShapeFlags  shapeFlags       = PxShapeFlags.eVISUALIZATION | PxShapeFlags.eSCENE_QUERY_SHAPE | PxShapeFlags.eSIMULATION_SHAPE;
                //BIOQUIRK: shapeFlags should be able to be defaulted now but it isn't.
                PxShape *shape  = physics->createShape(stackBoxGeometry, *material, isExclusive: false, shapeFlags);
                float    stackZ = 10f;
                for (int stackNum = 0; stackNum < 5; stackNum++)
                {
                    const int size = 10;

                    PxVec3 transformPosition = new PxVec3()
                    {
                        x = 0f,
                        y = 0f,
                        z = stackZ -= 10f
                    };
                    PxTransform transform = new(transformPosition);

                    for (int i = 0; i < size; i++)
                    {
                        for (int j = 0; j < size - i; j++)
                        {
                            PxVec3 position = new PxVec3()
                            {
                                x = ((float)(j * 2) - (float)(size - i)) * halfExtent,
                                y = ((float)(i * 2 + 1)) * halfExtent,
                                z = 0f
                            };
                            PxTransform localTransform = new(position);

                            PxTransform     bodyTransform = transform.transform(localTransform);
                            PxRigidDynamic *body          = physics->createRigidDynamic(bodyTransform);
                            body->attachShape(ref *shape);
                            PxRigidBodyExt.updateMassAndInertia(ref *body, 10f);
                            scene->addActor(ref *body);
                        }
                    }
                }
                shape->release();
            }

            //---------------------------------------------------------------------------------------------------------------------------------------
            Console.WriteLine("Throwing a ball at the stacks");
            {
                PxVec3 position = new PxVec3()
                {
                    x = 0f,
                    y = 40f,
                    z = 100f,
                };
                PxTransform      transform = new(position);
                PxSphereGeometry geometry  = new(10f);

                PxVec3 velocity = new PxVec3()
                {
                    x = 0f,
                    y = -50f,
                    z = -100f
                };

                PxTransform     identity = new(default(PxIDENTITY)); //BIOQUIRK: This could be a special generated property instead. Also missing default.
                PxRigidDynamic *dynamic  = PxCreateDynamic(ref *physics, transform, geometry, ref *material, 10f, identity);
                dynamic->setAngularDamping(0.5f);
                dynamic->setLinearVelocity(velocity);
                scene->addActor(ref *dynamic);
            }

            //---------------------------------------------------------------------------------------------------------------------------------------
            const int noInputFrameCount = 100;

            Console.WriteLine($"Simulating the world{(Console.IsInputRedirected ? $" for {noInputFrameCount} frames." : "... (Press escape to stop.)")}");
            Stopwatch sw       = new Stopwatch();
            int       frameNum = 0;

            const uint scratchMemoryBlockSize  = 16 * 1024;
            const uint scratchMemoryBlockCount = 4;
            uint       scratchMemorySize       = scratchMemoryBlockSize * scratchMemoryBlockCount;
            void *     scratchMemory           = allocator.allocate(scratchMemorySize, null, null, 0);

            while (true)
            {
                double msSinceLastTick = sw.Elapsed.TotalMilliseconds;
                string consoleTitle    = $"Simulating frame {frameNum} -- {msSinceLastTick:0.00} ms -- {1.0 / (msSinceLastTick / 1000.0):00.0} FPS";
                if (BasicAllocator.AllocationCount > 0) // This is only applicable when a allocator implemented in C# is in use, assume 0 allocations implies the PhysX one is being used
                {
                    consoleTitle += $" -- {BasicAllocator.AllocationCount} allocations";
                    BasicAllocator.AllocationCount = 0;
                }
                Console.Title = consoleTitle;
                frameNum++;

                sw.Restart();

                scene->simulate(1f / 60f, scratchMemBlock: scratchMemory, scratchMemBlockSize: scratchMemorySize);

                uint errors;
                scene->fetchResults(true, &errors);
                if (errors != 0)
                {
                    Console.WriteLine($"fetchResults error: {errors}");
                }

                if (Console.IsInputRedirected)
                {
                    if (frameNum > noInputFrameCount)
                    {
                        break;
                    }
                }
                else if (Console.KeyAvailable && Console.ReadKey(true).Key == ConsoleKey.Escape)
                {
                    break;
                }
            }

            //---------------------------------------------------------------------------------------------------------------------------------------
            Console.WriteLine("Shutting down");
            allocator.deallocate(scratchMemory);
            physics->release();
            foundation->release();
        }
Пример #6
0
    public static void initPhysics()
    {
        gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, ref gAllocator.Value, ref gErrorCallback.Value);
        gPvd        = PxCreatePvd(ref *gFoundation);
        PxPvdTransport *transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);

        gPvd->connect(ref *transport, PxPvdInstrumentationFlags.eALL);
        gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, ref *gFoundation, new PxTolerancesScale(), true, gPvd);

        PxSceneDesc sceneDesc = new(*gPhysics->getTolerancesScale());

        sceneDesc.gravity = new PxVec3(0.0f, -9.81f, 0.0f);

        uint numWorkers = 1;

        gDispatcher             = PxDefaultCpuDispatcherCreate(numWorkers);
        sceneDesc.cpuDispatcher = (PxCpuDispatcher *)gDispatcher; //BIOQUIRK: Base cast
        sceneDesc.filterShader  = &VehicleFilterShader;

        gScene = gPhysics->createScene(sceneDesc);

        PxPvdSceneClient *pvdClient = gScene->getScenePvdClient();

        if (pvdClient != null)
        {
            pvdClient->setScenePvdFlag(PxPvdSceneFlags.eTRANSMIT_CONSTRAINTS, true);
            pvdClient->setScenePvdFlag(PxPvdSceneFlags.eTRANSMIT_CONTACTS, true);
            pvdClient->setScenePvdFlag(PxPvdSceneFlags.eTRANSMIT_SCENEQUERIES, true);
        }
        gMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0.6f);

        gCooking = PxCreateCooking(PX_PHYSICS_VERSION, ref *gFoundation, new PxCookingParams(new PxTolerancesScale()));

        /////////////////////////////////////////////

        PxInitVehicleSDK(ref *gPhysics);
        PxVehicleSetBasisVectors(new PxVec3(0, 1, 0), new PxVec3(0, 0, 1));
        PxVehicleSetUpdateMode(PxVehicleUpdateMode.eVELOCITY_CHANGE);

        //Create the batched scene queries for the suspension raycasts.
        gVehicleSceneQueryData = VehicleSceneQueryData.allocate(1, PX_MAX_NB_WHEELS, 1, 1, &WheelSceneQueryPreFilterBlocking, null, ref gAllocator.Value);
        gBatchQuery            = VehicleSceneQueryData.setUpBatchedSceneQuery(0, *gVehicleSceneQueryData, gScene);

        //Create the friction table for each combination of tire and surface type.
        gFrictionPairs = createFrictionPairs(gMaterial);

        //Create a plane to drive on.
        PxFilterData groundPlaneSimFilterData = new((uint)COLLISION_FLAG_GROUND, (uint)COLLISION_FLAG_GROUND_AGAINST, 0, 0);

        gGroundPlane = createDrivablePlane(groundPlaneSimFilterData, gMaterial, gPhysics);
        gScene->addActor(ref *gGroundPlane);

        //Create a vehicle that will drive on the plane.
        VehicleDesc vehicleDesc = initVehicleDesc();

        gVehicleNoDrive = createVehicleNoDrive(vehicleDesc, gPhysics, gCooking);
        PxTransform startTransform = new(new PxVec3(0, (vehicleDesc.chassisDims.y * 0.5f + vehicleDesc.wheelRadius + 1.0f), 0), new PxQuat(PxIdentity));

        gVehicleNoDrive->getRigidDynamicActor()->setGlobalPose(startTransform);
        gScene->addActor(ref *gVehicleNoDrive->getRigidDynamicActor());

        //Set the vehicle to rest in first gear.
        //Set the vehicle to use auto-gears.
        gVehicleNoDrive->setToRestState();

        gVehicleModeTimer     = 0.0f;
        gVehicleOrderProgress = 0;
        startBrakeMode();
    }