Three.js - 使用鼠标移动创建/更新网格并单击

时间:2018-05-02 02:30:25

标签: javascript three.js mesh

我希望能够通过用户鼠标点击创建一个Mesh。每次用户点击新点时,都会添加到网格中。此外,当用户移动鼠标时,最后一点应该跟随光标。

我已经能够使用Line,其几何是BufferGeometry,其中位置被设置为BufferGeometry的属性。

然后当用户点击时,我将x,y坐标添加到位置数组,然后设置BufferGeometry的绘制范围。当用户移动鼠标时,我正在更新最后一个位置的x,y坐标,然后将BufferGeometry.attributes.position.needsUpdate设置为true。这也有效。

然而现在我现在想要能够使用网格而不是线条,因为我想要一个封闭的形状,但是它在显示/更新时遇到了困难。

是否有一种简单的方法可以在鼠标点击/鼠标移动时更新并向网格添加点?

Example

let scene, camera, renderer, raycaster, canvas;

let linePositions, lineGeometry, line, myMesh;

let count = 0;

init();
initScene();
animate();

function init() {
  document.addEventListener('click', onClick);
  document.addEventListener('mousemove', onMouseMove);
}

function initScene() {
  scene = new THREE.Scene();
  scene.background = new THREE.Color(0xf0f0f0);

  camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

  camera.position.z = 5;

  raycaster = new THREE.Raycaster();

  renderer = new THREE.WebGLRenderer();
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);
  initCanvas();
}

/* Initialize the Canvas so we can raycast the mouse click and mouse move */
function initCanvas() {
  const geometry = new THREE.PlaneGeometry(7, 7, 1, 0);
  const material = new THREE.MeshBasicMaterial({
    visible: false
  });

  canvas = new THREE.Mesh(geometry, material);
  scene.add(canvas);

  addLineAndMesh();
}

function addLineAndMesh() {

  linePositions = new THREE.BufferAttribute(new Float32Array(25 * 3), 3).setDynamic(true);

  // geometry
  lineGeometry = new THREE.BufferGeometry();
  lineGeometry.addAttribute('position', linePositions);

  // material
  const lineMaterial = new THREE.LineBasicMaterial({
    color: 0xff0000,
    linewidth: 1
  });

  const material = new THREE.MeshLambertMaterial({
    color: 0xff0000,
    side: THREE.DoubleSide,
    opacity: 0.6
  });

  myMesh = new THREE.Mesh(lineGeometry, material);
  scene.add(myMesh);

  // line
  line = new THREE.Line(lineGeometry, lineMaterial);
  scene.add(line);
}

function animate() {
  requestAnimationFrame(animate);
  renderer.render(scene, camera);
};

function onClick(e) {
  const pos = getMousePosition(e);

  if (count === 0) {
    setPositions(pos, false);
    count++;
  }

  setPositions(pos, false);
  count++;

  lineGeometry.setDrawRange(0, count);
}

function onMouseMove(e) {
  const pos = getMousePosition(e);
  setPositions(pos, true);
}

function setPositions(pos, isUpdate) {
  const index = isUpdate ? count - 1 : count;

  linePositions.setXYZ(index, pos.x, pos.y, 0);

  linePositions.needsUpdate = true;
  line.frustumCulled = false;
  myMesh.frustumCulled = false;
}

function getMousePosition(e) {
  e.preventDefault();

  let mouse = {};
  mouse.x = (e.offsetX / renderer.domElement.width) * 2 - 1;
  mouse.y = -(e.offsetY / renderer.domElement.height) * 2 + 1;
  mouse.z = 0;

  raycaster.setFromCamera(mouse, camera);

  const intersects = raycaster.intersectObjects([canvas]);

  if (intersects.length > 0 && intersects[0]) {
    mouse = intersects[0].point;
  }

  return mouse;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/89/three.min.js"></script>

0 个答案:

没有答案