Recently I had the opportunity to experiment with a Looking Glass Go display. I used the opportunity to extend Camera3D’s functionality to create images in the correct format for displays made by this company.
These displays require you to render a few dozen images of the same scene at slightly different camera angles. The images are then arranged in a grid called a “Quilt”.
The screen then rearranges the pixels inside the lenticular display so that each eye gets a slightly different view of the scene. This creates the 3D effect.
Camera3D takes care of the camera positioning and image arrangements for you, making it easy for Processing and py5 users to create content for these displays.
An example sketch is below:
import camera3D.Camera3D;
Camera3D camera3D;
float rotX = 0;
float rotY = 0;
float rotZ = 0;
void setup() {
// default for Looking Glass Go is 11 columns by 6 rows and a frame size of
// 372 by 682. This makes the quilt size 4092 by 4092.
size(372, 682, P3D);
pixelDensity(displayDensity());
camera3D = new Camera3D(this);
camera3D.setBackgroundColor(color(192));
// the default quilt dimensions are 11x6 with an aspect ratio of 0.5625
// these are the suggested settings for the Looking Glass Go
// set the output location to an appropriate directory on your computer
camera3D.renderLookingGlassQuilt().setQuiltDimensions(11, 6, 0.5625).setOutputLocation("/tmp/frames/");
// 30 second recording at 30 fps
camera3D.setFrameLimit(30 * 30);
strokeWeight(2);
stroke(0);
fill(255, 255, 255);
}
void preDraw() {
rotX += 0.5;
rotY += 0.1;
rotZ += 0.3;
}
void draw() {
translate(width / 2, height / 2, 0);
push();
rotateX(radians(rotX));
rotateY(radians(rotY));
rotateZ(radians(rotZ));
box(125);
pop();
int xSpacing = 100;
int ySpacing = 200;
int zSpacing = 100;
for (int x = -xSpacing; x <= xSpacing; x += 2 * xSpacing) {
for (int y = -ySpacing; y <= ySpacing; y += 2 * ySpacing) {
for (int z = -zSpacing; z <= zSpacing; z += 2 * zSpacing) {
push();
translate(x, y, z);
rotateX(radians(rotX));
rotateY(radians(rotY));
rotateZ(radians(rotZ));
box(25);
pop();
}
}
}
}
Yes, Camera3D works in py5 also. You can find information about how to do that here:
The full sized quilt image is 4092x4092 pixels so I didn’t want to add it to my post. If you want to see that image you can find it with the link at the bottom of this page:
Hmmm, it doesn’t look like it did anything. Did you add pixelDensity(2) to the Sketch right after the call to size()? If that isn’t it, I’m going to have to investigate more. I’m glad py5 gives great results, but I want to undrestand why!
I didn’t add it right after size(); it was about 2 or 3 lines down. However, I moved it to the second line in setup() and the result is the same. To avoid confusion I’m posting the code that I ran as well as the output that goes with that code. I’ve seen this before with other 3D demos that I created first in java mode and then translated to py5; they always seem to look better in py5.
Fascinating. I just looked at py5’s code and Processing’s code and I don’t see any relevant differences. I do note that py5 will call pixelDensity(displayDensity()); on your behalf, but to the best of my knowledge adding that to a Java Sketch should then yield results identical to py5. I’ll have experiment with this some more on my laptop to see what’s going on. Thanks for pointing this out.
The source code was run through different editors: java mode was run by Processing IDE and py5 was run by Thonny. Possibly that makes a difference? Resolution still good when py5 source code is run from command line:
Can you share the code you used for this Python version? You previously posted your Java code.
For my MacOS computer here I see I get the same image for Python and Java. But for this machine I get a warning when I call pixelDensity(2) because this display doesn’t do that. You didn’t mention getting a warning, so your computer must have one of the high density displays.
It’s aimed at real-time, interactive sketches, and includes a few examples and a preview mode for development without the display connected.
Really nice to see another approach to this, especially with py5 support as well! I imagine there are quite a few different challenges when handling the same multiview/quilt pipeline across C++/Java and Python — looking forward to more discussion and exchange around this!
Wow, really? This is awesome! Can you tell me more about how this works? Camera3D can’t do real-time Sketches for Looking Glass displays. I thought that to do so I’d need complex shaders. I looked at your source code and I see some C++ code but no shaders. Can you tell me more about your approach? What kind of frame rate can you get now?
I don’t think the editor should matter here. But I don’t have much of a clue why the renderer works better with py5 compared to Processing. I poured over the code and the only thing I noticed that is different is that with py5, the pixelDensity() call takes place before the call to size(), not after. It is also in a separate settings() method. Can you create a separate settings() function and move the pixelDensity() call and size() calls there?
My monitor is a big screen LG (and high density I thought) but it returns pixelDensity = 1 so that would explain the poor resolution in java mode apparently. I tried setting the pixel density to 2, but it raised an exception and said it was not available. My desktop setup is a mac mini with a bring your own monitor; it is not a notebook or iMac.
What I cannot understand is why the same thing doesn’t happen with py5. It runs ok ‘as is’ with py5 source code and I don’t have to mess with pixelDensity (you have stated that your code took care of that). Why is it that you can set it but I can’t using java mode in the Processing IDE (P3D, openGL renderer)?
Console output:
display count needs to be implemented for non-AWT pixelDensity = 1 AWT disabled, displayWidth/displayHeight will be 0 display count needs to be implemented for non-AWT display count needs to be implemented for non-AWT pixelDensity(2) is not available for this display