Java 动态OBB碰撞检测(分离轴定理):找到碰撞发生的时间?

Java 动态OBB碰撞检测(分离轴定理):找到碰撞发生的时间?,java,collision-detection,Java,Collision Detection,现在,我正尝试使用分离轴定理在Java中实现一个动态的3-D OBB碰撞测试。我试图找到每个分离轴的实体的相交时间从0到1,0是帧的开始,1是帧的结束 这是我的密码: private float calculateITime(OBB obb, Vector3f axis /*the separating axis we are testing*/, Vector3f d /*Current OBB's origin minus other OBB's origin*/, float ra /

现在,我正尝试使用分离轴定理在Java中实现一个动态的3-D OBB碰撞测试。我试图找到每个分离轴的实体的相交时间从0到1,0是帧的开始,1是帧的结束

这是我的密码:

private float calculateITime(OBB obb, 
Vector3f axis /*the separating axis we are testing*/,
Vector3f d /*Current OBB's origin minus other OBB's origin*/, 
float ra /*the first obb's projection*/,
float rb /*the second obb's projection*/,
float r /*what I understand to be the total length of the combined projections*/) {
    //Find the time, from 0 (the beginning of the frame) to 1 (the end of the frame), that the obb's first intersected.
    float intersectionLength = r - Math.abs(ra) - Math.abs(rb); //The measure of how much the two projections overlap

    Vector3f aVelocity = this.getCollisionPacket().getVelocity();
    Vector3f bVelocity = obb.getCollisionPacket().getVelocity();

    double aMagnitude = Mathematics.dotProduct(axis, Mathematics.crossProduct(aVelocity, d));
    double bMagnitude = Mathematics.dotProduct(axis, Mathematics.crossProduct(bVelocity, d));

    double totalDistanceCovered = 0;

    if(aMagnitude <= 0 && bMagnitude <= 0) {
        totalDistanceCovered = Math.abs(aMagnitude - bMagnitude);
    } else if((aMagnitude >= 0 && bMagnitude <= 0) || (aMagnitude <= 0 && bMagnitude >= 0)) {
        totalDistanceCovered = Math.abs(aMagnitude + bMagnitude);
    } else if(aMagnitude >= 0 && bMagnitude >= 0) {
        totalDistanceCovered = Math.abs(aMagnitude - bMagnitude);
    }

    System.out.println("PotentialITime: " + Math.abs(intersectionLength / totalDistanceCovered));
    return (float) Math.abs(intersectionLength / totalDistanceCovered);
}
专用浮点计算时间(OBB OBB,
向量3f轴/*我们正在测试的分离轴*/,
矢量3f d/*当前OBB原点减去其他OBB原点*/,
浮动ra/*第一个obb的投影*/,
浮动rb/*第二个obb的投影*/,
浮点数r/*我理解为组合投影的总长度*/){
//查找obb第一次相交的时间,从0(帧的开始)到1(帧的结束)。
float intersectionLength=r-Math.abs(ra)-Math.abs(rb);//两个投影重叠程度的度量
Vector3f aVelocity=this.getCollisionPackage().getVelocity();
Vector3f bVelocity=obb.getCollisionPacket().getVelocity();
double aMagnitude=Mathematics.dotProduct(axis,Mathematics.crossProduct(aVelocity,d));
double bMagnitude=数学.dotProduct(轴,数学.crossProduct(bVelocity,d));
双总距离覆盖=0;
如果(振幅=0){
totalDistanceCovered=Math.abs(A幅度-B幅度);
}
System.out.println(“潜在时间:+Math.abs(相交长度/总距离));
返回(浮点)数学绝对值(相交长度/总距离);
}
然而,我得到的价值远远高于一。假设我已经正确地理解了如何正确地实现分离轴定理,那么我错在哪里呢

如果你认为你有答案,但如果我把剩下的内容贴出来(虽然很长),那会很有帮助,让我知道,我会帮你做的。谢谢

最后说明:

此函数位于OBB类中。因此,“本”是指OBB,“OBB”是指其他OBB

getVelocity()返回在没有碰撞的情况下在单个帧中发生的总位移

“数学”是我自己的静态课程。假设它工作正常。直到我做了Vector3f之后,我才意识到它有所有这些有用的功能


是我正在使用的PDF文件。我被困在第9页的2.3.1中。

几周后,我想出了如何做我想做的事情。事实上,我在几周前就提出了这个问题,但我刚刚想发布我的解决方案

private boolean determineCollision(OBB obb, Vector3f separatingAxis, double velocityMagnitude, float ra, float rb, float r) {
    //Find the time, from 0 (the beginning of the frame) to 1 (the end of the frame), that the obb's first intersected.

    //If r is negative, the first OBB is to the "right." Otherwise, it is to the "left."
    collisionRightSide.add(r < 0);
    boolean currColRightSide = collisionRightSide.get(collisionRightSide.size() - 1);

    double timeRange[] = new double[2]; //From 0 (beginning of frame) to 1 (end of frame)

    //Perform a regular static test if there is no movement for optimization's sake
    boolean noStaticOverlap = Math.abs(r) > (ra + rb);
    if(velocityMagnitude == 0) {
        timeRange[0] = 0; timeRange[1] = 1;
        axisTimes.add(timeRange);
        return !noStaticOverlap;
    }

    double spaceBetweenProjections = Math.abs(r) - Math.abs(ra) - Math.abs(rb);

    //Note that if velocity magnitude is negative, the first OBB is moving "right," and the other way for positive.
    if(currColRightSide) {
        if(velocityMagnitude < 0) {
            if(noStaticOverlap) {
//                  System.out.println("(Right side) OBBs are moving away");
                return false;
            } else {
                timeRange[0] = 0;
                timeRange[1] = Math.abs(spaceBetweenProjections / velocityMagnitude);
            }
        } else if(velocityMagnitude > 0) {
            if(noStaticOverlap) {
                timeRange[0] = Math.abs(spaceBetweenProjections / velocityMagnitude);;
                timeRange[1] = Math.abs((spaceBetweenProjections + 2 * rb) / velocityMagnitude);
            } else {
                timeRange[0] = 0;
                timeRange[1] = Math.abs((spaceBetweenProjections + 2 * rb) / velocityMagnitude);
            }
        }
    } else {
        if(velocityMagnitude > 0) {
            if(noStaticOverlap) {
//                  System.out.println("(Left side) OBBs are moving away");
                return false;
            } else {
                timeRange[0] = 0;
                timeRange[1] = Math.abs(spaceBetweenProjections / velocityMagnitude);
            }
        } else if(velocityMagnitude < 0) {
            if(noStaticOverlap) {
                timeRange[0] = Math.abs(spaceBetweenProjections / velocityMagnitude);
                timeRange[1] = Math.abs((spaceBetweenProjections + 2 * rb) / velocityMagnitude);
            } else {
                timeRange[0] = 0;
                timeRange[1] = Math.abs((spaceBetweenProjections + 2 * rb) / velocityMagnitude);
            }
        }
    }       

    //Clamp values
    if(timeRange[0] < 0) timeRange[0] = 0;
    if(timeRange[1] > 1) timeRange[1] = 1;

    //Switch so that the greater value comes last
    if(timeRange[0] > timeRange[1]) {
        double temp = timeRange[0];
        timeRange[0] = timeRange[1];
        timeRange[1] = temp;
    }

    if(timeRange[0] > 1 && timeRange[1] < 0) return false;

    axisTimes.add(timeRange);

    return true;
}
private boolean determinationcollision(OBB OBB,向量3F分隔轴,双速度幅度,浮点ra,浮点rb,浮点r){
//查找obb第一次相交的时间,从0(帧的开始)到1(帧的结束)。
//如果r为负值,则第一个OBB位于“右侧”。否则,它位于“左侧”
碰撞右侧。相加(r<0);
布尔值currColRightSide=collisionRightSide.get(collisionRightSide.size()-1);
双精度时间范围[]=新双精度[2];//从0(帧开始)到1(帧结束)
//如果为了优化而没有移动,则执行定期静态测试
布尔值=Math.abs(r)>(ra+rb);
如果(速度幅度==0){
时间范围[0]=0;时间范围[1]=1;
添加(时间范围);
返回!诺斯提克重叠;
}
项目之间的双空格=Math.abs(r)-Math.abs(ra)-Math.abs(rb);
//请注意,如果“速度幅值”为负值,则第一个OBB将“向右”移动,反之为正。
如果(右侧){
if(速度幅度<0){
如果(重叠){
//System.out.println(“(右侧)OBB正在移动”);
返回false;
}否则{
时间范围[0]=0;
时间范围[1]=Math.abs(项目之间的空间/速度幅度);
}
}否则如果(速度幅值>0){
如果(重叠){
时间范围[0]=Math.abs(项目之间的空间/速度幅度);;
时间范围[1]=Math.abs((项目之间的空间+2*rb)/速度幅度);
}否则{
时间范围[0]=0;
时间范围[1]=Math.abs((项目之间的空间+2*rb)/速度幅度);
}
}
}否则{
如果(速度幅值>0){
如果(重叠){
//System.out.println(“(左侧)OBB正在移动”);
返回false;
}否则{
时间范围[0]=0;
时间范围[1]=Math.abs(项目之间的空间/速度幅度);
}
}else if(速度幅值<0){
如果(重叠){
时间范围[0]=Math.abs(项目之间的空间/速度幅度);
时间范围[1]=Math.abs((项目之间的空间+2*rb)/速度幅度);
}否则{
时间范围[0]=0;
时间范围[1]=Math.abs((项目之间的空间+2*rb)/速度幅度);
}
}
}       
//钳位值
如果(时间范围[0]<0)时间范围[0]=0;
如果(时间范围[1]>1)时间范围[1]=1;
//切换以使较大的值最后出现
if(时间范围[0]>时间范围[1]){
双温=时间范围[0];
时间范围[0]=时间范围[1];
时间范围[1]=温度;
}
if(timeRange[0]>1&&timeRange[1]<0)返回false;
添加(时间范围);
返回true;
}
谢谢StackOverflow给我这个问题的风滚草徽章。如果有人提出了更好或更优化的方法,请让我知道。谢谢D