PhysX/[NVIDIA] PhysX_Tutorial
1. PhysX 초기화
헛둘이
2023. 2. 25. 17:25
#include <PxPhysicsAPI.h>
int main() {
// declare variables
physx::PxDefaultAllocator mDefaultAllocatorCallback;
// 물리 엔진에서 사용하는 모든 동적 할당은 이 할당자를 거친다.
// 사용자 지정 할당자는 PxAllocatorCallback 클래스를 구현해야 한다.
physx::PxDefaultErrorCallback mDefaultErrorCallback;
// 오류나 경고를 처리하는 콜백 클래스이다.
physx::PxDefaultCpuDispatcher* mDispatcher = NULL;
// PhysX는 CPU와 GPU를 모두 사용하는 하이브리드 물리 엔진이며,
// 이 클래스는 CPU 코어를 효율적으로 사용하는 데 중요한 역할을 한다.
physx::PxTolerancesScale mToleranceScale;
// 공차 값들의 집합으로, 길이, 질량, 속도 등의 단위를 정리한다.
// 물리 시뮬레이션에 사용되는 값들을 적절한 범위로 조절하는 데 사용된다.
physx::PxFoundation* mFoundation = NULL;
// PhysX 시스템의 초기화와 종료를 담당하는 클래스
// 이 클래스를 사용해서 메모리 할당, 오류 처리기를 설정하고,
// PhysX 라이브러리를 초기화하고 종료한다.
// 이 클래스의 객체는 나중에 PxCreatePhysics 함수를 통해 물리 엔진을 생성한다.
physx::PxPhysics* mPhysics = NULL;
// 물리 엔진의 핵심 클래스 중 하나
// 기본적인 객체들을 생성하고, 초기화하며, 조작하는 데 사용된다.
// PxPhysics 객체를 생성하는 것은 물리엔진 초기화 작업 중 가장 중요한 부분
physx::PxScene* mScene = NULL;
// 물리 시뮬레이션을 위한 공간을 정의하고 관리하는 데 사용된다.
// 충돌 감지와 응답, 그리고 물리엔진 내부적인 시뮬레이션 과정을 관리한다
// 따라서 물리 시뮬레이션을 수행하기 위해서는 이 클래스의 객체가 반드시 필요하다
physx::PxMaterial* mMaterial = NULL;
// 물리적인 속성을 정의하는 객체
// 두 개체가 충돌할 때 생기는 마찰, 탄성 등의 특성을 정의한다.
physx::PxPvd* mPvd = NULL;
// 시뮬레이션 디버깅을 위한 도구
// 클라이언트-서버 구조로 되어 있으며,
// Pvd는 일종의 서버 역할을 하고, 실행되는 프로그램이 클라이언트
// 클라이언트에서 서버쪽에 접속하면 서버쪽에서 그 데이터를 모니터링한다.
// init physx
mFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, mDefaultAllocatorCallback, mDefaultErrorCallback);
if (!mFoundation) throw("PxCreateFoundation failed!");
// Foundation 객체를 생성하는 코드
// 물리 시뮬레이션의 기본 세팅 및 초기화, 오류 처리, 디버깅에 사용된다.
physx::PxPvdTransport* transport = physx::PxDefaultPvdSocketTransportCreate("127.0.0.1", 5425, 10);
if (transport == nullptr)
return 0;
// PhysX Visual Debugger에서 사용하는 네트워크 전송 객체 생성
mPvd = PxCreatePvd(*mFoundation);
// Pvd 객체 생성
mPvd->connect(*transport, physx::PxPvdInstrumentationFlag::eALL);
// Pvd를 사용해서 물리 시뮬레이션을 디버깅하고 모니터링할 수 있게 설정하는 코드
mToleranceScale.length = 100; // typical length of an object
// 길위 단위에 대한 공차 값을 100으로 설정한다
// 이 값은 물리 시뮬레이션의 정확도와 성능에 영향을 미친다.
mToleranceScale.speed = 981; // typical speed of an object, gravity*1s is a reasonable choice
// 길이 단위 당 초당 이동 거리를 나타낸다
// 일반적으로는 중력 가속도를 나타냄
mPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *mFoundation, mToleranceScale, true, mPvd);
// 물리 시뮬레이션 인스턴스를 만든다.
physx::PxSceneDesc sceneDesc(mPhysics->getTolerancesScale());
// 허용 오차값으로 sceneDesc를 초기화한다.
// sceneDesc는 Scene을 만드는 데 필요한 구조체
sceneDesc.gravity = physx::PxVec3(0.0f, -9.81f, 0.0f);
// 물리 시뮬레이션에서 중력을 설정하는 코드
// 각각의 변수는 x, y, z축을 나타내며, 현재 y축 방향으로 음의 중력을 설정한다.
mDispatcher = physx::PxDefaultCpuDispatcherCreate(2);
// CPU 디스패처를 생성하는 코드
// 디스패처는 물체 간 충돌 검출 및 충돌 결과 처리를 수행한다.
// 인자로 넘기는 2는 CPU 코어 갯수
sceneDesc.cpuDispatcher = mDispatcher;
// PhysX 시뮬레이션에서 CPU 연산을 처리하기 위한 디스패처를 설정한다
// 이렇게 설정하면 시뮬레이션에서 물리연산은 지정된 디스패처에서 처리된다.
sceneDesc.filterShader = physx::PxDefaultSimulationFilterShader;
// PxDefaultSimulationFilterShader은 기본 필터링 콜백 함수
// 이 필터링 함수는 물리 시뮬레이션에서 충돌과 관련된 처리를 수행하며,
// 충돌 그룹 및 마스크를 설정하여 물체 간 상호작용을 제어한다.
mScene = mPhysics->createScene(sceneDesc);
// 시뮬레이션에서 사용할 새로운 장면을 생성하는 코드
// Scene은 시뮬레이션에서 사용할 물리 객체(바디, 조인트, 콜리전 모양)을 추가할 수 있다.
physx::PxPvdSceneClient* pvdClient = mScene->getScenePvdClient();
if (pvdClient)
{
pvdClient->setScenePvdFlag(physx::PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true);
pvdClient->setScenePvdFlag(physx::PxPvdSceneFlag::eTRANSMIT_CONTACTS, true);
pvdClient->setScenePvdFlag(physx::PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, true);
}
// create simulation
mMaterial = mPhysics->createMaterial(0.5f, 0.5f, 0.6f);
physx::PxRigidStatic* groundPlane = PxCreatePlane(*mPhysics, physx::PxPlane(0, 1, 0, 50), *mMaterial);
mScene->addActor(*groundPlane);
float halfExtent = .5f;
physx::PxShape* shape = mPhysics->createShape(physx::PxBoxGeometry(halfExtent, halfExtent, halfExtent), *mMaterial);
physx::PxU32 size = 30;
physx::PxTransform t(physx::PxVec3(0));
for (physx::PxU32 i = 0; i < size; i++) {
for (physx::PxU32 j = 0; j < size - i; j++) {
physx::PxTransform localTm(physx::PxVec3(physx::PxReal(j * 2) - physx::PxReal(size - i), physx::PxReal(i * 2 + 1), 0) * halfExtent);
physx::PxRigidDynamic* body = mPhysics->createRigidDynamic(t.transform(localTm));
body->attachShape(*shape);
physx::PxRigidBodyExt::updateMassAndInertia(*body, 10.0f);
mScene->addActor(*body);
}
}
shape->release();
// run simulation
while (1) {
mScene->simulate(1.0f / 60.0f);
mScene->fetchResults(true);
}
}