1.4K tris0.88 × 1.73 × 1.19 m
Use it in code
Remix in the editorhologram-projector.js · 217 lines
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
0 comments
No comments yet. Share how you used this model or what could be better.
Related models
Same category or similar tags









