Giter VIP home page Giter VIP logo

procedural-gl-js's Introduction

procedural-gl.js

Procedural GL JS is a library for creating 3D map experiences on the web, written in JavaScript and WebGL. It is built on top of THREE.js.

It provides an easy-to-use, but powerful framework to allow beautiful landscapes of the outdoors to be embedded into web pages. It loads super-fast and is optimized for mobile devices.

Demo | Docs | Overlay playground | Elevation data | Source

Key features

  • Novel GPU powered level-of-detail system gives butter-smooth rendering, including on mobile
  • Stream in standard raster imagery tiles. Supports map tiles from a variety of providers
  • Easily include elevation data for 3D terrain
  • Powerful overlay capabilities. Draw crisp markers and lines
  • Well-thought-out API, complex applications can be built without needing to deal with 3D concepts
  • Great UX and intuitive controls, mouse-based on desktop & touch-based on mobile
  • Tiny filesize means library is parsed fast. Package size is less than THREE.js thanks to code stripping

Screenshots

Install

npm install procedural-gl

Usage

import Procedural from 'procedural-gl';

// Choose a DOM element into which the library should render
const container = document.getElementById( 'container' );

// Configure datasources
const datasource = {
  provider: 'maptiler',
  // To get a free key, use https://cloud.maptiler.com/account/?ref=procedural
  apiKey: 'GET_AN_API_KEY_FROM_MAPTILER'
};

// Initialize library and optionally add UI controls
Procedural.init( { container, datasource } );
Procedural.setRotationControlVisible( true );

// Load real-world location
const montBlanc = { latitude: 45.8326364, longitude: 6.8564201 };
Procedural.displayLocation( montBlanc );

Connecting to a datasource

To actually load data using a library you will need to connect to a source of data. The quickest way to get setup is to register for a free account with MapTiler and then use the API key as shown above.

For detailed instructions for setting up the datasource, see this page in the wiki

Examples

Sponsor

If this library is useful to you, please consider sponsoring the project.

Blog posts / Guides

License

Procedural GL JS is licensed under the Mozilla Public License Version 2.0.

procedural-gl-js's People

Contributors

felixpalmer 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  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  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  avatar

Watchers

 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

procedural-gl-js's Issues

street maps are breaking

for some reasons i can't use street maps, or basically anything except map-tiler satellite imagery

Screenshot 2020-12-18 at 10 47 08 PM

Unexpected Behaviour after clicking on marker

Description
Camera makes a jump when clicking on markers if camera angle different from default.

To Reproduce
Steps to reproduce the behavior:

  1. Go to playground
  2. Change camera's viewing angle
  3. Click on any markers on the sidebar
  4. Camera moves smoothly to the location then makes a sudden angle change

Expected behavior
Camera angle to change smoothly with the translate animation

Screenshots
Example

Desktop

  • OS: MacOS
  • Browser Safari, Chrome (88.0.4324.96)
  • Version 11.1

Mobile

  • OS: iOS
  • Browser Safari, Chrome
  • Version 14.3

datasources/base.js ImageLoader.load - Error callback broken

The imageLoader onProgress-callback is missing from the ImageLoader.load-call so the error callback never triggers in case of a tile that is missing.
From the Three.js ImageLoader documentation:

// load a image resource
// instantiate a loader
const loader = new THREE.ImageLoader();

loader.load(
	// resource URL
	'textures/skyboxsun25degtest.png',

	// onLoad callback
	function ( image ) {
		// use the image, e.g. draw part of it on a canvas
		const canvas = document.createElement( 'canvas' );
		const context = canvas.getContext( '2d' );
		context.drawImage( image, 100, 100 );
	},

	// onProgress callback currently not supported
	undefined,

	// onError callback
	function () {
		console.error( 'An error happened.' );
	}
);

