- added DerivedMesh.drawUVEdges function & implementations
[blender.git] / source / blender / src / editface.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33
34 #include <math.h>
35 #include <string.h>
36
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40
41 #include "MEM_guardedalloc.h"
42
43 #include "BLI_blenlib.h"
44 #include "BLI_arithb.h"
45
46 #include "MTC_matrixops.h"
47
48 #include "IMB_imbuf_types.h"
49 #include "IMB_imbuf.h"
50
51 #include "DNA_image_types.h"
52 #include "DNA_mesh_types.h"
53 #include "DNA_meshdata_types.h"
54 #include "DNA_object_types.h"
55 #include "DNA_space_types.h"
56 #include "DNA_screen_types.h"
57 #include "DNA_scene_types.h"
58 #include "DNA_view3d_types.h"
59 #include "DNA_userdef_types.h"
60
61 #include "BKE_utildefines.h"
62 #include "BKE_depsgraph.h"
63 #include "BKE_displist.h"
64 #include "BKE_global.h"
65 #include "BKE_mesh.h"
66 #include "BKE_texture.h"
67 #include "BKE_object.h"
68
69 #include "BSE_view.h"
70 #include "BSE_edit.h"
71 #include "BSE_drawview.h"       /* for backdrawview3d */
72
73 #include "BIF_editsima.h"
74 #include "BIF_interface.h"
75 #include "BIF_mywindow.h"
76 #include "BIF_toolbox.h"
77 #include "BIF_screen.h"
78 #include "BIF_gl.h"
79 #include "BIF_graphics.h"
80 #include "BIF_space.h"  /* for allqueue */
81
82 #include "BDR_drawmesh.h"
83 #include "BDR_editface.h"
84 #include "BDR_vpaint.h"
85
86 #include "BDR_editface.h"
87 #include "BDR_vpaint.h"
88
89 #include "mydevice.h"
90 #include "blendef.h"
91 #include "butspace.h"
92
93 #include "TPT_DependKludge.h"
94
95 #ifdef NAN_TPT
96 #include "../img/IMG_Api.h"
97 #include "BSE_trans_types.h"
98 #endif /* NAN_TPT */
99
100 #include "BDR_unwrapper.h"
101
102 TFace *lasttface=NULL;
103
104 static void uv_calc_center_vector(float *result, Object *ob, Mesh *me)
105 {
106         float min[3], max[3], *cursx;
107         int a;
108         TFace *tface;
109         MFace *mface;
110
111         switch (G.vd->around) 
112         {
113         case V3D_CENTRE: /* bounding box center */
114                 min[0]= min[1]= min[2]= 1e20f;
115                 max[0]= max[1]= max[2]= -1e20f; 
116
117                 tface= me->tface;
118                 mface= me->mface;
119                 for(a=0; a<me->totface; a++, mface++, tface++) {
120                         if(tface->flag & TF_SELECT && mface->v3) {
121                                 DO_MINMAX((me->mvert+mface->v1)->co, min, max);
122                                 DO_MINMAX((me->mvert+mface->v2)->co, min, max);
123                                 DO_MINMAX((me->mvert+mface->v3)->co, min, max);
124                                 if(mface->v4) DO_MINMAX((me->mvert+mface->v4)->co, min, max);
125                         }
126                 }
127                 VecMidf(result, min, max);
128                 break;
129         case V3D_CURSOR: /*cursor center*/ 
130                 cursx= give_cursor();
131                 /* shift to objects world */
132                 result[0]= cursx[0]-ob->obmat[3][0];
133                 result[1]= cursx[1]-ob->obmat[3][1];
134                 result[2]= cursx[2]-ob->obmat[3][2];
135                 break;
136         case V3D_LOCAL: /*object center*/
137         case V3D_CENTROID: /* multiple objects centers, only one object here*/
138         default:
139                 result[0]= result[1]= result[2]= 0.0;
140                 break;
141         }
142 }
143
144 static void uv_calc_map_matrix(float result[][4], Object *ob, float upangledeg, float sideangledeg, float radius)
145 {
146         float rotup[4][4], rotside[4][4], viewmatrix[4][4], rotobj[4][4];
147         float sideangle= 0.0, upangle= 0.0;
148         int k;
149
150         /* get rotation of the current view matrix */
151         Mat4CpyMat4(viewmatrix,G.vd->viewmat);
152         /* but shifting */
153         for( k= 0; k< 4; k++) viewmatrix[3][k] =0.0;
154
155         /* get rotation of the current object matrix */
156         Mat4CpyMat4(rotobj,ob->obmat);
157         /* but shifting */
158         for( k= 0; k< 4; k++) rotobj[3][k] =0.0;
159
160         Mat4Clr(*rotup);
161         Mat4Clr(*rotside);
162
163         /* compensate front/side.. against opengl x,y,z world definition */
164         /* this is "kanonen gegen spatzen", a few plus minus 1 will do here */
165         /* i wanted to keep the reason here, so we're rotating*/
166         sideangle= M_PI * (sideangledeg + 180.0) /180.0;
167         rotside[0][0]= (float)cos(sideangle);
168         rotside[0][1]= -(float)sin(sideangle);
169         rotside[1][0]= (float)sin(sideangle);
170         rotside[1][1]= (float)cos(sideangle);
171         rotside[2][2]= 1.0f;
172       
173         upangle= M_PI * upangledeg /180.0;
174         rotup[1][1]= (float)cos(upangle)/radius;
175         rotup[1][2]= -(float)sin(upangle)/radius;
176         rotup[2][1]= (float)sin(upangle)/radius;
177         rotup[2][2]= (float)cos(upangle)/radius;
178         rotup[0][0]= (float)1.0/radius;
179
180         /* calculate transforms*/
181         Mat4MulSerie(result,rotup,rotside,viewmatrix,rotobj,NULL,NULL,NULL,NULL);
182 }
183
184 static void uv_calc_shift_project(float *target, float *shift, float rotmat[][4], int projectionmode, float *source, float *min, float *max)
185 {
186         float pv[3];
187
188         VecSubf(pv, source, shift);
189         Mat4MulVecfl(rotmat, pv);
190
191         switch(projectionmode) {
192         case B_UVAUTO_CYLINDER: 
193                 tubemap(pv[0], pv[1], pv[2], &target[0],&target[1]);
194                 /* split line is always zero */
195                 if (target[0] >= 1.0f) target[0] -= 1.0f;  
196                 break;
197
198         case B_UVAUTO_SPHERE: 
199                 spheremap(pv[0], pv[1], pv[2], &target[0],&target[1]);
200                 /* split line is always zero */
201                 if (target[0] >= 1.0f) target[0] -= 1.0f;
202                 break;
203
204         case 3: /* ortho special case for BOUNDS */
205                 target[0] = -pv[0];
206                 target[1] = pv[2];
207                 break;
208
209         case 4: 
210                 {
211                 /* very special case for FROM WINDOW */
212                 float pv4[4], dx, dy, x= 0.0, y= 0.0;
213
214                 dx= G.vd->area->winx;
215                 dy= G.vd->area->winy;
216
217                 VecCopyf(pv4, source);
218         pv4[3] = 1.0;
219
220                 /* rotmat is the object matrix in this case */
221         Mat4MulVec4fl(rotmat,pv4); 
222
223                 /* almost project_short */
224             Mat4MulVec4fl(G.vd->persmat,pv4);
225                 if (fabs(pv4[3]) > 0.00001) { /* avoid division by zero */
226                         target[0] = dx/2.0 + (dx/2.0)*pv4[0]/pv4[3];
227                         target[1] = dy/2.0 + (dy/2.0)*pv4[1]/pv4[3];
228                 }
229                 else {
230                         /* scaling is lost but give a valid result */
231                         target[0] = dx/2.0 + (dx/2.0)*pv4[0];
232                         target[1] = dy/2.0 + (dy/2.0)*pv4[1];
233                 }
234
235         /* G.vd->persmat seems to do this funky scaling */ 
236                 if(dx > dy) {
237                         y= (dx-dy)/2.0;
238                         dy = dx;
239                 }
240                 else {
241                         x= (dy-dx)/2.0;
242                         dx = dy;
243                 }
244                 target[0]= (x + target[0])/dx;
245                 target[1]= (y + target[1])/dy;
246
247                 }
248                 break;
249
250     default:
251                 target[0] = 0.0;
252                 target[1] = 1.0;
253         }
254
255         /* we know the values here and may need min_max later */
256         /* max requests independand from min; not fastest but safest */ 
257         if(min) {
258                 min[0] = MIN2(target[0], min[0]);
259                 min[1] = MIN2(target[1], min[1]);
260         }
261         if(max) {
262                 max[0] = MAX2(target[0], max[0]);
263                 max[1] = MAX2(target[1], max[1]);
264         }
265 }
266
267 void calculate_uv_map(unsigned short mapmode)
268 {
269         Mesh *me;
270         TFace *tface;
271         MFace *mface;
272         Object *ob;
273         float dx, dy, rotatematrix[4][4], radius= 1.0, min[3], cent[3], max[3];
274         float fac= 1.0, upangledeg= 0.0, sideangledeg= 90.0;
275         int i, b, mi, a, n;
276         /* settings from buttonswindow */
277         extern float uv_calc_radius, uv_calc_cubesize;
278         extern short uv_calc_mapdir, uv_calc_mapalign;
279
280         if(uv_calc_mapdir==1)  {
281                 upangledeg= 90.0;
282                 sideangledeg= 0.0;
283         }
284         else {
285                 upangledeg= 0.0;
286                 if(uv_calc_mapalign==1) sideangledeg= 0.0;
287                 else sideangledeg= 90.0;
288         }
289
290         me= get_mesh(ob=OBACT);
291         if(me==0 || me->tface==0) return;
292         if(me->totface==0) return;
293         
294         switch(mapmode) {
295         case B_UVAUTO_BOUNDS1:
296         case B_UVAUTO_BOUNDS2:
297         case B_UVAUTO_BOUNDS4:
298         case B_UVAUTO_BOUNDS8:
299                 switch(mapmode) {
300                 case B_UVAUTO_BOUNDS2: fac = 0.5; break;
301                 case B_UVAUTO_BOUNDS4: fac = 0.25; break;
302                 case B_UVAUTO_BOUNDS8: fac = 0.125; break;
303                 }
304
305                 min[0]= min[1]= 1.0;
306                 max[0]= max[1]= 0.0;
307
308                 uv_calc_center_vector(cent, ob, me);
309                 uv_calc_map_matrix(rotatematrix, ob, upangledeg, sideangledeg, 1.0f);
310                         
311                 tface= me->tface;
312                 mface= me->mface;
313                 for(a=0; a<me->totface; a++, mface++, tface++) {
314                         if(tface->flag & TF_SELECT && mface->v3) {
315                                 uv_calc_shift_project(tface->uv[0],cent,rotatematrix,3,(me->mvert+mface->v1)->co,min,max);
316                                 uv_calc_shift_project(tface->uv[1],cent,rotatematrix,3,(me->mvert+mface->v2)->co,min,max);
317                                 uv_calc_shift_project(tface->uv[2],cent,rotatematrix,3,(me->mvert+mface->v3)->co,min,max);
318                                 if(mface->v4)
319                                         uv_calc_shift_project(tface->uv[3],cent,rotatematrix,3,(me->mvert+mface->v4)->co,min,max);
320                         }
321                 }
322                 
323                 /* rescale UV to be in 0..1,1/2,1/4,1/8 */
324                 dx= (max[0]-min[0]);
325                 dy= (max[1]-min[1]);
326
327                 tface= me->tface;
328                 mface= me->mface;
329                 for(a=0; a<me->totface; a++, mface++, tface++) {
330                         if(tface->flag & TF_SELECT && mface->v3) {
331                                 if(mface->v4) b= 3; else b= 2;
332                                 for(; b>=0; b--) {
333                                         tface->uv[b][0]= ((tface->uv[b][0]-min[0])*fac)/dx;
334                                         tface->uv[b][1]= 1.0-fac+((tface->uv[b][1]-min[1])*fac)/dy;
335                                 }
336                         }
337                 }
338                 break;
339
340         case B_UVAUTO_WINDOW:           
341                 cent[0] = cent[1] = cent[2] = 0.0; 
342                 Mat4CpyMat4(rotatematrix,ob->obmat);
343
344                 tface= me->tface;
345                 mface= me->mface;
346                 for(a=0; a<me->totface; a++, mface++, tface++) {
347                         if(tface->flag & TF_SELECT && mface->v3) {
348                                 uv_calc_shift_project(tface->uv[0],cent,rotatematrix,4,(me->mvert+mface->v1)->co,NULL,NULL);
349                                 uv_calc_shift_project(tface->uv[1],cent,rotatematrix,4,(me->mvert+mface->v2)->co,NULL,NULL);
350                                 uv_calc_shift_project(tface->uv[2],cent,rotatematrix,4,(me->mvert+mface->v3)->co,NULL,NULL);
351                                 if(mface->v4)
352                                         uv_calc_shift_project(tface->uv[3],cent,rotatematrix,4,(me->mvert+mface->v4)->co,NULL,NULL);
353                         }
354                 }
355                 break;
356
357         case B_UVAUTO_STD8:
358         case B_UVAUTO_STD4:
359         case B_UVAUTO_STD2:
360         case B_UVAUTO_STD1:
361                 switch(mapmode) {
362                 case B_UVAUTO_STD8: fac = 0.125; break;
363                 case B_UVAUTO_STD4: fac = 0.25; break;
364                 case B_UVAUTO_STD2: fac = 0.5; break;
365                 }
366
367                 tface= me->tface;
368                 for(a=0; a<me->totface; a++, tface++)
369                         if(tface->flag & TF_SELECT) 
370                                 default_uv(tface->uv, fac);
371                 break;
372
373         case B_UVAUTO_CYLINDER:
374         case B_UVAUTO_SPHERE:
375                 uv_calc_center_vector(cent, ob, me);
376                         
377                 if(mapmode==B_UVAUTO_CYLINDER) radius = uv_calc_radius;
378
379                 /* be compatible to the "old" sphere/cylinder mode */
380                 if (uv_calc_mapdir== 2)
381                         Mat4One(rotatematrix);
382                 else 
383                         uv_calc_map_matrix(rotatematrix,ob,upangledeg,sideangledeg,radius);
384
385                 tface= me->tface;
386                 mface= me->mface;
387                 for(a=0; a<me->totface; a++, mface++, tface++) {
388                         if(tface->flag & TF_SELECT && mface->v3) {
389                                 uv_calc_shift_project(tface->uv[0],cent,rotatematrix,mapmode,(me->mvert+mface->v1)->co,NULL,NULL);
390                                 uv_calc_shift_project(tface->uv[1],cent,rotatematrix,mapmode,(me->mvert+mface->v2)->co,NULL,NULL);
391                                 uv_calc_shift_project(tface->uv[2],cent,rotatematrix,mapmode,(me->mvert+mface->v3)->co,NULL,NULL);
392                                 n = 3;       
393                                 if(mface->v4) {
394                                         uv_calc_shift_project(tface->uv[3],cent,rotatematrix,mapmode,(me->mvert+mface->v4)->co,NULL,NULL);
395                                         n=4;
396                                 }
397
398                                 mi = 0;
399                                 for (i = 1; i < n; i++)
400                                         if (tface->uv[i][0] > tface->uv[mi][0]) mi = i;
401
402                                 for (i = 0; i < n; i++) {
403                                         if (i != mi) {
404                                                 dx = tface->uv[mi][0] - tface->uv[i][0];
405                                                 if (dx > 0.5) tface->uv[i][0] += 1.0;
406                                         } 
407                                 } 
408                         }
409                 }
410
411                 break;
412
413         case B_UVAUTO_CUBE:
414                 {
415                 /* choose x,y,z axis for projetion depending on the largest normal */
416                 /* component, but clusters all together around the center of map */
417                 float no[3];
418                 short cox, coy;
419                 float *loc= ob->obmat[3];
420                 MVert *mv= me->mvert;
421
422                 tface= me->tface;
423                 mface= me->mface;
424                 for(a=0; a<me->totface; a++, mface++, tface++) {
425                         if(tface->flag & TF_SELECT && mface->v3) {
426                                 CalcNormFloat((mv+mface->v1)->co, (mv+mface->v2)->co, (mv+mface->v3)->co, no);
427                                         
428                                 no[0]= fabs(no[0]);
429                                 no[1]= fabs(no[1]);
430                                 no[2]= fabs(no[2]);
431                                 
432                                 cox=0; coy= 1;
433                                 if(no[2]>=no[0] && no[2]>=no[1]);
434                                 else if(no[1]>=no[0] && no[1]>=no[2]) coy= 2;
435                                 else { cox= 1; coy= 2; }
436                                 
437                                 tface->uv[0][0]= 0.5+0.5*uv_calc_cubesize*(loc[cox] + (mv+mface->v1)->co[cox]);
438                                 tface->uv[0][1]= 0.5+0.5*uv_calc_cubesize*(loc[coy] + (mv+mface->v1)->co[coy]);
439                                 dx = floor(tface->uv[0][0]);
440                                 dy = floor(tface->uv[0][1]);
441                                 tface->uv[0][0] -= dx;
442                                 tface->uv[0][1] -= dy;
443                                 tface->uv[1][0]= 0.5+0.5*uv_calc_cubesize*(loc[cox] + (mv+mface->v2)->co[cox]);
444                                 tface->uv[1][1]= 0.5+0.5*uv_calc_cubesize*(loc[coy] + (mv+mface->v2)->co[coy]);
445                                 tface->uv[1][0] -= dx;
446                                 tface->uv[1][1] -= dy;
447                                 tface->uv[2][0]= 0.5+0.5*uv_calc_cubesize*(loc[cox] + (mv+mface->v3)->co[cox]);
448                                 tface->uv[2][1]= 0.5+0.5*uv_calc_cubesize*(loc[coy] + (mv+mface->v3)->co[coy]);
449                                 tface->uv[2][0] -= dx;
450                                 tface->uv[2][1] -= dy;
451                                 if(mface->v4) {
452                                         tface->uv[3][0]= 0.5+0.5*uv_calc_cubesize*(loc[cox] + (mv+mface->v4)->co[cox]);
453                                         tface->uv[3][1]= 0.5+0.5*uv_calc_cubesize*(loc[coy] + (mv+mface->v4)->co[coy]);
454                                         tface->uv[3][0] -= dx;
455                                         tface->uv[3][1] -= dy;
456                                 }
457                         }
458                 }
459                 }
460                 break; 
461         default:
462                 return;
463         } /* end switch mapmode */
464
465         /* clipping and wrapping */
466         if(G.sima && G.sima->flag & SI_CLIP_UV) {
467                 tface= me->tface;
468                 mface= me->mface;
469                 for(a=0; a<me->totface; a++, mface++, tface++) {
470                         if(!(tface->flag & TF_SELECT && mface->v3)) continue;
471                                 
472                         dx= dy= 0;
473                         if(mface->v4) b= 3; else b= 2;
474                         for(; b>=0; b--) {
475                                 while(tface->uv[b][0] + dx < 0.0) dx+= 0.5;
476                                 while(tface->uv[b][0] + dx > 1.0) dx-= 0.5;
477                                 while(tface->uv[b][1] + dy < 0.0) dy+= 0.5;
478                                 while(tface->uv[b][1] + dy > 1.0) dy-= 0.5;
479                         }
480         
481                         if(mface->v4) b= 3; else b= 2;
482                         for(; b>=0; b--) {
483                                 tface->uv[b][0]+= dx;
484                                 CLAMP(tface->uv[b][0], 0.0, 1.0);
485                                 
486                                 tface->uv[b][1]+= dy;
487                                 CLAMP(tface->uv[b][1], 0.0, 1.0);
488                         }
489                 }
490         }
491
492         BIF_undo_push("UV calculation");
493
494         allqueue(REDRAWVIEW3D, 0);
495         allqueue(REDRAWIMAGE, 0);
496 }
497
498 void set_lasttface()
499 {
500         Mesh *me;
501         TFace *tface;
502         int a;
503         
504         lasttface= 0;
505         if(OBACT==NULL || OBACT->type!=OB_MESH) return;
506         
507         me= get_mesh(OBACT);
508         if(me==0 || me->tface==0) return;
509         
510         tface= me->tface;
511         a= me->totface;
512         while(a--) {
513                 if(tface->flag & TF_ACTIVE) {
514                         lasttface= tface;
515                         return;
516                 }
517                 tface++;
518         }
519
520         tface= me->tface;
521         a= me->totface;
522         while(a--) {
523                 if(tface->flag & TF_SELECT) {
524                         lasttface= tface;
525                         return;
526                 }
527                 tface++;
528         }
529
530         tface= me->tface;
531         a= me->totface;
532         while(a--) {
533                 if((tface->flag & TF_HIDE)==0) {
534                         lasttface= tface;
535                         return;
536                 }
537                 tface++;
538         }
539 }
540
541 void default_uv(float uv[][2], float size)
542 {
543         int dy;
544         
545         if(size>1.0) size= 1.0;
546
547         dy= 1.0-size;
548         
549         uv[0][0]= 0;
550         uv[0][1]= size+dy;
551         
552         uv[1][0]= 0;
553         uv[1][1]= dy;
554         
555         uv[2][0]= size;
556         uv[2][1]= dy;
557         
558         uv[3][0]= size;
559         uv[3][1]= size+dy;
560         
561         
562 }
563
564 void default_tface(TFace *tface)
565 {
566         default_uv(tface->uv, 1.0);
567
568         tface->col[0]= tface->col[1]= tface->col[2]= tface->col[3]= vpaint_get_current_col();
569
570         tface->mode= TF_TEX;
571         tface->mode= 0;
572         tface->flag= TF_SELECT;
573         tface->tpage= 0;
574         tface->mode |= TF_DYNAMIC;
575 }
576
577 void make_tfaces(Mesh *me) 
578 {
579         TFace *tface;
580         int a;
581         
582         a= me->totface;
583         if(a==0) return;
584         tface= me->tface= MEM_callocN(a*sizeof(TFace), "tface");
585         while(a--) {
586                 default_tface(tface);
587                 tface++;
588         }
589         if(me->mcol) {
590                 mcol_to_tface(me, 1);
591         }
592 }
593
594
595 void reveal_tface()
596 {
597         Mesh *me;
598         TFace *tface;
599         int a;
600         
601         me= get_mesh(OBACT);
602         if(me==0 || me->tface==0 || me->totface==0) return;
603         
604         tface= me->tface;
605         a= me->totface;
606         while(a--) {
607                 if(tface->flag & TF_HIDE) {
608                         tface->flag |= TF_SELECT;
609                         tface->flag -= TF_HIDE;
610                 }
611                 tface++;
612         }
613
614         BIF_undo_push("Reveal UV face");
615
616         object_tface_flags_changed(OBACT, 0);
617 }
618
619 void hide_tface()
620 {
621         Mesh *me;
622         TFace *tface;
623         int a;
624         
625         me= get_mesh(OBACT);
626         if(me==0 || me->tface==0 || me->totface==0) return;
627         
628         if(G.qual & LR_ALTKEY) {
629                 reveal_tface();
630                 return;
631         }
632         
633         tface= me->tface;
634         a= me->totface;
635         while(a--) {
636                 if(tface->flag & TF_HIDE);
637                 else {
638                         if(G.qual & LR_SHIFTKEY) {
639                                 if( (tface->flag & TF_SELECT)==0) tface->flag |= TF_HIDE;
640                         }
641                         else {
642                                 if( (tface->flag & TF_SELECT)) tface->flag |= TF_HIDE;
643                         }
644                 }
645                 if(tface->flag & TF_HIDE) tface->flag &= ~TF_SELECT;
646                 
647                 tface++;
648         }
649
650         BIF_undo_push("Hide UV face");
651
652         object_tface_flags_changed(OBACT, 0);
653 }
654
655 void select_linked_tfaces(int mode)
656 {
657         Object *ob;
658         Mesh *me;
659         TFace *tf;
660         MFace *mf;
661         int a, doit=1, mark=0;
662         char *cpmain, *linkflag;
663         short mval[2];
664         unsigned int index=0;
665
666         ob = OBACT;
667         me = get_mesh(ob);
668         if(me==0 || me->tface==0 || me->totface==0) return;
669
670         if (mode==0 || mode==1) {
671                 if (!(ob->lay & G.vd->lay))
672                         error("The active object is not in this layer");
673                         
674                 getmouseco_areawin(mval);
675                 if (!face_pick(me, mval[0], mval[1], &index)) return;
676         }
677
678         if(me->medge) {
679                 select_linked_tfaces_with_seams(mode, me, index);
680                 return;
681         }
682
683         cpmain= MEM_callocN(me->totvert, "cpmain");
684         linkflag= MEM_callocN(sizeof(char)*me->totface, "linkflaguv");
685
686         if (mode==0 || mode==1) {
687                 /* only put face under cursor in array */
688                 mf= ((MFace*)me->mface) + index;
689                 cpmain[mf->v1]= cpmain[mf->v2]= cpmain[mf->v3]= 1;
690                 if (mf->v4) cpmain[mf->v4]= 1;
691                 linkflag[index]= 1;
692         }
693         else {
694                 /* fill array by selection */
695                 tf= me->tface;
696                 mf= me->mface;
697                 for(a=0; a<me->totface; a++, tf++, mf++) {
698                         if(tf->flag & TF_HIDE);
699                         else if(tf->flag & TF_SELECT) {
700                                 if(mf->v3) {
701                                         cpmain[mf->v1]= 1;
702                                         cpmain[mf->v2]= 1;
703                                         cpmain[mf->v3]= 1;
704                                         if(mf->v4) cpmain[mf->v4]= 1;
705                                         linkflag[a]= 1;
706                                 }
707                         }
708                 }
709         }
710         
711         while(doit) {
712                 doit= 0;
713                 
714                 /* expand selection */
715                 tf= me->tface;
716                 mf= me->mface;
717                 for(a=0; a<me->totface; a++, tf++, mf++) {
718                         if(tf->flag & TF_HIDE);
719                         else if(mf->v3 && !linkflag[a]) {
720                                 mark= 0;
721
722                                 if(cpmain[mf->v1] || cpmain[mf->v2] || cpmain[mf->v3])
723                                         mark= 1;
724                                 else if(mf->v4 && cpmain[mf->v4])
725                                         mark= 1;
726
727                                 if(mark) {
728                                         linkflag[a]= 1;
729                                         cpmain[mf->v1]= cpmain[mf->v2]= cpmain[mf->v3]= 1;
730                                         if(mf->v4) cpmain[mf->v4]= 1;
731                                         doit= 1;
732                                 }
733                         }
734                 }
735                 
736         }
737
738         if(mode==0 || mode==2) {
739                 for(a=0, tf=me->tface; a<me->totface; a++, tf++)
740                         if(linkflag[a])
741                                 tf->flag |= TF_SELECT;
742                         else
743                                 tf->flag &= ~TF_SELECT;
744         }
745         else if(mode==1) {
746                 for(a=0, tf=me->tface; a<me->totface; a++, tf++)
747                         if(linkflag[a] && (tf->flag & TF_SELECT))
748                                 break;
749
750                 if (a<me->totface) {
751                         for(a=0, tf=me->tface; a<me->totface; a++, tf++)
752                                 if(linkflag[a])
753                                         tf->flag &= ~TF_SELECT;
754                 }
755                 else {
756                         for(a=0, tf=me->tface; a<me->totface; a++, tf++)
757                                 if(linkflag[a])
758                                         tf->flag |= TF_SELECT;
759                 }
760         }
761         
762         MEM_freeN(cpmain);
763         MEM_freeN(linkflag);
764         
765         BIF_undo_push("Select linked UV face");
766
767         object_tface_flags_changed(OBACT, 0);
768 }
769
770 void deselectall_tface()
771 {
772         Mesh *me;
773         TFace *tface;
774         int a, sel;
775                 
776         me= get_mesh(OBACT);
777         if(me==0 || me->tface==0) return;
778         
779         tface= me->tface;
780         a= me->totface;
781         sel= 0;
782         while(a--) {
783                 if(tface->flag & TF_HIDE);
784                 else if(tface->flag & TF_SELECT) sel= 1;
785                 tface++;
786         }
787         
788         tface= me->tface;
789         a= me->totface;
790         while(a--) {
791                 if(tface->flag & TF_HIDE);
792                 else {
793                         if(sel) tface->flag &= ~TF_SELECT;
794                         else tface->flag |= TF_SELECT;
795                 }
796                 tface++;
797         }
798
799         BIF_undo_push("(De)select all UV face");
800
801         object_tface_flags_changed(OBACT, 0);
802 }
803
804 void selectswap_tface(void)
805 {
806         Mesh *me;
807         TFace *tface;
808         int a;
809                 
810         me= get_mesh(OBACT);
811         if(me==0 || me->tface==0) return;
812         
813         tface= me->tface;
814         a= me->totface;
815         while(a--) {
816                 if(tface->flag & TF_HIDE);
817                 else {
818                         if(tface->flag & TF_SELECT) tface->flag &= ~TF_SELECT;
819                         else tface->flag |= TF_SELECT;
820                 }
821                 tface++;
822         }
823
824         BIF_undo_push("Select inverse UV face");
825
826         object_tface_flags_changed(OBACT, 0);
827 }
828
829 void rotate_uv_tface()
830 {
831         Mesh *me;
832         TFace *tface;
833         MFace *mface;
834         short mode;
835         int a;
836         
837         me= get_mesh(OBACT);
838         if(me==0 || me->tface==0) return;
839         
840         mode= pupmenu("Rotate %t|UV Co-ordinates %x1|Vertex Colors %x2");
841         
842         if(mode<1) return;
843         
844         tface= me->tface;
845         mface= me->mface;
846         a= me->totface;
847         while(a--) {
848                 if(tface->flag & TF_SELECT) {
849                         if(mode==1) {
850                                 float u1= tface->uv[0][0];
851                                 float v1= tface->uv[0][1];
852                                 
853                                 tface->uv[0][0]= tface->uv[1][0];
854                                 tface->uv[0][1]= tface->uv[1][1];
855         
856                                 tface->uv[1][0]= tface->uv[2][0];
857                                 tface->uv[1][1]= tface->uv[2][1];
858         
859                                 if(mface->v4) {
860                                         tface->uv[2][0]= tface->uv[3][0];
861                                         tface->uv[2][1]= tface->uv[3][1];
862                                 
863                                         tface->uv[3][0]= u1;
864                                         tface->uv[3][1]= v1;
865                                 }
866                                 else {
867                                         tface->uv[2][0]= u1;
868                                         tface->uv[2][1]= v1;
869                                 }
870                         }
871                         else if(mode==2) {
872                                 unsigned int tcol= tface->col[0];
873                                 
874                                 tface->col[0]= tface->col[1];
875                                 tface->col[1]= tface->col[2];
876         
877                                 if(mface->v4) {
878                                         tface->col[2]= tface->col[3];
879                                         tface->col[3]= tcol;
880                                 }
881                                 else {
882                                         tface->col[2]= tcol;
883                                 }
884                         }
885                 }
886                 tface++;
887                 mface++;
888         }
889         
890         BIF_undo_push("Rotate UV face");
891
892         object_uvs_changed(OBACT);
893 }
894
895 void mirror_uv_tface()
896 {
897         Mesh *me;
898         TFace *tface;
899         MFace *mface;
900         short mode;
901         int a;
902         
903         me= get_mesh(OBACT);
904         if(me==0 || me->tface==0) return;
905         
906         mode= pupmenu("Mirror %t|UV Co-ordinates %x1|Vertex Colors %x2");
907         
908         if(mode<1) return;
909         
910         tface= me->tface;
911         mface= me->mface;
912         a= me->totface;
913         while(a--) {
914                 if(tface->flag & TF_SELECT) {
915                         if(mode==1) {
916                                 float u1= tface->uv[0][0];
917                                 float v1= tface->uv[0][1];
918                                 if(mface->v4) {
919                                         tface->uv[0][0]= tface->uv[3][0];
920                                         tface->uv[0][1]= tface->uv[3][1];
921                                 
922                                         tface->uv[3][0]= u1;
923                                         tface->uv[3][1]= v1;
924
925                                         u1= tface->uv[1][0];
926                                         v1= tface->uv[1][1];
927
928                                         tface->uv[1][0]= tface->uv[2][0];
929                                         tface->uv[1][1]= tface->uv[2][1];
930                                 
931                                         tface->uv[2][0]= u1;
932                                         tface->uv[2][1]= v1;
933                                 }
934                                 else {
935                                         tface->uv[0][0]= tface->uv[2][0];
936                                         tface->uv[0][1]= tface->uv[2][1];
937                                         tface->uv[2][0]= u1;
938                                         tface->uv[2][1]= v1;
939                                 }
940                         }
941                         else if(mode==2) {
942                                 unsigned int tcol= tface->col[0];
943                                 if(mface->v4) {
944                                         tface->col[0]= tface->col[3];
945                                         tface->col[3]= tcol;
946
947                                         tcol = tface->col[1];
948                                         tface->col[1]= tface->col[2];
949                                         tface->col[2]= tcol;
950                                 }
951                                 else {
952                                         tface->col[0]= tface->col[2];
953                                         tface->col[2]= tcol;
954                                 }
955                         }
956                 }
957                 tface++;
958                 mface++;
959         }
960         
961         BIF_undo_push("Mirror UV face");
962
963         object_uvs_changed(OBACT);
964 }
965
966 void minmax_tface(float *min, float *max)
967 {
968         Object *ob;
969         Mesh *me;
970         MFace *mf;
971         TFace *tf;
972         MVert *mv;
973         int a;
974         float vec[3], bmat[3][3];
975         
976         ob = OBACT;
977         if (ob==0) return;
978         me= get_mesh(ob);
979         if(me==0 || me->tface==0) return;
980         
981         Mat3CpyMat4(bmat, ob->obmat);
982
983         mv= me->mvert;
984         mf= me->mface;
985         tf= me->tface;
986         for (a=me->totface; a>0; a--, mf++, tf++) {
987                 if (!mf->v3 || tf->flag & TF_HIDE || !(tf->flag & TF_SELECT))
988                         continue;
989
990                 VECCOPY(vec, (mv+mf->v1)->co);
991                 Mat3MulVecfl(bmat, vec);
992                 VecAddf(vec, vec, ob->obmat[3]);
993                 DO_MINMAX(vec, min, max);               
994
995                 VECCOPY(vec, (mv+mf->v2)->co);
996                 Mat3MulVecfl(bmat, vec);
997                 VecAddf(vec, vec, ob->obmat[3]);
998                 DO_MINMAX(vec, min, max);               
999
1000                 VECCOPY(vec, (mv+mf->v3)->co);
1001                 Mat3MulVecfl(bmat, vec);
1002                 VecAddf(vec, vec, ob->obmat[3]);
1003                 DO_MINMAX(vec, min, max);               
1004
1005                 if (mf->v4) {
1006                         VECCOPY(vec, (mv+mf->v4)->co);
1007                         Mat3MulVecfl(bmat, vec);
1008                         VecAddf(vec, vec, ob->obmat[3]);
1009                         DO_MINMAX(vec, min, max);
1010                 }
1011         }
1012 }
1013
1014 /**
1015  * Returns the face under the give position in screen coordinates.
1016  * Code extracted from face_select routine.
1017  * Question: why is all of the backbuffer drawn?
1018  * We're only interested in one pixel!
1019  * @author      Maarten Gribnau
1020  * @param       me              the mesh with the faces to be picked
1021  * @param       x               the x-coordinate to pick at
1022  * @param       y               the y-coordinate to pick at
1023  * @param       index   the index of the face
1024  * @return 1 if found, 0 if none found
1025  */
1026 int face_pick(Mesh *me, short x, short y, unsigned int *index)
1027 {
1028         unsigned int col;
1029
1030         if (me==0 || me->tface==0)
1031                 return 0;
1032
1033         /* Have OpenGL draw in the back buffer with color coded face indices */
1034         if (curarea->win_swap==WIN_EQUAL) {
1035                 G.vd->flag |= V3D_NEEDBACKBUFDRAW;
1036         }
1037         if (G.vd->flag & V3D_NEEDBACKBUFDRAW) {
1038                 backdrawview3d(0);
1039                 persp(PERSP_VIEW);
1040         }
1041         /* Read the pixel under the cursor */
1042 #ifdef __APPLE__
1043         glReadBuffer(GL_AUX0);
1044 #endif
1045         glReadPixels(x+curarea->winrct.xmin, y+curarea->winrct.ymin, 1, 1,
1046                 GL_RGBA, GL_UNSIGNED_BYTE, &col);
1047         glReadBuffer(GL_BACK);
1048
1049         /* Unbelievable! */
1050         if (G.order==B_ENDIAN) {
1051                 SWITCH_INT(col);
1052         }
1053         /* Convert the color back to a face index */
1054         *index = framebuffer_to_index(col);
1055         if (col==0 || (*index)<=0 || (*index)>me->totface)
1056                 return 0;
1057
1058         (*index)--;
1059         
1060         return 1;
1061 }
1062
1063 void face_select()
1064 {
1065         Object *ob;
1066         Mesh *me;
1067         TFace *tface, *tsel;
1068         MFace *msel;
1069         short mval[2];
1070         unsigned int a, index;
1071
1072         /* Get the face under the cursor */
1073         ob = OBACT;
1074         if (!(ob->lay & G.vd->lay)) {
1075                 error("The active object is not in this layer");
1076         }
1077         me = get_mesh(ob);
1078         getmouseco_areawin(mval);
1079         if (!face_pick(me, mval[0], mval[1], &index)) return;
1080         
1081         tsel= (((TFace*)me->tface)+index);
1082         msel= (((MFace*)me->mface)+index);
1083
1084         if (tsel->flag & TF_HIDE) return;
1085         
1086         /* clear flags */
1087         tface = me->tface;
1088         a = me->totface;
1089         while (a--) {
1090                 if (G.qual & LR_SHIFTKEY)
1091                         tface->flag &= ~TF_ACTIVE;
1092                 else
1093                         tface->flag &= ~(TF_ACTIVE+TF_SELECT);
1094                 tface++;
1095         }
1096         
1097         tsel->flag |= TF_ACTIVE;
1098
1099         if (G.qual & LR_SHIFTKEY) {
1100                 if (tsel->flag & TF_SELECT)
1101                         tsel->flag &= ~TF_SELECT;
1102                 else
1103                         tsel->flag |= TF_SELECT;
1104         }
1105         else tsel->flag |= TF_SELECT;
1106         
1107         lasttface = tsel;
1108         
1109         /* image window redraw */
1110         
1111         BIF_undo_push("Select UV face");
1112
1113         object_tface_flags_changed(OBACT, 1);
1114 }
1115
1116 void face_borderselect()
1117 {
1118         Mesh *me;
1119         TFace *tface;
1120         rcti rect;
1121         unsigned int *rectm, *rt;
1122         int a, sx, sy, index, val;
1123         char *selar;
1124         
1125         me= get_mesh(OBACT);
1126         if(me==0 || me->tface==0) return;
1127         if(me->totface==0) return;
1128         
1129         val= get_border(&rect, 3);
1130         
1131         /* why readbuffer here? shouldn't be necessary (maybe a flush or so) */
1132         glReadBuffer(GL_BACK);
1133 #ifdef __APPLE__
1134         glReadBuffer(GL_AUX0); /* apple only */
1135 #endif
1136         
1137         if(val) {
1138                 selar= MEM_callocN(me->totface+1, "selar");
1139                 
1140                 sx= (rect.xmax-rect.xmin+1);
1141                 sy= (rect.ymax-rect.ymin+1);
1142                 if(sx*sy<=0) return;
1143
1144                 rt=rectm= MEM_mallocN(sizeof(int)*sx*sy, "selrect");
1145                 glReadPixels(rect.xmin+curarea->winrct.xmin,  rect.ymin+curarea->winrct.ymin, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE,  rectm);
1146                 if(G.order==B_ENDIAN) IMB_convert_rgba_to_abgr(sx*sy, rectm);
1147
1148                 a= sx*sy;
1149                 while(a--) {
1150                         if(*rt) {
1151                                 index= framebuffer_to_index(*rt);
1152                                 if(index<=me->totface) selar[index]= 1;
1153                         }
1154                         rt++;
1155                 }
1156                 
1157                 tface= me->tface;
1158                 for(a=1; a<=me->totface; a++, tface++) {
1159                         if(selar[a]) {
1160                                 if(tface->flag & TF_HIDE);
1161                                 else {
1162                                         if(val==LEFTMOUSE) tface->flag |= TF_SELECT;
1163                                         else tface->flag &= ~TF_SELECT;
1164                                 }
1165                         }
1166                 }
1167                 
1168                 MEM_freeN(rectm);
1169                 MEM_freeN(selar);
1170
1171                 BIF_undo_push("Border Select UV face");
1172
1173                 object_tface_flags_changed(OBACT, 0);
1174         }
1175 #ifdef __APPLE__        
1176         glReadBuffer(GL_BACK);
1177 #endif
1178 }
1179
1180 /* Pupmenu codes: */
1181 #define UV_CUBE_MAPPING 2
1182 #define UV_CYL_MAPPING 3
1183 #define UV_SPHERE_MAPPING 4
1184 #define UV_BOUNDS8_MAPPING 68
1185 #define UV_BOUNDS4_MAPPING 65
1186 #define UV_BOUNDS2_MAPPING 66
1187 #define UV_BOUNDS1_MAPPING 67
1188 #define UV_STD8_MAPPING 131
1189 #define UV_STD4_MAPPING 130
1190 #define UV_STD2_MAPPING 129
1191 #define UV_STD1_MAPPING 128
1192 #define UV_WINDOW_MAPPING 5
1193 #define UV_LSCM_MAPPING 6
1194 #define UV_CYL_EX 32
1195 #define UV_SPHERE_EX 34
1196
1197 /* Some macro tricks to make pupmenu construction look nicer :-)
1198    Sorry, just did it for fun. */
1199
1200 #define _STR(x) " " #x
1201 #define STRING(x) _STR(x)
1202
1203 #define MENUSTRING(string, code) string " %x" STRING(code)
1204 #define MENUTITLE(string) string " %t|" 
1205
1206 void uv_autocalc_tface()
1207 {
1208         short mode;
1209         mode= pupmenu(MENUTITLE("UV Calculation")
1210                       MENUSTRING("Cube",          UV_CUBE_MAPPING) "|"
1211                       MENUSTRING("Cylinder",      UV_CYL_MAPPING) "|"
1212                       MENUSTRING("Sphere",        UV_SPHERE_MAPPING) "|"
1213                       MENUSTRING("LSCM",          UV_LSCM_MAPPING) "|"
1214                       MENUSTRING("Bounds to 1/8", UV_BOUNDS8_MAPPING) "|"
1215                       MENUSTRING("Bounds to 1/4", UV_BOUNDS4_MAPPING) "|"
1216                       MENUSTRING("Bounds to 1/2", UV_BOUNDS2_MAPPING) "|"
1217                       MENUSTRING("Bounds to 1/1", UV_BOUNDS1_MAPPING) "|"
1218                       MENUSTRING("Standard 1/8",  UV_STD8_MAPPING) "|"
1219                       MENUSTRING("Standard 1/4",  UV_STD4_MAPPING) "|"
1220                       MENUSTRING("Standard 1/2",  UV_STD2_MAPPING) "|"
1221                       MENUSTRING("Standard 1/1",  UV_STD1_MAPPING) "|"
1222                       MENUSTRING("From Window",   UV_WINDOW_MAPPING) );
1223         
1224         
1225         switch(mode) {
1226         case UV_CUBE_MAPPING:
1227                 calculate_uv_map(B_UVAUTO_CUBE); break;
1228         case UV_CYL_MAPPING:
1229                 calculate_uv_map(B_UVAUTO_CYLINDER); break;
1230         case UV_SPHERE_MAPPING:
1231                 calculate_uv_map(B_UVAUTO_SPHERE); break;
1232         case UV_BOUNDS8_MAPPING:
1233                 calculate_uv_map(B_UVAUTO_BOUNDS8); break;
1234         case UV_BOUNDS4_MAPPING:
1235                 calculate_uv_map(B_UVAUTO_BOUNDS4); break;
1236         case UV_BOUNDS2_MAPPING:
1237                 calculate_uv_map(B_UVAUTO_BOUNDS2); break;
1238         case UV_BOUNDS1_MAPPING:
1239                 calculate_uv_map(B_UVAUTO_BOUNDS1); break;
1240         case UV_STD8_MAPPING:
1241                 calculate_uv_map(B_UVAUTO_STD8); break;
1242         case UV_STD4_MAPPING:
1243                 calculate_uv_map(B_UVAUTO_STD4); break;
1244         case UV_STD2_MAPPING:
1245                 calculate_uv_map(B_UVAUTO_STD2); break;
1246         case UV_STD1_MAPPING:
1247                 calculate_uv_map(B_UVAUTO_STD1); break;
1248         case UV_WINDOW_MAPPING:
1249                 calculate_uv_map(B_UVAUTO_WINDOW); break;
1250         case UV_LSCM_MAPPING:
1251                 unwrap_lscm(); break;
1252         }
1253 }
1254
1255 void set_faceselect()   /* toggle */
1256 {
1257         Object *ob = OBACT;
1258         Mesh *me = 0;
1259         
1260         scrarea_queue_headredraw(curarea);
1261         if(ob==NULL || ob->id.lib) return;
1262         
1263         if(G.f & G_FACESELECT) G.f &= ~G_FACESELECT;
1264         else {
1265                 if (ob && ob->type == OB_MESH) G.f |= G_FACESELECT;
1266         }
1267
1268         allqueue(REDRAWVIEW3D, 0);
1269         allqueue(REDRAWBUTSEDIT, 0);
1270         allqueue(REDRAWIMAGE, 0);
1271         
1272         ob= OBACT;
1273         me= get_mesh(ob);
1274         if(me && me->tface==NULL) make_tfaces(me);
1275
1276         if(G.f & G_FACESELECT) {
1277                 setcursor_space(SPACE_VIEW3D, CURSOR_FACESEL);
1278                 if(me) {
1279                         set_lasttface();
1280                         set_seamtface(); /* set TF_SEAM flags in tface */
1281                 }
1282                 BIF_undo_push("Set UV Faceselect");
1283         }
1284         else if((G.f & (G_WEIGHTPAINT|G_VERTEXPAINT|G_TEXTUREPAINT))==0) {
1285                 if(me) {
1286                         reveal_tface();
1287                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1288                 }
1289                 setcursor_space(SPACE_VIEW3D, CURSOR_STD);
1290                 BIF_undo_push("End UV Faceselect");
1291         }
1292         countall();
1293 }
1294
1295
1296 #ifdef NAN_TPT
1297 /**
1298  * Get the view ray through the screen point.
1299  * Uses the OpenGL settings of the active view port.
1300  * The coordinates should be given in viewport coordinates.
1301  * @author      Maarten Gribnau
1302  * @param       x               the x-coordinate of the screen point.
1303  * @param       y               the y-coordinate of the screen point.
1304  * @param       org             origin of the view ray.
1305  * @param       dir             direction of the view ray.
1306  */
1307 static void get_pick_ray(short x, short y, float org[3], float dir[3])
1308 {
1309         double mvmatrix[16];
1310         double projmatrix[16];
1311         GLint viewport[4];
1312         double px, py, pz;
1313         float l;
1314
1315         /* Get the matrices needed for gluUnProject */
1316         glGetIntegerv(GL_VIEWPORT, viewport);
1317         glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
1318         glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);
1319
1320         /* Set up viewport so that gluUnProject will give correct values */
1321         viewport[0] = 0;
1322         viewport[1] = 0;
1323         /* printf("viewport = (%4d, %4d, %4d, %4d)\n", viewport[0], viewport[1], viewport[2], viewport[3]); */
1324         /* printf("cursor = (%4d, %4d)\n", x, y); */
1325
1326         gluUnProject((GLdouble) x, (GLdouble) y, 0.0, mvmatrix, projmatrix, viewport, &px, &py, &pz);
1327         org[0] = (float)px; org[1] = (float)py; org[2] = (float)pz;
1328         /* printf("world point at z=0.0 is (%f, %f, %f)\n", org[0], org[1], org[2]); */
1329         gluUnProject((GLdouble) x, (GLdouble) y, 1.0, mvmatrix, projmatrix, viewport, &px, &py, &pz); 
1330         /* printf("world point at z=1.0 is (%f, %f, %f)\n", px, py, pz); */
1331         dir[0] = ((float)px) - org[0];
1332         dir[1] = ((float)py) - org[1];
1333         dir[2] = ((float)pz) - org[2];
1334         l = (float)sqrt(dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2]);
1335         if (!l) return;
1336         l = 1. / l;
1337         dir[0] *= l; dir[1] *= l; dir[2] *= l;
1338         /* printf("ray org. is (%f, %f, %f)\n", org[0], org[1], org[2]); */
1339         /* printf("ray dir. is (%f, %f, %f)\n", dir[0], dir[1], dir[2]); */
1340 }
1341
1342
1343 static int triangle_ray_intersect(float tv0[3], float tv1[3], float tv2[3], float org[3], float dir[3], float uv[2])
1344 {
1345         float v1v0[3];
1346         float v2v0[3];
1347         float n[3], an[3];
1348         float t, d, l;
1349         float p[3];
1350         double u0, v0, u1, v1, u2, v2, uvtemp;
1351         unsigned int iu, iv;
1352
1353         /* Calculate normal of the plane (cross, normalize)
1354          * Could really use moto here...
1355          */
1356         v1v0[0] = tv1[0] - tv0[0];
1357         v1v0[1] = tv1[1] - tv0[1];
1358         v1v0[2] = tv1[2] - tv0[2];
1359         v2v0[0] = tv2[0] - tv0[0];
1360         v2v0[1] = tv2[1] - tv0[1];
1361         v2v0[2] = tv2[2] - tv0[2];
1362         n[0] = (v1v0[1] * v2v0[2]) - (v1v0[2] * v2v0[1]);
1363         n[1] = (v1v0[2] * v2v0[0]) - (v1v0[0] * v2v0[2]);
1364         n[2] = (v1v0[0] * v2v0[1]) - (v1v0[1] * v2v0[0]);
1365         l = sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
1366         if (!l) return 0;
1367         l = 1. / l;
1368         n[0] *= l; n[1] *= l; n[2] *= l;
1369
1370         /* Calculate intersection point */
1371         t = n[0]*dir[0] + n[1]*dir[1] + n[2]*dir[2];
1372         if (fabs(t) < 1.0e-6) return 0;
1373         d = -(n[0]*tv0[0] + n[1]*tv0[1] + n[2]*tv0[2]);
1374         t = -(((n[0]*org[0] + n[1]*org[1] + n[2]*org[2]) + d) / t);
1375         if (t < 0) return 0;
1376         p[0] = org[0] + dir[0]*t;
1377         p[1] = org[1] + dir[1]*t;
1378         p[2] = org[2] + dir[2]*t;
1379         /*printf("intersection at (%f, %f, %f)\n", p[0], p[1], p[2]);*/
1380
1381         /* Calculate the largest component of the normal */
1382         an[0] = fabs(n[0]); an[1] = fabs(n[1]); an[2] = fabs(n[2]);
1383         if ((an[0] > an[1]) && (an[0] > an[2])) {
1384                 iu = 1; iv = 2;
1385         }
1386         else if ((an[1] > an[0]) && (an[1] > an[2])) {
1387                 iu = 2; iv = 0;
1388         }
1389         else {
1390                 iu = 0; iv = 1;
1391         }
1392         /* printf("iu, iv = (%d, %d)\n", iu, iv); */
1393
1394         /* Calculate (u,v) */
1395         u0 = p[iu] - tv0[iu];
1396         v0 = p[iv] - tv0[iv];
1397         u1 = tv1[iu] - tv0[iu];
1398         v1 = tv1[iv] - tv0[iv];
1399         u2 = tv2[iu] - tv0[iu];
1400         v2 = tv2[iv] - tv0[iv];
1401         /* printf("u0, v0, u1, v1, u2, v2 = (%f, %f, %f, %f, %f, %f)\n", u0, v0, u1, v1, u2, v2); */
1402
1403         /* These calculations should be in double precision.
1404          * On windows we get inpredictable results in single precision
1405          */
1406         if (u1 == 0) {
1407                 uvtemp = u0/u2;
1408                 uv[1] = (float)uvtemp;
1409                 /* if ((uv[1] >= 0.) && (uv[1] <= 1.)) { */
1410                         uv[0] = (float)((v0 - uvtemp*v2) / v1);
1411                 /* } */
1412         }
1413         else {
1414                 uvtemp = (v0*u1 - u0*v1)/(v2*u1-u2*v1);
1415                 uv[1] = (float)uvtemp;
1416                 /* if ((uv[1] >= 0) && (uv[1] <= 1)) { */
1417                         uv[0] = (float)((u0 - uvtemp*u2) / u1);
1418                 /* } */
1419         }
1420         /* printf("uv[0], uv[1] = (%f, %f)\n", uv[0], uv[1]); */
1421         return ((uv[0] >= 0) && (uv[1] >= 0) && ((uv[0]+uv[1]) <= 1)) ? 2 : 1;
1422 }
1423
1424 /**
1425  * Returns the vertex (local) coordinates of a face.
1426  * No bounds checking!
1427  * @author      Maarten Gribnau
1428  * @param       mesh    the mesh with the face.
1429  * @param       face    the face.
1430  * @param       v1              vertex 1 coordinates.
1431  * @param       v2              vertex 2 coordinates.
1432  * @param       v3              vertex 3 coordinates.
1433  * @param       v4              vertex 4 coordinates.
1434  * @return      number of vertices of this face
1435  */
1436 static int face_get_vertex_coordinates(Mesh* mesh, TFace* face, float v1[3], float v2[3], float v3[3], float v4[3])
1437 {
1438         int num_vertices;
1439         MVert *mv;
1440         MFace *mf = (MFace *) (((MFace *)mesh->mface) + (face - (TFace *) mesh->tface));
1441
1442         num_vertices = mf->v4 == 0 ? 3 : 4;
1443         mv = mesh->mvert + mf->v1;
1444         v1[0] = mv->co[0]; v1[1] = mv->co[1]; v1[2] = mv->co[2];
1445         mv = mesh->mvert + mf->v2;
1446         v2[0] = mv->co[0]; v2[1] = mv->co[1]; v2[2] = mv->co[2];
1447         mv = mesh->mvert + mf->v3;
1448         v3[0] = mv->co[0]; v3[1] = mv->co[1]; v3[2] = mv->co[2];
1449         if (num_vertices == 4) {
1450                 mv = mesh->mvert + mf->v4;
1451                 v4[0] = mv->co[0]; v4[1] = mv->co[1]; v4[2] = mv->co[2];
1452         }
1453
1454         return num_vertices;
1455 }
1456
1457 /**
1458  * Finds texture coordinates from face edge interpolation values.
1459  * @author      Maarten Gribnau
1460  * @param       face    the face.
1461  * @param       v1              vertex 1 index.
1462  * @param       v2              vertex 2 index.
1463  * @param       v3              vertex 3 index.
1464  * @param       a               interpolation value of edge v2-v1.
1465  * @param       b               interpolation value of edge v3-v1.
1466  * @param       u               (u,v) coordinate.
1467  * @param       v               (u,v) coordinate.
1468  */
1469 static void face_get_uv(TFace* face, int v1, int v2, int v3, float a, float b, float* u, float* v)
1470 {
1471         float uv01[2], uv21[2];
1472
1473         /* Pin a,b inside [0,1] range */
1474 #if 0
1475         a = (float)fmod(a, 1.);
1476         b = (float)fmod(b, 1.);
1477 #else
1478         if (a < 0.f) a = 0.f;
1479         else if (a > 1.f) a = 1.f;
1480         if (b < 0.f) b = 0.f;
1481         else if (b > 1.f) b = 1.f;
1482 #endif
1483
1484         /* Convert to texture coordinates */
1485         uv01[0] = face->uv[v2][0] - face->uv[v1][0];
1486         uv01[1] = face->uv[v2][1] - face->uv[v1][1];
1487         uv21[0] = face->uv[v3][0] - face->uv[v1][0];
1488         uv21[1] = face->uv[v3][1] - face->uv[v1][1];
1489         uv01[0] *= a;
1490         uv01[1] *= a;
1491         uv21[0] *= b;
1492         uv21[1] *= b;
1493         *u = face->uv[v1][0] + (uv01[0] + uv21[0]);
1494         *v = face->uv[v1][1] + (uv01[1] + uv21[1]);
1495 }
1496
1497 /**
1498  * Get the (u,v) coordinates on a face from a point in screen coordinates.
1499  * The coordinates should be given in viewport coordinates.
1500  * @author      Maarten Gribnau
1501  * @param       object  the object with the mesh
1502  * @param       mesh    the mesh with the face to be picked.
1503  * @param       face    the face to be picked.
1504  * @param       x               the x-coordinate to pick at.
1505  * @param       y               the y-coordinate to pick at.
1506  * @param       u               the u-coordinate calculated.
1507  * @param       v               the v-coordinate calculated.
1508  * @return      intersection result:
1509  *                      0 == no intersection, (u,v) invalid
1510  *                      1 == intersection, (u,v) valid
1511  */
1512 static int face_pick_uv(Object* object, Mesh* mesh, TFace* face, short x, short y, float* u, float* v)
1513 {
1514         float org[3], dir[3];
1515         float ab[2];
1516         float v1[3], v2[3], v3[3], v4[3];
1517         int result;
1518         int num_verts;
1519
1520         /* Get a view ray to intersect with the face */
1521         get_pick_ray(x, y, org, dir);
1522
1523         /* Convert local vertex coordinates to world */
1524         num_verts = face_get_vertex_coordinates(mesh, face, v1, v2, v3, v4);
1525         /* Convert local vertex coordinates to world */
1526         Mat4MulVecfl(object->obmat, v1);
1527         Mat4MulVecfl(object->obmat, v2);
1528         Mat4MulVecfl(object->obmat, v3);
1529         if (num_verts > 3) {
1530                 Mat4MulVecfl(object->obmat, v4);
1531         }
1532
1533         /* Get (u,v) values (local face coordinates) of intersection point
1534          * If face is a quad, there are two triangles to check.
1535          */
1536         result = triangle_ray_intersect(v2, v1, v3, org, dir, ab);
1537         if ( (num_verts == 3) || ((num_verts == 4) && (result > 1)) ) {
1538                 /* Face is a triangle or a quad with a hit on the first triangle */
1539                 face_get_uv(face, 1, 0, 2, ab[0], ab[1], u, v);
1540                 /* printf("triangle 1, texture (u,v)=(%f, %f)\n", *u, *v); */
1541         }
1542         else {
1543                 /* Face is a quad and no intersection with first triangle */
1544                 result = triangle_ray_intersect(v4, v3, v1, org, dir, ab);
1545                 face_get_uv(face, 3, 2, 0, ab[0], ab[1], u, v);
1546                 /* printf("triangle 2, texture (u,v)=(%f, %f)\n", *u, *v); */
1547         }
1548         return result > 0;
1549 }
1550
1551 /**
1552  * First attempt at drawing in the texture of a face.
1553  * @author      Maarten Gribnau
1554  */
1555 void face_draw()
1556 {
1557         Object *ob;
1558         Mesh *me;
1559         TFace *face, *face_old = 0;
1560         short xy[2], xy_old[2];
1561         //int a, index;
1562         Image *img=NULL, *img_old = NULL;
1563         IMG_BrushPtr brush;
1564         IMG_CanvasPtr canvas = 0;
1565         unsigned int rowBytes, face_index;
1566         char *warn_packed_file = 0;
1567         float uv[2], uv_old[2];
1568         extern VPaint Gvp;
1569         short mousebut;
1570
1571         ob = OBACT;
1572         if (!ob) {
1573                 error("No active object"); return;
1574         }
1575         if (!(ob->lay & G.vd->lay)) {
1576                 error("The active object is not in this layer"); return;
1577         }
1578         me = get_mesh(ob);
1579         if (!me) {
1580                 error("The active object does not have a mesh obData"); return;
1581         }
1582
1583         brush = IMG_BrushCreate(Gvp.size, Gvp.size, Gvp.r, Gvp.g, Gvp.b, Gvp.a);
1584         if (!brush) {
1585                 error("Can't create brush"); return;
1586         }
1587
1588         if (U.flag & USER_LMOUSESELECT) mousebut = R_MOUSE;
1589         else mousebut = L_MOUSE;
1590
1591         persp(PERSP_VIEW);
1592
1593         getmouseco_areawin(xy_old);
1594         while (get_mbut() & mousebut) {
1595                 getmouseco_areawin(xy);
1596                 /* Check if cursor has moved */
1597                 if ((xy[0] != xy_old[0]) || (xy[1] != xy_old[1])) {
1598
1599                         /* Get face to draw on */
1600                         if (!face_pick(me, xy[0], xy[1], &face_index)) face = NULL;
1601                         else face = (((TFace*)me->tface)+face_index);
1602
1603                         /* Check if this is another face. */
1604                         if (face != face_old) {
1605                                 /* The active face changed, check the texture */
1606                                 if (face) {
1607                                         img = face->tpage;
1608                                 }
1609                                 else {
1610                                         img = 0;
1611                                 }
1612
1613                                 if (img != img_old) {
1614                                         /* Faces have different textures. Finish drawing in the old face. */
1615                                         if (face_old && canvas) {
1616                                                 face_pick_uv(ob, me, face_old, xy[0], xy[1], &uv[0], &uv[1]);
1617                                                 IMG_CanvasDrawLineUV(canvas, brush, uv_old[0], uv_old[1], uv[0], uv[1]);
1618                                                 img_old->ibuf->userflags |= IB_BITMAPDIRTY;
1619                                                 /* Delete old canvas */
1620                                                 IMG_CanvasDispose(canvas);
1621                                                 canvas = 0;
1622                                         }
1623
1624                                         /* Create new canvas and start drawing in the new face. */
1625                                         if (img) {
1626                                                 if (img->ibuf && img->packedfile == 0) {
1627                                                         /* MAART: skipx is not set most of the times. Make a guess. */
1628                                                         rowBytes = img->ibuf->skipx ? img->ibuf->skipx : img->ibuf->x * 4;
1629                                                         canvas = IMG_CanvasCreateFromPtr(img->ibuf->rect, img->ibuf->x, img->ibuf->y, rowBytes);
1630                                                         if (canvas) {
1631                                                                 face_pick_uv(ob, me, face, xy_old[0], xy_old[1], &uv_old[0], &uv_old[1]);
1632                                                                 face_pick_uv(ob, me, face, xy[0], xy[1], &uv[0], &uv[1]);
1633                                                                 IMG_CanvasDrawLineUV(canvas, brush, uv_old[0], uv_old[1], uv[0], uv[1]);
1634                                                                 img->ibuf->userflags |= IB_BITMAPDIRTY;
1635                                                         }
1636                                                 }
1637                                                 else {
1638                                                         /* TODO: should issue warning that no texture is assigned */
1639                                                         if (img->packedfile) {
1640                                                                 warn_packed_file = img->id.name + 2;
1641                                                                 img = 0;
1642                                                         }
1643                                                 }
1644                                         }
1645                                 }
1646                                 else {
1647                                         /* Face changed and faces have the same texture. */
1648                                         if (canvas) {
1649                                                 /* Finish drawing in the old face. */
1650                                                 if (face_old) {
1651                                                         face_pick_uv(ob, me, face_old, xy[0], xy[1], &uv[0], &uv[1]);
1652                                                         IMG_CanvasDrawLineUV(canvas, brush, uv_old[0], uv_old[1], uv[0], uv[1]);
1653                                                         img_old->ibuf->userflags |= IB_BITMAPDIRTY;
1654                                                 }
1655
1656                                                 /* Start drawing in the new face. */
1657                                                 if (face) {
1658                                                         face_pick_uv(ob, me, face, xy_old[0], xy_old[1], &uv_old[0], &uv_old[1]);
1659                                                         face_pick_uv(ob, me, face, xy[0], xy[1], &uv[0], &uv[1]);
1660                                                         IMG_CanvasDrawLineUV(canvas, brush, uv_old[0], uv_old[1], uv[0], uv[1]);
1661                                                         img->ibuf->userflags |= IB_BITMAPDIRTY;
1662                                                 }
1663                                         }
1664                                 }
1665                         }
1666                         else {
1667                                 /* Same face, continue drawing */
1668                                 if (face && canvas) {
1669                                         /* Get the new (u,v) coordinates */
1670                                         face_pick_uv(ob, me, face, xy[0], xy[1], &uv[0], &uv[1]);
1671                                         IMG_CanvasDrawLineUV(canvas, brush, uv_old[0], uv_old[1], uv[0], uv[1]);
1672                                         img->ibuf->userflags |= IB_BITMAPDIRTY;
1673                                 }
1674                         }
1675
1676                         if (face && img) {
1677                                 /* Make OpenGL aware of a change in the texture */
1678                                 free_realtime_image(img);
1679                                 /* Redraw the view */
1680                                 scrarea_do_windraw(curarea);
1681                                 screen_swapbuffers();
1682                         }
1683
1684                         xy_old[0] = xy[0];
1685                         xy_old[1] = xy[1];
1686                         uv_old[0] = uv[0];
1687                         uv_old[1] = uv[1];
1688                         face_old = face;
1689                         img_old = img;
1690                 }
1691         }
1692
1693         IMG_BrushDispose(brush);
1694         if (canvas) {
1695                 IMG_CanvasDispose(canvas);
1696                 canvas = 0;
1697         }
1698
1699         if (warn_packed_file) {
1700                 error("Painting in packed images is not supported: %s", warn_packed_file);
1701         }
1702
1703         persp(PERSP_WIN);
1704
1705         BIF_undo_push("UV face draw");
1706         allqueue(REDRAWVIEW3D, 0);
1707         allqueue(REDRAWIMAGE, 0);
1708         allqueue(REDRAWHEADERS, 0);
1709 }
1710
1711  /* Selects all faces which have the same uv-texture as the active face 
1712  * @author      Roel Spruit
1713  * @return      Void
1714  * Errors:      - Active object not in this layer
1715  *              - No active face or active face has no UV-texture                       
1716  */
1717 void get_same_uv(void)
1718 {
1719         Object *ob;
1720         Mesh *me;
1721         TFace *tface;   
1722         short a, foundtex=0;
1723         Image *ima;
1724         char uvname[160];
1725         
1726         ob = OBACT;
1727         if (!(ob->lay & G.vd->lay)) {
1728                 error("The active object is not in this layer");
1729                 return;
1730         }
1731         me = get_mesh(ob);
1732         
1733                 
1734         /* Search for the active face with a UV-Texture */
1735         tface = me->tface;
1736         a = me->totface;
1737         while (a--) {           
1738                 if(tface->flag & TF_ACTIVE){                    
1739                         ima=tface->tpage;
1740                         if(ima && ima->name){
1741                                 strcpy(uvname,ima->name);                       
1742                                 a=0;
1743                                 foundtex=1;
1744                         }
1745                 }
1746                 tface++;
1747         }               
1748         
1749         if(!foundtex) {
1750                 error("No active face, or active face has no UV texture");
1751                 return;
1752         }
1753
1754         /* select everything with the same texture */
1755         tface = me->tface;
1756         a = me->totface;
1757         while (a--) {           
1758                 ima=tface->tpage;
1759                 if(ima && ima->name){
1760                         if(!strcmp(ima->name, uvname)){
1761                                 tface->flag |= TF_SELECT;
1762                         }
1763                         else tface->flag &= ~TF_SELECT;
1764                 }
1765                 else tface->flag &= ~TF_SELECT;
1766                 tface++;
1767         }
1768         
1769         /* image window redraw */
1770         BIF_undo_push("Get same UV");
1771
1772         object_tface_flags_changed(OBACT, 0);
1773 }
1774 #endif /* NAN_TPT */