본문 바로가기
PhysX/[NVIDIA] PhysX_Tutorial

7. PhysX - RigidBody Dynamics - 1

by 헛둘이 2023. 3. 4.

속도 (Velocity)

- PhysX 시뮬레이션에서, 물체의 운동은 선속도, 각속도로 분리된다.
- 물체의 운동은 중력, 적용된 힘과 토크, 충돌 등 다양한 제약 조건으로 발생한다.
 
선속도를 가져오는 메서드

PxVec3 PxRigidBody::getLinearVelocity();

 
각속도를 가져오는 메서드

PxVec3 PxRigidBody::getAngularVelocity();

 
그리고 선속도와 각속도를 아래와 같이 설정할 수 있다.

void PxRigidBody::setLinearVelocity(const PxVec3& linVel, bool autowake);
void PxRigidBody::setAngularVelocity(const PxVec3& angVel, bool autowake);

 


질량 속성 (Mass Properties)

- 질량 속성은 질량, 관성 모멘트, 무게 중심 위치를 나타낸다.
- PxRigidBdoyExt::updateMassAndInertia() 헬퍼 함수를 통해 질량 속성을 쉽게 계산할 수 있다.
- 이 함수는 물체의 모양과 균일한 밀도 값을 기반으로 모든 속성을 설정한다.
- 또한 물체의 질량 / 관성 텐서를 수동으로 설정할 때 값들은 양수여야 하지만 0이어도 된다.
*텐서(tensor)란?
: 물체의 질량 분포와 회전에 관한 정보를 담고 있음
: 물체가 어떤 축을 중심으로 회전할 때 필요한 에너지와 각속도를 계산할 때 사용된다.
: 물리 엔진에서는 물체의 질량과 함께 관성 텐서를 설정해서 물체의 운동 상태를 시뮬레이션한다.
 
- 관성 값으로 0이 들어오면, PhysX는 해당 축 주위의 무한한 질량 또는 관성을 의미한다고 해석한다.
- 이를 사용해서 모든 선형 웅동에 저항하거나 모든 또는 일부 각 운동을 저항하는 물체를 생성할 수 있다.
- 이를 통해 아래와 같은 효과를 달성할 수 있다.
 
1. 키네마틱으로 움직이는 물체
2. 이동은 키네마틱하게 동작하지만, 회전은 동적인 물체
3. 반대로 이동은 동적으로 동작하지만, 회전은 키네마틱하게 동작하는 물체
4. 특정 축을 중심으로 회전할 수 있는 물체
 

PxRigidDynamic* dyn = physics.createRigidDynamic(PxTransform(PxVec3(0.f, 2.5f, 0.f)));
PxRigidActorExt::createExclusiveShape(*dyn, PxBoxGeometry(2.f, 0.2f, 0.1f), material);
PxRigidActorExt::createExclusiveShape(*dyn, PxBoxGeometry(0.2f, 2.f, 0.1f), material);
dyn->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, true);
dyn->setAngularVelocity(PxVec3(0.f, 0.f, 5.f));
dyn->setAngularDamping(0.f);
PxRigidStatic* st = mPhysics.createRigidStatic(PxTransform(PxVec3(0.f, 1.5f, -1.f)));
PxRigidActorExt::createExclusiveShape(*t, PxBoxGeometry(0.5f, 1.5f, 0.8f), material);
scene.addActor(dyn);
scene.addActor(st);

- 위 코드는 풍차를 예시로 든 코드이다.
- 풍차의 정적인 박스 프레임과, 날개를 나타내는 십자형을 생성한다.
- 풍차 날개에서 중력과 각도 감쇠를 끄고, 초기 각속도를 부여한다.
- 그러나 다른 물체가 날개에 충돌하면 풍차는 제대로 작동하지 않을 것이다.
- 이럴 때 날개에 무한한 질량과 관성을 가지도록 해서 다른 물체와의 상호작용에서 자유로워질 수 있다.

dyn->setMass(0.f);
dyn->setMassSpaceInertiaTensor(PxVec3(0.f));

- 이 예제에서 터빈은 끊임없이 일정한 각속도로 회전한다.
- 그러나 몸체의 속도는 제약조건에 의해 영향을 받지 않는다
 
 
 


힘과 토크 적용 (Applying Forces and Torques)

 
- 물체와 상호작용하는 가장 적절한 방법은 그 물체에 힘을 가하는 것이다!
- 고전역학에서 물체간 대부분의 상호작용은 보통 힘을 사용하여 해결한다.
 
F = MA (힘 = 질량 * 가속도)
 
