This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/src/editmesh_add.c

700 lines
16 KiB
C
Raw Normal View History

/**
* $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
#ifdef WIN32
#include "BLI_winstuff.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_mywindow.h"
#include "BIF_screen.h"
#include "BIF_space.h"
#include "BIF_toolbox.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];
TEST_EDITMESH
Mat3CpyMat4(mat, G.obedit->obmat);
Mat3Inv(imat, mat);
v1= em->verts.first;
while(v1) {
if(v1->f & 1) break;
v1= v1->next;
}
eve= v1; /* prevent there are more selected */
while(eve) {
eve->f&= ~1;
eve= eve->next;
}
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= 1;
if(v1) {
addedgelist(v1, eve, NULL);
v1->f= 0;
}
countall();
allqueue(REDRAWVIEW3D, 0);
makeDispList(G.obedit);
while(get_mbut()&R_MOUSE);
}
void addedgeface_mesh(void)
{
EditMesh *em = G.editMesh;
EditVert *eve, *neweve[4];
EditFace *efa;
float con1, con2, con3;
short aantal=0;
if( (G.vd->lay & G.obedit->lay)==0 ) return;
/* how many selected ? */
eve= em->verts.first;
while(eve) {
if(eve->f & 1) {
aantal++;
if(aantal>4) break;
neweve[aantal-1]= eve;
}
eve= eve->next;
}
if(aantal==2) {
addedgelist(neweve[0], neweve[1], NULL);
allqueue(REDRAWVIEW3D, 0);
makeDispList(G.obedit);
return;
}
if(aantal<2 || aantal>4) {
error("Incorrect number of vertices to make edge/face");
return;
}
efa= NULL; // check later
if(aantal==3) {
if(exist_face(neweve[0], neweve[1], neweve[2], 0)==0) {
efa= addfacelist(neweve[0], neweve[1], neweve[2], 0, NULL);
}
else error("The selected vertices already form a face");
}
else if(aantal==4) {
if(exist_face(neweve[0], neweve[1], neweve[2], neweve[3])==0) {
con1= convex(neweve[0]->co, neweve[1]->co, neweve[2]->co, neweve[3]->co);
con2= convex(neweve[0]->co, neweve[2]->co, neweve[3]->co, neweve[1]->co);
con3= convex(neweve[0]->co, neweve[3]->co, neweve[1]->co, neweve[2]->co);
if(con1>=con2 && con1>=con3)
efa= addfacelist(neweve[0], neweve[1], neweve[2], neweve[3], NULL);
else if(con2>=con1 && con2>=con3)
efa= addfacelist(neweve[0], neweve[2], neweve[3], neweve[1], NULL);
else
efa= addfacelist(neweve[0], neweve[2], neweve[1], neweve[3], NULL);
}
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! */
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);
}
countall();
allqueue(REDRAWVIEW3D, 0);
makeDispList(G.obedit);
}
void adduplicateflag(int flag)
{
EditMesh *em = G.editMesh;
/* old verts have flag 128 set, and flag 'flag' cleared
new verts have flag 'flag' set */
EditVert *eve, *v1, *v2, *v3, *v4;
EditEdge *eed;
EditFace *efa;
/* vertices first */
eve= em->verts.last;
while(eve) {
eve->f&= ~128;
if(eve->f & flag) {
v1= addvertlist(eve->co);
v1->f= eve->f;
eve->f-= flag;
eve->f|= 128;
eve->vn= v1;
#ifdef __NLA
/* >>>>> FIXME: Copy deformation weight ? */
v1->totweight = eve->totweight;
if (eve->totweight){
v1->dw = MEM_mallocN (eve->totweight * sizeof(MDeformWeight), "deformWeight");
memcpy (v1->dw, eve->dw, eve->totweight * sizeof(MDeformWeight));
}
else
v1->dw=NULL;
#endif
}
eve= eve->prev;
}
eed= em->edges.first;
while(eed) {
if( (eed->v1->f & 128) && (eed->v2->f & 128) ) {
v1= eed->v1->vn;
v2= eed->v2->vn;
addedgelist(v1, v2, eed);
}
eed= eed->next;
}
/* then dupicate faces */
efa= em->faces.first;
while(efa) {
if( (efa->v1->f & 128) && (efa->v2->f & 128) && (efa->v3->f & 128) ) {
if(efa->v4) {
if(efa->v4->f & 128) {
v1= efa->v1->vn;
v2= efa->v2->vn;
v3= efa->v3->vn;
v4= efa->v4->vn;
addfacelist(v1, v2, v3, v4, efa);
}
}
else {
v1= efa->v1->vn;
v2= efa->v2->vn;
v3= efa->v3->vn;
addfacelist(v1, v2, v3, 0, efa);
}
}
efa= efa->next;
}
}
void adduplicate_mesh(void)
{
TEST_EDITMESH
waitcursor(1);
undo_push_mesh("Duplicate");
adduplicateflag(1);
waitcursor(0);
countall(); /* for G.totvert in calc_meshverts() */
transform('d');
}
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];
static short tot=32, seg=32, subdiv=2;
short a, b, ext=0, fill=0, totoud, newob=0;
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 */
eve= em->verts.first;
while(eve) {
if(eve->f & 1) eve->f&= ~1;
eve= eve->next;
}
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!= 11) {
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");
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");
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");
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");
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");
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");
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");
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");
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");
break;
case 13: /* Monkey */
if(newob) rename_id((ID *)G.obedit, "Suzanne");
if(newob) rename_id((ID *)me, "Suzanne");
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= 1;
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= 1;
if(vdown) vdown->f= 1;
/* 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);
if(ext) addfacelist(v2, v2->next, v4, v4->next, NULL);
}
else {
v3= v1;
v4= v2;
for(a=1; a<tot; a++) {
addfacelist(vdown, v3, v3->next, 0, NULL);
v3= v3->next;
if(ext) {
addfacelist(vtop, v4, v4->next, 0, NULL);
v4= v4->next;
}
}
if(type>1) {
addfacelist(vdown, v3, v1, 0, NULL);
if(ext) addfacelist(vtop, v4, v2, 0, 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);
v3= v3->next;
v4= v4->next;
}
addfacelist(v3, v1, v2, v4, NULL);
}
else if(type==7) { /* cone */
v3= v1;
for(a=1; a<tot; a++) {
addfacelist(vtop, v3->next, v3, 0, NULL);
v3= v3->next;
}
addfacelist(vtop, v1, v3, 0, 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(2,0);
translateflag(2, vec);
}
}
else if(type==11) { /* UVsphere */
float tmat[3][3];
/* 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]= cent[0]+dia*sin(phi);
vec[1]= cent[1];
vec[2]= cent[2]+dia*cos(phi);
Mat3MulVecfl(imat,vec);
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);
Mat3MulMat3(tmat, cmat, mat);
Mat3MulMat3(cmat, imat, tmat);
for(a=0; a<seg; a++) {
extrudeflag(2, 0);
rotateflag(2, v1->co, cmat);
}
removedoublesflag(4, 0.0001);
}
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);
}
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");
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[monkeynv+i]= (fabs(v[0]= -v[0])<0.001)?tv[i]:addvertlist(v);
}
for (i=0; i<monkeynf; i++) {
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);
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);
}
MEM_freeN(tv);
}
if(type!=0 && type!=10) righthandfaces(1);
countall();
allqueue(REDRAWINFO, 1); /* 1, because header->win==0! */
allqueue(REDRAWALL, 0);
makeDispList(G.obedit);
if (type==13) notice("Oooh Oooh Oooh");
}