Codels
1.4K tris0.88 × 1.73 × 1.19 m

Use it in code

Remix in the editor
Self-contained ES module — only depends on three. Call the factory and add the group to your scene.
/**
 * Hologram Projector — Codels 3D model library
 * License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
 * Triangles: 1,432 · Size (W × H × D): 0.88 × 1.73 × 1.19 m
 *
 * Usage:
 *   import { createHologramProjector } from './hologram-projector.js';
 *   
 *   const model = createHologramProjector();
 *   model.position.set(0, 0, 0);
 *   scene.add(model);
 */
import * as THREE from 'three';

const deg = THREE.MathUtils.degToRad;

// Revolve a 2D profile [[radius, y], ...] around the Y axis.
function lathe(points, segments, phiStart = 0, phiLength = Math.PI * 2) {
  return new THREE.LatheGeometry(points.map(([x, y]) => new THREE.Vector2(x, y)), segments, phiStart, phiLength);
}

// Tube along a smooth curve through the given points.
function tube(path, radius, tubularSegments, radialSegments, closed = false) {
  const curve = new THREE.CatmullRomCurve3(path.map(([x, y, z]) => new THREE.Vector3(x, y, z)), closed);
  return new THREE.TubeGeometry(curve, tubularSegments, radius, radialSegments, closed);
}

