1.1K tris1.45 × 1.86 × 0.84 m
Use it in code
Remix in the editorcontrol-console.js · 276 lines
Self-contained ES module — only depends on three. Call the factory and add the group to your scene.
/**
* 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;
Ratings & comments
0 comments
No comments yet. Share how you used this model or what could be better.
Related models
Same category or similar tags









