Welcome to mirror list, hosted at ThFree Co, Russian Federation.

BME_extrude.c « tools « bmesh « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 70baff2adf684ea0d66fd90ae5028fcd2ff20eb4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
/**
 *          BMESH EXTRUDE TOOL
 *
 * A rewrite of the old editmesh extrude code with the 
 * redundant parts broken into multiple functions
 * in an effort to reduce code. This works with multiple 
 * selection modes, and is intended to build the
 * extrusion in steps, depending on what elements are selected. 
 * Also decoupled the calculation of transform normal
 * and put it in UI where it probably is more appropriate 
 * for the moment.
 *
 * TODO:
 *  -Fit this into the new 'easy' API.
*/

void BME_extrude_verts(BME_Mesh *bm, GHash *vhash){
	BMVert *v, *nv = NULL;
	BMEdge *ne = NULL;
	float vec[3];

	//extrude the vertices
	for(v=BME_first(bm,BME_VERT);v;v=BME_next(bm,BME_VERT,v)){
		if(BME_SELECTED(v)){
			VECCOPY(vec,v->co);
			nv = BME_MV(bm,vec);
			nv->tflag2 =1; //mark for select
			ne = BME_ME(bm,v,nv);
			ne->tflag1 = 2; //mark as part of skirt 'ring'
			BLI_ghash_insert(vhash,v,nv);
			BME_VISIT(v);
		}
	}
}

void BME_extrude_skirt(BME_Mesh *bm, GHash *ehash){
	
	BMFace *nf=NULL;
	BMEdge *e, *l=NULL, *r=NULL, *edar[4], *ne;
	BMVert *v, *v1, *v2, *lv, *rv, *nv;

	for(e=BME_first(bm,BME_EDGE);e;e=BME_next(bm,BME_EDGE,e)){
		if(BME_SELECTED(e)){
			/*find one face incident upon e and use it for winding of new face*/
			if(e->l){
				v1 = e->l->next->v;
				v2 = e->l->v;
			}
			else{
				v1 = e->v1;
				v2 = e->v2;
			}
			
			if(v1->e->tflag1 == 2) l = v1->e;
			else l = BME_disk_next_edgeflag(v1->e, v1, 0, 2);
			if(v2->e->tflag1 == 2) r = v2->e;
			else r = BME_disk_next_edgeflag(v2->e, v2, 0, 2);
			
			lv = BME_edge_getothervert(l,v1);
			rv = BME_edge_getothervert(r,v2);
			
			ne = BME_ME(bm,lv,rv);
			ne->tflag2 = 1; //mark for select
			BLI_ghash_insert(ehash,e,ne);
			BME_VISIT(e);
			
			edar[0] = e;
			edar[1] = l;
			edar[2] = ne;
			edar[3] = r;
			BME_MF(bm,v1,v2,edar,4);
		}
	}
}

void BME_cap_skirt(BME_Mesh *bm, GHash *vhash, GHash *ehash){
	BMVert *v, *nv, *v1, *v2;
	BMEdge *e, **edar, *ne;
	BME_Loop *l;
	BMFace *f, *nf;
	MemArena *edgearena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
	float vec[3];
	int i, j, del_old =0;
	

	//loop through faces, then loop through their verts. If the verts havnt been visited yet, duplicate these.
	for(f=BME_first(bm,BME_POLY);f;f=BME_next(bm,BME_POLY,f)){
		if(BME_SELECTED(f)){
			l = f->loopbase;
			do{
				if(!(BME_ISVISITED(l->v))){ //interior vertex
					//dupe vert
					VECCOPY(vec,l->v->co);
					nv = BME_MV(bm,vec);
					BLI_ghash_insert(vhash,l->v,nv);
					//mark for delete
					l->v->tflag1 = 1;
					BME_VISIT(l->v); //we dont want to dupe it again.
				}
				l=l->next;
			}while(l!=f->lbase);
		}
	}
	
	//find out if we delete old faces or not. This needs to be improved a lot.....
	for(e=BME_first(bm,BME_EDGE);e;e=BME_next(bm,BME_EDGE,e)){
		if(BME_SELECTED(e) && e->l){
			i= BME_cycle_length(&(e->l->radial));
			if(i > 2){ 
				del_old = 1;
				break;
			}
		}
	}
	
	
	//build a new edge net, insert the new edges into the edge hash
	for(f=BME_first(bm,BME_POLY);f;f=BME_next(bm,BME_POLY,f)){
		if(BME_SELECTED(f)){
			l=f->loopbase;
			do{
				if(!(BME_ISVISITED(l->e))){ //interior edge
					//dupe edge
					ne = BME_ME(bm,BLI_ghash_lookup(vhash,l->e->v1),BLI_ghash_lookup(vhash,l->e->v2));
					BLI_ghash_insert(ehash,l->e,ne);
					//mark for delete
					l->e->tflag1 = 1;
					BME_VISIT(l->e); //we dont want to dupe it again.
				}
				l=l->next;
			}while(l!=f->lbase);
		}
	}
	
	//build new faces. grab edges from edge hash.
	for(f=BME_first(bm,BME_POLY);f;f=BME_next(bm,BME_POLY,f)){
		if(BME_SELECTED(f)){
			edar = MEM_callocN(sizeof(BMEdge*)*f->len,"Extrude array");
			 v1 = BLI_ghash_lookup(vhash,f->loopbase->v);
			v2 = BLI_ghash_lookup(vhash,f->loopbase->next->v);
			for(i=0,l=f->loopbase; i < f->len; i++,l=l->next){
				ne = BLI_ghash_lookup(ehash,l->e);
				edar[i] = ne;
			}
			nf=BME_MF(bm,v1,v2,edar,f->len);
			nf->tflag2 = 1; // mark for select
			if(del_old) f->tflag1 = 1; //mark for delete
			MEM_freeN(edar);
		}
	}
	BLI_memarena_free(edgearena);
}

