Blender V2.61 - r43446
|
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