rotation handles now include motor range indicators

master
Jake 2025-11-05 15:36:59 +08:00
parent f77ff74f94
commit 244dcf3893
1 changed files with 52 additions and 26 deletions

View File

@ -8,7 +8,7 @@ const renderer = new THREE.WebGLRenderer({ canvas, antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight); renderer.setSize(window.innerWidth, window.innerHeight);
const scene = new THREE.Scene(); const scene = new THREE.Scene();
scene.background = new THREE.Color(0x111111); scene.background = new THREE.Color(0xaaaaaa);
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 100); const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 100);
camera.position.set(2, 2, 2); camera.position.set(2, 2, 2);
@ -18,7 +18,9 @@ camera.lookAt(0, 0, 0);
scene.add(new THREE.AmbientLight(0xffffff, 0.6)); scene.add(new THREE.AmbientLight(0xffffff, 0.6));
const directional = new THREE.DirectionalLight(0xffffff, 0.8); const directional = new THREE.DirectionalLight(0xffffff, 0.8);
directional.position.set(15, 10, 7); directional.position.set(15, 10, 7);
scene.add(directional); const directional2 = new THREE.DirectionalLight(0xffffff, 0.8);
directional2.position.set(-15, 10, -7);
scene.add(directional2);
// Controls // Controls
const controls = new OrbitControls(camera, renderer.domElement); const controls = new OrbitControls(camera, renderer.domElement);
@ -81,39 +83,63 @@ function createRotationArc(axis, lower, upper, radius = 0.1, segments = 32) {
} }
function createRotationSector(axis, lower, upper, radius = 0.1, segments = 64) { function createRotationSector(axis, lower, upper, radius = 0.1, segments = 64) {
const shape = new THREE.Shape(); const motorMargin = 0.4; // hardcoded extra range beyond joint limits
shape.moveTo(0, 0); const motorLower = lower - motorMargin;
const motorUpper = upper + motorMargin;
for (let i = 0; i <= segments; i++) { const redMaterial = new THREE.MeshBasicMaterial({
const angle = lower + (upper - lower) * (i / segments); color: 0xff0000,
shape.lineTo(Math.cos(angle) * radius, Math.sin(angle) * radius);
}
shape.lineTo(0, 0); // close the shape
const geometry = new THREE.ShapeGeometry(shape);
const material = new THREE.MeshBasicMaterial({
color: 0x888888, // light gray
transparent: true, transparent: true,
opacity: 0.3, // translucent opacity: 0.2,
side: THREE.DoubleSide, // show both sides of the fill side: THREE.DoubleSide,
depthTest: false, // ✅ always on top depthTest: false,
depthWrite: false depthWrite: false
}); });
const whiteMaterial = new THREE.MeshBasicMaterial({
color: 0xffffff,
transparent: true,
opacity: 0.6,
side: THREE.DoubleSide,
depthTest: false,
depthWrite: false
});
const mesh = new THREE.Mesh(geometry, material); 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);
const geometry = new THREE.ShapeGeometry(shape);
return new THREE.Mesh(geometry, material);
}
// Orient the sector to match the axis const redLeft = createArc(motorLower, lower, redMaterial);
const whiteArc = createArc(lower, upper, whiteMaterial);
const redRight = createArc(upper, motorUpper, redMaterial);
// Orient all arcs to match the axis
const basis = new THREE.Matrix4(); const basis = new THREE.Matrix4();
const up = new THREE.Vector3(0, 0, 1); const up = new THREE.Vector3(0, 0, 1);
const quaternion = new THREE.Quaternion().setFromUnitVectors(up, axis.clone().normalize()); const quaternion = new THREE.Quaternion().setFromUnitVectors(up, axis.clone().normalize());
basis.makeRotationFromQuaternion(quaternion); basis.makeRotationFromQuaternion(quaternion);
mesh.applyMatrix4(basis);
return mesh; redLeft.applyMatrix4(basis);
whiteArc.applyMatrix4(basis);
redRight.applyMatrix4(basis);
const group = new THREE.Group();
group.add(redLeft);
group.add(whiteArc);
group.add(redRight);
return group;
} }
function createAngleIndicator(axis, angle, radius = 0.1) { function createAngleIndicator(axis, angle, radius = 0.1) {
const dir = new THREE.Vector3(Math.cos(angle), Math.sin(angle), 0).multiplyScalar(radius); const dir = new THREE.Vector3(Math.cos(angle), Math.sin(angle), 0).multiplyScalar(radius);
@ -123,11 +149,11 @@ function createAngleIndicator(axis, angle, radius = 0.1) {
]); ]);
const material = new THREE.LineBasicMaterial({ const material = new THREE.LineBasicMaterial({
color: 0xffffff, // white color: 0xffffff, // white
linewidth: 2, // note: linewidth only works in some renderers linewidth: 2, // note: linewidth only works in some renderers
depthTest: false, // ✅ always on top depthTest: false, // ✅ always on top
depthWrite: false depthWrite: false
}); });
const line = new THREE.Line(geometry, material); const line = new THREE.Line(geometry, material);