응애맘마조

230531 강의 본문

공부/3D강의

230531 강의

TH.Wert 2023. 5. 31. 23:55

충돌 처리에 대해 강의를 했었습니다.

#include "Common.hlsl"

struct VertexInput
{
    float4 Position : POSITION0;
    float4 Color : COLOR0;
};
struct PixelInput
{
    float4 Position : SV_POSITION;
    float4 Color : COLOR0;
};

PixelInput VS(VertexInput input)
{
   
    PixelInput output;
    output.Position = mul(input.Position, World);
    output.Position = mul(output.Position, ViewProj);
    output.Color = input.Color;
    return output;
}

float4 PS(PixelInput input) : SV_TARGET
{
    return float4(1, 0, 0, 1);
}

충돌 처리의 객체를 확인하기 위해 색상을 빨간색으로 했습니다. 항상 만들던 객체들은 모서리가 전부 검은색입니다.

#pragma once
enum class ColliderType
{
   SPHERE,
   BOX,
   OBOX,
};

class Collider : public Transform
{
    friend class GameObject;
public:
    shared_ptr<Mesh>        mesh;
    shared_ptr<Shader>      shader;
    ColliderType            type;
    bool                    visible;
public:
    Collider(ColliderType type);
    ~Collider();
    void                Update(class GameObject* ob);
    void                Render();
    void                RenderDetail();
    bool                Intersect(Collider* target);
    bool                Intersect(Ray Ray,Vector3& Hit);
};
#include "Framework.h"

Collider::Collider(ColliderType type)
{
	this->type = type;
	visible = true;
	switch (type)
	{
	case ColliderType::SPHERE:
		mesh = RESOURCE->meshes.Load("1.SphereCollider.mesh");
		break;
	case ColliderType::BOX:
		mesh = RESOURCE->meshes.Load("1.BoxCollider.mesh");
		break;
	case ColliderType::OBOX:
		mesh = RESOURCE->meshes.Load("1.BoxCollider.mesh");
		break;
	}
	shader = RESOURCE->shaders.Load("1.Collider.hlsl");
}

Collider::~Collider()
{
	SafeReset(mesh);
	SafeReset(shader);
}

void Collider::Update(GameObject* ob)
{
	parent = ob;
	if (type == ColliderType::SPHERE)
	{
		scale.z = scale.y = scale.x;
	}
	Transform::Update();
	if (type == ColliderType::BOX)
	{
		T = Matrix::CreateTranslation(GetWorldPos());
		W = S * T;
	}
}

void Collider::Render()
{
	if (visible)
	{
		Transform::Set();
		mesh->Set();
		shader->Set();
		D3D->GetDC()->DrawIndexed(mesh->indexCount, 0, 0);
	}
}

void Collider::RenderDetail()
{
	switch (type)
	{
	case ColliderType::SPHERE:
	{
		ImGui::Text("Sphere");
		break;
	}
	case ColliderType::BOX:
	{
		ImGui::Text("Box");
		break;
	}
	case ColliderType::OBOX:
	{
		ImGui::Text("OBox");
		break;
	}
	}
	ImGui::Checkbox("isVisible", &visible);
	Transform::RenderDetail();
}

