JSFiddle - React, Tailwind, and code Playground

HTML

<!DOCTYPE html>
<html>
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r123/three.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/tween.js/18.6.4/tween.umd.js"></script>
  </head>
  <body>
    <canvas width="640" height="550"></canvas>
		<div>
			<button style="top: 0; left: 0" onclick="lookLeft()">←</button>
			<button style="top: 0; left: 320px" onclick="lookRight()">→</button>
		</div>
  </body>
</html>

CSS

body {
  margin: 0;
}
canvas {
  background-color: #eee;
}
button {
  width: 320px;
  height: 40px;
  font-size: 20px;
  box-sizing: border-box;
  position: absolute;
}

JavaScript

const Tween = TWEEN.Tween;
const Easing = TWEEN.Easing;
const canvas = document.querySelector('canvas');
const renderer = new THREE.WebGLRenderer({canvas});
const camera = new THREE.PerspectiveCamera(45, canvas.width / canvas.height, 1, 10000)
const scene = new THREE.Scene();
scene.background = new THREE.Color(0xeeeeee);
scene.add(new THREE.AxesHelper(100));

const update3rdPersonCamera = (() => {
  let _rotation = 0;
  let _distance = 800;
  let _angle = Math.PI / 4;
  const center_point = new THREE.Vector3(0, 0, 0);
  return (rotation = _rotation, distance = _distance, angle = _angle) => {
    const y = distance * Math.sin(angle);
    const projection = distance * Math.cos(angle);
    const x = projection * Math.cos(rotation - Math.PI / 2);
    const z = -projection * Math.sin(rotation - Math.PI / 2);
    camera.position.set(x, y, z);
    camera.lookAt(center_point);
    _rotation = rotation;
    _distance = distance;
    _angle = angle;
  };
})();

update3rdPersonCamera();

function createWireframe(geometry) {
  const wireframe = new THREE.WireframeGeometry(geometry);
  const line = new THREE.LineSegments(wireframe);
  line.material.depthTest = false;
  line.material.opacity = 0.25;
  line.material.transparent = true;
  return line;
}

const R = 50;
const sin60 = Math.sin(Math.PI / 3);
const waypoints = [
  [R, 0],
  [R / 2, -sin60 * R],
  [-R / 2, -sin60 * R],
  [-R, 0],
  [-R / 2, sin60 * R],
  [R / 2, sin60 * R]
];

const shape = new THREE.Shape();
shape.moveTo(...waypoints[waypoints.length - 1]);
waypoints.forEach(point => shape.lineTo(...point));
const cell_geometry = new THREE.ShapeBufferGeometry(shape).center().applyMatrix4(new THREE.Matrix4().makeRotationX(-Math.PI / 2));
const fog_of_war_geometry = new THREE.ExtrudeBufferGeometry(shape, {
  depth: 20,
  bevelEnabled: false
}).center().applyMatrix4(new THREE.Matrix4().makeRotationX(-Math.PI / 2));

const pattern = [
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
  [0, 0, 0,...