Three.js 在鼠标点击的地方绘制,但完全平行于相机方向

Ali*_*ice 1 javascript 3d three.js raycasting

我不确定如何做到这一点。我阅读了很多关于光线投射的内容,这似乎有助于找到与某物相交的点,但在这种情况下,我只想将 2d 鼠标坐标插入到 3d 点鼠标点击的确切位置,无论缩放、旋转、那里是否有对象等。

我已经想到但没有接近的一种方法是制作一个平行于相机的隐形平面,始终垂直定向并始终与 y 轴相交。然后使用光线投射器击中飞机,根据需要绘制,然后删除飞机。不过,这似乎是一种愚蠢的方法。

目前我有一种方法效果很好,但是当线条远离原点或相机放大时会出现一些问题

在这张照片中,我从两个不同的角度画了两条线。垂直线是相机与 x 轴和 z 轴水平时的样子,我在 y 轴上画一条直线,而水平线是我在相机朝下涂鸦时发生的情况。 https://i.imgur.com/f8qw5xV.png

可以看到,这个计算好像是用到相机的距离来做的,所以距离相机越远,计算中的失真就越大。怎样才能摆脱这种扭曲?

来源:https : //github.com/AskAlice/mandala-3d-threejs 现场演示:https : //askalice.me/mandala/

这是相关的代码:

js/content.js@112

function get3dPointZAxis(event)
{
    camPos = camera.position;
    var mv = new THREE.Vector3((event.clientX / window.innerWidth) * 2 - 1, -(event.clientY/window.innerHeight) * 2 + 1, 1).unproject(camera);
    var m2 = new THREE.Vector3(0,0,0);
    var pos = camPos.clone(); 
    pos.add(mv.sub(camPos).normalize().multiplyScalar(m2.distanceTo(camPos)));
    return pos;
}
Run Code Online (Sandbox Code Playgroud)

我使用了来自两个 stackoverflow 帖子的信息来解决这个问题,它有我所描述的问题。

首先,这篇文章展示了如何绘制并将其转换为 z 轴。它是平的。但是我在尝试在三个维度上进行工作时遇到了很多麻烦。

如何在运行时使用three.js绘制线段

然后我使用以下帖子中的信息至少使其与 xz 轴上的相机平行,如下所示:https : //i.imgur.com/E9AQNpH.png

在three.js中平行于投影平面移动对象

pri*_*849 5

带有THREE.Plane()和的选项THREE.Raycaster().ray.intersectPlane()

var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
var plane = new THREE.Plane();
var planeNormal = new THREE.Vector3();
var point = new THREE.Vector3();

function getPoint(event){
  mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
  mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
  planeNormal.copy(camera.position).normalize();
  plane.setFromNormalAndCoplanarPoint(planeNormal, scene.position);
  raycaster.setFromCamera(mouse, camera);
  raycaster.ray.intersectPlane(plane, point);
}
Run Code Online (Sandbox Code Playgroud)

运行代码片段,单击“绘制”复选框将其设置为选中状态,随机移动鼠标(不按下鼠标),再次单击复选框,按下鼠标旋转场景。所有点都在同一平面上。

var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
var plane = new THREE.Plane();
var planeNormal = new THREE.Vector3();
var point = new THREE.Vector3();

function getPoint(event){
  mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
  mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
  planeNormal.copy(camera.position).normalize();
  plane.setFromNormalAndCoplanarPoint(planeNormal, scene.position);
  raycaster.setFromCamera(mouse, camera);
  raycaster.ray.intersectPlane(plane, point);
}
Run Code Online (Sandbox Code Playgroud)
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 0, 10);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

var controls = new THREE.OrbitControls(camera, renderer.domElement);

var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
var plane = new THREE.Plane();
var planeNormal = new THREE.Vector3();
var point = new THREE.Vector3();

document.addEventListener("mousedown", onMouseDown, false);
document.addEventListener("mousemove", onMouseMove, false);

function getPoint(event) {
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
  planeNormal.copy(camera.position).normalize();
  plane.setFromNormalAndCoplanarPoint(planeNormal, scene.position);
  raycaster.setFromCamera(mouse, camera);
  raycaster.ray.intersectPlane(plane, point);
}

function setPoint() {
  var sphere = new THREE.Mesh(new THREE.SphereBufferGeometry(.125, 4, 2), new THREE.MeshBasicMaterial({
    color: "yellow",
    wireframe: true
  }));
  sphere.position.copy(point);
  scene.add(sphere);
}

function onMouseDown(event) {
  getPoint(event);
  if (draw.checked) setPoint();
}

function onMouseMove(event) {
  getPoint(event);
  if (draw.checked) setPoint();
}

render();

function render() {
  requestAnimationFrame(render);
  renderer.render(scene, camera);
}
Run Code Online (Sandbox Code Playgroud)
body {
  overflow: hidden;
  margin: 0;
}
Run Code Online (Sandbox Code Playgroud)