4 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
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
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.
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.
23 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24 * All rights reserved.
26 * The Original Code is: all of this file.
28 * Contributor(s): none yet.
30 * ***** END GPL/BL DUAL LICENSE BLOCK *****
33 /* main mesh editing routines. please note that 'vlak' is used here to denote a 'face'. */
34 /* at that time for me a face was something at the frontside of a human head! (ton) */
45 #include "BLI_winstuff.h"
47 #include "MEM_guardedalloc.h"
51 #include "MTC_matrixops.h"
53 #include "DNA_mesh_types.h"
54 #include "DNA_object_types.h"
55 #include "DNA_screen_types.h"
56 #include "DNA_key_types.h"
57 #include "DNA_scene_types.h"
58 #include "DNA_view3d_types.h"
59 #include "DNA_material_types.h"
60 #include "DNA_texture_types.h"
61 #include "DNA_userdef_types.h"
63 #include "BLI_blenlib.h"
64 #include "BLI_arithb.h"
65 #include "BLI_editVert.h"
69 #include "BKE_utildefines.h"
71 #include "BKE_object.h"
72 #include "BKE_texture.h"
73 #include "BKE_displist.h"
74 #include "BKE_global.h"
75 #include "BKE_library.h"
77 #include "BKE_material.h"
81 #include "BIF_graphics.h"
82 #include "BIF_editkey.h"
83 #include "BIF_space.h"
84 #include "BIF_toolbox.h"
85 #include "BIF_screen.h"
86 #include "BIF_interface.h"
87 #include "BIF_editmesh.h"
88 #include "BIF_mywindow.h"
89 #include "BIF_resources.h"
90 #include "BIF_glutil.h"
91 #include "BIF_cursors.h"
95 #include "BSE_trans_types.h"
97 #include "BDR_drawobject.h"
98 #include "BDR_editobject.h"
99 #include "BDR_editface.h"
100 #include "BDR_vpaint.h"
102 #include "mydevice.h"
104 #include "nla.h" /* For __NLA : Important - Do not remove! */
107 #include "GHOST_C-api.h"
112 #define snprintf _snprintf
118 static void free_editverts(ListBase *edve);
119 static float convex(float *v1, float *v2, float *v3, float *v4);
122 void make_editMesh_real(Mesh *me);
123 void load_editMesh_real(Mesh *me, int);
127 /* extern ListBase fillvertbase, filledgebase; */ /* scanfill.c, in
128 the lib... already in BLI_blenlib.h */
131 #define free(a) freeN(a)
132 #define malloc(a) mallocN(a, "malloc")
133 #define calloc(a, b) callocN((a)*(b), "calloc")
134 #define freelist(a) freelistN(a)
137 extern short editbutflag;
139 static float icovert[12][3] = {
141 {144.72, -105.144,-89.443},
142 {-55.277, -170.128,-89.443},
143 {-178.885,0,-89.443},
144 {-55.277,170.128,-89.443},
145 {144.72,105.144,-89.443},
146 {55.277,-170.128,89.443},
147 {-144.72,-105.144,89.443},
148 {-144.72,105.144,89.443},
149 {55.277,170.128,89.443},
153 static short icovlak[20][3] = {
177 #define UVCOPY(t, s) memcpy(t, s, 2 * sizeof(float));
179 #define TEST_EDITMESH if(G.obedit==0) return; \
180 if( (G.vd->lay & G.obedit->lay)==0 ) return;
182 #define FACE_MARKCLEAR(f) (f->f1 = 1)
184 /* ***************** HASH ********************* */
186 /* HASH struct quickly finding of edges */
188 struct EditEdge *eed;
189 struct HashEdge *next;
192 struct HashEdge *hashedgetab=NULL;
194 /********* qsort routines *********/
203 static int vergxco(const void *v1, const void *v2)
205 const struct xvertsort *x1=v1, *x2=v2;
207 if( x1->x > x2->x ) return 1;
208 else if( x1->x < x2->x) return -1;
214 struct EditVlak *evl;
218 static int vergvlak(const void *v1, const void *v2)
220 const struct vlaksort *x1=v1, *x2=v2;
222 if( x1->x > x2->x ) return 1;
223 else if( x1->x < x2->x) return -1;
228 /* ************ ADD / REMOVE / FIND ****************** */
230 #define EDHASH(a, b) ( (a)*256 + (b) )
231 #define EDHASHSIZE 65536
234 static void check_hashedge(void)
236 int i, i2, doubedge=0;
237 struct HashEdge *he, *he2;
239 for (i=0; i<64; i++) {
242 while (he && he->eed) {
243 for (i2=i+1; i2<64; i2++) {
247 if (he->eed == he2->eed) doubedge++;
257 if (doubedge) printf("%d double edges!\n", doubedge);
261 EditVert *addvertlist(float *vec)
264 static unsigned char hashnr= 0;
266 eve= calloc(sizeof(EditVert),1);
267 BLI_addtail(&G.edve, eve);
269 if(vec) VECCOPY(eve->co, vec);
273 /* new verts get keyindex of -1 since they did not
274 * have a pre-editmode vertex order
280 EditEdge *findedgelist(EditVert *v1, EditVert *v2)
286 hashedgetab= MEM_callocN(EDHASHSIZE*sizeof(struct HashEdge), "hashedgetab");
290 if( (long)v1 > (long)v2) {
296 he= hashedgetab + EDHASH(v1->hash, v2->hash);
300 if(he->eed && he->eed->v1==v1 && he->eed->v2==v2) return he->eed;
307 static void insert_hashedge(EditEdge *eed)
309 /* assuming that eed is not in the list yet, and that a find has been done before */
311 struct HashEdge *first, *he;
313 first= hashedgetab + EDHASH(eed->v1->hash, eed->v2->hash);
315 if( first->eed==0 ) {
319 he= (struct HashEdge *)malloc(sizeof(struct HashEdge));
321 he->next= first->next;
326 static void remove_hashedge(EditEdge *eed)
328 /* assuming eed is in the list */
330 struct HashEdge *first, *he, *prev=NULL;
333 he=first= hashedgetab + EDHASH(eed->v1->hash, eed->v2->hash);
337 /* remove from list */
342 first->next= he->next;
348 prev->next= he->next;
358 void free_hashedgetab(void)
360 struct HashEdge *he, *first, *hen;
366 for(a=0; a<EDHASHSIZE; a++, first++) {
374 MEM_freeN(hashedgetab);
379 EditEdge *addedgelist(EditVert *v1, EditVert *v2)
394 if(v1==0 || v2==0) return 0;
396 /* find in hashlist */
397 eed= findedgelist(v1, v2);
401 eed= (EditEdge *)calloc(sizeof(EditEdge), 1);
404 BLI_addtail(&G.eded, eed);
406 insert_hashedge(eed);
412 void remedge(EditEdge *eed)
415 BLI_remlink(&G.eded, eed);
417 remove_hashedge(eed);
420 static void freevlak(EditVlak *evl)
425 static void freevlaklist(ListBase *lb)
427 EditVlak *evl, *next;
435 lb->first= lb->last= 0;
438 EditVlak *addvlaklist(EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4, EditVlak *example)
441 EditEdge *e1, *e2=0, *e3=0, *e4=0;
444 /* add face to list and do the edges */
445 e1= addedgelist(v1, v2);
446 if(v3) e2= addedgelist(v2, v3);
447 if(v4) e3= addedgelist(v3, v4); else e3= addedgelist(v3, v1);
448 if(v4) e4= addedgelist(v4, v1);
450 if(v1==v2 || v2==v3 || v1==v3) return 0;
453 evl= (EditVlak *)calloc(sizeof(EditVlak), 1);
465 evl->mat_nr= example->mat_nr;
466 evl->tf= example->tf;
467 evl->flag= example->flag;
470 if (G.obedit && G.obedit->actcol)
471 evl->mat_nr= G.obedit->actcol-1;
472 default_uv(evl->tf.uv, 1.0);
474 /* Initialize colors */
475 evl->tf.col[0]= evl->tf.col[1]= evl->tf.col[2]= evl->tf.col[3]= vpaint_get_current_col();
478 BLI_addtail(&G.edvl, evl);
480 if(evl->v4) CalcNormFloat4(v1->co, v2->co, v3->co, v4->co, evl->n);
481 else CalcNormFloat(v1->co, v2->co, v3->co, evl->n);
486 static int comparevlak(EditVlak *vl1, EditVlak *vl2)
488 EditVert *v1, *v2, *v3, *v4;
490 if(vl1->v4 && vl2->v4) {
496 if(vl1->v1==v1 || vl1->v2==v1 || vl1->v3==v1 || vl1->v4==v1) {
497 if(vl1->v1==v2 || vl1->v2==v2 || vl1->v3==v2 || vl1->v4==v2) {
498 if(vl1->v1==v3 || vl1->v2==v3 || vl1->v3==v3 || vl1->v4==v3) {
499 if(vl1->v1==v4 || vl1->v2==v4 || vl1->v3==v4 || vl1->v4==v4) {
506 else if(vl1->v4==0 && vl2->v4==0) {
511 if(vl1->v1==v1 || vl1->v2==v1 || vl1->v3==v1) {
512 if(vl1->v1==v2 || vl1->v2==v2 || vl1->v3==v2) {
513 if(vl1->v1==v3 || vl1->v2==v3 || vl1->v3==v3) {
525 static int dubbelvlak(EditVlak *evltest)
533 if(comparevlak(evltest, evl)) return 1;
541 static int exist_vlak(EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4)
543 EditVlak *evl, evltest;
552 if(comparevlak(&evltest, evl)) return 1;
559 static int vlakselectedOR(EditVlak *evl, int flag)
562 if(evl->v1->f & flag) return 1;
563 if(evl->v2->f & flag) return 1;
564 if(evl->v3->f & flag) return 1;
565 if(evl->v4 && (evl->v4->f & 1)) return 1;
569 int vlakselectedAND(EditVlak *evl, int flag)
571 if(evl->v1->f & flag) {
572 if(evl->v2->f & flag) {
573 if(evl->v3->f & flag) {
575 if(evl->v4->f & flag) return 1;
584 void recalc_editnormals(void)
590 if(evl->v4) CalcNormFloat4(evl->v1->co, evl->v2->co, evl->v3->co, evl->v4->co, evl->n);
591 else CalcNormFloat(evl->v1->co, evl->v2->co, evl->v3->co, evl->n);
596 static void flipvlak(EditVlak *evl)
599 SWAP(EditVert *, evl->v2, evl->v4);
600 SWAP(EditEdge *, evl->e1, evl->e4);
601 SWAP(EditEdge *, evl->e2, evl->e3);
602 SWAP(unsigned int, evl->tf.col[1], evl->tf.col[3]);
603 SWAP(float, evl->tf.uv[1][0], evl->tf.uv[3][0]);
604 SWAP(float, evl->tf.uv[1][1], evl->tf.uv[3][1]);
607 SWAP(EditVert *, evl->v2, evl->v3);
608 SWAP(EditEdge *, evl->e1, evl->e3);
609 SWAP(unsigned int, evl->tf.col[1], evl->tf.col[2]);
610 evl->e2->dir= 1-evl->e2->dir;
611 SWAP(float, evl->tf.uv[1][0], evl->tf.uv[2][0]);
612 SWAP(float, evl->tf.uv[1][1], evl->tf.uv[2][1]);
614 if(evl->v4) CalcNormFloat4(evl->v1->co, evl->v2->co, evl->v3->co, evl->v4->co, evl->n);
615 else CalcNormFloat(evl->v1->co, evl->v2->co, evl->v3->co, evl->n);
619 void flip_editnormals(void)
625 if( vlakselectedAND(evl, 1) ) {
632 /* ************************ IN & OUT ***************************** */
634 static void edge_normal_compare(EditEdge *eed, EditVlak *evl1)
637 float cent1[3], cent2[3];
640 evl2= (EditVlak *)eed->vn;
641 if(evl1==evl2) return;
643 inp= evl1->n[0]*evl2->n[0] + evl1->n[1]*evl2->n[1] + evl1->n[2]*evl2->n[2];
644 if(inp<0.999 && inp >-0.999) eed->f= 1;
646 if(evl1->v4) CalcCent4f(cent1, evl1->v1->co, evl1->v2->co, evl1->v3->co, evl1->v4->co);
647 else CalcCent3f(cent1, evl1->v1->co, evl1->v2->co, evl1->v3->co);
648 if(evl2->v4) CalcCent4f(cent2, evl2->v1->co, evl2->v2->co, evl2->v3->co, evl2->v4->co);
649 else CalcCent3f(cent2, evl2->v1->co, evl2->v2->co, evl2->v3->co);
651 VecSubf(cent1, cent2, cent1);
653 inp= cent1[0]*evl1->n[0] + cent1[1]*evl1->n[1] + cent1[2]*evl1->n[2];
655 if(inp < -0.001 ) eed->f1= 1;
658 static void edge_drawflags(void)
661 EditEdge *eed, *e1, *e2, *e3, *e4;
664 /* - count number of times edges are used in faces: 0 en 1 time means draw edge
665 * - edges more than 1 time used: in *vn is pointer to first face
666 * - check all faces, when normal differs to much: draw (flag becomes 1)
669 /* later on: added flags for 'cylinder' and 'sphere' intersection tests in old
673 recalc_editnormals();
678 eve->f1= 1; /* during test it's set at zero */
694 if(e1->f<3) e1->f+= 1;
695 if(e2->f<3) e2->f+= 1;
696 if(e3->f<3) e3->f+= 1;
697 if(e4 && e4->f<3) e4->f+= 1;
699 if(e1->vn==0) e1->vn= (EditVert *)evl;
700 if(e2->vn==0) e2->vn= (EditVert *)evl;
701 if(e3->vn==0) e3->vn= (EditVert *)evl;
702 if(e4 && e4->vn==0) e4->vn= (EditVert *)evl;
707 if(G.f & G_ALLEDGES) {
710 if(evl->e1->f>=2) evl->e1->f= 1;
711 if(evl->e2->f>=2) evl->e2->f= 1;
712 if(evl->e3->f>=2) evl->e3->f= 1;
713 if(evl->e4 && evl->e4->f>=2) evl->e4->f= 1;
720 /* handle single-edges for 'test cylinder flag' (old engine) */
724 if(eed->f==1) eed->f1= 1;
728 /* all faces, all edges with flag==2: compare normal */
731 if(evl->e1->f==2) edge_normal_compare(evl->e1, evl);
732 if(evl->e2->f==2) edge_normal_compare(evl->e2, evl);
733 if(evl->e3->f==2) edge_normal_compare(evl->e3, evl);
734 if(evl->e4 && evl->e4->f==2) edge_normal_compare(evl->e4, evl);
739 /* sphere collision flag */
744 eed->v1->f1= eed->v2->f1= 0;
752 static int contrpuntnorm(float *n, float *puno) /* dutch: check vertex normal */
756 inp= n[0]*puno[0]+n[1]*puno[1]+n[2]*puno[2];
758 /* angles 90 degrees: dont flip */
759 if(inp> -0.000001) return 0;
764 void vertexnormals(int testflip)
769 float n1[3], n2[3], n3[3], n4[3], co[4], fac1, fac2, fac3, fac4, *temp;
770 float *f1, *f2, *f3, *f4, xn, yn, zn;
773 if(G.obedit && G.obedit->type==OB_MESH) {
775 if((me->flag & ME_TWOSIDED)==0) testflip= 0;
778 if(G.totvert==0) return;
781 /* fake vertex normals for 'halo puno'! */
784 VECCOPY(eve->no, eve->co);
785 Normalise( (float *)eve->no);
794 eve->no[0]= eve->no[1]= eve->no[2]= 0.0;
798 /* calculate cosine angles and add to vertex normal */
801 VecSubf(n1, evl->v2->co, evl->v1->co);
802 VecSubf(n2, evl->v3->co, evl->v2->co);
807 VecSubf(n3, evl->v1->co, evl->v3->co);
810 co[0]= saacos(-n3[0]*n1[0]-n3[1]*n1[1]-n3[2]*n1[2]);
811 co[1]= saacos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]);
812 co[2]= saacos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]);
816 VecSubf(n3, evl->v4->co, evl->v3->co);
817 VecSubf(n4, evl->v1->co, evl->v4->co);
821 co[0]= saacos(-n4[0]*n1[0]-n4[1]*n1[1]-n4[2]*n1[2]);
822 co[1]= saacos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]);
823 co[2]= saacos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]);
824 co[3]= saacos(-n3[0]*n4[0]-n3[1]*n4[1]-n3[2]*n4[2]);
828 if(testflip && contrpuntnorm(evl->n, temp) ) co[0]= -co[0];
829 temp[0]+= co[0]*evl->n[0];
830 temp[1]+= co[0]*evl->n[1];
831 temp[2]+= co[0]*evl->n[2];
834 if(testflip && contrpuntnorm(evl->n, temp) ) co[1]= -co[1];
835 temp[0]+= co[1]*evl->n[0];
836 temp[1]+= co[1]*evl->n[1];
837 temp[2]+= co[1]*evl->n[2];
840 if(testflip && contrpuntnorm(evl->n, temp) ) co[2]= -co[2];
841 temp[0]+= co[2]*evl->n[0];
842 temp[1]+= co[2]*evl->n[1];
843 temp[2]+= co[2]*evl->n[2];
847 if(testflip && contrpuntnorm(evl->n, temp) ) co[3]= -co[3];
848 temp[0]+= co[3]*evl->n[0];
849 temp[1]+= co[3]*evl->n[1];
850 temp[2]+= co[3]*evl->n[2];
856 /* normalise vertex normals */
859 len= Normalise(eve->no);
861 VECCOPY(eve->no, eve->co);
867 /* vertex normal flip-flags for shade (render) */
877 fac1= evl->n[0]*f1[0] + evl->n[1]*f1[1] + evl->n[2]*f1[2];
881 fac2= evl->n[0]*f2[0] + evl->n[1]*f2[1] + evl->n[2]*f2[2];
885 fac3= evl->n[0]*f3[0] + evl->n[1]*f3[1] + evl->n[2]*f3[2];
891 fac4= evl->n[0]*f4[0] + evl->n[1]*f4[1] + evl->n[2]*f4[2];
897 /* projection for cubemap! */
902 if(zn>xn && zn>yn) evl->f += ME_PROJXY;
903 else if(yn>xn && yn>zn) evl->f += ME_PROJXZ;
904 else evl->f += ME_PROJYZ;
910 void free_editMesh(void)
913 // if(G.edve.first) BLI_freelist(&G.edve);
914 if(G.edve.first) free_editverts(&G.edve);
915 if(G.eded.first) BLI_freelist(&G.eded);
916 if(G.edvl.first) freevlaklist(&G.edvl);
918 G.totvert= G.totface= 0;
921 static void free_editverts(ListBase *edve) {
933 for (eve= edve->first; eve; eve=eve->next){
943 static void free_editvert (EditVert *eve)
952 void make_editMesh(void)
956 me= get_mesh(G.obedit);
957 if (me != G.undo_last_data) {
958 G.undo_edit_level= -1;
959 G.undo_edit_highest= -1;
960 if (G.undo_clear) G.undo_clear();
961 G.undo_last_data= me;
962 G.undo_clear= undo_clear_mesh;
964 make_editMesh_real(me);
967 void make_editMesh_real(Mesh *me)
973 EditVert *eve, **evlist, *eve1, *eve2, *eve3, *eve4;
978 if(G.obedit==0) return;
980 /* because of reload */
983 G.totvert= tot= me->totvert;
994 actkey= me->key->block.first;
996 if(actkey->flag & SELECT) break;
997 actkey= actkey->next;
1002 key_to_mesh(actkey, me);
1003 tot= actkey->totelem;
1006 /* make editverts */
1009 evlist= (EditVert **)MEM_mallocN(tot*sizeof(void *),"evlist");
1010 for(a=0; a<tot; a++, mvert++) {
1011 eve= addvertlist(mvert->co);
1014 // face select sets selection in next loop
1015 if( (G.f & G_FACESELECT)==0 )
1016 eve->f |= (mvert->flag & 1);
1018 if (mvert->flag & ME_HIDE) eve->h= 1;
1019 eve->no[0]= mvert->no[0]/32767.0;
1020 eve->no[1]= mvert->no[1]/32767.0;
1021 eve->no[2]= mvert->no[2]/32767.0;
1023 /* lets overwrite the keyindex of the editvert
1024 * with the order it used to be in before
1033 eve->totweight = mvert->totweight;
1035 eve->dw = BLI_callocN (sizeof(MDeformWeight) * mvert->totweight, "deformWeight");
1036 memcpy (eve->dw, mvert->dw, sizeof(MDeformWeight) * mvert->totweight);
1042 eve->totweight = me->dvert[a].totweight;
1043 if (me->dvert[a].dw){
1044 eve->dw = MEM_callocN (sizeof(MDeformWeight) * me->dvert[a].totweight, "deformWeight");
1045 memcpy (eve->dw, me->dvert[a].dw, sizeof(MDeformWeight) * me->dvert[a].totweight);
1052 if(actkey && actkey->totelem!=me->totvert);
1056 /* make edges and faces */
1059 mcol= (unsigned int *)me->mcol;
1061 for(a=0; a<me->totface; a++, mface++) {
1062 eve1= evlist[mface->v1];
1063 eve2= evlist[mface->v2];
1064 if(mface->v3) eve3= evlist[mface->v3]; else eve3= 0;
1065 if(mface->v4) eve4= evlist[mface->v4]; else eve4= 0;
1067 evl= addvlaklist(eve1, eve2, eve3, eve4, NULL);
1070 if(mcol) memcpy(evl->tf.col, mcol, 4*sizeof(int));
1075 if( tface->flag & TF_SELECT) {
1076 if(G.f & G_FACESELECT) {
1079 if(eve3) eve3->f |= 1;
1080 if(eve4) eve4->f |= 1;
1085 evl->mat_nr= mface->mat_nr;
1086 evl->flag= mface->flag;
1089 if(me->tface) tface++;
1094 /* intrr: needed because of hidden vertices imported from Mesh */
1098 if(eed->v1->h || eed->v2->h) eed->h= 1;
1107 if (mesh_uses_displist(me))
1108 makeDispList(G.obedit);
1113 /** Rotates MFace and UVFace vertices in case the last
1114 * vertex index is = 0.
1115 * This function is a hack and may only be called in the
1116 * conversion from EditMesh to Mesh data.
1117 * This function is similar to test_index_mface in
1118 * blenkernel/intern/mesh.c.
1119 * To not clutter the blenkernel code with more bad level
1120 * calls/structures, this function resides here.
1124 static void fix_faceindices(MFace *mface, EditVlak *evl, int nr)
1128 unsigned int tmpcol;
1130 /* first test if the face is legal */
1132 if(mface->v3 && mface->v3==mface->v4) {
1136 if(mface->v2 && mface->v2==mface->v3) {
1137 mface->v3= mface->v4;
1141 if(mface->v1==mface->v2) {
1142 mface->v2= mface->v3;
1143 mface->v3= mface->v4;
1148 /* prevent a zero index value at the wrong location */
1150 if(mface->v2==0) SWAP(int, mface->v1, mface->v2);
1154 SWAP(int, mface->v1, mface->v2);
1155 SWAP(int, mface->v2, mface->v3);
1156 /* rotate face UV coordinates, too */
1157 UVCOPY(tmpuv, evl->tf.uv[0]);
1158 UVCOPY(evl->tf.uv[0], evl->tf.uv[1]);
1159 UVCOPY(evl->tf.uv[1], evl->tf.uv[2]);
1160 UVCOPY(evl->tf.uv[2], tmpuv);
1161 /* same with vertex colours */
1162 tmpcol = evl->tf.col[0];
1163 evl->tf.col[0] = evl->tf.col[1];
1164 evl->tf.col[1] = evl->tf.col[2];
1165 evl->tf.col[2] = tmpcol;
1170 if(a & ME_V1V2) mface->edcode |= ME_V3V1;
1171 if(a & ME_V2V3) mface->edcode |= ME_V1V2;
1172 if(a & ME_V3V1) mface->edcode |= ME_V2V3;
1176 if(a & ME_FLIPV1) mface->puno |= ME_FLIPV2;
1177 if(a & ME_FLIPV2) mface->puno |= ME_FLIPV3;
1178 if(a & ME_FLIPV3) mface->puno |= ME_FLIPV1;
1182 if(mface->v3==0 || mface->v4==0) {
1183 SWAP(int, mface->v1, mface->v3);
1184 SWAP(int, mface->v2, mface->v4);
1185 /* swap UV coordinates */
1186 UVCOPY(tmpuv, evl->tf.uv[0]);
1187 UVCOPY(evl->tf.uv[0], evl->tf.uv[2]);
1188 UVCOPY(evl->tf.uv[2], tmpuv);
1189 UVCOPY(tmpuv, evl->tf.uv[1]);
1190 UVCOPY(evl->tf.uv[1], evl->tf.uv[3]);
1191 UVCOPY(evl->tf.uv[3], tmpuv);
1192 /* swap vertex colours */
1193 tmpcol = evl->tf.col[0];
1194 evl->tf.col[0] = evl->tf.col[2];
1195 evl->tf.col[2] = tmpcol;
1196 tmpcol = evl->tf.col[1];
1197 evl->tf.col[1] = evl->tf.col[3];
1198 evl->tf.col[3] = tmpcol;
1202 if(a & ME_V1V2) mface->edcode |= ME_V3V4;
1203 if(a & ME_V2V3) mface->edcode |= ME_V2V3;
1204 if(a & ME_V3V4) mface->edcode |= ME_V1V2;
1205 if(a & ME_V4V1) mface->edcode |= ME_V4V1;
1209 if(a & ME_FLIPV1) mface->puno |= ME_FLIPV3;
1210 if(a & ME_FLIPV2) mface->puno |= ME_FLIPV4;
1211 if(a & ME_FLIPV3) mface->puno |= ME_FLIPV1;
1212 if(a & ME_FLIPV4) mface->puno |= ME_FLIPV2;
1220 /* load from EditMode to Mesh */
1222 void load_editMesh()
1228 me= get_mesh(G.obedit);
1230 load_editMesh_real(me, 0);
1234 void load_editMesh_real(Mesh *me, int undo)
1237 MVert *mvert, *oldverts;
1239 KeyBlock *actkey=0, *currkey;
1243 float *fp, *newkey, *oldkey, nor[3];
1250 ototvert= me->totvert;
1252 /* lets save the old verts just in case we are actually working on
1253 * a key ... we now do processing of the keys at the end*/
1254 oldverts = me->mvert;
1256 /* this one also tests of edges are not in faces: */
1257 /* eed->f==0: not in face, f==1: draw it */
1258 /* eed->f1 : flag for dynaface (cylindertest, old engine) */
1259 /* eve->f1 : flag for dynaface (sphere test, old engine) */
1262 /* WATCH IT: in evl->f is punoflag (for vertex normal) */
1263 vertexnormals( (me->flag & ME_NOPUNOFLIP)==0 );
1267 if(eed->f==0) G.totface++;
1271 /* new Face block */
1272 if(G.totface==0) mface= 0;
1273 else mface= MEM_callocN(G.totface*sizeof(MFace), "loadeditMesh1");
1274 /* nieuw Vertex block */
1275 if(G.totvert==0) mvert= 0;
1276 else mvert= MEM_callocN(G.totvert*sizeof(MVert), "loadeditMesh2");
1279 if (G.totvert==0) dvert=0;
1280 else dvert = MEM_callocN(G.totvert*sizeof(MDeformVert), "loadeditMesh3");
1282 if (me->dvert) free_dverts(me->dvert, me->totvert);
1288 if(me->mface) MEM_freeN(me->mface);
1290 me->totvert= G.totvert;
1291 me->totface= G.totface;
1293 /* the vertices, abuse ->vn as counter */
1298 VECCOPY(mvert->co, eve->co);
1299 mvert->mat_nr= 255; /* what was this for, halos? */
1302 VECCOPY(nor, eve->no);
1303 VecMulf(nor, 32767.0);
1304 VECCOPY(mvert->no, nor);
1308 dvert->totweight=eve->totweight;
1310 dvert->dw = MEM_callocN (sizeof(MDeformWeight)*eve->totweight,
1312 memcpy (dvert->dw, eve->dw,
1313 sizeof(MDeformWeight)*eve->totweight);
1319 eve->vn= (EditVert *)(long)(a++); /* counter */
1324 if(eve->f1==1) mvert->flag |= ME_SPHERETEST;
1325 mvert->flag |= (eve->f & 1);
1326 if (eve->h) mvert->flag |= ME_HIDE;
1336 /* If we didn't actually need the dverts, get rid of them */
1338 free_dverts(me->dvert, G.totvert);
1347 mface= &((MFace *) me->mface)[i];
1349 mface->v1= (unsigned int) evl->v1->vn;
1350 mface->v2= (unsigned int) evl->v2->vn;
1351 mface->v3= (unsigned int) evl->v3->vn;
1352 if(evl->v4) mface->v4= (unsigned int) evl->v4->vn;
1354 mface->mat_nr= evl->mat_nr;
1355 mface->puno= evl->f;
1356 mface->flag= evl->flag;
1358 /* mat_nr in vertex */
1360 mvert= me->mvert+mface->v1;
1361 if(mvert->mat_nr == (char)255) mvert->mat_nr= mface->mat_nr;
1362 mvert= me->mvert+mface->v2;
1363 if(mvert->mat_nr == (char)255) mvert->mat_nr= mface->mat_nr;
1364 mvert= me->mvert+mface->v3;
1365 if(mvert->mat_nr == (char)255) mvert->mat_nr= mface->mat_nr;
1367 mvert= me->mvert+mface->v4;
1368 if(mvert->mat_nr == (char)255) mvert->mat_nr= mface->mat_nr;
1372 /* watch: evl->e1->f==0 means loose edge */
1375 mface->edcode |= ME_V1V2;
1379 mface->edcode |= ME_V2V3;
1384 mface->edcode |= ME_V3V4;
1387 mface->edcode |= ME_V3V1;
1391 if(evl->e4 && evl->e4->f==1) {
1392 mface->edcode |= ME_V4V1;
1396 /* no index '0' at location 3 or 4 */
1397 if(evl->v4) fix_faceindices(mface, evl, 4);
1398 else fix_faceindices(mface, evl, 3);
1404 /* add loose edges as a face */
1408 mface= &((MFace *) me->mface)[i];
1409 mface->v1= (unsigned int) eed->v1->vn;
1410 mface->v2= (unsigned int) eed->v2->vn;
1411 test_index_mface(mface, 2);
1412 mface->edcode= ME_V1V2;
1420 /* tface block, always when undo even when it wasnt used,
1421 this because of empty me pointer */
1422 if( (me->tface || undo) && me->totface ) {
1425 tf=tfn= MEM_callocN(sizeof(TFace)*me->totface, "tface");
1431 if(G.f & G_FACESELECT) {
1432 if( vlakselectedAND(evl, 1) ) tf->flag |= TF_SELECT;
1433 else tf->flag &= ~TF_SELECT;
1439 /* if undo, me was empty */
1440 if(me->tface) MEM_freeN(me->tface);
1443 else if(me->tface) {
1444 MEM_freeN(me->tface);
1448 /* mcol: same as tface... */
1449 if( (me->mcol || undo) && me->totface) {
1450 unsigned int *mcn, *mc;
1452 mc=mcn= MEM_mallocN(4*sizeof(int)*me->totface, "mcol");
1455 memcpy(mc, evl->tf.col, 4*sizeof(int));
1460 if(me->mcol) MEM_freeN(me->mcol);
1461 me->mcol= (MCol *)mcn;
1464 MEM_freeN(me->mcol);
1469 /* are there keys? */
1472 /* find the active key */
1473 actkey= me->key->block.first;
1475 if(actkey->flag & SELECT) break;
1476 actkey= actkey->next;
1479 /* Lets reorder the key data so that things line up roughly
1480 * with the way things were before editmode */
1481 currkey = me->key->block.first;
1484 fp=newkey= MEM_callocN(me->key->elemsize*G.totvert,
1486 oldkey = currkey->data;
1493 if (eve->keyindex >= 0) {
1494 if(currkey == actkey) {
1495 if (actkey == me->key->refkey) {
1496 VECCOPY(fp, mvert->co);
1499 VECCOPY(fp, mvert->co);
1500 VECCOPY(mvert->co, oldverts[eve->keyindex].co);
1504 VECCOPY(fp, oldkey + 3 * eve->keyindex);
1508 VECCOPY(fp, mvert->co);
1515 currkey->totelem= G.totvert;
1516 MEM_freeN(currkey->data);
1517 currkey->data = newkey;
1519 currkey= currkey->next;
1524 if(oldverts) MEM_freeN(oldverts);
1526 if(actkey) do_spec_key(me->key);
1528 /* te be sure: clear ->vn pointers */
1535 /* displists of all users, including this one */
1536 freedisplist(&me->disp);
1537 freedisplist(&G.obedit->disp);
1541 if (ototvert<me->totvert) {
1542 ms= MEM_callocN(me->totvert*sizeof(MSticky), "msticky");
1543 memcpy(ms, me->msticky, ototvert*sizeof(MSticky));
1544 MEM_freeN(me->msticky);
1546 error("Sticky was too small");
1552 void remake_editMesh(void)
1554 undo_push_mesh("Undo all changes");
1556 allqueue(REDRAWVIEW3D, 0);
1557 makeDispList(G.obedit);
1560 /* ********************* TOOLS ********************* */
1564 void make_sticky(void)
1571 float ho[4], mat[4][4];
1574 if(G.scene->camera==0) return;
1577 error("Unable to perform function in EditMode");
1582 if TESTBASELIB(base) {
1583 if(base->object->type==OB_MESH) {
1588 if(me->msticky) MEM_freeN(me->msticky);
1589 me->msticky= MEM_mallocN(me->totvert*sizeof(MSticky), "sticky");
1591 /* like convert to render data */
1593 R.r.xsch= (R.r.size*R.r.xsch)/100;
1594 R.r.ysch= (R.r.size*R.r.ysch)/100;
1599 R.ycor= ( (float)R.r.yasp)/( (float)R.r.xasp);
1605 R.xend= R.xstart+R.rectx-1;
1606 R.yend= R.ystart+R.recty-1;
1608 where_is_object(G.scene->camera);
1609 Mat4CpyMat4(R.viewinv, G.scene->camera->obmat);
1610 Mat4Ortho(R.viewinv);
1611 Mat4Invert(R.viewmat, R.viewinv);
1613 RE_setwindowclip(1, -1);
1615 where_is_object(ob);
1616 Mat4MulMat4(mat, ob->obmat, R.viewmat);
1619 for(a=0; a<me->totvert; a++, ms++, mvert++) {
1620 VECCOPY(ho, mvert->co);
1621 Mat4MulVecfl(mat, ho);
1622 RE_projectverto(ho, ho);
1623 ms->co[0]= ho[0]/ho[3];
1624 ms->co[1]= ho[1]/ho[3];
1630 allqueue(REDRAWBUTSEDIT, 0);
1633 void fasterdraw(void)
1640 if(G.obedit) return;
1643 me= G.main->mesh.first;
1645 me->flag &= ~ME_ISDONE;
1651 if( TESTBASELIB(base) && (base->object->type==OB_MESH)) {
1652 me= base->object->data;
1653 if(me->id.lib==0 && (me->flag & ME_ISDONE)==0) {
1654 me->flag |= ME_ISDONE;
1657 for(a=0; a<me->totface; a++) {
1658 if( (mface->edcode & ME_V1V2) && ( (toggle++) & 1) ) {
1659 mface->edcode-= ME_V1V2;
1661 if( (mface->edcode & ME_V2V3) && ( (toggle++) & 1)) {
1662 mface->edcode-= ME_V2V3;
1664 if( (mface->edcode & ME_V3V1) && ( (toggle++) & 1)) {
1665 mface->edcode-= ME_V3V1;
1667 if( (mface->edcode & ME_V4V1) && ( (toggle++) & 1)) {
1668 mface->edcode-= ME_V4V1;
1670 if( (mface->edcode & ME_V3V4) && ( (toggle++) & 1)) {
1671 mface->edcode-= ME_V3V4;
1680 /* important?: reset flags again */
1681 me= G.main->mesh.first;
1683 me->flag &= ~ME_ISDONE;
1687 allqueue(REDRAWVIEW3D, 0);
1690 void slowerdraw(void) /* reset fasterdraw */
1697 if(G.obedit) return;
1701 if( TESTBASELIB(base) && (base->object->type==OB_MESH)) {
1702 me= base->object->data;
1707 for(a=0; a<me->totface; a++) {
1709 mface->edcode |= ME_V1V2|ME_V2V3;
1717 allqueue(REDRAWVIEW3D, 0);
1721 void convert_to_triface(int all)
1723 EditVlak *evl, *evln, *next;
1725 undo_push_mesh("Convert to triangles");
1731 if(all || vlakselectedAND(evl, 1) ) {
1733 evln= addvlaklist(evl->v1, evl->v2, evl->v3, 0, evl);
1734 evln= addvlaklist(evl->v1, evl->v3, evl->v4, 0, evl);
1736 evln->tf.uv[1][0]= evln->tf.uv[2][0];
1737 evln->tf.uv[1][1]= evln->tf.uv[2][1];
1738 evln->tf.uv[2][0]= evln->tf.uv[3][0];
1739 evln->tf.uv[2][1]= evln->tf.uv[3][1];
1741 evln->tf.col[1]= evln->tf.col[2];
1742 evln->tf.col[2]= evln->tf.col[3];
1744 BLI_remlink(&G.edvl, evl);
1754 void deselectall_mesh(void) /* toggle */
1759 if(G.obedit->lay & G.vd->lay) {
1770 if (a) undo_push_mesh("Deselect all");
1771 else undo_push_mesh("Select all");
1783 allqueue(REDRAWVIEW3D, 0);
1787 void righthandfaces(int select) /* makes faces righthand turning */
1789 EditEdge *eed, *ed1, *ed2, *ed3, *ed4;
1790 EditVlak *evl, *startvl;
1791 float maxx, nor[3], cent[3];
1792 int totsel, found, foundone, direct, turn;
1794 /* based at a select-connected to witness loose objects */
1796 /* count per edge the amount of faces */
1798 /* find the ultimate left, front, upper face */
1800 /* put normal to the outside, and set the first direction flags in edges */
1802 /* then check the object, and set directions / direction-flags: but only for edges with 1 or 2 faces */
1803 /* this is in fact the 'select connected' */
1805 /* in case (selected) faces were not done: start over with 'find the ultimate ...' */
1816 /* count faces and edges */
1820 if(select==0 || vlakselectedAND(evl, 1) ) {
1826 if(evl->v4) evl->e4->f1++;
1834 /* from the outside to the inside */
1842 CalcCent3f(cent, evl->v1->co, evl->v2->co, evl->v3->co);
1843 cent[0]= fabs(cent[0])+fabs(cent[1])+fabs(cent[2]);
1853 /* set first face correct: calc normal */
1854 CalcNormFloat(startvl->v1->co, startvl->v2->co, startvl->v3->co, nor);
1855 CalcCent3f(cent, startvl->v1->co, startvl->v2->co, startvl->v3->co);
1857 /* first normal is oriented this way or the other */
1860 if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] > 0.0) flipvlak(startvl);
1863 if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] < 0.0) flipvlak(startvl);
1866 else if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] < 0.0) flipvlak(startvl);
1870 if(eed->v1==startvl->v1) eed->f= 1;
1874 if(eed->v1==startvl->v2) eed->f= 1;
1878 if(eed->v1==startvl->v3) eed->f= 1;
1883 if(eed->v1==startvl->v4) eed->f= 1;
1895 if(direct) evl= G.edvl.first;
1896 else evl= G.edvl.last;
1908 if(ed1->v1==evl->v1 && ed1->f==1) turn= 1;
1909 if(ed1->v2==evl->v1 && ed1->f==2) turn= 1;
1913 if(ed2->v1==evl->v2 && ed2->f==1) turn= 1;
1914 if(ed2->v2==evl->v2 && ed2->f==2) turn= 1;
1918 if(ed3->v1==evl->v3 && ed3->f==1) turn= 1;
1919 if(ed3->v2==evl->v3 && ed3->f==2) turn= 1;
1922 else if(ed4 && ed4->f) {
1923 if(ed4->v1==evl->v4 && ed4->f==1) turn= 1;
1924 if(ed4->v2==evl->v4 && ed4->f==2) turn= 1;
1934 if(ed1->v1==evl->v1) ed1->f= 2;
1936 if(ed2->v1==evl->v2) ed2->f= 2;
1938 if(ed3->v1==evl->v3) ed3->f= 2;
1941 if(ed4->v1==evl->v4) ed4->f= 2;
1949 if(ed1->v1== evl->v1) ed1->f= 1;
1951 if(ed2->v1==evl->v2) ed2->f= 1;
1953 if(ed3->v1==evl->v3) ed3->f= 1;
1956 if(ed4->v1==evl->v4) ed4->f= 1;
1962 if(direct) evl= evl->next;
1963 else evl= evl->prev;
1969 recalc_editnormals();
1971 makeDispList(G.obedit);
1976 static EditVert *findnearestvert(short sel)
1978 /* if sel==1 the vertices with flag==1 get a disadvantage */
1979 EditVert *eve,*act=0;
1980 static EditVert *acto=0;
1981 short dist=100,temp,mval[2];
1983 if(G.edve.first==0) return 0;
1986 calc_meshverts_ext(); /* drawobject.c */
1988 /* we count from acto->next to last, and from first to acto */
1989 /* does acto exist? */
1992 if(eve==acto) break;
1995 if(eve==0) acto= G.edve.first;
1997 if(acto==0) return 0;
1999 /* is there an indicated vertex? part 1 */
2000 getmouseco_areawin(mval);
2004 temp= abs(mval[0]- eve->xs)+ abs(mval[1]- eve->ys);
2005 if( (eve->f & 1)==sel ) temp+=5;
2014 /* is there an indicated vertex? part 2 */
2019 temp= abs(mval[0]- eve->xs)+ abs(mval[1]- eve->ys);
2020 if( (eve->f & 1)==sel ) temp+=5;
2026 if(eve== acto) break;
2037 static EditEdge *findnearestedge()
2039 EditEdge *closest, *eed;
2040 short found=0, mval[2];
2041 float distance[2], v1[2], v2[2], mval2[2];
2043 calc_meshverts_ext_f2(); /*sets (eve->f & 2) for vertices that aren't visible*/
2045 if(G.eded.first==0) return NULL;
2049 /* reset test flags */
2055 getmouseco_areawin(mval);
2056 mval2[0] = (float)mval[0]; /* cast to float because of the pdist function only taking floats...*/
2057 mval2[1] = (float)mval[1];
2060 while(eed) { /*compare the distance to the rest of the edges and find the closest one*/
2061 if( !((eed->v1->f & 2) && (eed->v2->f & 2))){ /* Are both vertices of the edge invisible? then don't select the edge*/
2062 v1[0] = eed->v1->xs; /* oh great! the screencoordinates are not an array....grrrr*/
2063 v1[1] = eed->v1->ys;
2064 v2[0] = eed->v2->xs;
2065 v2[1] = eed->v2->ys;
2067 distance[1] = PdistVL2Dfl(mval2, v1, v2);
2069 if(distance[1]<50){ /* TODO: make this maximum selecting distance selectable (the same with vertice select?) */
2070 if(found) { /*do we have to compare it to other distances? */
2071 if (distance[1]<distance[0]){
2072 distance[0]=distance[1];
2073 closest=eed; /*save the current closest edge*/
2076 distance[0]=distance[1];
2094 if(found) return closest;
2099 /* this is a template function to demonstrate a loop with drawing...
2100 it is a temporal mode, so use with wisdom! if you can avoid, always better. (ton)
2108 /* uses callback mechanism to draw it all in current area */
2109 scrarea_do_windraw(curarea);
2112 eed= findnearestedge();
2114 /* set window matrix to perspective, default an area returns with buttons transform */
2116 /* make a copy, for safety */
2118 /* multiply with the object transformation */
2119 mymultmatrix(G.obedit->obmat);
2123 glColor3ub(255, 255, 0);
2125 glVertex3fv(eed->v1->co);
2126 glVertex3fv(eed->v2->co);
2130 /* restore matrix transform */
2133 headerprint("We are now in evil edge select mode. Press any key to exit");
2135 /* this also verifies other area/windows for clean swap */
2136 screen_swapbuffers();
2138 /* testing for user input... */
2141 short event= extern_qread(&val); // extern_qread stores important events for the mainloop to handle
2143 /* val==0 on key-release event */
2144 if(val && event!=MOUSEY && event!=MOUSEX) {
2148 /* sleep 0.01 second to prevent overload in this poor loop */
2153 /* send event to redraw this window, does header too */
2154 addqueue(curarea->win, REDRAW, 1);
2159 functionality: various loop functions
2160 parameters: mode tells the function what it should do with the loop:
2166 EditEdge *start, *eed, *opposite,*currente, *oldstart;
2167 EditVlak *evl, *currentvl, *formervl;
2168 short lastface=0, foundedge=0, c=0, tri=0, side=1, totface=0, searching=1, event=0, noface=1;
2170 if ((G.obedit==0) || (G.edvl.first==0)) return;
2172 if(mode=='c')undo_push_mesh("Loop Subdivide");
2173 else if(mode=='s')undo_push_mesh("Faceloop select");
2180 /* reset variables */
2181 start=eed=opposite=currente=0;
2182 evl=currentvl=formervl=0;
2184 lastface=foundedge=c=tri=totface=0;
2186 /* Look for an edge close by */
2187 start=findnearestedge();
2189 /* If the edge doesn't belong to a face, it's not a valid starting edge */
2194 if(evl->e1->f & 16){
2198 else if(evl->e2->f & 16){
2202 else if(evl->e3->f & 16){
2206 else if(evl->e4 && evl->e4->f & 16){
2215 /* Did we find anything that is selectable? */
2216 if(start && !noface && (oldstart==NULL || start!=oldstart)){
2218 /* If we stay in the neighbourhood of this edge, we don't have to recalculate the loop everytime*/
2224 eed->f &= ~(2|4|8|32);
2225 eed->v1->f &= ~(2|8|16);
2226 eed->v2->f &= ~(2|8|16);
2237 /* Tag the starting edge */
2238 start->f |= (2|4|8);
2244 /*-----Limit the Search----- */
2245 while(!lastface && c<totface+1){
2247 /*----------Get Loop------------------------*/
2248 tri=foundedge=lastface=0;
2250 while(evl && !foundedge && !tri){
2252 if(!(evl->v4)){ /* Exception for triangular faces */
2254 if((evl->e1->f | evl->e2->f | evl->e3->f) & 2){
2261 if((evl->e1->f | evl->e2->f | evl->e3->f | evl->e4->f) & 2){
2263 if(c==0){ /* just pick a face, doesn't matter wich side of the edge we go to */
2266 if(!(evl->e1->v1->f & 2) && !(evl->e1->v2->f & 2)){
2270 else if(!(evl->e2->v1->f & 2) && !(evl->e2->v2->f & 2)){
2274 else if(!(evl->e3->v1->f & 2) && !(evl->e3->v2->f & 2)){
2278 else if(!(evl->e4->v1->f & 2) && !(evl->e4->v2->f & 2)){
2286 /* mark this side of the edge so we know in which direction we went */
2287 if(side==1) evl->f |= 4;
2291 if(evl!=formervl){ /* prevent going backwards in the loop */
2293 if(!(evl->e1->v1->f & 2) && !(evl->e1->v2->f & 2)){
2297 else if(!(evl->e2->v1->f & 2) && !(evl->e2->v2->f & 2)){
2301 else if(!(evl->e3->v1->f & 2) && !(evl->e3->v2->f & 2)){
2305 else if(!(evl->e4->v1->f & 2) && !(evl->e4->v2->f & 2)){
2317 /*----------END Get Loop------------------------*/
2320 /*----------Decisions-----------------------------*/
2322 /* mark the edge and face as done */
2326 if(opposite->f & 4) lastface=1; /* found the starting edge! close loop */
2328 /* un-set the testflags */
2330 currente->v1->f &= ~2;
2331 currente->v2->f &= ~2;
2333 /* set the opposite edge to be the current edge */
2336 /* set the current face to be the FORMER face (to prevent going backwards in the loop) */
2339 /* set the testflags */
2341 currente->v1->f |= 2;
2342 currente->v2->f |= 2;
2347 /* un-set the testflags */
2349 currente->v1->f &= ~2;
2350 currente->v2->f &= ~2;
2352 /* mark the edge and face as done */
2356 /* cheat to correctly split tri's:
2357 * Set eve->f & 16 for the last vertex of the loop
2360 currentvl->v1->f |= 16;
2361 currentvl->v2->f |= 16;
2362 currentvl->v3->f |= 16;
2364 currente->v1->f &= ~16;
2365 currente->v2->f &= ~16;
2368 /* is the the first time we've ran out of possible faces?
2369 * try to start from the beginning but in the opposite direction to select as many
2370 * verts as possible.
2375 currente->v1->f |= 2;
2376 currente->v2->f |= 2;
2382 /*----------END Decisions-----------------------------*/
2385 /*-----END Limit the Search----- */
2388 /*------------- Preview lines--------------- */
2390 /* uses callback mechanism to draw it all in current area */
2391 scrarea_do_windraw(curarea);
2393 /* set window matrix to perspective, default an area returns with buttons transform */
2395 /* make a copy, for safety */
2397 /* multiply with the object transformation */
2398 mymultmatrix(G.obedit->obmat);
2400 glColor3ub(255, 255, 0);
2407 if(!(evl->e1->f & 8)){
2409 glVertex3fv(evl->e1->v1->co);
2410 glVertex3fv(evl->e1->v2->co);
2414 if(!(evl->e2->f & 8)){
2416 glVertex3fv(evl->e2->v1->co);
2417 glVertex3fv(evl->e2->v2->co);
2421 if(!(evl->e3->f & 8)){
2423 glVertex3fv(evl->e3->v1->co);
2424 glVertex3fv(evl->e3->v2->co);
2429 if(!(evl->e4->f & 8)){
2431 glVertex3fv(evl->e4->v1->co);
2432 glVertex3fv(evl->e4->v2->co);
2450 cen[a][0]= (evl->e1->v1->co[0] + evl->e1->v2->co[0])/2.0;
2451 cen[a][1]= (evl->e1->v1->co[1] + evl->e1->v2->co[1])/2.0;
2452 cen[a][2]= (evl->e1->v1->co[2] + evl->e1->v2->co[2])/2.0;
2454 evl->e1->v1->f |= 8;
2455 evl->e1->v2->f |= 8;
2459 if((evl->e2->f & 8) && a!=2){
2460 cen[a][0]= (evl->e2->v1->co[0] + evl->e2->v2->co[0])/2.0;
2461 cen[a][1]= (evl->e2->v1->co[1] + evl->e2->v2->co[1])/2.0;
2462 cen[a][2]= (evl->e2->v1->co[2] + evl->e2->v2->co[2])/2.0;
2464 evl->e1->v1->f |= 8;
2465 evl->e1->v2->f |= 8;
2469 if((evl->e3->f & 8) && a!=2){
2470 cen[a][0]= (evl->e3->v1->co[0] + evl->e3->v2->co[0])/2.0;
2471 cen[a][1]= (evl->e3->v1->co[1] + evl->e3->v2->co[1])/2.0;
2472 cen[a][2]= (evl->e3->v1->co[2] + evl->e3->v2->co[2])/2.0;
2474 evl->e1->v1->f |= 8;
2475 evl->e1->v2->f |= 8;
2481 if((evl->e4->f & 8) && a!=2){
2482 cen[a][0]= (evl->e4->v1->co[0] + evl->e4->v2->co[0])/2.0;
2483 cen[a][1]= (evl->e4->v1->co[1] + evl->e4->v2->co[1])/2.0;
2484 cen[a][2]= (evl->e4->v1->co[2] + evl->e4->v2->co[2])/2.0;
2486 evl->e1->v1->f |= 8;
2487 evl->e1->v2->f |= 8;
2492 else{ /* if it's a triangular face, set the remaining vertex as the cutcurve coordinate */
2494 if(evl->v1->f & 16){
2495 cen[a][0]= evl->v1->co[0];
2496 cen[a][1]= evl->v1->co[1];
2497 cen[a][2]= evl->v1->co[2];
2500 else if(evl->v2->f & 16){
2501 cen[a][0]= evl->v2->co[0];
2502 cen[a][1]= evl->v2->co[1];
2503 cen[a][2]= evl->v2->co[2];
2506 else if(evl->v3->f & 16){
2507 cen[a][0]= evl->v3->co[0];
2508 cen[a][1]= evl->v3->co[1];
2509 cen[a][2]= evl->v3->co[2];
2516 glVertex3fv(cen[0]);
2517 glVertex3fv(cen[1]);
2525 /* restore matrix transform */
2528 headerprint("LMB to confirm, RMB to cancel");
2530 /* this also verifies other area/windows for clean swap */
2531 screen_swapbuffers();
2533 /*--------- END Preview Lines------------*/
2535 }/*if(start!=NULL){ */
2538 unsigned short val=0;
2539 event= extern_qread(&val); // extern_qread stores important events for the mainloop to handle
2541 /* val==0 on key-release event */
2542 if(val && (event==ESCKEY || event==RIGHTMOUSE || event==LEFTMOUSE || event==RETKEY)){
2547 }/*while(event!=ESCKEY && event!=RIGHTMOUSE && event!=LEFTMOUSE && event!=RETKEY){*/
2549 /*----------Select Loop------------*/
2550 if(mode=='s' && start!=NULL && (event==LEFTMOUSE || event==RETKEY)){
2558 if(evl->v4)evl->v4->f |= 1;
2563 /*----------END Select Loop------------*/
2565 /*----------Cut Loop---------------*/
2566 if(mode=='c' && start!=NULL && (event==LEFTMOUSE || event==RETKEY)){
2568 /* subdivide works on selected verts... */
2578 subdivideflag(8, 0, B_KNIFE); /* B_KNIFE tells subdivide that edgeflags are already set */
2582 if(eed->v1->f & 16) eed->v1->f |= 1;
2583 else eed->v1->f &= ~1;
2585 if(eed->v2->f & 16) eed->v2->f |= 1;
2586 else eed->v2->f &= ~1;
2591 /*----------END Cut Loop-----------------------------*/
2597 eed->f &= ~(2|4|8|32);
2598 eed->v1->f &= ~(2|16);
2599 eed->v2->f &= ~(2|16);
2610 /* send event to redraw this window, does header too */
2611 addqueue(curarea->win, REDRAW, 1);
2614 void edge_select(void)
2616 EditEdge *closest=0;
2618 closest=findnearestedge();
2620 if(closest){ /* Did we find anything that is selectable?*/
2622 if( (G.qual & LR_SHIFTKEY)==0) {
2625 undo_push_mesh("Edge select");
2627 for(eve= G.edve.first; eve; eve= eve->next) eve->f&= ~1;
2630 closest->v1->f |= 1;
2631 closest->v2->f |= 1;
2634 /* both of the vertices are selected: deselect both*/
2635 if((closest->v1->f & 1) && (closest->v2->f & 1) ){
2636 closest->v1->f &= ~1;
2637 closest->v2->f &= ~1;
2641 closest->v1->f |= 1;
2642 closest->v2->f |= 1;
2646 allqueue(REDRAWVIEW3D, 0);
2650 static void draw_vertices_special(int mode, EditVert *act) /* teken = draw */
2652 /* (only this view, no other windows) */
2653 /* hackish routine for visual speed:
2654 * mode 0: deselect the selected ones, draw then, except act
2655 * mode 1: only draw act
2658 float size= BIF_GetThemeValuef(TH_VERTEX_SIZE);
2665 mymultmatrix(G.obedit->obmat);
2668 BIF_GetThemeColor3ubv(TH_VERTEX, col);
2670 /* set zbuffer on, its default off outside main drawloops */
2671 if(G.vd->drawtype > OB_WIRE) {
2673 glEnable(GL_DEPTH_TEST);
2677 eve= (EditVert *)G.edve.first;
2680 if(eve!=act && (eve->f & 1)) {
2682 glVertex3fv(act->co);
2689 glDisable(GL_DEPTH_TEST);
2693 /* draw active vertex */
2694 if(act->f & 1) BIF_GetThemeColor3ubv(TH_VERTEX_SELECT, col);
2695 else BIF_GetThemeColor3ubv(TH_VERTEX, col);
2697 glColor3ub(col[0], col[1], col[2]);
2700 glVertex3fv(act->co);
2709 void mouse_mesh(void)
2713 if(G.qual & LR_ALTKEY) {
2714 if (G.qual & LR_CTRLKEY) edge_select();
2718 act= findnearestvert(1);
2721 glDrawBuffer(GL_FRONT);
2723 if( (act->f & 1)==0) act->f+= 1;
2724 else if(G.qual & LR_SHIFTKEY) act->f-= 1;
2726 if((G.qual & LR_SHIFTKEY)==0) {
2727 undo_push_mesh("Vertex select");
2728 draw_vertices_special(0, act);
2730 else draw_vertices_special(1, act);
2735 glDrawBuffer(GL_BACK);
2737 /* signal that frontbuf differs from back */
2738 curarea->win_swap= WIN_FRONT_OK;
2740 if(G.f & (G_FACESELECT|G_DRAWFACES|G_DRAWEDGES)) {
2741 /* update full view later on */
2742 allqueue(REDRAWVIEW3D, 0);
2746 rightmouse_transform();
2750 static void selectconnectedAll(void)
2754 short flag=1,toggle=0;
2756 if(G.eded.first==0) return;
2758 undo_push_mesh("Select Connected (All)");
2763 if(toggle & 1) eed= G.eded.first;
2764 else eed= G.eded.last;
2770 if( (v2->f & 1)==0 ) {
2775 else if(v2->f & 1) {
2776 if( (v1->f & 1)==0 ) {
2782 if(toggle & 1) eed= eed->next;
2783 else eed= eed->prev;
2788 allqueue(REDRAWVIEW3D, 0);
2792 void selectconnected_mesh(int qual)
2794 EditVert *eve,*v1,*v2,*act= 0;
2796 short flag=1,sel,toggle=0;
2798 if(G.eded.first==0) return;
2800 if(qual & LR_CTRLKEY) {
2801 selectconnectedAll();
2806 if(qual & LR_SHIFTKEY) sel=2;
2808 act= findnearestvert(sel-2);
2810 error(" Nothing indicated ");
2814 undo_push_mesh("Select linked");
2815 /* clear test flags */
2821 act->f= (act->f & ~3) | sel;
2826 if(toggle & 1) eed= G.eded.first;
2827 else eed= G.eded.last;
2833 if( (v2->f & 2)==0 ) {
2834 v2->f= (v2->f & ~3) | sel;
2838 else if(v2->f & 2) {
2839 if( (v1->f & 2)==0 ) {
2840 v1->f= (v1->f & ~3) | sel;
2845 if(toggle & 1) eed= eed->next;
2846 else eed= eed->prev;
2851 allqueue(REDRAWVIEW3D, 0);
2855 short extrudeflag(short flag,short type)
2857 /* when type=1 old extrusion faces are removed (for spin etc) */
2858 /* all verts with (flag & 'flag'): extrude */
2859 /* from old verts, 'flag' is cleared, in new ones it is set */
2861 EditVert *eve, *v1, *v2, *v3, *v4, *nextve;
2862 EditEdge *eed, *e1, *e2, *e3, *e4, *nexted;
2863 EditVlak *evl, *evl2, *nextvl;
2864 short sel=0, deloud= 0, smooth= 0;
2866 if(G.obedit==0 || get_mesh(G.obedit)==0) return 0;
2868 /* clear vert flag f1, we use this to detext a loose selected vertice */
2871 if(eve->f & flag) eve->f1= 1;
2875 /* clear edges counter flag, if selected we set it at 1 */
2878 if( (eed->v1->f & flag) && (eed->v2->f & flag) ) {
2885 eed->f1= 1; /* this indicates it is an 'old' edge (in this routine we make new ones) */
2890 /* we set a flag in all selected faces, and increase the associated edge counters */
2896 if (evl->flag & ME_SMOOTH) {
2897 if (vlakselectedOR(evl, 1)) smooth= 1;
2900 if(vlakselectedAND(evl, flag)) {
2906 if(e1->f < 3) e1->f++;
2907 if(e2->f < 3) e2->f++;
2908 if(e3->f < 3) e3->f++;
2909 if(e4 && e4->f < 3) e4->f++;
2912 else if(vlakselectedOR(evl, flag)) {
2918 if( (e1->v1->f & flag) && (e1->v2->f & flag) ) e1->f1= 2;
2919 if( (e2->v1->f & flag) && (e2->v2->f & flag) ) e2->f1= 2;
2920 if( (e3->v1->f & flag) && (e3->v2->f & flag) ) e3->f1= 2;
2921 if( e4 && (e4->v1->f & flag) && (e4->v2->f & flag) ) e4->f1= 2;
2927 /* set direction of edges */
2932 if(evl->e1->v1 == evl->v1) evl->e1->dir= 0;
2933 else evl->e1->dir= 1;
2936 if(evl->e2->v1 == evl->v2) evl->e2->dir= 0;
2937 else evl->e2->dir= 1;
2940 if(evl->e3->v1 == evl->v3) evl->e3->dir= 0;
2941 else evl->e3->dir= 1;
2943 if(evl->e4 && evl->e4->f==2) {
2944 if(evl->e4->v1 == evl->v4) evl->e4->dir= 0;
2945 else evl->e4->dir= 1;
2952 /* the current state now is:
2953 eve->f1==1: loose selected vertex
2955 eed->f==0 : edge is not selected, no extrude
2956 eed->f==1 : edge selected, is not part of a face, extrude
2957 eed->f==2 : edge selected, is part of 1 face, extrude
2958 eed->f==3 : edge selected, is part of more faces, no extrude
2960 eed->f1==0: new edge
2961 eed->f1==1: edge selected, is part of selected face, when eed->f==3: remove
2962 eed->f1==2: edge selected, is not part of a selected face
2964 evl->f==1 : duplicate this face
2967 /* copy all selected vertices, */
2968 /* write pointer to new vert in old struct at eve->vn */
2971 eve->f&= ~128; /* clear, for later test for loose verts */
2976 VECCOPY(v1->co, eve->co);
2985 if(sel==0) return 0;
2987 /* all edges with eed->f==1 or eed->f==2 become faces */
2988 /* if deloud==1 then edges with eed->f>2 are removed */
2993 eed->v1->f|=128; /* = no loose vert! */
2996 if( (eed->f==1 || eed->f==2) ) {
2997 if(eed->f1==2) deloud=1;
2999 if(eed->dir==1) evl2= addvlaklist(eed->v1, eed->v2, eed->v2->vn, eed->v1->vn, NULL);
3000 else evl2= addvlaklist(eed->v2, eed->v1, eed->v1->vn, eed->v2->vn, NULL);
3001 if (smooth) evl2->flag |= ME_SMOOTH;
3010 if(eed->f==3 && eed->f1==1) {