nst-guide / web

Mapping website for National Scenic Trails
https://nst.guide
GNU General Public License v3.0
5 stars 0 forks source link

3D terrain mesh #12

Open kylebarron opened 4 years ago

kylebarron commented 4 years ago

https://github.com/mapbox/martini https://observablehq.com/@mourner/martin-real-time-rtin-terrain-mesh https://github.com/turban/webgl-terrain

Amazing tutorials, though a bit old: https://blog.mastermaps.com/2013/10/terrain-building-with-threejs-part-1.html https://blog.mastermaps.com/2013/10/terrain-building-with-threejs.html https://blog.mastermaps.com/2013/10/textural-terrains-with-threejs.html

kylebarron commented 4 years ago

Three terrain plugin?: https://github.com/IceCreamYou/THREE.Terrain

kylebarron commented 4 years ago

Wrapper for THREE.js for web and react-native!! <3 https://github.com/react-spring/react-three-fiber

kylebarron commented 4 years ago

Tutorial for using with react: https://dev.to/manan30/creating-a-rudimentary-pool-table-game-using-react-three-js-and-react-three-fiber-part-1-363l

kylebarron commented 4 years ago

This snippet gets a grid of terrain values from a mapbox terrain-rgb tile, and passes those values to martini.

I couldn't get the martini import to work in ijavascript because it uses the new es6 syntax, but everything else is tested.

var getPixels = require("get-pixels")
var Martini = require('@mapbox/martini')
var path = '/Users/kyle/github/mapping/nst-guide/hillshade/data/tmp-rgbify/terrain_cubicspline/12/720/1638.png'

let data
getPixels(path, function(err, pixels) {
  if(err) {
    console.log("Bad image path")
    return
  }
  data = pixels
  console.log("got pixels", pixels.shape.slice())
})

tileSize = data.shape[0]
gridSize = tileSize + 1

var terrain = new Float32Array(gridSize * gridSize);

let r, g, b;
let height_values = []
for (let x = 0; x < tileSize; x++) {
  for (let y = 0; y < tileSize; y++) {
    R = data.get(x, y, 0)
    G = data.get(x, y, 1)
    B = data.get(x, y, 2)
    height = -10000 + ((R * 256 * 256 + G * 256 + B) * 0.1)
    terrain[y * gridSize + x] = height;
    height_values.push(height)
  }
}

// backfill right and bottom borders
for (let x = 0; x < gridSize - 1; x++) {
  terrain[gridSize * (gridSize - 1) + x] = terrain[gridSize * (gridSize - 2) + x];
}
for (let y = 0; y < gridSize; y++) {
  terrain[gridSize * y + gridSize - 1] = terrain[gridSize * y + gridSize - 2];
}

// set up mesh generator for a certain 2^k+1 grid size
const martini = new Martini(gridSize);

// generate RTIN hierarchy from terrain data (an array of size^2 length)
const tile = martini.createTile(terrain);

// get a mesh (vertices and triangles indices) for a 10m error
const mesh = tile.getMesh(10);
kylebarron commented 4 years ago

Merged from mobile; mobile is nver going to really happen, though web hopefully will through deck.gl