Blender V2.61 - r43446

GPC_Canvas.cpp

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): none yet.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #ifndef NOPNG
00034 #ifdef WIN32
00035 #include "png.h"
00036 #else
00037 #include <png.h>
00038 #endif
00039 #endif // NOPNG
00040 
00041 #include "RAS_IPolygonMaterial.h"
00042 #include "GPC_Canvas.h"
00043 
00044 GPC_Canvas::TBannerId GPC_Canvas::s_bannerId = 0;
00045 
00046 
00047 GPC_Canvas::GPC_Canvas(
00048     int width,
00049     int height
00050 ) : 
00051     m_width(width),
00052     m_height(height),
00053     m_bannersEnabled(false)
00054 {
00055 }
00056 
00057 
00058 GPC_Canvas::~GPC_Canvas()
00059 {
00060     DisposeAllBanners();
00061 }
00062 
00063 
00064 //  void GPC_Canvas::InitPostRenderingContext(void)
00065 //  {
00066 //      glViewport(0, 0, m_width, m_height);
00067 //      glMatrixMode(GL_PROJECTION);
00068 //      glLoadIdentity();
00069     
00070 //      glOrtho(-2.0, 2.0, -2.0, 2.0, -20.0, 20.0);
00071 
00072 //      glMatrixMode(GL_MODELVIEW);
00073 //      glLoadIdentity();
00074 
00075 //      glEnable(GL_DEPTH_TEST);
00076 
00077 //      glDepthFunc(GL_LESS);
00078 
00079 //      glShadeModel(GL_SMOOTH);
00080 //  }
00081 
00082 void GPC_Canvas::Resize(int width, int height)
00083 {
00084     m_width = width;
00085     m_height = height;
00086 }
00087 
00088 void GPC_Canvas::EndFrame()
00089 {
00090     if (m_bannersEnabled)
00091         DrawAllBanners();   
00092 }
00093 
00094 
00095 void GPC_Canvas::ClearColor(float r, float g, float b, float a)
00096 {
00097     ::glClearColor(r,g,b,a);
00098 }
00099 
00100 void GPC_Canvas::SetViewPort(int x1, int y1, int x2, int y2)
00101 {
00102         /*  x1 and y1 are the min pixel coordinate (e.g. 0)
00103             x2 and y2 are the max pixel coordinate
00104             the width,height is calculated including both pixels
00105             therefore: max - min + 1
00106         */
00107         
00108         /* XXX, nasty, this needs to go somewhere else,
00109          * but where... definitly need to clean up this
00110          * whole canvas/rendertools mess.
00111          */
00112     glEnable(GL_SCISSOR_TEST);
00113 
00114     glViewport(x1,y1,x2-x1 + 1,y2-y1 + 1);
00115     glScissor(x1,y1,x2-x1 + 1,y2-y1 + 1);
00116 };
00117 
00118 
00119 void GPC_Canvas::ClearBuffer(
00120     int type
00121 ){
00122 
00123     int ogltype = 0;
00124     if (type & RAS_ICanvas::COLOR_BUFFER )
00125         ogltype |= GL_COLOR_BUFFER_BIT;
00126     if (type & RAS_ICanvas::DEPTH_BUFFER )
00127         ogltype |= GL_DEPTH_BUFFER_BIT;
00128 
00129     ::glClear(ogltype);
00130 }
00131 
00132 
00133 GPC_Canvas::TBannerId GPC_Canvas::AddBanner(
00134     unsigned int bannerWidth, unsigned int bannerHeight,
00135     unsigned int imageWidth, unsigned int imageHeight,
00136     unsigned char* imageData, 
00137     TBannerAlignment alignment, bool enabled)
00138 {
00139     TBannerData banner;
00140 
00141     banner.alignment = alignment;
00142     banner.enabled = enabled;
00143     banner.displayWidth = bannerWidth;
00144     banner.displayHeight = bannerHeight;
00145     banner.imageWidth = imageWidth;
00146     banner.imageHeight = imageHeight;
00147     unsigned int bannerDataSize = imageWidth*imageHeight*4;
00148     banner.imageData = new unsigned char [bannerDataSize];
00149     ::memcpy(banner.imageData, imageData, bannerDataSize);
00150     banner.textureName = 0;
00151 
00152     m_banners.insert(TBannerMap::value_type(++s_bannerId, banner));
00153     return s_bannerId;
00154 }
00155 
00156 
00157 void GPC_Canvas::DisposeBanner(TBannerId id)
00158 {
00159     TBannerMap::iterator it = m_banners.find(id);
00160     if (it != m_banners.end()) {
00161         DisposeBanner(it->second);
00162         m_banners.erase(it);
00163     }
00164 }
00165 
00166 void GPC_Canvas::DisposeAllBanners()
00167 {
00168     TBannerMap::iterator it = m_banners.begin();
00169     while (it != m_banners.end()) {
00170         DisposeBanner(it->second);
00171         it++;
00172     }
00173 }
00174 
00175 void GPC_Canvas::SetBannerEnabled(TBannerId id, bool enabled)
00176 {
00177     TBannerMap::iterator it = m_banners.find(id);
00178     if (it != m_banners.end()) {
00179         it->second.enabled = enabled;
00180     }
00181 }
00182 
00183 
00184 void GPC_Canvas::SetBannerDisplayEnabled(bool enabled)
00185 {
00186     m_bannersEnabled = enabled;
00187 }
00188 
00189 
00190 void GPC_Canvas::DisposeBanner(TBannerData& banner)
00191 {
00192     if (banner.imageData) {
00193         delete [] banner.imageData;
00194         banner.imageData = 0;
00195     }
00196     if (banner.textureName) {
00197         ::glDeleteTextures(1, (GLuint*)&banner.textureName);
00198     }
00199 }
00200 
00201 void GPC_Canvas::DrawAllBanners(void)
00202 {
00203     if(!m_bannersEnabled || (m_banners.size() < 1))
00204         return;
00205     
00206     // Save the old rendering parameters.
00207 
00208     CanvasRenderState render_state;
00209     PushRenderState(render_state);
00210 
00211     // Set up everything for banner display.
00212     
00213     // Set up OpenGL matrices 
00214     SetOrthoProjection();
00215     // Activate OpenGL settings needed for display of the texture
00216     ::glDisable(GL_LIGHTING);
00217     ::glDisable(GL_DEPTH_TEST);
00218     ::glDisable(GL_FOG);
00219     ::glEnable(GL_TEXTURE_2D);
00220     ::glEnable(GL_BLEND);
00221     ::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00222 
00223     TBannerMap::iterator it = m_banners.begin();
00224     while (it != m_banners.end()) {
00225         if (it->second.enabled) {
00226             DrawBanner(it->second);
00227         }
00228         it++;
00229     }
00230 
00231     PopRenderState(render_state);
00232 }
00233 
00234 
00235 void GPC_Canvas::DrawBanner(TBannerData& banner)
00236 {
00237     if(!banner.enabled)
00238         return;
00239 
00240     // Set up coordinates
00241     int coords[4][2];
00242     if (banner.alignment == alignTopLeft) {
00243         // Upper left
00244         coords[0][0] = 0;
00245         coords[0][1] = ((int)m_height)-banner.displayHeight;
00246         coords[1][0] = banner.displayWidth;
00247         coords[1][1] = ((int)m_height)-banner.displayHeight;
00248         coords[2][0] = banner.displayWidth;
00249         coords[2][1] = ((int)m_height);
00250         coords[3][0] = 0;
00251         coords[3][1] = ((int)m_height);
00252     }
00253     else {
00254         // Lower right
00255         coords[0][0] = (int)m_width - banner.displayWidth;
00256         coords[0][1] = 0;
00257         coords[1][0] = m_width;
00258         coords[1][1] = 0;
00259         coords[2][0] = m_width;
00260         coords[2][1] = banner.displayHeight;
00261         coords[3][0] = (int)m_width - banner.displayWidth;
00262         coords[3][1] = banner.displayHeight;
00263     }
00264     // Set up uvs
00265     int uvs[4][2] = {
00266         { 0, 1},
00267         { 1, 1},
00268         { 1, 0},
00269         { 0, 0}
00270     };
00271 
00272     if (!banner.textureName) {
00273         ::glGenTextures(1, (GLuint*)&banner.textureName);
00274         ::glBindTexture(GL_TEXTURE_2D, banner.textureName);
00275         ::glTexImage2D(
00276             GL_TEXTURE_2D,          // target
00277             0,                      // level
00278             4,                      // components
00279             banner.imageWidth,      // width
00280             banner.displayHeight,   // height
00281             0,                      // border
00282             GL_RGBA,                // format
00283             GL_UNSIGNED_BYTE,       // type
00284             banner.imageData);      // image data
00285         ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00286         ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00287     }
00288     else {
00289         ::glBindTexture(GL_TEXTURE_2D, banner.textureName);
00290     }
00291 
00292     // Draw the rectangle with the texture on it
00293     ::glBegin(GL_QUADS);
00294     ::glColor4f(1.f, 1.f, 1.f, 1.f);
00295     ::glTexCoord2iv((GLint*)uvs[0]);
00296     ::glVertex2iv((GLint*)coords[0]);
00297     ::glTexCoord2iv((GLint*)uvs[1]);
00298     ::glVertex2iv((GLint*)coords[1]);
00299     ::glTexCoord2iv((GLint*)uvs[2]);
00300     ::glVertex2iv((GLint*)coords[2]);
00301     ::glTexCoord2iv((GLint*)uvs[3]);
00302     ::glVertex2iv((GLint*)coords[3]);
00303     ::glEnd();
00304 }
00305 
00306     void
00307 GPC_Canvas::
00308 PushRenderState(
00309     CanvasRenderState & render_state
00310 ){
00311 #if 0
00312 
00313     ::glMatrixMode(GL_PROJECTION);
00314     ::glPushMatrix();
00315     ::glMatrixMode(GL_MODELVIEW);
00316     ::glPushMatrix();
00317     ::glMatrixMode(GL_TEXTURE);
00318     ::glPushMatrix();
00319     // Save old OpenGL settings
00320     ::glGetIntegerv(GL_LIGHTING, (GLint*)&(render_state.oldLighting));
00321     ::glGetIntegerv(GL_DEPTH_TEST, (GLint*)&(render_state.oldDepthTest));
00322     ::glGetIntegerv(GL_FOG, (GLint*)&(render_state.oldFog));
00323     ::glGetIntegerv(GL_TEXTURE_2D, (GLint*)&(render_state.oldTexture2D));
00324     ::glGetIntegerv(GL_BLEND, (GLint*)&(render_state.oldBlend));
00325     ::glGetIntegerv(GL_BLEND_SRC, (GLint*)&(render_state.oldBlendSrc));
00326     ::glGetIntegerv(GL_BLEND_DST, (GLint*)&(render_state.oldBlendDst));
00327     ::glGetFloatv(GL_CURRENT_COLOR, render_state.oldColor);
00328     ::glGetIntegerv(GL_DEPTH_WRITEMASK,(GLint*)&(render_state.oldWriteMask));
00329 #else
00330 
00331     glPushAttrib(GL_ALL_ATTRIB_BITS);
00332 
00333 #endif
00334 }
00335 
00336     void
00337 GPC_Canvas::
00338 PopRenderState(
00339     const CanvasRenderState & render_state
00340 ){
00341 #if 0
00342     // Restore OpenGL settings
00343     render_state.oldLighting ? ::glEnable(GL_LIGHTING) : glDisable(GL_LIGHTING);
00344     render_state.oldDepthTest ? ::glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST);
00345     render_state.oldFog ? ::glEnable(GL_FOG) : ::glDisable(GL_FOG);
00346     render_state.oldTexture2D ? ::glEnable(GL_TEXTURE_2D) : glDisable(GL_TEXTURE_2D);
00347     render_state.oldBlend ? glEnable(GL_BLEND) : ::glDisable(GL_BLEND);
00348     ::glBlendFunc((GLenum)render_state.oldBlendSrc, (GLenum)render_state.oldBlendDst);
00349     render_state.oldWriteMask ? ::glEnable(GL_DEPTH_WRITEMASK) : glDisable(GL_DEPTH_WRITEMASK);
00350 
00351     ::glColor4fv(render_state.oldColor);
00352     // Restore OpenGL matrices
00353     ::glMatrixMode(GL_TEXTURE);
00354     ::glPopMatrix();
00355     ::glMatrixMode(GL_PROJECTION);
00356     ::glPopMatrix();
00357     ::glMatrixMode(GL_MODELVIEW);
00358     ::glPopMatrix();
00359 
00360 #else
00361 
00362     glPopAttrib();
00363 #endif
00364 }
00365 
00366     void
00367 GPC_Canvas::
00368 SetOrthoProjection(
00369 ){
00370     // Set up OpenGL matrices 
00371     ::glViewport(0, 0, m_width, m_height);
00372     ::glScissor(0, 0, m_width, m_height);
00373     ::glMatrixMode(GL_PROJECTION);
00374     ::glLoadIdentity();
00375     ::glOrtho(0, m_width, 0, m_height, -1, 1);
00376     ::glMatrixMode(GL_MODELVIEW);
00377     ::glLoadIdentity();
00378     ::glMatrixMode(GL_TEXTURE);
00379     ::glLoadIdentity();
00380 }
00381 
00382     void
00383 GPC_Canvas::
00384 MakeScreenShot(
00385     const char* filename
00386 ){
00387     png_structp png_ptr;
00388     png_infop info_ptr;
00389     unsigned char *pixels = 0;
00390     png_bytepp row_pointers = 0;
00391     int i, bytesperpixel = 3, color_type = PNG_COLOR_TYPE_RGB;
00392     FILE *fp = 0;
00393 
00394     png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
00395     if (!png_ptr) 
00396     {
00397         std::cout << "Cannot png_create_write_struct." << std::endl;
00398         return;
00399     }
00400 
00401     info_ptr = png_create_info_struct(png_ptr);
00402     if (!info_ptr) 
00403     {
00404         png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
00405         std::cout << "Cannot png_create_info_struct." << std::endl;
00406         return;
00407     }
00408 
00409     if (setjmp(png_jmpbuf(png_ptr))) {
00410         png_destroy_write_struct(&png_ptr, &info_ptr);
00411         delete [] pixels;
00412         delete [] row_pointers;
00413         // printf("Aborting\n");
00414         if (fp) {
00415             fflush(fp);
00416             fclose(fp);
00417         }
00418         return;
00419     }
00420 
00421     // copy image data
00422 
00423     pixels = new unsigned char[GetWidth() * GetHeight() * bytesperpixel * sizeof(unsigned char)];
00424     if (!pixels) {
00425         std::cout << "Cannot allocate pixels array" << std::endl;
00426         return;
00427     }
00428 
00429     glReadPixels(0, 0, GetWidth(), GetHeight(), GL_RGB, GL_UNSIGNED_BYTE, pixels);
00430 
00431     fp = fopen(filename, "wb");
00432     if (!fp)
00433     {
00434         std::cout << "Couldn't open " << filename << " for writing." << std::endl;
00435         longjmp(png_jmpbuf(png_ptr), 1);
00436     }
00437 
00438     png_init_io(png_ptr, fp);
00439 
00440     /*
00441     png_set_filter(png_ptr, 0,
00442         PNG_FILTER_NONE  | PNG_FILTER_VALUE_NONE |
00443         PNG_FILTER_SUB   | PNG_FILTER_VALUE_SUB  |
00444         PNG_FILTER_UP    | PNG_FILTER_VALUE_UP   |
00445         PNG_FILTER_AVG   | PNG_FILTER_VALUE_AVG  |
00446         PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH|
00447         PNG_ALL_FILTERS);
00448 
00449     png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
00450     */
00451 
00452     // png image settings
00453     png_set_IHDR(png_ptr,
00454                  info_ptr,
00455                  GetWidth(),
00456                  GetHeight(),
00457                  8,
00458                  color_type,
00459                  PNG_INTERLACE_NONE,
00460                  PNG_COMPRESSION_TYPE_DEFAULT,
00461                  PNG_FILTER_TYPE_DEFAULT);
00462 
00463     // write the file header information
00464     png_write_info(png_ptr, info_ptr);
00465 
00466     // allocate memory for an array of row-pointers
00467     row_pointers = new png_bytep [(GetHeight() * sizeof(png_bytep))];
00468     if (!row_pointers) 
00469     {
00470         std::cout << "Cannot allocate row-pointers array" << std::endl;
00471         longjmp(png_jmpbuf(png_ptr), 1);
00472     }
00473 
00474     // set the individual row-pointers to point at the correct offsets
00475     for (i = 0; i < GetHeight(); i++) {
00476         row_pointers[GetHeight()-1-i] = (png_bytep)
00477             ((unsigned char *)pixels + (i * GetWidth()) * bytesperpixel * sizeof(unsigned char));
00478     }
00479 
00480     // write out the entire image data in one call
00481     png_write_image(png_ptr, row_pointers);
00482 
00483     // write the additional chunks to the PNG file (not really needed)
00484     png_write_end(png_ptr, info_ptr);
00485 
00486     // clean up
00487     delete [] (pixels);
00488     delete [] (row_pointers);
00489     png_destroy_write_struct(&png_ptr, &info_ptr);
00490 
00491     if (fp) 
00492     {
00493         fflush(fp);
00494         fclose(fp);
00495     }
00496 }
00497