add collision
This commit is contained in:
parent
285250d83f
commit
54f5e96b7c
@ -1,102 +1,8 @@
|
|||||||
#include "precompile.h"
|
#include "precompile.h"
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include<cfloat>
|
|
||||||
|
|
||||||
#include "entity.h"
|
#include "entity.h"
|
||||||
#include "collider.h"
|
#include "collider.h"
|
||||||
|
#include "collision.h"
|
||||||
static bool IntersectSegmentCircle(Vector2D& p0, Vector2D& p1, Vector2D& pos, float rad)
|
|
||||||
{
|
|
||||||
Vector2D t = p1 - p0;
|
|
||||||
float d = std::max(t.Norm(), 0.0001f);
|
|
||||||
Vector2D n = p0 - pos;
|
|
||||||
float v = n.Dot(t);
|
|
||||||
float z = n.Dot(n) - rad*rad;
|
|
||||||
if (z > 0 && v > 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
float u = v*v - z;
|
|
||||||
if (u < 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
float i = sqrt(u);
|
|
||||||
float x = -v - i;
|
|
||||||
if (x < 0 && (x = -v + i), x <= d) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool IntersectSegmentAabb(Vector2D& p0, Vector2D& p1, Vector2D& _min, Vector2D& _max)
|
|
||||||
{
|
|
||||||
float t = 0.0f;
|
|
||||||
float d = FLT_MAX;
|
|
||||||
Vector2D n = p0;
|
|
||||||
Vector2D v = p1 - p0;
|
|
||||||
float z = v.Norm();
|
|
||||||
v = z > (float)1e-5 ? v / z : Vector2D(1, 0);
|
|
||||||
if (std::abs(v.x) < (float)1e-5) {
|
|
||||||
v.x = float(2e-5);
|
|
||||||
}
|
|
||||||
if (std::abs(v.y) < (float)1e-5) {
|
|
||||||
v.y = (float)2e-5;
|
|
||||||
}
|
|
||||||
if (std::abs(v.x) > (float)1e-5) {
|
|
||||||
float u = (_min.x - n.x) / v.x;
|
|
||||||
float i = (_max.x - n.x) / v.x;
|
|
||||||
t = std::max(t, std::min(u, i));
|
|
||||||
d = std::min(d, std::max(u, i));
|
|
||||||
if (t > d) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (std::abs(v.y) > (float)1e-5) {
|
|
||||||
float x = (_min.y - n.y) / v.y;
|
|
||||||
float l = (_max.y - n.y) / v.y;
|
|
||||||
t = std::max(t, std::min(x, l));
|
|
||||||
d = std::min(d, std::max(x, l));
|
|
||||||
if (t > d) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (t > z) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool IntersectAabbCircle(AabbCollider* a, CircleCollider* b)
|
|
||||||
{
|
|
||||||
if (b->pos.x >= a->_min.x && b->pos.x <= a->_max.x &&
|
|
||||||
b->pos.y >= a->_min.y && b->pos.y <= a->_max.y) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Vector2D nearest_point(a8::Clamp(b->pos.x, a->_min.x, a->_max.y),
|
|
||||||
a8::Clamp(b->pos.y, a->_min.y, a->_max.y));
|
|
||||||
Vector2D i = b->pos - nearest_point;
|
|
||||||
float n = a8::LengthSqr(i);
|
|
||||||
return n < b->rad*b->rad;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool IntersectAabbAabb(AabbCollider* a, AabbCollider* b)
|
|
||||||
{
|
|
||||||
Vector2D a_v = (a->_max - a->_min) * 0.5f;
|
|
||||||
Vector2D a_center = a->_min + a_v;
|
|
||||||
Vector2D b_v = (b->_max - b->_min) * 0.5f;
|
|
||||||
Vector2D b_center = b->_min + b_v;
|
|
||||||
Vector2D z = b_center - a_center;
|
|
||||||
float u = a_v.x + b_v.x - std::abs(z.x);
|
|
||||||
return u > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool IntersectCircleCircle(CircleCollider* a, CircleCollider* b)
|
|
||||||
{
|
|
||||||
float t = a->rad + b->rad;
|
|
||||||
Vector2D d = b->pos - a->pos;
|
|
||||||
float n = a8::LengthSqr(d);
|
|
||||||
return n < t*t;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ColliderComponent::Intersect(ColliderComponent* b)
|
bool ColliderComponent::Intersect(ColliderComponent* b)
|
||||||
{
|
{
|
||||||
@ -105,17 +11,27 @@ bool ColliderComponent::Intersect(ColliderComponent* b)
|
|||||||
break;
|
break;
|
||||||
case CT_Aabb:
|
case CT_Aabb:
|
||||||
{
|
{
|
||||||
|
AabbCollider* a_aabb = (AabbCollider*)this;
|
||||||
switch (b->type) {
|
switch (b->type) {
|
||||||
case CT_None:
|
case CT_None:
|
||||||
break;
|
break;
|
||||||
case CT_Aabb:
|
case CT_Aabb:
|
||||||
{
|
{
|
||||||
return IntersectAabbAabb((AabbCollider*)this, (AabbCollider*)b);
|
AabbCollider* b_aabb = (AabbCollider*)b;
|
||||||
|
return IntersectAabbAabb(a_aabb->_min,
|
||||||
|
a_aabb->_max,
|
||||||
|
b_aabb->_min,
|
||||||
|
b_aabb->_max
|
||||||
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CT_Circle:
|
case CT_Circle:
|
||||||
{
|
{
|
||||||
return IntersectAabbCircle((AabbCollider*)this, (CircleCollider*)b);
|
CircleCollider* b_circle = (CircleCollider*)b;
|
||||||
|
return IntersectAabbCircle(a_aabb->_min,
|
||||||
|
a_aabb->_max,
|
||||||
|
b_circle->pos,
|
||||||
|
b_circle->rad);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -123,17 +39,27 @@ bool ColliderComponent::Intersect(ColliderComponent* b)
|
|||||||
break;
|
break;
|
||||||
case CT_Circle:
|
case CT_Circle:
|
||||||
{
|
{
|
||||||
|
CircleCollider* a_circle = (CircleCollider*)this;
|
||||||
switch (b->type) {
|
switch (b->type) {
|
||||||
case CT_None:
|
case CT_None:
|
||||||
break;
|
break;
|
||||||
case CT_Aabb:
|
case CT_Aabb:
|
||||||
{
|
{
|
||||||
return IntersectAabbCircle((AabbCollider*)b, (CircleCollider*)this);
|
AabbCollider* b_aabb = (AabbCollider*)b;
|
||||||
|
return IntersectAabbCircle(b_aabb->_min,
|
||||||
|
b_aabb->_max,
|
||||||
|
a_circle->pos,
|
||||||
|
a_circle->rad);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CT_Circle:
|
case CT_Circle:
|
||||||
{
|
{
|
||||||
return IntersectCircleCircle((CircleCollider*)this, (CircleCollider*)b);
|
CircleCollider* b_circle = (CircleCollider*)b;
|
||||||
|
return IntersectCircleCircle(
|
||||||
|
a_circle->pos,
|
||||||
|
a_circle->rad,
|
||||||
|
b_circle->pos,
|
||||||
|
b_circle->rad);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
96
server/gameserver/collision.cc
Normal file
96
server/gameserver/collision.cc
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
#include "precompile.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include<cfloat>
|
||||||
|
|
||||||
|
bool IntersectSegmentCircle(Vector2D& p0, Vector2D& p1, Vector2D& pos, float rad)
|
||||||
|
{
|
||||||
|
Vector2D t = p1 - p0;
|
||||||
|
float d = std::max(t.Norm(), 0.0001f);
|
||||||
|
Vector2D n = p0 - pos;
|
||||||
|
float v = n.Dot(t);
|
||||||
|
float z = n.Dot(n) - rad*rad;
|
||||||
|
if (z > 0 && v > 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
float u = v*v - z;
|
||||||
|
if (u < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
float i = sqrt(u);
|
||||||
|
float x = -v - i;
|
||||||
|
if (x < 0 && (x = -v + i), x <= d) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IntersectSegmentAabb(Vector2D& p0, Vector2D& p1, Vector2D& _min, Vector2D& _max)
|
||||||
|
{
|
||||||
|
float t = 0.0f;
|
||||||
|
float d = FLT_MAX;
|
||||||
|
Vector2D n = p0;
|
||||||
|
Vector2D v = p1 - p0;
|
||||||
|
float z = v.Norm();
|
||||||
|
v = z > (float)1e-5 ? v / z : Vector2D(1, 0);
|
||||||
|
if (std::abs(v.x) < (float)1e-5) {
|
||||||
|
v.x = float(2e-5);
|
||||||
|
}
|
||||||
|
if (std::abs(v.y) < (float)1e-5) {
|
||||||
|
v.y = (float)2e-5;
|
||||||
|
}
|
||||||
|
if (std::abs(v.x) > (float)1e-5) {
|
||||||
|
float u = (_min.x - n.x) / v.x;
|
||||||
|
float i = (_max.x - n.x) / v.x;
|
||||||
|
t = std::max(t, std::min(u, i));
|
||||||
|
d = std::min(d, std::max(u, i));
|
||||||
|
if (t > d) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (std::abs(v.y) > (float)1e-5) {
|
||||||
|
float x = (_min.y - n.y) / v.y;
|
||||||
|
float l = (_max.y - n.y) / v.y;
|
||||||
|
t = std::max(t, std::min(x, l));
|
||||||
|
d = std::min(d, std::max(x, l));
|
||||||
|
if (t > d) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (t > z) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IntersectAabbCircle(Vector2D& a_min, Vector2D& a_max, Vector2D& b_pos, float& b_rad)
|
||||||
|
{
|
||||||
|
if (b_pos.x >= a_min.x && b_pos.x <= a_max.x &&
|
||||||
|
b_pos.y >= a_min.y && b_pos.y <= a_max.y) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Vector2D nearest_point(a8::Clamp(b_pos.x, a_min.x, a_max.y),
|
||||||
|
a8::Clamp(b_pos.y, a_min.y, a_max.y));
|
||||||
|
Vector2D i = b_pos - nearest_point;
|
||||||
|
float n = a8::LengthSqr(i);
|
||||||
|
return n < b_rad*b_rad;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IntersectAabbAabb(Vector2D& a_min, Vector2D& a_max, Vector2D& b_min, Vector2D& b_max)
|
||||||
|
{
|
||||||
|
Vector2D a_v = (a_max - a_min) * 0.5f;
|
||||||
|
Vector2D a_center = a_min + a_v;
|
||||||
|
Vector2D b_v = (b_max - b_min) * 0.5f;
|
||||||
|
Vector2D b_center = b_min + b_v;
|
||||||
|
Vector2D z = b_center - a_center;
|
||||||
|
float u = a_v.x + b_v.x - std::abs(z.x);
|
||||||
|
return u > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IntersectCircleCircle(Vector2D& a_pos, float& a_rad, Vector2D& b_pos, float& b_rad)
|
||||||
|
{
|
||||||
|
float t = a_rad + b_rad;
|
||||||
|
Vector2D d = b_pos - a_pos;
|
||||||
|
float n = a8::LengthSqr(d);
|
||||||
|
return n < t*t;
|
||||||
|
}
|
7
server/gameserver/collision.h
Normal file
7
server/gameserver/collision.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
bool IntersectSegmentCircle(Vector2D& p0, Vector2D& p1, Vector2D& pos, float rad);
|
||||||
|
bool IntersectSegmentAabb(Vector2D& p0, Vector2D& p1, Vector2D& _min, Vector2D& _max);
|
||||||
|
bool IntersectAabbCircle(Vector2D& a_min, Vector2D& a_max, Vector2D& b_pos, float& b_rad);
|
||||||
|
bool IntersectAabbAabb(Vector2D& a_min, Vector2D& a_max, Vector2D& b_min, Vector2D& b_max);
|
||||||
|
bool IntersectCircleCircle(Vector2D& a_pos, float& a_rad, Vector2D& b_pos, float& b_rad);
|
Loading…
x
Reference in New Issue
Block a user