Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebGL Implementation of main plotting interface in Grapher. #223

Merged
merged 38 commits into from
Jul 15, 2016

Conversation

adamcw
Copy link
Contributor

@adamcw adamcw commented Jul 12, 2016

Resolves issues #185 and #208. Makes use of WebGL to do the data plotting portion of each graph in order to greatly improve the performance of live data view as well as zoom/pan operations.

d3.js was retained for the axes and and interface as SVG, while THREE.js library was introduced to handle the plotting of the data via WebGL.

This dual library usage was used to get the most performance gain for the least development time, as implementing axes and other features in WebGL will be time consuming. It is a longer term goal to move all plotting towards WebGL in order to allow screenshotting (Issue #184).

Performance was also improved by causing only the parts of the graph that need to be re-rendered under actions like zooming to be re-rendered. This also makes it possible to now retain the zoom level during live updates, the changing of plotting types, and the toggling of traces.

/**
* Import the THREE namespace from the module.
*/
const THREE = three.default;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This throws a compiler error, but was the only way I could get the library to play nicely with TypeScript. If someone can work out how to import the library without this hack, please let me know, I wasted a few hours trying and ultimately moved on.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem here is that the typescript definition files for these libraries (and most libraries actually) were set up assuming they would be imported using CommonJS style imports like in node, rather than es6 imports. To fix this, you have to change the typings file slightly, like so: 7096169

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I did track down that I could probably fix it by changing the typings file, but I didn't like the idea of changing it manually. Doing this will lead to problems whenever someone tries to update the typings in the future without knowing to update the format of the exports.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree it's not ideal to keep these local changes, but this is the reason why we've got the .d.ts definition files checked into the repo, rather than installing them using one of the tools to manage typescript definitions (originally it was tsd, then typings, now the latest thing is to install types packages from npm like @types/three, who knows what it will be next month...). In practice we don't update these definitions very often, but if we do make an update and forget to change the module declaration, at least we get compiler errors to remind us to fix it :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I will leave this line as-is, then submit another PR making the required typings changes and then removing this line.

@adamcw
Copy link
Contributor Author

adamcw commented Jul 12, 2016

I have mostly created this PR to start a dialog on breaking it up further. I figured this would be best done as a semi-team process as this sort of thing is likely to be common as large scale refactors/redesigns become required throughout the codebase(s).

This is ultimately the smallest PR that maintains feature parity as well as builds/runs. This opens the question of if stacking smaller, non-building, PRs may be preferred where they are only merged once all have been reviewed and approved. I don't believe this concept is currently an accepted workflow so I thought a discussion first may be useful.

@maffoo
Copy link
Contributor

maffoo commented Jul 12, 2016

I get a couple of typescript compilation errors, but they're not too hard to fix: e341a33

@adamcw
Copy link
Contributor Author

adamcw commented Jul 12, 2016

Interesting, I do not get any compilation warnings. This might suggest we have different versions of TypeScript running?

/**
* Resets the current zoom level to fit the data.
*/
resetZoomControl() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this is not referenced anywhere.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean attached()? or resetZoomControl()?

attached() is called when the component loads.
resetZoomControl() is called from the html UI element.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant resetZoomControl(). I don't see it referenced anywhere here or in the element html (https://github.com/labrad/scalabrad-web/blob/185-graphing-performance-webgl/client-js/app/elements/labrad-plot.html); am I missing something?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh, I must have merged it poorly. The intent was to have resetZoom be private, then have resetZoomControl be the pubic hook the UI uses.

It's basically a separation of the API the UI calls and the API the internal module calls.

Ultimately, it's a bit of a waste since it's just an alias, but the idea would be that the UI hooks can be altered independently, as well as having UI elements call descriptive names from the HTML, while internally calling a UI independent name.

@adamcw
Copy link
Contributor Author

adamcw commented Jul 13, 2016

@joshmutus 2D Datasets not working is a strange regression, I'm looking into it now.

The zoom rectangle will probably need to be rendered in WebGL rather than SVG. I could render it as a second SVG layer, but since we want to move everything toward WebGL anyway, may as well do it that way now.

@joshmutus
Copy link
Contributor

@adamcw Where you able to recreate the behaviour? I can send you the dataset that chokes up on my system if you like

@adamcw
Copy link
Contributor Author

adamcw commented Jul 13, 2016

I've fixed the rendering portion if that is what you refer to. I restructured the rendering pipeline due to comments and it meant that not everything was updated when it had to be after new data was added.

@joshmutus
Copy link
Contributor

@adamcw renders super nicely for large datasets now. Really really snappy. Thanks.

I have a weird problem, the plot doesn't show up when I'm looking at the app through remote desktop... None of the plot widget loads at all. Neither the axes or the data:
screenshot from 2016-07-13 16 02 42

Renders fine on the same machine, just not through Chrome remote desktop session:
screenshot from 2016-07-13 16 01 18

Any idea what could be happening there?

@adamcw
Copy link
Contributor Author

adamcw commented Jul 13, 2016

That error is when WebGL is disabled in the browser (I've encountered it before trying to do headless testing of WebGL applications). For some reason via remote desktop, WebGL is being disabled, Chrome is probably detecting that you don't have the ability to do proper hardware acceleration through the Remote Desktop and shuts it off.

@joshmutus
Copy link
Contributor

Yikes. Is there a way to force it on? This might be inconvenient if you have to remote desktop into a system to access the webserver, but I suppose that should never happen?

@joshmutus
Copy link
Contributor

This did the trick. We might want to catch this error and bring up a dialog to point to this workaround.

Step 1: Open Google Chrome
Step 2: Type chrome://flags in the address bar
Step 3: Press Ctrl + f and type ” Rendering list “, “Override software rendering list” should come up, >Now click on Enable and restart the browser.

@adamcw
Copy link
Contributor Author

adamcw commented Jul 14, 2016

I determined, that since the zoomRectangle will never be in screenshots anyway, there was no reason not to just render it as a div on top of the plot. PTAL.

@adamcw adamcw added this to the v2.0 milestone Jul 14, 2016
* Fires when the component is attached to the DOM.
*/
attached(): void {
this.plotID = Math.random();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typescript compiler throws an error here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line shouldn't have even been there, fixed.

@@ -1,9 +1,25 @@
import 'd3';

import {THREE} from 'three';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get runtime errors from this. I think this needs to get the default import, rather than an item named 'THREE' from inside the module. That is:

import THREE from 'three';

@maffoo
Copy link
Contributor

maffoo commented Jul 15, 2016

One comment about import (ts compiler doesn't complain, but it fails at runtime; we can investigate this separately). Otherwise LGTM.

@adamcw adamcw merged commit 7d46390 into master Jul 15, 2016
@adamcw adamcw deleted the 185-graphing-performance-webgl branch July 15, 2016 18:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants