1.4K tris3.64 × 2.71 × 3.93 m
Use it in code
Remix in the editorteleporter-pad.js · 300 lines
Self-contained ES module — only depends on three. Call the factory and add the group to your scene.
/**
* Teleporter Pad — Codels 3D model library
* License: CC0-1.0 · Units: meters · Y-up · Front: +Z · Origin: center of the base (y = 0)
* Triangles: 1,448 · Size (W × H × D): 3.64 × 2.71 × 3.93 m
*
* Usage:
* import { createTeleporterPad } from './teleporter-pad.js';
*
* const model = createTeleporterPad();
* 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);
}
// 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 createTeleporterPad() {
const root = new THREE.Group();
root.name = 'TeleporterPad';
// 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: 0x2b3038, roughness: 0.55, metalness: 0.4, flatShading: true });
const metalMat = new THREE.MeshStandardMaterial({ name: 'metal', color: 0x7d858f, roughness: 0.4, metalness: 0.6, flatShading: true });
const glowMat = new THREE.MeshStandardMaterial({ name: 'glow', color: 0x4fd8ff, roughness: 0.4, emissive: 0x4fd8ff, emissiveIntensity: 1.3, flatShading: true });
const glowDimMat = new THREE.MeshStandardMaterial({ name: 'glowDim', color: 0x3a8fac, roughness: 0.4, emissive: 0x4fd8ff, emissiveIntensity: 0.6, flatShading: true });
const crystalMat = new THREE.MeshStandardMaterial({ name: 'crystal', color: 0x95e8ff, roughness: 0.2, emissive: 0x4fd8ff, emissiveIntensity: 1.2, flatShading: true });
const beamMat = new THREE.MeshStandardMaterial({ name: 'beam', color: 0x4fd8ff, roughness: 0.3, emissive: 0x4fd8ff, emissiveIntensity: 0.6, transparent: true, opacity: 0.18, flatShading: true });
const ringLightMat = new THREE.MeshStandardMaterial({ name: 'ringLight', color: 0xa7ecff, roughness: 0.3, emissive: 0x84e4ff, emissiveIntensity: 1.2, flatShading: true });
// Shared geometries
const boxGeo = new THREE.BoxGeometry(0.03, 0.02, 0.16);
const boxGeo2 = new THREE.BoxGeometry(0.4, 0.12, 0.34);
const extrudeGeo = extrude([[-0.16, 0], [0.14, 0], [0.1, 0.85], [0.3, 1.45], [0.4, 1.66], [0.26, 1.72], [-0.04, 1.25], [-0.12, 0.85]], 0.18);
const extrudeGeo2 = extrude([[-0.074, 0.14], [0.046, 0.14], [0.03, 0.871], [0.11, 1.387], [0.15, 1.5676], [0.094, 1.6192], [-0.026, 1.215], [-0.058, 0.871]], 0.22);
const boxGeo3 = new THREE.BoxGeometry(0.03, 0.62, 0.1);
const octahedronGeo = new THREE.OctahedronGeometry(0.14, 0);
const cylinderGeo = new THREE.CylinderGeometry(0.07, 0.09, 0.1, 6);
// Parts
const platform = new THREE.Mesh(lathe([[0, 0], [1.82, 0], [1.8, 0.06], [1.68, 0.16], [1.55, 0.16], [1.52, 0.28], [0, 0.28]], 20), shellMat);
platform.name = 'platform';
root.add(platform);
const transmissionDisc = new THREE.Mesh(new THREE.CylinderGeometry(1.44, 1.46, 0.03, 20), darkMat);
transmissionDisc.name = 'transmissionDisc';
transmissionDisc.position.set(0, 0.29, 0);
root.add(transmissionDisc);
const discRim = new THREE.Mesh(new THREE.CylinderGeometry(1.54, 1.54, 0.04, 20, 1, true), darkMat);
discRim.name = 'discRim';
discRim.position.set(0, 0.29, 0);
root.add(discRim);
const ring1 = new THREE.Mesh(new THREE.RingGeometry(1.26, 1.38, 20), glowMat);
ring1.name = 'ring1';
ring1.position.set(0, 0.31, 0);
ring1.rotation.set(deg(-90), 0, 0);
root.add(ring1);
const ring2 = new THREE.Mesh(new THREE.RingGeometry(0.84, 0.93, 20), glowDimMat);
ring2.name = 'ring2';
ring2.position.set(0, 0.31, 0);
ring2.rotation.set(deg(-90), 0, 0);
root.add(ring2);
const ring3 = new THREE.Mesh(new THREE.RingGeometry(0.45, 0.525, 20), glowMat);
ring3.name = 'ring3';
ring3.position.set(0, 0.31, 0);
ring3.rotation.set(deg(-90), 0, 0);
root.add(ring3);
const emitter = new THREE.Mesh(new THREE.CylinderGeometry(0.27, 0.3, 0.05, 6), glowMat);
emitter.name = 'emitter';
emitter.position.set(0, 0.325, 0);
root.add(emitter);
const emitterCore = new THREE.Mesh(new THREE.CylinderGeometry(0.15, 0.15, 0.06, 6), darkMat);
emitterCore.name = 'emitterCore';
emitterCore.position.set(0, 0.34, 0);
root.add(emitterCore);
const box9 = new THREE.Mesh(boxGeo, darkMat);
box9.position.set(0.4975, 0.165, 1.5312);
box9.rotation.set(0, deg(18), 0);
root.add(box9);
const box10 = new THREE.Mesh(boxGeo, darkMat);
box10.position.set(1.3025, 0.165, 0.9463);
box10.rotation.set(0, deg(54), 0);
root.add(box10);
const box11 = new THREE.Mesh(boxGeo, darkMat);
box11.position.set(1.61, 0.165, 0);
box11.rotation.set(0, deg(90), 0);
root.add(box11);
const box12 = new THREE.Mesh(boxGeo, darkMat);
box12.position.set(1.3025, 0.165, -0.9463);
box12.rotation.set(0, deg(126), 0);
root.add(box12);
const box13 = new THREE.Mesh(boxGeo, darkMat);
box13.position.set(0.4975, 0.165, -1.5312);
box13.rotation.set(0, deg(162), 0);
root.add(box13);
const box14 = new THREE.Mesh(boxGeo, darkMat);
box14.position.set(-0.4975, 0.165, -1.5312);
box14.rotation.set(0, deg(198), 0);
root.add(box14);
const box15 = new THREE.Mesh(boxGeo, darkMat);
box15.position.set(-1.3025, 0.165, -0.9463);
box15.rotation.set(0, deg(234), 0);
root.add(box15);
const box16 = new THREE.Mesh(boxGeo, darkMat);
box16.position.set(-1.61, 0.165, 0);
box16.rotation.set(0, deg(270), 0);
root.add(box16);
const box17 = new THREE.Mesh(boxGeo, darkMat);
box17.position.set(-1.3025, 0.165, 0.9463);
box17.rotation.set(0, deg(306), 0);
root.add(box17);
const box18 = new THREE.Mesh(boxGeo, darkMat);
box18.position.set(-0.4975, 0.165, 1.5312);
box18.rotation.set(0, deg(342), 0);
root.add(box18);
const step = new THREE.Mesh(new THREE.BoxGeometry(0.9, 0.14, 0.36), shellMat);
step.name = 'step';
step.position.set(0, 0.07, 1.9);
root.add(step);
const stepLight = new THREE.Mesh(new THREE.BoxGeometry(0.7, 0.02, 0.04), glowMat);
stepLight.name = 'stepLight';
stepLight.position.set(0, 0.13, 2.09);
root.add(stepLight);
const pylon1 = new THREE.Group();
pylon1.name = 'pylon1';
pylon1.position.set(1.1314, 0.16, 1.1314);
pylon1.rotation.set(0, deg(135), 0);
root.add(pylon1);
const foot = new THREE.Mesh(boxGeo2, darkMat);
foot.name = 'foot';
foot.position.set(0, 0.06, 0);
pylon1.add(foot);
const fin = new THREE.Mesh(extrudeGeo, shellMat);
fin.name = 'fin';
fin.position.set(0, 0.1, 0);
pylon1.add(fin);
const spine = new THREE.Mesh(extrudeGeo2, darkMat);
spine.name = 'spine';
spine.position.set(0, 0.08, 0);
pylon1.add(spine);
const strip = new THREE.Mesh(boxGeo3, glowMat);
strip.name = 'strip';
strip.position.set(0.115, 0.55, 0);
strip.rotation.set(0, 0, deg(2.7));
pylon1.add(strip);
const crystal = new THREE.Mesh(octahedronGeo, crystalMat);
crystal.name = 'crystal';
crystal.position.set(0.47, 1.8, 0);
crystal.rotation.set(0, 0, deg(-62));
crystal.scale.set(1, 1.7, 1);
pylon1.add(crystal);
const crystalMount = new THREE.Mesh(cylinderGeo, metalMat);
crystalMount.name = 'crystalMount';
crystalMount.position.set(0.36, 1.74, 0);
crystalMount.rotation.set(0, 0, deg(-62));
pylon1.add(crystalMount);
const pylon2 = new THREE.Group();
pylon2.name = 'pylon2';
pylon2.position.set(1.1314, 0.16, -1.1314);
pylon2.rotation.set(0, deg(225), 0);
root.add(pylon2);
const foot2 = new THREE.Mesh(boxGeo2, darkMat);
foot2.name = 'foot';
foot2.position.set(0, 0.06, 0);
pylon2.add(foot2);
const fin2 = new THREE.Mesh(extrudeGeo, shellMat);
fin2.name = 'fin';
fin2.position.set(0, 0.1, 0);
pylon2.add(fin2);
const spine2 = new THREE.Mesh(extrudeGeo2, darkMat);
spine2.name = 'spine';
spine2.position.set(0, 0.08, 0);
pylon2.add(spine2);
const strip2 = new THREE.Mesh(boxGeo3, glowMat);
strip2.name = 'strip';
strip2.position.set(0.115, 0.55, 0);
strip2.rotation.set(0, 0, deg(2.7));
pylon2.add(strip2);
const crystal2 = new THREE.Mesh(octahedronGeo, crystalMat);
crystal2.name = 'crystal';
crystal2.position.set(0.47, 1.8, 0);
crystal2.rotation.set(0, 0, deg(-62));
crystal2.scale.set(1, 1.7, 1);
pylon2.add(crystal2);
const crystalMount2 = new THREE.Mesh(cylinderGeo, metalMat);
crystalMount2.name = 'crystalMount';
crystalMount2.position.set(0.36, 1.74, 0);
crystalMount2.rotation.set(0, 0, deg(-62));
pylon2.add(crystalMount2);
const pylon3 = new THREE.Group();
pylon3.name = 'pylon3';
pylon3.position.set(-1.1314, 0.16, -1.1314);
pylon3.rotation.set(0, deg(315), 0);
root.add(pylon3);
const foot3 = new THREE.Mesh(boxGeo2, darkMat);
foot3.name = 'foot';
foot3.position.set(0, 0.06, 0);
pylon3.add(foot3);
const fin3 = new THREE.Mesh(extrudeGeo, shellMat);
fin3.name = 'fin';
fin3.position.set(0, 0.1, 0);
pylon3.add(fin3);
const spine3 = new THREE.Mesh(extrudeGeo2, darkMat);
spine3.name = 'spine';
spine3.position.set(0, 0.08, 0);
pylon3.add(spine3);
const strip3 = new THREE.Mesh(boxGeo3, glowMat);
strip3.name = 'strip';
strip3.position.set(0.115, 0.55, 0);
strip3.rotation.set(0, 0, deg(2.7));
pylon3.add(strip3);
const crystal3 = new THREE.Mesh(octahedronGeo, crystalMat);
crystal3.name = 'crystal';
crystal3.position.set(0.47, 1.8, 0);
crystal3.rotation.set(0, 0, deg(-62));
crystal3.scale.set(1, 1.7, 1);
pylon3.add(crystal3);
const crystalMount3 = new THREE.Mesh(cylinderGeo, metalMat);
crystalMount3.name = 'crystalMount';
crystalMount3.position.set(0.36, 1.74, 0);
crystalMount3.rotation.set(0, 0, deg(-62));
pylon3.add(crystalMount3);
const pylon4 = new THREE.Group();
pylon4.name = 'pylon4';
pylon4.position.set(-1.1314, 0.16, 1.1314);
pylon4.rotation.set(0, deg(405), 0);
root.add(pylon4);
const foot4 = new THREE.Mesh(boxGeo2, darkMat);
foot4.name = 'foot';
foot4.position.set(0, 0.06, 0);
pylon4.add(foot4);
const fin4 = new THREE.Mesh(extrudeGeo, shellMat);
fin4.name = 'fin';
fin4.position.set(0, 0.1, 0);
pylon4.add(fin4);
const spine4 = new THREE.Mesh(extrudeGeo2, darkMat);
spine4.name = 'spine';
spine4.position.set(0, 0.08, 0);
pylon4.add(spine4);
const strip4 = new THREE.Mesh(boxGeo3, glowMat);
strip4.name = 'strip';
strip4.position.set(0.115, 0.55, 0);
strip4.rotation.set(0, 0, deg(2.7));
pylon4.add(strip4);
const crystal4 = new THREE.Mesh(octahedronGeo, crystalMat);
crystal4.name = 'crystal';
crystal4.position.set(0.47, 1.8, 0);
crystal4.rotation.set(0, 0, deg(-62));
crystal4.scale.set(1, 1.7, 1);
pylon4.add(crystal4);
const crystalMount4 = new THREE.Mesh(cylinderGeo, metalMat);
crystalMount4.name = 'crystalMount';
crystalMount4.position.set(0.36, 1.74, 0);
crystalMount4.rotation.set(0, 0, deg(-62));
pylon4.add(crystalMount4);
const energyColumn = new THREE.Mesh(new THREE.CylinderGeometry(1.23, 1.23, 2.4, 20, 1, true), beamMat);
energyColumn.name = 'energyColumn';
energyColumn.position.set(0, 1.51, 0);
root.add(energyColumn);
const floatRing1 = new THREE.Mesh(new THREE.TorusGeometry(1.17, 0.018, 3, 16), ringLightMat);
floatRing1.name = 'floatRing1';
floatRing1.position.set(0, 0.98, 0);
floatRing1.rotation.set(deg(90), 0, 0);
root.add(floatRing1);
const floatRing2 = new THREE.Mesh(new THREE.TorusGeometry(1.08, 0.018, 3, 16), ringLightMat);
floatRing2.name = 'floatRing2';
floatRing2.position.set(0, 1.63, 0);
floatRing2.rotation.set(deg(90), 0, 0);
root.add(floatRing2);
const floatRing3 = new THREE.Mesh(new THREE.TorusGeometry(0.99, 0.018, 3, 16), ringLightMat);
floatRing3.name = 'floatRing3';
floatRing3.position.set(0, 2.28, 0);
floatRing3.rotation.set(deg(90), 0, 0);
root.add(floatRing3);
root.traverse((o) => {
if (o.isMesh) {
o.castShadow = true;
o.receiveShadow = true;
}
});
return root;
}
export default createTeleporterPad;
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









