我实现了
使用定向边界框进行动态碰撞检测中描述的算法,仅适用于非共面三角形,并基于分离轴定理。
这是我的GitHub存储库,其中包含代码(在文件
collision-tests.js
中)和演示/测试页面:
该代码故意编写以匹配“动态碰撞”文档的相关部分。下面是交点测试函数(以及整个
collision-tests.js
文件的全部内容)。请注意,three.js三角形对象具有三个顶点的
a
、
b
和
c
属性。
function doTrianglesIntersect(t1, t2) {
var A0 = t1.a;
var A1 = t1.b;
var A2 = t1.c;
var E0 = A1.clone().sub(A0);
var E1 = A2.clone().sub(A0);
var E2 = E1.clone().sub(E0);
var N = E0.clone().cross(E1);
var B0 = t2.a;
var B1 = t2.b;
var B2 = t2.c;
var F0 = B1.clone().sub(B0);
var F1 = B2.clone().sub(B0);
var F2 = F1.clone().sub(F0);
var M = F0.clone().cross(F1);
var D = B0.clone().sub(A0);
function areProjectionsSeparated(p0, p1, p2, q0, q1, q2) {
var min_p = Math.min(p0, p1, p2),
max_p = Math.max(p0, p1, p2),
min_q = Math.min(q0, q1, q2),
max_q = Math.max(q0, q1, q2);
return ((min_p > max_q) || (max_p < min_q));
}
{
var p0 = 0,
p1 = 0,
p2 = 0,
q0 = N.dot(D),
q1 = q0 + N.dot(F0),
q2 = q0 + N.dot(F1);
if (areProjectionsSeparated(p0, p1, p2, q0, q1, q2))
return false;
}
{
var p0 = 0,
p1 = M.dot(E0),
p2 = M.dot(E1),
q0 = M.dot(D),
q1 = q0,
q2 = q0;
if (areProjectionsSeparated(p0, p1, p2, q0, q1, q2))
return false;
}
{
var p0 = 0,
p1 = 0,
p2 = -(N.dot(F0)),
q0 = E0.clone().cross(F0).dot(D),
q1 = q0,
q2 = q0 + M.dot(E0);
if (areProjectionsSeparated(p0, p1, p2, q0, q1, q2))
return false;
}
{
var p0 = 0,
p1 = 0,
p2 = -(N.dot(F1)),
q0 = E0.clone().cross(F1).dot(D),
q1 = q0 - M.dot(E0),
q2 = q0;
if (areProjectionsSeparated(p0, p1, p2, q0, q1, q2))
return false;
}
{
var p0 = 0,
p1 = 0,
p2 = -(N.dot(F2)),
q0 = E0.clone().cross(F2).dot(D),
q1 = q0 - M.dot(E0),
q2 = q1;
if (areProjectionsSeparated(p0, p1, p2, q0, q1, q2))
return false;
}
{
var p0 = 0,
p1 = N.dot(F0),
p2 = 0,
q0 = E1.clone().cross(F0).dot(D),
q1 = q0,
q2 = q0 + M.dot(E1);
if (areProjectionsSeparated(p0, p1, p2, q0, q1, q2))
return false;
}
{
var p0 = 0,
p1 = N.dot(F1),
p2 = 0,
q0 = E1.clone().cross(F1).dot(D),
q1 = q0 - M.dot(E1),
q2 = q0;
if (areProjectionsSeparated(p0, p1, p2, q0, q1, q2))
return false;
}
{
var p0 = 0,
p1 = N.dot(F2),
p2 = 0,
q0 = E1.clone().cross(F2).dot(D),
q1 = q0 - M.dot(E1),
q2 = q1;
if (areProjectionsSeparated(p0, p1, p2, q0, q1, q2))
return false;
}
{
var p0 = 0,
p1 = N.dot(F0),
p2 = p1,
q0 = E2.clone().cross(F0).dot(D),
q1 = q0,
q2 = q0 + M.dot(E2);
if (areProjectionsSeparated(p0, p1, p2, q0, q1, q2))
return false;
}
{
var p0 = 0,
p1 = N.dot(F1),
p2 = p1,
q0 = E2.clone().cross(F1).dot(D),
q1 = q0 - M.dot(E2),
q2 = q0;
if (areProjectionsSeparated(p0, p1, p2, q0, q1, q2))
return false;
}
{
var p0 = 0,
p1 = N.dot(F2),
p2 = p1,
q0 = E2.clone().cross(F2).dot(D),
q1 = q0 - M.dot(E2),
q2 = q1;
if (areProjectionsSeparated(p0, p1, p2, q0, q1, q2))
return false;
}
return true;
}