기본적으로 캡슐은 구의 이동 궤적이라 할 수 있다. (길이가 5이고 반지름이 2인 캡슐이 있다면 0부터 5까지 반지름이 2인 원이 쭉 이동 한 궤적이 바로 캡슐인 것이다.
First, we need a test for the closest point, P, on a line segment, L, to point X.
We can define L as its endpoints A and B:
We can derive the vector, v, as that which points from A to B:
Next, we define a vector, w, pointing from A to our point, X.
Now, we’ve expressed the relationship between X and L in terms of vectors. By defining w and v each pointing from A, we’re working in a 2D Cartesian coordinate frame where A is the origin. Because of this, we can take advantage of some geometrical properties of vectors that will allow us to find the closest point on L to X. Specifically, we’re going to project w onto v:
where dot is the dot product:
When envisioning projection, I find it helpful to think of vectors as having a spatial domain. If you compute the dot product of 2 vectors, it represents how much 1 vector exists in the domain of the other. The dot product of a vector and itself is a value which is a maximum of that vector’s domain. Anything greater than this value exceeds the domain. The dot product of a vector and one perpendicular to it is zero, and defines the minimum of that domain (exclusive). So the domain of a vector, u, in practice, ends up being spanned by any scalar value, q, which satisfies the constraint:
Now let’s apply this geometric intuition to our problem of finding the closest point on a line segment. What happens if the vector w points in an opposite direction than v? dot(w,v) will be negative. Therefore w cannot exist in the domain of v. If this is the case, it should be evident that A will be the closest point on L to X. Next, let’s consider the easy-to-imagine scenario of w exceeding the maximum of v’s domain, by defining w as pointing in the same direction as v, but having twice its length. Clearly, B in this case will be the closest point to X.
Example 1. Closest point on segment to user’s mouse:
If the projection of w onto v does satisfy the domain constraint, then P will be on the segment L (and may also be A or B). So what we need is for our projection to parametrize a point on v. Because projection includes division by the squared length of the vector being projected onto, our domain becomes:
Where t is the projection. By clamping t to this range, and using it to scale the vector v, we find the point on v closest to X. Because we’re working in the space of A, we need to transform back to world coordinates, by adding A:
Here’s the implementation in my geometry library (Vector2D is not a native data type), with the variables changed to match the description of the problem:
Circle/Line Collision Test
Now that we’ve found the closest point on a line segment, L, to a point, X, determining intersection of a circle and line segment is as simple as checking whether the distance between X and P is less than the radius of the circle. Of course, X defines the center of the circle.
Example 2. Intersecting a circle and line segment:
Note that in the code below, I’m checking for distance by comparing the squared distance against the squared length of the circle’s radius. This is to avoid an expensive square root call.
Circle/Capsule Collision Test
Lastly, intersecting a circle and a capsule is as simple as inflating the circle’s radius by the radius of the capsule. You can see in the below example that we’re really just doing a circle/line test on an inflated circle.
Example 3. Intersecting a circle and capsule:
One extremely nice aspect of working with circles is that, not allowing the shapes to penetrate, circle’s can be touching another convex shape at a maximum of 1 point. Due in part to this convenience, the collision normal will always point from the closest point on the convex shape through the circle’s center.
'Programming > 물리엔진/게임엔진' 카테고리의 다른 글
오일러각 - gimbal lock 문제(쿼터니언으로 해결 가능) (0) | 2013.01.29 |
---|---|
쿼터니온을 Yaw, Pitch, Roll 로 뽑기 (0) | 2013.01.29 |
구와 박스(OBB 또는 AABB)의 충돌체크 (0) | 2013.01.29 |
물리엔진 구현에 필요한 요소들 및 구현 팁(생각나는대로 추가 중) (0) | 2013.01.29 |
간단한 충돌체크 및 간단한 수학 (0) | 2013.01.29 |