Mapbox free camera "look at" with adjustable height - javascript

I'm trying to change the camera 'look at' height on the mapbox scene which include 3d objects
https://srvlc.sse.codesandbox.io/ or https://codesandbox.io/s/srvlc
You can see if you maximum zoom-out, camera target height is 0, I mean directly on the map, which is fine for small 3d objects, but not for big. I added an issue on their git too for a feature request, but meanwhile I'm curious if there is a workaround or something which I missed
I tried with map.transform._centerAltitude which seems to work for zoom, but broke pann & rotate controls

Related

How to optimize camera property changes in three.js?

I am basically using a modified version of the random points WebGL three.js demo that can be found here:
https://threejs.org/examples/#webgl_points_random
Now I added a scroll event listener to change the fov and position of the camera when scrolling down, but because of the way cameras work in three.js, I have to update the camera projection matrix in every frame and this is very bad for the performance as you can see in the following examples:
Although it's quite smooth in firefox
it is very choppy on other browser such as Safari or Chrome.

Performant GL Triangles Mapbox GL JS

I am working on trying to create a basic, grid-based, but performant weather-arrow visualization system.
EDIT 2:
Up-to-date version here: ( Mapbox Tracker ) of the system using the workflow which is described below
Usage Instructions:
- Click on Wind icon (on the left)
- Wait for triangles to occupy screen
- Pan time-slider (at the bottom)
As you will observe (especially on larger resolutions or when panning time slider quickly) there is quite a performance hit when drawing the triangles.
I would greatly appreciate any advice on where to start with either using something in the current API which would help, or any ideas on how to tap into the current graphics pipeline with some type of custom buffer where I would only need to rotate, scale, change color of triangles already populated in screen space.
I feel as though my specific use-case would greatly benefit from something like this, I really just don't know how to approach it.
I have a naive implementation running using this workflow:
Create a geojson FeatureCollection source
Create a fill layer
Using Data Driven property: fill-color
Data function:
Get map bounds
Project sw & ne into screen points (map.project(LatLng))
Divide height and width into portions
Loop through width and height portions
Lookup data
Access data rotation property
Create vertices based on center point + size
Rotate vertices
Create Point objects for vertices
Unproject Point Object and wrap map.unproject(Point).wrap()
Create Feature Object, assign Data driven Color
Assign unprojected LatLng as Coordinates to Polygon geometry
Add to Feature Array for Collection
Call setData on layer
So while this works, I'm looking for advice for a more performance friendly approach.
What I'm thinking here is whether I can somehow create a custom layer, one where I only need to draw to screen co-ordinates to represent the data relative to its LatLng point. So that I can draw colored, scaled, rotated triangles in screen space, and then have them update to relevant data from the new relative LatLng position.
E.g. Update some type of Mesh on screen instead of having to: unproject, then update feature collection source using map.getSource('arrows').setData(d), requestAnimationFrame(function) etc.
I've done similar in three.js in other projects but I would much rather use something that is more mapbox native. Does this sound feasible? Am I going to see a decent performance boost if so?
I've not dealt with raw gl calls before etc so I might need a pointer or two in the right direction if its going to need to get as low level as that.
EDIT:
Previous Implementation using gmaps / three.js : volvooceanrace
(wait for button on left to go from grey to black) click on top button which shows a 'wind' label when hovered over, slide red time bar underneath to change data.
Added screenshot of current working implementation
Mapbox GL Arrows
Not sure what was available in 2016, but a reasonable approach these days might be to use symbol layers, and the icon-rotate data-driven property to rotate each icon based on the property of its data point.

Three.js rotate everything except camera

I have given up trying to orbit a camera around my scene in Three.js and have now decided to revert to doing what I used to do in XNA, just rotate everything except the camera.
The reason I have given up is because I cannot get the camera to orbit properly 360 degrees in all the axis, it starts inverting after going over the top or under the bottom. Using THREE.OrbitControls does not solve this because it merely restricts rotation in the problematic axis instead of fixing the problem.
My problem is now getting this other rotation story working. What I have done is put all objects except the camera in another object "rotSection" and I am now just rotating that object. This is working but rotation is always performed according to the relative (0, 0, 0) position of the rotation object which seems to always stay in the one corner but I would like to rotate around the centre of my world on not around the edge. I have tried to centre the rotSection relative to the scene but it still rotates around its corner and not its centre. Any idea how I can get rotation of an Object3D around a certain point?
The engines don’t move the ship at all. The ship stays where it is and
the engines move the universe around it.
Futurama
The camera in 3d technically never rotates, everything else is rotated and move in order to bring it to camera's local space. You don't have to do any tricks in order to do this, this should be the core of the 3d engine, setting the matrices, setting up the shaders, and doing the correct transforms. Three.js does this for you.
Perhaps you should look into quaternions? Specifically the axisAngle conversion to quats. THREE.OrbitControls won't do what you want.

Setting up a 2D view in Three.js

