Table of Contents

Nvidia PhysX

物理引擎


安装流程

可参考:physxsetup.pdf

  1. 下载的内容是代码,需要自行编译
  2. blast/flow/physx的代码放在同一个仓库中,但是编译是分开的,编译自己需要的就可以了
  3. 安装CMake,physx/generate_projects.bat搭建编译环境
  4. VS中自行编译
  5. 配置Include和Link之后,就可以使用了
  6. PhysX的CRT使用的是MT,使用PhysX的工程也需要使用MT(默认是MD)

Hello World

// 这是PhysX API的一个Hello World程序,不带渲染
 
#include <algorithm>
 
#include <PxPhysicsAPI.h>
 
constexpr auto PVD_HOST = "localhost";
 
using namespace physx;
 
// 用于管理和分配内存,这里使用的是一份默认的实现
// 实现这个类以定制某些功能
static PxDefaultAllocator gAllocator;
// 错误处理类,这里使用的也是默认实现
static PxDefaultErrorCallback gErrorCallback;
 
static PxFoundation* gFoundation = NULL;
static PxPhysics* gPhysics = NULL;
 
// 这是个啥
static PxDefaultCpuDispatcher* gDispatcher = NULL;
 
// 场景和材质
static PxScene* gScene = NULL;
static PxMaterial* gMaterial = NULL;
 
// [?]用于调试
static PxPvd* gPvd = NULL;
 
static PxReal stackZ = 10.0f;
 
// 向场景中添加Actor
static PxRigidDynamic* createDynamic(const PxTransform& t, const PxGeometry& geometry, const PxVec3& velocity = PxVec3(0))
{
    PxRigidDynamic* dynamic = PxCreateDynamic(*gPhysics, t, geometry, *gMaterial, 10.0f);
    dynamic->setAngularDamping(0.5f);
    dynamic->setLinearVelocity(velocity);
    gScene->addActor(*dynamic);
    return dynamic;
}
 
// 向场景中添加Actor
static void createStack(const PxTransform& t, PxU32 size, PxReal halfExtent)
{
    PxShape* shape = gPhysics->createShape(PxBoxGeometry(halfExtent, halfExtent, halfExtent), *gMaterial);
    for (PxU32 i = 0; i < size; i++)
    {
        for (PxU32 j = 0; j < size - i; j++)
        {
            PxTransform localTm(PxVec3(PxReal(j * 2) - PxReal(size - i), PxReal(i * 2 + 1), 0) * halfExtent);
            PxRigidDynamic* body = gPhysics->createRigidDynamic(t.transform(localTm));
            body->attachShape(*shape);
            PxRigidBodyExt::updateMassAndInertia(*body, 10.0f);
            gScene->addActor(*body);
        }
    }
    shape->release();
}
 
inline void initPhysics(bool interactive)
{
    // 创建Foundation
    gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
 
    gPvd = PxCreatePvd(*gFoundation);
    PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);
    gPvd->connect(*transport, PxPvdInstrumentationFlag::eALL);
 
    // 创建Physics
    gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(), true, gPvd);
 
    // 创建场景
    PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
    sceneDesc.gravity = PxVec3(0.0f, -9.81f, 0.0f);
    gDispatcher = PxDefaultCpuDispatcherCreate(2);
    sceneDesc.cpuDispatcher = gDispatcher;
    sceneDesc.filterShader = PxDefaultSimulationFilterShader;
    gScene = gPhysics->createScene(sceneDesc);
 
    PxPvdSceneClient* pvdClient = gScene->getScenePvdClient();
    if (pvdClient)
    {
        pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true);
        pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, true);
        pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, true);
    }
 
    // 创建材质
    gMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0.6f);
 
    // 向场景中添加Actor
    PxRigidStatic* groundPlane = PxCreatePlane(*gPhysics, PxPlane(0, 1, 0, 0), *gMaterial);
    gScene->addActor(*groundPlane);
 
    for (PxU32 i = 0; i < 5; i++)
        createStack(PxTransform(PxVec3(0, 0, stackZ -= 10.0f)), 10, 2.0f);
 
    if (!interactive)
        createDynamic(PxTransform(PxVec3(0, 40, 100)), PxSphereGeometry(10), PxVec3(0, -50, -100));
}
 
// 步进
void stepPhysics(bool /*interactive*/)
{
    gScene->simulate(1.0f / 60.0f);
    gScene->fetchResults(true);
}
 
// 清理工作
void cleanupPhysics(bool /*interactive*/)
{
    PX_RELEASE(gScene);
    PX_RELEASE(gDispatcher);
    PX_RELEASE(gPhysics);
    if (gPvd)
    {
        PxPvdTransport* transport = gPvd->getTransport();
        gPvd->release();	gPvd = NULL;
        PX_RELEASE(transport);
    }
    PX_RELEASE(gFoundation);
 
    printf("SnippetHelloWorld done.\n");
}
 
int main()
{
    static const PxU32 frameCount = 100;
 
    // 初始化物理引擎
    initPhysics(false);
 
    // 执行仿真
    for (PxU32 i = 0; i < frameCount; i++)
        stepPhysics(false);
 
    // 清理物理引擎
    cleanupPhysics(false);
 
    return 0;
}

文档笔记