Fawkes API  Fawkes Development Version
texture_drawer.cpp
00001 
00002 /***************************************************************************
00003  *  texture_drawer.cpp - Skeleton Visualization GUI: texture drawer
00004  *
00005  *  Created: Tue Mar 29 17:09:25 2011 (on the way to Magdeburg for GO2011)
00006  *  Copyright  2006-2011  Tim Niemueller [www.niemueller.de]
00007  *
00008  ****************************************************************************/
00009 
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version.
00014  *
00015  *  This program is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  *  GNU Library General Public License for more details.
00019  *
00020  *  Read the full text in the LICENSE.GPL file in the doc directory.
00021  */
00022 
00023 #include "texture_drawer.h"
00024 
00025 #include <fvcams/camera.h>
00026 #include <fvutils/color/colorspaces.h>
00027 #include <fvutils/color/conversions.h>
00028 
00029 #include <cstdlib>
00030 #include <cstdio>
00031 #include <algorithm>
00032 #include <GL/glut.h>
00033 
00034 using namespace fawkes;
00035 using namespace firevision;
00036 
00037 /** @class SkelGuiTextureDrawer "texture_drawer.h"
00038  * Draw images from camera in texture.
00039  * Uses texture mapping to show an image acquired from a camera in the
00040  * background.
00041  * @author Tim Niemueller
00042  *
00043  * @fn SkelGuiTextureDrawer::fill_texture()
00044  * Fill texture with data.
00045  * This function is called during draw() and the sub-class shall implement it
00046  * to fill the texture with the data to show. Be aware that the texture size
00047  * and the actually shown size will likely differ.
00048  */
00049 
00050 /** Constructor.
00051  * @param width width of visible area
00052  * @param height height of visible area
00053  */
00054 SkelGuiTextureDrawer::SkelGuiTextureDrawer(unsigned int width, unsigned int height)
00055   : __width(width), __height(height),
00056     __texture_width(get_closest_power_of_two(__width)),
00057     __texture_height(get_closest_power_of_two(__height))
00058 {
00059   __texture = (unsigned char *)malloc(__texture_width *__texture_height * 3);
00060   memset(__texture, 0, __texture_width * __texture_height * 3);
00061 
00062   __texture_initialized = false;
00063 }
00064 
00065 /** Destructor. */
00066 SkelGuiTextureDrawer::~SkelGuiTextureDrawer()
00067 {
00068   free(__texture);
00069 }
00070 
00071 unsigned int
00072 SkelGuiTextureDrawer::get_closest_power_of_two(unsigned int n)
00073 {
00074   unsigned int m = 2;
00075   while(m < n) m<<=1;
00076 
00077   return m;
00078 }
00079 
00080 void
00081 SkelGuiTextureDrawer::init_texture()
00082 {
00083   glGenTextures(1, &__texture_id);
00084   glBindTexture(GL_TEXTURE_2D, __texture_id);
00085 
00086   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00087   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00088 
00089   memset(__texture_coords, 0, sizeof(__texture_coords));
00090   __texture_coords[0] = (float)__width  / __texture_width;
00091   __texture_coords[1] = (float)__height / __texture_height;
00092   __texture_coords[2] = (float)__width  / __texture_width;
00093   __texture_coords[7] = (float)__height / __texture_height;
00094 
00095   __texture_initialized = true;
00096 }
00097 
00098 
00099 void
00100 SkelGuiTextureDrawer::draw_rectangle(float topLeftX, float topLeftY,
00101                                    float bottomRightX, float bottomRightY)
00102 {
00103   GLfloat verts[8] = {  topLeftX, topLeftY, topLeftX, bottomRightY,
00104                         bottomRightX, bottomRightY, bottomRightX, topLeftY };
00105   glVertexPointer(2, GL_FLOAT, 0, verts);
00106   glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
00107   glFlush();
00108 }
00109 
00110 /** Draw texture to screen. */
00111 void
00112 SkelGuiTextureDrawer::draw()
00113 {
00114   if (!__texture_initialized) init_texture();
00115 
00116   fill_texture();
00117 
00118   glBindTexture(GL_TEXTURE_2D, __texture_id);
00119   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, __texture_width, __texture_height,
00120                0, GL_RGB, GL_UNSIGNED_BYTE, __texture);
00121 
00122   // Display the OpenGL texture map
00123   glColor4f(0.75,0.75,0.75,1);
00124 
00125   glEnable(GL_TEXTURE_2D);
00126   glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00127   glTexCoordPointer(2, GL_FLOAT, 0, __texture_coords);
00128   draw_rectangle(__width, __height, 0, 0);
00129   glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00130   glDisable(GL_TEXTURE_2D);
00131 }
00132 
00133 /** Copy an RGB buffer to texture.
00134  * @param rgb_buf the RGB buffer to copy, it must exactly of dimensions __width
00135  * and __height.
00136  */
00137 void
00138 SkelGuiTextureDrawer::copy_rgb_to_texture(const unsigned char *rgb_buf)
00139 {
00140   unsigned char *row = __texture;
00141   unsigned char *tex = __texture;
00142   const unsigned char *rgb = rgb_buf;
00143   unsigned int bytes = 0;
00144   for (unsigned int h = 0; h < __height; ++h) {
00145     tex = row;
00146     for (unsigned int w = 0; w < __width; ++w) {
00147       *tex++ = *rgb++;
00148       *tex++ = *rgb++;
00149       *tex++ = *rgb++;
00150       ++bytes;
00151     }
00152     row += __texture_width * 3;
00153   }
00154 }