2005-11-23
VB를 이용한 선분과 원의 충돌체크
고등학교때까지만 해도 기하쪽은 상당히 자신있었는데 나이가 들어갈수록 3D 쪽에는 상당히 취약해서 가고 있다. 몇 달 전 관련 서적을 쭈욱 질러주고 조금 보다가 때려쳤었다. 그러다 이번에 유지 보수 중인 legacy code 에서 brute force 충돌 체크 코드를 좀 더 깔끔하게 해보고자 선분과 원의 충돌 체크를 구현해보게 되었다. 역시나 이럴 때에는 MFC 보다는 .NET winform 이 제일 손쉽기에 재빨리 VB.NET 을 띄워 줬다.
우선 Matrix 나 Vector 류의 함수는 .NET framework 에서 지원하지 않기 때문에 DirectX 쪽의 참조를 갖고 와야 한다. 그다음 리얼타임렌더링 625 페이지를 펼쳐서 그대로 코딩하면 된다. 실제로 타이핑은 금방 끝났는데 웬걸 제대로 동작하지 않아서 이 사람 저 사람 붙잡고 물어보다가 잠이 들고, 오늘 회사에 와서 차분히 책을 읽어보니 그 중 한 넘이 normalized vector 여야 한다는 걸 찾아냈다. 뿌듯.. -_-+
책은 반직선과 구의 충돌이라서 선분 충돌을 구하려면 교차 좌표 중 가까운 넘을 찾아내서 그 길이가 원래 반직선 길이보다 짧아야 진짜 충돌이 된다. 사실 3D 를 쭉 하던 사람들이야 너무 쉬운 것일테지만 수학책을 한동안 놓고 살았던 본인에게는 꽤나 막중한 과제였다. 역시나 해내고 나니 성취감 보다는 허탈감이 든다. 흑.
Imports Microsoft.DirectX
Public Class Form1
Inherits System.Windows.Forms.Form
Dim bCollided As Boolean = False
Dim circleRect As Rectangle
Dim PenWidth As Integer = 1
Dim o As Vector2 = New Vector2
Dim o2 As Vector2 = New Vector2
Dim c As Vector2 = New Vector2
Dim r As Single = New Single
Dim d As Vector2 = New Vector2
Dim l As Vector2 = New Vector2
Dim s As Single = New Single
Dim l2 As Single = New Single
Dim m2 As Single = New Single
Dim world As Matrix = New Matrix
Dim t As Single = New Single
Private Function CheckCollide() As Boolean
r = circleRect.Width / 2
c.X = circleRect.X + r
c.Y = circleRect.Y + r
Dim P As Vector2 = Vector2.Subtract(o2, o)
d = Vector2.Normalize(P)
l = Vector2.Subtract(c, o) ' l = c - o
s = Vector2.Dot(l, d) ' s = l dot d
l2 = Vector2.Dot(l, l) ' l^2 = l dot l
Dim r2 As Single = r * r
If (s r2) Then ' if ( s r^2 ) return reject
Return False
End If
m2 = l2 - s * s ' m^2 = l^2 - s^2
If (m2 > r2) Then ' if ( m^2 > r^2 ) return reject
Return False
End If
' 이제 선분이 교차하고 있다. 교차하는 두 점을 구한 후 가장 가까운 넘과의 거리가 선분의 길이보다 작아야 한다.
Dim q As Single = Math.Sqrt(r2 - m2)
If (l2 > r2) Then
t = s - q
Else
t = s + q
End If
Return P.Length >= t
End Function
Private Sub setupCircle(ByVal e As Point)
If e.X