XB PointStream Release 0.1

I’m working with Mickael Medel at Seneca College’s CDOT (Center for Development of Open Technology) on XB PointStream, a JavaScript tool which will render high quality point clouds in the browser. If you have a WebGL-enabled browser, check out our 0.1 release!


For a 0.1 release, I think we have something fairly decent. I does mostly what it should–it renders a large amount of point cloud data on Minefield, Webkit and Chrome at a fast frame rate. The largest issue we have right now is compressing files, which Mickael is working on.

It took a while to get to 0.1 and I think we’re on the right track. Here’s how we did it:

Creating the Octree

The fundamental problem we face is that of rendering millions of points in the browser in real time. I knew one way we could speed up rendering is to spatially partition the point cloud and do frustum culling. I looked into a few different forms of spatial partitioning and found octrees could be an appropriate data structure. After doing a bit of research and reading, I felt I had an understanding of how to implement one and wrote one in a Processing sketch. As test data, I just generated a series of random points along the surface of a sphere and inserted them into the octree:

The theory was if I had it working on Processing, I could take the exact sketch and feed it into Processing.js. Using a WebGL-capable browser, I should see a similar result. Unfortunately, I did run into a bug, which took up an entire evening to track down. I got some help from the Processing.js community and by using a newer parser, I managed to make the octree and points render on Minefield using Processing.js. The main problem was it was very slow.

Parsing ASC Files

After I had a (mostly) working octree, I was interested to see it accept some real data. I used Arius3D‘s PointStream ImageSuite to convert a PSI file into something I could easily parse, an ASC file. This format presents the data in an easy human and computer readable format:

-8.088 -12.421 -14.033 64 32 16 -0.372 -0.247 -0.894
-8.088 -12.293 -14.033 64 40 24 -0.380 -0.153 -0.911
-8.088 -12.165 -14.033 56 40 24 -0.341 -0.012 -0.939

It was clear the order was positions, colors then normals. I wrote up a small XHR script to download the data, split on spaces, parsed the strings to numbers and inserted the values into the octree. I managed to make it render, but only at around 1 FPS.

Performance Explosion

The problem with Processing.js is there isn’t a way to create a shape once and render it from a cached buffer. Each frame, shapes need to be re-created in case they deform. The renderer then suffers a performance hit, but this has been filed on our lighthouse account. So I had to create a work-around and optimization to get things rendering at a decent frame rate.

A related problem is that Processing.js renders points by translating and drawing the data in a VBO which contains only one primitive. This works if rendering a particle system which only has a few hundred points, but not for dense point clouds. I knew by increasing the VBO to larger size, I could improve performance, but I had no idea how much of an increase I would see. I spent almost two days hacking apart pieces of Processing.js, fixing my octree, stitching pieces of JavaScript within my sketch and debugging until I had the point cloud rendered. I checked the frame rate and I was completely surprised at the performance gain. We were now rendering at ~50 FPS for 150,000 lit points. Depending on the depth of the octree, I see performance between 20 to 50 FPS. The more octants there are, the more culling can be done, but the performance does suffer. This is something we’ll need to work on.

Next Steps

I recently added some fixes so XB PointStream renders on Chrome and I’ll be implementing octant/frustum culling this week. I’ll also start to remove the Processing.js crutch so our library can begin to take shape.