2.2.1 • Published 11 months ago

four-js v2.2.1

Weekly downloads
6
License
MIT
Repository
github
Last release
11 months ago

four.js

An attemp to render 4 dimensional objects with three.js.

Full demo: anakata

Installation

yarn add four-js
# or
npm --save install four-js

Usage

Full working example here

To run it: git clone https://github.com/paradoxxxzero/four.js && cd four.js && yarn install && yarn start then open http://localhost:44444/examples/tesseract.html

Creating

import { HyperGeometry, shapes } from 'four-js'

// Import tesseract preset shape
const { tesseract } = shapes

// Create an HyperRenderer which will be used to make 4d -> 3d projections
const hyperRenderer = new HyperRenderer(1.5, 5)

4D -> 3D Projection

// Instantiate an HyperMesh with the shape
const hyperMesh = new HyperMesh(shape)

// (...) Setup the three.js scene as usual and add the HyperMesh:
scene.add(hyperMesh)

4D -> 3D Cross Section

// Instantiate an HyperSlice with the shape
const hyperSlice = new HyperSlice(shape)

// (...) Setup the three.js scene as usual and add the HyperSlice:
scene.add(hyperSlice)

Updating

This will render a tesseract that you can then rotate by updating the HyperRenderer rotation:

update() {
  requestAnimationFrame(update)
  // Rotate takes the rotation speed around the 6 planes:
  hyperRenderer.rotate({ xy: 0, xz: 0, xw: 5, yz: 0, yw: 10, zw: 10 })

  // Move the cross section along the w-axis
  hyperRenderer.shiftSlice(0.5, wmin, wmax)

  // Update the hyperMesh
  hyperMesh.update(hyperRenderer)

  // Update the hyperSlice
  hyperSlice.update(hyperRenderer)

  // Render the scene
  renderer.render(scene, camera)
}

Configuration

HyperMesh and HyperSlice accept a configuration object as second argument:

const meshConfig = {
  faces: {
    // Configuration regarding faces
    enabled: true, // Render faces
    useColors: true, // Use vertex coloring through colorGenerator
    colorGenerator: cellColors, // Called with ({shape, colors}) must return a function that returns a colors from ({cell, face, vertex, type}) indexes
    colors: defaultColors, // Colors to chose from
    reuse: 'none', // One of ['all', 'faces', 'none'], specifies whether to duplicate vertex in faces / cells. Useful for polychora due to needing a normal per face per vertex.
    split: 'cells', // One of ['none', 'cells', 'faces'], specifies whether to render one Mesh, one Mesh per cell, one Mesh pes face
    splitScale: 100, // Scale of each split, allow for better comprehension of 4D Mesh when used with split: 'cells'
    material: new MeshPhongMaterial({
      // The material (or list of materials per split) to use when rendering
      transparent: true,
      opacity: 0.25,
      blending: NormalBlending,
      depthWrite: false,
      side: DoubleSide,
      vertexColors: true,
    }),
  },
  edges: {
    // Render edges
    enabled: true,
    useColors: true,
    colorGenerator: cellColors,
    colors: defaultColors,
    reuse: 'faces',
    split: 'cells',
    splitScale: 100,
    material: new LineBasicMaterial({
      transparent: true,
      opacity: 0.25,
      blending: AdditiveBlending,
      depthWrite: false,
      vertexColors: true,
      linewidth: 2,
    }),
  },
  points: {
    // Render points
    enabled: false,
    useColors: true,
    colorGenerator: cellColors,
    colors: defaultColors,
    reuse: 'faces',
    split: 'none',
    splitScale: 100,
    material: new ShaderMaterial({
      uniforms: {
        size: { value: 5 },
        opacity: { value: 0.25 },
      },
      vertexShader: pointsVertexShader,
      fragmentShader: pointsFragmentShader,
      transparent: true,
      blending: AdditiveBlending,
    }),
  },
}

const hyperMesh = new HyperMesh(shape, meshConfig)

