在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();
答案 0 :(得分:0)
对象位置对于交叉检查应该无关紧要。在这种情况下,几何更重要。更新顶点数组后,应设置planGeom.verticesNeedUpdate = true;
。
您刚刚在平面的局部坐标系中移动了顶点,而不是世界坐标系中的平面。所以,飞机的矩阵没有改变,你的console.log给你(0,0,0)
。
修改强>
也许raycaster的矢量是错误的。 mousex
和mousey
是否来自鼠标事件?我错过了那些台词:
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);