April 25, 2016

Markup3D Sample for View & Data API

Default blog image

    Here is a reworked version of one of my early sample for View & Data API: This illustrates how you can create markups pointing to a specific point on your model. The main feature is that the markups display a 2D symbol on the canvas and is hooked up to camera events, so when rotating the model, the 3D world point changes position and so does the 2D symbol, giving the impression that the markup sticks to that point.

There are few remarks about the implementation that I wanted to highlight in this post:

I extensively used SVG to handle any 2D symbol on top of the WebGL canvas: this is clearly what gives the most flexibility and nicest visuals as far as 2D graphics are concerned. To manipulate SVG, I find Snap.svg pretty handy, a thin wrapper I already blogged about previously. 

I am splitting the source into several files as it makes sense and also facilitate code reuse, then I rely on a build step using webpack to bundle all those files, including also the .css, into a single .js that can easily be loaded by my main application. Also webpack makes it very easy to use Babel to transpile code to enjoy all the benefits of ES2015 modern syntax.

Here are how the extension files look like: 

Screen Shot 2016-04-22 at 17.32.15

The entry point is Viewing.Extension.Markup3D.js but most the logic is implemented in the tool and LeaderNote classes. One thing that is interesting to point out is that the markups can be stored as part of the state. This isn't a documented feature, but if you look into the source code for viewer.getState and viewer.restoreState you will see that those methods are iterating through the loaded extensions in order to let them inject or restore custom state data. 

In order to use that feature, all you need to do is implementing those same methods in your extension, which looks has below in my sample:

 1 /////////////////////////////////////////////////////////////////
 2 //
 3 //  From viewer.getState: 
 4 //  Allow extensions to inject their state data
 5 //
 6 //  for (var extensionName in viewer.loadedExtensions) {
 7 //    viewer.loadedExtensions[extensionName].getState(
 8 //      viewerState);
 9 //  }
10 /////////////////////////////////////////////////////////////////
11 getState(viewerState) {
13   this.markup3DTool.getState(
14     viewerState);
15 }
17 /////////////////////////////////////////////////////////////////
18 //
19 //    From viewer.restoreState: 
20 //    Allow extensions to restore their data
21 //
22 //    for (var extensionName in viewer.loadedExtensions) {
23 //      viewer.loadedExtensions[extensionName].restoreState(
24 //        viewerState, immediate);
25 //    }
26 /////////////////////////////////////////////////////////////////
27 restoreState(viewerState, immediate) {
29   this.markup3DTool.restoreState(
30     viewerState, immediate);
31 }

The complete implementation is available from there: Viewing.Extension.Markup3D

And here is a sample you can play with. It also includes the StateManager so you can save and restore markups. Click any point on the model to create new markups, double click a label to edit the markup properties, drag an existing label to modify its position.



Related Posts