Codels
1,1 тыс. треуг.1,45 × 1,86 × 0,84 m

Использовать в коде

Ремикс в редакторе
Самодостаточный ES-модуль — зависит только от three. Вызовите фабрику и добавьте группу в сцену.
/**
 * Control Console — Codels 3D model library
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 1,068 · Size (W × H × D): 1.45 × 1.86 × 0.84 m
 *
 * Usage:
 *   import { createControlConsole } from './control-console.js';
 *   
 *   const model = createControlConsole();
 *   model.position.set(0, 0, 0);
 *   scene.add(model);
 */
import * as THREE from 'three';

const deg = THREE.MathUtils.degToRad;

// Extrude a 2D outline along Z (centered). bevel = [thickness, size, segments].
function extrude(outline, depth, holes = [], bevel = null) {
  const shape = new THREE.Shape(outline.map(([x, y]) => new THREE.Vector2(x, y)));
  for (const hole of holes) shape.holes.push(new THREE.Path(hole.map(([x, y]) => new THREE.Vector2(x, y))));
  const options = bevel
    ? { depth, bevelEnabled: true, bevelThickness: bevel[0], bevelSize: bevel[1], bevelSegments: bevel[2] }
    : { depth, bevelEnabled: false };
  return new THREE.ExtrudeGeometry(shape, options).translate(0, 0, -depth / 2);
}

