diff --git a/resources/views/rd/fire-shutter-drawing/index.blade.php b/resources/views/rd/fire-shutter-drawing/index.blade.php index a730a783..7986191c 100644 --- a/resources/views/rd/fire-shutter-drawing/index.blade.php +++ b/resources/views/rd/fire-shutter-drawing/index.blade.php @@ -1112,50 +1112,91 @@ function fs3dBuild() { meshes.shaft.position.set(0, shaftY, 0); scene.add(meshes.shaft); - // === MOTOR (샤프트 1.2배 크기, 돌출축 + 복주머니 결합 구조) === + // === MOTOR (DH-150K/300K 스타일: 본체 + 기어박스 + 베이스 + 다리) === meshes.motor = new THREE.Group(); - const motorMat = new THREE.MeshStandardMaterial({ color: 0x2563eb, metalness: 0.4, roughness: 0.4 }); - const legMat = new THREE.MeshStandardMaterial({ color: 0x374151, metalness: 0.5, roughness: 0.4 }); + const motorR = b.shaftDia * 0.6; // 모터 반지름 (샤프트 1.2배) + const metalMat = new THREE.MeshStandardMaterial({ color: 0x94a3b8, metalness: 0.6, roughness: 0.3 }); + const darkMat = new THREE.MeshStandardMaterial({ color: 0x374151, metalness: 0.5, roughness: 0.4 }); + const blueMat = new THREE.MeshStandardMaterial({ color: 0x2563eb, metalness: 0.4, roughness: 0.4 }); - // Motor body (원통형, 샤프트의 1.2배) - const motorR = b.shaftDia * 0.6; // 반지름 = 샤프트직경 * 1.2 / 2 - const motorLen = motorR * 3; // 모터 길이 - const motorBodyGeo = new THREE.CylinderGeometry(motorR, motorR, motorLen, 24); - motorBodyGeo.rotateZ(Math.PI / 2); - const motorBody = new THREE.Mesh(motorBodyGeo, motorMat); - // 브라켓 안쪽(샤프트 방향)에 모터 배치 — 복주머니 옆 - const motorCenterX = motorDir * (W1 / 2 - bkW - couplingLen - motorLen / 2); - motorBody.position.set(motorCenterX, 0, 0); - meshes.motor.add(motorBody); + // 모터 위치: 브라켓 안쪽, 복주머니 옆 + const motorBodyLen = motorR * 2.5; // 본체 길이 + const gearBoxLen = motorR * 1.2; // 기어박스 길이 + const totalMotorLen = motorBodyLen + gearBoxLen; + const motorStartX = motorDir * (W1 / 2 - bkW - couplingLen); // 복주머니 끝 + const motorMidX = motorStartX - motorDir * totalMotorLen / 2; // 모터 전체 중심 - // Motor end cap (바깥쪽 마감판 — 샤프트 반대편) - const endCapGeo = new THREE.CylinderGeometry(motorR + 5, motorR + 5, 8, 24); - endCapGeo.rotateZ(Math.PI / 2); - const endCapMat = new THREE.MeshStandardMaterial({ color: 0x1e40af, metalness: 0.5, roughness: 0.3 }); - const endCap = new THREE.Mesh(endCapGeo, endCapMat); - endCap.position.set(motorCenterX - motorDir * (motorLen / 2 + 4), 0, 0); - meshes.motor.add(endCap); + // 1) 모터 본체 (은색 원통 — 메인 실린더) + const bodyGeo = new THREE.CylinderGeometry(motorR, motorR, motorBodyLen, 24); + bodyGeo.rotateZ(Math.PI / 2); + const body = new THREE.Mesh(bodyGeo, metalMat); + const bodyCX = motorStartX - motorDir * (gearBoxLen + motorBodyLen / 2); + body.position.set(bodyCX, 0, 0); + meshes.motor.add(body); - // Motor output shaft (모터 돌출축 — 모터에서 복주머니 방향으로 돌출) - const outShaftR = b.shaftDia * 0.25; - const outShaftLen = 40; - const outShaftGeo = new THREE.CylinderGeometry(outShaftR, outShaftR, outShaftLen, 16); - outShaftGeo.rotateZ(Math.PI / 2); - const outShaftMat = new THREE.MeshStandardMaterial({ color: 0x94a3b8, metalness: 0.8, roughness: 0.2 }); - const outShaft = new THREE.Mesh(outShaftGeo, outShaftMat); - outShaft.position.set(motorCenterX + motorDir * (motorLen / 2 + outShaftLen / 2), 0, 0); + // 2) 상단 리브 (본체 위의 냉각 핀 3줄) + for (let i = 0; i < 3; i++) { + const ribGeo = new THREE.BoxGeometry(motorBodyLen * 0.7, 4, motorR * 0.15); + const rib = new THREE.Mesh(ribGeo, darkMat); + const ribZ = (i - 1) * motorR * 0.5; + rib.position.set(bodyCX, motorR + 2, ribZ); + meshes.motor.add(rib); + } + + // 3) 기어박스 (파란색, 본체보다 살짝 넓은 박스 — 복주머니 쪽) + const gearR = motorR * 1.15; + const gearGeo = new THREE.CylinderGeometry(gearR, gearR, gearBoxLen, 24); + gearGeo.rotateZ(Math.PI / 2); + const gear = new THREE.Mesh(gearGeo, blueMat); + const gearCX = motorStartX - motorDir * (gearBoxLen / 2); + gear.position.set(gearCX, 0, 0); + meshes.motor.add(gear); + + // 4) 기어박스 전면 플랜지 (복주머니 결합면) + const gfGeo = new THREE.CylinderGeometry(gearR + 8, gearR + 8, 5, 24); + gfGeo.rotateZ(Math.PI / 2); + const gf = new THREE.Mesh(gfGeo, darkMat); + gf.position.set(motorStartX - motorDir * 2.5, 0, 0); + meshes.motor.add(gf); + + // 5) 후면 마감판 (본체 뒤쪽) + const ecGeo = new THREE.CylinderGeometry(motorR + 3, motorR + 3, 6, 24); + ecGeo.rotateZ(Math.PI / 2); + const ec = new THREE.Mesh(ecGeo, darkMat); + ec.position.set(bodyCX - motorDir * (motorBodyLen / 2 + 3), 0, 0); + meshes.motor.add(ec); + + // 6) 마운팅 베이스 (브라켓 위에 안착하는 플레이트) + const baseW = totalMotorLen * 0.85; + const baseH = 6; + const baseD = motorR * 1.6; + const baseGeo = new THREE.BoxGeometry(baseW, baseH, baseD); + const basePlate = new THREE.Mesh(baseGeo, darkMat); + const baseY = -motorR - baseH / 2; + basePlate.position.set(motorMidX, baseY, 0); + meshes.motor.add(basePlate); + + // 7) 마운팅 다리 (베이스 → 브라켓까지 연결, 3개) + const legH = bkH / 2 - motorR - baseH; // 베이스 하단 ~ 브라켓 상면 + if (legH > 0) { + const legGeo = new THREE.BoxGeometry(10, legH, 20); + const legOffsets = [-baseW * 0.35, 0, baseW * 0.35]; + legOffsets.forEach(dx => { + const leg = new THREE.Mesh(legGeo, darkMat); + leg.position.set(motorMidX + motorDir * dx, baseY - baseH / 2 - legH / 2, 0); + meshes.motor.add(leg); + }); + } + + // 8) 출력축 (기어박스 → 복주머니 방향) + const outR = b.shaftDia * 0.2; + const outLen = 30; + const outGeo = new THREE.CylinderGeometry(outR, outR, outLen, 12); + outGeo.rotateZ(Math.PI / 2); + const outShaft = new THREE.Mesh(outGeo, metalMat); + outShaft.position.set(motorStartX + motorDir * (outLen / 2), 0, 0); meshes.motor.add(outShaft); - // Motor mounting legs (3개) - const legW = 10, legH = 50, legD = 25; - const legGeo = new THREE.BoxGeometry(legW, legH, legD); - const legOffsets = [-motorLen * 0.35, 0, motorLen * 0.35]; - legOffsets.forEach(dx => { - const leg = new THREE.Mesh(legGeo, legMat); - leg.position.set(motorCenterX + motorDir * dx, -motorR - legH / 2, 0); - meshes.motor.add(leg); - }); - meshes.motor.position.set(0, shaftY, 0); scene.add(meshes.motor);