Merge branch 'feature-faces' into temp-merge-faces
commit
7cc7331db1
|
@ -6,13 +6,15 @@ const HYPERPLANE = 2.0;
|
||||||
|
|
||||||
class FourDShape extends THREE.Group {
|
class FourDShape extends THREE.Group {
|
||||||
|
|
||||||
constructor(node_ms, link_ms, structure) {
|
constructor(node_ms, link_ms, face_ms, structure) {
|
||||||
super();
|
super();
|
||||||
this.node_ms = node_ms;
|
this.node_ms = node_ms;
|
||||||
this.link_ms = link_ms;
|
this.link_ms = link_ms;
|
||||||
|
this.face_ms = face_ms;
|
||||||
this.nodes4 = structure.nodes;
|
this.nodes4 = structure.nodes;
|
||||||
this.nodes3 = {};
|
this.nodes3 = {};
|
||||||
this.links = structure.links;
|
this.links = structure.links;
|
||||||
|
this.faces = ( "faces" in structure ) ? structure.faces : [];
|
||||||
this.node_size = structure.geometry.node_size;
|
this.node_size = structure.geometry.node_size;
|
||||||
this.link_size = structure.geometry.link_size;
|
this.link_size = structure.geometry.link_size;
|
||||||
this.node_scale = 1;
|
this.node_scale = 1;
|
||||||
|
@ -71,6 +73,32 @@ class FourDShape extends THREE.Group {
|
||||||
link.object.children[0].rotation.x = Math.PI / 2.0;
|
link.object.children[0].rotation.x = Math.PI / 2.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
setFaceGeometry(face, geometry) {
|
||||||
|
const values = [];
|
||||||
|
for( const f of face.nodes ) {
|
||||||
|
const v3 = this.nodes3[f].v3;
|
||||||
|
values.push(v3.x);
|
||||||
|
values.push(v3.y);
|
||||||
|
values.push(v3.z);
|
||||||
|
}
|
||||||
|
const v3 = this.nodes3[face.nodes[0]].v3;
|
||||||
|
values.push(v3.x);
|
||||||
|
values.push(v3.y);
|
||||||
|
values.push(v3.z);
|
||||||
|
const vertices = new Float32Array(values);
|
||||||
|
geometry.setAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
makeFace(material, face) {
|
||||||
|
const geometry = new THREE.BufferGeometry();
|
||||||
|
this.setFaceGeometry(face, geometry)
|
||||||
|
const mesh = new THREE.Mesh( geometry, material );
|
||||||
|
this.add(mesh);
|
||||||
|
return mesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fourDtoV3(x, y, z, w, rotations) {
|
fourDtoV3(x, y, z, w, rotations) {
|
||||||
const v4 = new THREE.Vector4(x, y, z, w);
|
const v4 = new THREE.Vector4(x, y, z, w);
|
||||||
for ( const m4 of rotations ) {
|
for ( const m4 of rotations ) {
|
||||||
|
@ -94,6 +122,10 @@ class FourDShape extends THREE.Group {
|
||||||
const material = this.getMaterial(l, this.link_ms);
|
const material = this.getMaterial(l, this.link_ms);
|
||||||
l.object = this.makeLink(material, l);
|
l.object = this.makeLink(material, l);
|
||||||
}
|
}
|
||||||
|
for( const f of this.faces ) {
|
||||||
|
const material = this.getMaterial(f, this.face_ms);
|
||||||
|
f.object = this.makeFace(material, f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -109,6 +141,10 @@ class FourDShape extends THREE.Group {
|
||||||
for( const l of this.links ) {
|
for( const l of this.links ) {
|
||||||
this.updateLink(l);
|
this.updateLink(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for( const f of this.faces ) {
|
||||||
|
this.setFaceGeometry(f, f.object.geometry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
16
main.js
16
main.js
|
@ -8,6 +8,8 @@ import { FourDGUI } from './gui.js';
|
||||||
import { FourDShape } from './fourDShape.js';
|
import { FourDShape } from './fourDShape.js';
|
||||||
import { get_colours } from './colours.js';
|
import { get_colours } from './colours.js';
|
||||||
|
|
||||||
|
const FACE_OPACITY = 0.3;
|
||||||
|
|
||||||
// scene, lights and camera
|
// scene, lights and camera
|
||||||
|
|
||||||
const scene = new THREE.Scene();
|
const scene = new THREE.Scene();
|
||||||
|
@ -40,6 +42,17 @@ const node_ms = node_colours.map((c) => new THREE.MeshStandardMaterial({color: c
|
||||||
|
|
||||||
const link_ms = [ material ];
|
const link_ms = [ material ];
|
||||||
|
|
||||||
|
|
||||||
|
const face_ms = [
|
||||||
|
new THREE.MeshLambertMaterial( { color: 0x44ff44 } )
|
||||||
|
];
|
||||||
|
|
||||||
|
for( const face_m of face_ms ) {
|
||||||
|
face_m.transparent = true;
|
||||||
|
face_m.opacity = FACE_OPACITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const STRUCTURES = {
|
const STRUCTURES = {
|
||||||
'5-cell': POLYTOPES.cell5(),
|
'5-cell': POLYTOPES.cell5(),
|
||||||
'16-cell': POLYTOPES.cell16(),
|
'16-cell': POLYTOPES.cell16(),
|
||||||
|
@ -55,7 +68,8 @@ function createShape(name) {
|
||||||
if( shape ) {
|
if( shape ) {
|
||||||
scene.remove(shape);
|
scene.remove(shape);
|
||||||
}
|
}
|
||||||
shape = new FourDShape(node_ms, link_ms, STRUCTURES[name]);
|
console.log(STRUCTURES[name]);
|
||||||
|
shape = new FourDShape(node_ms, link_ms, face_ms, STRUCTURES[name]);
|
||||||
scene.add(shape);
|
scene.add(shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
83
polytopes.js
83
polytopes.js
|
@ -170,9 +170,82 @@ export const cell24 = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// notes on coherent indexing
|
// face detection for the 120-cell
|
||||||
// see table in https://en.wikipedia.org/wiki/120-cell - maybe adapt the
|
|
||||||
// unit radius table
|
// NOTE: all of these return node ids, not nodes
|
||||||
|
|
||||||
|
// return all the links which connect to a node
|
||||||
|
|
||||||
|
function nodes_links(links, nodeid) {
|
||||||
|
return links.filter((l) => l.source === nodeid || l.target === nodeid);
|
||||||
|
}
|
||||||
|
|
||||||
|
// filter to remove a link to a given id from a set of links
|
||||||
|
|
||||||
|
function not_to_this(link, nodeid) {
|
||||||
|
return !(link.source === nodeid || link.target === nodeid);
|
||||||
|
}
|
||||||
|
|
||||||
|
// given nodes n1, n2, return all neighbours of n2 which are not n1
|
||||||
|
|
||||||
|
function unmutuals(links, n1id, n2id) {
|
||||||
|
const nlinks = nodes_links(links, n2id).filter((l) => not_to_this(l, n1id));
|
||||||
|
return nlinks.map((l) => {
|
||||||
|
if( l.source === n2id ) {
|
||||||
|
return l.target;
|
||||||
|
} else {
|
||||||
|
return l.source;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function fingerprint(ids) {
|
||||||
|
const sids = [...ids];
|
||||||
|
sids.sort();
|
||||||
|
return sids.join(',');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function auto_120cell_faces(links) {
|
||||||
|
const faces = [];
|
||||||
|
const seen = {};
|
||||||
|
let id = 1;
|
||||||
|
for( const edge of links ) {
|
||||||
|
const v1 = edge.source;
|
||||||
|
const v2 = edge.target;
|
||||||
|
const n1 = unmutuals(links, v2, v1);
|
||||||
|
const n2 = unmutuals(links, v1, v2);
|
||||||
|
const shared = [];
|
||||||
|
for( const a of n1 ) {
|
||||||
|
const an = unmutuals(links, v1, a);
|
||||||
|
for( const d of n2 ) {
|
||||||
|
const dn = unmutuals(links, v2, d);
|
||||||
|
for( const x of an ) {
|
||||||
|
for( const y of dn ) {
|
||||||
|
if( x == y ) {
|
||||||
|
shared.push([v1, a, x, d, v2])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( shared.length !== 3 ) {
|
||||||
|
console.log(`Bad shared faces for ${edge.id} ${v1} ${v2}`);
|
||||||
|
}
|
||||||
|
for( const face of shared ) {
|
||||||
|
const fp = fingerprint(face);
|
||||||
|
if( !seen[fp] ) {
|
||||||
|
faces.push({ id: id, nodes: face });
|
||||||
|
id++;
|
||||||
|
seen[fp] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return faces;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function make_120cell_vertices() {
|
function make_120cell_vertices() {
|
||||||
|
@ -310,8 +383,8 @@ export const cell120 = () => {
|
||||||
geometry: {
|
geometry: {
|
||||||
node_size: 0.02,
|
node_size: 0.02,
|
||||||
link_size: 0.02
|
link_size: 0.02
|
||||||
}
|
},
|
||||||
|
faces: faces
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue