MoniWiki메모장_물리
Login:
Password:
대문|찾기|바뀐글|목록|메모장|책갈피|연꽃|링크
Edit Diff Reload Search Print Info Mail Help RSS

@ 2004-11-23 @

  게임에서의 물리학 (김성완 샘 감사^^)
1 하드웨어 가속
2 게임에서의 물리학
2.1 Euler's Method
2.2 Hook's law
2.3 Verlet Intergrator
3 Chaos
4 Jump 기본로직
{_r} 메모장으로 가기

* 충돌참고

1 하드웨어 가속 #

#.PPU(물리연산 프로세스 유닛) ; CPU가 담당하는 이미지 재생과 관련된 물리 연산을 전담하는 주변기기
/ 콘솔 게임프로세싱 처리 개념 = CPU + GPU + PPU

#.GPU (Graphics Processing Unit)는
중앙처리장치인 CPU만으로 고정밀도의 그래픽을 단독으로 처리하기에 무리가 있기 때문에, 이를 보조하기 위하여 3D그래픽 연산 전용의 프로세서 GPU가 개발 되었습니다.

GPU라는 용어는 엔비디아(NVIDIA)사에서 1999년에 ‘지포스(GeForce)’라는 이름의 새로운 그래픽 컨트롤러(Graphics Controller: 그래픽카드용 칩)을 내놓으며 처음 제창한 것이다. 지포스는 CPU의 도움 없이 자체적으로 폴리곤(Polygon: 3D 그래픽을 구성하는 도형)의 변형(Transform) 및 광원(Lighting)효과를 구사하는 기능, 이른바 ‘하드웨어(Hardware) T&L’을 갖추고 있었다. 이는 이전까지 사용했던 그래픽 컨트롤러와는 확연히 다른 개념이었기 때문에 이를 구분하고자 GPU라는 이름이 붙게 되었다. 그리고 지포스의 출시 후 1년이 지난 2000년, ATi(현재의 AMD)사에서 ‘라데온(Radeon)’이라는 GPU를 출시하게 되면서 양사의 경쟁이 본격화 된다.

#.인텔 > Havok - 물리 계산을 CPU에서 보조 역할을 담당


-. 헬게이트는 정상적인 경우, 싱글 프로세스로 작동을 하지만
배경 설정이나 이펙트 등에 물리(하복) 연산이 진행될 때, 다른 프로세스가 작동
--> 심할 경우, 물리 계산이 끝날 때까지 화면이 멈추는 현상 발생

#.NVIDIA > (AGEIA) PhysX - 물리 계산을 그래픽카드에서 보조 역할을 담당


2 게임에서의 물리학 #

2.1 Euler's Method #

  • 힘F(t) = m*A ( m는 질량, A는 가속도 )
    F(t)를 알고 있을 때, 미분방정식을 위치에 대해서 푼다면 시간에 따른 위치값R(t)을 알수 있다.
  • Δt<<1 ( Δt가 충분히 작다면 )
    ┌ Rnew = Rold + Vnew*Δt ( R은 위치, Rold는 초기위치 ) {_-} 위치의 값이 힘에 영향을 미친다.
    └ Vnew = Vold + F/m*Δt ( V는 속도, Vold는 초기속도 )

2.2 Hook's law #

  • 스프링계수(ks); 파티클 간의 응집력 {_-} 운동을 유발시킴
    -1) 계수가 클수록 모양을 그대로 유지할려는 힘으로 작용
    --> 임의의 한계치를 넘을 경우는 언제든제 폭발의 위험성을 가지고 있다.
    -2) 스프링은 상대적인 위치의 (거리에 따른)변화에 의해 탄성이 발생
  • 감쇠계수(kd); 저항이나 물성치에 의한 변화를 감소시키는 요소
    -1) 감쇠계수가 크면 반발하는 하는 힘의 작아진다. -> 딱딱한 물체 표현
    감쇠계수가 작으면 유동성이 큰 젤리와 같은 물질을 표현 할 수 있다.
  • 한쪽이 고정되어 있는 스프링에 질량 m인 물체가 다른쪽 끝에 있을 때,
    ∴Fs = -ks(l - lo)
    ( ks는 스프링상수, l은 스프링이 늘어난 길이, lo은 스프링의 원래길이 )
    ∴Fd = kd(v1 - v2)
    ( kd는 감쇠계수, v1은 초기 속도, v2는 나중속도, (v1 - v2)는 상대속도 )
    ∴F = Fs + Fd {_-} Euler's Method 적용해서 위치값Rnew를 구한다.
  • ※ 구속 조건에서 스프링 상수가 큰 딱딱한 물체에 심한 진동을 가할 경우 폭발의 위험성은 언제나 있다.

