A rotating cube. Hello world.

Github Codesandbox

/**
 * The "Hello World" of Trinity!
 */

import Trinity, { Engine, Scene, useCamera, useEngine, useOnUpdate } from "@hmans/trinity"
import React, { useRef } from "react"

/**
 * Our main component spins up the Trinity Engine and creates a simple scene.
 */
export const HelloWorldExample = () => (
  <Engine>
    <Scene backgroundColor="white">
      {/**
       * The default export of the Trinity package transparently provides React components that
       * manage instaces of classes from the THREE.* namespace.
       */}
      <Trinity.AmbientLight intensity={0.3} />
      <Trinity.DirectionalLight intensity={0.8} position={[10, 10, 3]} />

      {/**
       * Here's some other stuff we're including in the scene. Since is this just plain old
       * React, we can use components to give structure to our application.
       */}
      <Camera />
      <SimpleRotatingCube />
    </Scene>
  </Engine>
)

/**
 * Our Camera component creates a perspective camera (using THREE.PerspectiveCamera)
 * and registers it as the scene's active camera through the `useCamera` hook.
 */
const Camera = () => {
  const cameraRef = useRef()

  useCamera(cameraRef)

  return <Trinity.PerspectiveCamera ref={cameraRef} position={[0, 0, 5]} />
}

/**
 * Here's a simple component implementing a cube that is automatically rotating.
 */
const SimpleRotatingCube = () => {
  /* Whenever we want to imperatively modify scene objects, we can just use
  normal React refs. */
  const ref = useRef()

  /* The `useEngine` hook gives us access to some engine-specific objects.
  Here, we're getting a reference to the `triggerFrame` function which we're going
  to be using below. */
  const { triggerFrame } = useEngine()

  /* Trinity provides a collection of hooks that allow us to define game loop
  callbacks. The most common is `useOnUpdate`, which registers a function that will
  be executed on every engine tick. */
  useOnUpdate((dt) => {
    /* The update callbacks receive the current deltatime (the fraction of a second since
    the last tick) as their first and only argument. We can use this to smooth out
    animations and make them framerate independent. */
    ref.current.rotation.x = ref.current.rotation.y += dt

    /* Unlike other frameworks, Trinity will never automatically render a frame
    unless you ask it to. This is what the `triggerFrame` function is for; if any
    of the useOnUpdate callbacks invoke it, Trinity will render a frame in this tick. */
    triggerFrame()
  })

  /* Here's our actual mesh. Once again, we're just using the Trinity default export
  to wrap THREE.* classes in React components. */
  return (
    <Trinity.Mesh ref={ref}>
      <Trinity.BoxBufferGeometry args={[2, 2, 2]} />
      <Trinity.MeshStandardMaterial color="hotpink" />
    </Trinity.Mesh>
  )
}