// Same configuration (minus split/reuse configs) for HyperSlice:
const sliceConfig = {
  faces: {
    enabled: true,
    useColors: true,
    colorGenerator: cellColors,
    colors: defaultColors,
    material: new MeshPhongMaterial({
      side: DoubleSide,
      shininess: 50,
      vertexColors: true,
    }),
  },
  edges: {
    enabled: true,
    useColors: true,
    colorGenerator: cellColors,
    colors: defaultColors,
    material: new LineBasicMaterial({
      transparent: true,
      opacity: 0.25,
      blending: AdditiveBlending,
      depthWrite: false,
      vertexColors: true,
      linewidth: 2,
    }),
  },
  points: {
    enabled: false,
    useColors: true,
    colorGenerator: cellColors,
    colors: defaultColors,
    material: new ShaderMaterial({
      uniforms: {
        size: { value: 5 },
        opacity: { value: 0.25 },
      },
      vertexShader: pointsVertexShader,
      fragmentShader: pointsFragmentShader,
      transparent: true,
      blending: AdditiveBlending,
    }),
  },
}

const hyperSlice = new HyperSlice(shape, sliceConfig)

Shape definition

The 4 dimensional mesh descriptions are composed of vertices, faces and cells.

Here's what the tesseract description look like:

const tesseract = {
  // These are the classic vertices
  vertices: [
    [1, 1, 1, 1], // 0
    [1, 1, -1, 1], // 1
    [1, -1, -1, 1], // 2
    [1, -1, 1, 1], // 3
    [-1, 1, 1, 1], // 4
    [-1, 1, -1, 1], // 5
    [-1, -1, -1, 1], // 6
    [-1, -1, 1, 1], // 7
    [1, 1, 1, -1], // 8
    [1, 1, -1, -1], // 9
    [1, -1, -1, -1], // 10
    [1, -1, 1, -1], // 11
    [-1, 1, 1, -1], // 12
    [-1, 1, -1, -1], // 13
    [-1, -1, -1, -1], // 14
    [-1, -1, 1, -1], // 15
  ],
  // Each face is made by listing its vertices index
  faces: [
    [0, 1, 2, 3], // 0
    [0, 4, 5, 1], // 1
    [0, 3, 7, 4], // 2
    [3, 2, 6, 7], // 3
    [1, 5, 6, 2], // 4
    [4, 7, 6, 5], // 5
    [0, 1, 9, 8], // 6
    [4, 5, 13, 12], // 7
    [3, 2, 10, 11], // 8
    [7, 6, 14, 15], // 9
    [0, 3, 11, 8], // 10
    [4, 7, 15, 12], // 11
    [1, 2, 10, 9], // 12
    [5, 6, 14, 13], // 13
    [0, 4, 12, 8], // 14
    [1, 5, 13, 9], // 15
    [2, 6, 14, 10], // 16
    [3, 7, 15, 11], // 17
    [11, 10, 9, 8], // 18
    [9, 13, 12, 8], // 19
    [12, 15, 11, 8], // 20
    [15, 14, 10, 11], // 21
    [10, 14, 13, 9], // 22
    [13, 14, 15, 12], // 23
  ],
  // Each cell is made by listing its faces index
  cells: [
    [0, 1, 2, 3, 4, 5], // 0
    [0, 6, 12, 8, 10, 18], // 1
    [1, 6, 14, 7, 15, 19], // 2
    [4, 12, 16, 13, 15, 22], // 3
    [3, 8, 16, 9, 17, 21], // 4
    [2, 10, 17, 11, 14, 20], // 5
    [5, 7, 13, 9, 11, 23], // 6
    [18, 19, 20, 21, 22, 23], // 7
  ],
}

This means that the first cell

    [0, 1, 2, 3, 4, 5], // 0

is composed of 6 faces:

    [0, 1, 2, 3], // 0
    [0, 4, 5, 1], // 1
    [0, 3, 7, 4], // 2
    [3, 2, 6, 7], // 3
    [1, 5, 6, 2], // 4
    [4, 7, 6, 5], // 5

and the first face here

    [0, 1, 2, 3], // 0

is composed of 4 vertices:

    [1, 1, 1, 1], // 0
    [1, 1, -1, 1], // 1
    [1, -1, -1, 1], // 2
    [1, -1, 1, 1], // 3

Following that logic you can try to draw your own 4d models.

Feel free to make pull requests with your own creations!

Contributors

@FranzPoize

For his nice 3-sphere shape which has since been refactored and generalized into uvw-hypersurfaces.

2.2.1

11 months ago

2.2.0

11 months ago

2.1.0

2 years ago

2.0.1

3 years ago

1.1.0

3 years ago

2.0.0

3 years ago

1.0.3

3 years ago

1.0.2

3 years ago

1.0.1

3 years ago

1.0.0

3 years ago

0.1.3

3 years ago

0.1.2

3 years ago

0.1.1

3 years ago

0.1.0

3 years ago