现在,我正在尝试使用分离轴定理在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类中。因此,“this”指的是OBB,“obb”指的是另一个OBB。
collisionPacket.getVelocity()返回在没有碰撞的情况下将在单个帧中发生的总位移。
“数学”是我自己的静态课程。假设它正常工作。在我做完之前,我没有意识到Vector3f拥有所有这些有用的功能。
This是我正在使用的PDF。我陷入了第9页,即2.3.1。
答案 0 :(得分:0)
几周后,我想出了如何做我想做的事情。几个星期前我实际想出了这个,但我现在想要发布我的解决方案。
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;
}
感谢StackOverflow为这个问题提供了Tumbleweed徽章。如果有人提出更好或更优化的方法,请告诉我。谢谢! :d