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