Java 计算三维SAT碰撞法向量时出错
我一直在致力于在我的3d游戏引擎中实现SAT碰撞,使用LWJGL跟踪2d SAT碰撞。Java 计算三维SAT碰撞法向量时出错,java,math,vector,collision-detection,lwjgl,Java,Math,Vector,Collision Detection,Lwjgl,我一直在致力于在我的3d游戏引擎中实现SAT碰撞,使用LWJGL跟踪2d SAT碰撞。 由于本教程是针对2d的,我正在尝试进行3d碰撞,因此我需要稍微更改代码以满足我的需要,但未能成功完成。 这是SAT课程: public class SAT { public static IntersectionData collision(Box box1, Box box2){ float overlap = Float.MAX_VALUE; Vector3f smallest =
由于本教程是针对2d的,我正在尝试进行3d碰撞,因此我需要稍微更改代码以满足我的需要,但未能成功完成。
这是SAT课程:
public class SAT {
public static IntersectionData collision(Box box1, Box box2){
float overlap = Float.MAX_VALUE;
Vector3f smallest = null;
Vector3f[] box1Vertices = box1.getExtents();
Vector3f[] box2Vertices = box2.getExtents();
Vector3f[] box1Axes = getAxes(box1Vertices);
Vector3f[] box2Axes = getAxes(box2Vertices);
for (Vector3f axis:box1Axes){
Projection p1 = Projection.project(box1Vertices, axis);
Projection p2 = Projection.project(box2Vertices, axis);
if (!p1.overlap(p2))
return new IntersectionData(false, p1.getDistance(p2));
else {
float o = p1.getOverlap(p2);
if (o < overlap){
overlap = o;
smallest = axis;
}
}
}
for (Vector3f axis:box2Axes){
Projection p1 = Projection.project(box1Vertices, axis);
Projection p2 = Projection.project(box2Vertices, axis);
if (!p1.overlap(p2))
return new IntersectionData(false, p1.getDistance(p2));
else {
float o = p1.getOverlap(p2);
if (o < overlap){
overlap = o;
smallest = axis;
}
}
}
MTV mtv = new MTV(smallest, overlap);
return new IntersectionData(true, mtv.getOverlap());
}
private static Vector3f[] getAxes(Vector3f[] vertices){ // FIXME
Vector3f[] axes = new Vector3f[vertices.length];
for (int i = 0; i < vertices.length; i++){
Vector3f p1 = vertices[i];
Vector3f p2 = vertices[i + 1 == vertices.length ? 0 : i + 1];
Vector3f p3 = vertices[i + 2 >= vertices.length ? 1 : i + 1];
Vector3f edge1 = Vector3f.sub(p2, p1, null);
Vector3f edge2 = Vector3f.sub(p3, p1, null);
Vector3f normal1 = Vector3f.cross(edge1, edge2, null);
normal1.normalise();
axes[i] = normal1;
}
return axes;
}
}
class Projection {
private float min;
private float max;
private Projection(float min, float max) {
this.min = min;
this.max = max;
}
float getOverlap(Projection projection){
if (overlap(projection))
return Math.min(max, projection.max) - Math.max(min, projection.min);
return 0;
}
float getDistance(Projection projection){
if (overlap(projection))
return getOverlap(projection);
else
return Math.max(min, projection.min) - Math.max(max, projection.max);
}
boolean overlap(Projection projection){
return max > projection.min || projection.max > min;
}
static Projection project(Vector3f[] vertices, Vector3f axis){
float min = Vector3f.dot(axis, vertices[0]);
float max = min;
for (Vector3f vertex:vertices){
float p = Vector3f.dot(axis, vertex);
if (p < min)
min = p;
else if (p > max)
max = p;
}
return new Projection(min, max);
}
}
class MTV {
private Vector3f axis;
private float overlap;
MTV(Vector3f axis, float overlap) {
this.axis = axis;
this.overlap = overlap;
}
public Vector3f getAxis() {
return axis;
}
float getOverlap() {
return overlap;
}
}
注意:类IntersectionData只是一个存储两个对象发生碰撞以及到对象之间的距离的类,它已在引擎的其他部分中使用,并完全发挥作用。
由于某些原因,碰撞无法正确检测,并且对象会直接通过彼此,我怀疑问题的根源在于法向量的计算方式,因为当我运行模拟(引擎)时,我在
normal1.normalise()行上得到了IllegalStateException:Zero length vector
异常代码>
有人能帮我找到问题吗
编辑:解决方案:
问题是,在函数重叠(投影)
中,返回条件是使用|
而不是&
这看起来有点可疑,特别是最后一行中的i+1
:Java Vector3f p1=顶点[i];向量3f p2=顶点[i+1==顶点.length?0:i+1];向量3f p3=顶点[i+2>=顶点。长度?1:i+1]代码>我将其简化并更改为:javavector3fp1=顶点[I];向量3f p2=顶点[(i+1)%vertexts.length];向量3f p3=顶点[(i+2)%vertexts.length]代码>@httpdigest你好!谢谢你的回答!无论如何,这确实解决了异常,并且不再发生。但是碰撞仍然没有被发现。。。你知道为什么吗?再次感谢你。