React

by Cody Bennett

HTML

<div id="app"></div>

CSS

body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
}

li {
  margin: 8px 0;
}

h2 {
  font-weight: bold;
  margin-bottom: 15px;
}

.done {
  color: rgba(0, 0, 0, 0.3);
  text-decoration: line-through;
}

input {
  margin-right: 5px;
}

React

import React, { useEffect, useRef } from 'react';
import {
  Vector3,
  WebGLRenderer,
  sRGBEncoding,
  PerspectiveCamera,
  Scene,
  Fog,
  HemisphereLight,
  DirectionalLight,
  Group,
  Math as MathUtils,
} from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import { VRButton } from 'three/examples/jsm/webxr/VRButton.js';
import { XRControllerModelFactory } from 'three/examples/jsm/webxr/XRControllerModelFactory.js';
import Stats from 'stats.js';
import innerHeight from 'ios-inner-height';
import { cleanScene, removeLights, cleanRenderer } from 'utils/three';
import skeldModelPath from 'assets/skeld.glb';
import './index.css';

const SPEED_FACTOR = [0.1, 0.1, 0.1, 0.1];
const VISION = 1;

function isIterable(obj) {
  // checks for null and undefined
  if (obj == null) return false;

  return typeof obj[Symbol.iterator] === 'function';
}

const App = (props) => {
  const width = useRef(window.innerWidth);
  const height = useRef(window.innerHeight);
  const canvasRef = useRef();
  const renderer = useRef();
  const camera = useRef();
  const scene = useRef();
  const controls = useRef();
  const stats = useRef();
  const lights = useRef();
  const controller1 = useRef();
  const controller2 = useRef();
  const controllerGrip1 = useRef();
  const controllerGrip2 = useRef();
  const player = useRef();
  const cameraVector = useRef(new Vector3());
  const prevGamePads = useRef(new Map());

  useEffect(() => {
    renderer.current = new WebGLRenderer({
      canvas: canvasRef.current,
      powerPreference: 'high-performance',
      antialias: true,
    });
    renderer.current.setSize(width.current, height.current);
    renderer.current.setPixelRatio(1);
    renderer.current.outputEncoding = sRGBEncoding;
    renderer.current.shadowMap.enabled = true;
    renderer.current.xr.enabled = true;
    renderer.current.xr.setFramebufferScaleFactor(2.0);

   ...