1. PhysX 시작하기

  1. PhysX란?
  2. PhysX 기본 설정



1. PhysX란?

PhysX 는 NVIDIA 에서 제공하는 물리 엔진 SDK로, Unity 나 Unreal Engine 4 에도 사용되는 물리 연산 시뮬레이터이다.

PhysX 는 Actor 라고 불리는 오브젝트 단위로 Scene 에서 각 액터의 물리적 상호작용 등을 시뮬레이션하며, 액터는 RigidBody, Particle 등 여러 종류가 존재한다.




2. PhysX 기본 설정


class CPhysxMgr
	: public Singleton<CPhysxMgr>
{
	friend class CPhysxActor;
public:
	SINGLE(CPhysxMgr);

private:
	// 초기화 데이터
	PxDefaultAllocator					m_DefaultAllocatorCallback;
	PxDefaultErrorCallback				m_DefaultErrorCallback;
	PxDefaultCpuDispatcher*				m_Dispatcher;
	PxTolerancesScale					m_ToleranceScale;

	PxFoundation*						m_Foundation;
	PxPhysics*							m_Physics;

	PxScene*							m_Scene;

	// 시뮬레이션 대상 관리 컨테이너
	map<CGameObject*, PxRigidActor*>	m_mapRigidBody;

	// 디버그용 셰이더
	Ptr<CGraphicShader>					m_Shader;

	// 충돌 이벤트 처리 객체
	CSimulationEvent*					m_EventCallback;

public:
	void Init();
	void Tick();
	void Render();

	PxRigidActor* FindRigidBody(CGameObject* _Object);
	void RemoveRigidBody(CGameObject* _Object);
};


자료형 설명
PxDefaultAllocator PhysX 엔진에서 기본적으로 제공하는 메모리 할당자. PxAllocatorCallback을 구현한 클래스이며, PhysX 내부에서 동적 메모리를 할당할 때 사용된다.
PxDefaultErrorCallback PhysX에서 오류 메시지를 출력하는 기본 콜백 클래스. PxErrorCallback을 구현한 클래스이며, PhysX 내부에서 오류가 발생하면 자동으로 호출된다.
PxDefaultCpuDispatcher PhysX에서 멀티스레드 작업을 처리하는 기본 CPU 디스패처. PhysX의 PxScene에서 충돌 검사 및 시뮬레이션 작업을 여러 스레드에 분배하는 역할을 한다.
PxTolerancesScale PhysX에서 사용하는 물리 시뮬레이션의 스케일(단위 계수) 을 설정하는 구조체. PhysX 내부에서 부동소수점 연산의 안정성을 유지할 수 있도록 여러 물리 계산에 적용된다.
PxFoundation PhysX의 핵심 엔진을 초기화하는 기반 객체. PhysX 엔진의 모든 주요 시스템(PxPhysics, PxCooking, PxPvd 등)은 PxFoundation을 기반으로 생성된다.
PxPhysics PhysX의 핵심 물리 엔진 객체로, 물리 시뮬레이션을 관리하는 중심 요소. 모든 물리 관련 객체(PxScene, PxRigidDynamic, PxRigidStatic, PxMaterial 등)는 PxPhysics를 통해 생성된다.
PxScene PhysX의 물리 시뮬레이션을 실행하는 공간. 물리 객체(PxRigidDynamic, PxRigidStatic)를 배치하고, 중력과 충돌을 처리하며, PxScene 내부에서 프레임마다 물리 연산을 수행(simulate(), fetchResults())한다.
CSimulationEvent PhysX에서 발생하는 충돌, 트리거, 웨이크/슬립 이벤트를 처리하는 클래스. PxSimulationEventCallback 인터페이스를 상속받아 구현할 수 있다.


초기화는 아래와 같이 진행된다.

단, 디버그 렌더링과 충돌 이벤트 콜백 등록은 선택사항이다.



void CPhysxMgr::Init()
{
    // physx 초기화
    m_Foundation = PxCreateFoundation(PX_PHYSICS_VERSION, m_DefaultAllocatorCallback, m_DefaultErrorCallback);
    if (!m_Foundation) throw("PxCreateFoundation failed!");
    m_ToleranceScale.length = 1.f;
    m_ToleranceScale.speed = 400.f;
    m_Physics = PxCreatePhysics(PX_PHYSICS_VERSION, *m_Foundation, m_ToleranceScale);

    PxSceneDesc sceneDesc(m_Physics->getTolerancesScale());
    sceneDesc.gravity = PxVec3(0.f, -400.f, 0.f);
    m_Dispatcher = PxDefaultCpuDispatcherCreate(2);
    sceneDesc.cpuDispatcher = m_Dispatcher;
    sceneDesc.filterShader = FilterShaderExample;
    sceneDesc.flags |= PxSceneFlag::eENABLE_CCD;
    m_Scene = m_Physics->createScene(sceneDesc);

    // 디버그 렌더링 목록
    m_Scene->setVisualizationParameter(PxVisualizationParameter::eSCALE, 1.0f);
    m_Scene->setVisualizationParameter(PxVisualizationParameter::eBODY_AXES, 10.0f);
    m_Scene->setVisualizationParameter(PxVisualizationParameter::eCOLLISION_SHAPES, 1.0f);

    // 충돌 이벤트 콜백 등록
    m_EventCallback = new CSimulationEvent;
    m_Scene->setSimulationEventCallback(m_EventCallback);

    // physx 디버그용 셰이더 컴파일
    m_Shader = new CGraphicShader;

    m_Shader->CreateVertexShader(L"HLSL\\PhysxDebug.fx", "VS_PhysxDebug");
    m_Shader->CreatePixelShader(L"HLSL\\PhysxDebug.fx", "PS_PhysxDebug");
    m_Shader->SetDomain(SHADER_DOMAIN::DOMAIN_DEBUG);
    m_Shader->SetRSType(RS_TYPE::CULL_NONE);
    m_Shader->SetDSType(DS_TYPE::LESS);
    m_Shader->SetBSType(BS_TYPE::ALPHABLEND);
    m_Shader->SetTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
}