JSFiddle - React, Tailwind, and code Playground
by Josh Pullen
HTML
<script src="https://unpkg.com/[email protected]/build/three.min.js"></script>
<script src="https://unpkg.com/[email protected]/examples/js/controls/OrbitControls.js"></script>
CSS
body {
margin: 0;
}
.sketchpadContainer {
position: fixed;
top: 10px;
left: 10px;
}
#sketchpad {
background: #a0a0a0;
border-radius: 3px;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
}
.sketchpadLabel {
color: #ccc;
text-shadow: 0 1px 4px black;
text-align: center;
font-family: sans-serif;
font-size: 14px;
}
JavaScript
const scene = new THREE.Scene();
function sphere(u, v, vec) {
u = u * 2 * Math.PI;
v = v * Math.PI * 0.999 + 0.001;
vec.x = Math.cos(u) * Math.sin(v);
vec.y = Math.sin(u) * Math.sin(v);
vec.z = Math.cos(v);
}
function cylinder(u, v, vec) {
u = u * 2 * Math.PI;
v = v * Math.PI;
vec.x = Math.cos(u);
vec.y = Math.sin(u);
vec.z = Math.cos(v);
}
function torus(R = 1, r = 0.5) {
return function(u, v, vec) {
u = u * 2 * Math.PI;
v = (0.5 - v) * 2 * Math.PI;
vec.x = (R + r * Math.cos(v)) * Math.cos(u);
vec.y = (R + r * Math.cos(v)) * Math.sin(u);
vec.z = r * Math.sin(v);
}
}
function morph(geom1, geom2, t) {
return function(u, v, vec) {
geom1(u, v, vec);
let dest = new THREE.Vector3(0, 0, 0);
geom2(u, v, dest);
vec.multiplyScalar(1 - t);
vec.addScaledVector(dest, t);
}
}
function geomAtTime(t) {
return morph(torus(0.5, 0.5), torus(1, 0.5), t);
}
// xy plane
const geometry = new THREE.ParametricGeometry(geomAtTime(0), 50, 50);
const material = new THREE.MeshStandardMaterial({
color: 0xa0a0a0,
side: THREE.DoubleSide
});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
const camera = new THREE.PerspectiveCamera(
40,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.set(5, 5, 7);
camera.up = new THREE.Vector3(0, 0, 1);
const light = new THREE.AmbientLight(0x909090);
scene.add(light);
const light2 = new THREE.HemisphereLight(0xffffbb, 0x080820, 1);
scene.add(light2);
const renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
let t = 0;
function animate() {
requestAnimationFrame(animate);
t += 1;
mesh.geometry = new THREE.ParametricGeometry(geomAtTime((Math.sin(t / 20) + 1) / 2), 50, 50);
controls.update();
...