글의 요약 설명 부분. 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);
    }

    마우스 누른 부분이 충돌되었는지 확인

     


     

    실행화면