#include "PhotoBox.h" // C'tor. PhotoBox::PhotoBox() { mpScreen = NULL; mbDone = false; } // D'tor. PhotoBox::~PhotoBox() { } int PhotoBox::ResizeWindow(int iWidth, int iHeight) { /* Height / width ration */ GLfloat ratio; /* Protect against a divide by zero */ if ( iHeight == 0 ) iHeight = 1; ratio = ( GLfloat )iWidth / ( GLfloat )iHeight; /* Setup our viewport. */ glViewport( 0, 0, ( GLsizei )iWidth, ( GLsizei )iHeight ); /* change to the projection matrix and set our viewing volume. */ glMatrixMode( GL_PROJECTION ); glLoadIdentity( ); /* Set our perspective */ gluPerspective( 45.0f, ratio, 0.1f, 100.0f ); /* Make sure we're chaning the model view and not the projection */ glMatrixMode( GL_MODELVIEW ); /* Reset The View */ glLoadIdentity( ); return (1); } /** * Setup SDL * * @version 0.1 [2006.10.07] */ bool PhotoBox::Init() { int result = 0; // Initialize SDL's subsystems - in this case, only video. if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) { fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError()); exit(1); } // Register SDL_Quit to be called at exit; makes sure things are // cleaned up when we quit. atexit(SDL_Quit); // ---------------------------------------------- tmp /* Fetch the video info */ int videoFlags = 0; /* this holds some info about our display */ const SDL_VideoInfo *videoInfo; videoInfo = SDL_GetVideoInfo( ); if ( !videoInfo ) { fprintf( stderr, "Video query failed: %s\n", SDL_GetError( ) ); return (false); } videoFlags = SDL_OPENGL; /* Enable OpenGL in SDL */ /* this is wrong, the SDL_GL_ macros defined in SDL_video.h are for * operating on your opengl context using SDL_GL_SetAttribute() and * GetAttribute(), they are not SDL_SetVideoMode() bits */ videoFlags |= SDL_GL_DOUBLEBUFFER; /* Enable double buffering */ videoFlags |= SDL_HWPALETTE; /* Store the palette in hardware */ videoFlags |= SDL_RESIZABLE; /* Enable window resizing */ /* This checks to see if surfaces can be stored in memory */ if ( videoInfo->hw_available ) videoFlags |= SDL_HWSURFACE; else videoFlags |= SDL_SWSURFACE; /* This checks if hardware blits can be done */ if ( videoInfo->blit_hw ) videoFlags |= SDL_HWACCEL; /* get a SDL surface */ mpScreen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, videoFlags ); if ( mpScreen == NULL ) { LOG("SDL_SetVideoMode() failed\n"); return (false); } // video----- // Initialize the ARToolKit video subsystem arDebug = 1; char *vconf = "camera.xml"; result = arVideoOpen(vconf); // you may need to change this to the empty string for your platform.. see ARToolkit docs.. if (result == -1) LOG("arVideoOpen() failed\n"); // This function returns the size of the captured video frame, in pixels. result = arVideoInqSize( &mDim[0], &mDim[1] ); if (result == -1) LOG("arVideoInqSize() failed\n"); // Start capturing. result = arVideoCapStart(); if (result == -1) LOG("No camera connected!\n"); // end video ---- /* Sets up OpenGL double buffering */ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // video SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); glViewport(0,0, SCREEN_WIDTH, SCREEN_HEIGHT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0,1,0,1,0,1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glEnable(GL_TEXTURE_2D); glDisable(GL_DEPTH_TEST); // create texture glGenTextures(1, &mVideoTextID); glBindTexture(GL_TEXTURE_2D, mVideoTextID); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); mGLDim[0] = 1; mGLDim[1] = 1; for (int i = 0; i < 2; ++i) { while(mGLDim[i] < mDim[i]) mGLDim[i] <<= 1; mUV[i] = double(mDim[i]) / double(mGLDim[i]); } mTexBuf = new unsigned char[mGLDim[0] * mGLDim[1] * 3]; // end video mbWritten = false; // ---------------------------------------------- end mtp // tmp.. init gl // Enable smooth shading // glShadeModel( GL_SMOOTH ); // Set the background black glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); // Depth buffer setup glClearDepth( 1.0f ); // Enables Depth Testing glEnable( GL_DEPTH_TEST ); // The Type Of Depth Test To Do glDepthFunc( GL_LEQUAL ); // Really Nice Perspective Calculations glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST ); // end tmp init gl ResizeWindow(SCREEN_WIDTH, SCREEN_HEIGHT); // Start console OGLCONSOLE_Create(); OGLCONSOLE_Print("arVideoCapStart(): %d\n", result); OGLCONSOLE_EnterKey(PhotoBox::HandleConsoleCommand); // testing to create a file /* works ! FILE *fp; if ((fp = fopen("test.txt", "w+b"))) { fputc('t', fp); fclose(fp); } */ // HERE IS THE TEST PART int offset = 0; for (int x = 0; x < 100; ++x) { for (int y = 0; y < 100; ++y) { offset = (x * 100) + y; mTexBuf[offset] = 0xFF; mTexBuf[offset+1] = 0x00; mTexBuf[offset+2] = 0xFF; mTexBuf[offset+3] = 0xFF; } } //WritePNG("test.png",mTexBuf, 100, 100); //exit(1); return (true); } int PhotoBox::WritePNG(char *fn, unsigned char *raster, unsigned int w, unsigned int h) { FILE *fp; png_structp png; png_infop info; png_bytepp row_pointers; int i; /* create file */ fp = fopen (fn, "wb"); if (!fp) { // xe_msg (1, "Can not create %s:\n%s", fn, syserrstr()); return (-1); } /* build list of pointers to each row */ row_pointers = (png_bytepp) malloc (h * sizeof(png_bytep)); if (!row_pointers) { // xe_msg (1, "Can not malloc %d PNG row pointers", h); fclose (fp); return (-1); } for (i = 0; i < h; i++) row_pointers[i] = raster + i*(w*3); /* write png */ png = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); info = png_create_info_struct (png); if (setjmp (png_jmpbuf (png))) { // xe_msg (1, "PNG error"); png_destroy_write_struct (&png, &info); free (row_pointers); fclose (fp); return (-1); } png_init_io(png, fp); //void png_set_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, int color_type, int interlace_type, int compression_type, int filter_type); png_set_IHDR ( png // png struct pointer ,info // header info ,w // width ,h // height ,8 // bit depth ,PNG_COLOR_TYPE_RGB // color_type ,PNG_INTERLACE_NONE // interlace type ,PNG_COMPRESSION_TYPE_DEFAULT // compresssion type ,PNG_FILTER_TYPE_DEFAULT // filter type ); png_write_info (png, info); png_write_image (png, row_pointers); png_write_end (png, info); png_destroy_write_struct (&png, &info); free (row_pointers); /* check for io error */ if (ferror(fp)) { // xe_msg (1, "Write error %s:\n%s", fn, syserrstr()); fclose (fp); return (-1); } /* ok */ fclose (fp); return (0); } /* int PhotoBox::WritePNG(const char *file_name, png_bytep *rows, int w, int h, int colortype, int bitdepth ) { mbWritten = true; png_structp png_ptr; png_infop info_ptr; FILE *fp = NULL; char *doing = "open for writing"; if (!(fp = fopen("w.png", "w+b"))) { doing = strerror(errno); goto fail; } //fp = fopen("filename.txt", "wb") doing = "create png write struct"; if (!(png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL))) goto fail; doing = "create png info struct"; if (!(info_ptr = png_create_info_struct(png_ptr))) goto fail; if (setjmp(png_jmpbuf(png_ptr))) goto fail; doing = "init IO"; png_init_io(png_ptr, fp); doing = "write header"; png_set_IHDR(png_ptr, info_ptr, w, h, bitdepth, colortype, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); doing = "write info"; png_write_info(png_ptr, info_ptr); doing = "write image"; png_write_image(png_ptr, rows); doing = "write end"; png_write_end(png_ptr, NULL); doing = "closing file"; if(0 != fclose(fp)) goto fail; OGLCONSOLE_Print("WritePNG() success!"); return 0; fail: //OGLCONSOLE_Print("WritePNG() failed"); OGLCONSOLE_Print("%s\n",doing); arUtilSleep(20); return -1; } */ /** * Execute the main loop, and capture events. * * @version 0.1 [2006.10.07] */ int PhotoBox::Exec() { while (!mbDone) { // Render stuff Render(); // Poll for events, and handle the ones we care about. SDL_Event event; while (SDL_PollEvent(&event)) { if (OGLCONSOLE_SDLEvent(&event) == 0) { switch (event.type) { case SDL_KEYDOWN: break; case SDL_KEYUP: // If escape is pressed, return (and thus, quit) if (event.key.keysym.sym == SDLK_ESCAPE) return 0; break; case SDL_QUIT: { ShutDown(); mbDone = true; break; } } } } } return(1); } /** * Renders the screen. * * @version 0.1 [2006.10.07] */ void PhotoBox::Render() { /* rotational vars for the triangle and quad, respectively */ static GLfloat rtri, rquad; /* These are to calculate our fps */ static GLint T0 = 0; static GLint Frames = 0; // Lock surface if needed if (SDL_MUSTLOCK(mpScreen)) if (SDL_LockSurface(mpScreen) < 0) return; // camera input --------------- ARUint8* buffer = NULL; // while ( ( buffer = arVideoGetImage() ) == NULL ) arUtilSleep(2); buffer = arVideoGetImage(); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); static unsigned char** ss_rows; if (buffer != NULL && !mbWritten) { int y_offset = 0; unsigned char c; int pixel = 0; for (int y = 0; y < mDim[1]; ++y) { //y_offset = y * mGLDim[0] * 3; y_offset = y * mDim[0] * 3; for (int x = 0; x < mDim[0]; ++x) { // The << 2 multiplies the position by 4 moving // it to the correct location of the Uint8 buffer. c = buffer[ (((y) * mDim[0]+(x)) << 2) + 0]; mTexBuf[y_offset + x * 3 + 0] = c; c = buffer[ (((y) * mDim[0]+(x)) << 2) + 1]; mTexBuf[y_offset + x * 3 + 1] = c; c = buffer[ (((y) * mDim[0]+(x)) << 2) + 2]; mTexBuf[y_offset + x * 3 + 2] = c; } } if (!mbWritten) { WritePNG("test.png",mTexBuf, mDim[0], mDim[1]); LOG("Image written.\n"); mbWritten = true; } // WritePNG(".\test1.png", ( png_bytep *)mTexBuf, mDim[0], mDim[1], PNG_COLOR_TYPE_RGB, 8); // exit(1); // Clear The Screen And The Depth Buffer glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glColor3f(1,1,1); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, mVideoTextID); glTexImage2D( GL_TEXTURE_2D ,0 ,3 ,mGLDim[0] ,mGLDim[1] ,0 ,GL_RGB ,GL_UNSIGNED_BYTE ,mTexBuf ); glBegin( GL_QUADS ); glTexCoord2f( 0, 0 ); glVertex2f( 0, 1 ); glTexCoord2f( mUV[0], 0 ); glVertex2f( 0.2, 1 ); glTexCoord2f( mUV[0], mUV[1] ); glVertex2f( 0.2, 0.8 ); glTexCoord2f( 0, mUV[1] ); glVertex2f( 0, 0.8 ); glEnd(); } // end camera input ----------- // test with surface int x = 1; int y = 10; int color=0xff0000; unsigned int *ptr = (unsigned int*)mpScreen->pixels; int lineoffset = y * (mpScreen->pitch / 4); // ptr[lineoffset + x] = color; //SDL_UpdateRect(mpScreen, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); // end test with surface /* Render our console */ OGLCONSOLE_Draw(); /* Draw it to the screen */ SDL_GL_SwapBuffers( ); arVideoCapNext(); // Unlock if needed if (SDL_MUSTLOCK(mpScreen)) SDL_UnlockSurface(mpScreen); } /** * Shuts down SDL, OGLConsole, OpenGL * * @version 0.1 [2006.10.07] */ void PhotoBox::ShutDown() { // Shutdown the console OGLCONSOLE_Quit(); // Cleanup SDL SDL_Quit( ); } void PhotoBox::HandleConsoleCommand(OGLCONSOLE_Console console, char *cmd) { //if (!strncmp(cmd, "quit", 4)) PhotoBox::mbDone = true; if (!strncmp(cmd, "add", 3)) { int a, b; if (sscanf(cmd, "add %i %i", &a, &b) == 2) { OGLCONSOLE_Output(console, "%i + %i = %i\n", a, b, a+b); return; } OGLCONSOLE_Output(console, "usage: add INT INT\n"); return; } OGLCONSOLE_Output(console, "I don't understand this command: %s\n", cmd); } /* void cmdCB(OGLCONSOLE_Console console, char *cmd) { if (!strncmp(cmd, "quit", 4)) done = TRUE; else if (!strncmp(cmd, "add", 3)) { int a, b; if (sscanf(cmd, "add %i %i", &a, &b) == 2) { OGLCONSOLE_Output(console, "%i + %i = %i\n", a, b, a+b); return; } OGLCONSOLE_Output(console, "usage: add INT INT\n"); return; } OGLCONSOLE_Output(console, "I don't understand this command: %s\n", cmd); } */