Final Project: Aurora
For my project, I wanted to build a hologram after being shown a particular method used in the project Light Barrier by the group Kimchi and Chips. For my project I wanted to reproduce this effect in a smaller scale using lenses rather than mirrors and with much less funding.
For hardware, I made a wooden box with a mirror inside it and a platform on which a projector can be placed. On the top of the box is a hole in which wide-angle (concave) Fresnel lenses are placed. I also created a clear acrylic box which is placed on top of the first box to hold fog in place over the lenses. I purchased a fog machine from Guitar Center for the production of the fog.
For software, I made a C++ program which minimally utilizes Cinder. In this program I implemented methods which calculate the scene from the perspective of each lens. I do this using the thin lens formula.
Here is the relevant code for drawing the view.
void GhostApp::draw()
{
// clear out the window with black
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
float camToLensDist = 1000.0f;
float lensWidth = 35.0f; //number in mm
float lensHeight = 35.0f; //number in mm
float lensFocal = -40.0f/2.0f; // number in mm
int numXLenses = 10;
int numYLenses = 5;
for (int x = 0; x < numXLenses; x++){
for (int y = 0; y < numYLenses; y++){
// set the viewport
glViewport(config.offsetX + x*(config.viewWidth / numXLenses), config.offsetY + y*(config.viewHeight / numYLenses), config.viewWidth / numXLenses, config.viewHeight / numYLenses);
// lens, object and image positions
float lensCenterX = lensWidth*0.5f + (lensWidth*x) - (lensWidth*numXLenses*0.5);
float lensCenterY = lensHeight*0.5f + (lensHeight*y) - (lensHeight*numYLenses*0.5);
//distance to projector on xy plane
float Ho = sqrtf(lensCenterX*lensCenterX + lensCenterY*lensCenterY);
//distance to projector on z axis
float Do = camToLensDist;
//focal point
float f = lensFocal;
// 1/f = 1/di + 1/do
float Di = 1.0f / ((1.0f / f) - (1.0f / Do));
// -Di/Do = Hi/Ho
float Hi = (-Di*Ho) / Do;
float camX = (Hi == 0.0f) ? 0.0f : lensCenterX*(1.0f - (Hi / Ho));
float camY = (Hi == 0.0f) ? 0.0f : lensCenterY*(1.0f - (Hi / Ho));
float nearZ = camToLensDist*(-Di / Do);
float camZ = -(camToLensDist - nearZ);
float farZ = 10000.0f;
float left = (x*lensWidth - (numXLenses*lensWidth*0.5f)) - camX;
float right = ((x + 1)*lensWidth - (numXLenses*lensWidth*0.5f)) - camX;
float top = (y*lensHeight - (numYLenses*lensHeight*0.5)) - camY;
float bottom = ((y + 1)*lensHeight - (numYLenses*lensHeight*0.5)) - camY;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(left, right, top, bottom, nearZ, farZ);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gl::translate(-camX, -camY, -camZ - camToLensDist);
gl::scale(1.0f, 1.0f, -1.0f);
switch (scene){
case 0:
drawSpinSphereCircle();
break;
case 1:
drawDeer();
break;
case 2:
drawLine();
break;
default:
drawSpinSphereCircle();
scene = 0;
break;
}
glFlush();
}
}
// draw guide grids to help lens placement
if (grids){
glClear(GL_DEPTH_BUFFER_BIT);
glViewport(config.offsetX, config.offsetY, config.viewWidth, config.viewHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, config.viewWidth, 0, config.viewHeight, -10, 10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
for (int x = 1; x < numXLenses; x++){
gl::drawSolidRect(Rectf(x*(config.viewWidth / numXLenses) - 4.0f, 0, x*(config.viewWidth / numXLenses) + 4.0f, config.viewHeight));
}
for (int y = 1; y < numYLenses; y++){
gl::drawSolidRect(Rectf(0, y*(config.viewHeight / numYLenses) - 4.0f, config.viewWidth, y*(config.viewHeight / numYLenses) + 4.0f));
}
glFlush();
}
}
I’m proud of the software and the math that went into the system. I felt the build quality of the box could have been better had I planned the system more before building. The outcome and final visual is blurry and less defined than I had expected. I attribute this to a lack of clarity from the lenses and a lack of precision in the lens setup. All in all, I appreciate the project and feel that I have made something pleasing to look at.