art with code

2010-06-06

WebGL stereo rendering demo


Cross your eyes and prepare for eyestrain, here comes the WebGL stereogram. Drag with LMB to rotate, drag with MMB to pan, wheel zooms, shift-wheel scales model.

The demo uses glScissor and glViewport to restrict drawing to one side of the viewport, then draws the scene to the left and right sides with the camera offset slightly. The camera offset is along the right-vector of the camera and you can get it by finding the normal of the camera up and look vectors. Basically right = cross((lookAt - position), up), then leftEye = position - (sep/2 * right); rightEye = position + (sep/2 * right). Then you render to left viewport from rightEye and to the right viewport from leftEye.

2010-06-02

Loading WebGL models from tarballs



Plugged the TarGZ loader together with my old OBJ and binary model loaders and emerged with a couple demos that load a model and a texture from a gzipped tarball and render it using WebGL.

Verdict: use uncompressed tarballs and HTTP gzip compression whenever possible. Doing the gzip with JS doesn't cache the uncompressed data transparently (you'd have to do an offline storage hack), and it's kinda slow. Parsing tar vs. plain files is a bit different tradeoff. With tar you only have to manage a single file. With plain files, you need to manage the whole directory hierarchy they live in. Which may not be something that you can or want to do with your file serving host.

One solution is uncompressed tarballs and a .htaccess with deflate filter set for them, though it seems to screw up caching somehow (thanks for the .htaccess tip go to Evgeny Demidov)

AddOutputFilterByType DEFLATE text/html text/plain application/x-tar application/javascript

<Files *.bin>
SetOutputFilter DEFLATE
</Files>

which also helps for JSON models and OBJs and other textual things. The main problem with the tarballs is that loading the images takes a bit longer (read: hundredths / tenths of a second) due to having to dataURLize them. Well. If you pre-dataURL the images, that won't be a problem.

The main benefit of the tarballs is that everything's in a single file and you don't need a chain loader to initialize models in a single step. Instead of first showing an untextured model, then sometime later the model with a diffuse texture, then later the model with a diffuse texture and a normal map, etc., with single-step initialization you get the full textured model once all the data is loaded. Plus, if you have a standard model format of some sort with manifests and whatnot, you can swap models by changing a single URL. You can do that with a plain model.xml or somesuch as well, but then you need to manage multiple files. It's harder to reuse resources inside tarballs than resources as separate files, though.

Also updated the big whale model viewer to be mouse-controllable (drag with LMB to rotate, drag with MMB to pan, scroll wheel to zoom, shift-scroll wheel to scale).

2010-05-31

Holographic video

NHK is developing a holographic TV that doesn't require viewing glasses (via Reddit.)

The premise is simple: put a transparent surface between the viewer and the object. All the viewer sees is the photons coming from the transparent surface. Now sustain the photon emission from the transparent surface as-is and remove the object. To the viewer it looks like nothing has changed. The object seems to be still visible through the surface and you can walk around and look at it from different angles. A hologram! (When I understood the idea, I got a stupid goofy grin and walked around the house going all "WOOHOO! HOLOGRAMS! YEAH!")

Implementation then. The camera lens could be a large sheet of viewing-angle-optimized hemispherical pixels with an RGB light detector for each direction. The viewing device would swap the detectors for emitters. It'd require a huge lens (the size of the display, really) and require multiple times the megapixels of the usual one-directional image (as now each pixel is in fact several pixels, each facing a different direction.)

Except that they're not doing it quite like that. I don't fully understand it, but I think they're using an 2D array of lenses to get a flat projection and then record the resulting 2D image in the usual manner (project to a small CCD/CMOS/whatever). The display is a regular ultra-high-resolution flat panel with a similar array of lenses in front of it. Here's a good presentation slide deck: 3D-TV System Based on Spatial Imaging Method for Future.

2010-05-28

Loading .tar.gz with JavaScript

With the power of copy-pasting code from the INTERNET, I have now created a JavaScript library that streams gzip files and specifically .tar.gz files.

DEFLATE and CRC32 implementations found with Google and tweaked and bolted onto the tar parser. The performance is something between 1-5 MB/s on Chrome, third of that on Minefield.

In action: Demo page
Just the library: gzip.js

2010-05-25

Numbers, numbers

A Finnish copyright survey tells us that copyright infringement costs the Finnish recording industry more than 355 million euros every year. The yearly sales of the Finnish recording industry are around 100 million euros. If 30% of that is profit — 30% being the profit margin for software companies — they spend 70 million to make the records, get 100 million back in sales and pocket a cool 30 million in profit.

Now, as a result of the copyright infringement costs, the costs of the Finnish recording industry are actually 70 + 355 = 425 million euros. They spend 425 million euros, get 100 million back in sales and end up 325 million in the red. I will expect the whole industry to go bankrupt in three months, if not faster. Every euro they spend is costing them five.

2010-05-24

Slideshow-qgl, now with new features

Slideshow-qgl — my tiny slideshow app — now has recursive dir traversal, a fullscreen mode and a slideshow mode. Which makes it more useful than.. most slideshow apps out there. GQview and EOG, I'm looking at you. With a stern eye. And a hint of rebuke.

As you might guess from the name, slideshow-qgl is based on Qt4 and OpenGL. Qt4 makes it relatively easy to write and OpenGL makes it fast to pan & zoom & fade between images.

It follows the mplayer approach to GUI design, specifically "widgets are ugly, get rid of them." This is what it looks like with an image loaded and zoomed in a bit:



Right.

2010-05-21

Parsing tarballs with JavaScript

Update: Check out this augmented version that streams gzipped tarballs.

Here's a small piece of JavaScript to parse tarballs and my custom JSON packfiles. There be four demos as well: loading files from a tar, streaming images from a tar, loading files from a JSON packfile and streaming files from a JSON packfile.

The part that converts images to date URLs is a bit slower than it could be, as it has to strip high bytes off the characters. The upcoming JS File and Blob APIs for binary data handling should help there. Though if you have less than a hundred kB of images, I don't think you'll even notice the delay. Even half a meg of stuff unpacks in a fraction of second on my slow laptop (Pentium M 1.7GHz). If you do need speed, you can convert the images to data URIs beforehand.

Quickly estimating, it'd take something like fifteen seconds to load up a hundred megs of models and textures on my laptop, maybe around 5 s on a decent computer. Doing the initial archive parsing pass would take maybe a second for a hundred meg archive. If that's too slow for you, I want your internet connection. If the hundred meg tarball is split 1:4 geometry:textures, where the geometry takes 20 bytes per tri and the textures are 10x compressed JPEGs, it'd have 1 Mtri geometry and 240 Mpx textures.

The script doesn't handle gzip or any other compression, use gzip-encoding on the server for that. The tar file format is pretty simple: it's based on 512-byte blocks and each file begins with a 512-byte header, followed by the file data padded up to a multiple of 512 bytes. The numbers are represented as octal ASCII (though there is a GNU tar extension that uses binary ints for handling files bigger than 8 GB, which my script doesn't support).

My JSON packfile format consists of a one-line JSON header array of {filename : string, offset : bytes, length : bytes} followed by a newline and the concatenated file contents. Easy to create and parse.

Edit: Added streaming using xhr.readyState == 3 checks. It might cause some stuttering on the page when dataURLing the images, though it should be quite efficient otherwise. Optimizations welcome :)

Blog Archive