diff options
Diffstat (limited to 'source/blender/src/drawimage.c')
-rw-r--r-- | source/blender/src/drawimage.c | 582 |
1 files changed, 582 insertions, 0 deletions
diff --git a/source/blender/src/drawimage.c b/source/blender/src/drawimage.c new file mode 100644 index 00000000000..ede04c45d6b --- /dev/null +++ b/source/blender/src/drawimage.c @@ -0,0 +1,582 @@ +/** + * $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 <math.h> +#ifdef WIN32 +#include <io.h> +#include "BLI_winstuff.h" +#else +#include <unistd.h> +#endif +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_editVert.h" + +#include "IMB_imbuf_types.h" + +#include "DNA_image_types.h" +#include "DNA_mesh_types.h" +#include "DNA_packedFile_types.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" + +#include "BKE_utildefines.h" +#include "BKE_global.h" +#include "BKE_mesh.h" +#include "BKE_image.h" + +#include "BDR_editface.h" + +#include "BIF_gl.h" +#include "BIF_space.h" +#include "BIF_screen.h" +#include "BIF_mywindow.h" +#include "BIF_drawimage.h" + +/* Modules used */ +#include "mydevice.h" +#include "render.h" + + +void rectwrite_part(int winxmin, int winymin, int winxmax, int winymax, int x1, int y1, int xim, int yim, float zoomx, float zoomy, unsigned int *rect) +{ + int cx, cy, oldxim, x2, y2; + + oldxim= xim; + + /* coordinaten hoe 't op scherm komt */ + x2= x1+ zoomx*xim; + y2= y1+ zoomy*yim; + + /* partiele clip */ + if(x1<winxmin) { + /* recten bij OpenGL mogen niet links/onder van windowrand beginnen */ + cx= winxmin-x1+(int)zoomx; + /* zorg ervoor dat de rect pixelnauwkeurig wordt neergezet */ + cx/= zoomx; + cx++; + x1+= zoomx*cx; + xim-= cx; + rect+= cx; + } + if(y1<winymin) { + cy= winymin-y1+(int)zoomy; + cy/= zoomy; + cy++; + y1+= zoomy*cy; + rect+= cy*oldxim; + yim-= cy; + } + if(x2>=winxmax) { + cx= x2-winxmax; + cx/= zoomx; + xim-= cx+3; + } + if(y2>=winymax) { + cy= y2-winymax; + cy/= zoomy; + yim-= cy+3; + } + + if(xim<=0) return; + if(yim<=0) return; + + mywinset(G.curscreen->mainwin); + glScissor(winxmin, winymin, winxmax-winxmin+1, winymax-winymin+1); + + glPixelStorei(GL_UNPACK_ROW_LENGTH, oldxim); + + glPixelZoom(zoomx, zoomy); + + glRasterPos2i(x1, y1); + glDrawPixels(xim, yim, GL_RGBA, GL_UNSIGNED_BYTE, rect); + + glPixelZoom(1.0, 1.0); + + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + + mywinset(curarea->win); +} + +/** + * Sets up the fields of the View2D member of the SpaceImage struct + * This routine can be called in two modes: + * mode == 'f': float mode ??? + * mode == 'p': pixel mode ??? + * + * @param sima the image space to update + * @param mode the mode to use for the update + * @return void + * + */ +void calc_image_view(SpaceImage *sima, char mode) +{ + float xim=256, yim=256; + float x1, y1; + float zoom; + + if(sima->image && sima->image->ibuf) { + xim= sima->image->ibuf->x; + yim= sima->image->ibuf->y; + } + + sima->v2d.tot.xmin= 0; + sima->v2d.tot.ymin= 0; + sima->v2d.tot.xmax= xim; + sima->v2d.tot.ymax= yim; + + sima->v2d.mask.xmin= sima->v2d.mask.ymin= 0; + sima->v2d.mask.xmax= curarea->winx; + sima->v2d.mask.ymax= curarea->winy; + + + /* Which part of the image space do we see? */ + /* Same calculation as in lrectwrite: area left and down*/ + x1= curarea->winrct.xmin+(curarea->winx-sima->zoom*xim)/2; + y1= curarea->winrct.ymin+(curarea->winy-sima->zoom*yim)/2; + + x1-= sima->zoom*sima->xof; + y1-= sima->zoom*sima->yof; + + /* float! */ + zoom= sima->zoom; + + /* relatieve afbeeld links */ + sima->v2d.cur.xmin= ((curarea->winrct.xmin - (float)x1)/zoom); + sima->v2d.cur.xmax= sima->v2d.cur.xmin + ((float)curarea->winx/zoom); + + /* relatieve afbeeld links */ + sima->v2d.cur.ymin= ((curarea->winrct.ymin-(float)y1)/zoom); + sima->v2d.cur.ymax= sima->v2d.cur.ymin + ((float)curarea->winy/zoom); + + if(mode=='f') { + sima->v2d.cur.xmin/= xim; + sima->v2d.cur.xmax/= xim; + sima->v2d.cur.ymin/= yim; + sima->v2d.cur.ymax/= yim; + } +} + +void what_image(SpaceImage *sima) +{ + extern TFace *lasttface; /* editface.c */ + Mesh *me; + + if(sima->mode==SI_TEXTURE) { + if(G.f & G_FACESELECT) { + + sima->image= 0; + me= get_mesh((G.scene->basact) ? (G.scene->basact->object) : 0); + set_lasttface(); + + if(me && me->tface && lasttface) { + if(lasttface->mode & TF_TEX) { + sima->image= lasttface->tpage; + + if(sima->flag & SI_EDITTILE); + else sima->curtile= lasttface->tile; + + if(sima->image) { + if(lasttface->mode & TF_TILES) sima->image->tpageflag |= IMA_TILES; + else sima->image->tpageflag &= ~IMA_TILES; + } + } + } + } + } +} + +void image_changed(SpaceImage *sima, int dotile) +{ + TFace *tface; + Mesh *me; + int a; + + if(sima->mode==SI_TEXTURE) { + + if(G.f & G_FACESELECT) { + me= get_mesh((G.scene->basact) ? (G.scene->basact->object) : 0); + if(me && me->tface) { + tface= me->tface; + a= me->totface; + while(a--) { + if(tface->flag & TF_SELECT) { + + if(dotile==2) { + tface->mode &= ~TF_TILES; + } + else { + tface->tpage= sima->image; + tface->mode |= TF_TEX; + + if(dotile) tface->tile= sima->curtile; + } + + if(sima->image) { + if(sima->image->tpageflag & IMA_TILES) tface->mode |= TF_TILES; + else tface->mode &= ~TF_TILES; + + if(sima->image->id.us==0) sima->image->id.us= 1; + } + } + tface++; + } + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSGAME, 0); + } + } + } +} + + +void uvco_to_areaco(float *vec, short *mval) +{ + float x, y; + + mval[0]= 3200; + + x= (vec[0] - G.v2d->cur.xmin)/(G.v2d->cur.xmax-G.v2d->cur.xmin); + y= (vec[1] - G.v2d->cur.ymin)/(G.v2d->cur.ymax-G.v2d->cur.ymin); + + if(x>=0.0 && x<=1.0) { + if(y>=0.0 && y<=1.0) { + mval[0]= G.v2d->mask.xmin + x*(G.v2d->mask.xmax-G.v2d->mask.xmin); + mval[1]= G.v2d->mask.ymin + y*(G.v2d->mask.ymax-G.v2d->mask.ymin); + } + } +} + +void uvco_to_areaco_noclip(float *vec, short *mval) +{ + float x, y; + + mval[0]= 3200; + + x= (vec[0] - G.v2d->cur.xmin)/(G.v2d->cur.xmax-G.v2d->cur.xmin); + y= (vec[1] - G.v2d->cur.ymin)/(G.v2d->cur.ymax-G.v2d->cur.ymin); + + x= G.v2d->mask.xmin + x*(G.v2d->mask.xmax-G.v2d->mask.xmin); + y= G.v2d->mask.ymin + y*(G.v2d->mask.ymax-G.v2d->mask.ymin); + + mval[0]= x; + mval[1]= y; +} + + +void draw_tfaces(void) +{ + TFace *tface; + MFace *mface; + Mesh *me; + unsigned int col; + int a; + + glPointSize(2.0); + + if(G.f & G_FACESELECT) { + me= get_mesh((G.scene->basact) ? (G.scene->basact->object) : 0); + if(me && me->tface) { + + calc_image_view(G.sima, 'f'); /* float */ + myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax); + + tface= me->tface; + mface= me->mface; + a= me->totface; + + while(a--) { + if(mface->v3 && (tface->flag & TF_SELECT) ) { + + cpack(0x0); + glBegin(GL_LINE_LOOP); + glVertex2fv( tface->uv[0] ); + glVertex2fv( tface->uv[1] ); + glVertex2fv( tface->uv[2] ); + if(mface->v4) glVertex2fv( tface->uv[3] ); + glEnd(); + + setlinestyle(2); + /* kleuren: R=x G=y */ + + if(tface->flag & TF_ACTIVE) cpack(0xFF00); else cpack(0xFFFFFF); + + glBegin(GL_LINE_STRIP); + glVertex2fv( tface->uv[0] ); + glVertex2fv( tface->uv[1] ); + glEnd(); + + if(tface->flag & TF_ACTIVE) cpack(0xFF); else cpack(0xFFFFFF); + + glBegin(GL_LINE_STRIP); + glVertex2fv( tface->uv[0] ); + if(mface->v4) glVertex2fv( tface->uv[3] ); else glVertex2fv( tface->uv[2] ); + glEnd(); + + cpack(0xFFFFFF); + + glBegin(GL_LINE_STRIP); + glVertex2fv( tface->uv[1] ); + glVertex2fv( tface->uv[2] ); + if(mface->v4) glVertex2fv( tface->uv[3] ); + glEnd(); + + setlinestyle(0); + + glBegin(GL_POINTS); + + if(tface->flag & TF_SEL1) col= 0x77FFFF; else col= 0xFF70FF; + cpack(col); + glVertex2fv(tface->uv[0]); + + if(tface->flag & TF_SEL2) col= 0x77FFFF; else col= 0xFF70FF; + cpack(col); + glVertex2fv(tface->uv[1]); + + if(tface->flag & TF_SEL3) col= 0x77FFFF; else col= 0xFF70FF; + cpack(col); + glVertex2fv(tface->uv[2]); + + if(mface->v4) { + if(tface->flag & TF_SEL4) col= 0x77FFFF; else col= 0xFF70FF; + cpack(col); + glVertex2fv(tface->uv[3]); + } + glEnd(); + } + + tface++; + mface++; + } + } + } + glPointSize(1.0); +} + +static unsigned int *get_part_from_ibuf(ImBuf *ibuf, short startx, short starty, short endx, short endy) +{ + unsigned int *rt, *rp, *rectmain; + short y, heigth, len; + + /* de juiste offset in rectot */ + + rt= ibuf->rect+ (starty*ibuf->x+ startx); + + len= (endx-startx); + heigth= (endy-starty); + + rp=rectmain= MEM_mallocN(heigth*len*sizeof(int), "rect"); + + for(y=0; y<heigth; y++) { + memcpy(rp, rt, len*4); + rt+= ibuf->x; + rp+= len; + } + return rectmain; +} + +void drawimagespace(void) +{ + ImBuf *ibuf= NULL; + unsigned int *rect; + int x1, y1, xmin, xmax, ymin, ymax; + short sx, sy, dx, dy; + + glClearColor(.1875, .1875, .1875, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + + curarea->win_swap= WIN_BACK_OK; + + xmin= curarea->winrct.xmin; xmax= curarea->winrct.xmax; + ymin= curarea->winrct.ymin; ymax= curarea->winrct.ymax; + + what_image(G.sima); + + if(G.sima->image) { + + if(G.sima->image->ibuf==0) { + load_image(G.sima->image, IB_rect, G.sce, G.scene->r.cfra); + } + ibuf= G.sima->image->ibuf; + } + + if(ibuf==0 || ibuf->rect==0) { + calc_image_view(G.sima, 'f'); + myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax); + cpack(0x404040); + glRectf(0.0, 0.0, 1.0, 1.0); + draw_tfaces(); + + return; + } + + /* plek berekenen */ + x1= xmin+(curarea->winx-G.sima->zoom*ibuf->x)/2; + y1= ymin+(curarea->winy-G.sima->zoom*ibuf->y)/2; + + x1-= G.sima->zoom*G.sima->xof; + y1-= G.sima->zoom*G.sima->yof; + + + if(G.sima->flag & SI_EDITTILE) { + rectwrite_part(xmin, ymin, xmax, ymax, x1, y1, ibuf->x, ibuf->y, (float)G.sima->zoom, (float)G.sima->zoom, ibuf->rect); + + dx= ibuf->x/G.sima->image->xrep; + dy= ibuf->y/G.sima->image->yrep; + sy= (G.sima->curtile / G.sima->image->xrep); + sx= G.sima->curtile - sy*G.sima->image->xrep; + + sx*= dx; + sy*= dy; + + calc_image_view(G.sima, 'p'); /* pixel */ + myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax); + + cpack(0x0); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glRects(sx, sy, sx+dx-1, sy+dy-1); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + cpack(0xFFFFFF); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glRects(sx+1, sy+1, sx+dx, sy+dy); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } + else if(G.sima->mode==SI_TEXTURE) { + if(G.sima->image->tpageflag & IMA_TILES) { + + + /* eventjes laten staan */ + if(G.sima->image->xrep<1) return; + if(G.sima->image->yrep<1) return; + + if(G.sima->curtile >= G.sima->image->xrep*G.sima->image->yrep) + G.sima->curtile = G.sima->image->xrep*G.sima->image->yrep - 1; + + dx= ibuf->x/G.sima->image->xrep; + dy= ibuf->y/G.sima->image->yrep; + + sy= (G.sima->curtile / G.sima->image->xrep); + sx= G.sima->curtile - sy*G.sima->image->xrep; + + sx*= dx; + sy*= dy; + + rect= get_part_from_ibuf(ibuf, sx, sy, sx+dx, sy+dy); + + /* rect= ibuf->rect; */ + for(sy= 0; sy+dy<=ibuf->y; sy+= dy) { + for(sx= 0; sx+dx<=ibuf->x; sx+= dx) { + + rectwrite_part(xmin, ymin, xmax, ymax, + x1+sx*G.sima->zoom, y1+sy*G.sima->zoom, dx, dy, (float)G.sima->zoom, (float)G.sima->zoom, rect); + } + } + + MEM_freeN(rect); + } + else + rectwrite_part(xmin, ymin, xmax, ymax, x1, y1, ibuf->x, ibuf->y, (float)G.sima->zoom,(float)G.sima->zoom, ibuf->rect); + + draw_tfaces(); + } + + calc_image_view(G.sima, 'f'); /* float */ +} + +void image_viewmove(void) +{ + short mval[2], mvalo[2], xof, yof; + + getmouseco_sc(mvalo); + + while(get_mbut()&(L_MOUSE|M_MOUSE)) { + + getmouseco_sc(mval); + + xof= (mvalo[0]-mval[0])/G.sima->zoom; + yof= (mvalo[1]-mval[1])/G.sima->zoom; + + if(xof || yof) { + + G.sima->xof+= xof; + G.sima->yof+= yof; + + mvalo[0]= mval[0]; + mvalo[1]= mval[1]; + + scrarea_do_windraw(curarea); + screen_swapbuffers(); + } + else BIF_wait_for_statechange(); + } +} + +/** + * Updates the fields of the View2D member of the SpaceImage struct. + * Default behavior is to reset the position of the image and set the zoom to 1 + * If the image will not fit within the window rectangle, the zoom is adjusted + * + * @return void + * + */ +void image_home(void) +{ + int width, height; + float zoomX, zoomY; + + if (curarea->spacetype != SPACE_IMAGE) return; + if ((G.sima->image == 0) || (G.sima->image->ibuf == 0)) return; + + /* Check if the image will fit in the image with zoom==1 */ + width = curarea->winx; + height = curarea->winy; + if (((G.sima->image->ibuf->x >= width) || (G.sima->image->ibuf->y >= height)) && + ((width > 0) && (height > 0))) { + /* Find the zoom value that will fit the image in the image space */ + zoomX = ((float)width) / ((float)G.sima->image->ibuf->x); + zoomY = ((float)height) / ((float)G.sima->image->ibuf->y); + G.sima->zoom= MIN2(zoomX, zoomY); + + /* Now make it a power of 2 */ + G.sima->zoom = 1 / G.sima->zoom; + G.sima->zoom = log(G.sima->zoom) / log(2); + G.sima->zoom = ceil(G.sima->zoom); + G.sima->zoom = pow(2, G.sima->zoom); + G.sima->zoom = 1 / G.sima->zoom; + } + else { + G.sima->zoom= (float)1; + } + + G.sima->xof= G.sima->yof= 0; + + calc_image_view(G.sima, 'p'); + + scrarea_queue_winredraw(curarea); +} + |