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) 2004 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 *****
35
editmesh_mods.c, UI level access, no geometry changes
47
#include "MEM_guardedalloc.h"
49
#include "MTC_matrixops.h"
51
#include "DNA_mesh_types.h"
52
#include "DNA_material_types.h"
53
#include "DNA_meshdata_types.h"
54
#include "DNA_object_types.h"
55
#include "DNA_texture_types.h"
56
#include "DNA_scene_types.h"
57
#include "DNA_screen_types.h"
58
#include "DNA_view3d_types.h"
60
#include "BLI_blenlib.h"
61
#include "BLI_arithb.h"
62
#include "BLI_editVert.h"
65
#include "BKE_displist.h"
66
#include "BKE_DerivedMesh.h"
67
#include "BKE_global.h"
69
#include "BKE_material.h"
70
#include "BKE_texture.h"
71
#include "BKE_utildefines.h"
73
#include "BIF_editmesh.h"
74
#include "BIF_resources.h"
76
#include "BIF_glutil.h"
77
#include "BIF_graphics.h"
78
#include "BIF_interface.h"
79
#include "BIF_mywindow.h"
80
#include "BIF_resources.h"
81
#include "BIF_screen.h"
82
#include "BIF_space.h"
83
#include "BIF_toolbox.h"
85
#include "BDR_drawobject.h"
86
#include "BDR_editobject.h"
88
#include "BSE_drawview.h"
92
#include "IMB_imbuf.h"
96
#include "render.h" // externtex
101
/* ****************************** SELECTION ROUTINES **************** */
103
int em_solidoffs=0, em_wireoffs=0, em_vertoffs; // set in drawobject.c ... for colorindices
105
static void check_backbuf(void)
107
if(G.vd->flag & V3D_NEEDBACKBUFDRAW) {
112
/* samples a single pixel (copied from vpaint) */
113
static unsigned int sample_backbuf(int x, int y)
117
if(x>=curarea->winx || y>=curarea->winy) return 0;
118
x+= curarea->winrct.xmin;
119
y+= curarea->winrct.ymin;
121
check_backbuf(); // actually not needed for apple
124
glReadBuffer(GL_AUX0);
126
glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
127
glReadBuffer(GL_BACK);
129
if(G.order==B_ENDIAN) SWITCH_INT(col);
131
return framebuffer_to_index(col);
134
/* reads full rect, converts indices */
135
static unsigned int *read_backbuf(short xmin, short ymin, short xmax, short ymax)
137
unsigned int *dr, *buf;
139
short xminc, yminc, xmaxc, ymaxc;
142
if(xmin<0) xminc= 0; else xminc= xmin;
143
if(xmax>=curarea->winx) xmaxc= curarea->winx-1; else xmaxc= xmax;
144
if(xminc > xmaxc) return NULL;
146
if(ymin<0) yminc= 0; else yminc= ymin;
147
if(ymax>=curarea->winy) ymaxc= curarea->winy-1; else ymaxc= ymax;
148
if(yminc > ymaxc) return NULL;
150
buf= MEM_mallocN( (xmaxc-xminc+1)*(ymaxc-yminc+1)*sizeof(int), "sample rect");
152
check_backbuf(); // actually not needed for apple
155
glReadBuffer(GL_AUX0);
157
glReadPixels(curarea->winrct.xmin+xminc, curarea->winrct.ymin+yminc, (xmaxc-xminc+1), (ymaxc-yminc+1), GL_RGBA, GL_UNSIGNED_BYTE, buf);
158
glReadBuffer(GL_BACK);
160
if(G.order==B_ENDIAN) IMB_convert_rgba_to_abgr((xmaxc-xminc+1)*(ymaxc-yminc+1), buf);
162
a= (xmaxc-xminc+1)*(ymaxc-yminc+1);
165
if(*dr) *dr= framebuffer_to_index(*dr);
169
/* put clipped result back, if needed */
170
if(xminc==xmin && xmaxc==xmax && yminc==ymin && ymaxc==ymax) return buf;
172
unsigned int *buf1= MEM_callocN( (xmax-xmin+1)*(ymax-ymin+1)*sizeof(int), "sample rect2");
179
for(ys= ymin; ys<=ymax; ys++) {
180
for(xs= xmin; xs<=xmax; xs++, dr++) {
181
if( xs>=xminc && xs<=xmaxc && ys>=yminc && ys<=ymaxc) {
195
/* smart function to sample a rect spiralling outside, nice for backbuf selection */
196
static unsigned int sample_backbuf_rect(unsigned int *buf, int size, int min, int max, short *dist)
198
unsigned int *bufmin, *bufmax;
199
int a, b, rc, nr, amount, dirvec[4][2];
205
dirvec[0][0]= 1; dirvec[0][1]= 0;
206
dirvec[1][0]= 0; dirvec[1][1]= -size;
207
dirvec[2][0]= -1; dirvec[2][1]= 0;
208
dirvec[3][0]= 0; dirvec[3][1]= size;
211
bufmax= buf+ size*size;
212
buf+= amount*size+ amount;
214
for(nr=1; nr<=size; nr++) {
217
for(b=0; b<nr; b++, distance++) {
219
if(*buf && *buf>=min && *buf<max ) {
220
*dist= (short) sqrt( (float)distance );
221
return *buf - min+1; // messy yah, but indices start at 1
224
buf+= (dirvec[rc][0]+dirvec[rc][1]);
226
if(buf<bufmin || buf>=bufmax) {
237
/* facilities for border select and circle select */
238
static char *selbuf= NULL;
240
/* opengl doesn't support concave... */
241
static void draw_triangulated(short mcords[][2], short tot)
243
ListBase lb={NULL, NULL};
249
dl= MEM_callocN(sizeof(DispList), "poly disp");
253
dl->verts= fp= MEM_callocN(tot*3*sizeof(float), "poly verts");
254
BLI_addtail(&lb, dl);
256
for(a=0; a<tot; a++, fp+=3) {
257
fp[0]= (float)mcords[a][0];
258
fp[1]= (float)mcords[a][1];
262
filldisplist(&lb, &lb);
265
dl= lb.first; // filldisplist adds in head of list
266
if(dl->type==DL_INDEX3) {
272
glBegin(GL_TRIANGLES);
274
glVertex3fv(fp+3*index[0]);
275
glVertex3fv(fp+3*index[1]);
276
glVertex3fv(fp+3*index[2]);
286
/* reads rect, and builds selection array for quick lookup */
287
/* returns if all is OK */
288
int EM_init_backbuf_border(short xmin, short ymin, short xmax, short ymax)
290
unsigned int *buf, *dr;
293
if(G.obedit==NULL || G.vd->drawtype<OB_SOLID || (G.vd->flag & V3D_ZBUF_SELECT)==0) return 0;
294
if(em_vertoffs==0) return 0;
296
dr= buf= read_backbuf(xmin, ymin, xmax, ymax);
297
if(buf==NULL) return 0;
299
/* build selection lookup */
300
selbuf= MEM_callocN(em_vertoffs+1, "selbuf");
302
a= (xmax-xmin+1)*(ymax-ymin+1);
304
if(*dr>0 && *dr<=em_vertoffs) selbuf[*dr]= 1;
311
int EM_check_backbuf_border(int index)
313
if(selbuf==NULL) return 1;
314
if(index>0 && index<=em_vertoffs)
315
return selbuf[index];
319
void EM_free_backbuf_border(void)
321
if(selbuf) MEM_freeN(selbuf);
325
/* mcords is a polygon mask
327
- draw with black in backbuffer,
328
- grab again and compare
331
int EM_mask_init_backbuf_border(short mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax)
333
unsigned int *buf, *bufmask, *dr, *drm;
336
/* method in use for face selecting too */
338
if(G.f & G_FACESELECT);
341
else if(G.vd->drawtype<OB_SOLID || (G.vd->flag & V3D_ZBUF_SELECT)==0) return 0;
343
if(em_vertoffs==0) return 0;
345
dr= buf= read_backbuf(xmin, ymin, xmax, ymax);
346
if(buf==NULL) return 0;
350
glDrawBuffer(GL_AUX0);
352
glDisable(GL_DEPTH_TEST);
357
/* yah, opengl doesn't do concave... tsk! */
358
draw_triangulated(mcords, tot);
360
glBegin(GL_LINE_LOOP); // for zero sized masks, lines
361
for(a=0; a<tot; a++) glVertex2s(mcords[a][0], mcords[a][1]);
365
glFinish(); // to be sure readpixels sees mask
367
glDrawBuffer(GL_BACK);
370
drm= bufmask= read_backbuf(xmin, ymin, xmax, ymax);
371
if(bufmask==NULL) return 0; // only when mem alloc fails, go crash somewhere else!
373
/* build selection lookup */
374
selbuf= MEM_callocN(em_vertoffs+1, "selbuf");
376
a= (xmax-xmin+1)*(ymax-ymin+1);
378
if(*dr>0 && *dr<=em_vertoffs && *drm==0) selbuf[*dr]= 1;
387
/* circle shaped sample area */
388
int EM_init_backbuf_circle(short xs, short ys, short rads)
390
unsigned int *buf, *dr;
391
short xmin, ymin, xmax, ymax, xc, yc;
394
if(G.obedit==NULL || G.vd->drawtype<OB_SOLID || (G.vd->flag & V3D_ZBUF_SELECT)==0) return 0;
395
if(em_vertoffs==0) return 0;
397
xmin= xs-rads; xmax= xs+rads;
398
ymin= ys-rads; ymax= ys+rads;
399
dr= buf= read_backbuf(xmin, ymin, xmax, ymax);
400
if(buf==NULL) return 0;
402
/* build selection lookup */
403
selbuf= MEM_callocN(em_vertoffs+1, "selbuf");
405
for(yc= -rads; yc<=rads; yc++) {
406
for(xc= -rads; xc<=rads; xc++, dr++) {
407
if(xc*xc + yc*yc < radsq) {
408
if(*dr>0 && *dr<=em_vertoffs) selbuf[*dr]= 1;
419
static EditVert *findnearestvert_f(short *dist, short sel)
421
static EditVert *acto= NULL;
422
EditMesh *em = G.editMesh;
423
/* if sel==1 the vertices with flag==1 get a disadvantage */
424
EditVert *eve,*act=NULL;
427
if(em->verts.first==NULL) return NULL;
430
calc_meshverts_ext(); /* drawobject.c */
432
/* we count from acto->next to last, and from first to acto */
433
/* does acto exist? */
434
eve= em->verts.first;
439
if(eve==NULL) acto= em->verts.first;
441
/* is there an indicated vertex? part 1 */
442
getmouseco_areawin(mval);
445
if(eve->h==0 && eve->xs!=3200) {
446
temp= abs(mval[0]- eve->xs)+ abs(mval[1]- eve->ys);
447
if( (eve->f & 1)==sel ) temp+=5;
456
/* is there an indicated vertex? part 2 */
458
eve= em->verts.first;
460
if(eve->h==0 && eve->xs!=3200) {
461
temp= abs(mval[0]- eve->xs)+ abs(mval[1]- eve->ys);
462
if( (eve->f & 1)==sel ) temp+=5;
468
if(eve== acto) break;
478
/* backbuffer version */
479
static EditVert *findnearestvert(short *dist, short sel)
481
if(G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT)) {
485
short mval[2], distance=255;
487
getmouseco_areawin(mval);
490
buf= read_backbuf(mval[0]-25, mval[1]-25, mval[0]+24, mval[1]+24);
492
index= sample_backbuf_rect(buf, 50, em_wireoffs, 0xFFFFFF, &distance); // globals, set in drawobject.c
494
if(distance < *dist) {
495
if(index>0) for(eve= G.editMesh->verts.first; eve; eve= eve->next, a++) if(index==a) break;
496
if(eve) *dist= distance;
501
else return findnearestvert_f(dist, sel);
504
/* helper for findnearest edge */
505
static float dist_mval_edge(short *mval, EditEdge *eed)
507
float v1[2], v2[2], mval2[2];
509
mval2[0] = (float)mval[0];
510
mval2[1] = (float)mval[1];
517
return PdistVL2Dfl(mval2, v1, v2);
520
static EditEdge *findnearestedge_f(short *dist)
522
EditMesh *em = G.editMesh;
523
EditEdge *closest, *eed;
525
short mval[2], distance;
527
if(em->edges.first==NULL) return NULL;
528
else eed= em->edges.first;
530
calc_meshverts_ext_f2(); /* sets/clears (eve->f & 2) for vertices that aren't visible */
532
getmouseco_areawin(mval);
535
/*compare the distance to the rest of the edges and find the closest one*/
538
/* Are both vertices of the edge ofscreen or either of them hidden? then don't select the edge*/
539
if( !((eed->v1->f & 2) && (eed->v2->f & 2)) && eed->h==0){
541
distance= dist_mval_edge(mval, eed);
542
if(eed->f & SELECT) distance+=5;
543
if(distance < *dist) {
552
for(eve=em->verts.first; eve; eve=eve->next){
559
/* backbuffer version */
560
EditEdge *findnearestedge(short *dist)
562
if(G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT)) {
566
short mval[2], distance=255;
568
getmouseco_areawin(mval);
571
buf= read_backbuf(mval[0]-25, mval[1]-25, mval[0]+24, mval[1]+24);
573
index= sample_backbuf_rect(buf, 50, em_solidoffs, em_wireoffs, &distance); // global, set in drawobject.c
575
if(distance < *dist) {
576
if(index>0 && index<=em_wireoffs-em_solidoffs) {
577
for(eed= G.editMesh->edges.first; eed; eed= eed->next, a++)
580
if(eed) *dist= distance;
586
else return findnearestedge_f(dist);
590
static EditFace *findnearestface_f(short *dist)
592
static EditFace *acto= NULL;
593
EditMesh *em = G.editMesh;
594
/* if selected the faces with flag==1 get a disadvantage */
595
EditFace *efa, *act=NULL;
598
if(em->faces.first==NULL) return NULL;
601
calc_mesh_facedots_ext();
603
/* we count from acto->next to last, and from first to acto */
604
/* does acto exist? */
605
efa= em->faces.first;
610
if(efa==NULL) acto= em->faces.first;
612
/* is there an indicated face? part 1 */
613
getmouseco_areawin(mval);
616
if(efa->h==0 && efa->fgonf!=EM_FGON) {
617
temp= abs(mval[0]- efa->xs)+ abs(mval[1]- efa->ys);
625
/* is there an indicated face? part 2 */
627
efa= em->faces.first;
629
if(efa->h==0 && efa->fgonf!=EM_FGON) {
630
temp= abs(mval[0]- efa->xs)+ abs(mval[1]- efa->ys);
635
if(efa== acto) break;
645
static EditFace *findnearestface(short *dist)
647
if(G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT)) {
650
short mval[2], distance;
652
calc_mesh_facedots_ext(); // shouldnt be needed each click
653
getmouseco_areawin(mval);
656
index= sample_backbuf(mval[0], mval[1]);
658
if(index && index<=em_solidoffs) {
659
for(efa= G.editMesh->faces.first; efa; efa= efa->next, a++) if(index==a) break;
661
distance= abs(mval[0]- efa->xs)+ abs(mval[1]- efa->ys);
663
if(G.scene->selectmode == SCE_SELECT_FACE || distance<*dist) { // only faces, no dist check
672
else return findnearestface_f(dist);
675
/* for interactivity, frontbuffer draw in current window */
676
static void unified_select_draw(EditVert *eve, EditEdge *eed, EditFace *efa)
679
DerivedMesh *dm = mesh_get_cage_derived(G.obedit, &dmNeedsFree);
681
glDrawBuffer(GL_FRONT);
685
mymultmatrix(G.obedit->obmat);
689
if(G.scene->selectmode & SCE_SELECT_VERTEX) {
690
glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE));
692
if(efa->f & SELECT) BIF_ThemeColor(TH_VERTEX_SELECT);
693
else BIF_ThemeColor(TH_VERTEX);
696
bglVertex3fv(efa->v1->co);
697
bglVertex3fv(efa->v2->co);
698
bglVertex3fv(efa->v3->co);
699
if(efa->v4) bglVertex3fv(efa->v4->co);
703
if(G.scene->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_FACE)) {
705
BIF_ThemeColor((efa->f & SELECT)?TH_EDGE_SELECT:TH_WIRE);
707
dm->drawMappedEdgeEM(dm, efa->e1);
708
dm->drawMappedEdgeEM(dm, efa->e2);
709
dm->drawMappedEdgeEM(dm, efa->e3);
711
dm->drawMappedEdgeEM(dm, efa->e4);
716
if(G.scene->selectmode & SCE_SELECT_FACE) {
718
glPointSize(BIF_GetThemeValuef(TH_FACEDOT_SIZE));
719
BIF_ThemeColor((efa->f & SELECT)?TH_FACE_DOT:TH_WIRE);
722
bglVertex3fv(efa->cent);
729
if(G.scene->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_FACE)) {
730
BIF_ThemeColor((eed->f & SELECT)?TH_EDGE_SELECT:TH_WIRE);
732
dm->drawMappedEdgeEM(dm, eed);
734
if(G.scene->selectmode & SCE_SELECT_VERTEX) {
736
glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE));
738
BIF_ThemeColor((eed->f & SELECT)?TH_VERTEX_SELECT:TH_VERTEX);
741
dm->getMappedVertCoEM(dm, eed->v1, co);
744
dm->getMappedVertCoEM(dm, eed->v2, co);
750
if(G.scene->selectmode & SCE_SELECT_VERTEX) {
752
glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE));
754
BIF_ThemeColor((eve->f & SELECT)?TH_VERTEX_SELECT:TH_VERTEX);
757
dm->getMappedVertCoEM(dm, eve, co);
767
glDrawBuffer(GL_BACK);
769
/* signal that frontbuf differs from back */
770
curarea->win_swap= WIN_FRONT_OK;
778
/* best distance based on screen coords.
779
use g.scene->selectmode to define how to use
780
selected vertices and edges get disadvantage
781
return 1 if found one
783
static int unified_findnearest(EditVert **eve, EditEdge **eed, EditFace **efa)
791
if(G.scene->selectmode & SCE_SELECT_VERTEX)
792
*eve= findnearestvert(&dist, SELECT);
793
if(G.scene->selectmode & SCE_SELECT_FACE)
794
*efa= findnearestface(&dist);
796
dist-= 20; // since edges select lines, we give dots advantage of 20 pix
797
if(G.scene->selectmode & SCE_SELECT_EDGE)
798
*eed= findnearestedge(&dist);
800
/* return only one of 3 pointers, for frontbuffer redraws */
802
*efa= NULL; *eve= NULL;
808
return (*eve || *eed || *efa);
811
/* **************** LOOP SELECTS *************** */
813
/* selects quads in loop direction of indicated edge */
814
/* only flush over edges with valence <= 2 */
815
static void faceloop_select(EditEdge *startedge, int select)
817
EditMesh *em = G.editMesh;
822
/* in eed->f1 we put the valence (amount of faces in edge) */
823
/* in eed->f2 we put tagged flag as correct loop */
824
/* in efa->f1 we put tagged flag as correct to select */
826
for(eed= em->edges.first; eed; eed= eed->next) {
830
for(efa= em->faces.first; efa; efa= efa->next) {
836
if(efa->e4) efa->e4->f1++;
846
for(efa= em->faces.first; efa; efa= efa->next) {
847
if(efa->e4 && efa->f1==0) { // not done quad
848
if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { // valence ok
850
// if edge tagged, select opposing edge and mark face ok
856
else if(efa->e2->f2) {
876
/* (de)select the faces */
877
for(efa= em->faces.first; efa; efa= efa->next) {
878
if(efa->f1) EM_select_face(efa, select);
883
/* helper for edgeloop_select, checks for eed->f2 tag in faces */
884
static int edge_not_in_tagged_face(EditEdge *eed)
886
EditMesh *em = G.editMesh;
889
for(efa= em->faces.first; efa; efa= efa->next) {
891
if(efa->e1==eed || efa->e2==eed || efa->e3==eed || efa->e4==eed) { // edge is in face
892
if(efa->e1->f2 || efa->e2->f2 || efa->e3->f2 || (efa->e4 && efa->e4->f2)) { // face is tagged
901
/* selects or deselects edges that:
902
- if edges has 2 faces:
903
- has vertices with valence of 4
904
- not shares face with previous edge
905
- if edge has 1 face:
906
- has vertices with valence 4
907
- not shares face with previous edge
908
- but also only 1 face
910
- has vertices with valence 2
912
static void edgeloop_select(EditEdge *starteed, int select)
914
EditMesh *em = G.editMesh;
920
/* in f1 we put the valence (amount of edges in a vertex, or faces in edge) */
921
/* in eed->f2 and efa->f1 we put tagged flag as correct loop */
922
for(eve= em->verts.first; eve; eve= eve->next) {
926
for(eed= em->edges.first; eed; eed= eed->next) {
929
if((eed->h & 1)==0) { // fgon edges add to valence too
930
eed->v1->f1++; eed->v2->f1++;
933
for(efa= em->faces.first; efa; efa= efa->next) {
939
if(efa->e4) efa->e4->f1++;
943
/* looped edges & vertices get tagged f2 */
945
if(starteed->v1->f1<5) starteed->v1->f2= 1;
946
if(starteed->v2->f1<5) starteed->v2->f2= 1;
947
/* sorry, first edge isnt even ok */
948
if(starteed->v1->f2==0 && starteed->v2->f2==0) looking= 0;
953
/* find correct valence edges which are not tagged yet, but connect to tagged one */
954
for(eed= em->edges.first; eed; eed= eed->next) {
955
if(eed->h==0 && eed->f2==0) { // edge not hidden, not tagged
956
if( (eed->v1->f1<5 && eed->v1->f2) || (eed->v2->f1<5 && eed->v2->f2)) { // valence of vertex OK, and is tagged
957
/* new edge is not allowed to be in face with tagged edge */
958
if(edge_not_in_tagged_face(eed)) {
959
if(eed->f1==starteed->f1) { // same amount of faces
962
if(eed->v2->f1<5) eed->v2->f2= 1;
963
if(eed->v1->f1<5) eed->v1->f2= 1;
970
/* and we do the select */
971
for(eed= em->edges.first; eed; eed= eed->next) {
972
if(eed->f2) EM_select_edge(eed, select);
976
/* ***************** MAIN MOUSE SELECTION ************** */
978
// just to have the functions nice together
979
static void mouse_mesh_loop(void)
984
eed= findnearestedge(&dist);
987
if((G.qual & LR_SHIFTKEY)==0) EM_clear_flag_all(SELECT);
989
if((eed->f & SELECT)==0) EM_select_edge(eed, 1);
990
else if(G.qual & LR_SHIFTKEY) EM_select_edge(eed, 0);
992
if(G.scene->selectmode & SCE_SELECT_FACE) {
993
faceloop_select(eed, eed->f & SELECT);
996
edgeloop_select(eed, eed->f & SELECT);
999
/* frontbuffer draw of last selected only */
1000
unified_select_draw(NULL, eed, NULL);
1002
EM_selectmode_flush();
1005
allqueue(REDRAWVIEW3D, 0);
1010
/* here actual select happens */
1011
void mouse_mesh(void)
1017
if(G.qual & LR_ALTKEY) mouse_mesh_loop();
1018
else if(unified_findnearest(&eve, &eed, &efa)) {
1020
if((G.qual & LR_SHIFTKEY)==0) EM_clear_flag_all(SELECT);
1024
if( (efa->f & SELECT)==0 ) {
1025
EM_select_face_fgon(efa, 1);
1027
else if(G.qual & LR_SHIFTKEY) {
1028
EM_select_face_fgon(efa, 0);
1032
if((eed->f & SELECT)==0) {
1033
EM_select_edge(eed, 1);
1035
else if(G.qual & LR_SHIFTKEY) {
1036
EM_select_edge(eed, 0);
1040
if((eve->f & SELECT)==0) eve->f |= SELECT;
1041
else if(G.qual & LR_SHIFTKEY) eve->f &= ~SELECT;
1044
/* frontbuffer draw of last selected only */
1045
unified_select_draw(eve, eed, efa);
1047
EM_selectmode_flush();
1050
allqueue(REDRAWVIEW3D, 0);
1053
rightmouse_transform();
1057
static void selectconnectedAll(void)
1059
EditMesh *em = G.editMesh;
1062
short done=1, toggle=0;
1064
if(em->edges.first==0) return;
1070
if(toggle & 1) eed= em->edges.first;
1071
else eed= em->edges.last;
1077
if(v1->f & SELECT) {
1078
if( (v2->f & SELECT)==0 ) {
1083
else if(v2->f & SELECT) {
1084
if( (v1->f & SELECT)==0 ) {
1090
if(toggle & 1) eed= eed->next;
1091
else eed= eed->prev;
1095
/* now use vertex select flag to select rest */
1100
allqueue(REDRAWVIEW3D, 0);
1101
BIF_undo_push("Select Connected (All)");
1104
void selectconnected_mesh(int qual)
1106
EditMesh *em = G.editMesh;
1107
EditVert *eve, *v1, *v2;
1110
short done=1, sel, toggle=0;
1112
if(em->edges.first==0) return;
1114
if(qual & LR_CTRLKEY) {
1115
selectconnectedAll();
1120
if( unified_findnearest(&eve, &eed, &efa)==0 ) {
1121
error("Nothing indicated ");
1126
if(qual & LR_SHIFTKEY) sel=0;
1128
/* clear test flags */
1129
for(v1= em->verts.first; v1; v1= v1->next) v1->f1= 0;
1131
/* start vertex/face/edge */
1133
else if(eed) eed->v1->f1= eed->v2->f1= 1;
1134
else efa->v1->f1= efa->v2->f1= efa->v3->f1= 1;
1136
/* set flag f1 if affected */
1141
if(toggle & 1) eed= em->edges.first;
1142
else eed= em->edges.last;
1149
if(v1->f1 && v2->f1==0) {
1153
else if(v1->f1==0 && v2->f1) {
1159
if(toggle & 1) eed= eed->next;
1160
else eed= eed->prev;
1164
/* now use vertex f1 flag to select/deselect */
1165
for(eed= em->edges.first; eed; eed= eed->next) {
1166
if(eed->v1->f1 && eed->v2->f1)
1167
EM_select_edge(eed, sel);
1169
for(efa= em->faces.first; efa; efa= efa->next) {
1170
if(efa->v1->f1 && efa->v2->f1 && efa->v3->f1 && (efa->v4==NULL || efa->v4->f1))
1171
EM_select_face(efa, sel);
1173
/* no flush needed, connected geometry is done */
1177
allqueue(REDRAWVIEW3D, 0);
1178
BIF_undo_push("Select Linked");
1182
/* swap is 0 or 1, if 1 it hides not selected */
1183
void hide_mesh(int swap)
1185
EditMesh *em = G.editMesh;
1191
if(G.obedit==0) return;
1193
/* hide happens on least dominant select mode, and flushes up, not down! (helps preventing errors in subsurf) */
1194
/* - vertex hidden, always means edge is hidden too
1195
- edge hidden, always means face is hidden too
1196
- face hidden, only set face hide
1197
- then only flush back down what's absolute hidden
1199
if(G.scene->selectmode & SCE_SELECT_VERTEX) {
1200
for(eve= em->verts.first; eve; eve= eve->next) {
1201
if((eve->f & SELECT)!=swap) {
1208
for(eed= em->edges.first; eed; eed= eed->next) {
1209
if(eed->v1->h || eed->v2->h) {
1215
for(efa= em->faces.first; efa; efa= efa->next) {
1216
if(efa->e1->h || efa->e2->h || efa->e3->h || (efa->e4 && efa->e4->h)) {
1222
else if(G.scene->selectmode & SCE_SELECT_EDGE) {
1224
for(eed= em->edges.first; eed; eed= eed->next) {
1225
if((eed->f & SELECT)!=swap) {
1227
EM_select_edge(eed, 0);
1231
for(efa= em->faces.first; efa; efa= efa->next) {
1232
if(efa->e1->h || efa->e2->h || efa->e3->h || (efa->e4 && efa->e4->h)) {
1240
for(efa= em->faces.first; efa; efa= efa->next) {
1241
if((efa->f & SELECT)!=swap) {
1243
EM_select_face(efa, 0);
1248
/* flush down, only whats 100% hidden */
1249
for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
1250
for(eed= em->edges.first; eed; eed= eed->next) eed->f1= 0;
1252
if(G.scene->selectmode & SCE_SELECT_FACE) {
1253
for(efa= em->faces.first; efa; efa= efa->next) {
1254
if(efa->h) a= 1; else a= 2;
1258
if(efa->e4) efa->e4->f1 |= a;
1262
if(G.scene->selectmode >= SCE_SELECT_EDGE) {
1263
for(eed= em->edges.first; eed; eed= eed->next) {
1264
if(eed->f1==1) eed->h |= 1;
1265
if(eed->h & 1) a= 1; else a= 2;
1271
if(G.scene->selectmode >= SCE_SELECT_VERTEX) {
1272
for(eve= em->verts.first; eve; eve= eve->next) {
1273
if(eve->f1==1) eve->h= 1;
1277
allqueue(REDRAWVIEW3D, 0);
1278
makeDispList(G.obedit);
1279
BIF_undo_push("Hide");
1283
void reveal_mesh(void)
1285
EditMesh *em = G.editMesh;
1290
if(G.obedit==0) return;
1292
for(eve= em->verts.first; eve; eve= eve->next) {
1298
for(eed= em->edges.first; eed; eed= eed->next) {
1301
if(G.scene->selectmode & SCE_SELECT_VERTEX);
1302
else EM_select_edge(eed, 1);
1305
for(efa= em->faces.first; efa; efa= efa->next) {
1308
if(G.scene->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_VERTEX));
1309
else EM_select_face(efa, 1);
1313
EM_fgon_flags(); // redo flags and indices for fgons
1314
EM_selectmode_flush();
1316
allqueue(REDRAWVIEW3D, 0);
1317
makeDispList(G.obedit);
1318
BIF_undo_push("Reveal");
1321
void select_non_manifold(void)
1323
EditMesh *em = G.editMesh;
1328
/* Selects isolated verts, and edges that do not have 2 neighboring
1332
if(G.scene->selectmode==SCE_SELECT_FACE) {
1333
error("Doesn't work in face selection mode");
1337
eve= em->verts.first;
1339
/* this will count how many edges are connected
1345
eed= em->edges.first;
1347
/* this will count how many faces are connected to
1350
/* increase edge count for verts */
1356
efa= em->faces.first;
1358
/* increase face count for edges */
1367
/* select verts that are attached to an edge that does not
1368
* have 2 neighboring faces */
1369
eed= em->edges.first;
1371
if (eed->h==0 && eed->f1 != 2) {
1372
EM_select_edge(eed, 1);
1377
/* select isolated verts */
1378
eve= em->verts.first;
1381
if (!eve->h) eve->f |= SELECT;
1387
addqueue(curarea->win, REDRAW, 0);
1388
BIF_undo_push("Select Non Manifold");
1391
void selectswap_mesh(void) /* UI level */
1393
EditMesh *em = G.editMesh;
1398
if(G.scene->selectmode & SCE_SELECT_VERTEX) {
1400
for(eve= em->verts.first; eve; eve= eve->next) {
1402
if(eve->f & SELECT) eve->f &= ~SELECT;
1403
else eve->f|= SELECT;
1407
else if(G.scene->selectmode & SCE_SELECT_EDGE) {
1408
for(eed= em->edges.first; eed; eed= eed->next) {
1410
EM_select_edge(eed, !(eed->f & SELECT));
1415
for(efa= em->faces.first; efa; efa= efa->next) {
1417
EM_select_face(efa, !(efa->f & SELECT));
1422
EM_selectmode_flush();
1425
allqueue(REDRAWVIEW3D, 0);
1427
BIF_undo_push("Select Swap");
1431
void deselectall_mesh(void) /* this toggles!!!, UI level */
1434
if(G.obedit->lay & G.vd->lay) {
1436
if( EM_nvertices_selected() ) {
1437
EM_clear_flag_all(SELECT);
1438
BIF_undo_push("Deselect All");
1441
EM_set_flag_all(SELECT);
1442
BIF_undo_push("Select All");
1446
allqueue(REDRAWVIEW3D, 0);
1450
void select_more(void)
1452
EditMesh *em = G.editMesh;
1457
for(eve= em->verts.first; eve; eve= eve->next) {
1458
if(eve->f & SELECT) eve->f1= 1;
1462
/* set f1 flags in vertices to select 'more' */
1463
for(eed= em->edges.first; eed; eed= eed->next) {
1465
if (eed->v1->f & SELECT)
1467
if (eed->v2->f & SELECT)
1472
/* new selected edges, but not in facemode */
1473
if(G.scene->selectmode <= SCE_SELECT_EDGE) {
1475
for(eed= em->edges.first; eed; eed= eed->next) {
1477
if(eed->v1->f1 && eed->v2->f1) EM_select_edge(eed, 1);
1481
/* new selected faces */
1482
for(efa= em->faces.first; efa; efa= efa->next) {
1484
if(efa->v1->f1 && efa->v2->f1 && efa->v3->f1 && (efa->v4==NULL || efa->v4->f1))
1485
EM_select_face(efa, 1);
1490
addqueue(curarea->win, REDRAW, 0);
1491
BIF_undo_push("Select More");
1494
void select_less(void)
1496
EditMesh *em = G.editMesh;
1500
if(G.scene->selectmode <= SCE_SELECT_EDGE) {
1501
/* eed->f1 == 1: edge with a selected and deselected vert */
1503
for(eed= em->edges.first; eed; eed= eed->next) {
1507
if ( !(eed->v1->f & SELECT) && (eed->v2->f & SELECT) )
1509
if ( (eed->v1->f & SELECT) && !(eed->v2->f & SELECT) )
1514
/* deselect edges with flag set */
1515
for(eed= em->edges.first; eed; eed= eed->next) {
1516
if (eed->h==0 && eed->f1 == 1) {
1517
EM_select_edge(eed, 0);
1520
EM_deselect_flush();
1524
/* deselect faces with 1 or more deselect edges */
1525
/* eed->f1 == mixed selection edge */
1526
for(eed= em->edges.first; eed; eed= eed->next) eed->f1= 0;
1528
for(efa= em->faces.first; efa; efa= efa->next) {
1530
if(efa->f & SELECT) {
1534
if(efa->e4) efa->e4->f1 |= 1;
1540
if(efa->e4) efa->e4->f1 |= 2;
1544
for(efa= em->faces.first; efa; efa= efa->next) {
1546
if(efa->e1->f1==3 || efa->e2->f1==3 || efa->e3->f1==3 || (efa->e4 && efa->e4->f1==3)) {
1547
EM_select_face(efa, 0);
1551
EM_selectmode_flush();
1556
allqueue(REDRAWVIEW3D, 0);
1560
void selectrandom_mesh(void) /* randomly selects a user-set % of vertices/edges/faces */
1562
EditMesh *em = G.editMesh;
1568
if(G.obedit==NULL || (G.obedit->lay & G.vd->lay)==0) return;
1570
/* Get the percentage of vertices to randomly select as 'randfac' */
1571
if(button(&randfac,0, 100,"Percentage:")==0) return;
1573
BLI_srand( BLI_rand() ); /* random seed */
1575
if(G.scene->selectmode & SCE_SELECT_VERTEX) {
1576
for(eve= em->verts.first; eve; eve= eve->next) {
1578
if ( (BLI_frand() * 100) < randfac)
1583
else if(G.scene->selectmode & SCE_SELECT_EDGE) {
1584
for(eed= em->edges.first; eed; eed= eed->next) {
1586
if ( (BLI_frand() * 100) < randfac)
1587
EM_select_edge(eed, 1);
1592
for(efa= em->faces.first; efa; efa= efa->next) {
1594
if ( (BLI_frand() * 100) < randfac)
1595
EM_select_face(efa, 1);
1600
EM_selectmode_flush();
1603
allqueue(REDRAWVIEW3D, 0);
1606
void editmesh_select_by_material(int index)
1608
EditMesh *em = G.editMesh;
1611
for (efa=em->faces.first; efa; efa= efa->next) {
1612
if (efa->mat_nr==index) {
1613
EM_select_face(efa, 1);
1617
EM_selectmode_flush();
1620
void editmesh_deselect_by_material(int index)
1622
EditMesh *em = G.editMesh;
1625
for (efa=em->faces.first; efa; efa= efa->next) {
1626
if (efa->mat_nr==index) {
1627
EM_select_face(efa, 0);
1631
EM_selectmode_flush();
1634
void EM_selectmode_menu(void)
1638
if(G.scene->selectmode & SCE_SELECT_VERTEX) pupmenu_set_active(1);
1639
else if(G.scene->selectmode & SCE_SELECT_EDGE) pupmenu_set_active(2);
1640
else pupmenu_set_active(3);
1642
val= pupmenu("Select Mode%t|Vertices|Edges|Faces");
1644
if(val==1) G.scene->selectmode= SCE_SELECT_VERTEX;
1645
else if(val==2) G.scene->selectmode= SCE_SELECT_EDGE;
1646
else G.scene->selectmode= SCE_SELECT_FACE;
1648
EM_selectmode_set(); // when mode changes
1649
allqueue(REDRAWVIEW3D, 1);
1653
/* ************************* SEAMS AND EDGES **************** */
1655
void editmesh_mark_seam(int clear)
1657
EditMesh *em= G.editMesh;
1659
Mesh *me= G.obedit->data;
1661
/* auto-enable seams drawing */
1663
if(!(G.f & G_DRAWSEAMS)) {
1665
allqueue(REDRAWBUTSEDIT, 0);
1668
me->medge= MEM_callocN(sizeof(MEdge), "fake mesh edge");
1672
eed= em->edges.first;
1674
if((eed->h==0) && (eed->f & SELECT)) {
1679
BIF_undo_push("Mark Seam");
1682
eed= em->edges.first;
1684
if((eed->h==0) && (eed->f & SELECT)) {
1689
BIF_undo_push("Clear Seam");
1692
allqueue(REDRAWVIEW3D, 0);
1698
ret= pupmenu("Edge Specials%t|Mark Seam %x1|Clear Seam %x2|Rotate Edge CW%x3|Rotate Edge CCW%x4");
1703
editmesh_mark_seam(0);
1706
editmesh_mark_seam(1);
1709
edge_rotate_selected(2);
1712
edge_rotate_selected(1);
1718
/* **************** NORMALS ************** */
1720
void righthandfaces(int select) /* makes faces righthand turning */
1722
EditMesh *em = G.editMesh;
1723
EditEdge *eed, *ed1, *ed2, *ed3, *ed4;
1724
EditFace *efa, *startvl;
1725
float maxx, nor[3], cent[3];
1726
int totsel, found, foundone, direct, turn, tria_nr;
1728
/* based at a select-connected to witness loose objects */
1730
/* count per edge the amount of faces */
1732
/* find the ultimate left, front, upper face (not manhattan dist!!) */
1733
/* also evaluate both triangle cases in quad, since these can be non-flat */
1735
/* put normal to the outside, and set the first direction flags in edges */
1737
/* then check the object, and set directions / direction-flags: but only for edges with 1 or 2 faces */
1738
/* this is in fact the 'select connected' */
1740
/* in case (selected) faces were not done: start over with 'find the ultimate ...' */
1744
eed= em->edges.first;
1746
eed->f2= 0; // edge direction
1747
eed->f1= 0; // counter
1751
/* count faces and edges */
1753
efa= em->faces.first;
1755
if(select==0 || (efa->f & SELECT) ) {
1761
if(efa->v4) efa->e4->f1++;
1769
/* from the outside to the inside */
1771
efa= em->faces.first;
1778
CalcCent3f(cent, efa->v1->co, efa->v2->co, efa->v3->co);
1779
cent[0]= cent[0]*cent[0] + cent[1]*cent[1] + cent[2]*cent[2];
1787
CalcCent3f(cent, efa->v1->co, efa->v3->co, efa->v4->co);
1788
cent[0]= cent[0]*cent[0] + cent[1]*cent[1] + cent[2]*cent[2];
1800
/* set first face correct: calc normal */
1803
CalcNormFloat(startvl->v1->co, startvl->v3->co, startvl->v4->co, nor);
1804
CalcCent3f(cent, startvl->v1->co, startvl->v3->co, startvl->v4->co);
1806
CalcNormFloat(startvl->v1->co, startvl->v2->co, startvl->v3->co, nor);
1807
CalcCent3f(cent, startvl->v1->co, startvl->v2->co, startvl->v3->co);
1809
/* first normal is oriented this way or the other */
1812
if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] > 0.0) flipface(startvl);
1815
if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] < 0.0) flipface(startvl);
1818
else if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] < 0.0) flipface(startvl);
1822
if(eed->v1==startvl->v1) eed->f2= 1;
1826
if(eed->v1==startvl->v2) eed->f2= 1;
1830
if(eed->v1==startvl->v3) eed->f2= 1;
1835
if(eed->v1==startvl->v4) eed->f2= 1;
1847
if(direct) efa= em->faces.first;
1848
else efa= em->faces.last;
1860
if(ed1->v1==efa->v1 && ed1->f2==1) turn= 1;
1861
if(ed1->v2==efa->v1 && ed1->f2==2) turn= 1;
1865
if(ed2->v1==efa->v2 && ed2->f2==1) turn= 1;
1866
if(ed2->v2==efa->v2 && ed2->f2==2) turn= 1;
1870
if(ed3->v1==efa->v3 && ed3->f2==1) turn= 1;
1871
if(ed3->v2==efa->v3 && ed3->f2==2) turn= 1;
1874
else if(ed4 && ed4->f2) {
1875
if(ed4->v1==efa->v4 && ed4->f2==1) turn= 1;
1876
if(ed4->v2==efa->v4 && ed4->f2==2) turn= 1;
1886
if(ed1->v1==efa->v1) ed1->f2= 2;
1888
if(ed2->v1==efa->v2) ed2->f2= 2;
1890
if(ed3->v1==efa->v3) ed3->f2= 2;
1893
if(ed4->v1==efa->v4) ed4->f2= 2;
1901
if(ed1->v1== efa->v1) ed1->f2= 1;
1903
if(ed2->v1==efa->v2) ed2->f2= 1;
1905
if(ed3->v1==efa->v3) ed3->f2= 1;
1908
if(ed4->v1==efa->v4) ed4->f2= 1;
1914
if(direct) efa= efa->next;
1915
else efa= efa->prev;
1921
recalc_editnormals();
1923
makeDispList(G.obedit);
1929
/* ********** ALIGN WITH VIEW **************** */
1932
static void editmesh_calc_selvert_center(float cent_r[3])
1934
EditMesh *em = G.editMesh;
1938
cent_r[0]= cent_r[1]= cent_r[0]= 0.0;
1940
for (eve= em->verts.first; eve; eve= eve->next) {
1941
if (eve->f & SELECT) {
1942
cent_r[0]+= eve->co[0];
1943
cent_r[1]+= eve->co[1];
1944
cent_r[2]+= eve->co[2];
1956
static int tface_is_selected(TFace *tf)
1958
return (!(tf->flag & TF_HIDE) && (tf->flag & TF_SELECT));
1961
static int faceselect_nfaces_selected(Mesh *me)
1965
for (i=0; i<me->totface; i++) {
1966
MFace *mf= ((MFace*) me->mface) + i;
1967
TFace *tf= ((TFace*) me->tface) + i;
1969
if (mf->v3 && tface_is_selected(tf))
1976
/* XXX, code for both these functions should be abstract,
1977
* then unified, then written for other things (like objects,
1978
* which would use same as vertices method), then added
1979
* to interface! Hoera! - zr
1981
void faceselect_align_view_to_selected(View3D *v3d, Mesh *me, int axis)
1983
if (!faceselect_nfaces_selected(me)) {
1984
error("No faces selected.");
1989
norm[0]= norm[1]= norm[2]= 0.0;
1990
for (i=0; i<me->totface; i++) {
1991
MFace *mf= ((MFace*) me->mface) + i;
1992
TFace *tf= ((TFace*) me->tface) + i;
1994
if (mf->v3 && tface_is_selected(tf)) {
1995
float *v1, *v2, *v3, fno[3];
1997
v1= me->mvert[mf->v1].co;
1998
v2= me->mvert[mf->v2].co;
1999
v3= me->mvert[mf->v3].co;
2001
float *v4= me->mvert[mf->v4].co;
2002
CalcNormFloat4(v1, v2, v3, v4, fno);
2004
CalcNormFloat(v1, v2, v3, fno);
2013
view3d_align_axis_to_vector(v3d, axis, norm);
2017
void editmesh_align_view_to_selected(View3D *v3d, int axis)
2019
EditMesh *em = G.editMesh;
2020
int nselverts= EM_nvertices_selected();
2024
error("No faces or vertices selected.");
2026
error("At least one face or three vertices must be selected.");
2028
} else if (EM_nfaces_selected()) {
2032
norm[0]= norm[1]= norm[2]= 0.0;
2033
for (efa= em->faces.first; efa; efa= efa->next) {
2034
if (faceselectedAND(efa, SELECT)) {
2036
if (efa->v4) CalcNormFloat4(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co, fno);
2037
else CalcNormFloat(efa->v1->co, efa->v2->co, efa->v3->co, fno);
2038
/* XXX, fixme, should be flipped intp a
2039
* consistent direction. -zr
2047
Mat4Mul3Vecfl(G.obedit->obmat, norm);
2048
view3d_align_axis_to_vector(v3d, axis, norm);
2050
float cent[3], norm[3];
2051
EditVert *eve, *leve= NULL;
2053
norm[0]= norm[1]= norm[2]= 0.0;
2054
editmesh_calc_selvert_center(cent);
2055
for (eve= em->verts.first; eve; eve= eve->next) {
2056
if (eve->f & SELECT) {
2059
CalcNormFloat(cent, leve->co, eve->co, tno);
2061
/* XXX, fixme, should be flipped intp a
2062
* consistent direction. -zr
2072
Mat4Mul3Vecfl(G.obedit->obmat, norm);
2073
view3d_align_axis_to_vector(v3d, axis, norm);
2077
/* **************** VERTEX DEFORMS *************** */
2079
void vertexsmooth(void)
2081
EditMesh *em = G.editMesh;
2084
float *adror, *adr, fac;
2088
if(G.obedit==0) return;
2091
eve= em->verts.first;
2093
if(eve->f & SELECT) teller++;
2096
if(teller==0) return;
2098
adr=adror= (float *)MEM_callocN(3*sizeof(float *)*teller, "vertsmooth");
2099
eve= em->verts.first;
2101
if(eve->f & SELECT) {
2102
eve->vn= (EditVert *)adr;
2109
eed= em->edges.first;
2111
if( (eed->v1->f & SELECT) || (eed->v2->f & SELECT) ) {
2112
fvec[0]= (eed->v1->co[0]+eed->v2->co[0])/2.0;
2113
fvec[1]= (eed->v1->co[1]+eed->v2->co[1])/2.0;
2114
fvec[2]= (eed->v1->co[2]+eed->v2->co[2])/2.0;
2116
if((eed->v1->f & SELECT) && eed->v1->f1<255) {
2118
VecAddf((float *)eed->v1->vn, (float *)eed->v1->vn, fvec);
2120
if((eed->v2->f & SELECT) && eed->v2->f1<255) {
2122
VecAddf((float *)eed->v2->vn, (float *)eed->v2->vn, fvec);
2128
eve= em->verts.first;
2130
if(eve->f & SELECT) {
2132
adr= (float *)eve->vn;
2133
fac= 0.5/(float)eve->f1;
2135
eve->co[0]= 0.5*eve->co[0]+fac*adr[0];
2136
eve->co[1]= 0.5*eve->co[1]+fac*adr[1];
2137
eve->co[2]= 0.5*eve->co[2]+fac*adr[2];
2145
recalc_editnormals();
2147
allqueue(REDRAWVIEW3D, 0);
2148
makeDispList(G.obedit);
2149
BIF_undo_push("Vertex Smooth");
2152
void vertexnoise(void)
2154
EditMesh *em = G.editMesh;
2158
float b2, ofs, vec[3];
2160
if(G.obedit==0) return;
2162
ma= give_current_material(G.obedit, G.obedit->actcol);
2163
if(ma==0 || ma->mtex[0]==0 || ma->mtex[0]->tex==0) {
2166
tex= ma->mtex[0]->tex;
2168
ofs= tex->turbul/200.0;
2170
eve= (struct EditVert *)em->verts.first;
2172
if(eve->f & SELECT) {
2174
if(tex->type==TEX_STUCCI) {
2176
b2= BLI_hnoise(tex->noisesize, eve->co[0], eve->co[1], eve->co[2]);
2177
if(tex->stype) ofs*=(b2*b2);
2178
vec[0]= 0.2*(b2-BLI_hnoise(tex->noisesize, eve->co[0]+ofs, eve->co[1], eve->co[2]));
2179
vec[1]= 0.2*(b2-BLI_hnoise(tex->noisesize, eve->co[0], eve->co[1]+ofs, eve->co[2]));
2180
vec[2]= 0.2*(b2-BLI_hnoise(tex->noisesize, eve->co[0], eve->co[1], eve->co[2]+ofs));
2182
VecAddf(eve->co, eve->co, vec);
2186
externtex(ma->mtex[0], eve->co, &tin, &dum, &dum, &dum, &dum);
2187
eve->co[2]+= 0.05*tin;
2193
recalc_editnormals();
2194
allqueue(REDRAWVIEW3D, 0);
2195
makeDispList(G.obedit);
2196
BIF_undo_push("Vertex Noise");
2199
void vertices_to_sphere(void)
2201
EditMesh *em = G.editMesh;
2204
float *curs, len, vec[3], cent[3], fac, facm, imat[3][3], bmat[3][3];
2211
if(button(&perc, 1, 100, "Percentage:")==0) return;
2216
Mat3CpyMat4(bmat, ob->obmat);
2217
Mat3Inv(imat, bmat);
2220
curs= give_cursor();
2221
cent[0]= curs[0]-ob->obmat[3][0];
2222
cent[1]= curs[1]-ob->obmat[3][1];
2223
cent[2]= curs[2]-ob->obmat[3][2];
2224
Mat3MulVecfl(imat, cent);
2228
eve= em->verts.first;
2230
if(eve->f & SELECT) {
2232
len+= VecLenf(cent, eve->co);
2238
if(len==0.0) len= 10.0;
2240
eve= em->verts.first;
2242
if(eve->f & SELECT) {
2243
vec[0]= eve->co[0]-cent[0];
2244
vec[1]= eve->co[1]-cent[1];
2245
vec[2]= eve->co[2]-cent[2];
2249
eve->co[0]= fac*(cent[0]+vec[0]*len) + facm*eve->co[0];
2250
eve->co[1]= fac*(cent[1]+vec[1]*len) + facm*eve->co[1];
2251
eve->co[2]= fac*(cent[2]+vec[2]*len) + facm*eve->co[2];
2257
recalc_editnormals();
2258
allqueue(REDRAWVIEW3D, 0);
2259
makeDispList(G.obedit);
2260
BIF_undo_push("To Sphere");