Как центрировать орфографическую камеру

#reactjs #three.js #react-three-fiber #orthographic

Вопрос:

Я хочу расположить орфографическую камеру так, чтобы она была сосредоточена на черном квадрате.

Но по какой-то странной причине он автоматически поворачивается и вместо этого показывает вид сверху черного квадрата, и мы видим только тонкую черную линию.

Бывают случаи, когда скрипка меняется, вид автоматически обновляется и снова отображается правильная сторона черного квадрата.

В моей центральной функции мне нужно обновить камеру? Или я должен просто манипулировать элементами управления? Я пробовал и то, и другое, но безрезультатно.

Функция центральной камеры:

 const centerCamera = (controls, camera) => {
  const point = new THREE.Vector3(0, 500, 1);

  camera.position.copy(point);
  camera.lookAt(point.x, point.y, 10);

  controls.target.copy(point);

  controls.update();

  camera.updateProjectionMatrix();
  camera.updateMatrix();
};
 

Сцена:

 import "./styles.css";
import * as THREE from "three";
import React from "react";
import { Canvas } from "@react-three/fiber";
import { MapControls, OrthographicCamera } from "@react-three/drei";

const CONTENT_GEOMETRY = roundedRect(-350, -50, 700, 100, 100 / 3.7);

function roundedRect(x = 0, y = 0, width = 50, height = 50, radius = 5) {
  const ctx = new THREE.Shape();
  ctx.moveTo(x, y   radius);
  ctx.lineTo(x, y   height - radius);
  ctx.quadraticCurveTo(x, y   height, x   radius, y   height);
  ctx.lineTo(x   width - radius, y   height);
  ctx.quadraticCurveTo(x   width, y   height, x   width, y   height - radius);
  ctx.lineTo(x   width, y   radius);
  ctx.quadraticCurveTo(x   width, y, x   width - radius, y);
  ctx.lineTo(x   radius, y);
  ctx.quadraticCurveTo(x, y, x, y   radius);
  ctx.closePath();
  return ctx;
}

const centerCamera = (controls, camera) => {
  const point = new THREE.Vector3(0, 500, 1);

  camera.position.copy(point);
  camera.lookAt(point.x, point.y, point.z);

  controls.target.copy(point);

  controls.update();

  camera.updateProjectionMatrix();
  camera.updateMatrix();
};

export default function App() {
  const dpr = typeof window !== "undefined" ? window?.devicePixelRatio ?? 0 : 0;
  return (
    <div className="App">
      <Canvas
        frameloop="always"
        style={{ height: "100vh" }}
        linear
        dpr={Math.max(dpr, 2)}
      >
        <Content
          onMount={(controls, camera) => {
            centerCamera(controls, camera);
          }}
        />
      </Canvas>
    </div>
  );
}

const Content = ({ onMount }) => {
  const controls = React.useRef(null);
  const camera = React.useRef();

  React.useEffect(() => {
    if (controls.current amp;amp; camera.current) {
      onMount(controls.current, camera.current);
    }
  }, [onMount]);

  return (
    <>
      <MapControls
        ref={controls}
        screenSpacePanning
        dampingFactor={1}
        enableRotate={false}
      />
      <OrthographicCamera ref={camera} makeDefault position={[0, 0, 2]} />
      <mesh position={[0, 500, 1]}>
        <shapeBufferGeometry args={[CONTENT_GEOMETRY]} />
        <meshBasicMaterial color="#000000" />
      </mesh>
    </>
  );
};

 

https://codesandbox.io/s/sleepy-dewdney-zuvyx?file=/src/App.js

Ответ №1:

Я думаю, что ваша проблема в том, что

   camera.position.copy(point);
  camera.lookAt(point.x, point.y, point.z);
 

Вы говорите камере перейти в определенное положение, а затем посмотреть в то же самое положение, что дает вам нежелательные результаты: в каком направлении вы смотрите, когда пункт назначения находится в том же месте, где вы находитесь? Попробуйте lookAt() занять другую позицию. Например: point.y - 1 посмотрел бы вниз, point.x 1 посмотрел бы вправо.

Комментарии:

1. Спасибо за ваш ответ @marquizzo. Вы правы, когда указываете, что 2 пункта одинаковы, это была глупая ошибка с моей стороны. Однако, если я переключусь на camera.LookAt(точка.x, точка.y, 10); проблема останется прежней. Есть какие-нибудь мысли по этому поводу?