MagicPhysX
.NET PhysX 5 binding to all platforms(win-x64, osx-x64, osx-arm64, linux-x64, linux-arm64) for 3D engine, deep learning, dedicated server of gaming. This library is built on top of NVIDIA PhysX 5 and physx-rs.
Use case:
- 3D View for MAUI, WPF, Avalonia
- Physics for Your Own Game Engine
- Simulate robotics for deep learning
- Server side physics for dedicated server of gaming
Getting Started
PhysX Binding provides all of PhysX feature through C API. This library is distributed via NuGet.
PM> Install-Package MagicPhysX
C API is provided in NativeMethods
in MagicPhysX
namespace. Methods are almostly prefixed phys_Px
or Px
. In addition, extension methods are defined for contexts, just like object-oriented methods. For example, for PxPhysics*
:
PxPhysics* physics = physx_create_physics(foundation);
// C API
PxScene* scene1 = PxPhysics_createScene_mut(physics, &sceneDesc);
// Extension methods
PxScene* scene2 = physics->CreateSceneMut(&sceneDesc);
Extension methods API is simpler and similar as original C++ PhysX API.
Here is the simple bound sphere on plane sample.
using MagicPhysX; // for enable Extension Methods.
using static MagicPhysX.NativeMethods; // recommend to use C API.
// create foundation(allocator, logging, etc...)
var foundation = physx_create_foundation();
// create physics system
var physics = physx_create_physics(foundation);
// create physics scene settings
var sceneDesc = PxSceneDesc_new(PxPhysics_getTolerancesScale(physics));
// you can create PhysX primitive(PxVec3, etc...) by C# struct
sceneDesc.gravity = new PxVec3 { x = 0.0f, y = -9.81f, z = 0.0f };
var dispatcher = phys_PxDefaultCpuDispatcherCreate(1, null, PxDefaultCpuDispatcherWaitForWorkMode.WaitForWork, 0);
sceneDesc.cpuDispatcher = (PxCpuDispatcher*)dispatcher;
sceneDesc.filterShader = get_default_simulation_filter_shader();
// create physics scene
var scene = physics->CreateSceneMut(&sceneDesc);
var material = physics->CreateMaterialMut(0.5f, 0.5f, 0.6f);
// create plane and add to scene
var plane = PxPlane_new_1(0.0f, 1.0f, 0.0f, 0.0f);
var groundPlane = physics->PhysPxCreatePlane(&plane, material);
scene->AddActorMut((PxActor*)groundPlane, null);
// create sphere and add to scene
var sphereGeo = PxSphereGeometry_new(10.0f);
var vec3 = new PxVec3 { x = 0.0f, y = 40.0f, z = 100.0f };
var transform = PxTransform_new_1(&vec3);
var identity = PxTransform_new_2(PxIDENTITY.PxIdentity);
var sphere = physics->PhysPxCreateDynamic(&transform, (PxGeometry*)&sphereGeo, material, 10.0f, &identity);
PxRigidBody_setAngularDamping_mut((PxRigidBody*)sphere, 0.5f);
scene->AddActorMut((PxActor*)sphere, null);
// simulate scene
for (int i = 0; i < 200; i++)
{
// 30fps update
scene->SimulateMut(1.0f / 30.0f, null, null, 0, true);
uint error = 0;
scene->FetchResultsMut(true, &error);
// output to console(frame-count: position-y)
var pose = PxRigidActor_getGlobalPose((PxRigidActor*)sphere);
Console.WriteLine($"{i:000}: {pose.p.y}");
}
// release resources
PxScene_release_mut(scene);
PxDefaultCpuDispatcher_release_mut(dispatcher);
PxPhysics_release_mut(physics);
Other samples(FixedJoint
, DistanceJoint
, SphericalJoint
, RevoluteJoint
,RaycastSingle
, BricksDoubleDomino
, Geometries
) are exist in ConsoleSandbox.
Document
MagicPhysX uses physx-rs C binding(physx-sys). You can refer these document.
PhysX Visual Debugger
MagicPhysX can enable PhysX Visual Debugger to debug physcs scene.
To use pvd, add this instruction on scene init.
var foundation = physx_create_foundation();
// create pvd
var pvd = phys_PxCreatePvd(foundation);
fixed (byte* bytePointer = "127.0.0.1"u8.ToArray())
{
var transport = phys_PxDefaultPvdSocketTransportCreate(bytePointer, 5425, 10);
pvd->ConnectMut(transport, PxPvdInstrumentationFlags.All);
}
// create physics
uint PX_PHYSICS_VERSION_MAJOR = 5;
uint PX_PHYSICS_VERSION_MINOR = 1;
uint PX_PHYSICS_VERSION_BUGFIX = 3;
uint versionNumber = (PX_PHYSICS_VERSION_MAJOR << 24) + (PX_PHYSICS_VERSION_MINOR << 16) + (PX_PHYSICS_VERSION_BUGFIX << 8);
var tolerancesScale = new PxTolerancesScale { length = 1, speed = 10 };
var physics = phys_PxCreatePhysics(versionNumber, foundation, &tolerancesScale, true, pvd, null);
phys_PxInitExtensions(physics, pvd);
var sceneDesc = PxSceneDesc_new(PxPhysics_getTolerancesScale(physics));
sceneDesc.gravity = new PxVec3 { x = 0.0f, y = -9.81f, z = 0.0f };
var dispatcher = phys_PxDefaultCpuDispatcherCreate(1, null, PxDefaultCpuDispatcherWaitForWorkMode.WaitForWork, 0);
sceneDesc.cpuDispatcher = (PxCpuDispatcher*)dispatcher;
sceneDesc.filterShader = get_default_simulation_filter_shader();
var scene = PxPhysics_createScene_mut(physics, &sceneDesc);
// pvd client
var pvdClient = scene->GetScenePvdClientMut();
if (pvdClient != null)
{
pvdClient->SetScenePvdFlagMut(PxPvdSceneFlag.TransmitConstraints, true);
pvdClient->SetScenePvdFlagMut(PxPvdSceneFlag.TransmitContacts, true);
pvdClient->SetScenePvdFlagMut(PxPvdSceneFlag.TransmitScenequeries, true);
}
Toolkit Sample
C API is slightly complex in C# usage. Here is the sample of high level framework, PhysicsSystem.
using MagicPhysX.Toolkit;
using System.Numerics;
unsafe
{
using var physics = new PhysicsSystem(enablePvd: false);
using var scene = physics.CreateScene();
var material = physics.CreateMaterial(0.5f, 0.5f, 0.6f);
var plane = scene.AddStaticPlane(0.0f, 1.0f, 0.0f, 0.0f, new Vector3(0, 0, 0), Quaternion.Identity, material);
var sphere = scene.AddDynamicSphere(1.0f, new Vector3(0.0f, 10.0f, 0.0f), Quaternion.Identity, 10.0f, material);
for (var i = 0; i < 200; i++)
{
scene.Update(1.0f / 30.0f);
var position = sphere.transform.position;
Console.WriteLine($"{i:D2} : x={position.X:F6}, y={position.Y:F6}, z={position.Z:F6}");
}
}
Code sample is available in MagicPhysX.Toolkit.
Native Build Instruction
require Rust.
Open directory src\libmagicphysx
.
Run cargo build
.
Native binaries in package is built on GitHub Actions build-physx.yml. If we need to update physx-sys(PhysX) version, run this GitHub Actions to input physxversion.
License
This library is licensed under the MIT License.