Another attempt to make extrude deliver correct normals.

Rule is flipped when it doesn't extrude a 'volume', in that case normals
point outside based on extruding in direction of original normals.
This commit is contained in:
2005-04-15 20:29:08 +00:00
parent ca9e54b6aa
commit f6977da8e2

View File

@@ -457,27 +457,38 @@ void EM_hide_reset(void)
/* ******** EXTRUDE ********* */
static void set_edge_directions(void)
static void add_normal_aligned(float *nor, float *add)
{
if( INPR(nor, add) < 0.0 )
VecSubf(nor, nor, add);
else
VecAddf(nor, nor, add);
}
static void set_edge_directions_f2(int val)
{
EditMesh *em= G.editMesh;
EditFace *efa= em->faces.first;
/* edge directions are used for extrude, to detect direction of edges that make new faces */
/* we have set 'f2' flags in edges that need to get a direction set (e.g. get new face) */
/* the val argument differs... so we need it as arg */
while(efa) {
// non selected face
if(efa->f== 0) {
if(efa->e1->f) {
if(efa->f & SELECT) {
if(efa->e1->f2<val) {
if(efa->e1->v1 == efa->v1) efa->e1->dir= 0;
else efa->e1->dir= 1;
}
if(efa->e2->f) {
if(efa->e2->f2<val) {
if(efa->e2->v1 == efa->v2) efa->e2->dir= 0;
else efa->e2->dir= 1;
}
if(efa->e3->f) {
if(efa->e3->f2<val) {
if(efa->e3->v1 == efa->v3) efa->e3->dir= 0;
else efa->e3->dir= 1;
}
if(efa->e4 && efa->e4->f) {
if(efa->e4 && efa->e4->f2<val) {
if(efa->e4->v1 == efa->v4) efa->e4->dir= 0;
else efa->e4->dir= 1;
}
@@ -586,9 +597,12 @@ short extrudeflag_edges_indiv(short flag, float *nor)
EditFace *efa;
for(eve= em->verts.first; eve; eve= eve->next) eve->vn= NULL;
for(eed= em->edges.first; eed; eed= eed->next) eed->vn= NULL;
set_edge_directions();
for(eed= em->edges.first; eed; eed= eed->next) {
eed->vn= NULL;
eed->f2= ((eed->f & flag)!=0);
}
set_edge_directions_f2(2);
/* sample for next loop */
for(efa= em->faces.first; efa; efa= efa->next) {
@@ -609,7 +623,7 @@ short extrudeflag_edges_indiv(short flag, float *nor)
/* for transform */
if(eed->vn) {
efa= (EditFace *)eed->vn;
if(efa->f & SELECT) VecAddf(nor, nor, efa->n);
if(efa->f & SELECT) add_normal_aligned(nor, efa->n);
}
}
}
@@ -689,8 +703,8 @@ static short extrudeflag_edge(short flag, float *nor)
}
for(eed= em->edges.first; eed; eed= eed->next) {
eed->f1= 0; // amount of selected faces
eed->f2= 0; // amount of unselected faces
eed->f1= 0; // amount of unselected faces
eed->f2= 0; // amount of selected faces
if(eed->f & SELECT) {
eed->v1->f1= 1; // we call this 'selected vertex' now
eed->v2->f1= 1;
@@ -699,17 +713,17 @@ static short extrudeflag_edge(short flag, float *nor)
}
for(efa= em->faces.first; efa; efa= efa->next) {
if(efa->f & SELECT) {
efa->e1->f1++;
efa->e2->f1++;
efa->e3->f1++;
if(efa->e4) efa->e4->f1++;
}
else {
efa->e1->f2++;
efa->e2->f2++;
efa->e3->f2++;
if(efa->e4) efa->e4->f2++;
}
else {
efa->e1->f1++;
efa->e2->f1++;
efa->e3->f1++;
if(efa->e4) efa->e4->f1++;
}
// sample for next loop
efa->e1->vn= (EditVert *)efa;
efa->e2->vn= (EditVert *)efa;
@@ -717,33 +731,34 @@ static short extrudeflag_edge(short flag, float *nor)
if(efa->e4) efa->e4->vn= (EditVert *)efa;
}
set_edge_directions();
set_edge_directions_f2(2);
/* step 2: make new faces from edges */
for(eed= em->edges.last; eed; eed= eed->prev) {
if(eed->f & SELECT) {
if(eed->f1<2) {
if(eed->v1->vn==NULL)
eed->v1->vn= addvertlist(eed->v1->co);
if(eed->v2->vn==NULL)
eed->v2->vn= addvertlist(eed->v2->co);
if(eed->dir==1) addfacelist(eed->v1, eed->v2, eed->v2->vn, eed->v1->vn, (EditFace *)eed->vn, NULL);
else addfacelist(eed->v2, eed->v1, eed->v1->vn, eed->v2->vn, (EditFace *)eed->vn, NULL);
}
}
}
/* step 3a if *one* selected face has edge with unselected face; remove old selected faces */
/* step 1.5: if *one* selected face has edge with unselected face; remove old selected faces */
for(efa= em->faces.last; efa; efa= efa->prev) {
if(efa->f & SELECT) {
if(efa->e1->f2 || efa->e2->f2 || efa->e3->f2 || (efa->e4 && efa->e4->f2)) {
if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1 || (efa->e4 && efa->e4->f1)) {
del_old= 1;
break;
}
}
}
/* step 2: make new faces from edges */
for(eed= em->edges.last; eed; eed= eed->prev) {
if(eed->f & SELECT) {
if(eed->f2<2) {
if(eed->v1->vn==NULL)
eed->v1->vn= addvertlist(eed->v1->co);
if(eed->v2->vn==NULL)
eed->v2->vn= addvertlist(eed->v2->co);
/* if del_old, the preferred normal direction is exact opposite as for keep old faces */
if(eed->dir!=del_old) addfacelist(eed->v1, eed->v2, eed->v2->vn, eed->v1->vn, (EditFace *)eed->vn, NULL);
else addfacelist(eed->v2, eed->v1, eed->v1->vn, eed->v2->vn, (EditFace *)eed->vn, NULL);
}
}
}
/* step 3: make new faces from faces */
for(efa= em->faces.last; efa; efa= efa->prev) {
if(efa->f & SELECT) {
@@ -766,7 +781,7 @@ static short extrudeflag_edge(short flag, float *nor)
}
/* for transform */
VecAddf(nor, nor, efa->n);
add_normal_aligned(nor, efa->n);
}
}
@@ -914,7 +929,7 @@ short extrudeflag_vert(short flag, float *nor)
efa= efa->next;
}
set_edge_directions();
set_edge_directions_f2(3);
/* the current state now is:
eve->f1==1: loose selected vertex
@@ -960,6 +975,16 @@ short extrudeflag_vert(short flag, float *nor)
if del_old==0 the extrude creates a volume.
*/
/* find if we delete old faces */
for(eed= em->edges.last; eed; eed= eed->next) {
if( (eed->f2==1 || eed->f2==2) ) {
if(eed->f1==2) {
del_old= 1;
break;
}
}
}
eed= em->edges.last;
while(eed) {
nexted= eed->prev;
@@ -970,7 +995,8 @@ short extrudeflag_vert(short flag, float *nor)
if( (eed->f2==1 || eed->f2==2) ) {
if(eed->f1==2) del_old= 1;
if(eed->dir==1) efa2= addfacelist(eed->v1, eed->v2, eed->v2->vn, eed->v1->vn, NULL, NULL);
/* if del_old, the preferred normal direction is exact opposite as for keep old faces */
if(eed->dir!=del_old) efa2= addfacelist(eed->v1, eed->v2, eed->v2->vn, eed->v1->vn, NULL, NULL);
else efa2= addfacelist(eed->v2, eed->v1, eed->v1->vn, eed->v2->vn, NULL, NULL);
if(eed->vn) {
@@ -1020,7 +1046,7 @@ short extrudeflag_vert(short flag, float *nor)
efa2= addfacelist(v1, v2, v3, v4, efa, efa); /* hmm .. not sure about edges here */
/* for transform */
VecAddf(nor, nor, efa->n);
add_normal_aligned(nor, efa->n);
if(del_old) {
BLI_remlink(&em->faces, efa);