/*unified extrude code*/
void BME_extrude_mesh(BME_Mesh *bm, int type){
	
	BMVert *v;
	BMEdge *e;
	BMFace *f;
	BME_Loop *l;
	
	struct GHash *vhash, *ehash;
	/*Build a hash table of old pointers and new pointers.*/
	vhash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
	ehash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
	
	BME_selectmode_flush(bm); //ensure consistent selection. contains hack to make sure faces get consistent select.
	if(type & BME_EXTRUDE_FACES){ //Find selected edges with more than one incident face that is also selected. deselect them.
		for(e=BME_first(bm,BME_EDGE);e;e=BME_next(bm,BME_EDGE,e)){
			int totsel=0;
			if(e->l){
				l= e->l;
				do{
					if(BME_SELECTED(l->f)) totsel++;
					l=BME_radial_nextloop(l);
				}while(l!=e->l);
			}
			if(totsel > 1) BME_select_edge(bm,e,0);
		}
	}

	/*another hack to ensure consistent selection.....*/
	for(e=BME_first(bm,BME_EDGE);e;e=BME_next(bm,BME_EDGE,e)){
		if(BME_SELECTED(e)) BME_select_edge(bm,e,1);
	}
	
	/*now we are ready to extrude*/
	if(type & BME_EXTRUDE_VERTS) BME_extrude_verts(bm,vhash);
	if(type & BME_EXTRUDE_EDGES) BME_extrude_skirt(bm,ehash);
	if(type & BME_EXTRUDE_FACES) BME_cap_skirt(bm,vhash,ehash);
	
	/*clear all selection flags*/
	BME_clear_flag_all(bm, SELECT|BME_VISITED);
	/*go through and fix up selection flags. Anything with BME_NEW should be selected*/
	for(f=BME_first(bm,BME_POLY);f;f=BME_next(bm,BME_POLY,f)){
		if(f->tflag2 == 1) BME_select_poly(bm,f,1);
		if(f->tflag1 == 1) BME_VISIT(f); //mark for delete
	}
	for(e=BME_first(bm,BME_EDGE);e;e=BME_next(bm,BME_EDGE,e)){
		if(e->tflag2 == 1) BME_select_edge(bm,e,1);
		if(e->tflag1 == 1) BME_VISIT(e); // mark for delete
	}
	for(v=BME_first(bm,BME_VERT);v;v=BME_next(bm,BME_VERT,v)){
		if(v->tflag2 == 1) BME_select_vert(bm,v,1);
		if(v->tflag1 == 1) BME_VISIT(v); //mark for delete
	}
	/*go through and delete all of our old faces , edges and vertices.*/
	remove_tagged_polys(bm);
	remove_tagged_edges(bm);
	remove_tagged_verts(bm);
	/*free our hash tables*/
	BLI_ghash_free(vhash,NULL, NULL); //check usage!
	BLI_ghash_free(ehash,NULL, NULL); //check usage!
	BME_selectmode_flush(bm);
}