To Reproduce
The issue becomes noticeable when using a custom datasource with a lot of requests returning 204 for 'Tile does not exist' using Tileserver-GL (maptiler/tileserver-gl#278).
What happens is that the request errors do not get deleted from this.fetching, pile up there and eventually trigger throttling which, in turn, after 32 errors, blocks the request of any new tile.

datasources/base.js #95-100

    // Throttle downloads
    let downloadIndices = Object.values( this.fetching );
    if ( downloadIndices.length > 32 ) {
      log( 'throttling...' );
      return;
    }

Expected behavior
With the error callback working, the errors get deleted from this.fetching and do not trigger throttling, but in case of 'missing tiles' will try again and retrigger the error.

Proposed fix
I think errors should be stored in an object similar to this.fetching

    this.fetching = {};
    this.failed = {};

populated on error and then checked against at the beginning of fetchIfNeeded():

  fetchIfNeeded( quadkey ) {
    if ( this.lookup[ quadkey ] !== undefined ||
       this.fetching[ quadkey ] !== undefined ||
       this.failed[ quadkey ] ) {
      // Have data, download in progress, or tried and failed: skip
      return;
    }

    // Throttle downloads
    let downloadIndices = Object.values( this.fetching );
    if ( downloadIndices.length > 32 ) {
      log( 'throttling...' );
      return;
    }

    let newIndex = this.findNewIndex( quadkey );

    // Mark as download in progress
    this.fetching[ quadkey ] = newIndex;

    // Actually fetch data
    let url = this.urlForTile( ...tilebelt.quadkeyToTile( quadkey ) );
    ImageLoader.load( url, ( image ) => {
      // Image loaded OK
      this.imgCache[ quadkey ] = image;
      insertIntoTextureArray( this.textureArray, newIndex, image );

      // Remove download and mark image location in lookup
      delete this.fetching[ quadkey ];
      this.lookup[ quadkey ] = newIndex;

      // TODO remove, just for demo page
      if ( this.useFloat ) {
        let el = document.getElementById( 'elevation-tile-count' );
        if ( el ) {
          let n = parseInt( el.innerHTML );
          if ( isNaN( n ) ) { n = 0 }

          el.innerHTML = ++n;
        }
      }

      this.updateIndirectionTexture();
      this.notifyUpdate();
    },
    undefined,
    ( err ) => {
      if ( err.name == 'InvalidStateError' ) {
        let newIndex = this.findNewIndex( quadkey );
        this.failed[ quadkey ] = newIndex;
        log( 'InvalidStateError / HTTP 204', quadkey );
      } else {
        console.error( 'Failed to get image', quadkey );
      }

      delete this.fetching[ quadkey ];
    } );
  }

Http 204 produces 'InvalidStateError' which should not trigger a console.error but everything else still does.

Three.js function

greetings!

Is this possible to use three.js object to combine with this library?
for example : add one Box above/below 3d map
thank you!

Camera bug

Hi Felix!

First of all, thank you very much for your great project! What about the issue, I tried to fix it by myself with PR in mind, but failed to do that. So I just report it to you.

Describe the bug
If to follow example of call to configureControls presented at
https://github.com/felixpalmer/procedural-gl-js/blob/main/src/export/controls.js#L37
we see option value maxPolarAngle: 0.8 * Math.PI.
That's great idea because it allows us for example to look on mountains from below to top.

However, on more-less flat surfaces the camera easily goes below ground level when this maxPolarAngle value is used.
And then, the view sometimes becomes corrupted, with no way to return above ground level.

To Reproduce
Steps to reproduce the behavior:

  1. Use configureControls function with maxPolarAngle: 0.8 * Math.PI option.
  2. Move camera under ground (below ground level) using rotation.
  3. Pan it a little bit (staying below ground).
  4. See no way back for camera to the above ground level ;-)

Screenshot from 2021-05-11 14-37-44

Issues running compile

Thanks for making this great library open source! It is a really exciting contribution to the web mapping ecosystem. I was trying to run procedural-gl.js locally and ran into some issues while running shaders/minify.sh.

The first issue I encountered is that glsl-validate.py could not be found. I found that it references your library glsl-validator, but after bringing that in discovered that the compiled binaries for MacOS seem to be for an older runtime. I did some research into the origins of those binaries and it seems they come from angle, but it seems the essl_to_glsl utility no longer exists.

The second issue I encountered is that glslmin doesn't seem to work with newer versions of nodejs, at least not entirely. Using the syntax in minify.sh glslmin would hang on the first file and never finish or write an output. I was able to work around this by piping the input into the utility instead as so cat beacon.frag | cat glslmin > min/beacon.frag, but that seems less than ideal.

Do you have any advice for getting this step of the build pipeline to complete? Are there other utilities that could be used in place of glsl-validate.py and glslmin?

My system is as follows:
MacOS 10.15.7
Node v12.14.1
Python 2.7.16
Python3 3.7.9

