three.js PlaneGeometry和intersectObjects

时间:2015-10-21 10:32:05

标签: three.js

three.js中,我创建了一个平面:

var planGeom = new THREE.PlaneGeometry( 5,5,1,1 );
var planMat = new THREE.MeshBasicMaterial( {color: 0xffff00, side: THREE.DoubleSide} );
var plan = new THREE.Mesh( planGeom, planMat );

然后我设置顶点坐标:

for(var i=0;i<4;i++){
    planGeom .vertices[i].x =  myCoordsTab[i].x;   
    planGeom .vertices[i].y =  myCoordsTab[i].y;
    planGeom .vertices[i].z =  myCoordsTab[i].z;
}

最后:

scene.add( plan );

平面出现在3D场景中的好位置,但是当我输出其位置时:

console.log(plan.position.x+' '+plan.position.y+' '+plan.position.z);

我得到(0,0,0)

然后,当我尝试检查是否点击该平面时:

var vector = new THREE.Vector3( mousex, mousey, 0.5 );
projector = new THREE.Projector();
projector.unprojectVector( vector, camera );
var ray = new THREE.Ray( camera.position, vector.subSelf( camera.position ).normalize() );
var intersects = ray.intersectObjects( scene.children );

无论我在场景中点击哪里,它总是返回我点击的平面。 例如,使用SphereGeometry检查点击次数没有问题。

那么如果它(显然)始终保持在(0,0,0)中,如何检查PlaneGeometry上的点击,这会使所有点击都被认为是在飞机上?

我使用three.js 53,这是我知道的一个非常古老的版本,但是我在很久以前就开始了一个很大的项目,并且在上一个版本中有太多的东西要改变,所以我希望这个问题可以解决在版本53中。

编辑

使用

plan.geometry.verticesNeedUpdate = true;
plan.geometry.computeCentroids();

我现在有一些有效的东西,但并非在所有情况下都有效。 我有:

camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 );

如果我像我那样定义PlaneGeometry的顶点:

planGeom .vertices[0].x =  50;
planGeom .vertices[0].y =  20;
planGeom .vertices[0].z =  -20;

planGeom .vertices[1].x =  50;
planGeom .vertices[1].y =  20;
planGeom .vertices[1].z =  20;

planGeom .vertices[2].x =  50;
planGeom .vertices[2].y =  -20;
planGeom .vertices[2].z =  -20;

planGeom .vertices[3].x =  50;
planGeom .vertices[3].y =  -20;
planGeom .vertices[3].z =  20;

飞机在摄像机前面(距离50,我可以看到整个平面)和intersectObjects返回我在场景中点击的任何地方点击平面,并返回每次点击:

(intersects[0].point.x, intersects[0].point.y, intersects[0].point.z) = (0, 0, 0)

但如果我将其定义为:

planGeom .vertices[0].x =  -20;
planGeom .vertices[0].y =  20;
planGeom .vertices[0].z =  -50;

planGeom .vertices[1].x =  20;
planGeom .vertices[1].y =  20;
planGeom .vertices[1].z =  -50;

planGeom .vertices[2].x =  -20;
planGeom .vertices[2].y =  -20;
planGeom .vertices[2].z =  -50;

planGeom .vertices[3].x =  20;
planGeom .vertices[3].y =  -20;
planGeom .vertices[3].z =  -50;

平面位于摄影机的左侧,而且对象只返回我点击的3D点的坐标,并且只有当我点击平面时才会返回;单击每个角返回相应顶点的坐标。例如:

(intersects[0].point.x, intersects[0].point.y, intersects[0].point.z) = (planGeom .vertices[0].x, planGeom .vertices[0].y, planGeom .vertices[0].z)

在飞机中心点击一下:

(intersects[0].point.x, intersects[0].point.y, intersects[0].point.z) = (0, 0, -50)

所以现在,我想知道为什么它在所有情况下都不起作用?我将做一个简单的例子,它将比所有这些解释更简单:)。

修改

以下是一个示例:您首先在相机前面看到的平面为场景中的每次点击返回一个交点。左侧的第二个平面(拖动场景旋转)返回一个良好的交叉点。 http://jsfiddle.net/9ggk00so/1/

修改

工作代码:http://jsfiddle.net/9ggk00so/3/

确实,缺少一条指令:

plan.geometry.verticesNeedUpdate = true;
plan.geometry.computeFaceNormals();//ok with that one
plan.geometry.computeCentroids();

1 个答案:

答案 0 :(得分:0)

对象位置对于交叉检查应该无关紧要。在这种情况下,几何更重要。更新顶点数组后,应设置planGeom.verticesNeedUpdate = true;

Geometry Reference

您刚刚在平面的局部坐标系中移动了顶点,而不是世界坐标系中的平面。所以,飞机的矩阵没有改变,你的console.log给你(0,0,0)

修改

也许raycaster的矢量是错误的。 mousexmousey是否来自鼠标事件?我错过了那些台词:

var mousex = (event.clientX / SCREEN_WIDTH) * 2 - 1;
var mousey =  - (event.clientY / SCREEN_HEIGHT) * 2 + 1;

var vector = new THREE.Vector3(mousex, mousey, 0.5);

// if your canvas doesn't fill the page
// you need to determine the offset of the canvas and consider it as follows

var mousex = ((event.clientX - offsetX) / SCREEN_WIDTH) * 2 - 1;
var mousey = - ((event.clientY - offsetY) / SCREEN_HEIGHT) * 2 + 1;

var vector = new THREE.Vector3(mousex, mousey, 0.5);

Raycaster Reference