export function createHologramProjector() {
  const root = new THREE.Group();
  root.name = 'HologramProjector';

  // Materials
  const shellMat = new THREE.MeshStandardMaterial({ name: 'shell', 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 metalMat = new THREE.MeshStandardMaterial({ name: 'metal', color: 0x8a929c, roughness: 0.4, metalness: 0.6, flatShading: true });
  const glowMat = new THREE.MeshStandardMaterial({ name: 'glow', color: 0x38d4ff, roughness: 0.4, emissive: 0x38d4ff, emissiveIntensity: 1.2, flatShading: true });
  const buttonMat = new THREE.MeshStandardMaterial({ name: 'button', color: 0xff8a3a, roughness: 0.4, emissive: 0xff8a3a, flatShading: true });
  const holoMat = new THREE.MeshStandardMaterial({ name: 'holo', color: 0x74e1ff, roughness: 0.2, emissive: 0x38d4ff, emissiveIntensity: 0.9, transparent: true, opacity: 0.45, flatShading: true });
  const holoLineMat = new THREE.MeshStandardMaterial({ name: 'holoLine', color: 0xa5ecff, roughness: 0.3, emissive: 0x7ee3ff, emissiveIntensity: 1.2, flatShading: true });
  const beamMat = new THREE.MeshStandardMaterial({ name: 'beam', color: 0x38d4ff, roughness: 0.3, emissive: 0x38d4ff, emissiveIntensity: 0.6, transparent: true, opacity: 0.16, flatShading: true });

  // Shared geometries
  const boxGeo = new THREE.BoxGeometry(0.05, 0.13, 0.02);
  const boxGeo2 = new THREE.BoxGeometry(0.05, 0.1, 0.02);
  const cylinderGeo = new THREE.CylinderGeometry(0.018, 0.03, 0.1803, 5);
  const octahedronGeo = new THREE.OctahedronGeometry(0.032, 0);
  const boxGeo3 = new THREE.BoxGeometry(0.03, 0.014, 0.03);
  const torusGeo = new THREE.TorusGeometry(0.2423, 0.006, 3, 12);
  const torusGeo2 = new THREE.TorusGeometry(0.285, 0.006, 3, 16);

  // Parts
  const plinth = new THREE.Mesh(new THREE.CylinderGeometry(0.44, 0.47, 0.08, 8), darkMat);
  plinth.name = 'plinth';
  plinth.position.set(0, 0.04, 0);
  plinth.rotation.set(0, deg(22.5), 0);
  root.add(plinth);
  const pedestal = new THREE.Mesh(lathe([[0, 0.08], [0.42, 0.08], [0.42, 0.15], [0.3, 0.22], [0.26, 0.27], [0.26, 0.6], [0.32, 0.66], [0.38, 0.73], [0.38, 0.8], [0.33, 0.83], [0.17, 0.78], [0, 0.78]], 8), shellMat);
  pedestal.name = 'pedestal';
  pedestal.rotation.set(0, deg(22.5), 0);
  root.add(pedestal);
  const waistBand = new THREE.Mesh(new THREE.CylinderGeometry(0.275, 0.275, 0.05, 8), darkMat);
  waistBand.name = 'waistBand';
  waistBand.position.set(0, 0.425, 0);
  waistBand.rotation.set(0, deg(22.5), 0);
  root.add(waistBand);
  const glowStrip1 = new THREE.Mesh(boxGeo, glowMat);
  glowStrip1.name = 'glowStrip1';
  glowStrip1.position.set(0, 0.53, 0.2462);
  root.add(glowStrip1);
  const box5 = new THREE.Mesh(boxGeo2, glowMat);
  box5.position.set(0, 0.32, 0.2462);
  root.add(box5);
  const glowStrip2 = new THREE.Mesh(boxGeo, glowMat);
  glowStrip2.name = 'glowStrip2';
  glowStrip2.position.set(0.2462, 0.53, 0);
  glowStrip2.rotation.set(0, deg(90), 0);
  root.add(glowStrip2);
  const box7 = new THREE.Mesh(boxGeo2, glowMat);
  box7.position.set(0.2462, 0.32, 0);
  box7.rotation.set(0, deg(90), 0);
  root.add(box7);
  const glowStrip3 = new THREE.Mesh(boxGeo, glowMat);
  glowStrip3.name = 'glowStrip3';
  glowStrip3.position.set(0, 0.53, -0.2462);
  glowStrip3.rotation.set(0, deg(180), 0);
  root.add(glowStrip3);
  const box9 = new THREE.Mesh(boxGeo2, glowMat);
  box9.position.set(0, 0.32, -0.2462);
  box9.rotation.set(0, deg(180), 0);
  root.add(box9);
  const glowStrip4 = new THREE.Mesh(boxGeo, glowMat);
  glowStrip4.name = 'glowStrip4';
  glowStrip4.position.set(-0.2462, 0.53, 0);
  glowStrip4.rotation.set(0, deg(270), 0);
  root.add(glowStrip4);
  const box11 = new THREE.Mesh(boxGeo2, glowMat);
  box11.position.set(-0.2462, 0.32, 0);
  box11.rotation.set(0, deg(270), 0);
  root.add(box11);
  const rimLight = new THREE.Mesh(new THREE.TorusGeometry(0.355, 0.012, 3, 8), glowMat);
  rimLight.name = 'rimLight';
  rimLight.position.set(0, 0.815, 0);
  rimLight.rotation.set(deg(90), 0, 0);
  root.add(rimLight);
  const lensMount = new THREE.Mesh(new THREE.CylinderGeometry(0.1, 0.12, 0.04, 8), metalMat);
  lensMount.name = 'lensMount';
  lensMount.position.set(0, 0.8, 0);
  root.add(lensMount);
  const lens = new THREE.Mesh(new THREE.CylinderGeometry(0.075, 0.075, 0.02, 8), glowMat);
  lens.name = 'lens';
  lens.position.set(0, 0.83, 0);
  root.add(lens);
  const prong1 = new THREE.Mesh(cylinderGeo, metalMat);
  prong1.name = 'prong1';
  prong1.position.set(0.2598, 0.885, 0.15);
  prong1.rotation.set(deg(-9.5821), deg(-1.4145), deg(16.7573));
  root.add(prong1);
  const prongTip1 = new THREE.Mesh(octahedronGeo, glowMat);
  prongTip1.name = 'prongTip1';
  prongTip1.position.set(0.2338, 0.985, 0.135);
  root.add(prongTip1);
  const prong2 = new THREE.Mesh(cylinderGeo, metalMat);
  prong2.name = 'prong2';
  prong2.position.set(0, 0.885, -0.3);
  prong2.rotation.set(deg(19.44), 0, 0);
  root.add(prong2);
  const prongTip2 = new THREE.Mesh(octahedronGeo, glowMat);
  prongTip2.name = 'prongTip2';
  prongTip2.position.set(0, 0.985, -0.27);
  root.add(prongTip2);
  const prong3 = new THREE.Mesh(cylinderGeo, metalMat);
  prong3.name = 'prong3';
  prong3.position.set(-0.2598, 0.885, 0.15);
  prong3.rotation.set(deg(-9.5821), deg(1.4145), deg(-16.7573));
  root.add(prong3);
  const prongTip3 = new THREE.Mesh(octahedronGeo, glowMat);
  prongTip3.name = 'prongTip3';
  prongTip3.position.set(-0.2338, 0.985, 0.135);
  root.add(prongTip3);
  const controlPad = new THREE.Group();
  controlPad.name = 'controlPad';
  controlPad.position.set(0, 0.135, 0.38);
  controlPad.rotation.set(deg(42), 0, 0);
  root.add(controlPad);
  const padBody = new THREE.Mesh(new THREE.BoxGeometry(0.24, 0.04, 0.1), darkMat);
  padBody.name = 'padBody';
  controlPad.add(padBody);
  const padScreen = new THREE.Mesh(new THREE.BoxGeometry(0.07, 0.012, 0.05), glowMat);
  padScreen.name = 'padScreen';
  padScreen.position.set(-0.06, 0.025, 0);
  controlPad.add(padScreen);
  const padButton1 = new THREE.Mesh(boxGeo3, buttonMat);
  padButton1.name = 'padButton1';
  padButton1.position.set(0.035, 0.025, 0);
  controlPad.add(padButton1);
  const padButton2 = new THREE.Mesh(boxGeo3, shellMat);
  padButton2.name = 'padButton2';
  padButton2.position.set(0.08, 0.025, 0);
  controlPad.add(padButton2);
  const cable = new THREE.Mesh(tube([[0, 0.12, -0.36], [0, 0.05, -0.5], [0.08, 0.022, -0.66], [0.22, 0.022, -0.74]], 0.022, 8, 4), darkMat);
  cable.name = 'cable';
  root.add(cable);
  const lightCone = new THREE.Mesh(new THREE.CylinderGeometry(0.36, 0.08, 0.9, 12, 1, true), beamMat);
  lightCone.name = 'lightCone';
  lightCone.position.set(0, 1.28, 0);
  root.add(lightCone);
  const hologram = new THREE.Group();
  hologram.name = 'hologram';
  hologram.position.set(0, 1.35, 0);
  root.add(hologram);
  const globe = new THREE.Mesh(new THREE.IcosahedronGeometry(0.27, 1), holoMat);
  globe.name = 'globe';
  hologram.add(globe);
  const equator = new THREE.Mesh(new THREE.TorusGeometry(0.285, 0.007, 3, 16), holoLineMat);
  equator.name = 'equator';
  equator.rotation.set(deg(90), 0, 0);
  hologram.add(equator);
  const torus31 = new THREE.Mesh(torusGeo, holoLineMat);
  torus31.position.set(0, -0.15, 0);
  torus31.rotation.set(deg(90), 0, 0);
  hologram.add(torus31);
  const torus32 = new THREE.Mesh(torusGeo, holoLineMat);
  torus32.position.set(0, 0.15, 0);
  torus32.rotation.set(deg(90), 0, 0);
  hologram.add(torus32);
  const meridian = new THREE.Mesh(torusGeo2, holoLineMat);
  meridian.name = 'meridian';
  meridian.rotation.set(0, deg(30), 0);
  hologram.add(meridian);
  const torus34 = new THREE.Mesh(torusGeo2, holoLineMat);
  torus34.rotation.set(0, deg(120), 0);
  hologram.add(torus34);
  const orbit = new THREE.Mesh(new THREE.TorusGeometry(0.42, 0.006, 3, 20), holoLineMat);
  orbit.name = 'orbit';
  orbit.rotation.set(deg(74), 0, deg(18));
  hologram.add(orbit);
  const moon = new THREE.Mesh(new THREE.SphereGeometry(0.045, 6, 4), holoLineMat);
  moon.name = 'moon';
  moon.position.set(0.4, 0.12, 0.05);
  hologram.add(moon);
  const projectionRing = new THREE.Mesh(new THREE.TorusGeometry(0.3, 0.008, 3, 16), holoLineMat);
  projectionRing.name = 'projectionRing';
  projectionRing.position.set(0, 1.05, 0);
  projectionRing.rotation.set(deg(90), 0, 0);
  root.add(projectionRing);

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

export default createHologramProjector;

Ratings & comments

—
No ratings yet — be the first.
5
0
4
0
3
0
2
0
1
0

Sign in to rate and comment.

0 comments

No comments yet. Share how you used this model or what could be better.

Related models

Same category or similar tags