Public
Edited
Apr 12, 2023
Fork of Three.js
2 forks
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
options = {
const toggleHelpers = checkboxes.includes("ShowHelpers");
const toggleAnimation = checkboxes.includes("Animation");
return {
toggleHelpers,
toggleAnimation
};
}
Insert cell
keyword = {
let keyword = selectAtlas.slice(0, -2);
keyword = keyword.split(",")[0];
keyword = keyword.split("(")[0];
while (keyword.endsWith(" ")) {
keyword = keyword.slice(0, -1);
}
keyword = keyword.replaceAll(" ", "-");
keyword = keyword.toLowerCase();
return keyword;
}
Insert cell
// {
// let list = document.getElementById("webgl").childNodes;
// for (const c of list) {
// document.getElementById("webgl").removeChild(c);
// }
// document.getElementById("webgl").appendChild(renderer.domElement);
// // document.getElementById("webgl").appendChild(stats.domElement);
// return md`## Add renderer to webgl`;
// }
Insert cell
// Continuously updates
{
while (true) {
cube.rotation.z += 0.03;
cube.rotation.y += 0.02;

if (options.toggleAnimation) {
brain.rotation.y += 0.01;
atlas.rotation.y = brain.rotation.y;
spheres.rotation.y = brain.rotation.y;

if (options.toggleHelpers) {
helpBrain.update();
helpAtlas.update();
}
}

renderer.render(scene, camera);
// stats.update();
yield null;
}
}
Insert cell
// {
// function loop() {
// cube.rotation.z += 0.03;
// cube.rotation.y += 0.02;

// if (options.toggleAnimation) {
// brain.rotation.y += 0.01;
// atlas.rotation.y = brain.rotation.y;
// spheres.rotation.y = brain.rotation.y;

// if (options.toggleHelpers) {
// helpBrain.update();
// helpAtlas.update();
// }
// }

// renderer.render(scene, camera);

