gpt4 book ai didi

javascript - Three.js: "select tool"如何检测2D正方形与3D物体的交集

转载 作者:搜寻专家 更新时间:2023-11-01 04:08:39 26 4
gpt4 key购买 nike

基本上我想创建的是:

我有一个包含对象的 3D map ,我想选择屏幕上 2D 框 x1,y1 到 x2,y2 中的所有对象。

关于如何完成的任何想法,因为我对如何开始一无所知。

提前致谢!

prevXprevY 是鼠标按下的坐标:

function onDocumentMouseUp(event) {
event.preventDefault();

var x = (event.clientX / window.innerWidth) * 2 - 1;
var y = -(event.clientY / window.innerHeight) * 2 + 1;

var width = (x - prevX); //* window.innerWidth;
var height = (y - prevY); //* window.innerHeight;
var dx = prevX; //* window.innerWidth;
var dy = prevY; //* window.innerHeight;

console.log(
dx + ',' +
dy + "," +
(dx + width) + "," +
(dy + height) +
", width=" + width +
", height=" + height
);
var topLeftCorner3D = new THREE.Vector3(dx, dy, 1).unproject(
camera);
var topRightCorner3D = new THREE.Vector3(dx + width, dy, 1)
.unproject(camera);
var bottomLeftCorner3D = new THREE.Vector3(dx, dy + height,
1).unproject(camera);
var bottomRightCorner3D = new THREE.Vector3(dx + width, dy +
height, 1).unproject(camera);

var topPlane = new THREE.Plane();
var rightPlane = new THREE.Plane();
var bottomPlane = new THREE.Plane();
var leftPlane = new THREE.Plane();

topPlane.setFromCoplanarPoints(camera.position,
topLeftCorner3D, topRightCorner3D);
rightPlane.setFromCoplanarPoints(camera.position,
topRightCorner3D, bottomRightCorner3D);
bottomPlane.setFromCoplanarPoints(camera.position,
bottomRightCorner3D, bottomLeftCorner3D);
leftPlane.setFromCoplanarPoints(camera.position,
bottomLeftCorner3D, topLeftCorner3D);

//var frustum = new THREE.Frustum( topPlane, bottomPlane, leftPlane, rightPlane, nearPlane, farPlane);

function isObjectInFrustum(object3D) {
var sphere = object3D.geometry.boundingSphere;
var center = sphere.center;
var negRadius = -sphere.radius;

if (topPlane.distanceToPoint(center) < negRadius) { return false; }
if (bottomPlane.distanceToPoint(center) < negRadius) { return false; }
if (rightPlane.distanceToPoint(center) < negRadius) { return false; }
if (leftPlane.distanceToPoint(center) < negRadius) { return false; }

return true;
}
var matches = [];
for (var i = 0; i < window.objects.length; i++) {

if (isObjectInFrustum(window.objects[i])) {
window.objects[i].material = window.selectedMaterial;
}
}
}

最佳答案

在屏幕空间中相交一个盒子相当于在 3D 空间中相交一个金字塔(透视图)或一个立方体(正交 View )。我认为您应该根据您的 2D 框定义一个 THREE.Frustum

对于透视相机:

  1. 将屏幕空间框 Angular 坐标转换为 3D 向量(从相机位置到给定点的向量)

var topLeftCorner3D = new THREE.Vector3( topLeftCorner2D.x, topLeftCorner2D.y, 1 ).unproject( camera );

  1. 根据这些点构建 4 个平面(一个平面代表盒子的一侧)。平面的第三个点是相机位置。

topPlane.setFromCoplanarPoints (camera.position, topLeftCorner3D , topRightCorner3D ) rightPlane.setFromCoplanarPoints (camera.position, topRightCorner3D , bottomRightCorner3D ) bottomPlane.setFromCoplanarPoints (camera.position,bottomRightCorner3D , bottomLeftCorner3D ) leftPlane.setFromCoplanarPoints (camera.position, bottomLeftCorner3D , topLeftCorner3D )

  1. 基于这些平面构造一个视锥体,将相机近平面和远平面添加到它们。

var frustum = new THREE.Frustum( topPlane, bottomPlane, leftPlane, rightPlane, nearPlane, farPlane);

  1. 将平截头体与对象相交

frustum.intersectsBox(object.geometry.boundingBox)

frustum.intersectsSphere(object.geometry.boundingSphere)

使用 Frustum 对象本身的替代方法:您可以跳过近平面和远平面,您只需检查该对象是否在与您的 4 个平面相邻的空间中。您可以编写一个函数,例如只有 4 个平面的 Frustum.intersectSphere() 方法:

function isObjectInFrustum(object3D) {
var sphere = object3D.geometry.boundingSphere;
var center = sphere.center;
var negRadius = - sphere.radius;

if ( topPlane.distanceToPoint( center )< negRadius ) return false;
if ( bottomPlane.distanceToPoint( center )< negRadius ) return false;
if ( rightPlane.distanceToPoint( center )< negRadius ) return false;
if ( leftPlane.distanceToPoint( center )< negRadius ) return false;

return true;
}

关于javascript - Three.js: "select tool"如何检测2D正方形与3D物体的交集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27295415/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com