728x90
Collider.cpp, h
더보기
#pragma once
//-----------------------------------------------------------------------------
//Ray
//-----------------------------------------------------------------------------
struct Ray
{
Ray()
: Position(0, 0, 0), Direction(0, 0, 0)
{
}
Ray(Vector3& position, Vector3& direction)
: Position(position), Direction(direction)
{
}
Vector3 Position;
Vector3 Direction;
};
//-----------------------------------------------------------------------------
//ColliderObject
//-----------------------------------------------------------------------------
struct ColliderObject
{
class Transform* Init = NULL;//실제 본의 위치가 안맞아서 보정하는 값
class Transform* World = NULL;
class Collider* Collision = NULL;
public:
ColliderObject();
~ColliderObject();
};
//-----------------------------------------------------------------------------
//Collider
//-----------------------------------------------------------------------------
class Collider
{
public:
Collider(Transform* transform, Transform* init = NULL);
~Collider();
void Update();
void Render(Color color = Color(0, 1, 0, 1));
bool Intersection(Vector3& position, Vector3& direction, float* outDistance = NULL);
bool Intersection(Ray& ray, float* outDistance = NULL);
private:
Transform* init = NULL;
Transform* transform;
Vector3 lines[8];
};
bool Collider::Intersection(Vector3 & position, Vector3 & direction, float * outDistance)
{
return Intersection(Ray(position, direction), outDistance);
}
bool Collider::Intersection(Ray & ray, float * outDistance)
{
//컬라이더가 붙을 월드 위치
Transform temp;
temp.World(transform->World());
//보정값이 있다면 보정공간을 컬라이더가 붙을 월드 위치로 변환
if (init != NULL) temp.World(init->World() * transform->World());
Matrix world = temp.World();
Vector3 minPosition, maxPosition;
D3DXVec3TransformCoord(&minPosition, &lines[0], &world);
D3DXVec3TransformCoord(&maxPosition, &lines[7], &world);
if (fabsf(ray.Direction.x) == 0) ray.Direction.x = 1e-6f;
if (fabsf(ray.Direction.y) == 0) ray.Direction.y = 1e-6f;
if (fabsf(ray.Direction.z) == 0) ray.Direction.z = 1e-6f;
float minValue = 0.0f, maxValue = FLT_MAX;
//X축 검사
if (fabsf(ray.Direction.x) >= 1e-6f)
{
float value = 1.0f / ray.Direction.x;
float minX = (minPosition.x - ray.Position.x) * value;
float maxX = (maxPosition.x - ray.Position.x) * value;
if (minX > maxX)
{
float temp = minX;
minX = maxX;
maxX = temp;
}
minValue = max(minX, minValue);
maxValue = min(maxX, maxValue);
if (minValue > maxValue)
return false;
}
//Y축 검사
if (fabsf(ray.Direction.y) >= 1e-6f)
{
float value = 1.0f / ray.Direction.y;
float minY = (minPosition.y - ray.Position.y) * value;
float maxY = (maxPosition.y - ray.Position.y) * value;
if (minY > maxY)
{
float temp = minY;
minY = maxY;
maxY = temp;
}
minValue = max(minY, minValue);
maxValue = min(maxY, maxValue);
if (minValue > maxValue)
return false;
}
//Z축 검사
if (fabsf(ray.Direction.z) >= 1e-6f)
{
float value = 1.0f / ray.Direction.z;
float minZ = (minPosition.z - ray.Position.z) * value;
float maxZ = (maxPosition.z - ray.Position.z) * value;
if (minZ > maxZ)
{
float temp = minZ;
minZ = maxZ;
maxZ = temp;
}
minValue = max(minZ, minValue);
maxValue = min(maxZ, maxValue);
if (minValue > maxValue)
return false;
}
if (outDistance != NULL)
*outDistance = minValue;
return true;
}
기존Collider cpp, h에 추가로 함수, 구조체 선언 정의
Viewport.cpp, h
더보기


void Viewport::GetMouseRay(Vector3 * outPosition, Vector3 * outDirection, Matrix * world)
{
Matrix W;
if (world != NULL) memcpy(&W, world, sizeof(Matrix));
else D3DXMatrixIdentity(&W);
Matrix V = Context::Get()->View();
Matrix P = Context::Get()->Projection();
Viewport* Vp = Context::Get()->GetViewport();
Vector3 mouse = Mouse::Get()->GetPosition();
mouse.z = 0.0f;
Vector3 n = Vp->Unproject(mouse, W, V, P);
mouse.z = 1.0f;
Vector3 f = Vp->Unproject(mouse, W, V, P);
//2D -> 3D 좌표계 값 셋팅
*outPosition = n;
*outDirection = f - n;
}
마우스 2D->3D 좌표계 값을 받는 함수 정의
AnimationDemo.cpp h
더보기




헤더(private)에 변수 하나 선언


cpp, Update, Render 영역에 추가
실행
보충
더보기




Collider AABB 충돌 관련 함수를 설명 하자면

요건 Vector3(위치), Vector3(방향), float (거리) 받아서 아래에 있는 함수에 Ray 구조체 형태로 값을 넘겨주는 외부 호출용 함수

이제 요 함수에서 처리를 해주는데 분류를 하자면
1. 셋팅

마우스의 위치, 방향, 거리를 받아서 계산할 준비 단계 이다. 여기서 기억 해둬야 할점은 ray는 마우스 값
2. AABB충돌 계산

조건 -> 마우스 방향의x 값이 크거나 같을 경우 계산을 해주는데
value : 1.0f에 마우스 방향의 x 값을 나누어진 값
mixX : minPosition (왼쪽하단) * 마우스.x * value -> 왼쪽 하단 마우스 위치를 빼고 값
maxX : maxPosition (우측상단) * 마우스.x * value -> 우측 상단 마우스 위치를 빼고 값
조건 minX가 maxX 클 경우 교환
minValue, maxValue : 마우스와 Collider의 충돌 여부 판정
x,y,z 검사해서 3개의 조건에서 넘어가지면 true 반환
문제점
AABB충돌의 문제점은 2D에도 작성 하듯이 실제 충돌 범위는 초록색 박스 범위내에서 다 충돌 처리 되어버린다
해결 방안은 OBB 충돌 처리로 바꿔서 실시간 값을 받아서 충돌 처리 해주면 된다.
'DirectX > DirectX 3D_(구)' 카테고리의 다른 글
30_Instance (0) | 2021.08.08 |
---|---|
29_RenderShader (0) | 2021.08.04 |
27_Raycast (0) | 2021.08.03 |
26_Projection (0) | 2021.08.03 |
25_Viewport (0) | 2021.08.02 |