/**
     * Initializes physics and creates a scene
     */
    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);
        gCooking = PxCreateCooking(PX_PHYSICS_VERSION, ref *gFoundation, new PxCookingParams(new PxTolerancesScale()));
        PxInitExtensions(ref *gPhysics, gPvd);

        uint numCores = SnippetUtils.getNbPhysicalCores();

        gDispatcher = PxDefaultCpuDispatcherCreate(numCores == 0 ? 0 : numCores - 1);
        PxSceneDesc sceneDesc = new(*gPhysics->getTolerancesScale());

        sceneDesc.gravity       = new PxVec3(0, -9.81f, 0);
        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);
        }
    }
    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
    }