Java 2个OBB的接触点?
我正在为我的GTA2类游戏学习物理,这样我就可以学习更多关于游戏物理的知识 碰撞检测和分辨率非常有效 我现在只是不确定当我撞到墙上时如何计算接触点 这是我的OBB课程:Java 2个OBB的接触点?,java,math,geometry,Java,Math,Geometry,我正在为我的GTA2类游戏学习物理,这样我就可以学习更多关于游戏物理的知识 碰撞检测和分辨率非常有效 我现在只是不确定当我撞到墙上时如何计算接触点 这是我的OBB课程: public class OBB2D { private Vector2D projVec = new Vector2D(); private static Vector2D projAVec = new Vector2D(); private static Vector2D projBVec = new Ve
public class OBB2D
{
private Vector2D projVec = new Vector2D();
private static Vector2D projAVec = new Vector2D();
private static Vector2D projBVec = new Vector2D();
private static Vector2D tempNormal = new Vector2D();
private Vector2D deltaVec = new Vector2D();
// Corners of the box, where 0 is the lower left.
private Vector2D corner[] = new Vector2D[4];
private Vector2D center = new Vector2D();
private Vector2D extents = new Vector2D();
private RectF boundingRect = new RectF();
private float angle;
//Two edges of the box extended away from corner[0].
private Vector2D axis[] = new Vector2D[2];
private double origin[] = new double[2];
public OBB2D(float centerx, float centery, float w, float h, float angle)
{
for(int i = 0; i < corner.length; ++i)
{
corner[i] = new Vector2D();
}
for(int i = 0; i < axis.length; ++i)
{
axis[i] = new Vector2D();
}
set(centerx,centery,w,h,angle);
}
public OBB2D(float left, float top, float width, float height)
{
for(int i = 0; i < corner.length; ++i)
{
corner[i] = new Vector2D();
}
for(int i = 0; i < axis.length; ++i)
{
axis[i] = new Vector2D();
}
set(left + (width / 2), top + (height / 2),width,height,0.0f);
}
public void set(float centerx,float centery,float w, float h,float angle)
{
float vxx = (float)Math.cos(angle);
float vxy = (float)Math.sin(angle);
float vyx = (float)-Math.sin(angle);
float vyy = (float)Math.cos(angle);
vxx *= w / 2;
vxy *= (w / 2);
vyx *= (h / 2);
vyy *= (h / 2);
corner[0].x = centerx - vxx - vyx;
corner[0].y = centery - vxy - vyy;
corner[1].x = centerx + vxx - vyx;
corner[1].y = centery + vxy - vyy;
corner[2].x = centerx + vxx + vyx;
corner[2].y = centery + vxy + vyy;
corner[3].x = centerx - vxx + vyx;
corner[3].y = centery - vxy + vyy;
this.center.x = centerx;
this.center.y = centery;
this.angle = angle;
computeAxes();
extents.x = w / 2;
extents.y = h / 2;
computeBoundingRect();
}
//Updates the axes after the corners move. Assumes the
//corners actually form a rectangle.
private void computeAxes()
{
axis[0].x = corner[1].x - corner[0].x;
axis[0].y = corner[1].y - corner[0].y;
axis[1].x = corner[3].x - corner[0].x;
axis[1].y = corner[3].y - corner[0].y;
// Make the length of each axis 1/edge length so we know any
// dot product must be less than 1 to fall within the edge.
for (int a = 0; a < axis.length; ++a)
{
float l = axis[a].length();
float ll = l * l;
axis[a].x = axis[a].x / ll;
axis[a].y = axis[a].y / ll;
origin[a] = corner[0].dot(axis[a]);
}
}
public void computeBoundingRect()
{
boundingRect.left = JMath.min(JMath.min(corner[0].x, corner[3].x), JMath.min(corner[1].x, corner[2].x));
boundingRect.top = JMath.min(JMath.min(corner[0].y, corner[1].y),JMath.min(corner[2].y, corner[3].y));
boundingRect.right = JMath.max(JMath.max(corner[1].x, corner[2].x), JMath.max(corner[0].x, corner[3].x));
boundingRect.bottom = JMath.max(JMath.max(corner[2].y, corner[3].y),JMath.max(corner[0].y, corner[1].y));
}
public void set(RectF rect)
{
set(rect.centerX(),rect.centerY(),rect.width(),rect.height(),0.0f);
}
// Returns true if other overlaps one dimension of this.
private boolean overlaps1Way(OBB2D other)
{
for (int a = 0; a < axis.length; ++a) {
double t = other.corner[0].dot(axis[a]);
// Find the extent of box 2 on axis a
double tMin = t;
double tMax = t;
for (int c = 1; c < corner.length; ++c) {
t = other.corner[c].dot(axis[a]);
if (t < tMin) {
tMin = t;
} else if (t > tMax) {
tMax = t;
}
}
// We have to subtract off the origin
// See if [tMin, tMax] intersects [0, 1]
if ((tMin > 1 + origin[a]) || (tMax < origin[a])) {
// There was no intersection along this dimension;
// the boxes cannot possibly overlap.
return false;
}
}
// There was no dimension along which there is no intersection.
// Therefore the boxes overlap.
return true;
}
public void moveTo(float centerx, float centery)
{
float cx,cy;
cx = center.x;
cy = center.y;
deltaVec.x = centerx - cx;
deltaVec.y = centery - cy;
for (int c = 0; c < 4; ++c)
{
corner[c].x += deltaVec.x;
corner[c].y += deltaVec.y;
}
boundingRect.left += deltaVec.x;
boundingRect.top += deltaVec.y;
boundingRect.right += deltaVec.x;
boundingRect.bottom += deltaVec.y;
this.center.x = centerx;
this.center.y = centery;
computeAxes();
}
// Returns true if the intersection of the boxes is non-empty.
public boolean overlaps(OBB2D other)
{
if(right() < other.left())
{
return false;
}
if(bottom() < other.top())
{
return false;
}
if(left() > other.right())
{
return false;
}
if(top() > other.bottom())
{
return false;
}
if(other.getAngle() == 0.0f && getAngle() == 0.0f)
{
return true;
}
return overlaps1Way(other) && other.overlaps1Way(this);
}
public Vector2D getCenter()
{
return center;
}
public float getWidth()
{
return extents.x * 2;
}
public float getHeight()
{
return extents.y * 2;
}
public void setAngle(float angle)
{
set(center.x,center.y,getWidth(),getHeight(),angle);
}
public float getAngle()
{
return angle;
}
public void setSize(float w,float h)
{
set(center.x,center.y,w,h,angle);
}
public float left()
{
return boundingRect.left;
}
public float right()
{
return boundingRect.right;
}
public float bottom()
{
return boundingRect.bottom;
}
public float top()
{
return boundingRect.top;
}
public RectF getBoundingRect()
{
return boundingRect;
}
public boolean overlaps(float left, float top, float right, float bottom)
{
if(right() < left)
{
return false;
}
if(bottom() < top)
{
return false;
}
if(left() > right)
{
return false;
}
if(top() > bottom)
{
return false;
}
return true;
}
public static float distance(float ax, float ay,float bx, float by)
{
if (ax < bx)
return bx - ay;
else
return ax - by;
}
public Vector2D project(float ax, float ay)
{
projVec.x = Float.MAX_VALUE;
projVec.y = Float.MIN_VALUE;
for (int i = 0; i < corner.length; ++i)
{
float dot = Vector2D.dot(corner[i].x,corner[i].y,ax,ay);
projVec.x = JMath.min(dot, projVec.x);
projVec.y = JMath.max(dot, projVec.y);
}
return projVec;
}
public Vector2D getCorner(int c)
{
return corner[c];
}
public int getNumCorners()
{
return corner.length;
}
public static float collisionResponse(OBB2D a, OBB2D b, Vector2D outNormal)
{
float depth = Float.MAX_VALUE;
for (int i = 0; i < a.getNumCorners() + b.getNumCorners(); ++i)
{
Vector2D edgeA;
Vector2D edgeB;
if(i >= a.getNumCorners())
{
edgeA = b.getCorner((i + b.getNumCorners() - 1) % b.getNumCorners());
edgeB = b.getCorner(i % b.getNumCorners());
}
else
{
edgeA = a.getCorner((i + a.getNumCorners() - 1) % a.getNumCorners());
edgeB = a.getCorner(i % a.getNumCorners());
}
tempNormal.x = edgeB.x -edgeA.x;
tempNormal.y = edgeB.y - edgeA.y;
tempNormal.normalize();
projAVec.equals(a.project(tempNormal.x,tempNormal.y));
projBVec.equals(b.project(tempNormal.x,tempNormal.y));
float distance = OBB2D.distance(projAVec.x, projAVec.y,projBVec.x,projBVec.y);
if (distance > 0.0f)
{
return 0.0f;
}
else
{
float d = Math.abs(distance);
if (d < depth)
{
depth = d;
outNormal.equals(tempNormal);
}
}
}
float dx,dy;
dx = b.getCenter().x - a.getCenter().x;
dy = b.getCenter().y - a.getCenter().y;
float dot = Vector2D.dot(dx,dy,outNormal.x,outNormal.y);
if(dot > 0)
{
outNormal.x = -outNormal.x;
outNormal.y = -outNormal.y;
}
return depth;
}
public Vector2D getMoveDeltaVec()
{
return deltaVec;
}
};
公共类OBB2D
{
private Vector2D projVec=new Vector2D();
私有静态向量2d projAVec=新向量2d();
私有静态Vector2D projBVec=new Vector2D();
私有静态向量2D tempNormal=新向量2D();
私有向量2d deltaVec=新向量2d();
//长方体的角,其中0为左下角。
私有向量2D角点[]=新向量2D[4];
私有向量2D中心=新向量2D();
私有Vector2D范围=新Vector2D();
private RectF boundingRect=new RectF();
私人浮动角度;
//长方体的两条边从角[0]向外延伸。
私有向量2D轴[]=新向量2D[2];
私人双起点[]=新双起点[2];
公共OBB2D(浮动中心X、浮动中心Y、浮动w、浮动h、浮动角度)
{
对于(int i=0;itMax){
tMax=t;
}
}
//我们必须减去原点
//查看[tMin,tMax]是否与[0,1]相交
如果((tMin>1+原点[a])| |(tMax<原点[a])){
//在这个维度上没有交叉点;
//这些盒子不可能重叠。
返回false;
}
}
//没有一个维度是没有交叉点的。
//因此,框重叠。
返回true;
}
公共无效移动到(浮动中心X、浮动中心Y)
{
浮动cx,cy;
cx=中心点x;
cy=中心y;
deltaVec.x=centerx-cx;
deltaVec.y=中心y-cy;
对于(int c=0;c<4;++c)
{
角[c].x+=deltaVec.x;
角[c].y+=deltaVec.y;
}
boundingRect.left+=deltaVec.x;
boundingRect.top+=deltaVec.y;
boundingRect.right+=deltaVec.x;
boundingRect.bottom+=deltaVec.y;
this.center.x=centerx;
this.center.y=centery;
计算机();
}
//如果框的交点为非空,则返回true。
公共布尔重叠(OBB2D其他)
{
if(right()other.right())
{
返回false;
}
如果(top()>other.bottom())
//Test if OBB b intersects plane p
int TestOBBPlane(OBB b, Plane p)
{
// Compute the projection interval radius of b onto L(t) = b.c + t * p.n
float r = b.e[0]*Abs(Dot(p.n, b.u[0])) +
b.e[1]*Abs(Dot(p.n, b.u[1])) +
b.e[2]*Abs(Dot(p.n, b.u[2]));
// Compute distance of box center from plane
float s = Dot(p.n, b.c) – p.d;
// Intersection occurs when distance s falls within [-r,+r] interval
return Abs(s) <= r;
}
CASE 1: L = Ax
CASE 2: L = Ay
CASE 3: L = Az
CASE 4: L = Bx
CASE 5: L = By
CASE 6: L = Bz
CASE 7: L = Ax x Bx
CASE 8: L = Ax x By
CASE 9: L = Ax x Bz
CASE 10: L = Ay x Bx
CASE 11: L = Ay x By
CASE 12: L = Ay x Bz
CASE 13: L = Az x Bx
CASE 14: L = Az x By
CASE 15: L = Az x Bz