Public
Edited
May 26, 2024
1 star
Insert cell
Insert cell
renderer.domElement;
Insert cell
airplanes = {
return new Array(80).fill(null).map(() => getAirplane());
}
Insert cell
airplanes.forEach(airplane => scene.add(airplane.mesh));
Insert cell
getAirplane = () => new Airplane(
Math.PI + 2 * (Math.random() - 0.5) * Math.PI,
Math.PI + 2 * (Math.random() - 0.5) * Math.PI,
Math.PI + 2 * (Math.random() - 0.5) * Math.PI,
(Math.random() - 0.5) * 0.002,
(Math.random() - 0.5) * 0.002,
(Math.random() - 0.5) * 0.002,
1 + (Math.random() - 0.5)
);
Insert cell
{
let time = Date.now();
while(true) { // tick
const currentTime = Date.now();
const deltaTime = currentTime - time;
time = currentTime;
airplanes.forEach(airplane => airplane.tick(deltaTime));
renderer.render(scene, camera);

yield null;
}
}
Insert cell
class Airplane {
constructor(x, y, z, dx, dy, dz, velocity) {
this.startDirection = new THREE.Vector3(0, -1, 0);
this.move = new THREE.Vector3();
this.mesh = new THREE.Mesh(geometry, material);
this.mesh.rotation.set(x ,y, z);
this.velocity = velocity;
this.deltas = {
dx,
dy,
dz
}
}
tick(deltaTime) {
this.mesh.rotation.x += this.deltas.dx * deltaTime;
this.mesh.rotation.y += this.deltas.dy * deltaTime;
this.mesh.rotation.z += this.deltas.dz * deltaTime;
this.move.set(...this.startDirection.toArray());
this.move.applyEuler(this.mesh.rotation);
this.move.multiplyScalar(this.velocity);
this.mesh.position.add(this.move);
}
}
Insert cell
height = 400
Insert cell
mesh = new THREE.Mesh(geometry, material)
Insert cell
geometry = {
const vertices = [
{ pos: [ 0, -4, -0.5 ] },
{ pos: [ 2.5, 4, 1.5 ] },
{ pos: [ 0.5, 4, 0.5 ] },
{ pos: [ 0, -4, -0.5 ] },
{ pos: [ 0.5, 4, 0.5 ] },
{ pos: [ 0, 4, -1.5 ] },
{ pos: [ 0, -4, -0.5 ] },
{ pos: [ 0, 4, -1.5 ] },
{ pos: [ -0.5, 4, 0.5 ] },
{ pos: [ 0, -4, -0.5 ] },
{ pos: [ -0.5, 4, 0.5 ] },
{ pos: [ -2.5, 4, 1.5 ] }
];

const positions = [];

for (const vertex of vertices) {
positions.push(...vertex.pos);
}

const geometry = new THREE.BufferGeometry();
const positionNumComponents = 3;
geometry.setAttribute(
'position',
new THREE.BufferAttribute(new Float32Array(positions), positionNumComponents));

geometry.computeVertexNormals();

return geometry;
}
Insert cell
material = {
const color = 0xe4eaf6;
const material = new THREE.MeshPhongMaterial({
side: THREE.DoubleSide,
color});
return material;
}
Insert cell
Insert cell
scene = {
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x405cb1);

scene.add(light);
scene.add(new THREE.HemisphereLight(
0xffffff,
0xffffff,
0.6
));

return scene;
}
Insert cell
camera = {
const fov = 75;
const aspect = width / height;
const near = 0.1;
const far = 2000;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.z = 240;
camera.lookAt(0, 0, 0);
return camera;
}
Insert cell
renderer = {
const renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(width, height);
renderer.setPixelRatio(devicePixelRatio);
invalidation.then(() => (renderer.dispose()));
return renderer;
}
Insert cell
THREE = {
const THREE = window.THREE = await require("three@0.130.0/build/three.min.js");
return THREE;
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more