bool Collider::Intersect(Collider* target)
{
	if (type == ColliderType::BOX)
	{
		BoundingBox box1;
		box1.Center = GetWorldPos();
		box1.Extents = Vector3(S._11, S._22, S._33);
		if (target->type == ColliderType::BOX)
		{
			BoundingBox box2;
			box2.Center = target->GetWorldPos();
			box2.Extents = Vector3(target->S._11, target->S._22, target->S._33);
			return box1.Intersects(box2);
		}
		else if (target->type == ColliderType::OBOX)
		{
			BoundingOrientedBox box2;
			box2.Center = target->GetWorldPos();
			box2.Extents = Vector3(target->S._11, target->S._22, target->S._33);
			box2.Orientation = Quaternion::CreateFromRotationMatrix(target->RT);
			return box1.Intersects(box2);
		}
		else
		{
			BoundingSphere box2;
			box2.Center = target->GetWorldPos();
			box2.Radius = target->S._11 ;
			return box1.Intersects(box2);
		}
	}
	else if (type == ColliderType::OBOX)
	{
		BoundingOrientedBox box1;
		box1.Center = GetWorldPos();
		box1.Extents = Vector3(S._11, S._22, S._33) ;
		box1.Orientation = Quaternion::CreateFromRotationMatrix(RT);
		if (target->type == ColliderType::BOX)
		{
			BoundingBox box2;
			box2.Center = target->GetWorldPos();
			box2.Extents = Vector3(target->S._11, target->S._22, target->S._33);
			return box1.Intersects(box2);
		}
		else if (target->type == ColliderType::OBOX)
		{
			BoundingOrientedBox box2;
			box2.Center = target->GetWorldPos();
			box2.Extents = Vector3(target->S._11, target->S._22, target->S._33);
			box2.Orientation = Quaternion::CreateFromRotationMatrix(target->RT);
			return box1.Intersects(box2);
		}
		else
		{
			BoundingSphere box2;
			box2.Center = target->GetWorldPos();
			box2.Radius = target->S._11;
			return box1.Intersects(box2);
		}
	}
	else
	{
		BoundingSphere box1;
		box1.Center = GetWorldPos();
		box1.Radius = S._11;
		if (target->type == ColliderType::BOX)
		{
			BoundingBox box2;
			box2.Center = target->GetWorldPos();
			box2.Extents = Vector3(target->S._11, target->S._22, target->S._33) ;
			return box1.Intersects(box2);
		}
		else if (target->type == ColliderType::OBOX)
		{
			BoundingOrientedBox box2;
			box2.Center = target->GetWorldPos();
			box2.Extents = Vector3(target->S._11, target->S._22, target->S._33);
			box2.Orientation = Quaternion::CreateFromRotationMatrix(target->RT);
			return box1.Intersects(box2);
		}
		else
		{
			BoundingSphere box2;
			box2.Center = target->GetWorldPos();
			box2.Radius = target->S._11 ;
			return box1.Intersects(box2);
		}
	}
	return false;
}

bool Collider::Intersect(Ray Ray, Vector3& Hit)
{
	Ray.direction.Normalize();
	float Dis;
	bool result = false;
	if (type == ColliderType::BOX)
	{
		BoundingBox box1;
		box1.Center = GetWorldPos();
		box1.Extents = Vector3(S._11, S._22, S._33);
		result =Ray.Intersects(box1, Dis);
		Hit = Ray.position + Ray.direction * Dis;
	}
	else if (type == ColliderType::OBOX)
	{
		BoundingBox box1;
		box1.Center = Vector3(0,0,0);
		box1.Extents = Vector3(S._11, S._22, S._33) ;
		Matrix inverse = S.Invert() * W;
		inverse = inverse.Invert();
		Ray.position = Vector3::Transform(Ray.position, inverse);
		Ray.direction = Vector3::TransformNormal(Ray.direction, inverse);
		Ray.direction.Normalize();


		result = Ray.Intersects(box1, Dis);
		Hit = Ray.position + Ray.direction * Dis;
		Hit = Vector3::Transform(Hit, inverse.Invert());
	}
	else
	{
		BoundingSphere box1;
		box1.Center = GetWorldPos();
		box1.Radius = S._11;
		result = Ray.Intersects(box1, Dis);
		Hit = Ray.position + Ray.direction * Dis;
	}

	return result;
}

헤더와 cpp파일입니다.

AABB일 때와 OBB일 때의 충돌처리를 했습니다. AABB는 정렬된 축으로 충돌을 판정하기 때문에 rotation을 할 수 없도록 하고 OBB는 회전된 축으로 판정을 해야 하기 때문에 2D에서 했던 것처럼 투영을 해서 판정을 해야 되기 때문에 연산량이 많아지게 됩니다. 그래서 게임을 만들 때 AABB 안에 먼저 들어와 있는지 판정을 먼저 하고 OBB를 하는 것이 좋다고 합니다.

 

읽어주셔서 감사합니다.

'공부 > 3D강의' 카테고리의 다른 글

230602 강의  (0) 2023.06.05
230601 강의  (0) 2023.06.01
230530 강의  (0) 2023.05.30
230526 강의  (0) 2023.05.29
230525 강의  (0) 2023.05.25