JSFiddle - React, Tailwind, and code Playground

by grano

CSS

body{
  overflow: hidden;
  margin: 0;
}

JavaScript

import * as THREE from 'https://threejs.org/build/three.module.js';
import {OrbitControls} from 'https://threejs.org/examples/jsm/controls/OrbitControls.js';
import {BufferGeometryUtils} from "https://threejs.org/examples/jsm/utils/BufferGeometryUtils.js";
import {GUI} from "https://threejs.org/examples/jsm/libs/dat.gui.module.js";


let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 100);
camera.position.set(0, 5, 10);
let renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);

let controls = new OrbitControls(camera, renderer.domElement);

let light = new THREE.DirectionalLight(0xffffff, 1);
light.position.setScalar(10);
scene.add(light, new THREE.AmbientLight(0xffffff, 0.5));

let geoms = [
	createGeom(false),
//  createGeom(true)
];
let g = BufferGeometryUtils.mergeBufferGeometries(geoms, true);

let m = [
	new THREE.MeshStandardMaterial({color: "silver", wireframe: true, metalness: 0.75, roughness: 0.5}),
  new THREE.MeshLambertMaterial({color: "gold", wireframe: true})
];
let o = new THREE.Mesh(g, m);
scene.add(o);

let params = {
	wireframe: true
};
let gui = new GUI();
gui.add(params, "wireframe").onChange( val => {
	m.forEach(m => {m.wireframe = val});
});

renderer.setAnimationLoop(() => {
  renderer.render(scene, camera);
})

function createGeom(upside){
  let g = new THREE.BoxGeometry(1, 1, 1, 360, 1, 1);
  g.translate(0.5, 0.5, 0);
  let pos = g.attributes.position;

  let v = new THREE.Vector3();
  let r = 2;
  let R = 3;
  let waves = 5;
  for(let i = 0; i < pos.count; i++){
    v.fromBufferAttribute(pos, i);

    let angle = v.x * Math.PI * 2;

    let radius = v.z > 0 ? R : r;
    let y = v.y < 0.5 ? v.y : v.y + Math.sin(v.x * Math.PI * 2 * waves) * 0.25;

    pos.setXYZ(i, Math.cos(angle) * radius, y, -Math.sin(angle) * radius);
  }
  g.translate(0, -1, 0);
  if(upside) g.rotateX(Math.PI);
 ...