Thank you!

Adjustable zoom cap for terrain tiles

Hi, @felixpalmer! First of all big thanks and congratulations on an amazing library! The recent update, which provides API for custom terrain tilesources was exactly what our project needed so much! A bit of the background on how we try to use your library - our project aims to visualize the changes that happened to the landscape of one of the Kyiv districts, in Ukraine, throughout the 20 century and until now (in the area where the Holocaust massacre happened during the WW2, which is the focus of our research investigation).

For this, we have prepared custom rgb tile-sources of high resolution (max zoom level in our terrain tilesets is 18, tilesize is standard 512x512), for different years. However, we noticed that the library caps the max zoom level of the tile-source (fetching happens for the 10th zoom level at the max), this way preventing the landscape to render in a higher detail at the close-ups. Is it possible to configure the max zoom of the tileset in any way? E.g. as a part of the datasource configuration? Maybe it could be configured similarly to how this is specified in the tilejson specs, with 'maxzoom' and 'minzoom' properties? Thank you very much for your answer in advance!

image

THREE.js scene and camera access

Hi Felix,

hope you are doing well! what a great package, really cool :-) I had a few questions, if possible.

I was wondering, is there any way to access the THREE.js camera and scene such that the user can see what the current viewpoint (camera position) is? For instance, then the user can manipulate the view using the mouse, get access to the location and camera position to then programmatically zoom to it say. Is that possible?

In the same vain, as your tool is build on top of THREE.js, is it possible to add custom meshes to a scene, similar to what one can do with globe.gl?

image

FYI, its render controls and utility functions are quite handy to create and sync additional annotation layers to a view.

Anyways, congrats on your package, really amazing!

kind regards, Herman

Mouse scroll zoom speed is slow

When zooming with the mouse wheel, the zoom feels very slow.

Some values that I see in the JS debugger:

// handleMouseWheel():
event.deltaY = 3
getZoomScale(event.deltaY) = 0.999
scope.zoomSpeed = 0.5

This is the difference between what was probably 2 full mousewheel rotations, barely perceptable. (Excuse the uneven cropping.)
imgnote-042720fb-ffe8-40bf-8465-606d9a57a3ae
imgnote-ac664644-97fd-4a60-acba-a8ff5918cf7a

zooming out to globe level?

Hey, this library is gorgeous!
I was wondering whether it would be possible to zoom out to see the whole globe.
What are the technical limitations there?

Mapbox static tiles are not well placed

Hi, just tried to use mapbox static tile server, but it seems that some tile coordinates are messed, see here:

Captura de ecrã 2021-03-04 190036

Using this

const datasource = {
    elevation: {
      apiKey: APIKEY,
    },
    imagery: {
      apiKey: APIKEY,
      urlFormat: 'https://api.mapbox.com/styles/v1/mapbox/streets-v9/tiles/{z}/{x}/{y}?access_token={apiKey}',
  
  };

Add THREE.js objects into procedural-gl-js scene.

I'm not quite sure if this is the right place to put this, so let me know if not

Anyway, so I have a question, is it possible to add THREE.js objects into a procedural-gl-js scene? Because I believe procedual-gl-js uses THREE.js behind the scenes (though correct me if not).
So could I, for instance, and create a cube with THREE.js, and add it to the procedural-gl-js scene in some way?

Many thanks :)

focusOnLocation doesn't work in some locations.

Describe the bug
In some locations, when using focusOnLocation, the camera is placed in correct position, but is facing away from the location.

To Reproduce
In the Overlay editor, enter the following geojson:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "color": "white",
        "padding": 10,
        "name": "Example",
        "background": "green",
        "icon": "star"
      },
      "geometry": {
        "type": "Point",
        "coordinates": [
          21.884765625,
          53.01
        ]
      }
    }
  ]
}

Expected behavior
Camera should point towards the location. It works for this example:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "color": "white",
        "padding": 10,
        "name": "Example",
        "background": "green",
        "icon": "star"
      },
      "geometry": {
        "type": "Point",
        "coordinates": [
          21.884765625,
          53.0
        ]
      }
    }
  ]
}

The only difference between those two examples is the latitude (53.0N vs 53.01N).

Desktop (please complete the following information):

  • OS: Mac OS catalina
  • Browser: Chrome, Safari, Firefox

picker.raycastTerrain error

