Giter Club home page Giter Club logo

bare-minimum-3d's Introduction

NPM MINIFIED GZIPPED Install Size Coverage Status Test Passing Code Climate technical debt buy me coffee

Bare Minimum 3d

A small package to transform declared 3d data (points, polygons, lines) to 2d data. The output is intended to be fed to a BareMinimum2d React component.

Extremely lightweight and fairly configurable, this package has zero dependencies and a relatively straightforward declarative API. See also: why I created this project.

You can checkout a demo application (and play with the parameters!) at: https://mithi.github.io/hello-3d-world

Getting started

$ npm i @mithi/bare-minimum-3d
$ npm i bare-minimum-2d

You can check out the examples of SceneOptions, SceneSettings, ViewSettings that you can pass to the renderScene() function. You can pass 3d data such as this hexapod or pyramid. When you pass the hexapod data along with the other example parameters linked above, this is the corresponding 2d data that renderScene() would return.

import BareMinimum2d from "bare-minimum-2d"
import renderScene from "@mithi/bare-minimum-3d"

const { container, data } = renderScene(
    viewSettings, sceneSettings, sceneOptions, data3d
)

<BareMinimum2d {...{container, data} />

Please check the wiki / documentation, to learn more about the arguments that you'll need to pass to BareMinimum3d's renderScene() function.

0.4.0 Update

In Version 0.4.0 all utility functions are now exposed to the users, so you can use it however you like. With all the building blocks available to you, you can even build your own custom renderScene function, should you want to!

import {
    renderScene,
    SCENE_ORIENTATION,
    getWorldWrtCameraMatrix,
    AxesRenderer,
    SceneCube,
    DataRenderer,
    SceneCubeRenderer,
    Vector,
    rotateXYZmatrix,
    multiply4x4matrix,
    radians,
} from "@mithi/bare-minimum-3d"

⚠️❗ Limitations

This library does NOT perform clipping or hidden surface removal. Each element are just painted to the screen in the order that you declare them in your array of data, and the scene elements are always rendered first, meaning your data will be rendered on top of any scene element. This means that it is possible that elements will incorrectly overlap other elements that are actually nearer to the camera. There is no plan to fix this... unless someone makes a pull request! ❤️

Contributing PRs welcome!

Please read the contributing guidelines and the recommended commit style guide! Thank you!

bare-minimum-3d's People

Contributors

dependabot[bot] avatar fuddl avatar mithi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

fuddl

bare-minimum-3d's Issues

refactor: axes rendering

Currently, you can inspect https://github.com/mithi/bare-minimum-3d/blob/master/src/scene-cube-renderer.ts

Which has the following two helper functions

Draw Axes

const drawAxes = (
    p0: Vector,
    vx: Vector,
    vy: Vector,
    vz: Vector,
    name: string,
    AxesOptions: AxesOptions
) => {
    const {
        intersectionPointColor,
        intersectionPointSize,
        xColor,
        yColor,
        zColor,
        lineSize,
        edgeOpacity,
    } = AxesOptions

    let opacity = edgeOpacity || 1
    let size = lineSize || 1
    const xAxis: Lines2dSpecs = drawAxis(p0, vx, xColor, opacity, size, name, "x")
    const yAxis: Lines2dSpecs = drawAxis(p0, vy, yColor, opacity, size, name, "y")
    const zAxis: Lines2dSpecs = drawAxis(p0, vz, zColor, opacity, size, name, "z")

    const centerPoint: Points2dSpecs = {
        x: [p0.x],
        y: [p0.y],
        color: intersectionPointColor,
        opacity: 1.0,
        size: intersectionPointSize || 3,
        type: DataSpecType.points,
        id: `point-${name}`,
    }

    return [xAxis, yAxis, zAxis, centerPoint]
}

Draw Axis

const drawAxis = (
    p: Vector,
    v: Vector,
    color: string,
    opacity: number,
    size: number,
    name: string,
    axisType: string
): Lines2dSpecs => ({
    x0: [p.x],
    y0: [p.y],
    x1: [v.x],
    y1: [v.y],
    color,
    opacity,
    size,
    type: DataSpecType.lines,
    id: `${axisType}-${name}`,
})

Which is called by the following three methods.

It would be much cleaner if these 2 functions are replaced by one class which has the responsibility of drawing the 3 axes.

feat: Hidden points removal

feat: Add ability to draw 3d circles

Algorithm

  1. Start with a 2d circle defined by a radius, centered at the origin, in the xy plane
  2. Get 5 points of a circle(r, 0), (-r, 0), (0, r), (0, -r), (0, 0)
  3. Transform these 5 points in 3d given the 3 euler angles and the actual center (x, y, z)
  4. Convert these points into 2d by projecting it to the canvas, the circle is now and ellipse
  5. Get the radiusX and radiusY of the ellipse given the origin and two of the transformed points (compute the distance)
  6. Get the angle of this new ellipse by getting the dot product of one of the vectors formed by the origin and one of the points and the x axis
  7. We have now defined the ellipse (2d center, radiusX, radiusY, angle) representation

distance to the camera

the DataRenderer currently returns two dimensional coordinates. I suppose it could additionally return the virtual distance to the camera. This could enable plug-ins to do things like:

fix: Github action to automatically publish upon release currently does NOT work

name: Node.js_Package
on:
release:
types: [created]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
# Setup .npmrc file to publish to npm
- uses: actions/setup-node@v1
with:
node-version: '10.x'
registry-url: 'https://registry.npmjs.org'
- run: npm install
# Publish to npm
- run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
# Setup .npmrc file to publish to GitHub Packages

optimize: Lazy load projected points of scene cube

In the scene cube (https://github.com/mithi/bare-minimum-3d/blob/master/src/scene-cube.ts
) class, when the object is instantiated, the points of the cube are projected eagerly.

But sometimes they are not rendered by the scene cube renderer (https://github.com/mithi/bare-minimum-3d/blob/master/src/scene-cube-renderer.ts).

This is why it's better if we lazy load and /or memoize these things instead.

Scene Cube Constructor

    constructor(
        euler: { x: number; y: number; z: number },
        worldWrtCameraMatrix: matrix4x4,
        zOffset: number,
        range: number,
        projectionConstant: number
    ) {
        this.wrtWorldMatrix = rotateXYZmatrix(euler)
        this.wrtCameraMatrix = multiply4x4matrix(
            worldWrtCameraMatrix,
            this.wrtWorldMatrix
        )
        this.zOffset = zOffset
        this.range = range
        this.projectionConstant = projectionConstant
        this.crossPoints2d = this._projectedPoints(this.crossPoints3d)
        this.vertexPoints2d = this._projectedPoints(this.vertexPoints3d)
        const [center2d] = this._projectedPoints([this.center3d])
        this.center2d = center2d
        this.axes2d = this._projectedPoints(this.axes3d)
        this.worldAxes2d = this._projectedPoints(this.axes3d, 0, worldWrtCameraMatrix)
        const [worldOrigin2d] = this._projectedPoints(
            [this.center3d],
            0,
            worldWrtCameraMatrix
        )
        this.worldOrigin2d = worldOrigin2d
    }

Scene cube renderer expert

    render(): Array<Data2dSpecs> {
        return [
            ...this.drawXYplane(),
            ...this.drawBox(),
            ...this.drawCrossSectionLines(),
            ...this.drawEdgeAxes(),
            ...this.drawWorldAxes(),
            ...this.drawCubeAxes(),
        ]
    }

    drawBox(): Array<Polygon2dSpecs> {
        const { sceneEdges } = this.sceneOptions
        if (!sceneEdges) {
            return []
        }

Implement custom geometry API

@mithi next I'll try to implement the API into bare-minimum-3d. I guess it should look like this:

renderScene(viewSettings, sceneSettings, sceneOptions, data3d, plugins)

feat: Render Scene Defaults

Motivation

renderScene() takes in viewSettings, sceneSettings,sceneOptions and data

Scene options has a shape that is specified here https://github.com/mithi/bare-minimum-3d/blob/master/src/parameter-types.ts You have to specify a lot of color, opacity, and lineSize among others. You may not want to think about these things.

Solution

So there should be an additional alternative function than can be used:
renderSceneDefaults(viewSettings, sceneSettings, sceneOptionsBoolean, backgroundColor, theme, data)

The user should be able to override the background color should s/he wish

The user should also be able to specify a theme which is light or dark which will use the default colors and lines etc.
The user should specify which scene option elements you want to show ie

const sceneOptionsBoolean: Record<string, boolean> = {
    showWorldAxes: true,
    showEdgeAxes: true,
    showCubeAxes: true,
    showXYplane: true,
    showCrosslines: true,
    showCubeEdges: true,
}

For the sceneOptions parameter, we can use these defaults for dark mode

const edgeAxes = {
    intersectionPointColor: "#FF00FF",
    intersectionPointSize: 5,
    xColor: "#E91E63",
    yColor: "#03A9F4",
    zColor: "#CDDC39",
    lineSize: 1,
    edgeOpacity: 1.0,
}

const worldAxes = {
    intersectionPointColor: "#FFFF00",
    intersectionPointSize: 5,
    xColor: "#E91E63",
    yColor: "#03A9F4",
    zColor: "#CDDC39",
    lineSize: 3,
    edgeOpacity: 1.0,
}

const cubeAxes = {
    intersectionPointColor: "#00FF00",
    intersectionPointSize: 5,
    xColor: "#E91E63",
    yColor: "#03A9F4",
    zColor: "#CDDC39",
    lineSize: 3,
    edgeOpacity: 1.0,
}

const sceneOptions = {
    paper: { color: "#17212B", opacity: 1 },
    xyPlane: { color: "#0652DD", opacity: 0.1 },
    sceneEdges: { color: "#1e3799", opacity: 1 },
    crossLines: { color: "#079992", opacity: 1 },
    edgeAxes,
    worldAxes,
    cubeAxes,
}

chore: Add prettier test and code climate configs + automatically publish in npm registry

  • prettier test
  • code climate configs
  • coveralls
  • github actions to automatically publish in both npm and github registry
  • Add 3 badges
    • bundlephobia - minified + gzipped
    • npm version

See also
https://github.com/mithi/hexapod/blob/master/.codeclimate.yml
https://github.com/mithi/hexapod/blob/master/.github/workflows/build.yml
https://dev.to/joeattardi/how-to-publish-an-npm-package-to-npm-and-github-package-registry-simultaneously-using-github-actions-213a

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.