Three.js: "select tool" How to determine the intersection of 2D-square and three-dimensional objects

Basically what I want to create:

I have a 3D map with objects, I want to select all the objects that are in the x1, y1-x2, y2 2D window on my screen.

Any ideas how this should be done, because I do not know how to start.

Thanks in advance!

prevXand prevY- mouse coordinate down:

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;
    }
  }
}
+4
source share
3 answers

The intersection of a box in the screen space is equivalent to the intersection of a pyramid (perspective) or a cube (orthogonal view) of three-dimensional space. I think you should determine THREE.Frustumbased on your 2D window.

:

  • 3D- ( )

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

  1. 4 ( ). - .

topPlane.setFromCoplanarPoints( .position, topLeftCorner3D, topRightCorner3D) Plane.setFromCoplanarPoints( .position, RightCorner3D, RightCorner3D) Plane.setFromCoplanarPoints( .position, RightCorner3D, LeftCorner3D) Plane.setFromCoplanarPoints( .position, LeftCorner3D, topLeftCorner3D)

  1. Frustum, , .

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

frustum.intersectsBox(object.geometry.boundingBox)

frustum.intersectsSphere(object.geometry.boundingSphere)

Frustum: , , , 4- . Frustum.intersectSphere() 4 :

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;  
}
+3

. THREE.Geometry boundingBox. null, , computeBoundingBox().

scene.traverse( function ( node ) {
    if ( node.geometry )
         node.geometry.computeBoundingBox();
} );

, 2D- ( "y" - UP):

mesh.geometry.boundingBox.min.x
mesh.geometry.boundingBox.min.z
mesh.geometry.boundingBox.max.x
mesh.geometry.boundingBox.max.z

. http://threejs.org/docs/#Reference/Core/Geometry

(, , , )

+1

, , . js. , 8 , . . ( ClojureScript), 3D , . . , readpixels ( , , readpixels , , ).

I made a working example of subfrust selection at http://jsbin.com/tamoce/3/ , but it is too inaccurate. An important part:

          var rx1 = ( x1 / window.innerWidth ) * 2 - 1;
          var rx2 = ( x2 / window.innerWidth ) * 2 - 1;
          var ry1 = -( y1 / window.innerHeight ) * 2 + 1;
          var ry2 = -( y2 / window.innerHeight ) * 2 + 1;

          var projectionMatrix = new THREE.Matrix4();
          projectionMatrix.makeFrustum( rx1, rx2, ry1, ry2, camera.near, camera.far );

          camera.updateMatrixWorld();
          camera.matrixWorldInverse.getInverse( camera.matrixWorld );

          var viewProjectionMatrix = new THREE.Matrix4();
          viewProjectionMatrix.multiplyMatrices( projectionMatrix, camera.matrixWorldInverse );

          var frustum = new THREE.Frustum();
          frustum.setFromMatrix( viewProjectionMatrix );
0
source

All Articles