image
image
hi felixpalmer:
1,this is a great repo ,thanks you let us learning from this repo
2. i have same confuse above that maybe that is a error so i issue it
3. i try add three object into the sence, the obj's location must be {x,y,z} in sence 。 i want to picker from GPU renders Terrain's {x,y,z} .and than obj could real create on the terrain.

Offset location indicator line

When using image markers I'm shifting them upwards to make them visible even if they would be clipped normally.
Additionally I draw a circle in order to mark the real position. With a growing number of images and/or a growing offset between the image marker and the real position users may not be able to assign image markers to the corresponding real positions.

I'd like to be able to draw an offset indicator line between the image marker an the real position. Please see the attached screenshot with a faked offset indicator line.

image

Temporal grid overlay

This is great! Next to markers and features as overlay, could this application also render temporal grid overlay to visualise for example flood events?

Multiple containers

At the moment it seems to be the case that there can only be 1 Procedural container in the DOM. Despite the performance hit having multiple, is this something that is on the road map?

Get world coordinates from user click

Hi, don't know if this is already possible, but it would be very useful to have a kind of callback to get the world coordinates where the user clicked. This would serve several purposes:

  • Letting the user click on a map coordinate and focusOnLocation;
  • Get the world coordinates from user click, so the user can create custom overlays or even draw on map

Explicitly control which map tiles get loaded

Hello,

Thanks for your great work on this library!

I'm evaluating using procedural-gl-js in a visualization tool, to plot 3D GPS flight paths. In this application, the viewer is only concerned with the area immediately around the flight path. This flight path might be small (a few kilometers), large (hundreds of kilometers), and irregularly shaped (a random path that stretches very far in some direction).

Is there any way to configure the range of tiles loaded around the display location, or explicitly choose which tiles to load?
Right now, the map seems to load a pretty large area in a square around the GPS coordinates specified using displayLocation. For example, if I search "Boston, MA", the example loads almost all of Massachusetts. I'm hoping to do a few things:

  1. Only load the map tiles directly underneath the flight path
  2. Load tiles that may stretch very far in one direction, perhaps horizontally across 100s of kilometers.

I'd love to be able to pass in an explicit list of XYZ tile coordinates,. I looked around the source code, but couldn't find where the library is converting lat/lng coordinates into an list of tiles to load. Would be happy to contribute if I could be pointed in the right direction!

Environment parameters are being reset

First of all really nice library, much faster and easier to use than the other globe libraries 👍

Describe the bug
The environment parameters are being reset after sometime when using Procedural.displayLocation

To Reproduce
Steps to reproduce the behaviour:

     // Environment
    const environment = {
      title: 'custom',
      parameters: {
        inclination: 0.6,
        fogDropoff: 0
      }
    }
    Procedural.setEnvironment(environment)
    const location1 = { latitude: 52.3676, longitude: 4.9041 }
    const location2 = { latitude: 45.8326364, longitude: 6.8564201 }
    Procedural.displayLocation(location2);
    setTimeout(()=> {
      Procedural.displayLocation(location1);
// Fog comes back in play here
    }, 5000)

Expected behaviour
Expected is that the environment parameters would stay the same.

Animation Control/Timeline

This library is really impressive, especially on Mobile. As I am considering migrating my project over to this, one of the really useful things with Cesium is the ability to control the internal clock externally, so a camera path over time can be controlled by a slider component or similar.

As a feature request, would it be possible to expose setting the internal clock ticks or similar, to allow the same feature in this Library?

Potential Settler Sponsor here!

Hello Felix. Let me congratulate you for this awesome repo. We have a product that we are thinking of implementing this, so we have some questions:

  • Can this be wrapped on React?
  • Can this be wrapped on A-frame?
  • Is it possible to have more control of the resolution/tiles when we zoom in
  • Does the elevation data only come from one provider? Or other providers can be used? (mapbox, google, etc)
  • Is it possible to change from satellite images to terrain and roads similar to Google Maps for example?
  • Does this work with WebXR api, and for example experience it on Oculus Quest or Hololens?

Hope to get your reply.
Best regards.

[Question] is it possible to add an area (polygon) as an overlay?

Hey!

Thanks for the great library. Really enjoyed trying it out so far 🙂

I have one question:

Is it possible to add an area (polygon) as an overlay? I tried it now for some time but it does not seem to display. What I'm trying to achieve is something like this:

