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);
    }

}