How to center Orthographic Camera

Viewed 199

I want to position the Orthographic camera so that it is centered on the black square.

But for some weird reason it automatically rotates and shows the top view of the black square instead and we only see a thin black line.

There are times when the fiddle is changed and the view is auto refreshed and the correct side of the black square is shown again.

In my center function do I need to update the camera? Or should I just manipulate the controls? I've tried both approached but to no avail.

Center camera function:

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();
};

Scene:

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 && 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 Answers

I think your problem is with

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

You're telling the camera to go to a position, then look at that same position, which gives you undesired results: which direction do you look at when the destination is in the same place where you are? Try giving the lookAt() a different position. For example: point.y - 1 would look down, point.x + 1 would look right.

Related