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 * Contributor(s): Blender Foundation 00022 * 00023 * ***** END GPL LICENSE BLOCK ***** 00024 */ 00025 00031 #include <stdio.h> 00032 #include <string.h> 00033 00034 #include "MEM_guardedalloc.h" 00035 00036 #include "DNA_vec_types.h" 00037 00038 #include "BLI_utildefines.h" 00039 00040 #include "BKE_colortools.h" 00041 00042 #include "BLI_math.h" 00043 #include "BLI_threads.h" 00044 00045 #include "BIF_gl.h" 00046 #include "BIF_glutil.h" 00047 00048 #ifndef GL_CLAMP_TO_EDGE 00049 #define GL_CLAMP_TO_EDGE 0x812F 00050 #endif 00051 00052 00053 /* ******************************************** */ 00054 00055 /* defined in BIF_gl.h */ 00056 GLubyte stipple_halftone[128] = { 00057 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 00058 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 00059 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 00060 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 00061 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 00062 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 00063 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 00064 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 00065 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 00066 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 00067 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 00068 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 00069 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 00070 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 00071 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 00072 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55}; 00073 00074 00075 /* repeat this pattern 00076 X000X000 00077 00000000 00078 00X000X0 00079 00000000 */ 00080 00081 00082 GLubyte stipple_quarttone[128] = { 00083 136,136,136,136,0,0,0,0,34,34,34,34,0,0,0,0, 00084 136,136,136,136,0,0,0,0,34,34,34,34,0,0,0,0, 00085 136,136,136,136,0,0,0,0,34,34,34,34,0,0,0,0, 00086 136,136,136,136,0,0,0,0,34,34,34,34,0,0,0,0, 00087 136,136,136,136,0,0,0,0,34,34,34,34,0,0,0,0, 00088 136,136,136,136,0,0,0,0,34,34,34,34,0,0,0,0, 00089 136,136,136,136,0,0,0,0,34,34,34,34,0,0,0,0, 00090 136,136,136,136,0,0,0,0,34,34,34,34,0,0,0,0}; 00091 00092 00093 GLubyte stipple_diag_stripes_pos[128] = { 00094 0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe, 00095 0x03, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x07, 0xf8, 00096 0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0, 00097 0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80, 00098 0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01, 00099 0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x07, 0xf8, 0x07, 00100 0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f, 00101 0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f, 00102 0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe, 00103 0x03, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x07, 0xf8, 00104 0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0, 00105 0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80, 00106 0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01, 00107 0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x07, 0xf8, 0x07, 00108 0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f, 00109 0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f}; 00110 00111 00112 GLubyte stipple_diag_stripes_neg[128] = { 00113 0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01, 00114 0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x07, 0xf8, 0x07, 00115 0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f, 00116 0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f, 00117 0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe, 00118 0x03, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x07, 0xf8, 00119 0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0, 00120 0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80, 00121 0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01, 00122 0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x07, 0xf8, 0x07, 00123 0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f, 00124 0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f, 00125 0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe, 00126 0x03, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x07, 0xf8, 00127 0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0, 00128 0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80}; 00129 00130 00131 void fdrawbezier(float vec[4][3]) 00132 { 00133 float dist; 00134 float curve_res = 24, spline_step = 0.0f; 00135 00136 dist= 0.5f*ABS(vec[0][0] - vec[3][0]); 00137 00138 /* check direction later, for top sockets */ 00139 vec[1][0]= vec[0][0]+dist; 00140 vec[1][1]= vec[0][1]; 00141 00142 vec[2][0]= vec[3][0]-dist; 00143 vec[2][1]= vec[3][1]; 00144 /* we can reuse the dist variable here to increment the GL curve eval amount*/ 00145 dist = 1.0f/curve_res; 00146 00147 cpack(0x0); 00148 glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, vec[0]); 00149 glBegin(GL_LINE_STRIP); 00150 while (spline_step < 1.000001f) { 00151 /*if(do_shaded) 00152 UI_ThemeColorBlend(th_col1, th_col2, spline_step);*/ 00153 glEvalCoord1f(spline_step); 00154 spline_step += dist; 00155 } 00156 glEnd(); 00157 } 00158 00159 void fdrawline(float x1, float y1, float x2, float y2) 00160 { 00161 float v[2]; 00162 00163 glBegin(GL_LINE_STRIP); 00164 v[0] = x1; v[1] = y1; 00165 glVertex2fv(v); 00166 v[0] = x2; v[1] = y2; 00167 glVertex2fv(v); 00168 glEnd(); 00169 } 00170 00171 void fdrawbox(float x1, float y1, float x2, float y2) 00172 { 00173 float v[2]; 00174 00175 glBegin(GL_LINE_STRIP); 00176 00177 v[0] = x1; v[1] = y1; 00178 glVertex2fv(v); 00179 v[0] = x1; v[1] = y2; 00180 glVertex2fv(v); 00181 v[0] = x2; v[1] = y2; 00182 glVertex2fv(v); 00183 v[0] = x2; v[1] = y1; 00184 glVertex2fv(v); 00185 v[0] = x1; v[1] = y1; 00186 glVertex2fv(v); 00187 00188 glEnd(); 00189 } 00190 00191 void sdrawline(short x1, short y1, short x2, short y2) 00192 { 00193 short v[2]; 00194 00195 glBegin(GL_LINE_STRIP); 00196 v[0] = x1; v[1] = y1; 00197 glVertex2sv(v); 00198 v[0] = x2; v[1] = y2; 00199 glVertex2sv(v); 00200 glEnd(); 00201 } 00202 00203 /* 00204 00205 x1,y2 00206 | \ 00207 | \ 00208 | \ 00209 x1,y1-- x2,y1 00210 00211 */ 00212 00213 static void sdrawtripoints(short x1, short y1, short x2, short y2) 00214 { 00215 short v[2]; 00216 v[0]= x1; v[1]= y1; 00217 glVertex2sv(v); 00218 v[0]= x1; v[1]= y2; 00219 glVertex2sv(v); 00220 v[0]= x2; v[1]= y1; 00221 glVertex2sv(v); 00222 } 00223 00224 void sdrawtri(short x1, short y1, short x2, short y2) 00225 { 00226 glBegin(GL_LINE_STRIP); 00227 sdrawtripoints(x1, y1, x2, y2); 00228 glEnd(); 00229 } 00230 00231 void sdrawtrifill(short x1, short y1, short x2, short y2) 00232 { 00233 glBegin(GL_TRIANGLES); 00234 sdrawtripoints(x1, y1, x2, y2); 00235 glEnd(); 00236 } 00237 00238 void sdrawbox(short x1, short y1, short x2, short y2) 00239 { 00240 short v[2]; 00241 00242 glBegin(GL_LINE_STRIP); 00243 00244 v[0] = x1; v[1] = y1; 00245 glVertex2sv(v); 00246 v[0] = x1; v[1] = y2; 00247 glVertex2sv(v); 00248 v[0] = x2; v[1] = y2; 00249 glVertex2sv(v); 00250 v[0] = x2; v[1] = y1; 00251 glVertex2sv(v); 00252 v[0] = x1; v[1] = y1; 00253 glVertex2sv(v); 00254 00255 glEnd(); 00256 } 00257 00258 00259 /* ******************************************** */ 00260 00261 void setlinestyle(int nr) 00262 { 00263 if(nr==0) { 00264 glDisable(GL_LINE_STIPPLE); 00265 } 00266 else { 00267 00268 glEnable(GL_LINE_STIPPLE); 00269 glLineStipple(nr, 0xAAAA); 00270 } 00271 } 00272 00273 /* Invert line handling */ 00274 00275 #define glToggle(mode, onoff) (((onoff)?glEnable:glDisable)(mode)) 00276 00277 void set_inverted_drawing(int enable) 00278 { 00279 glLogicOp(enable?GL_INVERT:GL_COPY); 00280 glToggle(GL_COLOR_LOGIC_OP, enable); 00281 glToggle(GL_DITHER, !enable); 00282 } 00283 00284 void sdrawXORline(int x0, int y0, int x1, int y1) 00285 { 00286 if(x0==x1 && y0==y1) return; 00287 00288 set_inverted_drawing(1); 00289 00290 glBegin(GL_LINES); 00291 glVertex2i(x0, y0); 00292 glVertex2i(x1, y1); 00293 glEnd(); 00294 00295 set_inverted_drawing(0); 00296 } 00297 00298 void sdrawXORline4(int nr, int x0, int y0, int x1, int y1) 00299 { 00300 static short old[4][2][2]; 00301 static char flags[4]= {0, 0, 0, 0}; 00302 00303 /* with builtin memory, max 4 lines */ 00304 00305 set_inverted_drawing(1); 00306 00307 glBegin(GL_LINES); 00308 if(nr== -1) { /* flush */ 00309 for (nr=0; nr<4; nr++) { 00310 if (flags[nr]) { 00311 glVertex2sv(old[nr][0]); 00312 glVertex2sv(old[nr][1]); 00313 flags[nr]= 0; 00314 } 00315 } 00316 } else { 00317 if(nr>=0 && nr<4) { 00318 if(flags[nr]) { 00319 glVertex2sv(old[nr][0]); 00320 glVertex2sv(old[nr][1]); 00321 } 00322 00323 old[nr][0][0]= x0; 00324 old[nr][0][1]= y0; 00325 old[nr][1][0]= x1; 00326 old[nr][1][1]= y1; 00327 00328 flags[nr]= 1; 00329 } 00330 00331 glVertex2i(x0, y0); 00332 glVertex2i(x1, y1); 00333 } 00334 glEnd(); 00335 00336 set_inverted_drawing(0); 00337 } 00338 00339 void fdrawXORellipse(float xofs, float yofs, float hw, float hh) 00340 { 00341 if(hw==0) return; 00342 00343 set_inverted_drawing(1); 00344 00345 glPushMatrix(); 00346 glTranslatef(xofs, yofs, 0.0); 00347 glScalef(1,hh/hw,1); 00348 glutil_draw_lined_arc(0.0, M_PI*2.0, hw, 20); 00349 glPopMatrix(); 00350 00351 set_inverted_drawing(0); 00352 } 00353 void fdrawXORcirc(float xofs, float yofs, float rad) 00354 { 00355 set_inverted_drawing(1); 00356 00357 glPushMatrix(); 00358 glTranslatef(xofs, yofs, 0.0); 00359 glutil_draw_lined_arc(0.0, M_PI*2.0, rad, 20); 00360 glPopMatrix(); 00361 00362 set_inverted_drawing(0); 00363 } 00364 00365 void glutil_draw_filled_arc(float start, float angle, float radius, int nsegments) 00366 { 00367 int i; 00368 00369 glBegin(GL_TRIANGLE_FAN); 00370 glVertex2f(0.0, 0.0); 00371 for (i=0; i<nsegments; i++) { 00372 float t= (float) i/(nsegments-1); 00373 float cur= start + t*angle; 00374 00375 glVertex2f(cosf(cur)*radius, sinf(cur)*radius); 00376 } 00377 glEnd(); 00378 } 00379 00380 void glutil_draw_lined_arc(float start, float angle, float radius, int nsegments) 00381 { 00382 int i; 00383 00384 glBegin(GL_LINE_STRIP); 00385 for (i=0; i<nsegments; i++) { 00386 float t= (float) i/(nsegments-1); 00387 float cur= start + t*angle; 00388 00389 glVertex2f(cosf(cur)*radius, sinf(cur)*radius); 00390 } 00391 glEnd(); 00392 } 00393 00394 int glaGetOneInteger(int param) 00395 { 00396 GLint i; 00397 glGetIntegerv(param, &i); 00398 return i; 00399 } 00400 00401 float glaGetOneFloat(int param) 00402 { 00403 GLfloat v; 00404 glGetFloatv(param, &v); 00405 return v; 00406 } 00407 00408 void glaRasterPosSafe2f(float x, float y, float known_good_x, float known_good_y) 00409 { 00410 GLubyte dummy= 0; 00411 00412 /* As long as known good coordinates are correct 00413 * this is guarenteed to generate an ok raster 00414 * position (ignoring potential (real) overflow 00415 * issues). 00416 */ 00417 glRasterPos2f(known_good_x, known_good_y); 00418 00419 /* Now shift the raster position to where we wanted 00420 * it in the first place using the glBitmap trick. 00421 */ 00422 glBitmap(0, 0, 0, 0, x - known_good_x, y - known_good_y, &dummy); 00423 } 00424 00425 static int get_cached_work_texture(int *w_r, int *h_r) 00426 { 00427 static GLint texid= -1; 00428 static int tex_w= 256; 00429 static int tex_h= 256; 00430 00431 if (texid==-1) { 00432 GLint ltexid= glaGetOneInteger(GL_TEXTURE_2D); 00433 unsigned char *tbuf; 00434 00435 glGenTextures(1, (GLuint *)&texid); 00436 00437 glBindTexture(GL_TEXTURE_2D, texid); 00438 00439 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 00440 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 00441 00442 tbuf= MEM_callocN(tex_w*tex_h*4, "tbuf"); 00443 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex_w, tex_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, tbuf); 00444 MEM_freeN(tbuf); 00445 00446 glBindTexture(GL_TEXTURE_2D, ltexid); 00447 } 00448 00449 *w_r= tex_w; 00450 *h_r= tex_h; 00451 return texid; 00452 } 00453 00454 void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, void *rect, float scaleX, float scaleY) 00455 { 00456 unsigned char *uc_rect= (unsigned char*) rect; 00457 float *f_rect= (float *)rect; 00458 float xzoom= glaGetOneFloat(GL_ZOOM_X), yzoom= glaGetOneFloat(GL_ZOOM_Y); 00459 int ltexid= glaGetOneInteger(GL_TEXTURE_2D); 00460 int lrowlength= glaGetOneInteger(GL_UNPACK_ROW_LENGTH); 00461 int subpart_x, subpart_y, tex_w, tex_h; 00462 int seamless, offset_x, offset_y, nsubparts_x, nsubparts_y; 00463 int texid= get_cached_work_texture(&tex_w, &tex_h); 00464 00465 /* Specify the color outside this function, and tex will modulate it. 00466 * This is useful for changing alpha without using glPixelTransferf() 00467 */ 00468 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 00469 glPixelStorei(GL_UNPACK_ROW_LENGTH, img_w); 00470 glBindTexture(GL_TEXTURE_2D, texid); 00471 00472 /* don't want nasty border artifacts */ 00473 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 00474 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 00475 00476 #ifdef __APPLE__ 00477 /* workaround for os x 10.5/10.6 driver bug: http://lists.apple.com/archives/Mac-opengl/2008/Jul/msg00117.html */ 00478 glPixelZoom(1.f, 1.f); 00479 #endif 00480 00481 /* setup seamless 2=on, 0=off */ 00482 seamless= ((tex_w<img_w || tex_h<img_h) && tex_w>2 && tex_h>2)? 2: 0; 00483 00484 offset_x= tex_w - seamless; 00485 offset_y= tex_h - seamless; 00486 00487 nsubparts_x= (img_w + (offset_x - 1))/(offset_x); 00488 nsubparts_y= (img_h + (offset_y - 1))/(offset_y); 00489 00490 for (subpart_y=0; subpart_y<nsubparts_y; subpart_y++) { 00491 for (subpart_x=0; subpart_x<nsubparts_x; subpart_x++) { 00492 int remainder_x= img_w-subpart_x*offset_x; 00493 int remainder_y= img_h-subpart_y*offset_y; 00494 int subpart_w= (remainder_x<tex_w)? remainder_x: tex_w; 00495 int subpart_h= (remainder_y<tex_h)? remainder_y: tex_h; 00496 int offset_left= (seamless && subpart_x!=0)? 1: 0; 00497 int offset_bot= (seamless && subpart_y!=0)? 1: 0; 00498 int offset_right= (seamless && remainder_x>tex_w)? 1: 0; 00499 int offset_top= (seamless && remainder_y>tex_h)? 1: 0; 00500 float rast_x= x+subpart_x*offset_x*xzoom; 00501 float rast_y= y+subpart_y*offset_y*yzoom; 00502 00503 /* check if we already got these because we always get 2 more when doing seamless*/ 00504 if(subpart_w<=seamless || subpart_h<=seamless) 00505 continue; 00506 00507 if(format==GL_FLOAT) { 00508 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, GL_RGBA, GL_FLOAT, &f_rect[subpart_y*offset_y*img_w*4 + subpart_x*offset_x*4]); 00509 00510 /* add an extra border of pixels so linear looks ok at edges of full image. */ 00511 if(subpart_w<tex_w) 00512 glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, GL_RGBA, GL_FLOAT, &f_rect[subpart_y*offset_y*img_w*4 + (subpart_x*offset_x+subpart_w-1)*4]); 00513 if(subpart_h<tex_h) 00514 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, GL_RGBA, GL_FLOAT, &f_rect[(subpart_y*offset_y+subpart_h-1)*img_w*4 + subpart_x*offset_x*4]); 00515 if(subpart_w<tex_w && subpart_h<tex_h) 00516 glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, GL_RGBA, GL_FLOAT, &f_rect[(subpart_y*offset_y+subpart_h-1)*img_w*4 + (subpart_x*offset_x+subpart_w-1)*4]); 00517 } 00518 else { 00519 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, GL_RGBA, GL_UNSIGNED_BYTE, &uc_rect[subpart_y*offset_y*img_w*4 + subpart_x*offset_x*4]); 00520 00521 if(subpart_w<tex_w) 00522 glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, GL_RGBA, GL_UNSIGNED_BYTE, &uc_rect[subpart_y*offset_y*img_w*4 + (subpart_x*offset_x+subpart_w-1)*4]); 00523 if(subpart_h<tex_h) 00524 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, GL_RGBA, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y*offset_y+subpart_h-1)*img_w*4 + subpart_x*offset_x*4]); 00525 if(subpart_w<tex_w && subpart_h<tex_h) 00526 glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y*offset_y+subpart_h-1)*img_w*4 + (subpart_x*offset_x+subpart_w-1)*4]); 00527 } 00528 00529 glEnable(GL_TEXTURE_2D); 00530 glBegin(GL_QUADS); 00531 glTexCoord2f((float)(0 + offset_left)/tex_w, (float)(0 + offset_bot)/tex_h); 00532 glVertex2f(rast_x + (float)offset_left*xzoom, rast_y + (float)offset_bot*xzoom); 00533 00534 glTexCoord2f((float)(subpart_w - offset_right)/tex_w, (float)(0 + offset_bot)/tex_h); 00535 glVertex2f(rast_x + (float)(subpart_w - offset_right)*xzoom*scaleX, rast_y + (float)offset_bot*xzoom); 00536 00537 glTexCoord2f((float)(subpart_w - offset_right)/tex_w, (float)(subpart_h - offset_top)/tex_h); 00538 glVertex2f(rast_x + (float)(subpart_w - offset_right)*xzoom*scaleX, rast_y + (float)(subpart_h - offset_top)*yzoom*scaleY); 00539 00540 glTexCoord2f((float)(0 + offset_left)/tex_w, (float)(subpart_h - offset_top)/tex_h); 00541 glVertex2f(rast_x + (float)offset_left*xzoom, rast_y + (float)(subpart_h - offset_top)*yzoom*scaleY); 00542 glEnd(); 00543 glDisable(GL_TEXTURE_2D); 00544 } 00545 } 00546 00547 glBindTexture(GL_TEXTURE_2D, ltexid); 00548 glPixelStorei(GL_UNPACK_ROW_LENGTH, lrowlength); 00549 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 00550 00551 #ifdef __APPLE__ 00552 /* workaround for os x 10.5/10.6 driver bug (above) */ 00553 glPixelZoom(xzoom, yzoom); 00554 #endif 00555 } 00556 00557 void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, void *rect) 00558 { 00559 glaDrawPixelsTexScaled(x, y, img_w, img_h, format, rect, 1.0f, 1.0f); 00560 } 00561 00562 void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int format, int type, void *rect) 00563 { 00564 float xzoom= glaGetOneFloat(GL_ZOOM_X); 00565 float yzoom= glaGetOneFloat(GL_ZOOM_Y); 00566 00567 /* The pixel space coordinate of the intersection of 00568 * the [zoomed] image with the origin. 00569 */ 00570 float ix= -x/xzoom; 00571 float iy= -y/yzoom; 00572 00573 /* The maximum pixel amounts the image can be cropped 00574 * at the lower left without exceeding the origin. 00575 */ 00576 int off_x= floor(MAX2(ix, 0)); 00577 int off_y= floor(MAX2(iy, 0)); 00578 00579 /* The zoomed space coordinate of the raster position 00580 * (starting at the lower left most unclipped pixel). 00581 */ 00582 float rast_x= x + off_x*xzoom; 00583 float rast_y= y + off_y*yzoom; 00584 00585 GLfloat scissor[4]; 00586 int draw_w, draw_h; 00587 00588 /* Determine the smallest number of pixels we need to draw 00589 * before the image would go off the upper right corner. 00590 * 00591 * It may seem this is just an optimization but some graphics 00592 * cards (ATI) freak out if there is a large zoom factor and 00593 * a large number of pixels off the screen (probably at some 00594 * level the number of image pixels to draw is getting multiplied 00595 * by the zoom and then clamped). Making sure we draw the 00596 * fewest pixels possible keeps everyone mostly happy (still 00597 * fails if we zoom in on one really huge pixel so that it 00598 * covers the entire screen). 00599 */ 00600 glGetFloatv(GL_SCISSOR_BOX, scissor); 00601 draw_w = MIN2(img_w-off_x, ceil((scissor[2]-rast_x)/xzoom)); 00602 draw_h = MIN2(img_h-off_y, ceil((scissor[3]-rast_y)/yzoom)); 00603 00604 if (draw_w>0 && draw_h>0) { 00605 int old_row_length = glaGetOneInteger(GL_UNPACK_ROW_LENGTH); 00606 00607 /* Don't use safe RasterPos (slower) if we can avoid it. */ 00608 if (rast_x>=0 && rast_y>=0) { 00609 glRasterPos2f(rast_x, rast_y); 00610 } else { 00611 glaRasterPosSafe2f(rast_x, rast_y, 0, 0); 00612 } 00613 00614 glPixelStorei(GL_UNPACK_ROW_LENGTH, row_w); 00615 if(format==GL_LUMINANCE || format==GL_RED) { 00616 if(type==GL_FLOAT) { 00617 float *f_rect= (float *)rect; 00618 glDrawPixels(draw_w, draw_h, format, type, f_rect + (off_y*row_w + off_x)); 00619 } 00620 else if(type==GL_INT || type==GL_UNSIGNED_INT) { 00621 int *i_rect= (int *)rect; 00622 glDrawPixels(draw_w, draw_h, format, type, i_rect + (off_y*row_w + off_x)); 00623 } 00624 } 00625 else { /* RGBA */ 00626 if(type==GL_FLOAT) { 00627 float *f_rect= (float *)rect; 00628 glDrawPixels(draw_w, draw_h, format, type, f_rect + (off_y*row_w + off_x)*4); 00629 } 00630 else if(type==GL_UNSIGNED_BYTE) { 00631 unsigned char *uc_rect= (unsigned char *) rect; 00632 glDrawPixels(draw_w, draw_h, format, type, uc_rect + (off_y*row_w + off_x)*4); 00633 } 00634 } 00635 00636 glPixelStorei(GL_UNPACK_ROW_LENGTH, old_row_length); 00637 } 00638 } 00639 00640 /* 2D Drawing Assistance */ 00641 00642 void glaDefine2DArea(rcti *screen_rect) 00643 { 00644 int sc_w= screen_rect->xmax - screen_rect->xmin + 1; 00645 int sc_h= screen_rect->ymax - screen_rect->ymin + 1; 00646 00647 glViewport(screen_rect->xmin, screen_rect->ymin, sc_w, sc_h); 00648 glScissor(screen_rect->xmin, screen_rect->ymin, sc_w, sc_h); 00649 00650 /* The 0.375 magic number is to shift the matrix so that 00651 * both raster and vertex integer coordinates fall at pixel 00652 * centers properly. For a longer discussion see the OpenGL 00653 * Programming Guide, Appendix H, Correctness Tips. 00654 */ 00655 00656 glMatrixMode(GL_PROJECTION); 00657 glLoadIdentity(); 00658 glOrtho(0.0, sc_w, 0.0, sc_h, -1, 1); 00659 glTranslatef(0.375, 0.375, 0.0); 00660 00661 glMatrixMode(GL_MODELVIEW); 00662 glLoadIdentity(); 00663 } 00664 00665 struct gla2DDrawInfo { 00666 int orig_vp[4], orig_sc[4]; 00667 float orig_projmat[16], orig_viewmat[16]; 00668 00669 rcti screen_rect; 00670 rctf world_rect; 00671 00672 float wo_to_sc[2]; 00673 }; 00674 00675 void gla2DGetMap(gla2DDrawInfo *di, rctf *rect) 00676 { 00677 *rect= di->world_rect; 00678 } 00679 00680 void gla2DSetMap(gla2DDrawInfo *di, rctf *rect) 00681 { 00682 int sc_w, sc_h; 00683 float wo_w, wo_h; 00684 00685 di->world_rect= *rect; 00686 00687 sc_w= (di->screen_rect.xmax-di->screen_rect.xmin); 00688 sc_h= (di->screen_rect.ymax-di->screen_rect.ymin); 00689 wo_w= (di->world_rect.xmax-di->world_rect.xmin); 00690 wo_h= (di->world_rect.ymax-di->world_rect.ymin); 00691 00692 di->wo_to_sc[0]= sc_w/wo_w; 00693 di->wo_to_sc[1]= sc_h/wo_h; 00694 } 00695 00696 00697 gla2DDrawInfo *glaBegin2DDraw(rcti *screen_rect, rctf *world_rect) 00698 { 00699 gla2DDrawInfo *di= MEM_mallocN(sizeof(*di), "gla2DDrawInfo"); 00700 int sc_w, sc_h; 00701 float wo_w, wo_h; 00702 00703 glGetIntegerv(GL_VIEWPORT, (GLint *)di->orig_vp); 00704 glGetIntegerv(GL_SCISSOR_BOX, (GLint *)di->orig_sc); 00705 glGetFloatv(GL_PROJECTION_MATRIX, (GLfloat *)di->orig_projmat); 00706 glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *)di->orig_viewmat); 00707 00708 di->screen_rect= *screen_rect; 00709 if (world_rect) { 00710 di->world_rect= *world_rect; 00711 } else { 00712 di->world_rect.xmin= di->screen_rect.xmin; 00713 di->world_rect.ymin= di->screen_rect.ymin; 00714 di->world_rect.xmax= di->screen_rect.xmax; 00715 di->world_rect.ymax= di->screen_rect.ymax; 00716 } 00717 00718 sc_w= (di->screen_rect.xmax-di->screen_rect.xmin); 00719 sc_h= (di->screen_rect.ymax-di->screen_rect.ymin); 00720 wo_w= (di->world_rect.xmax-di->world_rect.xmin); 00721 wo_h= (di->world_rect.ymax-di->world_rect.ymin); 00722 00723 di->wo_to_sc[0]= sc_w/wo_w; 00724 di->wo_to_sc[1]= sc_h/wo_h; 00725 00726 glaDefine2DArea(&di->screen_rect); 00727 00728 return di; 00729 } 00730 00731 void gla2DDrawTranslatePt(gla2DDrawInfo *di, float wo_x, float wo_y, int *sc_x_r, int *sc_y_r) 00732 { 00733 *sc_x_r= (wo_x - di->world_rect.xmin)*di->wo_to_sc[0]; 00734 *sc_y_r= (wo_y - di->world_rect.ymin)*di->wo_to_sc[1]; 00735 } 00736 void gla2DDrawTranslatePtv(gla2DDrawInfo *di, float world[2], int screen_r[2]) 00737 { 00738 screen_r[0]= (world[0] - di->world_rect.xmin)*di->wo_to_sc[0]; 00739 screen_r[1]= (world[1] - di->world_rect.ymin)*di->wo_to_sc[1]; 00740 } 00741 00742 void glaEnd2DDraw(gla2DDrawInfo *di) 00743 { 00744 glViewport(di->orig_vp[0], di->orig_vp[1], di->orig_vp[2], di->orig_vp[3]); 00745 glScissor(di->orig_vp[0], di->orig_vp[1], di->orig_vp[2], di->orig_vp[3]); 00746 glMatrixMode(GL_PROJECTION); 00747 glLoadMatrixf(di->orig_projmat); 00748 glMatrixMode(GL_MODELVIEW); 00749 glLoadMatrixf(di->orig_viewmat); 00750 00751 MEM_freeN(di); 00752 } 00753 00754 /* **************** glPoint hack ************************ */ 00755 00756 static int curmode=0; 00757 static int pointhack=0; 00758 static GLubyte Squaredot[16] = { 0xff,0xff,0xff,0xff, 00759 0xff,0xff,0xff,0xff, 00760 0xff,0xff,0xff,0xff, 00761 0xff,0xff,0xff,0xff}; 00762 00763 void bglBegin(int mode) 00764 { 00765 curmode= mode; 00766 00767 if(mode==GL_POINTS) { 00768 float value[4]; 00769 glGetFloatv(GL_POINT_SIZE_RANGE, value); 00770 if(value[1] < 2.0f) { 00771 glGetFloatv(GL_POINT_SIZE, value); 00772 pointhack= floor(value[0] + 0.5f); 00773 if(pointhack>4) pointhack= 4; 00774 } 00775 else glBegin(mode); 00776 } 00777 } 00778 00779 int bglPointHack(void) 00780 { 00781 float value[4]; 00782 int pointhack_px; 00783 glGetFloatv(GL_POINT_SIZE_RANGE, value); 00784 if(value[1] < 2.0f) { 00785 glGetFloatv(GL_POINT_SIZE, value); 00786 pointhack_px= floorf(value[0]+0.5f); 00787 if(pointhack_px>4) pointhack_px= 4; 00788 return pointhack_px; 00789 } 00790 return 0; 00791 } 00792 00793 void bglVertex3fv(float *vec) 00794 { 00795 switch(curmode) { 00796 case GL_POINTS: 00797 if(pointhack) { 00798 glRasterPos3fv(vec); 00799 glBitmap(pointhack, pointhack, (float)pointhack/2.0f, (float)pointhack/2.0f, 0.0, 0.0, Squaredot); 00800 } 00801 else glVertex3fv(vec); 00802 break; 00803 } 00804 } 00805 00806 void bglVertex3f(float x, float y, float z) 00807 { 00808 switch(curmode) { 00809 case GL_POINTS: 00810 if(pointhack) { 00811 glRasterPos3f(x, y, z); 00812 glBitmap(pointhack, pointhack, (float)pointhack/2.0f, (float)pointhack/2.0f, 0.0, 0.0, Squaredot); 00813 } 00814 else glVertex3f(x, y, z); 00815 break; 00816 } 00817 } 00818 00819 void bglVertex2fv(float *vec) 00820 { 00821 switch(curmode) { 00822 case GL_POINTS: 00823 if(pointhack) { 00824 glRasterPos2fv(vec); 00825 glBitmap(pointhack, pointhack, (float)pointhack/2, pointhack/2, 0.0, 0.0, Squaredot); 00826 } 00827 else glVertex2fv(vec); 00828 break; 00829 } 00830 } 00831 00832 00833 void bglEnd(void) 00834 { 00835 if(pointhack) pointhack= 0; 00836 else glEnd(); 00837 00838 } 00839 00840 /* Uses current OpenGL state to get view matrices for gluProject/gluUnProject */ 00841 void bgl_get_mats(bglMats *mats) 00842 { 00843 const double badvalue= 1.0e-6; 00844 00845 glGetDoublev(GL_MODELVIEW_MATRIX, mats->modelview); 00846 glGetDoublev(GL_PROJECTION_MATRIX, mats->projection); 00847 glGetIntegerv(GL_VIEWPORT, (GLint *)mats->viewport); 00848 00849 /* Very strange code here - it seems that certain bad values in the 00850 modelview matrix can cause gluUnProject to give bad results. */ 00851 if(mats->modelview[0] < badvalue && 00852 mats->modelview[0] > -badvalue) 00853 mats->modelview[0]= 0; 00854 if(mats->modelview[5] < badvalue && 00855 mats->modelview[5] > -badvalue) 00856 mats->modelview[5]= 0; 00857 00858 /* Set up viewport so that gluUnProject will give correct values */ 00859 mats->viewport[0] = 0; 00860 mats->viewport[1] = 0; 00861 } 00862 00863 /* *************** glPolygonOffset hack ************* */ 00864 00865 /* dist is only for ortho now... */ 00866 void bglPolygonOffset(float viewdist, float dist) 00867 { 00868 static float winmat[16], offset=0.0; 00869 00870 if(dist != 0.0f) { 00871 float offs; 00872 00873 // glEnable(GL_POLYGON_OFFSET_FILL); 00874 // glPolygonOffset(-1.0, -1.0); 00875 00876 /* hack below is to mimic polygon offset */ 00877 glMatrixMode(GL_PROJECTION); 00878 glGetFloatv(GL_PROJECTION_MATRIX, (float *)winmat); 00879 00880 /* dist is from camera to center point */ 00881 00882 if(winmat[15]>0.5f) offs= 0.00001f*dist*viewdist; // ortho tweaking 00883 else offs= 0.0005f*dist; // should be clipping value or so... 00884 00885 winmat[14]-= offs; 00886 offset+= offs; 00887 00888 glLoadMatrixf(winmat); 00889 glMatrixMode(GL_MODELVIEW); 00890 } 00891 else { 00892 00893 glMatrixMode(GL_PROJECTION); 00894 winmat[14]+= offset; 00895 offset= 0.0; 00896 glLoadMatrixf(winmat); 00897 glMatrixMode(GL_MODELVIEW); 00898 } 00899 } 00900 00901 void bglFlush(void) 00902 { 00903 glFlush(); 00904 #ifdef __APPLE__ 00905 // if(GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_MAC, GPU_DRIVER_OFFICIAL)) 00906 // XXX myswapbuffers(); //hack to get mac intel graphics to show frontbuffer 00907 #endif 00908 } 00909