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