taataa / tapspace

Zoomable user interface library for web apps.
https://taataa.github.io/tapspace/
MIT License
58 stars 8 forks source link

Perspective rendering and parallax motion #142

Closed axelpale closed 1 year ago

axelpale commented 4 years ago

(The intention of this issue is to document some design decisions discussed elsewhere.)

What if the scale of a space element would be interpreted as distance from the viewer? Could we have parallax motion effect when user pans the viewport?

Technically, this could be an option of SpaceView whether to render orthographically or perspectively. Under the hood, the main part could be implemented as a set of projections that alter the element's transformation before final rendering. For example we could have a module projections.js with following structure:

exports.orthogonal = setElementTransform;
exports.perspective = (el, tr, oculus) => {
  // do perspective correction for transformation tr
  // call setElementTransform(el, correctedTr)
}

The main downside, as it turns out after a bit of research, is poor computational efficiency. Interaction with the viewport, such as panning and zooming, must be as smooth as possible. The orthographic projection is very efficient because only the CSS transformation of the root DOM element must be modified when the viewport moves. With perspective projection and a vanishing point fixed to viewport center, the transformation of every element must be updated. The computational complexity jumps from O(1) to O(n) where n is the number of elements to render. As the rendering of elements is probably the most computationally intensive task in a tapspace application, such jump is too much.

To overcome the complexity, some optimisation could be done. For example, we could pick a subset of elements to update and do full perspective correction later. This is probably too laborious to implement for now.

Another approach might be to group elements into layers and apply the perspective correction to the layers only, as pointed out by @bptarpley. Given relatively small number of visible layers, and a deep, fractal-like content arrangement, the layer approach would keep the computational complexity at O(log n).

axelpale commented 1 year ago

Perspective rendering was implemented in 2.0.0-alpha.1 by using the matrix3d CSS transform. In 2.0.0-alpha.5 the orthogonal viewport rendering was removed and the concept of planarity was introduced, for API usability gains. This means that while the viewport is always in 3D, elements can be rendered in flat 2D when placed on a Plane component.

Computational efficiency of full 3D was measured to be around 300 elements. With planes, this limit is about 10 times higher, assuming that most of the elements are rendered flat on the plane.

Compatibility suffers a bit in 3D. The way browsers compose the final image from the 3D DOM is not standardised and therefore different engines behave a bit differently. See for example issue #154