ݺߣ

ݺߣShare a Scribd company logo
무중력 상태의 물리 기초
~그럴듯한 게임으로 만들어보자~
~대신 조작은 힘들겠지~
게임 구현과 현실은 차이가 있다
• 진짜 리얼한 물리엔진을 만드는 게 아님
• 시뮬레이션을 만드는 것도 아님
• 조작하는 ‘손 맛’이 제일 중요
• 테스트 해 보고 아니다 싶으면 비현실적인 해법으로 갈 수도 있
음
속도와 가속도
• 3차원이므로 벡터량인 속도와 가속도는 x, y, z 축으로 각각 분
배된다
• 예를 들어 속도가 100km/s 일 때 x, y, z 축과 이루는 각도가 X,
Y, Z 라면
X축 방향 속도 : 100 * cos(X)
Y축 방향 속도 : 100 * cos(Y)
Z축 방향 속도 : 100 * cos(Z)
(단위 km/s)
가 되는 것이다
속도와 가속도
• 앞과는 반대로, velocity(x, y, z) 값이 주어지면 이 값을 토대로
캐릭터의 속도를 구할 수 있다.
• 사실 구할 필요 없다.
• 다음 draw() 할 때 dt 만큼 각각의 속도에 곱해서 나온 값만큼 전역 좌
표계에서 이동시켜버리면 그만이다.
• Position(x, y, z) 에서 position.x = position.x + velocity.x * dt
• 나머지도 동일
• 속도가 있을 때 캐릭터 이동은 저렇게 하면 된다
• 속도가 변할 때는 어떻게 할까?
속도와 가속도
• 게임을 생각해보면 속도가 점점 늘거나 줄어야 된다
• 일반 이동이 키 하나에 0에서 100으로 가속하는 방식이면 안 된다
• 그럼 가속도가 있어야 한다
• 가속도도 속도와 마찬가지로 세 축 성분의 합으로 나타낸다
속도와 가속도
• Accel(x, y, z) 라는 가속도 항목을 두고
• Speed(x, y, z) 라는 속도 항목을 둔 다음
• dt 만큼 지났을 때 Speed(x, y, z)는?
• Speed.x = Speed.x + Accel.x * dt
• 나머지 항도 똑같음
• 자 이제 가속도가 있을 때 속도를 구해서 캐릭터 이동까지 가능
하다!
• 그런데 가속도가 변하면??
속도와 가속도
• 만약 가속도가 10m/s2 일 때 가만 두면 속도가 영원히 증가한다
• 해결해야죠
• 가속도가 점점 줄어들게 만들어야 한다
• 아니면 가속도가 순간적으로 작동하고 사라지게 한다
• 등가속도 운동만 고려해도 상관이 없다
• 가속도가 바뀌면 update() 할 때 바꿔주고 등가속도로 계산하는 과정을
짧은 시간 동안 반복하면 가속도가 변하는 운동을 나타낼 수 있다.
• 구현이 간단하다.
그냥 이렇게 계산하자는 이야기
* 실제로는 훨씬 정확함
속도와 가속도
• 속도 제한과 가속도 제한을 도입해야 한다.
• 추가로, 키 입력이 없을 때 가속도는 일정한 값을 가진다
If( 속도 > 0 || 속도 0 < )
가속도 = -a; (a는 속도의 부호와 같은 부호를 가짐)
Else // 속도 == 0
가속도 = 0;
• 그래야 속도가 줄어든다.
• 시간이 지날 수록 현재 속도에서 반대 방향 가속도만큼 빠지기 때문
속도와 가속도
• 키 입력이 있으면 해당 방향으로 가속도를 덮어쓴다
• 이건 테스트를 좀 해봐야 하는데.. 기존의 가속도를 덮어쓰는 게 조작감
이 좋을 것 같긴 함
• 기존 속도는 살려두는 편이 현실감 있는 조작
• 정리하면 “속도는 살리고, 가속도는 죽인다”
게임이라면?
int speed[3] = { 0, };
int accel[3] = { 0, };
1 2
유저가 어떤 방향(x, y, z)으로 가속
가속도 a를 세 방향으로 나눔3
4 가속도를 가지고 속도를 고침
accel[3] = { 3, 4, 5 };
accel[3] = { 3, 4, 5 };
float dt = 0.1;
speed[3] = { 0.3, 0.4, 0.5 };
5
speed[3] = { 0.3, 0.4, 0.5 };
속도를 가지고 위치를 고침
position[3] = { 0.03, 0.04, 0.05 };
추가로 있어야 할 것
• 연료를 소비해서 속도를 0으로 맞추는 기능이 있어야 함
• 안 그러면 조작하기가 너무 힘들다
• 코딩으로 구현하기는 쉬움
• 가속도 반영 방식을 생각해봐야 한다
• Update() 함수가 불려 올 때 주기적으로 계산해주는 방법이 좋을지 아
니면 충돌이나 운동 즉시 속도에 반영하고 이후의 운동을 등속도운동
의 합으로 간주하는 것이 좋을지 결정
만약 물체가 충돌하면?
• 운동량 보존의 법칙
질량A * 속도A 질량B * 속도B
질량A * 속도A’
질량B * 속도B’
MaVa + MbVb
= MaV’a + MbV’b
위 모델은 병진 운동만 있을 경우
• 회전이 함께 있을 경우 에너지가 분산된다.
• 엄밀히 생각하면 충돌이 있을 때 물체의 질량 중심과 관성 모멘
트를 구해서 병진 운동과 회전 운동에 분배해줘야 한다.
• 만들기 어렵다
• 그렇다면 미리 물체의 중심과 회전축을 결정해두고 충돌이 있
을 때 벡터만 가지고 판정을 하자!
아마 이렇게 되겠지
• 문제를 단순화 해서 2차원 물체의 질량 중심을 지나는 축과 동
일한 선 상에서 타격이 있다면
• 병진 운동 100% 회전 운동 0%
• 빗겨나서 충돌하면 병진과 회전이 동시에 발생
이때 충돌한 물체의 운동량은
(충돌지점 – 질량중심) 벡터와
(충돌지점 – 질량중심) 벡터에 수직인 벡터로 분할된다
전자는 병진운동, 후자는 회전운동에 영향을 준다
양쪽 벡터에 운동량의 정사영을 투사해 크기를 구할 수 있다
3차원에서는?
• 축을 하나 더 늘리면 된다
• 회전축은 질량중심을 지나면서 충돌 벡터와 직교함
• 외적한 값이 (질량중심-충돌벡터)벡터가 되는 두 벡터가 회전을
결정하는 벡터
여기서 잠깐 : 짐벌락
• 3D 물체를 회전시킬 때 중대한 문제가 있는데 Gimbal Lock 이
다.
• 물체를 회전 변환 시킬 때 같은 각도만큼 회전시켜도 적용하는 순서를
바꾸면 결과가 달라지는 현상이 생긴다.
• 이는 물체에서 한 축을 움직일 때 나머지 축도 영향을 받는다는 것이다
• 따라서 물체를 회전시키는 도중에 축이 겹쳐지는 경우가 생긴다.
• 이때 축의 자유도를 잃을 수 있는데 이것이 짐벌락이다.
• 짐벌락에 빠지게 되면 pitch, yaw, roll 중 일부가 불가능하게 된다.
쿼터니언?
• 실수부와 허수부로 구성된 4원수
• 회전 변환에 매우 유용
• 짐벌락이 발생하지 않는다
• 회전 행렬 계산보다 더 적은 원소를 사용한다
• 하지만 수식이 직관적이지 않고 이동을 나타내기 어렵다
• Graphics Advanced에서 다룬다고 하니 필요하면 추가 스터디
회전운동은 구현하기가 빡셈
• 병진운동까지는 유니티로 실험 가능
• 기본적인 속도와 가속도 개념을 바탕으로 우주에서만 가능한 독특한
이동방식을 만들었음
• freelancer 2에서 우주선 조작하는 느낌과 비슷함
현재까지 문제점
• 프로토타이핑으로 조작감을 시험해보기가 쉽지 않다.
• Unity가 알아서 다 해버림
• Direct 3D로 만들려니 기반작업이 많이 필요
• 운동에 관한 모델링이 깔끔하지 않다
• 기본적인 물리를 머리에 넣고 실제 구현된 예제를 통해 보강해 나가야
• 남의 코드를 열심히 보자

