raymarching 3d engine - calcuviz views

raymarching 3d engine - calcuviz views
Code
model_0 = require('../../models/raymarching/raymarching.js');

input values ⚙️

Code
viewof raymarching_iterations_in = Inputs.range([0,200], {value: 100, step:1, label: "raymarching_iterations_in"})

viewof alpha_in = Inputs.range([-180,180], {value: 69, step:1, label: "alpha_in"})

viewof beta_in = Inputs.range([-180, 180], {value: 38, step:1, label: "beta_in"})

viewof dist_in = Inputs.range([1, 3], {value: 1.88, step:0.01, label: "dist_in"})

viewof fov_in = Inputs.range([1,180], {value: 34, step:1, label: "fov_in"})

viewof sdf_shape_in = Inputs.select([
    'sphere',
    'cube',
    'cube_with_holes',
    'cube_and_torus',
    'teapot',
], {value: 'cube_and_torus', label: "sdf_shape"})

viewof screen_width_in = Inputs.range([0,150], {value: 50, step:10, label: "screen_width_in"})

viewof screen_height_in = Inputs.range([0,150], {value: 50, step:10, label: "screen_height_in"})

Visuals via calcuvizspec

Code
input_cursor = ({ // some things that will be common across visuals
  raymarching_iterations_in, alpha_in, beta_in, dist_in, fov_in, sdf_shape_in, screen_width_in, screen_height_in
})
spec_post_process = spec => {
  spec.width = 600;
  spec.height = 500;
  spec.encoding.y.sort = 'descending'
  spec.encoding.x.axis = { grid: false, domain: false, ticks: 0, labels: false }
  spec.encoding.y.axis = { grid: false, domain: false, ticks: 0, labels: false }
  spec.config = {"legend": {"disable": true}}
  spec.resolve = {scale: {color:'independent'}}
  spec.mark.clip = true;
  return spec;
}

scene

Code
vega_interactive(
  calcuvizspec({
    models: [model_0],
    input_cursors: [input_cursor],
    mark: 'rect', // heatmap
    encodings: {
      x: {'name': 'xq_in', type:'nominal', domain: _.range(0,screen_width_in,1)},
      y: {'name': 'yq_in', type:'nominal', domain: _.range(0,screen_height_in,1)},
      color: {'name': 'value', type:'quantitative'},
      row: {'name': 'formula', domain: ['brightness_2' /* can put more formulae here */]}
    },
    spec_post_process
  })
  , { renderer: 'svg'})

scene over diff. # raymarching iterations and cube shape 🕵️‍♂️👀

(and fixed 20 screen width/height)

Or how the sausage is made:

Code
vega_interactive( // mainly row:formula->raymarching_iterations_in
  calcuvizspec({
    models: [model_0],
    input_cursors: [{...input_cursor, screen_width_in: 20, screen_height_in: 20}],
    mark: 'rect', // heatmap
    encodings: {
      x: {'name': 'xq_in', type:'nominal', domain: _.range(0,20,1)},
      y: {'name': 'yq_in', type:'nominal', domain: _.range(0,20,1)},
      color: {'name': 'brightness_2', type:'quantitative'},
      column: {'name': 'raymarching_iterations_in', domain: [2,3,5,10,20,50]},
      row: {'name': 'sdf_shape_in', domain:[sdf_shape_in, 'cube', 'teapot']}
    },
    spec_post_process: spec => {
      spec = spec_post_process(spec);
      spec.width = 200/3;
      spec.height = 150/3;
      return spec
    }
  })
  , { renderer: 'svg'})

appendix

Code
vega_interactive = { // credit to Mike Bostock (starting point): https://observablehq.com/@mbostock/hello-vega-embed
  const v = window.vega = await require("vega");
  const vl = window.vl = await require("vega-lite");
  const ve = await require("vega-embed");
  async function vega(spec, options) {
    const div = document.createElement("div");
        div.setAttribute('id','chart-out');
    div.value = (await ve(div, spec, options)).view;
    div.value.addEventListener('mousemove', (event, item) => {
      //console.log(item);
      if (item != undefined && item.datum != undefined && item.datum.formula != undefined) {
              /*DN off viewof formula_select.value = item.datum.formula;
      viewof formula_select.dispatchEvent(new CustomEvent("input"))
*/
      }
    })
    div.value.addEventListener('click', (event, item) => {
      console.log(item.datum);
      
    }) // DN
    return div;
  }
  vega.changeset = v.changeset;
  return vega;
} //
Code
import {calcuvizspec} from "@declann/little-calcu-helpers"