采摘球
在拾取球体或分离的对象(不是一个内另一个)时,您可以使用与光线的简单距离来非常快速地获得最近的对象。
示例
该函数返回一个执行计算的函数。因为它只是您感兴趣的最接近的距离,所以距离可以保持为正方形。与相机的距离被保持为沿射线的单位距离。
function distanceFromRay() {
var dSqr, ox, oy, oz, vx, vy, vz;
function distanceSqr(px, py, pz) {
const ax = px - ox, ay = py - oy, az = pz - oz;
const u = (ax * vx + ay * vy + az * vz) / dSqr;
distanceSqr.unit = u;
if (u > 0) { // is past origin
const bx = ox + vx * u - px, by = oy + vy * u - py, bz = oz + vz * u - pz;
return bx * bx + by * by + bz * bz; // dist sqr to closest point on ray
}
return Infinity;
}
distanceSqr.unit = 0;
distanceSqr.setRay(x, y, z, xx, yy, zz) { // ray from origin x, y,z,
// infinite length along xx,yy,zz
(ox = x, oy = y, oz = z);
(vx = xx, vy = yy, vz = zz);
dSqr = vx * vx + vy * vy + vz * vz;
}
return distanceSqr;
}
用法
有一个一次性设置调用;
// setup
const distToRay = distanceFromRay();
在需要拾取的帧开始时,计算拾取射线并设置它。还要设置与光线和眼睛的最小距离。
// at start of frame set pick ray
distToRay.setRay(eye.x, eye.y, eye.z, pointer.ray.x, pointer.ray.y, pointer.ray.y);
var minDist = maxObjRadius * maxObjRadius;
var nearestObj = undefined;
var eyeDist = Infinity;
然后对于每个可拾取的对象,通过传递对象中心并将其与任何先前(在帧中)找到的距离、对象半径和距眼睛的距离进行比较来获取距离。
// per object
const dis = distToRay(obj.pos.x, obj.pos.y, obj.pos.z);
if (dis < obj.radius && dis < minDist && distToRay.unit > 0 && distToRay.unit < eyeDist ) {
minDist = dis;
eyeDist = distToRay.unit;
nearestObj = obj;
}
如果nearestObj 不是undefined 在帧的末尾,它将持有对拾取对象的引用。
// end of frame
if (nearestObj) {
// you have the closest object
}