// requestAnimationFrame(loop);
// }
// loop();
// }
Insert cell
## Meshes
Insert cell
cube = {
const material = new THREE.MeshNormalMaterial();
const geometry = new THREE.BoxGeometry(10, 10, 10);
const cube = new THREE.Mesh(geometry, material);
cube.position.y = 0;
cube.position.x = 100;
cube.position.z = 100;
return cube;
}
Insert cell
spheres = {
const table = atlasTable;

const material = new THREE.MeshNormalMaterial();

const mkSphere = (e) => {
const { x, y, z } = e;
const geometry = new THREE.SphereGeometry(1);
geometry.translate(-45, -50 * 0, -45);
const sphere = new THREE.Mesh(geometry, material);
sphere.position.x = parseInt(x);
sphere.position.y = parseInt(z);
sphere.position.z = parseInt(y);
return sphere;
};

const spheres = table.map(mkSphere);

const group = new THREE.Group();

spheres.map((e) => group.add(e));
// group.translate(-45, -50 * 0, -45);

// group.add(spheres[0]);

return group;
}
Insert cell
{
// for (const sphere of spheres) {
// scene.add(sphere);
// }
scene.add(spheres);
}
Insert cell
brainGeometry = {
const vertices = mkVertices(brainModel);
const geometry = mkGeometry(vertices);
// geometry.computeVertexNormals();
geometry.translate(-45, -50 * 0, -45);
return geometry;
}
Insert cell
brain = {
const material = new THREE.MeshPhongMaterial({
color: "hsl(0,100%,100%)",
opacity: 0.3,
transparent: true,
depthWrite: false,
side: THREE.DoubleSide
});

const mesh = new THREE.Mesh(brainGeometry, material);

return mesh;
}
Insert cell
helpBrain = {
const help = new THREE.BoxHelper(brain);
return help;
}
Insert cell
atlasGeometry = {
const vertices = mkVertices(atlasModel);
const geometry = mkGeometry(vertices);
// geometry.computeVertexNormals();
geometry.translate(-45, -50 * 0, -45);
return geometry;
}
Insert cell
atlas = {
const material = new THREE.MeshPhongMaterial({
color: atlasColor,
opacity: 0.3,
transparent: true,
depthWrite: false,
side: THREE.DoubleSide
});

const mesh = new THREE.Mesh(atlasGeometry, material);

mesh.rotation.y = brain.rotation.y;

return mesh;
}
Insert cell
helpAtlas = {
const help = new THREE.BoxHelper(atlas);
return help;
}
Insert cell
{
scene.add(brain);

scene.add(atlas);

if (options.toggleHelpers) {
scene.add(helpBrain);
scene.add(helpAtlas);
}

return md`### Brain`;
}
Insert cell
{
scene.add(cube);
return md`### Cube`;
}
Insert cell
{
let color = 0xffffff;
const intensity = 1;
const light = new THREE.AmbientLight(color, intensity);

scene.add(light);

color = 0x00ff00;
const light1 = new THREE.SpotLight(color);
light1.position.y = 100;
scene.add(light1);

if (options.toggleHelpers) {
const helper1 = new THREE.SpotLightHelper(light1);
scene.add(helper1);
}

return md`### Lights`;
}
Insert cell
{
// GRID HELPER
var size = 200;
var divisions = 8;
const helper = new THREE.GridHelper(size, divisions);
// helper.position.y = -70;
scene.add(helper);

return md`### Floor grid`;
}
Insert cell
## Scene & Camera & Render
Insert cell
stats = {
const stats = new Stats();
stats.domElement.style.left = "100px";
return stats;
}
Insert cell
scene = {
redrawButton;
atlasColor;
checkboxes;
selectAtlas;
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x001b42);
return scene;
}
Insert cell
height = width / 2
Insert cell
camera = {
const fov = 45;
const aspect = width / height;
const near = 1;
const far = 1000;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.set(150, 200, -150);
camera.lookAt(new THREE.Vector3(0, 0, 0));
return camera;
}
Insert cell
renderer = {
const renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(width, height);
renderer.setPixelRatio(devicePixelRatio);
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.addEventListener("change", () => renderer.render(scene, camera));
invalidation.then(() => (controls.dispose(), renderer.dispose()));
return renderer;
}
Insert cell
## Mesh models
Insert cell
brainModel = mkBrainModel()
Insert cell
atlasModel = mkSelectAtlasModel()
Insert cell
## Toolbox
Insert cell
mkGeometry = (vertices) => {
const positions = [];
const normals = [];
const uvs = [];
for (const vertex of vertices) {
positions.push(...vertex.pos);
normals.push(...vertex.norm);
uvs.push(...vertex.uv);
}

const geometry = new THREE.BufferGeometry();
const positionNumComponents = 3;
const normalNumComponents = 3;
const uvNumComponents = 2;
const positionAttr = new THREE.BufferAttribute(
new Float32Array(positions),
positionNumComponents
);
const normalAttr = new THREE.BufferAttribute(
new Float32Array(normals),
normalNumComponents
);
const uvAttr = new THREE.BufferAttribute(
new Float32Array(uvs),
uvNumComponents
);

geometry.setAttribute("position", positionAttr);
geometry.setAttribute("normal", normalAttr);
geometry.setAttribute("uv", uvAttr);

return geometry;
}
Insert cell
mkVertices = (meshModel) => {
const { positions, cells } = meshModel;
const norms = normals(cells, positions);

const vertices = [];

const uv3 = [
[0, 0],
[0, 1],
[1, 0]
];

let pos, norm, uv;
for (const cell of cells) {
// vertices.push(cell);
for (let i = 0; i < 3; i++) {
pos = positions[cell[i]];
norm = norms[cell[i]];
uv = uv3[i];
vertices.push({ pos, norm, uv });
}
}

return vertices;
}
Insert cell
mkSelectAtlasModel = () => {
const atlas = atlasTable.filter((e) => e.name === selectAtlas);
const value = parseInt(atlas[0].idx);
const _cells = rawCellsAll.filter((e) => parseInt(e.idx) === value);
const _vertices = rawVerticesAll.filter((e) => parseInt(e.idx) === value);

const cells = _cells.map((e) => [
parseInt(e.v2),
parseInt(e.v1),
parseInt(e.v0)
]);

const positions = _vertices.map((e) => [
parseFloat(e.z),
parseFloat(e.x),
parseFloat(e.y)
]);

const colors = _cells.map((e) => [0.8, 0.2, 0.2, 0.5]);

return { cells, positions, colors };
}
Insert cell
mkBrainModel = () => {
const _cells = rawCells0;
const _vertices = rawVertices0;

const cells = _cells.map((e) => [
parseInt(e.v2),
parseInt(e.v1),
parseInt(e.v0)
]);

const positions = _vertices.map((e) => [
parseFloat(e.z),
parseFloat(e.x),
parseFloat(e.y)
]);

const colors = _cells.map((e) => [0.4, 0.4, 0.4, 0.5]);

return { cells, positions, colors };

return bunny;
}
Insert cell
## Requirements
Insert cell
normals = (await import("https://cdn.skypack.dev/angle-normals@1.0.0")).default
Insert cell
THREE = {
const THREE = (window.THREE = await require("three@0.130.0/build/three.min.js"));
await require("three@0.130.0/examples/js/controls/OrbitControls.js").catch(
() => {}
);
await require("three@0.130.0/examples/js/libs/stats.min.js").catch(() => {});
return THREE;
}
Insert cell
## Resources
Insert cell
bunny = (await import("https://cdn.skypack.dev/bunny@1.0.1")).default
Insert cell
atlasTable = await FileAttachment("atlas_table.csv").csv()
Insert cell
rawCellsAll = await FileAttachment("cells-all.csv").csv()
Insert cell
rawVerticesAll = await FileAttachment("vertices-all.csv").csv()
Insert cell
rawCells0 = await FileAttachment("cells-0-1.csv").csv()
Insert cell
rawVertices0 = await FileAttachment("vertices-0-1.csv").csv()
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