[DirectX11] 069 Collider
글의 요약 설명 부분. 150자를 적어주세요. 글의 요약 설명 부분. 150자를 적어주세요. 글의 요약 설명 부분. 150자를 적어주세요. 글의 요약 설명 부분. 150자를 적어주세요. 글의 요약 설명 부분. 150자를 적어주세요. 글의 요약 설명 부분. 150자입니다
목차
Collider
Shader | |
Framework | |
Objects | |
Collider.h .cpp | |
UnitTest | |
Objects | |
ObbRaycastDemo.h .cpp 생성 | |
Main.h .cpp |
Collider
Collider.h
더보기
#pragma once
struct Ray
{
Ray() : Position(0, 0, 0), Direction(0, 0, 0)
{
}
Ray(Vector3& position, Vector3& direction)
:Position(position), Direction(direction)
{
}
Vector3 Position;
Vector3 Direction;
};
struct ColliderObject
{
class Transform* Init = NULL;
class Transform* Transform = NULL;
class Collider* Collider = NULL;
};
class Collider
{
public:
Collider(Transform* transform, Transform* init = NULL);
~Collider();
void Update();
void Render(Color color = Color(0, 1, 0, 1));
Transform* GetTransform() { return transform; }
bool Intersection(Ray& ray, float* outDistance);
private:
Transform* init = NULL;
Transform* transform;
Vector3 lines[8];
};
Collider.cpp
더보기
#include "Framework.h"
#include "Collider.h"
Collider::Collider(Transform * transform, Transform * init)
: transform(transform), init(init)
{
lines[0] = Vector3(-0.5f, -0.5f, -0.5f); //Min
lines[1] = Vector3(-0.5f, +0.5f, -0.5f);
lines[2] = Vector3(+0.5f, -0.5f, -0.5f);
lines[3] = Vector3(+0.5f, +0.5f, -0.5f);
lines[4] = Vector3(-0.5f, -0.5f, +0.5f);
lines[5] = Vector3(-0.5f, +0.5f, +0.5f);
lines[6] = Vector3(+0.5f, -0.5f, +0.5f);
lines[7] = Vector3(+0.5f, +0.5f, +0.5f); //Max
}
Collider::~Collider()
{
}
void Collider::Update()
{
}
void Collider::Render(Color color)
{
Transform temp;
temp.World(transform->World());
if (init != NULL)
temp.World(init->World() * transform->World());
Matrix world = temp.World();
Vector3 dest[8];
for (UINT i = 0; i < 8; i++)
D3DXVec3TransformCoord(&dest[i], &lines[i], &world);
//Front
DebugLine::Get()->RenderLine(dest[0], dest[1], color);
DebugLine::Get()->RenderLine(dest[1], dest[3], color);
DebugLine::Get()->RenderLine(dest[3], dest[2], color);
DebugLine::Get()->RenderLine(dest[2], dest[0], color);
//Backward
DebugLine::Get()->RenderLine(dest[4], dest[5], color);
DebugLine::Get()->RenderLine(dest[5], dest[7], color);
DebugLine::Get()->RenderLine(dest[7], dest[6], color);
DebugLine::Get()->RenderLine(dest[6], dest[4], color);
//Side
DebugLine::Get()->RenderLine(dest[0], dest[4], color);
DebugLine::Get()->RenderLine(dest[1], dest[5], color);
DebugLine::Get()->RenderLine(dest[2], dest[6], color);
DebugLine::Get()->RenderLine(dest[3], dest[7], color);
}
bool Collider::Intersection(Ray & ray, float * outDistance)
{
*outDistance = 0.0f;
Vector3 dest[8];
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.0f) ray.Direction.x = 1e-6f;
if (fabsf(ray.Direction.y) == 0.0f) ray.Direction.y = 1e-6f;
if (fabsf(ray.Direction.z) == 0.0f) ray.Direction.z = 1e-6f;
float minValue = 0.0f, maxValue = FLT_MAX;
//Check 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;
}
//거리 안에 없는 경우
else if (ray.Position.x < minPosition.x || ray.Position.x > maxPosition.x)
return false;
//Check 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;
}
//거리 안에 없는 경우
else if (ray.Position.y < minPosition.y || ray.Position.y > maxPosition.y)
return false;
//Check 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;
}
//거리 안에 없는 경우
else if (ray.Position.z < minPosition.z || ray.Position.z > maxPosition.z)
return false;
//거리 안에 있는 경우 최소거리(minValue)를 넣어서 리턴해준다.
*outDistance = minValue;
return true;
}
Obb Raycast Demo
ObbRaycastDemo.h
더보기
#pragma once
#include "Systems/IExecute.h"
class ObbRaycastDemo : public IExecute
{
public:
virtual void Initialize() override;
virtual void Ready() override {}
virtual void Destroy() override {}
virtual void Update() override;
virtual void PreRender() override {}
virtual void Render() override;
virtual void PostRender() override {}
virtual void ResizeScreen() override {}
private:
void Mesh();
void Airplane();
void Kachujin();
void KachujinCollider();
void CheckIntersection(); //마우스가 눌렸는지 체크
void Pass(UINT mesh, UINT model, UINT anim);
private:
Shader* shader;
CubeSky* sky;
Material* floor;
Material* stone;
Material* brick;
Material* wall;
MeshRender* cube;
MeshRender* cylinder;
MeshRender* sphere;
MeshRender* grid;
ModelRender* airplane = NULL;
ModelAnimator* kachujin = NULL;
ColliderObject** colliders;
int collisionIndex = -1; //Default값 설정. 마우스가 눌리면 값을 바꿔줄 것이다.
vector<MeshRender *> meshes;
vector<ModelRender *> models;
vector<ModelAnimator *> animators;
};
ObbRaycastDemo.cpp
더보기
#include "stdafx.h"
#include "ObbRaycastDemo.h"
void ObbRaycastDemo::Initialize()
{
Context::Get()->GetCamera()->RotationDegree(20, 0, 0);
Context::Get()->GetCamera()->Position(1, 36, -85);
shader = new Shader(L"55_Render.fx");
sky = new CubeSky(L"Environment/GrassCube1024.dds");
Mesh();
Airplane();
Kachujin();
KachujinCollider();
}
void ObbRaycastDemo::Update()
{
sky->Update();
cube->Update();
grid->Update();
cylinder->Update();
sphere->Update();
airplane->Update();
kachujin->Update();
for (UINT i = 0; i < kachujin->GetTransformCount(); i++)
{
Matrix attach;
kachujin->GetAttachTransform(i, &attach);
colliders[i]->Collider->GetTransform()->World(attach);
colliders[i]->Collider->Update();
}
CheckIntersection();
}
void ObbRaycastDemo::Render()
{
sky->Render();
Pass(0, 1, 2);
wall->Render();
sphere->Render();
brick->Render();
cylinder->Render();
stone->Render();
cube->Render();
floor->Render();
grid->Render();
airplane->Render();
kachujin->Render();
for (UINT i = 0; i < kachujin->GetTransformCount(); i++)
{
if ((int)i == collisionIndex)
colliders[i]->Collider->Render(Color(1, 0, 0, 1));
else
colliders[i]->Collider->Render();
}
}
void ObbRaycastDemo::Mesh()
{
//Create Material
{
floor = new Material(shader);
floor->DiffuseMap("Floor.png");
//floor->SpecularMap("Floor_Specular.png");
//floor->NormalMap("Floor_Normal.png");
//floor->Specular(1, 1, 1, 20);
stone = new Material(shader);
stone->DiffuseMap("Stones.png");
//stone->SpecularMap("Stones_Specular.png");
//stone->NormalMap("Stones_Normal.png");
//stone->Specular(1, 1, 1, 20);
brick = new Material(shader);
brick->DiffuseMap("Bricks.png");
//brick->SpecularMap("Bricks_Specular.png");
//brick->NormalMap("Bricks_Normal.png");
//brick->Specular(1, 0.3f, 0.3f, 20);
wall = new Material(shader);
wall->DiffuseMap("Wall.png");
//wall->SpecularMap("Wall_Specular.png");
//wall->NormalMap("Wall_Normal.png");
//wall->Specular(1, 1, 1, 20);
}
//Create Mesh
{
Transform* transform = NULL;
cube = new MeshRender(shader, new MeshCube());
transform = cube->AddTransform();
transform->Position(0, 5, 0);
transform->Scale(20, 10, 20);
grid = new MeshRender(shader, new MeshGrid(5, 5));
transform = grid->AddTransform();
transform->Position(0, 0, 0);
transform->Scale(12, 1, 12);
cylinder = new MeshRender(shader, new MeshCylinder(0.5f, 3.0f, 20, 20));
sphere = new MeshRender(shader, new MeshSphere(0.5f, 20, 20));
for (UINT i = 0; i < 5; i++)
{
transform = cylinder->AddTransform();
transform->Position(-30, 6, -15.0f + (float)i * 15.0f);
transform->Scale(5, 5, 5);
transform = cylinder->AddTransform();
transform->Position(30, 6, -15.0f + (float)i * 15.0f);
transform->Scale(5, 5, 5);
transform = sphere->AddTransform();
transform->Position(-30, 15.5f, -15.0f + (float)i * 15.0f);
transform->Scale(5, 5, 5);
transform = sphere->AddTransform();
transform->Position(30, 15.5f, -15.0f + (float)i * 15.0f);
transform->Scale(5, 5, 5);
}
}
sphere->UpdateTransforms();
cylinder->UpdateTransforms();
cube->UpdateTransforms();
grid->UpdateTransforms();
meshes.push_back(sphere);
meshes.push_back(cylinder);
meshes.push_back(cube);
meshes.push_back(grid);
}
void ObbRaycastDemo::Airplane()
{
airplane = new ModelRender(shader);
airplane->ReadMesh(L"B787/Airplane");
airplane->ReadMaterial(L"B787/Airplane");
Transform* transform = airplane->AddTransform();
transform->Position(2.0f, 9.91f, 2.0f);
transform->Scale(0.004f, 0.004f, 0.004f);
airplane->UpdateTransforms();
models.push_back(airplane);
}
void ObbRaycastDemo::Kachujin()
{
kachujin = new ModelAnimator(shader);
kachujin->ReadMesh(L"Kachujin/Mesh");
kachujin->ReadMaterial(L"Kachujin/Mesh");
kachujin->ReadClip(L"Kachujin/Sword And Shield Idle");
kachujin->ReadClip(L"Kachujin/Sword And Shield Walk");
kachujin->ReadClip(L"Kachujin/Sword And Shield Run");
kachujin->ReadClip(L"Kachujin/Sword And Shield Slash");
kachujin->ReadClip(L"Kachujin/Salsa Dancing");
Transform* transform = NULL;
transform = kachujin->AddTransform();
transform->Position(0, 0, -30);
transform->Scale(0.075f, 0.075f, 0.075f);
kachujin->PlayTweenMode(0, 0, 1.0f);
transform = kachujin->AddTransform();
transform->Position(-15, 0, -30);
transform->Scale(0.075f, 0.075f, 0.075f);
kachujin->PlayTweenMode(1, 1, 1.0f);
transform = kachujin->AddTransform();
transform->Position(-30, 0, -30);
transform->Scale(0.075f, 0.075f, 0.075f);
kachujin->PlayTweenMode(2, 2, 0.75f);
transform = kachujin->AddTransform();
transform->Position(15, 0, -30);
transform->Scale(0.075f, 0.075f, 0.075f);
kachujin->PlayBlendMode(3, 0, 1, 2);
kachujin->SetBlendAlpha(3, 1.5f);
transform = kachujin->AddTransform();
transform->Position(30, 0, -32.5f);
transform->Scale(0.075f, 0.075f, 0.075f);
kachujin->PlayTweenMode(4, 4, 0.75f);
kachujin->UpdateTransforms();
kachujin->SetAttachTransform(40);
animators.push_back(kachujin);
}
void ObbRaycastDemo::KachujinCollider()
{
UINT count = kachujin->GetTransformCount();
colliders = new ColliderObject*[count];
for (UINT i = 0; i < count; i++)
{
colliders[i] = new ColliderObject();
colliders[i]->Init = new Transform();
colliders[i]->Init->Position(0, 0, 0);
colliders[i]->Init->Scale(10, 30, 10);
colliders[i]->Transform = new Transform();
colliders[i]->Collider = new Collider(colliders[i]->Transform, colliders[i]->Init);
}
}
//마우스가 눌렸는지 체크
void ObbRaycastDemo::CheckIntersection()
{
if (Mouse::Get()->Down(0) == false) return;
Matrix V = Context::Get()->View();
Matrix P = Context::Get()->Projection();
Viewport* Vp = Context::Get()->GetViewport();
Vector3 mouse = Mouse::Get()->GetPosition();
Matrix world;
D3DXMatrixIdentity(&world);
Vector3 n, f;
mouse.z = 0.0f;
Vp->Unproject(&n, mouse, world, V, P);
mouse.z = 1.0f;
Vp->Unproject(&f, mouse, world, V, P);
Ray ray;
ray.Position = n;
ray.Direction = f - n;
float distance = 0.0f;
UINT count = kachujin->GetTransformCount();
bool check = false;
for (UINT i = 0; i < count; i++)
{
//충돌이 되었다면(=마우스가 눌렸다면)
if (colliders[i]->Collider->Intersection(ray, &distance))
{
collisionIndex = (int)i; //collisionIndex 값을 넣어준다.
check = true;
break;
}
}
//충돌이 되지 않았다면
if (check == false)
collisionIndex = -1; //collisionIndex은 default값인 -1
}
void ObbRaycastDemo::Pass(UINT mesh, UINT model, UINT anim)
{
for (MeshRender* temp : meshes)
temp->Pass(mesh);
for (ModelRender* temp : models)
temp->Pass(model);
for (ModelAnimator* temp : animators)
temp->Pass(anim);
}
마우스 누른 부분이 충돌되었는지 확인
실행화면
'⭐ DirectX > DirectX11 3D' 카테고리의 다른 글
[DirectX11] 071~73 Get MultiBones (0) | 2023.03.15 |
---|---|
[DirectX11] 070 OBB(Oriented Bounding Box) collision (3) | 2023.03.14 |
[DirectX11] 068 Unprojection - 2D 좌표를 3D 좌표로 변환 (0) | 2023.03.13 |
[DirectX11] 067 Projection (0) | 2023.03.09 |
[DirectX11] 066 3D 공간에서 충돌체 선택하기 (0) | 2023.03.08 |
댓글
이 글 공유하기
다른 글
-
[DirectX11] 071~73 Get MultiBones
[DirectX11] 071~73 Get MultiBones
2023.03.15 -
[DirectX11] 070 OBB(Oriented Bounding Box) collision
[DirectX11] 070 OBB(Oriented Bounding Box) collision
2023.03.14 -
[DirectX11] 068 Unprojection - 2D 좌표를 3D 좌표로 변환
[DirectX11] 068 Unprojection - 2D 좌표를 3D 좌표로 변환
2023.03.13 -
[DirectX11] 067 Projection
[DirectX11] 067 Projection
2023.03.09