From ef1295e72360d054578d806aa16a4a5e0b45add3 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Sun, 27 Jan 2008 19:26:17 +0000 Subject: === Custom Transform Orientation === Adding the possibility to use 2 or 3 vertice to define an edge or face-like orientation. Adding the possibility to use 2 connected edges to define a face-like orientation. --- source/blender/include/transform.h | 4 + source/blender/src/transform.c | 347 +++++++++++++++++++++++++++++-------- 2 files changed, 278 insertions(+), 73 deletions(-) (limited to 'source') diff --git a/source/blender/include/transform.h b/source/blender/include/transform.h index 48e840a7128..8f6d9bd75c7 100644 --- a/source/blender/include/transform.h +++ b/source/blender/include/transform.h @@ -473,6 +473,10 @@ char handleNumInput(NumInput *n, unsigned short event); int manageObjectSpace(int confirm, int set); int manageMeshSpace(int confirm, int set); +/* Those two fill in mat and return non-zero on success */ +int createSpaceNormal(float mat[3][3], float normal[3]); +int createSpaceNormalTangent(float mat[3][3], float normal[3], float tangent[3]); + int addMatrixSpace(float mat[3][3], char name[]); int addObjectSpace(struct Object *ob); void applyTransformOrientation(void); diff --git a/source/blender/src/transform.c b/source/blender/src/transform.c index 1855ad3d147..7dd70e39544 100644 --- a/source/blender/src/transform.c +++ b/source/blender/src/transform.c @@ -204,127 +204,328 @@ int manageObjectSpace(int confirm, int set) { return addObjectSpace(base->object); } +/* return 1 on confirm */ +int confirmSpace(int set, char text[]) +{ + char menu[64]; + + if (set) { + sprintf(menu, "Custome Space %%t|Add and Use %s%%x1", text); + } + else { + sprintf(menu, "Custome Space %%t|Add %s%%x1", text); + } + + if (pupmenu(menu) == 1) { + return 1; + } + else { + return 0; + } +} + + int manageMeshSpace(int confirm, int set) { EditMesh *em = G.editMesh; - float mat[3][3], vec[3] = {0.0f, 0.0f, 1.0f}; - int index; + float mat[3][3]; char name[36] = ""; + int index; - if (G.scene->selectmode & SCE_SELECT_VERTEX && G.totvertsel == 1) { - EditVert *eve; - - if (confirm == 0) { - if (set && pupmenu("Custome Space %t|Add and Use Vertex%x1") != 1) { + /* Vertice Selected */ + if (G.scene->selectmode & SCE_SELECT_VERTEX && (G.totvertsel == 1 || G.totvertsel == 2 || G.totvertsel == 3)) { + if (G.totvertsel == 1) { + EditSelection *ese; + EditVert *eve = NULL; + float normal[3]; + + for (ese = em->selected.first; ese; ese = ese->next) + { + if ( ese->type == EDITVERT ) { + eve = (EditVert *)ese->data; + break; + } + } + + if (eve == NULL) + return -1; + + if (confirm == 0 && confirmSpace(set, "vertex") == 0) { return -1; } - else if (set == 0 && pupmenu("Custome Space %t|Add Vertex%x1") != 1) { + + VECCOPY(normal, eve->no); + Mat4Mul3Vecfl(G.obedit->obmat, normal); + + if (createSpaceNormal(mat, normal) == 0) { + error("Cannot use vertex with zero-length normal"); return -1; } + + strcpy(name, "Vertex"); } - - for(eve = em->verts.first; eve; eve= eve->next) { - if(eve->h == 0 && (eve->f & SELECT)) - break; + else if (G.totvertsel == 2) { + EditSelection *ese; + EditVert *v1 = NULL, *v2 = NULL; + float normal[3]; + + for (ese = em->selected.first; ese; ese = ese->next) + { + if ( ese->type == EDITVERT ) { + if (v1 == NULL) { + v1 = (EditVert *)ese->data; + } + else { + v2 = (EditVert *)ese->data; + break; + } + } + } + + if (v2 == NULL) + return -1; + + if (confirm == 0 && confirmSpace(set, "Edge") == 0) { + return -1; + } + + VecSubf(normal, v2->co, v1->co); + Mat4Mul3Vecfl(G.obedit->obmat, normal); + + if (createSpaceNormal(mat, normal) == 0) { + error("Cannot use zero-length edge"); + return -1; + } + + strcpy(name, "Edge"); } - - if (eve == NULL) - return -1; - - VECCOPY(mat[2], eve->no); - if (Normalize(mat[2]) == 0.0f) { - error("Cannot use vertex with zero-length normal"); - return -1; + else if (G.totvertsel == 3) { + EditSelection *ese; + EditVert *v1 = NULL, *v2 = NULL, *v3 = NULL; + float normal[3], tangent[3], cotangent[3]; + + for (ese = em->selected.first; ese; ese = ese->next) + { + if ( ese->type == EDITVERT ) { + if (v1 == NULL) { + v1 = (EditVert *)ese->data; + } + else if (v2 == NULL) { + v2 = (EditVert *)ese->data; + } + else { + v3 = (EditVert *)ese->data; + break; + } + } + } + + if (v3 == NULL) + return -1; + + if (confirm == 0 && confirmSpace(set, "Face") == 0) { + return -1; + } + + VecSubf(tangent, v2->co, v1->co); + VecSubf(cotangent, v3->co, v2->co); + Crossf(normal, cotangent, tangent); + + Mat4Mul3Vecfl(G.obedit->obmat, normal); + Mat4Mul3Vecfl(G.obedit->obmat, tangent); + + if (createSpaceNormal(mat, normal) == 0) { + error("Cannot use zero-area face"); + return -1; + } + + strcpy(name, "Face"); } - - strcpy(name, "Vertex"); + } - else if(G.scene->selectmode & SCE_SELECT_EDGE && G.totedgesel == 1) { - EditEdge *eed; - - if (confirm == 0) { - if (set && pupmenu("Custome Space %t|Add and Use Edge%x1") != 1) { + /* Edge Selected */ + else if(G.scene->selectmode & SCE_SELECT_EDGE && (G.totedgesel == 1 || G.totedgesel == 2)) { + if (G.totedgesel == 1) { + EditSelection *ese; + EditEdge *eed = NULL; + float normal[3]; + + for (ese = em->selected.first; ese; ese = ese->next) + { + if ( ese->type == EDITEDGE ) { + eed = (EditEdge *)ese->data; + break; + } + } + + if (eed == NULL) + return -1; + + if (confirm == 0 && confirmSpace(set, "Edge") == 0) { return -1; } - else if (set == 0 && pupmenu("Custome Space %t|Add Edge%x1") != 1) { + + VecSubf(normal, eed->v2->co, eed->v1->co); + Mat4Mul3Vecfl(G.obedit->obmat, normal); + + if (createSpaceNormal(mat, normal) == 0) { + error("Cannot use zero-length edge"); return -1; } + + strcpy(name, "Edge"); } - - for(eed = em->edges.first; eed; eed= eed->next) { - if(eed->h == 0 && (eed->f & SELECT)) - break; - } - - if (eed == NULL) - return -1; - - VecSubf(mat[2], eed->v2->co, eed->v1->co); - if (Normalize(mat[2]) == 0.0f) { - error("Cannot use zero-length edges"); - return -1; - } - - strcpy(name, "Edge"); - } - else if(G.scene->selectmode & SCE_SELECT_FACE && G.totfacesel == 1) { - EditFace *efa; - - if (confirm == 0) { - if (set && pupmenu("Custome Space %t|Add and Use Face%x1") != 1) { + /* If selected edges form a triangle */ + else if (G.totedgesel == 2 && G.totvertsel == 3) { + EditSelection *ese; + EditEdge *e1 = NULL, *e2 = NULL; + EditVert *v1 = NULL, *v2 = NULL, *v3 = NULL; + float normal[3], tangent[3], cotangent[3]; + + for (ese = em->selected.first; ese; ese = ese->next) + { + if ( ese->type == EDITEDGE ) { + if (e1 == NULL) { + e1 = (EditEdge *)ese->data; + } + else { + e2 = (EditEdge *)ese->data; + break; + } + } + } + + if (e1->v1 == e2->v1) { + v1 = e1->v2; + v2 = e1->v1; + v3 = e2->v2; + } + else if (e1->v1 == e2->v2) { + v1 = e1->v2; + v2 = e1->v1; + v3 = e2->v1; + } + else if (e1->v2 == e2->v1) { + v1 = e1->v1; + v2 = e1->v2; + v3 = e2->v2; + } + else if (e1->v2 == e2->v2) { + v1 = e1->v1; + v2 = e1->v2; + v3 = e2->v1; + } + + if (v1 == NULL) + return -1; + + if (confirm == 0 && confirmSpace(set, "Face") == 0) { return -1; } - else if (set == 0 && pupmenu("Custome Space %t|Add Face%x1") != 1) { + + VecSubf(tangent, v2->co, v1->co); + VecSubf(cotangent, v3->co, v2->co); + Crossf(normal, cotangent, tangent); + + Mat4Mul3Vecfl(G.obedit->obmat, normal); + Mat4Mul3Vecfl(G.obedit->obmat, tangent); + + if (createSpaceNormal(mat, normal) == 0) { + error("Cannot use zero-area face"); return -1; } + + strcpy(name, "Face"); } + + } + /* Face Selected */ + else if(G.scene->selectmode & SCE_SELECT_FACE && G.totfacesel == 1) { + EditSelection *ese; + EditFace *efa = NULL; + float normal[3], tangent[3]; - for(efa = em->faces.first; efa; efa= efa->next) { - if(efa->h == 0 && (efa->f & SELECT)) - break; + if (confirm == 0 && confirmSpace(set, "Face") == 0) { + return -1; + } + + for (ese = em->selected.first; ese; ese = ese->next) + { + if ( ese->type == EDITFACE ) { + efa = (EditFace *)ese->data; + break; + } } if (efa == NULL) return -1; - VECCOPY(mat[2], efa->n); - if (Normalize(mat[2]) == 0.0f) { - error("Cannot use face with zero-length normal"); + VECCOPY(normal, efa->n); + VecSubf(tangent, efa->v2->co, efa->v1->co); + + Mat4Mul3Vecfl(G.obedit->obmat, normal); + Mat4Mul3Vecfl(G.obedit->obmat, tangent); + + if (createSpaceNormalTangent(mat, normal, tangent) == 0) { + error("Cannot use zero-area face"); return -1; } - VecSubf(vec, efa->v2->co, efa->v1->co); - strcpy(name, "Face"); } else { - notice("You need to select only one vertex, edge or face"); return -1; } - /* Applying matrix for global space */ - Mat4Mul3Vecfl(G.obedit->obmat, mat[2]); - Mat4Mul3Vecfl(G.obedit->obmat, vec); + /* Input name */ + sbutton(name, 1, 35, "name: "); + + index = addMatrixSpace(mat, name); + return index; +} - /* Calculating the other axis */ +int createSpaceNormal(float mat[3][3], float normal[3]) +{ + float tangent[3] = {0.0f, 0.0f, 1.0f}; - Crossf(mat[0], mat[2], vec); - if (Normalize(mat[0]) == 0.0f) { - vec[0] = 1.0f; - vec[1] = vec[2] = 0.0f; - Crossf(mat[0], vec, mat[2]); + VECCOPY(mat[2], normal); + if (Normalize(mat[2]) == 0.0f) { + return 0; /* error return */ + } + + Crossf(mat[0], mat[2], tangent); + if (Inpf(mat[0], mat[0]) == 0.0f) { + tangent[0] = 1.0f; + tangent[1] = tangent[2] = 0.0f; + Crossf(mat[0], tangent, mat[2]); } Crossf(mat[1], mat[2], mat[0]); Mat3Ortho(mat); + + return 1; +} - /* Input name */ - sbutton(name, 1, 35, "name: "); +int createSpaceNormalTangent(float mat[3][3], float normal[3], float tangent[3]) +{ + VECCOPY(mat[2], normal); + if (Normalize(mat[2]) == 0.0f) { + return 0; /* error return */ + } - index = addMatrixSpace(mat, name); - return index; + Crossf(mat[0], mat[2], tangent); + if (Normalize(mat[0]) == 0.0f) { + return 0; /* error return */ + } + + Crossf(mat[1], mat[2], mat[0]); + + Mat3Ortho(mat); + + return 1; } + int addObjectSpace(Object *ob) { float mat[3][3]; char name[36] = ""; -- cgit v1.2.3