2.3 Verlet Intergrator #

  • 개별적인 파티클의 움직임을 강체 운동으로 표현할 수 있고, 에너지가 보존 됨으로써 안정적이다.
    ∴ R( t+Δt ) = 2R(t) - R(t-Δt) + A*Δt²
  • -1) 오일러 해법의 V(속도)와 R(위치)의 항목이 2개의 R(위치)로 대체
    -2) 초기치 R(t-Δt) = R(t) - V(t)*Δt 로 계산
    -3) 예상해던 결과가 나오면 2~3번 루프를 돌려서 해당 프레임에서 고정시킬 수 있다.


3 Chaos #

  • 카오스라는 말은 그리스어 khaos에서 나온 것이지만 현재는 일반적으로 Chaos(카오스, 혼돈이라는 의미)로 표기한다.
    • 어떤 시스템의 어느 시점에서의 상태(=초기값)가 정해지면 그 후의 상태는 원리적으로 모두 결정된다고 하는 결정론적 법칙을 따르고 있음에도 불구하고, 아주 복잡해서 불규칙하고 불안정한 먼 장래의 상태를 예측하는 것이 불가능한 현상
  • 인용되는 식의 예;
    y = ax(1-x) a는 상수, x의 초기치를 0.1이라고 가정할 때,
    다음에 식에 적용할 x의 값은 현재 계산된 y의 값을 사용한다.(0과 1사이 값)


4 Jump 기본로직 #

  • 점프는 크게 3개의 영역으로 구분
    -1.윗쪽으로 힘이 작용하는 부분
    -2.중력에 의해 윗쪽으로 올라가는 힘이 사라지는 부분(꼭대기 부분)
    -3.중력에 의해 낙하하는 부분

  • 아래 코드의 문제는 float 타입을 서로 비교하는 기본적인 오류를 가지고 있음
    -.m_fGravity += (JumpGHIGHTRAVITY * (fDelta*fDelta)*0.5f ); 에서
    (fDelta*fDelta)*0.5f는 프레임 변화에 따른 진동을 감쇠하는 효과가 있다.
    -.문제점; 시간의 변화(델타time)가 일정하지 않을 때, 매끄러운 궤적을 만들지 못한다.
    -.oldTrans; 현재의 위치
    kNewTrans; 미래의 이동 위치

const float JumpGHIGHTRAVITY 1800.0f
const float SAFEHEIGHT = 2.0f;
const float STARTJUMP  = 100.0f;
static float fUp = 0.0f;	

// 점프 여부
if( !점프중 && 현재 애니메이션이 점프인가? )
{
  m_bJumpstart = true;
  m_bJump = true;
  fUp = STARTJUMP;
  m_fGravity = 0.0f;
}

if( m_bJump )  // 상승 부분
{
  m_fGravity += (JumpGHIGHTRAVITY * (fDelta*fDelta)*0.5f );
  fUp -= m_fGravity;

  if( fUp < 0.0f )
  {
    m_fGravity = 0.0f;
    m_bJump = false;
  }
  else
  {
    oldTrans.z += fUp;		
  }
}
else	// 낙하 여부
{
  if( (oldTrans.z - kNewTrans.z) > SAFEHEIGHT )
  {
    m_fGravity += (JumpGHIGHTRAVITY * (fDelta*fDelta)*0.5f );
    oldTrans.z -= m_fGravity;
  }
  else
  {
    oldTrans = kNewTrans;
    m_fGravity = 0.0f;
    m_bJumpstart = false;
  }
}

  • 위의 코드에서 점프를 검출하는 부분이 로직 안에 있기 때문에 프레임마다 판별하는 문제가 있어서
    외부에서 키 입력이 되는 부분에서 jump start를 함수로 호출하도록 수정
    -.궤적을 일정하기 유지 하기 위해 Sin곡선을 따라서 상승 후 정점에서 함수 사용해서 낙하
    -.점프 이벤트 발생시 현재 위치(m_pSavePosition)를 저장 후 상승구역에서 기준으로 사용
    -.정상부분에서 m_bJump02 = false, m_bJumpstart = false에서 다시 점프가능