I'm new to three.js and am trying to set up what amounts to a 2D visualization (for an assortment of layered sprites) using these 3D tools. I'd like some guidance on the PerspectiveCamera() arguments and camera.position.set() arguments. I already have a nudge in the right direction from this answer to a related question, which said to set the z coordinate equal to 0 in camera.position.set(x,y,z).
Below is the snippet of code I'm modifying from one of stemkoski's three.js examples. The parts that are hanging me up for the moment are the values for the VIEW_ANGLE, x, and y. Assuming I want to have a flat camera view on a plane the size of the screen how should I assign these variables? I've tried range of values but it's hard to tell from the visualization what is happening. Thanks in advance!
var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;
var VIEW_ANGLE = ?, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000;
camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);
scene.add(camera);
var x = ?, y = ?, z = 0;
camera.position.set(x,y,z);
camera.lookAt(scene.position);
UPDATE - perspective vs orthographic camera:
Thanks #GuyGood, I realize I need to make a design choice about the perspective camera versus the orthographic camera. I now see that the PerspectiveCamera(), even in this 2D context would allow for things like parallax, whereas OrthographicCamera() would allow for literal rendering of sizes (no diminishing with distance) no matter what layer my 2D element is on. I'm inclined to think I'll still use the PerspectiveCamera() for effects such as small amounts of parallax between the sprite layers (so I guess my project is not purely 2D!).
It seems then that the main thing is to make all the sprite layers parallel to the viewing plane and that camera.position.set() is the orthogonal viewing line to the center of the field of view.This must be basic for so many folks here; it is such a new world to me!
I think I still have a hard time wrapping my head around the role of VIEW_ANGLE, x, and y and the distance between the camera and the far and near viewing planes in a 2D visualization. With the orthographic camera this is pretty immaterial - you just need enough depth to include all the layers you want and a viewing plane that suits the scale of your sprites. However, with the perspective camera the role of depth and field influences the effect of parallax, but are there other considerations as well?
UPDATE 2 - Angle of view and other variables:
After a bit more tooling around in pursuit of how to think about Angle of View (Field of View, or FOV) for the camera and the x,y,z arguments for the camera position, I came across this helpful video summary of the role of Field of View in game design (a close enough analog to answer my questions for my 2D visualization). Along with this Field of View tutorial for photographers that I also found helpful (if maybe a touch cheesy ;), these two resources helped me get a sense of how to choose a Field of View for my project and what happens with either very wide or narrow Fields of View (which are measured in number of degrees out of 360). The best results are a mix of what feels like a natural field of vision for a human, depending on the distance of the screen or projection from their face, and is also keenly related to the relative scale of things in the foreground versus background in the visualization (wider fields of view make the background look smaller, narrower fields of view magnify the background - similar to, though not as pronounced as the effect of an orthographic camera). I hope you find this as helpful as I did!
UPDATE 3 - Further reading
For anyone zesting for more detail about camera specifications in a range of uses, you may find chapter 13 of Computer Graphics Principles and Practice as useful as I have for addressing my above questions and much more.
UPDATE 4 - Considerations for the z dimension in the Orthographic camera
As I've continued my project I decided to use the orthographic camera so that I could increment the z dimensions of my sprites in order to avoid z-fighting, yet not have them appear to recede progressively into the distance. By contrast, if I want to make it appear as though a sprite is receding into the distance, I can simply adjust its size. However, today I ran across a silly mistake that I wanted to point out to save others from the same trouble. Although the orthographic camera does not depict receding size as objects are more distant, take care that there is still a back frustrum plane past which objects will be culled from view. Today I accidentally incremented the z values of several of my objects past that plane and could not figure out why they were not showing up on screen. It can be easy to forget this factor about the z coordinate while working with the orthographic camera.
What is your goal? If you do not need perspective distortion, use the orthographic camera.
Also just check the documentation:
https://threejs.org/docs/#api/en/cameras/PerspectiveCamera
View Angle/Fieldof View is self explanatory, if you don't know what it is, read up on it.
http://www.incgamers.com/wp-content/uploads/2013/05/6a0120a85dcdae970b0120a86d9495970b.png
Concerning the x y and z value. Well, this depends on the size of your plane and the distance to the camera. You can either set the camera position or the plane's position and keep the camera at (0,0,0).
Just imagine a plane in 3D space. You can calculate the position of the camera depending on the size of your plane or just go by try and error...
For using the orthographic camera, see this post:
Three.js - Orthographic camera

Including an image with Three.js

I'm actually trying to include a .jpg image into my 3D scene. All solutions i have found consisted in apply those images on meshes as texture : but then the scene does not look like well. Indeed, we can see the mesh border whether it be a plane or sphere... I just want to see the image. Does exist it another solution ?
On my application, i want to rotate an airplane around the earth, and the problem is about including this airplane.
Thanks for your help :)
Perhaps the class THREE.Sprite will accomplish the effect you want. THREE.Sprite can display an image, and can use either screen coordinates (e.g. canvas coordinates) or it can be part of your 3D scene, but a sprite image is always facing the camera. If you want the image to rotate, you do need to use it as a texture on a mesh. Whatever you decide to do in the end, I've posted a bunch of tutorial-style examples at http://stemkoski.github.io/Three.js/ that may help. Good luck!

Categories