import * as THREE from 'three'; export function createRotationSector(axis, lower, upper, radius = 0.1, segments = 64) { const motorMargin = 0.4; const motorLower = lower - motorMargin; const motorUpper = upper + motorMargin; const redMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000, transparent: true, opacity: 0.2, side: THREE.DoubleSide, depthTest: false, depthWrite: false }); const whiteMaterial = new THREE.MeshBasicMaterial({ color: 0xffffff, transparent: true, opacity: 0.6, side: THREE.DoubleSide, depthTest: false, depthWrite: false }); function createArc(start, end, material) { const shape = new THREE.Shape(); shape.moveTo(0, 0); for (let i = 0; i <= segments; i++) { const angle = start + (end - start) * (i / segments); shape.lineTo(Math.cos(angle) * radius, Math.sin(angle) * radius); } shape.lineTo(0, 0); return new THREE.Mesh(new THREE.ShapeGeometry(shape), material); } const redLeft = createArc(motorLower, lower, redMaterial); const whiteArc = createArc(lower, upper, whiteMaterial); const redRight = createArc(upper, motorUpper, redMaterial); const up = new THREE.Vector3(0, 0, 1); const quaternion = new THREE.Quaternion().setFromUnitVectors(up, axis.clone().normalize()); const basis = new THREE.Matrix4().makeRotationFromQuaternion(quaternion); redLeft.applyMatrix4(basis); whiteArc.applyMatrix4(basis); redRight.applyMatrix4(basis); const group = new THREE.Group(); group.add(redLeft, whiteArc, redRight); return group; } export function createAngleIndicator(axis, angle, radius = 0.1) { const dir = new THREE.Vector3(Math.cos(angle), Math.sin(angle), 0).multiplyScalar(radius); const geometry = new THREE.BufferGeometry().setFromPoints([new THREE.Vector3(0, 0, 0), dir]); const material = new THREE.LineBasicMaterial({ color: 0xffffff, depthTest: false, depthWrite: false }); const line = new THREE.Line(geometry, material); const up = new THREE.Vector3(0, 0, 1); const quaternion = new THREE.Quaternion().setFromUnitVectors(up, axis.clone().normalize()); line.applyQuaternion(quaternion); return line; } export function createJointLabel(name, angle) { const canvas = document.createElement('canvas'); canvas.width = 256; canvas.height = 64; const ctx = canvas.getContext('2d'); ctx.fillStyle = 'rgba(0,0,0,0.6)'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.font = '20px monospace'; ctx.fillStyle = '#ffffff'; ctx.fillText(`${name}: ${(angle * 180 / Math.PI).toFixed(1)}°`, 10, 40); const texture = new THREE.CanvasTexture(canvas); const material = new THREE.SpriteMaterial({ map: texture, transparent: true }); const sprite = new THREE.Sprite(material); sprite.scale.set(0.5, 0.125, 1); // adjust size return sprite; }