diff --git a/main.js b/main.js index 9036cd3..7c5fdfb 100644 --- a/main.js +++ b/main.js @@ -4,6 +4,7 @@ import * as THREE from 'three'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; +import * as BufferGeometryUtils from 'three/addons/utils/BufferGeometryUtils.js'; // Initialise scene const scene = new THREE.Scene(); @@ -42,6 +43,17 @@ function makeCube(xCoord, material) { return cube; } +function makeCylinder(material) { + const radius = .25; + const height = 1; + const radialSegments = 8; + const geometry = new THREE.CylinderGeometry(radius, radius, height, radialSegments); + + const mesh = new THREE.Mesh(geometry, material); + scene.add(mesh); + return mesh; +} + class CornerCurve extends THREE.Curve { constructor(scale) { super(); @@ -49,39 +61,71 @@ class CornerCurve extends THREE.Curve { } getPoint(t) { - const tx = (Math.sin(.5 * Math.PI * t) -.5) * this.scale; - const ty = (Math.cos(.5 * Math.PI * t) -.5) * this.scale; + const tx = Math.sin(.5 * Math.PI * t) * this.scale - .5; + const ty = Math.cos(.5 * Math.PI * t) * this.scale - .5; const tz = 0; return new THREE.Vector3(tx, ty, tz); } } function makeCorner(material) { - const path = new CornerCurve(.75); + const path = new CornerCurve(.5); const tubularSegments = 20; const radius = .25; const radialSegments = 8; const closed = false; const geometry = new THREE.TubeGeometry(path, tubularSegments, radius, radialSegments, closed); - const mesh = new THREE.Mesh(geometry, material); + const mesh = new THREE.Mesh(geometry, material); + scene.add(mesh); + return mesh; +} + +function makeCap(material) { + const radius = .25; + const height = .5; + const radialSegments = 8; + const cylinder = new THREE.CylinderGeometry(radius, radius, height, radialSegments); + // Shift cylinder vertices down + const positionAttribute = cylinder.getAttribute('position'); + const vertex = new THREE.Vector3(); + for (let i = 0; i < positionAttribute.count; i++) { + vertex.fromBufferAttribute(positionAttribute, i); + positionAttribute.setXYZ(i, vertex.x, vertex.y - .25, vertex.z); + } + + const sphereRadius = .375; + const widthSegments = 12; + const heightSegments = 8; + const sphere = new THREE.SphereGeometry(sphereRadius, widthSegments, heightSegments); + + var capGeometry = BufferGeometryUtils.mergeGeometries([cylinder, sphere], false); + + const mesh = new THREE.Mesh(capGeometry, material); scene.add(mesh); return mesh; } let meshes = []; -meshes.push(makeCube(-2, redMaterial)); -meshes.push(makeCorner(greenMaterial)); -meshes.push(makeCube(2, blueMaterial)); +const cylinder = makeCylinder(redMaterial); +cylinder.position.x = -1; +meshes.push(cylinder); + +const corner = makeCorner(greenMaterial); +meshes.push(corner); + +const cap = makeCap(blueMaterial); +cap.position.x = 1; +meshes.push(cap); // Animation loop function animate() { requestAnimationFrame(animate); for (let i = 0; i < meshes.length; i++) { - const cube = meshes[i]; - cube.rotation.x += 0.01; - cube.rotation.y += 0.01; + const mesh = meshes[i]; + mesh.rotation.x += 0.01; + mesh.rotation.y += 0.01; } controls.update();