我希望能够通过用户鼠标点击创建一个Mesh。每次用户点击新点时,都会添加到网格中。此外,当用户移动鼠标时,最后一点应该跟随光标。
我已经能够使用Line,其几何是BufferGeometry,其中位置被设置为BufferGeometry的属性。
然后当用户点击时,我将x,y坐标添加到位置数组,然后设置BufferGeometry的绘制范围。当用户移动鼠标时,我正在更新最后一个位置的x,y坐标,然后将BufferGeometry.attributes.position.needsUpdate设置为true。这也有效。
然而现在我现在想要能够使用网格而不是线条,因为我想要一个封闭的形状,但是它在显示/更新时遇到了困难。
是否有一种简单的方法可以在鼠标点击/鼠标移动时更新并向网格添加点?
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>