export function createControlConsole() {
  const root = new THREE.Group();
  root.name = 'ControlConsole';

  // Materials
  const bodyMat = new THREE.MeshStandardMaterial({ name: 'body', color: 0xd0d6de, roughness: 0.45, metalness: 0.3, flatShading: true });
  const darkMat = new THREE.MeshStandardMaterial({ name: 'dark', color: 0x2f343c, roughness: 0.6, metalness: 0.35, flatShading: true });
  const screenMat = new THREE.MeshStandardMaterial({ name: 'screen', color: 0x123447, roughness: 0.25, emissive: 0x36c6ff, emissiveIntensity: 0.42, flatShading: true });
  const glowMat = new THREE.MeshStandardMaterial({ name: 'glow', color: 0x36c6ff, roughness: 0.4, emissive: 0x36c6ff, emissiveIntensity: 1.2, flatShading: true });
  const uiMat = new THREE.MeshStandardMaterial({ name: 'ui', color: 0xe9fbff, roughness: 0.3, emissive: 0xbff3ff, emissiveIntensity: 1.2, flatShading: true });
  const buttonMat = new THREE.MeshStandardMaterial({ name: 'button', color: 0xff8a3a, roughness: 0.4, emissive: 0xff8a3a, emissiveIntensity: 1.1, flatShading: true });
  const buttonBMat = new THREE.MeshStandardMaterial({ name: 'buttonB', color: 0x9bff5c, roughness: 0.4, emissive: 0x7dff3a, flatShading: true });

  // Shared geometries
  const boxGeo = new THREE.BoxGeometry(0.03, 0.62, 0.035);
  const boxGeo2 = new THREE.BoxGeometry(0.03, 0.9, 0.2);
  const boxGeo3 = new THREE.BoxGeometry(0.36, 0.02, 0.22);
  const boxGeo4 = new THREE.BoxGeometry(0.26, 0.02, 0.018);
  const boxGeo5 = new THREE.BoxGeometry(0.2, 0.02, 0.018);
  const boxGeo6 = new THREE.BoxGeometry(0.14, 0.02, 0.018);
  const boxGeo7 = new THREE.BoxGeometry(0.05, 0.035, 0.05);
  const boxGeo8 = new THREE.BoxGeometry(0.06, 0.02, 0.05);
  const boxGeo9 = new THREE.BoxGeometry(0.3, 0.022, 0.012);
  const boxGeo10 = new THREE.BoxGeometry(0.2, 0.022, 0.012);

  // Parts
  const desk = new THREE.Group();
  desk.name = 'desk';
  root.add(desk);
  const deskBody = new THREE.Mesh(extrude([[0.34, 0], [0.34, 0.08], [0.26, 0.13], [0.26, 0.74], [0.44, 0.86], [-0.1, 1.1], [-0.34, 1.1], [-0.34, 0]], 1.36, [], [0.02, 0.02, 1]), bodyMat);
  deskBody.name = 'deskBody';
  deskBody.position.set(0, 0.02, 0);
  deskBody.rotation.set(0, deg(-90), 0);
  desk.add(deskBody);
  const kickPlate = new THREE.Mesh(new THREE.BoxGeometry(1.34, 0.07, 0.02), darkMat);
  kickPlate.name = 'kickPlate';
  kickPlate.position.set(0, 0.06, 0.366);
  desk.add(kickPlate);
  const frontStrip = new THREE.Mesh(new THREE.BoxGeometry(1.2, 0.035, 0.03), glowMat);
  frontStrip.name = 'frontStrip';
  frontStrip.position.set(0, 0.64, 0.29);
  desk.add(frontStrip);
  const sideStripL = new THREE.Mesh(boxGeo, glowMat);
  sideStripL.name = 'sideStripL';
  sideStripL.position.set(0.708, 0.43, 0.2);
  desk.add(sideStripL);
  const sideVentL = new THREE.Mesh(boxGeo2, darkMat);
  sideVentL.name = 'sideVentL';
  sideVentL.position.set(0.708, 0.55, -0.22);
  desk.add(sideVentL);
  const sideStripR = new THREE.Mesh(boxGeo, glowMat);
  sideStripR.name = 'sideStripR';
  sideStripR.position.set(-0.708, 0.43, 0.2);
  desk.add(sideStripR);
  const sideVentR = new THREE.Mesh(boxGeo2, darkMat);
  sideVentR.name = 'sideVentR';
  sideVentR.position.set(-0.708, 0.55, -0.22);
  desk.add(sideVentR);
  const controlPanel = new THREE.Group();
  controlPanel.name = 'controlPanel';
  controlPanel.position.set(0, 1.0201, 0.1789);
  controlPanel.rotation.set(deg(23.9625), 0, 0);
  root.add(controlPanel);
  const panelInset = new THREE.Mesh(new THREE.BoxGeometry(1.24, 0.02, 0.5109), darkMat);
  panelInset.name = 'panelInset';
  panelInset.position.set(0, 0.005, 0);
  controlPanel.add(panelInset);
  const displayL = new THREE.Mesh(boxGeo3, screenMat);
  displayL.name = 'displayL';
  displayL.position.set(0.4, 0.02, -0.07);
  controlPanel.add(displayL);
  const box12 = new THREE.Mesh(boxGeo4, uiMat);
  box12.position.set(0.37, 0.026, -0.14);
  controlPanel.add(box12);
  const box13 = new THREE.Mesh(boxGeo5, uiMat);
  box13.position.set(0.4, 0.026, -0.09);
  controlPanel.add(box13);
  const box14 = new THREE.Mesh(boxGeo6, uiMat);
  box14.position.set(0.43, 0.026, -0.04);
  controlPanel.add(box14);
  const displayR = new THREE.Mesh(boxGeo3, screenMat);
  displayR.name = 'displayR';
  displayR.position.set(-0.4, 0.02, -0.07);
  controlPanel.add(displayR);
  const box16 = new THREE.Mesh(boxGeo4, uiMat);
  box16.position.set(-0.43, 0.026, -0.14);
  controlPanel.add(box16);
  const box17 = new THREE.Mesh(boxGeo5, uiMat);
  box17.position.set(-0.4, 0.026, -0.09);
  controlPanel.add(box17);
  const box18 = new THREE.Mesh(boxGeo6, uiMat);
  box18.position.set(-0.37, 0.026, -0.04);
  controlPanel.add(box18);
  const box19 = new THREE.Mesh(boxGeo7, buttonBMat);
  box19.position.set(-0.105, 0.025, -0.15);
  controlPanel.add(box19);
  const box20 = new THREE.Mesh(boxGeo7, bodyMat);
  box20.position.set(-0.035, 0.025, -0.15);
  controlPanel.add(box20);
  const box21 = new THREE.Mesh(boxGeo7, buttonMat);
  box21.position.set(0.035, 0.025, -0.15);
  controlPanel.add(box21);
  const box22 = new THREE.Mesh(boxGeo7, buttonBMat);
  box22.position.set(0.105, 0.025, -0.15);
  controlPanel.add(box22);
  const box23 = new THREE.Mesh(boxGeo7, buttonMat);
  box23.position.set(-0.105, 0.025, -0.075);
  controlPanel.add(box23);
  const box24 = new THREE.Mesh(boxGeo7, bodyMat);
  box24.position.set(-0.035, 0.025, -0.075);
  controlPanel.add(box24);
  const box25 = new THREE.Mesh(boxGeo7, buttonBMat);
  box25.position.set(0.035, 0.025, -0.075);
  controlPanel.add(box25);
  const box26 = new THREE.Mesh(boxGeo7, bodyMat);
  box26.position.set(0.105, 0.025, -0.075);
  controlPanel.add(box26);
  const box27 = new THREE.Mesh(boxGeo7, buttonMat);
  box27.position.set(-0.105, 0.025, 0);
  controlPanel.add(box27);
  const box28 = new THREE.Mesh(boxGeo7, buttonBMat);
  box28.position.set(-0.035, 0.025, 0);
  controlPanel.add(box28);
  const box29 = new THREE.Mesh(boxGeo7, buttonMat);
  box29.position.set(0.035, 0.025, 0);
  controlPanel.add(box29);
  const box30 = new THREE.Mesh(boxGeo7, bodyMat);
  box30.position.set(0.105, 0.025, 0);
  controlPanel.add(box30);
  const keyboard = new THREE.Mesh(new THREE.BoxGeometry(0.78, 0.02, 0.09), bodyMat);
  keyboard.name = 'keyboard';
  keyboard.position.set(-0.08, 0.02, 0.17);
  controlPanel.add(keyboard);
  const box32 = new THREE.Mesh(boxGeo8, darkMat);
  box32.position.set(-0.4, 0.034, 0.17);
  controlPanel.add(box32);
  const box33 = new THREE.Mesh(boxGeo8, darkMat);
  box33.position.set(-0.32, 0.034, 0.17);
  controlPanel.add(box33);
  const box34 = new THREE.Mesh(boxGeo8, darkMat);
  box34.position.set(-0.24, 0.034, 0.17);
  controlPanel.add(box34);
  const box35 = new THREE.Mesh(boxGeo8, darkMat);
  box35.position.set(-0.16, 0.034, 0.17);
  controlPanel.add(box35);
  const box36 = new THREE.Mesh(boxGeo8, buttonMat);
  box36.position.set(-0.08, 0.034, 0.17);
  controlPanel.add(box36);
  const box37 = new THREE.Mesh(boxGeo8, darkMat);
  box37.position.set(0, 0.034, 0.17);
  controlPanel.add(box37);
  const box38 = new THREE.Mesh(boxGeo8, darkMat);
  box38.position.set(0.08, 0.034, 0.17);
  controlPanel.add(box38);
  const box39 = new THREE.Mesh(boxGeo8, darkMat);
  box39.position.set(0.16, 0.034, 0.17);
  controlPanel.add(box39);
  const box40 = new THREE.Mesh(boxGeo8, darkMat);
  box40.position.set(0.24, 0.034, 0.17);
  controlPanel.add(box40);
  const joystickBase = new THREE.Mesh(new THREE.CylinderGeometry(0.05, 0.06, 0.03, 10), darkMat);
  joystickBase.name = 'joystickBase';
  joystickBase.position.set(0.48, 0.025, 0.14);
  controlPanel.add(joystickBase);
  const joystickStick = new THREE.Mesh(new THREE.CylinderGeometry(0.014, 0.014, 0.14, 6), bodyMat);
  joystickStick.name = 'joystickStick';
  joystickStick.position.set(0.48, 0.1, 0.14);
  controlPanel.add(joystickStick);
  const joystickKnob = new THREE.Mesh(new THREE.SphereGeometry(0.035, 8, 6), buttonMat);
  joystickKnob.name = 'joystickKnob';
  joystickKnob.position.set(0.48, 0.18, 0.14);
  controlPanel.add(joystickKnob);
  const monitor = new THREE.Group();
  monitor.name = 'monitor';
  monitor.position.set(0, 1.12, -0.22);
  root.add(monitor);
  const neck = new THREE.Mesh(new THREE.BoxGeometry(0.16, 0.22, 0.1), darkMat);
  neck.name = 'neck';
  neck.position.set(0, 0.06, -0.02);
  monitor.add(neck);
  const screenHousing = new THREE.Group();
  screenHousing.name = 'screenHousing';
  screenHousing.position.set(0, 0.12, 0);
  screenHousing.rotation.set(deg(-10), 0, 0);
  monitor.add(screenHousing);
  const bezel = new THREE.Mesh(new THREE.BoxGeometry(1.34, 0.6, 0.1), bodyMat);
  bezel.name = 'bezel';
  bezel.position.set(0, 0.3, 0);
  screenHousing.add(bezel);
  const mainScreen = new THREE.Mesh(new THREE.BoxGeometry(1.2, 0.48, 0.02), screenMat);
  mainScreen.name = 'mainScreen';
  mainScreen.position.set(0, 0.3, 0.055);
  screenHousing.add(mainScreen);
  const box49 = new THREE.Mesh(new THREE.BoxGeometry(0.05, 0.18, 0.012), uiMat);
  box49.position.set(-0.5, 0.21, 0.068);
  screenHousing.add(box49);
  const box50 = new THREE.Mesh(new THREE.BoxGeometry(0.05, 0.28, 0.012), uiMat);
  box50.position.set(-0.425, 0.26, 0.068);
  screenHousing.add(box50);
  const box51 = new THREE.Mesh(new THREE.BoxGeometry(0.05, 0.14, 0.012), uiMat);
  box51.position.set(-0.35, 0.19, 0.068);
  screenHousing.add(box51);
  const box52 = new THREE.Mesh(new THREE.BoxGeometry(0.05, 0.32, 0.012), uiMat);
  box52.position.set(-0.275, 0.28, 0.068);
  screenHousing.add(box52);
  const box53 = new THREE.Mesh(new THREE.BoxGeometry(0.05, 0.22, 0.012), uiMat);
  box53.position.set(-0.2, 0.23, 0.068);
  screenHousing.add(box53);
  const box54 = new THREE.Mesh(new THREE.BoxGeometry(0.05, 0.26, 0.012), uiMat);
  box54.position.set(-0.125, 0.25, 0.068);
  screenHousing.add(box54);
  const radarRing = new THREE.Mesh(new THREE.TorusGeometry(0.13, 0.012, 3, 24), uiMat);
  radarRing.name = 'radarRing';
  radarRing.position.set(0.38, 0.32, 0.068);
  screenHousing.add(radarRing);
  const torus56 = new THREE.Mesh(new THREE.TorusGeometry(0.06, 0.01, 3, 16), uiMat);
  torus56.position.set(0.38, 0.32, 0.068);
  screenHousing.add(torus56);
  const box57 = new THREE.Mesh(new THREE.BoxGeometry(0.13, 0.012, 0.012), uiMat);
  box57.position.set(0.44, 0.35, 0.07);
  box57.rotation.set(0, 0, deg(28));
  screenHousing.add(box57);
  const box58 = new THREE.Mesh(boxGeo9, buttonMat);
  box58.position.set(-0.05, 0.47, 0.068);
  screenHousing.add(box58);
  const box59 = new THREE.Mesh(boxGeo10, uiMat);
  box59.position.set(-0.1, 0.415, 0.068);
  screenHousing.add(box59);
  const box60 = new THREE.Mesh(boxGeo9, uiMat);
  box60.position.set(-0.05, 0.36, 0.068);
  screenHousing.add(box60);
  const box61 = new THREE.Mesh(boxGeo10, uiMat);
  box61.position.set(-0.1, 0.305, 0.068);
  screenHousing.add(box61);
  const topLight = new THREE.Mesh(new THREE.BoxGeometry(1.34, 0.04, 0.04), glowMat);
  topLight.name = 'topLight';
  topLight.position.set(0, 0.6, 0.03);
  screenHousing.add(topLight);

  root.traverse((o) => {
    if (o.isMesh) {
      o.castShadow = true;
      o.receiveShadow = true;
    }
  });
  return root;
}

export default createControlConsole;

Оценки и комментарии

—
Оценок пока нет — будьте первым.
5
0
4
0
3
0
2
0
1
0

Войдите, чтобы ставить оценки и оставлять комментарии.

0 комментариев

Комментариев пока нет. Расскажите, как вы использовали эту модель или что можно улучшить.

Похожие модели

Та же категория или похожие теги