/** * $Id$ * * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. The Blender * Foundation also sells licenses for use in proprietary software under * the Blender License. See http://www.blender.org/BL/ for information * about this. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. * * The Original Code is: all of this file. * * Contributor(s): none yet. * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ #include #ifdef HAVE_CONFIG_H #include #endif #ifdef WIN32 #include "BLI_winstuff.h" #endif #include "MEM_guardedalloc.h" #include "DNA_vec_types.h" #include "BIF_gl.h" #include "BIF_glutil.h" /* Invert line handling */ #define glToggle(mode, onoff) (((onoff)?glEnable:glDisable)(mode)) static void set_inverted_drawing(int enable) { glLogicOp(enable?GL_INVERT:GL_COPY); /* Use GL_BLEND_EQUATION_EXT on sgi (if we have it), * apparently GL_COLOR_LOGIC_OP doesn't work on O2? * Is this an sgi bug or our bug? */ #if defined(__sgi) && defined(GL_BLEND_EQUATION_EXT) glBlendEquationEXT(enable?GL_LOGIC_OP:GL_FUNC_ADD_EXT); glToggle(GL_BLEND, enable); #else glToggle(GL_COLOR_LOGIC_OP, enable); #endif glToggle(GL_DITHER, !enable); } void sdrawXORline(int x0, int y0, int x1, int y1) { if(x0==x1 && y0==y1) return; set_inverted_drawing(1); glBegin(GL_LINES); glVertex2i(x0, y0); glVertex2i(x1, y1); glEnd(); set_inverted_drawing(0); } void glutil_draw_front_xor_line(int x0, int y0, int x1, int y1) { glReadBuffer(GL_FRONT); glDrawBuffer(GL_FRONT); sdrawXORline(x0, y0, x1, y1); glFlush(); glReadBuffer(GL_BACK); glDrawBuffer(GL_BACK); } void sdrawXORline4(int nr, int x0, int y0, int x1, int y1) { static short old[4][2][2]; static char flags[4]= {0, 0, 0, 0}; /* with builtin memory, max 4 lines */ set_inverted_drawing(1); glBegin(GL_LINES); if(nr== -1) { /* flush */ for (nr=0; nr<4; nr++) { if (flags[nr]) { glVertex2sv(old[nr][0]); glVertex2sv(old[nr][1]); flags[nr]= 0; } } } else { if(nr>=0 && nr<4) { if(flags[nr]) { glVertex2sv(old[nr][0]); glVertex2sv(old[nr][1]); } old[nr][0][0]= x0; old[nr][0][1]= y0; old[nr][1][0]= x1; old[nr][1][1]= y1; flags[nr]= 1; } glVertex2i(x0, y0); glVertex2i(x1, y1); } glEnd(); set_inverted_drawing(0); } void fdrawXORcirc(float xofs, float yofs, float rad) { set_inverted_drawing(1); glPushMatrix(); glTranslatef(xofs, yofs, 0.0); glutil_draw_lined_arc(0.0, M_PI*2.0, rad, 20); glPopMatrix(); set_inverted_drawing(0); } void glutil_draw_filled_arc(float start, float angle, float radius, int nsegments) { int i; glBegin(GL_TRIANGLE_FAN); glVertex2f(0.0, 0.0); for (i=0; i=origin_x && y>=origin_y) { glRasterPos2f(x, y); glDrawPixels(img_w, img_h, GL_RGBA, GL_UNSIGNED_BYTE, uc_rect); } else { int old_row_length= glaGetOneInteger(GL_UNPACK_ROW_LENGTH); float xzoom= glaGetOneFloat(GL_ZOOM_X); float yzoom= glaGetOneFloat(GL_ZOOM_Y); /* The pixel space coordinate of the intersection of * the [zoomed] image with the origin. */ float ix= (origin_x-x)/xzoom; float iy= (origin_y-y)/yzoom; /* The maximum pixel amounts the image can cropped * without exceeding the origin. */ int off_x= floor((ix>origin_x)?ix:origin_x); int off_y= floor((iy>origin_y)?iy:origin_y); /* The zoomed space coordinate of the raster * position. */ float rast_x= x + off_x*xzoom; float rast_y= y + off_y*yzoom; if (off_xxmax - screen_rect->xmin; int sc_h= screen_rect->ymax - screen_rect->ymin; glViewport(screen_rect->xmin, screen_rect->ymin, sc_w, sc_h); glScissor(screen_rect->xmin, screen_rect->ymin, sc_w, sc_h); /* The 0.375 magic number is to shift the matrix so that * both raster and vertex integer coordinates fall at pixel * centers properly. For a longer discussion see the OpenGL * Programming Guide, Appendix H, Correctness Tips. */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0, sc_w, 0.0, sc_h, -1, 1); glTranslatef(0.375, 0.375, 0.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } struct gla2DDrawInfo { int orig_vp[4], orig_sc[4]; float orig_projmat[16], orig_viewmat[16]; rcti screen_rect; rctf world_rect; float wo_to_sc[2]; }; gla2DDrawInfo *glaBegin2DDraw(rcti *screen_rect, rctf *world_rect) { gla2DDrawInfo *di= MEM_mallocN(sizeof(*di), "gla2DDrawInfo"); int sc_w, sc_h; float wo_w, wo_h; glGetIntegerv(GL_VIEWPORT, (GLint *)di->orig_vp); glGetIntegerv(GL_SCISSOR_BOX, (GLint *)di->orig_sc); glGetFloatv(GL_PROJECTION_MATRIX, (GLfloat *)di->orig_projmat); glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *)di->orig_viewmat); di->screen_rect= *screen_rect; if (world_rect) { di->world_rect= *world_rect; } else { di->world_rect.xmin= di->screen_rect.xmin; di->world_rect.ymin= di->screen_rect.ymin; di->world_rect.xmax= di->screen_rect.xmax; di->world_rect.ymax= di->screen_rect.ymax; } sc_w= (di->screen_rect.xmax-di->screen_rect.xmin); sc_h= (di->screen_rect.ymax-di->screen_rect.ymin); wo_w= (di->world_rect.xmax-di->world_rect.xmin); wo_h= (di->world_rect.ymax-di->world_rect.ymin); di->wo_to_sc[0]= sc_w/wo_w; di->wo_to_sc[1]= sc_h/wo_h; glaDefine2DArea(&di->screen_rect); return di; } void gla2DDrawTranslatePt(gla2DDrawInfo *di, float wo_x, float wo_y, int *sc_x_r, int *sc_y_r) { *sc_x_r= (wo_x - di->world_rect.xmin)*di->wo_to_sc[0]; *sc_y_r= (wo_y - di->world_rect.ymin)*di->wo_to_sc[1]; } void gla2DDrawTranslatePtv(gla2DDrawInfo *di, float world[2], int screen_r[2]) { screen_r[0]= (world[0] - di->world_rect.xmin)*di->wo_to_sc[0]; screen_r[1]= (world[1] - di->world_rect.ymin)*di->wo_to_sc[1]; } void glaEnd2DDraw(gla2DDrawInfo *di) { glViewport(di->orig_vp[0], di->orig_vp[1], di->orig_vp[2], di->orig_vp[3]); glScissor(di->orig_vp[0], di->orig_vp[1], di->orig_vp[2], di->orig_vp[3]); glMatrixMode(GL_PROJECTION); glLoadMatrixf(di->orig_projmat); glMatrixMode(GL_MODELVIEW); glLoadMatrixf(di->orig_viewmat); MEM_freeN(di); } /* **************** glPoint hack ************************ */ static int curmode=0; static int pointhack=0; static GLubyte Squaredot[16] = { 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff}; void bglBegin(int mode) { curmode= mode; if(mode==GL_POINTS) { float value[4]; glGetFloatv(GL_POINT_SIZE_RANGE, value); if(value[1]<2.0) { glGetFloatv(GL_POINT_SIZE, value); pointhack= floor(value[0]+0.5); if(pointhack>4) pointhack= 4; } else glBegin(mode); } } void bglVertex3fv(float *vec) { switch(curmode) { case GL_POINTS: if(pointhack) { glRasterPos3fv(vec); glBitmap(pointhack, pointhack, (float)pointhack/2.0, (float)pointhack/2.0, 0.0, 0.0, Squaredot); } else glVertex3fv(vec); break; } } void bglVertex2fv(float *vec) { switch(curmode) { case GL_POINTS: if(pointhack) { glRasterPos2fv(vec); glBitmap(pointhack, pointhack, (float)pointhack/2, pointhack/2, 0.0, 0.0, Squaredot); } else glVertex2fv(vec); break; } } void bglEnd(void) { if(pointhack) pointhack= 0; else glEnd(); } /* *************** glPolygonOffset hack ************* */ // both temporal, so here for now (ton) #include "BKE_global.h" #include "DNA_view3d_types.h" /* dist is only for ortho now... */ void bglPolygonOffset(float dist) { static float winmat[16], offset=0.0; if(dist!=0.0) { float offs; // glEnable(GL_POLYGON_OFFSET_FILL); // glPolygonOffset(-1.0, -1.0); /* hack below is to mimic polygon offset */ glMatrixMode(GL_PROJECTION); glGetFloatv(GL_PROJECTION_MATRIX, (float *)winmat); /* dist is from camera to center point */ if(winmat[15]>0.5) offs= 0.00001*dist*G.vd->dist; // ortho tweaking else offs= 0.0005*dist; // should be clipping value or so... winmat[14]-= offs; offset+= offs; glLoadMatrixf(winmat); glMatrixMode(GL_MODELVIEW); } else { glMatrixMode(GL_PROJECTION); winmat[14]+= offset; offset= 0.0; glLoadMatrixf(winmat); glMatrixMode(GL_MODELVIEW); } }