diff options
author | Ken Hughes <khughes@pacific.edu> | 2006-05-25 20:45:24 +0400 |
---|---|---|
committer | Ken Hughes <khughes@pacific.edu> | 2006-05-25 20:45:24 +0400 |
commit | 48033e00c44c0ff5aab055f6ecfe833b7f688856 (patch) | |
tree | 18262846584b26a0c53612e1d5bce719041b940b /source | |
parent | 1b2d9b5ade184d26679b3b4f2e09f27d84b9fd39 (diff) |
===Python API===
Fulfilling a very old feature request: a new Mesh Primitives module is
introduced, which gives script writers access to the Blender mesh datablocks
created from the "Add->Mesh" menu. You can now do this:
from Blender import *
me = Mesh.Primitives.UVsphere(10,20,3) # 10 segments, 20 rings, diameter 3
ob = Object.New('Mesh','mySphere')
ob.link(me)
sc = Scene.GetCurrent()
sc.link(ob)
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/include/BIF_editmesh.h | 3 | ||||
-rw-r--r-- | source/blender/python/api2_2x/Mesh.c | 4 | ||||
-rw-r--r-- | source/blender/python/api2_2x/doc/MeshPrimitives.py | 160 | ||||
-rw-r--r-- | source/blender/python/api2_2x/meshPrimitive.c | 280 | ||||
-rw-r--r-- | source/blender/python/api2_2x/meshPrimitive.h | 46 | ||||
-rw-r--r-- | source/blender/src/editmesh_add.c | 555 |
6 files changed, 784 insertions, 264 deletions
diff --git a/source/blender/include/BIF_editmesh.h b/source/blender/include/BIF_editmesh.h index 8711c21b3a8..5cf5f6c8f8a 100644 --- a/source/blender/include/BIF_editmesh.h +++ b/source/blender/include/BIF_editmesh.h @@ -65,6 +65,9 @@ extern void separate_mesh(void); extern void separate_mesh_loose(void); /* ******************* editmesh_add.c */ +extern void make_prim(int type, float imat[3][3], short tot, short seg, + short subdiv, float dia, float d, short ext, short fill, + float cent[3]); extern void add_primitiveMesh(int type); extern void adduplicate_mesh(void); extern void add_click_mesh(void); diff --git a/source/blender/python/api2_2x/Mesh.c b/source/blender/python/api2_2x/Mesh.c index 5f1f8b8314f..ba383fd4068 100644 --- a/source/blender/python/api2_2x/Mesh.c +++ b/source/blender/python/api2_2x/Mesh.c @@ -80,6 +80,7 @@ #include "Image.h" #include "Material.h" #include "Mathutils.h" +#include "meshPrimitive.h" #include "constant.h" #include "gen_utils.h" @@ -7378,6 +7379,9 @@ PyObject *Mesh_Init( void ) submodule = Py_InitModule3( "Blender.Mesh", M_Mesh_methods, M_Mesh_doc ); + PyDict_SetItemString( PyModule_GetDict( submodule ), + "Primitives", MeshPrimitives_Init( ) ); + if( Modes ) PyModule_AddObject( submodule, "Modes", Modes ); if( FaceFlags ) diff --git a/source/blender/python/api2_2x/doc/MeshPrimitives.py b/source/blender/python/api2_2x/doc/MeshPrimitives.py new file mode 100644 index 00000000000..a6a0365b9c0 --- /dev/null +++ b/source/blender/python/api2_2x/doc/MeshPrimitives.py @@ -0,0 +1,160 @@ +# Blender.Mesh.Primitives module + +""" +The Blender.Mesh.Primitives submodule. + +B{New}: + +Mesh Primitive Data +=================== + +This submodule provides access Blender's mesh primitives. Each module +function returns a BPy_Mesh object which wraps the mesh data. This data can +then be manipulated using the L{Mesh} API. + +Example:: + + from Blender import * + + me = Mesh.Primitives.Cube(2.0) # create a new cube of size 2 + ob = Object.New('Mesh') # create a new mesh-type object + ob.link(me) # link mesh datablock with object + sc = Scene.GetCurrent() # get current scene + sc.link(ob) # add object to the scene + Window.RedrawAll() # update windows +""" + + +def Plane(size=2.0): + """ + Construct a filled planar mesh with 4 vertices. The default size + creates a 2 by 2 Blender unit plane, identical to the Blender UI. + @type size: float + @param size: optional size of the plane. + @rtype: L{BPy_Mesh<Mesh>} + @return: returns a mesh object. + """ + +def Cube(size=2.0): + """ + Construct a cube mesh. The default size creates a cube with each face + 2 by 2 Blender units, identical to the Blender UI. + @type size: float + @param size: optional size of the cube. + @rtype: L{BPy_Mesh<Mesh>} + @return: returns a mesh object. + """ + +def Circle(verts=32,diameter=2.8284): + """ + Construct a circle mesh. The defaults create a circle with a + diameter of 2*sqrt(2) Blender units, identical to the Blender UI. + @type verts: int + @param verts: optional number of vertices for the circle. + Value must be in the range [3,100]. + @type diameter: float + @param diameter: optional diameter of the circle. + @rtype: L{BPy_Mesh<Mesh>} + @return: returns a mesh object. + """ + +def Cylinder(verts=32, diameter=2.8284, length=1.0): + """ + Construct a cylindrical mesh (ends filled). The defaults create a + cylinder with a diameter of 2*sqrt(2) Blender units and length 1 unit, + identical to the Blender UI. + @type verts: int + @param verts: optional number of vertices in the cylinder's perimeter. + Value must be in the range [3,100]. + @type diameter: float + @param diameter: optional diameter of the cylinder. + @type length: float + @param length: optional length of the cylinder. + @rtype: L{BPy_Mesh<Mesh>} + @return: returns a mesh object. + """ + +def Tube(verts=32, diameter=2.8284, length=1.0): + """ + Construct a cylindrical mesh (ends not filled). The defaults create a + cylinder with a diameter of 2*sqrt(2) Blender units and length 1 unit, identical + to the Blender UI. + @type verts: int + @param verts: optional number of vertices in the tube's perimeter. + Value must be in the range [3,100]. + @type diameter: float + @param diameter: optional diameter of the tube. + @type length: float + @param length: optional length of the tube. + @rtype: L{BPy_Mesh<Mesh>} + @return: returns a mesh object. + """ + +def Cone(verts=32, diameter=2.8284, length=1.0): + """ + Construct a conic mesh (ends filled). The defaulte create a cone with a + base diameter of 2*sqrt(2) Blender units and length 1 unit, identical to the Blender + UI. + @type verts: int + @param verts: optional number of vertices in the cone's perimeter. + Value must be in the range [3,100]. + @type diameter: float + @param diameter: optional diameter of the cone. + @type length: float + @param length: optional length of the cone. + @rtype: L{BPy_Mesh<Mesh>} + @return: returns a mesh object. + """ + +def Grid(xres=32, yres=32, size=2.0): + """ + Construct a grid mesh. The defaults create a 32 by 32 mesh of size 2 + Blender units, identical to the Blender UI. + @type xres: int + @param xres: optional grid size in the x direction. + Value must be in the range [2,100]. + @type yres: int + @param yres: optional grid size in the y direction. + Value must be in the range [2,100]. + @type size: float + @param size: optional size of the grid. + @rtype: L{BPy_Mesh<Mesh>} + @return: returns a mesh object. + """ + +def UVsphere(segments=32, rings=32, diameter=2.8284): + """ + Construct a UV sphere mesh. The defaults create a 32 by 32 sphere with + a diameter of 2*sqrt(2) Blender units, identical to the Blender UI. + @type segments: int + @param segments: optional number of longitudinal divisions. + Value must be in the range [3,100]. + @type rings: int + @param rings: optional number of latitudinal divisions. + Value must be in the range [3,100]. + @type diameter: float + @param diameter: optional diameter of the sphere. + @rtype: L{BPy_Mesh<Mesh>} + @return: returns a mesh object. + """ + +def Icosphere(subdivisions=2, diameter=2.82824): + """ + Construct a Icosphere mesh. The defaults create sphere with 2 subdivisions + and diameter of 2*sqrt(2) Blender units, identical to the Blender UI. + @type subdivisions: int + @param subdivisions: optional number of subdivisions. + Value must be in the range [2,5]. + @type diameter: float + @param diameter: optional diameter of the sphere. + @rtype: L{BPy_Mesh<Mesh>} + @return: returns a mesh object. + """ + +def Monkey(): + """ + Construct a Suzanne mesh. + @rtype: L{BPy_Mesh<Mesh>} + @return: returns a mesh object. + """ + diff --git a/source/blender/python/api2_2x/meshPrimitive.c b/source/blender/python/api2_2x/meshPrimitive.c new file mode 100644 index 00000000000..6182159afc2 --- /dev/null +++ b/source/blender/python/api2_2x/meshPrimitive.c @@ -0,0 +1,280 @@ +/* + * $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) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * This is a new part of Blender, partially based on NMesh.c API. + * + * Contributor(s): Ken Hughes + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "Mesh.h" /*This must come first*/ + +#include "DNA_scene_types.h" +#include "BDR_editobject.h" +#include "BIF_editmesh.h" +#include "BKE_global.h" +#include "BKE_object.h" +#include "BKE_scene.h" +#include "BKE_library.h" +#include "blendef.h" + +#include "gen_utils.h" + +/* + * local helper procedure which does the dirty work of messing with the + * edit mesh, active objects, etc. + */ + +static PyObject *make_mesh( int type, char *name, short tot, short seg, + short subdiv, float dia, float height, short ext, short fill ) +{ + float cent[3] = {0,0,0}; + float imat[3][3]={{1,0,0},{0,1,0},{0,0,1}}; + Mesh *me; + BPy_Mesh *obj; + Object *ob; + Base *base; + + /* remember active object (if any) for later, so we can re-activate */ + base = BASACT; + + /* make a new object, "copy" to the editMesh structure */ + ob = add_object(OB_MESH); + me = (Mesh *)ob->data; + G.obedit = BASACT->object; + make_editMesh( ); + + /* create the primitive in the edit mesh */ + + make_prim( type, imat, /* mesh type, transform matrix */ + tot, seg, /* total vertices, segments */ + subdiv, /* subdivisions (for Icosphere only) */ + dia, -height, /* diameter-ish, height */ + ext, fill, /* extrude, fill end faces */ + cent ); /* location of center */ + + /* copy primitive back to the real mesh */ + load_editMesh( ); + free_editMesh( G.editMesh ); + G.obedit = NULL; + + /* remove object link to the data, then delete the object */ + ob->data = NULL; + me->id.us = 0; + free_and_unlink_base(BASACT); + + /* if there was an active object, reactivate it */ + if( base ) + scene_select_base(G.scene, base); + + /* create the BPy_Mesh that wraps this mesh */ + obj = (BPy_Mesh *)PyObject_NEW( BPy_Mesh, &Mesh_Type ); + + rename_id( &me->id, name ); + obj->mesh = me; + obj->object = NULL; + obj->new = 1; + return (PyObject *) obj; +} + +static PyObject *M_MeshPrim_Plane( PyObject *self_unused, PyObject *args ) +{ + float size = 2.0; + + if( !PyArg_ParseTuple( args, "|f", &size ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected optional float arg" ); + + size *= sqrt(2.0)/2.0; + return make_mesh( 0, "Plane", 4, 0, 0, size, -size, 0, 1 ); +} + +static PyObject *M_MeshPrim_Cube( PyObject *self_unused, PyObject *args ) +{ + float size = 2.0; + + if( !PyArg_ParseTuple( args, "|f", &size ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected optional float arg" ); + + size *= sqrt(2.0)/2.0; + return make_mesh( 1, "Cube", 4, 0, 0, size, -size, 1, 1 ); +} + +static PyObject *M_MeshPrim_Circle( PyObject *self_unused, PyObject *args ) +{ + int tot = 32; + float size = 2.0*sqrt(2.0); + + if( !PyArg_ParseTuple( args, "|if", &tot, &size ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected int and optional float arg" ); + if( tot < 3 || tot > 100 ) + return EXPP_ReturnPyObjError( PyExc_ValueError, + "number of vertices must be in the range [3:100]" ); + + size /= 2.0; + return make_mesh( 4, "Circle", tot, 0, 0, size, -size, 0, 0 ); +} + +static PyObject *M_MeshPrim_Cylinder( PyObject *self_unused, PyObject *args ) +{ + int tot = 32; + float size = 2.0*sqrt(2.0); + float len = 1.0; + + if( !PyArg_ParseTuple( args, "|iff", &tot, &size, &len ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected int and optional float arg" ); + if( tot < 3 || tot > 100 ) + return EXPP_ReturnPyObjError( PyExc_ValueError, + "number of vertices must be in the range [3:100]" ); + + size /= 2.0; + return make_mesh( 5, "Cylinder", tot, 0, 0, size, -len, 1, 1 ); +} + +static PyObject *M_MeshPrim_Tube( PyObject *self_unused, PyObject *args ) +{ + int tot = 32; + float size = 2.0*sqrt(2.0); + float len = 1.0; + + if( !PyArg_ParseTuple( args, "|iff", &tot, &size, &len ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected int and optional float arg" ); + if( tot < 3 || tot > 100 ) + return EXPP_ReturnPyObjError( PyExc_ValueError, + "number of vertices must be in the range [3:100]" ); + + size /= 2.0; + return make_mesh( 6, "Tube", tot, 0, 0, size, -len, 1, 0 ); +} + +static PyObject *M_MeshPrim_Cone( PyObject *self_unused, PyObject *args ) +{ + int tot = 32; + float size = 2.0*sqrt(2.0); + float len = 1.0; + + if( !PyArg_ParseTuple( args, "|iff", &tot, &size, &len ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected int and optional float arg" ); + if( tot < 3 || tot > 100 ) + return EXPP_ReturnPyObjError( PyExc_ValueError, + "number of vertices must be in the range [3:100]" ); + + size /= 2.0; + return make_mesh( 7, "Cone", tot, 0, 0, size, -len, 0, 1 ); +} + +static PyObject *M_MeshPrim_Grid( PyObject *self_unused, PyObject *args ) +{ + int xres = 32; + int yres = 32; + float size = 2.0; + + if( !PyArg_ParseTuple( args, "|iif", &xres, &yres, &size ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected two ints and an optional float arg" ); + if( xres < 2 || xres > 100 || yres < 2 || yres > 100 ) + return EXPP_ReturnPyObjError( PyExc_ValueError, + "resolution must be in the range [2:100]" ); + + size /= 2.0; + return make_mesh( 10, "Grid", xres, yres, 0, size, -size, 0, 0 ); +} + +static PyObject *M_MeshPrim_UVsphere( PyObject *self_unused, PyObject *args ) +{ + int segs = 32; + int rings = 32; + float size = 2.0*sqrt(2.0); + + if( !PyArg_ParseTuple( args, "|iif", &segs, &rings, &size ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected two ints and an optional float arg" ); + if( segs < 3 || segs > 100 || rings < 3 || rings > 100 ) + return EXPP_ReturnPyObjError( PyExc_ValueError, + "segments and rings must be in the range [3:100]" ); + + size /= 2.0; + return make_mesh( 11, "UVsphere", segs, rings, 0, size, -size, 0, 0 ); +} + +static PyObject *M_MeshPrim_Icosphere( PyObject *self_unused, PyObject *args ) +{ + int subdiv = 2; + float size = 2.0*sqrt(2.0); + + if( !PyArg_ParseTuple( args, "|if", &subdiv, &size ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected int and an optional float arg" ); + if( subdiv < 1 || subdiv > 5 ) + return EXPP_ReturnPyObjError( PyExc_ValueError, + "subdivisions must be in the range [1:5]" ); + + size /= 2.0; + return make_mesh( 12, "Icosphere", 0, 0, subdiv, size, -size, 0, 0 ); +} + +static PyObject *M_MeshPrim_Suzanne( PyObject *self_unused, PyObject *args ) +{ + return make_mesh( 13, "Monkey", 0, 0, 0, 0, 0, 0, 0 ); +} + +static struct PyMethodDef M_MeshPrim_methods[] = { + {"Plane", (PyCFunction)M_MeshPrim_Plane, METH_VARARGS, + "Create a plane mesh"}, + {"Cube", (PyCFunction)M_MeshPrim_Cube, METH_VARARGS, + "Create a cube mesh"}, + {"Circle", (PyCFunction)M_MeshPrim_Circle, METH_VARARGS, + "Create a circle mesh"}, + {"Cylinder", (PyCFunction)M_MeshPrim_Cylinder, METH_VARARGS, + "Create a cylindrical mesh"}, + {"Tube", (PyCFunction)M_MeshPrim_Tube, METH_VARARGS, + "Create a tube mesh"}, + {"Cone", (PyCFunction)M_MeshPrim_Cone, METH_VARARGS, + "Create a conic mesh"}, + {"Grid", (PyCFunction)M_MeshPrim_Grid, METH_VARARGS, + "Create a 2D grid mesh"}, + {"UVsphere", (PyCFunction)M_MeshPrim_UVsphere, METH_VARARGS, + "Create a UV sphere mesh"}, + {"Icosphere", (PyCFunction)M_MeshPrim_Icosphere, METH_VARARGS, + "Create a Ico sphere mesh"}, + {"Monkey", (PyCFunction)M_MeshPrim_Suzanne, METH_NOARGS, + "Create a Suzanne mesh"}, + {NULL, NULL, 0, NULL}, +}; + +static char M_MeshPrim_doc[] = "The Blender.Mesh.Primitives submodule"; + +PyObject *MeshPrimitives_Init( void ) +{ + return Py_InitModule3( "Blender.Mesh.Primitives", + M_MeshPrim_methods, M_MeshPrim_doc ); +} + diff --git a/source/blender/python/api2_2x/meshPrimitive.h b/source/blender/python/api2_2x/meshPrimitive.h new file mode 100644 index 00000000000..1aa60c31eb4 --- /dev/null +++ b/source/blender/python/api2_2x/meshPrimitive.h @@ -0,0 +1,46 @@ +/* + * $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) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * This is a new part of Blender. + * + * Contributor(s): Ken Hughes + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef EXPP_MESHPRIMITIVES_H +#define EXPP_MESHPRIMITIVES_H + +#include <Python.h> + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +/* PROTOS */ + +PyObject *MeshPrimitives_Init( void ); + +#endif /* EXPP_MESHPRIMITIVES_H */ diff --git a/source/blender/src/editmesh_add.c b/source/blender/src/editmesh_add.c index 5ae47c078c1..7a3003a01f9 100644 --- a/source/blender/src/editmesh_add.c +++ b/source/blender/src/editmesh_add.c @@ -734,15 +734,293 @@ int confirm_objectExists( Mesh **me, float mat[][3] ) return newob; } -void add_primitiveMesh(int type) +void make_prim(int type, float imat[3][3], short tot, short seg, + short subdiv, float dia, float d, short ext, short fill, + float cent[3]) { 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 phi, phid, vec[3]; float q[4], cmat[3][3], nor[3]= {0.0, 0.0, 0.0}; + short a, b; + + phid= 2*M_PI/tot; + phi= .25*M_PI; + + switch(type) { + case 10: /* grid */ + /* clear flags */ + eve= em->verts.first; + while(eve) { + eve->f= 0; + eve= eve->next; + } + /* one segment first: the X axis */ + 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); + } + break; + case 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; + } + break; + case 12: /* Icosphere */ + { + EditVert *eva[12]; + EditEdge *eed; + + /* 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++) { + EditFace *evtemp; + v1= eva[ icoface[a][0] ]; + v2= eva[ icoface[a][1] ]; + v3= eva[ icoface[a][2] ]; + evtemp = addfacelist(v1, v2, v3, 0, NULL, NULL); + evtemp->e1->f = 1+2; + evtemp->e2->f = 1+2; + evtemp->e3->f = 1+2; + } + + dia*=200; + for(a=1; a<subdiv; a++) esubdivideflag(2, dia, 0,1,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; + } + + // Clear the flag 2 from the edges + for(eed=em->edges.first;eed;eed=eed->next){ + if(eed->f & 2){ + eed->f &= !2; + } + } + } + break; + case 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 */ + for(eve= em->verts.first; eve; eve= eve->next) { + if(eve->f & SELECT) { + VecAddf(eve->co,eve->co,cent); + Mat3MulVecfl(imat,eve->co); + } + } + recalc_editnormals(); + } + break; + default: /* 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); + } + } + /* simple selection flush OK, based on fact it's a single model */ + EM_select_flush(); /* flushes vertex -> edge -> face selection */ + + if(type!=0 && type!=13) + righthandfaces(1); /* otherwise monkey has eyes in wrong direction */ +} + +void add_primitiveMesh(int type) +{ + Mesh *me; + float *curs, d, dia, phi, phid, cent[3], imat[3][3], mat[3][3]; + float cmat[3][3]; static short tot=32, seg=32, subdiv=2; - short a, b, ext=0, fill=0, totoud, newob=0; + short ext=0, fill=0, totoud, newob=0; char *undostr="Add Primitive"; char *name=NULL; @@ -864,272 +1142,21 @@ void add_primitiveMesh(int type) Mat3Inv(imat, mat); } - dia= sqrt(2.0)*G.vd->grid; + dia= G.vd->grid; + if(type != 10) + dia *= sqrt(2.0); + 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: the X axis */ - 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); - } - } - 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); - } + make_prim(type, imat, + tot, seg, subdiv, dia, d, + ext, fill, + cent); - removedoublesflag(4, 0.0001); + if(type<2) tot = totoud; - /* 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]; - EditEdge *eed; - - /* 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++) { - EditFace *evtemp; - v1= eva[ icoface[a][0] ]; - v2= eva[ icoface[a][1] ]; - v3= eva[ icoface[a][2] ]; - evtemp = addfacelist(v1, v2, v3, 0, NULL, NULL); - evtemp->e1->f = 1+2; - evtemp->e2->f = 1+2; - evtemp->e3->f = 1+2; - } - - dia*=200; - for(a=1; a<subdiv; a++) esubdivideflag(2, dia, 0,1,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; - } - - // Clear the flag 2 from the edges - for(eed=em->edges.first;eed;eed=eed->next){ - if(eed->f & 2){ - eed->f &= !2; - } - } - - - } 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 */ - for(eve= em->verts.first; eve; eve= eve->next) { - if(eve->f & SELECT) { - VecAddf(eve->co,eve->co,cent); - Mat3MulVecfl(imat,eve->co); - } - } - recalc_editnormals(); - } - // simple selection flush OK, based on fact it's a single model EM_select_flush(); // flushes vertex -> edge -> face selection |