- 힘은 물체의 가속도를 직접적으로 제어하지만, 속도와 위치는 간접적으로만 제어된다.
- 이런 이유 때문에 힘에 의한 제어는 즉각적인 반응이 필요한 경우 부적절하다.
- 그러나 힘의 장점은 장애물이 지정된 모든 물체에 적용되는 모든 힘에 대해 시뮬레이션이 유지될 수 있다는 것
(Ex. 중력은 물체에 힘을 가해 작용한다)
 
- 하나의 물체에 작용하는 힘들은 각 시뮬레이션 프레임마다 누적되고, 시뮬레이션에 적용된 다음 초기화된다.
- PxRigidBody와 PxRigidBodyExt 관련 메서드는 아래와 같다.
 

void PxRigidBody::addForce(const PxVec3& force, PxForceMode::Enum mode, bool autowake);
void PxRigidBody::addTorque(const PxVec3& torque, PxForceMode::Enum mode, bool autowake);

void PxRigidBodyExt::addForceAtPos(PxRigidBody& body, const PxVec3& force,
    const PxVec3& pos, PxForceMode::Enum mode, bool wakeup);
void PxRigidBodyExt::addForceAtLocalPos(PxRigidBody& body, const PxVec3& force,
    const PxVec3& pos, PxForceMode::Enum mode, bool wakeup);
void PxRigidBodyExt::addLocalForceAtPos(PxRigidBody& body, const PxVec3& force,
    const PxVec3& pos, PxForceMode::Enum mode, bool wakeup);
void PxRigidBodyExt::addLocalForceAtLocalPos(PxRigidBody& body, const PxVec3& force,
    const PxVec3& pos, PxForceMode::Enum mode, bool wakeup);

- 위 코드에서 PxForceMode 멤버는 간단한 힘을 적용하기 위해 기본값으로 PxForceMode::eFORCE를 갖는다.
- 다른 값으로는 PxForceMode::eIMPULSE가 있으며 이는 급격한 힘을 적용한다.
- PxForceMode::eVELOCITY_CHANGE는 같은 작업을 수행하지만, 물체의 질량을 무시하여 순간적인 속도변화를 준다.
 
- 적용되는 급격한 힘과 회전력에 따라 다음 시뮬레이션 프레임에서 발생할 선속도, 각속도 변화를 계산하는 확장 함수들이 있다.
- 아래의 코드 참고

void PxRigidBodyExt::computeVelocityDeltaFromImpulse(const PxRigidBody& body,
    const PxVec3& impulsiveForce, const PxVec3& impulsiveTorque, PxVec3& deltaLinearVelocity,
    PxVec3& deltaAngularVelocity);

- 이 함수는 다음 시뮬레이션 프레임에서 급격한 힘 또는 토크가 적용될 때, 예상되는 선속도 및 각속도 변화량을 계산하는 데 사용된다.
- 이 함수를 사용해서 물체의 업데이트된 속도를 미리 예측해서 시뮬레이션 프레임이 끝나기 전에 물체가 임계 속도를 초과할 가능성이 있는 경우 미리 로딩을 시작할 수 있다.
(물체가 임계속도에 도달할 가능성이 있는 경우 자원 로딩을 미리 시작해서, 시뮬레이션 프레임이 끝나는 순간에 자원을 더 빠르게 로딩할 수 있게 하는 것)
(FPS를 높이는 잠재적 가능성이 있으나 꼭 그렇다는 보장은 없음)
 
- 예상 선속도 및 각속도 변화량은 시뮬레이션 프레임의 time step과 적용할 힘 또는 토크에 비례한다.
- 제약 및 힘 접촉을 무시하면 예상되는 선속도 변화량과 각속도 변화량은 각각 deltaLinearVelocity와 deltaAngularVelocity로 반환된다.
- 예상 선속도는 body.getLinearVelocity() + deltaLinearVelocity로 계산되며,
- 예상 각속도는 body.getAngularVelocity() + deltaAngularVelocity로 계산된다.
 
- 필요 시 즉시 물체의 속도를 업데이트하려면,
- body.setLinearVelocity(body.getLinearVelocity() + deltaLinearVelocity)와
- body.setAngularVelocity(body.getAngularVelocity() + deltaAngularVelocity)를 사용할 수 있다.
 
 


중력 (Gravity)

 
- 중력은 일반적인 힘이라 PhysX에서 적용하기 간단하다.
- 씬 전체에 중력 효과 또는 균일한 힘을 적용하려면 중력 벡터를 PxScene::setGravity()를 사용해서 설정하면 된다.
- 매개변수는 중력 가속도이며, m/s 단위로 지구에서 9.8의 크기를 가지며 아래쪽을 가리켜야 한다.
- 이렇게 세팅하면 씬의 각 바디의 질량에 이 가속도 벡터를 곱한 것이 바디의 무게 중심에 적용된다.
 