class className
{
public:
  void StartJump();	

private:
  Point3	m_vSavePosition;
  bool	m_bJump02;	// 점프 이벤트를 받아서 캐릭터가 현재 상승 중인지를 표시	
  bool 	m_bJumpstart;	// 점프를 할 수 있는 상태 인지를 표시

  float 	m_fGravity;
  float 	m_fHightPos;
  float	m_fJumpStartTime;
  float 	m_fJumpTime;
  float	m_fJumpTimeMAX;
}
-----------------------------------------------------------------------------------
const float DEF_JumpGHIGHTRAVITY = 1600.0f;
const float DEF_JumpRAD = PI * 0.5;	// 90도
const float DEF_JumpMAX = 12.0f;	// jump시 최고 정점의 높이

void className::StartJump()	
{ 
  if( m_bJumpstart == true )	
    return;

  CPlayer * pkPlayer = GetPlayer();
  _TKASSERT( pkPlayer );
  
  m_pSavePosition = pkPlayer->GetWorldTranslate();

  ControllerSequence* pkSequence = pkPlayer->GetSequence(Animation_jump);
  m_fJumpTimeMAX = pkSequence->GetLength() * 1.1f;
  m_fJumpTime = m_fJumpTimeMAX * 0.5f;
  m_fJumpStartTime = GetCurTime();

  m_bJumpstart = true;
  m_bJump02 = true;
}

bool className::UpDate()
{
  ...
  // 점프 및 낙하 부분 - Sin곡선을 따라서 상승 후 정점에서 함수 사용해서 낙하
  //=========================================================================================
  float fjumptime = GetCurTime() - m_fJumpStartTime;

  if( m_bJump02 )	  // 점프시 상승 구간
  {
    float fjumpRAD = (fjumptime/m_fJumpTime) * DEF_JumpRAD;

    if( fjumptime < m_fJumpTime )	// 상승 중
    {
      m_fHightPos = Sin(fjumpRAD) * DEF_JumpMAX;
      m_fHightPos += m_vSavePosition.z;
    }
    else		// 최고 정점부분
    {
      m_fHightPos = m_vSavePosition.z + DEF_JumpMAX;
      m_bJump02 = false;
    }		
  }
  else  //점프가 아닐때 낙하
  {
    if((oldTrans.z - kNewTrans.z) < 2.0f)
    {
      m_fHightPos = kNewTrans.z;
      oldTrans = kNewTrans;
    }

    if(m_fHightPos > kNewTrans.z)
    {
      m_fGravity += (DEF_JumpGHIGHTRAVITY * ((fDelta*fDelta)*0.5));
      m_fHightPos  -= m_fGravity;
    }
    else	// if(m_fHightPos <= kNewTrans.z)
    {
      m_fHightPos = kNewTrans.z;
      m_fGravity = 0.0f;
      m_bJumpstart = false;
      m_bJump02 = false;
    }
  }

  oldTrans.z = m_fHightPos;
}




{_r} 메모장으로 가기

July, 2019
 123456
78910111213
14151617181920
21222324252627
28293031 

얕은 지식은 위험하다.

InterWiki
Artist
책갈피_GOF의디자인패턴
MoniWikiBlog
last modified 2014-03-17 16:09:52
고치기|찾기|쪽 지우기|비슷한 쪽 Valid XHTML 1.0! Valid CSS! powerd by MoniWiki
0.0253 sec