为什么我的代码生成的边界框总是在原点,而不是在鼠标按下时在光标位置渲染?

问题描述 投票:0回答:1

我正在尝试在三个 js 渲染上创建一个边界框缩放,用户可以在其中拖动一个框,然后相机将缩放有界区域。但是,该框未正确生成。 ` 公共 DragZoom(值: 布尔值): void { const 几何 = new THREE.PlaneGeometry(1, 1); const 材质 = new THREE.MeshBasicMaterial({ 颜色:0x808080, 不透明度:0.1, 透明:真实, });

let mesh = new THREE.Mesh(geometry, material);

let isDragging = false;
let initialCursorPos = new THREE.Vector2();
let initialBoxPos = new THREE.Vector3();

const borderGeometry = new THREE.EdgesGeometry(geometry);
const borderMaterial = new THREE.LineBasicMaterial({ color: 0x000000, linewidth: 2 });
const borderLines = new THREE.LineSegments(borderGeometry, borderMaterial);
mesh.add(borderLines);

const onMouseDown = (event: MouseEvent) => {
  isDragging = true;
  initialCursorPos.x = event.clientX;
  initialCursorPos.y = event.clientY;

  initialBoxPos.x = (event.clientX / window.innerWidth) * 2 - 1;
  initialBoxPos.y = -(event.clientY / window.innerHeight) * 2 + 1;
  mesh.position.set(initialBoxPos.x, initialBoxPos.y, 0);
  this.scene.add(mesh);
};

const onMouseMove = (event: MouseEvent) => {
  if (isDragging) {
    const deltaX = (event.clientX - initialCursorPos.x) / 40; // Divide by a smaller value for less aggressive scaling
    const deltaY = (event.clientY - initialCursorPos.y) / 40; // Divide by a smaller value for less aggressive scaling
    mesh.scale.set(deltaX, deltaY, 1);

    const boxSize = new THREE.Box3().setFromObject(mesh).getSize(new THREE.Vector3());
    const width = boxSize.x;
    const height = boxSize.y;
    const newX = initialBoxPos.x + (width / 2) * Math.sign(deltaX);
    const newY = initialBoxPos.y - (height / 2) * Math.sign(deltaY);
    mesh.position.set(newX, newY, 0);
  }
};

const onMouseUp = () => {
  if (isDragging) {
    isDragging = false;
    const boundingBox = new THREE.Box3().setFromObject(mesh);
    const boxSize = boundingBox.getSize(new THREE.Vector3());

    const cameraAspect = this.camera.aspect;
    const horizontalPadding = (boxSize.x - boxSize.y * cameraAspect) / 2;
    const verticalPadding = (boxSize.y - boxSize.x / cameraAspect) / 2;

    this.controls.fitToBox(mesh, true, {
      paddingTop: verticalPadding,
      paddingBottom: verticalPadding,
      paddingLeft: horizontalPadding,
      paddingRight: horizontalPadding,
    });
    this.scene.remove(mesh);
    mesh = null;
  }
};

this.renderer.domElement.addEventListener('mousedown', onMouseDown);
this.renderer.domElement.addEventListener('mousemove', onMouseMove);
this.renderer.domElement.addEventListener('mouseup', onMouseUp);

}`

我尝试使用mesh.position,但它似乎没有影响任何东西。

angular three.js
1个回答
0
投票

大多数情况下,屏幕坐标不能直接用作场景内实体的坐标。

mesh.position.set(initialBoxPos.x, initialBoxPos.y, 0);

您需要检查您的相机;场景中的 1 个长度单位很可能与屏幕上的 1 个像素不同。

您需要将屏幕坐标转换为场景坐标,这取决于相机,如下所示:

const canvasBounds = canvas.getBoundingClientRect();

const ndc = {
    x: ((clientX - canvasBounds.left) / canvas.width) * 2 - 1,
    y: (-(clientY - canvasBounds.top) / canvas.height) * 2 + 1,
    z: 0,
};

const worldPosition = new THREE.Vector3(ndc.x, ndc.y, ndc.z);
worldPosition.unproject(camera);

NDC的含义是标准化设备坐标。 NDC 空间中的所有坐标范围为 [−1, 1]

© www.soinside.com 2019 - 2024. All rights reserved.