Three.js 三坐标系中的有向盒交点
我想知道两个方向的边界框是否使用threeJS相交 有一个box3.intersect方法,但它仅适用于无方向的边界框 是否已经有内置的功能,或者我必须自己实现 我想知道下例中的每个蓝色框是否与粉红色框相交。我只是想知道他们是否接触,而不是交叉路口的样子Three.js 三坐标系中的有向盒交点,three.js,intersection,bounding-box,Three.js,Intersection,Bounding Box,我想知道两个方向的边界框是否使用threeJS相交 有一个box3.intersect方法,但它仅适用于无方向的边界框 是否已经有内置的功能,或者我必须自己实现 我想知道下例中的每个蓝色框是否与粉红色框相交。我只是想知道他们是否接触,而不是交叉路口的样子 谢谢如果你想自己动手,我推荐约翰尼·休恩的作品 下面是一个碰撞检测方法,给出了我为一个游戏制作的两个定向边界框。它不是3JS格式,但转换过来应该相当直接 注:用于矩阵数学。 重要提示:我认为分辨率向量中有一个缺陷,我还没有找到。不过,交叉口检
谢谢如果你想自己动手,我推荐约翰尼·休恩的作品 下面是一个碰撞检测方法,给出了我为一个游戏制作的两个定向边界框。它不是3JS格式,但转换过来应该相当直接 注:用于矩阵数学。 重要提示:我认为分辨率向量中有一个缺陷,我还没有找到。不过,交叉口检测似乎很准确
/**
* Checks if two given bounding boxes intersect with one another.
*
* Results an object with the following keys:
* @property {boolean} intersects - True if the bounding boxes intersect
* @property {vec3} resolution - A vector specifying the shortest distance
* and magnitude to move the boxes such that they are no longer intersecting
*
* Uses the Separating Axis Theorem
* See http://en.wikipedia.org/wiki/Hyperplane_separation_theorem)
* Looks for separating planes between the bounding boxes.
*
* @param {PhysJS.util.math.BoundingBox} box1 The first bounding box
* @param {PhysJS.util.math.BoundingBox} box2 The second bounding box
* @returns {Object} Containers two properties, 'intersects' and 'resolution'
*/
intersects: function (box1, box2) {
// assumes the position of each box to be an orthonormal basis
var pos1 = box1.getPosition(); // mat44
var pos2 = box2.getPosition(); // mat44
var center1 = vec4.transformMat4(vec4.create(), box1.getCenter(), pos1);
var center2 = vec4.transformMat4(vec4.create(), box2.getCenter(), pos2);
var centerDifference = vec4.subtract(vec4.create(), center2, center1);
var results = {
intersects: true,
resolution: null
};
// broad phase
var maxDiameter1 = vec4.length(vec4.subtract(vec4.create(), box1.getMax(), box1.getMin()));
var maxDiameter2 = vec4.length(vec4.subtract(vec4.create(), box2.getMax(), box2.getMin()));
if (vec4.length(centerDifference) > maxDiameter1 + maxDiameter2) {
results.intersects = false;
return results;
}
// narrow phase
// get the axis vectors of the first box
var ax1 = mat4.col(pos1, 0);
var ay1 = mat4.col(pos1, 1);
var az1 = mat4.col(pos1, 2);
// get the axis vectors of the second box
var ax2 = mat4.col(pos2, 0);
var ay2 = mat4.col(pos2, 1);
var az2 = mat4.col(pos2, 2);
// keep them in a list
var axes = [ax1, ay1, az1, ax2, ay2, az2];
// get the orientated radii vectors of the first box
var radii1 = box1.getRadii();
var radX1 = vec4.scale(vec4.create(), ax1, radii1[0]);
var radY1 = vec4.scale(vec4.create(), ay1, radii1[1]);
var radZ1 = vec4.scale(vec4.create(), az1, radii1[2]);
// get the orientated radii vectors of the second box
var radii2 = box2.getRadii();
var radX2 = vec4.scale(vec4.create(), ax2, radii2[0]);
var radY2 = vec4.scale(vec4.create(), ay2, radii2[1]);
var radZ2 = vec4.scale(vec4.create(), az2, radii2[2]);
var smallestDifference = Infinity;
// there are 15 axes to check, so loop through all of them until a separation plane is found
var zeros = vec4.create();
for (var i = 0; i < 15; i++) {
var axis;
// the first 6 axes are just the axes of each bounding box
if (i < 6) {
axis = axes[i];
}
// the last 9 axes are the cross product of all combinations of the first 6 axes
else {
var offset = i - 6;
var j = Math.floor(offset / 3);
var k = offset % 3;
axis = vec4.cross(vec4.create(), axes[j], axes[k + 3]);
if (vec4.close(axis, zeros)) {
// axes must be collinear, ignore
continue;
}
}
// get the projections of the first half box onto the axis
var projAx1 = Math.abs(vec4.dot(radX1, axis));
var projAy1 = Math.abs(vec4.dot(radY1, axis));
var projAz1 = Math.abs(vec4.dot(radZ1, axis));
// get the projections of the second half box onto the axis
var projAx2 = Math.abs(vec4.dot(radX2, axis));
var projAy2 = Math.abs(vec4.dot(radY2, axis));
var projAz2 = Math.abs(vec4.dot(radZ2, axis));
// sum the projections
var projectionBoxesSum = projAx1 + projAy1 + projAz1 + projAx2 + projAy2 + projAz2;
// get the projection of the center difference onto the axis
var projectionDifference = Math.abs(vec4.dot(centerDifference, axis));
if (projectionDifference >= projectionBoxesSum) {
// If the projection of the center difference onto the axis is greater
// than the sum of the box projections, then we found a separating plane!
// The bounding boxes therefore must not intersect
results.intersects = false;
break;
}
else {
// keep track of the difference, the smallest gives the minimum distance
// and direction to move the boxes such that they no longer intersect
var difference = projectionBoxesSum - projectionDifference;
if (difference < smallestDifference) {
results.resolution = vec4.scale(vec4.create(), axis, difference);
smallestDifference = difference;
}
}
}
if (results.intersects) {
// make sure the resolution vector is in the correct direction
var dot = vec4.dot(results.resolution, centerDifference);
var sign = dot ? dot < 0 ? -1 : 1 : 0;
vec4.scale(results.resolution, results.resolution, -sign);
}
return results;
}
/**
*检查两个给定的边界框是否相互相交。
*
*结果显示具有以下键的对象:
*@property{boolean}相交-如果边界框相交,则为True
*@property{vec3}分辨率-指定最短距离的向量
*和大小来移动长方体,使它们不再相交
*
*使用分离轴定理
*看http://en.wikipedia.org/wiki/Hyperplane_separation_theorem)
*查找边界框之间的分隔平面。
*
*@param{PhysJS.util.math.BoundingBox}box1第一个边界框
*@param{PhysJS.util.math.BoundingBox}box2第二个边界框
*@returns{Object}包含两个属性,“intersects”和“resolution”
*/
相交:函数(框1、框2){
//假定每个长方体的位置为正交基
var pos1=box1.getPosition();//mat44
var pos2=box2.getPosition();//mat44
var center1=vec4.transformat4(vec4.create(),box1.getCenter(),pos1);
var center2=vec4.transformat4(vec4.create(),box2.getCenter(),pos2);
var centerDifference=vec4.subtract(vec4.create(),center2,center1);
风险值结果={
交叉点:对,
分辨率:空
};
//宽相位
var maxDiameter1=vec4.length(vec4.subtract(vec4.create(),box1.getMax(),box1.getMin());
var maxDiameter2=vec4.length(vec4.subtract(vec4.create(),box2.getMax(),box2.getMin());
如果(矢量4.长度(中心差)>最大直径1+最大直径2){
结果:相交=假;
返回结果;
}
//窄相
//获取第一个框的轴向量
var ax1=mat4.col(位置1,0);
var ay1=mat4.col(位置1,1);
var az1=mat4.col(位置1,2);
//获取第二个框的轴向量
var ax2=mat4.col(pos2,0);
var ay2=mat4.col(位置2,1);
var-az2=mat4.col(pos2,2);
//把它们列在一个清单里
变量轴=[ax1,ay1,az1,ax2,ay2,az2];
//获取第一个长方体的定向半径向量
var radi1=box1.getRadii();
var radX1=vec4.scale(vec4.create(),ax1,radi1[0]);
var radY1=vec4.scale(vec4.create(),ay1,radi1[1]);
var radZ1=vec4.scale(vec4.create(),az1,radi1[2]);
//获取第二个长方体的定向半径向量
var radii=box2.getRadii();
var radX2=vec4.scale(vec4.create(),ax2,radi2[0]);
var radY2=vec4.scale(vec4.create(),ay2,radi2[1]);
var radZ2=vec4.scale(vec4.create(),az2,radi2[2]);
var最小差=无穷大;
//有15个轴需要检查,因此循环检查所有轴,直到找到分离面
var zeros=vec4.create();
对于(变量i=0;i<15;i++){
var轴;
//前6个轴只是每个边界框的轴
如果(i<6){
轴=轴[i];
}
//最后9个轴是前6个轴的所有组合的叉积
否则{
var偏移量=i-6;
var j=数学楼层(偏移量/3);
var k=偏移量%3;
axis=vec4.cross(vec4.create(),轴[j],轴[k+3]);
if(矢量4.闭合(轴,零)){
//轴必须共线,忽略
继续;
}
}
//将前半个长方体投影到轴上
var projAx1=Math.abs(vec4.dot(radX1,axis));
var projAy1=数学绝对值(向量点(radY1,轴));
var projAz1=数学abs(向量4.点(radZ1,轴));
//将后半个长方体的投影到轴上
var projAx2=Math.abs(vec4.dot(radX2,axis));
var projAy2=数学abs(向量4.点(radY2,轴));
var projAz2=数学abs(向量4点(radZ2,轴));
//将预测相加
var projectionBoxesSum=projAx1+projAy1+projAz1+projAx2+projAy2+projAz2;
//获取中心差在轴上的投影
var projectionDifference=Math.abs(vec4.dot(中心差,轴));
if(projectionDifference>=projectionBoxesSum){
//如果中心差在轴上的投影更大
//然后我们找到了一个分离平面!
//因此,边界框不得相交
结果:相交=假;
打破
}
否则{
//跟踪差异,最小值表示最小距离
//以及移动长方体的方向,以使它们不再相交
var差=projectionBoxesSum-projectionDifference;
if(差值<最小差值){
results.resolution=vec4.scale(vec4.create(),axis,difference);
最小差异=差异;
}
}
}
if(结果相交){
//确保分辨率向量的方向正确
var点=vec4.dot(结果.分辨率,中心差);
变量符号=点?点<0?-1