- 일부 액터는 중력에 영향을 받지 않아야 할 수도 있다.
- 그럴 땐 아래와 같은 플래그를 지정해주면 된다.

PxActor::setActorFlag(PxActorFlag::eDISABLE_GRAVITY, true);

 
*시뮬레이션 중 중력을 변경하거나 활성화/비활성화하는 경우 주의해야 한다.
- 성능상의 이유로 변경된 중력이 자동으로 *sleep 상태의 물체들을 깨우지 않는다
- 따라서 깨우려면 수동으로 PxRigidDynamic::wakeUp()을 호출해야 한다.
 
*sleep 상태란?
- 객체가 움직이지 않을 때 일종의 절전모드에 들어가는 것을 sleep 상태에 들어갔다고 한다.
- sleep 상태에 있는 객체는 시뮬레이션 성능을 향상시키기 위해 거의 계산되지 않는다.
- 그러나 sleep 상태의 객체가 다른 객체와 상호작용해야 할 때, 이 객체들을 sleep 상태에서 깨어나게 해야 한다.
- 이 과정을 '각종 외부 조작' 또는 '각종 외부 힘'이라고 부르며, 객체에 충돌이 일어나거나 힘을 가할 때 sleep 상태에서 벗어나 계산에 참여하게 된다.
 
 
 
 


마찰력 및 반발력 (Friction and Restitution)

- 모든 물리 객체에는 적어도 하나의 재질(Material)이 있으며,
- 이는 물체와의 충돌을 해결하는 데 사용되는 마찰력과 반발력 속성을 정의한다.
- 재질을 생성하려면 PxPhysics::createMaterial()을 호출하면 된다.

PxMaterial* mMaterial;

mMaterial = mPhysics->createMaterial(0.5f, 0.5f, 0.1f); // static friction, dynamic friction,
                                                        // restitution
if(!mMaterial)
    fatalError("createMaterial failed!");

 
모든 물체는 적어도 하나의 재질(Material)을 가진다
- 이 재질은 충돌해 있는 물체와 함께 충돌을 처리하는 마찰 및 반발력 속성을 정의한다.
- PhysX의 마찰 모델은 기본적으로 해석 모델보다 강력하다.
- PhysX 4.0에서 PxMaterialFlag::eIMPROVED_PATCH_FRICTION 플래그를 도입해서, 해석 모델에 훨씬 가까운 결과를 얻을 수 있다.
(기본적으로 유지되는 플래그임)
 
- 충돌하는 두 객체의 반발력 계수는 충돌 축을 따라 추돌 전과 후의 속도 비율을 나타내는 분수값이다.
- 반발력 계수 1은 탄성적인 충돌을 일으키며, 반발력 계수 < 1은 비탄성적인 충돌을 일으킨다.
 
*반발력 계수란?
- 물체가 충돌 후 튀어오르는 정도를 나타내는 값
- 충돌 전후의 두 물체의 상대 속도에 비례한다.
- 이 값이 1에 가까울 수록 충돌 후 물체가 튕겨져나가는 정도가 크며, 이를 탄성적 충돌이라고 한다.
- 그러나 반발력 계수가 1보다 작을 때는 충돌 후 물체가 완전히 멈추지 않고, 일정량의 운동에너지가 손실되기 때문에
이를 비탄성적인 충돌이라고 한다.
 
*탄성적/비탄성적 충돌 예시
- 고무공과 벽면의 충돌을 예시로 들 수 있다.
- 고무공이 벽면과 충돌하고 반발력 계수가 1이라면, 공은 벽면에서 튀어오르면서 원래 속도와 같은 크기의 역방향 속도를 갖게 된다. (탄성적 충돌)
- 그러나 반발력 계수가 0.5라면, 공인 더 낮은 속도로 벽면에서 튕겨나가게 된다 (비탄성적 충돌)

'PhysX > [NVIDIA] PhysX_Tutorial' 카테고리의 다른 글

9. PhysX - Character Controllers - 1  (1) 2023.03.04
8. PhysX - RigidBody Dynamics - 2  (0) 2023.03.04
6. PhysX - RigidBody 충돌 - 2  (0) 2023.03.03
5. PhysX - RigidBody 충돌 - 1  (0) 2023.03.03
4. PhysX - RigidBody 개요  (0) 2023.03.03

댓글