JSFiddle - React, Tailwind, and code Playground
by mcoirad
JavaScript
import * as THREE from "three";
const scene = new THREE.Scene();
const metalMaterial = new THREE.MeshStandardMaterial({
color: 0x707780,
roughness: 0.55,
metalness: 0.7
});
const jointMaterial = new THREE.MeshStandardMaterial({
color: 0x22252a,
roughness: 0.4,
metalness: 0.9
});
function createBox(width, height, depth, material = metalMaterial) {
const geometry = new THREE.BoxGeometry(width, height, depth);
const mesh = new THREE.Mesh(geometry, material);
mesh.castShadow = true;
mesh.receiveShadow = true;
return mesh;
}
/**
* Creates a limb whose top begins at its parent's origin.
* The limb extends downward along local Y.
*/
function createLimb({
length,
width,
depth = width,
material = metalMaterial
}) {
const joint = new THREE.Group();
const limb = createBox(width, length, depth, material);
limb.position.y = -length / 2;
joint.add(limb);
return {
joint,
mesh: limb,
endY: -length
};
}
function addJointMarker(parent, radius) {
const geometry = new THREE.SphereGeometry(radius, 12, 8);
const marker = new THREE.Mesh(geometry, jointMaterial);
marker.castShadow = true;
parent.add(marker);
return marker;
}
function createArm({
side,
shoulderX,
shoulderY,
upperArmLength,
forearmLength,
armWidth
}) {
const sign = side === "left" ? -1 : 1;
const shoulder = new THREE.Group();
shoulder.name = `${side}Shoulder`;
shoulder.position.set(shoulderX, shoulderY, 0);
addJointMarker(shoulder, armWidth * 0.65);
/*
* Rotate the arm's local downward direction slightly outward.
* Positive and negative Z rotations distinguish the two sides.
*/
shoulder.rotation.z = -sign * 0.08;
const upperArm = createLimb({
length: upperArmLength,
width: armWidth,
depth: armWidth * 1.15
});
shoulder.add(upperArm.joint);
const elbow = new THREE.Group();
elbow.name =...