Git Product home page Git Product logo

Comments (2)

urbien avatar urbien commented on August 18, 2024

Physics engines have a notion of a Renderer, in our case we are only concerned with DOM Renderer at the moment. We first approached this design for web worker thinking that we need to tun Renderer on a main thread and Physics engine on the web worker. But this notion was too simplistic. Note that Sliding window component below. It supposedly belongs to the Renderer, as it controls which objects are added or removed from DOM, but it can do all its calculations on web worker. Same with the Layout Manager, which probably corresponds best to a Scene manager in typical Physics engines.

So we ended up with the following architecture:

Web worker thread runs code for:

  1. Physics simulation. A physics engine (PhysicsJS now, with more like p2.js to follow) is used to make HTML5 objects (otherwise called bricks, tiles or bodies) move realistically by simulating physical forces with temporal aliasing to adjust for highly fluctuating frame rate on mobiles.
  2. Layout. Urbini uses a hybrid layout model. We let browser lay out inside the bricks, but we use JS layout manager, like a modified masonry.js to lay out the bricks on the page. The advantage of this model is that a brick is represented by a separate GPU bitmap and JS code can control its movements in 3D by setting brick's style.transform to a specific matrix3d. This proves to work really fast.
  3. Sliding window. Browser can only efficiently handle DOM with the small amount of elements. The goal of the sliding window is to keep in DOM only things that might be viewed by the user soon (determined by screen size, scroll speed, direction, etc.). Specifically for scrolling this means adding objects to the DOM in the direction of the scroll and removing them from the opposite side of the DOM. This technique seems to be a 2D equivalent of frustum culling used in 3D games, e.g. a new mobile WebGL game Hobbit Experience, which used culling algo from three.js. To better understand the role of a sliding window component in overall architecture, note that we discussed its implementation based on camera. To provide bouncing at the edges of content, camera would need to be a point object itself. @TomWHall even implemented camera in PhysicsJS based on issue we opened. But this approach did not work for us as PhysicsJS at the moment has no mechanism that would tell DOM Renderer what world objects are outside of the viewport and can be thus culled.

There is a message passing mechanism between worker and the main thread.
Mark, could you document it so that we could help Stefan and Jasper figure out how to reflect that better into their engines.

from urbini.

mvayngrib avatar mvayngrib commented on August 18, 2024

I'm not sure how @wellcaffeinated planned to use the web worker, the way we use it may not be quite generic enough for inclusion in the PhysicsJS library. Currently we have the whole physics engine in the worker. The main thread wouldn't know mass from acceleration if an apple fell on its head.

There are/were a few considerations:

  1. Everything that goes through the worker is async.
    Originally I wanted the worker to be as stupid as possible, so that the main thread could use virtually the same API to the physics engine as if the engine ran in the main thread. The async nature of the worker helped me abandon this idea, but I revisit it in my dreams occasionally. Instead we added ids to bodies (and may add them in the future to other objects), so that if the main thread wants to refer to a body/constraint/behavior/etc., it has a handle on it after instantiation. Many methods on the worker side simply convert from id to PhysicsJS entity and then call the intended PhysicsJS method on it.
  2. Clock.
    This is an issue that's still up for debate (and performance testing). Currently we don't run a synchronized clock between the worker and the main thread. The worker runs its own ticker and ticks away constantly (until @wellcaffienated gives us a fall-asleep-when-idle function), and the main thread basically just sits there and waits for updates. When it gets updates, it queues them up for consumption via requestAnimationFrame. This way the main thread's idle most of the time, unless something is happening on the screen. We also added a rendering resolution option to the PhysicsJS engine so we wouldn't re-render on changes less than a pixel (for example).
  3. Layout vs rendering (DOM only for now).
    We wanted to free up the main thread as much as possible, so the worker runs all the physics and sends just the CSS transforms to the main thread. In the worker, we have a layout manager which is a port of jquery.masonry by @desandro. We decided that masonry suited most of our layout needs, and that eventually every page could be laid out as masonry, if a trivial one in most cases. The main thread appends elements to the DOM, sends their dimensions to the worker, the worker lays them out and keeps track of their positions and sends the latest CSS transforms to the main thread when it decides there's something render-worthy. The sliding window that @urbien brought up is also essentially a part of the layout manager. It does however require more coordination with the main thread. It has its own simple API directed from the worker to the main thread, something along the lines of "give me more bricks," and "I removed these bricks."
  4. Synchronized representation.
    Our main thread has a MutationObserver on all bodies whose size it cares about for the purposes of updating/fixing the masonry in realtime. Each masonry instance is bounded, but those bounds can and do change dynamically. For example, an accordion widget changes the container's size with the user's every choice. In order to snap to bounds accurately, the worker needs to get updates about the new sizes of its masonry containers.

from urbini.

Related Issues (12)

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.