image
https://geojson.io/#map=13/48.3135/14.3413

When I take the geojson and put it into the overlay editor: https://www.procedural.eu/overlays.html it seems that the area (polygon) is recognized correctly but I can not see anything. This is the geojson I tried:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "stroke": "#555555",
        "stroke-width": 2,
        "stroke-opacity": 1,
        "fill": "#ff0000",
        "fill-opacity": 0.5
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [
              14.361705780029295,
              48.318478372736365
            ],
            [
              14.34608459472656,
              48.308888618124726
            ],
            [
              14.359989166259767,
              48.29404377802783
            ],
            [
              14.386768341064451,
              48.2964420830209
            ],
            [
              14.38436508178711,
              48.314482860683626
            ],
            [
              14.361705780029295,
              48.318478372736365
            ]
          ]
        ]
      }
    }
  ]
}

Am I doing something wrong or is this feature not implemented right now?

Thanks a lot

3D model, custom tiles and overlay

so glad to found this great repo, couple questions though:

  • can an image overlay be added over the map? also i can see only LineString but how about other types like circle etc? is there anything else can be added to the app in addition to markers and linestrings?
  • being based on THREE JS, is it possible to load a 3D model?
  • can i use custom local {z}{x}{y} imagery tiles?

cheers

Some questions about missing tiles and other things..

Hi,
I'm from TU Wien and we got our hands on some high resolution height data for Austria, and now we are playing around with it and with your 3d map. We are thinking of it as a possible research vehicle, and tool for mountaineers.

First of all, we are having some troubles: https://www.youtube.com/watch?v=3q-_05H2HpU

  • Some photo tiles are missing
  • some DEM tiles are also missing.

Our dem tiles have a resolution of 256x256, so we had to change that. we also increased the maxZoom for dem tiles to 20 i think. I don't know whether that has something to do with the problem. In any case, we are willing to put in work, but maybe you could give us some pointers? We have background in 3d, but not so much in java script yet.

Also another thing: it's likely we'll put one or several students onto some tasks. Are you still actively developing this project? Would you like to receive merge request? co-supervise or something? if you like we can also have a zoom meeting, if you moved on, that's also fine :)

Cheers, Adam

Remove all Overlays at once

Hi @felixpalmer , it would be very useful to have a removeAllOverlays method. Simply to remove all overlays without needing to express the features name. What do you think?

Map fails to load properly when latitude is above 61°N

Procedural GL JS looks to be a really interesting library, thanks for making it.

When you create a map that's centred on a location higher than 61°N, the map fails to work as expected. While there's no error in the browser console, neither the elevation data nor the satellite imagery looks like it's loaded properly. Interaction is broken too. This affects all of Iceland plus large parts of Norway, Sweden, Finland, Russia, Canada, and the United States (Alaska).

I've put a minimal failing example on JSFiddle (line 22 of the Javascript: toggle the latitude between 61.0 and 61.1 to see the map work or fail). You can also see this bug in the demo by searching for Gjøvik (~60°N, works) or Lillehammer (~61°N, fails), both in Norway.

Environment parameters are being reset

First of all really nice library, much faster and easier to use than the other globe libraries 👍

Describe the bug
The environment parameters are being reset after sometime when using Procedural.displayLocation

To Reproduce
Steps to reproduce the behaviour:

     // Environment
    const environment = {
      title: 'custom',
      parameters: {
        inclination: 0.6,
        fogDropoff: 0
      }
    }
    Procedural.setEnvironment(environment)
    const location1 = { latitude: 52.3676, longitude: 4.9041 }
    const location2 = { latitude: 45.8326364, longitude: 6.8564201 }
    Procedural.displayLocation(location2);
    setTimeout(()=> {
      Procedural.displayLocation(location1);
// Fog comes back in play here
    }, 5000)

Expected behaviour
Expected is that the environment parameters would stay the same.

Multiple Markers on Android

On multiple Android devices, when 2 Features with unique ID's are defined, onFeatureClicked is not responding.
If the Features have the same ID, behavior is as expected.
On Desktop and iOS, Features with unique ID's also behave as expected when clicked.

https://glitch.com/edit/#!/0309b

Support more attributes in updateOverlay

Currently updateOverlay only permits updates to the positions of markers, it would be nice if other parameters could also be updated using this "fast path", for example opacity and color.

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.