More Related Content

무중력 상태에 필요한 기초 물리

  • 1. 무중력 상태의 물리 기초 ~그럴듯한 게임으로 만들어보자~ ~대신 조작은 힘들겠지~
  • 2. 게임 구현과 현실은 차이가 있다 • 진짜 리얼한 물리엔진을 만드는 게 아님 • 시뮬레이션을 만드는 것도 아님 • 조작하는 ‘손 맛’이 제일 중요 • 테스트 해 보고 아니다 싶으면 비현실적인 해법으로 갈 수도 있 음
  • 3. 속도와 가속도 • 3차원이므로 벡터량인 속도와 가속도는 x, y, z 축으로 각각 분 배된다 • 예를 들어 속도가 100km/s 일 때 x, y, z 축과 이루는 각도가 X, Y, Z 라면 X축 방향 속도 : 100 * cos(X) Y축 방향 속도 : 100 * cos(Y) Z축 방향 속도 : 100 * cos(Z) (단위 km/s) 가 되는 것이다
  • 4. 속도와 가속도 • 앞과는 반대로, velocity(x, y, z) 값이 주어지면 이 값을 토대로 캐릭터의 속도를 구할 수 있다. • 사실 구할 필요 없다. • 다음 draw() 할 때 dt 만큼 각각의 속도에 곱해서 나온 값만큼 전역 좌 표계에서 이동시켜버리면 그만이다. • Position(x, y, z) 에서 position.x = position.x + velocity.x * dt • 나머지도 동일 • 속도가 있을 때 캐릭터 이동은 저렇게 하면 된다 • 속도가 변할 때는 어떻게 할까?
  • 5. 속도와 가속도 • 게임을 생각해보면 속도가 점점 늘거나 줄어야 된다 • 일반 이동이 키 하나에 0에서 100으로 가속하는 방식이면 안 된다 • 그럼 가속도가 있어야 한다 • 가속도도 속도와 마찬가지로 세 축 성분의 합으로 나타낸다
  • 6. 속도와 가속도 • Accel(x, y, z) 라는 가속도 항목을 두고 • Speed(x, y, z) 라는 속도 항목을 둔 다음 • dt 만큼 지났을 때 Speed(x, y, z)는? • Speed.x = Speed.x + Accel.x * dt • 나머지 항도 똑같음 • 자 이제 가속도가 있을 때 속도를 구해서 캐릭터 이동까지 가능 하다! • 그런데 가속도가 변하면??
  • 7. 속도와 가속도 • 만약 가속도가 10m/s2 일 때 가만 두면 속도가 영원히 증가한다 • 해결해야죠 • 가속도가 점점 줄어들게 만들어야 한다 • 아니면 가속도가 순간적으로 작동하고 사라지게 한다 • 등가속도 운동만 고려해도 상관이 없다 • 가속도가 바뀌면 update() 할 때 바꿔주고 등가속도로 계산하는 과정을 짧은 시간 동안 반복하면 가속도가 변하는 운동을 나타낼 수 있다. • 구현이 간단하다. 그냥 이렇게 계산하자는 이야기 * 실제로는 훨씬 정확함
  • 8. 속도와 가속도 • 속도 제한과 가속도 제한을 도입해야 한다. • 추가로, 키 입력이 없을 때 가속도는 일정한 값을 가진다 If( 속도 > 0 || 속도 0 < ) 가속도 = -a; (a는 속도의 부호와 같은 부호를 가짐) Else // 속도 == 0 가속도 = 0; • 그래야 속도가 줄어든다. • 시간이 지날 수록 현재 속도에서 반대 방향 가속도만큼 빠지기 때문
  • 9. 속도와 가속도 • 키 입력이 있으면 해당 방향으로 가속도를 덮어쓴다 • 이건 테스트를 좀 해봐야 하는데.. 기존의 가속도를 덮어쓰는 게 조작감 이 좋을 것 같긴 함 • 기존 속도는 살려두는 편이 현실감 있는 조작 • 정리하면 “속도는 살리고, 가속도는 죽인다”
  • 10. 게임이라면? int speed[3] = { 0, }; int accel[3] = { 0, }; 1 2 유저가 어떤 방향(x, y, z)으로 가속 가속도 a를 세 방향으로 나눔3 4 가속도를 가지고 속도를 고침 accel[3] = { 3, 4, 5 }; accel[3] = { 3, 4, 5 }; float dt = 0.1; speed[3] = { 0.3, 0.4, 0.5 }; 5 speed[3] = { 0.3, 0.4, 0.5 }; 속도를 가지고 위치를 고침 position[3] = { 0.03, 0.04, 0.05 };
  • 11. 추가로 있어야 할 것 • 연료를 소비해서 속도를 0으로 맞추는 기능이 있어야 함 • 안 그러면 조작하기가 너무 힘들다 • 코딩으로 구현하기는 쉬움 • 가속도 반영 방식을 생각해봐야 한다 • Update() 함수가 불려 올 때 주기적으로 계산해주는 방법이 좋을지 아 니면 충돌이나 운동 즉시 속도에 반영하고 이후의 운동을 등속도운동 의 합으로 간주하는 것이 좋을지 결정
  • 12. 만약 물체가 충돌하면? • 운동량 보존의 법칙 질량A * 속도A 질량B * 속도B 질량A * 속도A’ 질량B * 속도B’ MaVa + MbVb = MaV’a + MbV’b
  • 13. 위 모델은 병진 운동만 있을 경우 • 회전이 함께 있을 경우 에너지가 분산된다. • 엄밀히 생각하면 충돌이 있을 때 물체의 질량 중심과 관성 모멘 트를 구해서 병진 운동과 회전 운동에 분배해줘야 한다. • 만들기 어렵다 • 그렇다면 미리 물체의 중심과 회전축을 결정해두고 충돌이 있 을 때 벡터만 가지고 판정을 하자!
  • 14. 아마 이렇게 되겠지 • 문제를 단순화 해서 2차원 물체의 질량 중심을 지나는 축과 동 일한 선 상에서 타격이 있다면 • 병진 운동 100% 회전 운동 0% • 빗겨나서 충돌하면 병진과 회전이 동시에 발생 이때 충돌한 물체의 운동량은 (충돌지점 – 질량중심) 벡터와 (충돌지점 – 질량중심) 벡터에 수직인 벡터로 분할된다 전자는 병진운동, 후자는 회전운동에 영향을 준다 양쪽 벡터에 운동량의 정사영을 투사해 크기를 구할 수 있다
  • 15. 3차원에서는? • 축을 하나 더 늘리면 된다 • 회전축은 질량중심을 지나면서 충돌 벡터와 직교함 • 외적한 값이 (질량중심-충돌벡터)벡터가 되는 두 벡터가 회전을 결정하는 벡터
  • 16. 여기서 잠깐 : 짐벌락 • 3D 물체를 회전시킬 때 중대한 문제가 있는데 Gimbal Lock 이 다. • 물체를 회전 변환 시킬 때 같은 각도만큼 회전시켜도 적용하는 순서를 바꾸면 결과가 달라지는 현상이 생긴다. • 이는 물체에서 한 축을 움직일 때 나머지 축도 영향을 받는다는 것이다 • 따라서 물체를 회전시키는 도중에 축이 겹쳐지는 경우가 생긴다. • 이때 축의 자유도를 잃을 수 있는데 이것이 짐벌락이다. • 짐벌락에 빠지게 되면 pitch, yaw, roll 중 일부가 불가능하게 된다.
  • 17. 쿼터니언? • 실수부와 허수부로 구성된 4원수 • 회전 변환에 매우 유용 • 짐벌락이 발생하지 않는다 • 회전 행렬 계산보다 더 적은 원소를 사용한다 • 하지만 수식이 직관적이지 않고 이동을 나타내기 어렵다 • Graphics Advanced에서 다룬다고 하니 필요하면 추가 스터디
  • 18. 회전운동은 구현하기가 빡셈 • 병진운동까지는 유니티로 실험 가능 • 기본적인 속도와 가속도 개념을 바탕으로 우주에서만 가능한 독특한 이동방식을 만들었음 • freelancer 2에서 우주선 조작하는 느낌과 비슷함
  • 19. 현재까지 문제점 • 프로토타이핑으로 조작감을 시험해보기가 쉽지 않다. • Unity가 알아서 다 해버림 • Direct 3D로 만들려니 기반작업이 많이 필요 • 운동에 관한 모델링이 깔끔하지 않다 • 기본적인 물리를 머리에 넣고 실제 구현된 예제를 통해 보강해 나가야 • 남의 코드를 열심히 보자