fix: [rd] 방화셔터 체인/스프로켓 시각화 수정

- 샤프트 스프로켓 반지름 130→70mm (브라켓 180mm 내 수용)
- 모터 스프로켓 반지름 45.5→30mm
- 양쪽 스프로켓에 톱니바퀴 메시 추가 (18/10개 톱니)
- 체인 직선 구간 기울기 회전 적용
This commit is contained in:
김보곤
2026-03-09 09:31:31 +09:00
parent 4e1de76f15
commit 2b8f0c680e

View File

@@ -1143,19 +1143,38 @@ function fs3dBuild() {
const motorBkThick = motorBkD; // 18mm
const motorBkCX = motorDir * (W1 / 2 - motorBkThick / 2);
const motorR = b.shaftDia * 0.45;
const motorSprocketR = 130 * 0.35; // shaftSprocketR * 0.35
const motorZ = -(130 + motorSprocketR + 20); // 모터 Z 오프셋 (-Z = 셔터박스 뒤쪽)
const shaftSprocketR = 70; // 브라켓 높이(180mm) 내 크기 (ø140)
const motorSprocketR = 30; // 모터측 작은 스프로켓 (ø60)
const motorZ = -(shaftSprocketR + motorSprocketR + 20); // 모터 Z 오프셋 (-Z = 셔터박스 뒤쪽)
// 브라켓: Z 중심은 샤프트(0)와 모터(motorZ) 사이
const motorBkGeo = new THREE.BoxGeometry(motorBkThick, motorBkH, motorBkW);
const motorBk = new THREE.Mesh(motorBkGeo, bracketMat);
motorBk.position.set(motorBkCX, 0, motorZ / 2);
meshes.motor.add(motorBk);
// --- 2) 스프로켓 위치 기준 (체인 경로 계산용, 메시 없음) ---
const shaftSprocketR = 130;
// --- 2) 스프로켓 톱니바퀴 (샤프트측 + 모터측) ---
const sprocketThick = 12;
const sprocketFaceX = motorDir * (W1 / 2 - motorBkThick);
const shaftSprocketX = sprocketFaceX - motorDir * sprocketThick / 2;
const sprocketMat = new THREE.MeshStandardMaterial({ color: 0x374151, metalness: 0.6, roughness: 0.35 });
// 샤프트 스프로켓 톱니바퀴
const shaftSpGroup = new THREE.Group();
const shaftSpBodyGeo = new THREE.CylinderGeometry(shaftSprocketR * 0.85, shaftSprocketR * 0.85, sprocketThick, 32);
shaftSpBodyGeo.rotateZ(Math.PI / 2);
shaftSpGroup.add(new THREE.Mesh(shaftSpBodyGeo, sprocketMat));
const shaftTeethCount = 18;
const toothH = 8, toothTW = 6;
for (let i = 0; i < shaftTeethCount; i++) {
const a = (i / shaftTeethCount) * Math.PI * 2;
const tGeo = new THREE.BoxGeometry(sprocketThick * 0.8, toothTW, toothH);
const t = new THREE.Mesh(tGeo, sprocketMat);
t.position.set(0, (shaftSprocketR - toothH / 2) * Math.sin(a), (shaftSprocketR - toothH / 2) * Math.cos(a));
t.rotation.x = a;
shaftSpGroup.add(t);
}
shaftSpGroup.position.set(shaftSprocketX, 0, 0);
meshes.motor.add(shaftSpGroup);
// --- 3) 모터 (샤프트와 수평방향 Z 오프셋 — 슬랫과 간섭 없음) ---
const motorBodyLen = motorR * 3;
@@ -1190,12 +1209,23 @@ function fs3dBuild() {
mMount.position.set(motorCX, -motorR - 2.5, motorZ);
meshes.motor.add(mMount);
// 모터 출력 스프로켓 (샤프트 스프로켓과 같은 X면, Z=motorZ)
const mSpGeo = new THREE.CylinderGeometry(motorSprocketR, motorSprocketR, sprocketThick, 20);
mSpGeo.rotateZ(Math.PI / 2);
const mSpMesh = new THREE.Mesh(mSpGeo, darkMat);
mSpMesh.position.set(shaftSprocketX, 0, motorZ);
meshes.motor.add(mSpMesh);
// 모터 출력 스프로켓 톱니바퀴 (샤프트 스프로켓과 같은 X면, Z=motorZ)
const mSpGroup = new THREE.Group();
const mSpBodyGeo = new THREE.CylinderGeometry(motorSprocketR * 0.8, motorSprocketR * 0.8, sprocketThick, 20);
mSpBodyGeo.rotateZ(Math.PI / 2);
mSpGroup.add(new THREE.Mesh(mSpBodyGeo, sprocketMat));
const motorTeethCount = 10;
const mToothH = 6, mToothTW = 5;
for (let i = 0; i < motorTeethCount; i++) {
const a = (i / motorTeethCount) * Math.PI * 2;
const tGeo = new THREE.BoxGeometry(sprocketThick * 0.8, mToothTW, mToothH);
const t = new THREE.Mesh(tGeo, sprocketMat);
t.position.set(0, (motorSprocketR - mToothH / 2) * Math.sin(a), (motorSprocketR - mToothH / 2) * Math.cos(a));
t.rotation.x = a;
mSpGroup.add(t);
}
mSpGroup.position.set(shaftSprocketX, 0, motorZ);
meshes.motor.add(mSpGroup);
// --- 4) 체인 (RS #40, YZ 평면 — 수평으로 두 스프로켓 연결) ---
// 샤프트 스프로켓: (Y=0, Z=0), 모터 스프로켓: (Y=0, Z=motorZ)
@@ -1222,18 +1252,21 @@ function fs3dBuild() {
chainLine.position.x = shaftSprocketX;
meshes.motor.add(chainLine);
// 체인 직선 두께 (상/하단)
// 체인 직선 두께 (상/하단 — 스프로켓 반지름 차이만큼 기울기 적용)
const tangentLen = Math.sqrt(Math.pow(R1 - R2, 2) + motorZ * motorZ);
if (tangentLen > 10) {
const halfZ = motorZ / 2;
const chainTilt = Math.atan2(R1 - R2, Math.abs(motorZ)); // 반지름 차이에 의한 기울기
// 상단 직선
const csGeo = new THREE.BoxGeometry(6, 4, tangentLen);
const csTop = new THREE.Mesh(csGeo, chainMat);
csTop.position.set(shaftSprocketX, (R1 + R2) / 2, halfZ);
csTop.rotation.x = chainTilt;
meshes.motor.add(csTop);
// 하단 직선
const csBot = new THREE.Mesh(csGeo.clone(), chainMat);
csBot.position.set(shaftSprocketX, -(R1 + R2) / 2, halfZ);
csBot.rotation.x = -chainTilt;
meshes.motor.add(csBot);
}