Skip to content

Commit

Permalink
Added ability to take screenshots, since it's basically impossible to…
Browse files Browse the repository at this point in the history
… take one normally and get it sync'd right.
  • Loading branch information
bobsomers committed Mar 20, 2011
1 parent 159f5b4 commit fb9decc
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 8 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
SRC = src/main.cpp src/scene.cpp
SRC = src/main.cpp src/scene.cpp src/screenshot.cpp
OBJ = $(SRC:.cpp=.o)
OUT = 3dvgl

Expand Down
Binary file added left_screenshot.tga
Binary file not shown.
Binary file added right_screenshot.tga
Binary file not shown.
70 changes: 63 additions & 7 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ extern "C" {

#include "scene.h"
#include "stereo_helper.h"
#include "screenshot.h"

// global width and height of the window
int GW = 800;
Expand All @@ -20,18 +21,40 @@ struct nvstusb_context *nv_ctx = NULL;
// 3D camera from stereo helper
StereoHelper::Camera cam;

// forces a particular eye to be displayed (for debugging)
// 0 = normal swapping, 1 = left always, 2 = right always
int force_eye = 0;

// controls whether or not the pulsar is rotating
bool rotation = true;

void draw(int eye) {
static float rotation = 0.0f;
static float angle = 0.0f;

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

int show = 0;
switch (force_eye) {
case 0:
show = eye;
break;

case 1:
show = 1;
break;

case 2:
show = 0;
break;
}

// do the camera projection
StereoHelper::ProjectCamera(cam, (float)GW / GH, eye);
StereoHelper::ProjectCamera(cam, (float)GW / GH, show);

// draw Paul Bourke's test scene "pulsar"
rotation += 1.0f;
if (rotation) angle += 1.0f;
PaulBourke::MakeLighting();
PaulBourke::MakeGeometry(rotation);
PaulBourke::MakeGeometry(angle);
}

void idle() {
Expand All @@ -51,9 +74,24 @@ void idle() {
struct nvstusb_keys k;
nvstusb_get_keys(nv_ctx, &k);

if (k.toggled3D) printf("TOGGLE!\n");
if (k.deltaWheel != 0) printf("DELTA WHEEL %d\n", k.deltaWheel);
if (k.pressedDeltaWheel != 0) printf("PRESSED DELTA WHEEL %d\n", k.pressedDeltaWheel);
// the 3D button on the IR emitter controls toggling the rotation on and
// off
if (k.toggled3D) {
rotation = !rotation;
printf("Toggled rotation.\n");
}

// the wheel on the back adjusts the focal length of the camera (and
// interoccular distance, since we want to maintain IOD = 1/30th of the
// focal length)
if (k.deltaWheel != 0) {
cam.focal += k.deltaWheel;
cam.iod = cam.focal / 30.0f;
printf("Set camera focal length to %f.\n", cam.focal);
}

// you can also use k.pressedDeltaWheel, which reports the amount the wheel
// moves while the 3D button is pressed
}

void keyboard(unsigned char key, int x, int y) {
Expand All @@ -70,6 +108,23 @@ void keyboard(unsigned char key, int x, int y) {
cam.type = StereoHelper::TOE_IN;
printf("Using toe-in stereo camera.\n");
}
break;

case 'f': case 'F': // force eye
force_eye = (force_eye + 1) % 3;
if (force_eye == 0) {
printf("Swapping eyes normally.\n");
} else if (force_eye == 1) {
printf("Forcing left eye always.\n");
} else {
printf("Forcing right eye always.\n");
}
break;

case 's': case 'S': // take screenshot
Screenshot::Screenshot(0, 0, GW, GH, "screenshot.tga");
printf("Wrote frame buffer to screenshot.tga.\n");
break;
}
}

Expand Down Expand Up @@ -112,6 +167,7 @@ int main(int argc, char *argv[]) {
glShadeModel(GL_SMOOTH);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
Screenshot::Init();

// set up our 3D camera (see stereohelper.h for more documentation)
cam.type = StereoHelper::PARALLEL_AXIS_ASYMMETRIC;
Expand Down
69 changes: 69 additions & 0 deletions src/screenshot.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <GL/glut.h>

#include "screenshot.h"

void Screenshot::Init() {
// byte alignment
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
}

void Screenshot::Screenshot(int x, int y, int w, int h, const char *filename) {
// read from the front buffer
glReadBuffer(GL_FRONT);

// grab the pixel data
uint8_t buffer[w * h * (3 * sizeof(uint8_t))];
glReadPixels(x, y, w, h, GL_RGB, GL_UNSIGNED_BYTE, buffer);

// open the file for writing
FILE *fp = fopen(filename, "wb");
if (fp == NULL) {
perror("Failed to open screenshot file for writing!");
exit(EXIT_FAILURE);
}

// write 24-bit uncompressed targa header
// thanks to Paul Bourke (http://local.wasp.uwa.edu.au/~pbourke/dataformats/tga/)
putc(0, fp);
putc(0, fp);
putc(2, fp); // type is uncompressed RGB
putc(0, fp);
putc(0, fp);
putc(0, fp);
putc(0, fp);
putc(0, fp);
putc(0, fp); // x origin, low byte
putc(0, fp); // x origin, high byte
putc(0, fp); // y origin, low byte
putc(0, fp); // y origin, high byte
putc(w & 0xff, fp); // width, low byte
putc((w & 0xff00) >> 8, fp); // width, high byte
putc(h & 0xff, fp); // height, low byte
putc((h & 0xff00) >> 8, fp); // height, high byte
putc(24, fp); // 24-bit color depth
putc(0, fp);

// write the image data
for (int j = 0; j < h; j++) {
for (int i = 0; i < w; i++) {
// calculate the offset into the buffer
int offset = (i + j * w) * (3 * sizeof(uint8_t));

// copy out the bytes
uint8_t r = buffer[offset + 0];
uint8_t g = buffer[offset + 1];
uint8_t b = buffer[offset + 2];

// write out the bytes in BGR order
putc(b, fp);
putc(g, fp);
putc(r, fp);
}
}

fclose(fp);
}
16 changes: 16 additions & 0 deletions src/screenshot.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifndef __SCREENSHOT_H__
#define __SCREENSHOT_H__

namespace Screenshot {

// Sets OpenGL state such that we can take screenshots later.
void Init();

// Writes the framebuffer to a targa file with the specified filename.
// Region is from (x, y) in the bottom left to (x + w, y + h) in the top
// right.
void Screenshot(int x, int y, int w, int h, const char *filename);

}

#endif // __SCREENSHOT_H__

0 comments on commit fb9decc

Please sign in to comment.