Cosmetic changes, renamed CTX_NOPET to CTX_NO_PET CKey during transform now clears the constraint.
857 lines
20 KiB
C
857 lines
20 KiB
C
/**
|
|
* $Id:
|
|
*
|
|
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version. The Blender
|
|
* Foundation also sells licenses for use in proprietary software under
|
|
* the Blender License. See http://www.blender.org/BL/ for information
|
|
* about this.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
* The Original Code is Copyright (C) 2004 by NaN Holding BV.
|
|
* All rights reserved.
|
|
*
|
|
* The Original Code is: all of this file.
|
|
*
|
|
* Contributor(s): none yet.
|
|
*
|
|
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
|
*/
|
|
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
#include "DNA_mesh_types.h"
|
|
#include "DNA_meshdata_types.h"
|
|
#include "DNA_object_types.h"
|
|
#include "DNA_scene_types.h"
|
|
#include "DNA_screen_types.h"
|
|
#include "DNA_view3d_types.h"
|
|
|
|
#include "BLI_blenlib.h"
|
|
#include "BLI_arithb.h"
|
|
#include "BLI_editVert.h"
|
|
|
|
#include "BKE_displist.h"
|
|
#include "BKE_global.h"
|
|
#include "BKE_library.h"
|
|
#include "BKE_mesh.h"
|
|
#include "BKE_object.h"
|
|
#include "BKE_utildefines.h"
|
|
|
|
#include "BIF_editmesh.h"
|
|
#include "BIF_graphics.h"
|
|
#include "BIF_interface.h"
|
|
#include "BIF_mywindow.h"
|
|
#include "BIF_screen.h"
|
|
#include "BIF_space.h"
|
|
#include "BIF_toolbox.h"
|
|
#include "BIF_transform.h"
|
|
|
|
#include "BDR_editobject.h"
|
|
|
|
#include "BSE_view.h"
|
|
#include "BSE_edit.h"
|
|
|
|
#include "mydevice.h"
|
|
#include "blendef.h"
|
|
|
|
#include "editmesh.h"
|
|
|
|
static float icovert[12][3] = {
|
|
{0,0,-200},
|
|
{144.72, -105.144,-89.443},
|
|
{-55.277, -170.128,-89.443},
|
|
{-178.885,0,-89.443},
|
|
{-55.277,170.128,-89.443},
|
|
{144.72,105.144,-89.443},
|
|
{55.277,-170.128,89.443},
|
|
{-144.72,-105.144,89.443},
|
|
{-144.72,105.144,89.443},
|
|
{55.277,170.128,89.443},
|
|
{178.885,0,89.443},
|
|
{0,0,200}
|
|
};
|
|
static short icoface[20][3] = {
|
|
{1,0,2},
|
|
{1,0,5},
|
|
{2,0,3},
|
|
{3,0,4},
|
|
{4,0,5},
|
|
{1,5,10},
|
|
{2,1,6},
|
|
{3,2,7},
|
|
{4,3,8},
|
|
{5,4,9},
|
|
{10,1,6},
|
|
{6,2,7},
|
|
{7,3,8},
|
|
{8,4,9},
|
|
{9,5,10},
|
|
{6,10,11},
|
|
{7,6,11},
|
|
{8,7,11},
|
|
{9,8,11},
|
|
{10,9,11}
|
|
};
|
|
|
|
void addvert_mesh(void)
|
|
{
|
|
EditMesh *em = G.editMesh;
|
|
EditVert *eve,*v1=0;
|
|
float *curs, mat[3][3],imat[3][3];
|
|
|
|
// hurms, yah...
|
|
if(G.scene->selectmode==SCE_SELECT_FACE) return;
|
|
|
|
TEST_EDITMESH
|
|
|
|
Mat3CpyMat4(mat, G.obedit->obmat);
|
|
Mat3Inv(imat, mat);
|
|
|
|
v1= em->verts.first;
|
|
while(v1) {
|
|
if(v1->f & SELECT) break;
|
|
v1= v1->next;
|
|
}
|
|
eve= v1;
|
|
|
|
/* prevent there are more selected */
|
|
EM_clear_flag_all(SELECT);
|
|
|
|
eve= addvertlist(0);
|
|
|
|
curs= give_cursor();
|
|
VECCOPY(eve->co, curs);
|
|
eve->xs= G.vd->mx;
|
|
eve->ys= G.vd->my;
|
|
VecSubf(eve->co, eve->co, G.obedit->obmat[3]);
|
|
|
|
Mat3MulVecfl(imat, eve->co);
|
|
eve->f= SELECT;
|
|
|
|
if(v1) {
|
|
addedgelist(v1, eve, NULL);
|
|
v1->f= 0;
|
|
}
|
|
countall();
|
|
|
|
BIF_undo_push("Add vertex");
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
makeDispList(G.obedit);
|
|
|
|
while(get_mbut()&R_MOUSE);
|
|
|
|
}
|
|
|
|
/* selected faces get hidden edges */
|
|
static void make_fgon(void)
|
|
{
|
|
EditMesh *em = G.editMesh;
|
|
EditFace *efa;
|
|
EditEdge *eed;
|
|
EditVert *eve;
|
|
float *nor=NULL; // reference
|
|
int done=0, ret;
|
|
|
|
ret= pupmenu("FGon %t|Make|Clear");
|
|
if(ret<1) return;
|
|
|
|
if(ret==2) {
|
|
for(efa= em->faces.first; efa; efa= efa->next) {
|
|
if(efa->f & SELECT) {
|
|
efa->fgonf= 0;
|
|
efa->e1->h &= ~EM_FGON;
|
|
efa->e2->h &= ~EM_FGON;
|
|
efa->e3->h &= ~EM_FGON;
|
|
if(efa->e4) efa->e4->h &= ~EM_FGON;
|
|
}
|
|
}
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
EM_fgon_flags(); // redo flags and indices for fgons
|
|
makeDispList(G.obedit);
|
|
BIF_undo_push("Clear FGon");
|
|
return;
|
|
}
|
|
|
|
/* tagging edges. rule is:
|
|
- edge used by exactly 2 selected faces
|
|
- no vertices allowed with only tagged edges (return)
|
|
- face normals are allowed to difffer
|
|
|
|
*/
|
|
for(eed= em->edges.first; eed; eed= eed->next) {
|
|
eed->f1= 0; // amount of selected
|
|
eed->f2= 0; // amount of unselected
|
|
}
|
|
|
|
for(efa= em->faces.first; efa; efa= efa->next) {
|
|
if(efa->f & SELECT) {
|
|
if(nor==NULL) nor= efa->n;
|
|
if(efa->e1->f1 < 3) efa->e1->f1++;
|
|
if(efa->e2->f1 < 3) efa->e2->f1++;
|
|
if(efa->e3->f1 < 3) efa->e3->f1++;
|
|
if(efa->e4 && efa->e4->f1 < 3) efa->e4->f1++;
|
|
}
|
|
else {
|
|
if(efa->e1->f2 < 3) efa->e1->f2++;
|
|
if(efa->e2->f2 < 3) efa->e2->f2++;
|
|
if(efa->e3->f2 < 3) efa->e3->f2++;
|
|
if(efa->e4 && efa->e4->f2 < 3) efa->e4->f2++;
|
|
}
|
|
}
|
|
// now eed->f1 becomes tagged edge
|
|
for(eed= em->edges.first; eed; eed= eed->next) {
|
|
if(eed->f1==2 && eed->f2==0) eed->f1= 1;
|
|
else eed->f1= 0;
|
|
}
|
|
|
|
// no vertices allowed with only tagged edges
|
|
for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
|
|
for(eed= em->edges.first; eed; eed= eed->next) {
|
|
if(eed->f1) {
|
|
eed->v1->f1 |= 1;
|
|
eed->v2->f1 |= 1;
|
|
}
|
|
else {
|
|
eed->v1->f1 |= 2;
|
|
eed->v2->f1 |= 2;
|
|
}
|
|
}
|
|
for(eve= em->verts.first; eve; eve= eve->next) {
|
|
if(eve->f1==1) break;
|
|
}
|
|
if(eve) {
|
|
error("Cannot make polygon with interior vertices");
|
|
return;
|
|
}
|
|
|
|
// check for faces
|
|
if(nor==NULL) {
|
|
error("No faces selected to make FGon");
|
|
return;
|
|
}
|
|
|
|
// and there we go
|
|
for(eed= em->edges.first; eed; eed= eed->next) {
|
|
if(eed->f1) {
|
|
eed->h |= EM_FGON;
|
|
done= 1;
|
|
}
|
|
}
|
|
|
|
if(done==0) {
|
|
error("Didn't find FGon to create");
|
|
}
|
|
else {
|
|
Mesh *me= G.obedit->data;
|
|
// signal to save edges with ngon flags
|
|
if(!me->medge)
|
|
me->medge= MEM_callocN(sizeof(MEdge), "fake mesh edge");
|
|
|
|
EM_fgon_flags(); // redo flags and indices for fgons
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
makeDispList(G.obedit);
|
|
BIF_undo_push("Make FGon");
|
|
}
|
|
}
|
|
|
|
/* precondition; 4 vertices selected, check for 4 edges and create face */
|
|
static EditFace *addface_from_edges(void)
|
|
{
|
|
EditMesh *em = G.editMesh;
|
|
EditEdge *eed, *eedar[4]={NULL, NULL, NULL, NULL};
|
|
EditVert *v1=NULL, *v2=NULL, *v3=NULL, *v4=NULL;
|
|
int a;
|
|
|
|
/* find the 4 edges */
|
|
for(eed= em->edges.first; eed; eed= eed->next) {
|
|
if(eed->f & SELECT) {
|
|
if(eedar[0]==NULL) eedar[0]= eed;
|
|
else if(eedar[1]==NULL) eedar[1]= eed;
|
|
else if(eedar[2]==NULL) eedar[2]= eed;
|
|
else eedar[3]= eed;
|
|
}
|
|
}
|
|
if(eedar[3]) {
|
|
/* first 2 points */
|
|
v1= eedar[0]->v1;
|
|
v2= eedar[0]->v2;
|
|
|
|
/* find the 2 edges connected to first edge */
|
|
for(a=1; a<4; a++) {
|
|
if( eedar[a]->v1 == v2) v3= eedar[a]->v2;
|
|
else if(eedar[a]->v2 == v2) v3= eedar[a]->v1;
|
|
else if( eedar[a]->v1 == v1) v4= eedar[a]->v2;
|
|
else if(eedar[a]->v2 == v1) v4= eedar[a]->v1;
|
|
}
|
|
|
|
/* verify if last edge exists */
|
|
if(v3 && v4) {
|
|
for(a=1; a<4; a++) {
|
|
if( eedar[a]->v1==v3 && eedar[a]->v2==v4) break;
|
|
if( eedar[a]->v2==v3 && eedar[a]->v1==v4) break;
|
|
}
|
|
if(a!=4) {
|
|
return addfacelist(v1, v2, v3, v4, NULL, NULL);
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void addedgeface_mesh(void)
|
|
{
|
|
EditMesh *em = G.editMesh;
|
|
EditVert *eve, *neweve[4];
|
|
EditEdge *eed;
|
|
EditFace *efa;
|
|
short amount=0;
|
|
|
|
if( (G.vd->lay & G.obedit->lay)==0 ) return;
|
|
|
|
/* how many selected ? */
|
|
if(G.scene->selectmode & SCE_SELECT_EDGE) {
|
|
/* in edge mode finding selected vertices means flushing down edge codes... */
|
|
/* can't make face with only edge selection info... */
|
|
EM_selectmode_set();
|
|
}
|
|
|
|
for(eve= em->verts.first; eve; eve= eve->next) {
|
|
if(eve->f & SELECT) {
|
|
amount++;
|
|
if(amount>4) break;
|
|
neweve[amount-1]= eve;
|
|
}
|
|
}
|
|
if(amount==2) {
|
|
eed= addedgelist(neweve[0], neweve[1], NULL);
|
|
EM_select_edge(eed, 1);
|
|
BIF_undo_push("Add edge");
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
makeDispList(G.obedit);
|
|
return;
|
|
}
|
|
else if(amount > 4) {
|
|
make_fgon();
|
|
return;
|
|
}
|
|
else if(amount<2) {
|
|
error("Incorrect number of vertices to make edge/face");
|
|
return;
|
|
}
|
|
|
|
efa= NULL; // check later
|
|
|
|
if(amount==3) {
|
|
if(exist_face(neweve[0], neweve[1], neweve[2], 0)==0) {
|
|
|
|
efa= addfacelist(neweve[0], neweve[1], neweve[2], 0, NULL, NULL);
|
|
EM_select_face(efa, 1);
|
|
}
|
|
else error("The selected vertices already form a face");
|
|
}
|
|
else if(amount==4) {
|
|
if(exist_face(neweve[0], neweve[1], neweve[2], neweve[3])==0) {
|
|
int tria= 0;
|
|
|
|
/* remove trias if they exist, 4 cases.... */
|
|
if(exist_face(neweve[0], neweve[1], neweve[2], NULL)) tria++;
|
|
if(exist_face(neweve[0], neweve[1], neweve[3], NULL)) tria++;
|
|
if(exist_face(neweve[0], neweve[2], neweve[3], NULL)) tria++;
|
|
if(exist_face(neweve[1], neweve[2], neweve[3], NULL)) tria++;
|
|
|
|
if(tria==2) join_triangles();
|
|
else {
|
|
|
|
/* if 4 edges exist, we just create the face, convex or not */
|
|
efa= addface_from_edges();
|
|
if(efa==NULL) {
|
|
/* the order of vertices can be anything, three cases to check */
|
|
if( convex(neweve[0]->co, neweve[1]->co, neweve[2]->co, neweve[3]->co) ) {
|
|
efa= addfacelist(neweve[0], neweve[1], neweve[2], neweve[3], NULL, NULL);
|
|
}
|
|
else if( convex(neweve[0]->co, neweve[2]->co, neweve[3]->co, neweve[1]->co) ) {
|
|
efa= addfacelist(neweve[0], neweve[2], neweve[3], neweve[1], NULL, NULL);
|
|
}
|
|
else if( convex(neweve[0]->co, neweve[2]->co, neweve[1]->co, neweve[3]->co) ) {
|
|
efa= addfacelist(neweve[0], neweve[2], neweve[1], neweve[3], NULL, NULL);
|
|
}
|
|
else error("The selected vertices form a concave quad");
|
|
}
|
|
}
|
|
|
|
}
|
|
else error("The selected vertices already form a face");
|
|
}
|
|
|
|
if(efa) { // now we're calculating direction of normal
|
|
float inp;
|
|
/* dot product view mat with normal, should give info! */
|
|
|
|
EM_select_face(efa, 1);
|
|
CalcNormFloat(efa->v1->co, efa->v2->co, efa->v3->co, efa->n);
|
|
|
|
inp= efa->n[0]*G.vd->viewmat[0][2] + efa->n[1]*G.vd->viewmat[1][2] + efa->n[2]*G.vd->viewmat[2][2];
|
|
|
|
if(inp < 0.0) flipface(efa);
|
|
BIF_undo_push("Add face");
|
|
}
|
|
|
|
countall();
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
makeDispList(G.obedit);
|
|
}
|
|
|
|
|
|
void adduplicate_mesh(void)
|
|
{
|
|
|
|
TEST_EDITMESH
|
|
|
|
waitcursor(1);
|
|
|
|
adduplicateflag(SELECT);
|
|
|
|
waitcursor(0);
|
|
countall();
|
|
Transform(TFM_TRANSLATION, CTX_NO_PET);
|
|
}
|
|
|
|
|
|
|
|
void add_primitiveMesh(int type)
|
|
{
|
|
EditMesh *em = G.editMesh;
|
|
Mesh *me;
|
|
EditVert *eve, *v1=NULL, *v2, *v3, *v4=NULL, *vtop, *vdown;
|
|
float *curs, d, dia, phi, phid, cent[3], vec[3], imat[3][3], mat[3][3];
|
|
float q[4], cmat[3][3], nor[3]= {0.0, 0.0, 0.0};
|
|
static short tot=32, seg=32, subdiv=2;
|
|
short a, b, ext=0, fill=0, totoud, newob=0;
|
|
char *undostr="Add Primitive";
|
|
|
|
if(G.scene->id.lib) return;
|
|
|
|
/* this function also comes from an info window */
|
|
if ELEM(curarea->spacetype, SPACE_VIEW3D, SPACE_INFO); else return;
|
|
if(G.vd==0) return;
|
|
|
|
/* if editmode exists for other type, it exits */
|
|
check_editmode(OB_MESH);
|
|
|
|
if(G.f & (G_VERTEXPAINT+G_FACESELECT+G_TEXTUREPAINT)) {
|
|
G.f &= ~(G_VERTEXPAINT+G_FACESELECT+G_TEXTUREPAINT);
|
|
setcursor_space(SPACE_VIEW3D, CURSOR_EDIT);
|
|
}
|
|
|
|
/* if no obedit: new object and enter editmode */
|
|
if(G.obedit==NULL) {
|
|
/* add_object actually returns an object ! :-)
|
|
But it also stores the added object struct in
|
|
G.scene->basact->object (BASACT->object) */
|
|
|
|
add_object_draw(OB_MESH);
|
|
|
|
G.obedit= BASACT->object;
|
|
|
|
where_is_object(G.obedit);
|
|
|
|
make_editMesh();
|
|
setcursor_space(SPACE_VIEW3D, CURSOR_EDIT);
|
|
newob= 1;
|
|
}
|
|
me= G.obedit->data;
|
|
|
|
/* deselectall */
|
|
EM_clear_flag_all(SELECT);
|
|
|
|
totoud= tot; /* store, and restore when cube/plane */
|
|
|
|
/* imat and centre and size */
|
|
Mat3CpyMat4(mat, G.obedit->obmat);
|
|
|
|
curs= give_cursor();
|
|
VECCOPY(cent, curs);
|
|
cent[0]-= G.obedit->obmat[3][0];
|
|
cent[1]-= G.obedit->obmat[3][1];
|
|
cent[2]-= G.obedit->obmat[3][2];
|
|
|
|
if(type!= 31) {
|
|
Mat3CpyMat4(imat, G.vd->viewmat);
|
|
Mat3MulVecfl(imat, cent);
|
|
Mat3MulMat3(cmat, imat, mat);
|
|
Mat3Inv(imat,cmat);
|
|
} else {
|
|
Mat3Inv(imat, mat);
|
|
}
|
|
|
|
/* ext==extrudeflag, tot==amount of vertices in basis */
|
|
|
|
switch(type) {
|
|
case 0: /* plane */
|
|
tot= 4;
|
|
ext= 0;
|
|
fill= 1;
|
|
if(newob) rename_id((ID *)G.obedit, "Plane");
|
|
if(newob) rename_id((ID *)me, "Plane");
|
|
undostr="Add Plane";
|
|
break;
|
|
case 1: /* cube */
|
|
tot= 4;
|
|
ext= 1;
|
|
fill= 1;
|
|
if(newob) rename_id((ID *)G.obedit, "Cube");
|
|
if(newob) rename_id((ID *)me, "Cube");
|
|
undostr="Add Cube";
|
|
break;
|
|
case 4: /* circle */
|
|
if(button(&tot,3,100,"Vertices:")==0) return;
|
|
ext= 0;
|
|
fill= 0;
|
|
if(newob) rename_id((ID *)G.obedit, "Circle");
|
|
if(newob) rename_id((ID *)me, "Circle");
|
|
undostr="Add Circle";
|
|
break;
|
|
case 5: /* cylinder */
|
|
if(button(&tot,3,100,"Vertices:")==0) return;
|
|
ext= 1;
|
|
fill= 1;
|
|
if(newob) rename_id((ID *)G.obedit, "Cylinder");
|
|
if(newob) rename_id((ID *)me, "Cylinder");
|
|
undostr="Add Cylinder";
|
|
break;
|
|
case 6: /* tube */
|
|
if(button(&tot,3,100,"Vertices:")==0) return;
|
|
ext= 1;
|
|
fill= 0;
|
|
if(newob) rename_id((ID *)G.obedit, "Tube");
|
|
if(newob) rename_id((ID *)me, "Tube");
|
|
undostr="Add Tube";
|
|
break;
|
|
case 7: /* cone */
|
|
if(button(&tot,3,100,"Vertices:")==0) return;
|
|
ext= 0;
|
|
fill= 1;
|
|
if(newob) rename_id((ID *)G.obedit, "Cone");
|
|
if(newob) rename_id((ID *)me, "Cone");
|
|
undostr="Add Cone";
|
|
break;
|
|
case 10: /* grid */
|
|
if(button(&tot,2,100,"X res:")==0) return;
|
|
if(button(&seg,2,100,"Y res:")==0) return;
|
|
if(newob) rename_id((ID *)G.obedit, "Grid");
|
|
if(newob) rename_id((ID *)me, "Grid");
|
|
undostr="Add Grid";
|
|
break;
|
|
case 11: /* UVsphere */
|
|
if(button(&seg,3,100,"Segments:")==0) return;
|
|
if(button(&tot,3,100,"Rings:")==0) return;
|
|
if(newob) rename_id((ID *)G.obedit, "Sphere");
|
|
if(newob) rename_id((ID *)me, "Sphere");
|
|
undostr="Add UV Sphere";
|
|
break;
|
|
case 12: /* Icosphere */
|
|
if(button(&subdiv,1,5,"Subdivision:")==0) return;
|
|
if(newob) rename_id((ID *)G.obedit, "Sphere");
|
|
if(newob) rename_id((ID *)me, "Sphere");
|
|
undostr="Add Ico Sphere";
|
|
break;
|
|
case 13: /* Monkey */
|
|
if(newob) rename_id((ID *)G.obedit, "Suzanne");
|
|
if(newob) rename_id((ID *)me, "Suzanne");
|
|
undostr="Add Monkey";
|
|
break;
|
|
}
|
|
|
|
dia= sqrt(2.0)*G.vd->grid;
|
|
d= -G.vd->grid;
|
|
phid= 2*M_PI/tot;
|
|
phi= .25*M_PI;
|
|
|
|
|
|
if(type<10) { /* all types except grid, sphere... */
|
|
if(ext==0 && type!=7) d= 0;
|
|
|
|
/* vertices */
|
|
vtop= vdown= v1= v2= 0;
|
|
for(b=0; b<=ext; b++) {
|
|
for(a=0; a<tot; a++) {
|
|
|
|
vec[0]= cent[0]+dia*sin(phi);
|
|
vec[1]= cent[1]+dia*cos(phi);
|
|
vec[2]= cent[2]+d;
|
|
|
|
Mat3MulVecfl(imat, vec);
|
|
eve= addvertlist(vec);
|
|
eve->f= SELECT;
|
|
if(a==0) {
|
|
if(b==0) v1= eve;
|
|
else v2= eve;
|
|
}
|
|
phi+=phid;
|
|
}
|
|
d= -d;
|
|
}
|
|
/* centre vertices */
|
|
if(fill && type>1) {
|
|
VECCOPY(vec,cent);
|
|
vec[2]-= -d;
|
|
Mat3MulVecfl(imat,vec);
|
|
vdown= addvertlist(vec);
|
|
if(ext || type==7) {
|
|
VECCOPY(vec,cent);
|
|
vec[2]-= d;
|
|
Mat3MulVecfl(imat,vec);
|
|
vtop= addvertlist(vec);
|
|
}
|
|
} else {
|
|
vdown= v1;
|
|
vtop= v2;
|
|
}
|
|
if(vtop) vtop->f= SELECT;
|
|
if(vdown) vdown->f= SELECT;
|
|
|
|
/* top and bottom face */
|
|
if(fill) {
|
|
if(tot==4 && (type==0 || type==1)) {
|
|
v3= v1->next->next;
|
|
if(ext) v4= v2->next->next;
|
|
|
|
addfacelist(v3, v1->next, v1, v3->next, NULL, NULL);
|
|
if(ext) addfacelist(v2, v2->next, v4, v4->next, NULL, NULL);
|
|
|
|
}
|
|
else {
|
|
v3= v1;
|
|
v4= v2;
|
|
for(a=1; a<tot; a++) {
|
|
addfacelist(vdown, v3, v3->next, 0, NULL, NULL);
|
|
v3= v3->next;
|
|
if(ext) {
|
|
addfacelist(vtop, v4, v4->next, 0, NULL, NULL);
|
|
v4= v4->next;
|
|
}
|
|
}
|
|
if(type>1) {
|
|
addfacelist(vdown, v3, v1, 0, NULL, NULL);
|
|
if(ext) addfacelist(vtop, v4, v2, 0, NULL, NULL);
|
|
}
|
|
}
|
|
}
|
|
else if(type==4) { /* we need edges for a circle */
|
|
v3= v1;
|
|
for(a=1;a<tot;a++) {
|
|
addedgelist(v3, v3->next, NULL);
|
|
v3= v3->next;
|
|
}
|
|
addedgelist(v3, v1, NULL);
|
|
}
|
|
/* side faces */
|
|
if(ext) {
|
|
v3= v1;
|
|
v4= v2;
|
|
for(a=1; a<tot; a++) {
|
|
addfacelist(v3, v3->next, v4->next, v4, NULL, NULL);
|
|
v3= v3->next;
|
|
v4= v4->next;
|
|
}
|
|
addfacelist(v3, v1, v2, v4, NULL, NULL);
|
|
}
|
|
else if(type==7) { /* cone */
|
|
v3= v1;
|
|
for(a=1; a<tot; a++) {
|
|
addfacelist(vtop, v3->next, v3, 0, NULL, NULL);
|
|
v3= v3->next;
|
|
}
|
|
addfacelist(vtop, v1, v3, 0, NULL, NULL);
|
|
}
|
|
|
|
if(type<2) tot= totoud;
|
|
|
|
}
|
|
else if(type==10) { /* grid */
|
|
/* clear flags */
|
|
eve= em->verts.first;
|
|
while(eve) {
|
|
eve->f= 0;
|
|
eve= eve->next;
|
|
}
|
|
dia= G.vd->grid;
|
|
/* one segment first: de X as */
|
|
phi= 1.0;
|
|
phid= 2.0/((float)tot-1);
|
|
for(a=0;a<tot;a++) {
|
|
vec[0]= cent[0]+dia*phi;
|
|
vec[1]= cent[1]- dia;
|
|
vec[2]= cent[2];
|
|
Mat3MulVecfl(imat,vec);
|
|
eve= addvertlist(vec);
|
|
eve->f= 1+2+4;
|
|
if (a) addedgelist(eve->prev, eve, NULL);
|
|
phi-=phid;
|
|
}
|
|
/* extrude and translate */
|
|
vec[0]= vec[2]= 0.0;
|
|
vec[1]= dia*phid;
|
|
Mat3MulVecfl(imat, vec);
|
|
for(a=0;a<seg-1;a++) {
|
|
extrudeflag_vert(2, nor); // nor unused
|
|
translateflag(2, vec);
|
|
}
|
|
recalc_editnormals(); // does face centers too
|
|
}
|
|
else if(type==11) { /* UVsphere */
|
|
|
|
/* clear all flags */
|
|
eve= em->verts.first;
|
|
while(eve) {
|
|
eve->f= 0;
|
|
eve= eve->next;
|
|
}
|
|
|
|
/* one segment first */
|
|
phi= 0;
|
|
phid/=2;
|
|
for(a=0; a<=tot; a++) {
|
|
vec[0]= dia*sin(phi);
|
|
vec[1]= 0.0;
|
|
vec[2]= dia*cos(phi);
|
|
eve= addvertlist(vec);
|
|
eve->f= 1+2+4;
|
|
if(a==0) v1= eve;
|
|
else addedgelist(eve->prev, eve, NULL);
|
|
phi+= phid;
|
|
}
|
|
|
|
/* extrude and rotate */
|
|
phi= M_PI/seg;
|
|
q[0]= cos(phi);
|
|
q[3]= sin(phi);
|
|
q[1]=q[2]= 0;
|
|
QuatToMat3(q, cmat);
|
|
|
|
for(a=0; a<seg; a++) {
|
|
extrudeflag_vert(2, nor); // nor unused
|
|
rotateflag(2, v1->co, cmat);
|
|
}
|
|
|
|
removedoublesflag(4, 0.0001);
|
|
|
|
/* and now do imat */
|
|
eve= em->verts.first;
|
|
while(eve) {
|
|
if(eve->f & SELECT) {
|
|
VecAddf(eve->co,eve->co,cent);
|
|
Mat3MulVecfl(imat,eve->co);
|
|
}
|
|
eve= eve->next;
|
|
}
|
|
}
|
|
else if(type==12) { /* Icosphere */
|
|
EditVert *eva[12];
|
|
|
|
/* clear all flags */
|
|
eve= em->verts.first;
|
|
while(eve) {
|
|
eve->f= 0;
|
|
eve= eve->next;
|
|
}
|
|
dia/=200;
|
|
for(a=0;a<12;a++) {
|
|
vec[0]= dia*icovert[a][0];
|
|
vec[1]= dia*icovert[a][1];
|
|
vec[2]= dia*icovert[a][2];
|
|
eva[a]= addvertlist(vec);
|
|
eva[a]->f= 1+2;
|
|
}
|
|
for(a=0;a<20;a++) {
|
|
v1= eva[ icoface[a][0] ];
|
|
v2= eva[ icoface[a][1] ];
|
|
v3= eva[ icoface[a][2] ];
|
|
addfacelist(v1, v2, v3, 0, NULL, NULL);
|
|
}
|
|
|
|
dia*=200;
|
|
for(a=1; a<subdiv; a++) subdivideflag(2, dia, 0);
|
|
/* and now do imat */
|
|
eve= em->verts.first;
|
|
while(eve) {
|
|
if(eve->f & 2) {
|
|
VecAddf(eve->co,eve->co,cent);
|
|
Mat3MulVecfl(imat,eve->co);
|
|
}
|
|
eve= eve->next;
|
|
}
|
|
} else if (type==13) { /* Monkey */
|
|
extern int monkeyo, monkeynv, monkeynf;
|
|
extern signed char monkeyf[][4];
|
|
extern signed char monkeyv[][3];
|
|
EditVert **tv= MEM_mallocN(sizeof(*tv)*monkeynv*2, "tv");
|
|
EditFace *efa;
|
|
int i;
|
|
|
|
for (i=0; i<monkeynv; i++) {
|
|
float v[3];
|
|
v[0]= (monkeyv[i][0]+127)/128.0, v[1]= monkeyv[i][1]/128.0, v[2]= monkeyv[i][2]/128.0;
|
|
tv[i]= addvertlist(v);
|
|
tv[i]->f |= SELECT;
|
|
tv[monkeynv+i]= (fabs(v[0]= -v[0])<0.001)?tv[i]:addvertlist(v);
|
|
tv[monkeynv+i]->f |= SELECT;
|
|
}
|
|
for (i=0; i<monkeynf; i++) {
|
|
efa= addfacelist(tv[monkeyf[i][0]+i-monkeyo], tv[monkeyf[i][1]+i-monkeyo], tv[monkeyf[i][2]+i-monkeyo], (monkeyf[i][3]!=monkeyf[i][2])?tv[monkeyf[i][3]+i-monkeyo]:NULL, NULL, NULL);
|
|
efa= addfacelist(tv[monkeynv+monkeyf[i][2]+i-monkeyo], tv[monkeynv+monkeyf[i][1]+i-monkeyo], tv[monkeynv+monkeyf[i][0]+i-monkeyo], (monkeyf[i][3]!=monkeyf[i][2])?tv[monkeynv+monkeyf[i][3]+i-monkeyo]:NULL, NULL, NULL);
|
|
}
|
|
|
|
MEM_freeN(tv);
|
|
|
|
/* and now do imat */
|
|
eve= em->verts.first;
|
|
while(eve) {
|
|
if(eve->f & SELECT) {
|
|
VecAddf(eve->co,eve->co,cent);
|
|
Mat3MulVecfl(imat,eve->co);
|
|
}
|
|
eve= eve->next;
|
|
}
|
|
}
|
|
|
|
// simple selection flush OK, based on fact it's a single model
|
|
EM_select_flush(); // flushes vertex -> edge -> face selection
|
|
|
|
if(type!=0 && type!=10 && type!=13) righthandfaces(1);
|
|
countall();
|
|
|
|
allqueue(REDRAWINFO, 1); /* 1, because header->win==0! */
|
|
allqueue(REDRAWALL, 0);
|
|
makeDispList(G.obedit);
|
|
|
|
/* if a new object was created, it stores it in Mesh, for reload original data and undo */
|
|
if(newob) load_editMesh();
|
|
BIF_undo_push(undostr);
|
|
}
|
|
|