Part one of editmesh.c refactoring. The huge file has been split in

logical parts, and include files altered to denote internal and external
functions.

include/editmesh.h: internal calls for editmesh_xxx.c files
include/BIF_editmesh.h: external calls for these files

src/editmesh.c: basic alloc/lists and in/out editmode, undo, separate
src/editmesh_lib.c: basic utility calls for all editmesh_xxx.c (no UI)
src/editmesh_add.c: add prim, add duplicate, add vertex/edge/face (UI)
src/editmesh_mods.c: selecting, transforming (UI)
src/editmesh_loop.c: loop tools like knife, loop select, loop subdiv (UI)
src/editmesh_tools.c: other tools (extrude, spin, etc) (UI)

And a new file:

src/meshtools.c: tools for Mesh outside of editmode (normals, draw flags)
This commit is contained in:
Ton Roosendaal 2004-09-19 11:47:49 +00:00
parent dab46067bf
commit ca5b7386e5
15 changed files with 9449 additions and 8819 deletions

@ -30,6 +30,8 @@
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
/* External for editmesh_xxxx.c functions */
#ifndef BIF_EDITMESH_H
#define BIF_EDITMESH_H
@ -40,117 +42,13 @@ struct Mesh;
struct bDeformGroup;
struct View3D;
void free_hashedgetab(void);
void fasterdraw(void);
void slowerdraw(void);
void vertexnoise(void);
void vertexsmooth(void);
void make_sticky(void);
void deselectall_mesh(void);
/* ******************* editmesh.c */
extern void make_editMesh(void);
extern void load_editMesh(void);
extern void free_editMesh(void);
extern void remake_editMesh(void);
/* For Knife subdivide */
typedef struct CutCurve {
short x;
short y;
} CutCurve;
void KnifeSubdivide(char mode);
#define KNIFE_PROMPT 0
#define KNIFE_EXACT 1
#define KNIFE_MIDPOINT 2
CutCurve *get_mouse_trail(int * length, char mode);
#define TRAIL_POLYLINE 1 /* For future use, They don't do anything yet */
#define TRAIL_FREEHAND 2
#define TRAIL_MIXED 3 /* (1|2) */
#define TRAIL_AUTO 4
#define TRAIL_MIDPOINTS 8
short seg_intersect(struct EditEdge * e, CutCurve *c, int len);
void LoopMenu(void);
/* End Knife Subdiv */
/** Aligns the selected TFace's of @a me to the @a v3d,
* using the given axis (0-2). Can give a user error.
*/
void faceselect_align_view_to_selected(struct View3D *v3d, struct Mesh *me, int axis);
/** Aligns the selected faces or vertices of @a me to the @a v3d,
* using the given axis (0-2). Can give a user error.
*/
void editmesh_align_view_to_selected(struct View3D *v3d, int axis);
struct EditVert *addvertlist(float *vec);
struct EditEdge *addedgelist(struct EditVert *v1, struct EditVert *v2, struct EditEdge *example);
struct EditFace *addfacelist(struct EditVert *v1, struct EditVert *v2, struct EditVert *v3, struct EditVert *v4, struct EditFace *example);
struct EditEdge *findedgelist(struct EditVert *v1, struct EditVert *v2);
void remedge(struct EditEdge *eed);
int faceselectedAND(struct EditFace *efa, int flag);
void recalc_editnormals(void);
void flip_editnormals(void);
void vertexnormals(int testflip);
/* this is currently only used by the python NMesh module: */
void vertexnormals_mesh(struct Mesh *me, float *extverts);
void make_editMesh(void);
void load_editMesh(void);
void free_editMesh(void);
void remake_editMesh(void);
void convert_to_triface(int all);
void righthandfaces(int select);
void mouse_mesh(void);
void selectconnected_mesh(int qual);
short extrudeflag(short flag,short type);
void rotateflag(short flag, float *cent, float rotmat[][3]);
void translateflag(short flag, float *vec);
short removedoublesflag(short flag, float limit);
void xsortvert_flag(int flag);
void hashvert_flag(int flag);
void subdivideflag(int flag, float rad, int beauty);
void adduplicateflag(int flag);
void extrude_mesh(void);
void adduplicate_mesh(void);
void split_mesh(void);
void separatemenu(void);
void separate_mesh(void);
void separate_mesh_loose(void);
void loopoperations(char mode);
#define LOOP_SELECT 1
#define LOOP_CUT 2
void vertex_loop_select(void);
void edge_select(void);
void extrude_repeat_mesh(int steps, float offs);
void spin_mesh(int steps,int degr,float *dvec, int mode);
void screw_mesh(int steps,int turns);
void selectswap_mesh(void);
void addvert_mesh(void);
void addedgeface_mesh(void);
void delete_mesh(void);
void add_primitiveMesh(int type);
void hide_mesh(int swap);
void reveal_mesh(void);
void beauty_fill(void);
void join_triangles(void);
void edge_flip(void);
void join_mesh(void);
void sort_faces(void);
void vertices_to_sphere(void);
void fill_mesh(void);
void bevel_menu();
/* Editmesh Undo code */
/* Editmesh Undo code */
void undo_free_mesh(struct Mesh *me);
void undo_push_mesh(char *name);
void undo_pop_mesh(int steps);
@ -158,21 +56,90 @@ void undo_redo_mesh(void);
void undo_clear_mesh(void);
void undo_menu_mesh(void);
/* Selection */
void select_non_manifold(void);
void select_more(void);
void select_less(void);
void selectrandom_mesh(void);
extern void separatemenu(void);
extern void separate_mesh(void);
extern void separate_mesh_loose(void);
void Edge_Menu(void);
/* ******************* editmesh_add.c */
extern void add_primitiveMesh(int type);
extern void adduplicate_mesh(void);
extern void addvert_mesh(void);
extern void addedgeface_mesh(void);
void editmesh_select_by_material(int index);
void editmesh_deselect_by_material(int index);
/* ******************* editmesh_lib.c */
extern int faceselectedAND(struct EditFace *efa, int flag);
extern void recalc_editnormals(void);
extern void flip_editnormals(void);
extern void vertexnormals(int testflip);
void editmesh_mark_seam(int clear);
/* ******************* editmesh_mods.c */
extern void vertexnoise(void);
extern void vertexsmooth(void);
extern void righthandfaces(int select);
extern void mouse_mesh(void);
extern void deselectall_mesh(void);
extern void selectconnected_mesh(int qual);
extern void selectswap_mesh(void);
extern void hide_mesh(int swap);
extern void reveal_mesh(void);
extern void vertices_to_sphere(void);
/** Aligns the selected TFace's of @a me to the @a v3d,
* using the given axis (0-2). Can give a user error.
*/
extern void faceselect_align_view_to_selected(struct View3D *v3d, struct Mesh *me, int axis);
/** Aligns the selected faces or vertices of @a me to the @a v3d,
* using the given axis (0-2). Can give a user error.
*/
extern void editmesh_align_view_to_selected(struct View3D *v3d, int axis);
/* Selection */
extern void select_non_manifold(void);
extern void select_more(void);
extern void select_less(void);
extern void selectrandom_mesh(void);
extern void editmesh_select_by_material(int index);
extern void editmesh_deselect_by_material(int index);
extern void Edge_Menu(void);
extern void editmesh_mark_seam(int clear);
/* ******************* editmesh_loop.c */
#define KNIFE_PROMPT 0
#define KNIFE_EXACT 1
#define KNIFE_MIDPOINT 2
extern void KnifeSubdivide(char mode);
extern void LoopMenu(void);
#define LOOP_SELECT 1
#define LOOP_CUT 2
extern void loopoperations(char mode);
extern void vertex_loop_select(void);
/* ******************* editmesh_tools.c */
extern void convert_to_triface(int all);
extern short removedoublesflag(short flag, float limit);
extern void xsortvert_flag(int flag);
extern void hashvert_flag(int flag);
extern void subdivideflag(int flag, float rad, int beauty);
extern void extrude_mesh(void);
extern void split_mesh(void);
extern void extrude_repeat_mesh(int steps, float offs);
extern void spin_mesh(int steps,int degr,float *dvec, int mode);
extern void screw_mesh(int steps,int turns);
extern void delete_mesh(void);
extern void beauty_fill(void);
extern void join_triangles(void);
extern void edge_flip(void);
extern void fill_mesh(void);
extern void bevel_menu();
void edge_rotate_selected(void);
void edge_rotate(struct EditEdge *eed);
#endif

@ -0,0 +1,47 @@
/**
* $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.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
#ifndef BIF_MESHTOOLS_H
#define BIF_MESHTOOLS_H
extern void join_mesh(void);
extern void make_sticky(void);
extern void fasterdraw(void);
extern void slowerdraw(void);
extern void vertexnormals_mesh(Mesh *me, float *extverts);
extern void sort_faces(void);
#endif

@ -0,0 +1,89 @@
/**
* $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.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
/* Internal for editmesh_xxxx.c functions */
#ifndef EDITMESH_H
#define EDITMESH_H
#define TEST_EDITMESH if(G.obedit==0) return; \
if( (G.vd->lay & G.obedit->lay)==0 ) return;
#define UVCOPY(t, s) memcpy(t, s, 2 * sizeof(float));
/* ******************* editmesh.c */
extern void free_editvert(EditVert *eve);
extern void free_editedge(EditEdge *eed);
extern void free_editface(EditFace *efa);
extern void free_vertlist(ListBase *edve);
extern void free_edgelist(ListBase *lb);
extern void free_facelist(ListBase *lb);
extern void remedge(EditEdge *eed);
extern struct EditVert *addvertlist(float *vec);
extern struct EditEdge *addedgelist(struct EditVert *v1, struct EditVert *v2, struct EditEdge *example);
extern struct EditFace *addfacelist(struct EditVert *v1, struct EditVert *v2, struct EditVert *v3, struct EditVert *v4, struct EditFace *example);
extern struct EditEdge *findedgelist(struct EditVert *v1, struct EditVert *v2);
/* ******************* editmesh_add.c */
extern void adduplicateflag(int flag);
/* ******************* editmesh_lib.c */
extern int editmesh_nfaces_selected(void);
extern int editmesh_nvertices_selected(void);
extern int faceselectedOR(EditFace *efa, int flag);
extern int faceselectedAND(EditFace *efa, int flag);
extern int exist_face(EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4);
extern void flipface(EditFace *efa); // flips for normal direction
extern int compareface(EditFace *vl1, EditFace *vl2);
extern void delfaceflag(int flag);
extern short extrudeflag(short flag,short type);
extern void rotateflag(short flag, float *cent, float rotmat[][3]);
extern void translateflag(short flag, float *vec);
extern float convex(float *v1, float *v2, float *v3, float *v4);
/* ******************* editmesh_mods.c */
extern EditEdge *findnearestedge();
/* ******************* editmesh_tools.c */
#endif

@ -59,12 +59,10 @@
// TODO check to see how many of these includes are necessary
#include "BLI_blenlib.h"
#include "BLI_editVert.h"
#include "BLI_arithb.h"
#include "BLI_linklist.h"
#include "BLI_memarena.h"
#include "BIF_editmesh.h"
#ifdef HAVE_CONFIG_H
#include <config.h>

@ -98,6 +98,7 @@
#include "BIF_editmesh.h"
#include "BIF_editsound.h"
#include "BIF_interface.h"
#include "BIF_meshtools.h"
#include "BIF_mywindow.h"
#include "BIF_renderwin.h"
#include "BIF_resources.h"

File diff suppressed because it is too large Load Diff

@ -0,0 +1,699 @@
/**
* $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");
}

@ -0,0 +1,736 @@
/**
* $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 *****
*/
/*
editmesh_lib: generic (no UI, no menus) operations/evaluators for editmesh data
*/
#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 "BLI_blenlib.h"
#include "BLI_arithb.h"
#include "BLI_editVert.h"
#include "BKE_global.h"
#include "BKE_mesh.h"
#include "BKE_utildefines.h"
#include "BIF_editmesh.h"
#include "editmesh.h"
/* ********************* */
int editmesh_nfaces_selected(void)
{
EditMesh *em = G.editMesh;
EditFace *efa;
int count= 0;
for (efa= em->faces.first; efa; efa= efa->next)
if (faceselectedAND(efa, SELECT))
count++;
return count;
}
int editmesh_nvertices_selected(void)
{
EditMesh *em = G.editMesh;
EditVert *eve;
int count= 0;
for (eve= em->verts.first; eve; eve= eve->next)
if (eve->f & SELECT)
count++;
return count;
}
/* ***************** */
short extrudeflag(short flag,short type)
{
/* when type=1 old extrusion faces are removed (for spin etc) */
/* all verts with (flag & 'flag'): extrude */
/* from old verts, 'flag' is cleared, in new ones it is set */
EditMesh *em = G.editMesh;
EditVert *eve, *v1, *v2, *v3, *v4, *nextve;
EditEdge *eed, *e1, *e2, *e3, *e4, *nexted;
EditFace *efa, *efa2, *nextvl;
short sel=0, deloud= 0, smooth= 0;
if(G.obedit==0 || get_mesh(G.obedit)==0) return 0;
/* clear vert flag f1, we use this to detext a loose selected vertice */
eve= em->verts.first;
while(eve) {
if(eve->f & flag) eve->f1= 1;
else eve->f1= 0;
eve= eve->next;
}
/* clear edges counter flag, if selected we set it at 1 */
eed= em->edges.first;
while(eed) {
if( (eed->v1->f & flag) && (eed->v2->f & flag) ) {
eed->f= 1;
eed->v1->f1= 0;
eed->v2->f1= 0;
}
else eed->f= 0;
eed->f1= 1; /* this indicates it is an 'old' edge (in this routine we make new ones) */
eed= eed->next;
}
/* we set a flag in all selected faces, and increase the associated edge counters */
efa= em->faces.first;
while(efa) {
efa->f= 0;
if (efa->flag & ME_SMOOTH) {
if (faceselectedOR(efa, 1)) smooth= 1;
}
if(faceselectedAND(efa, flag)) {
e1= efa->e1;
e2= efa->e2;
e3= efa->e3;
e4= efa->e4;
if(e1->f < 3) e1->f++;
if(e2->f < 3) e2->f++;
if(e3->f < 3) e3->f++;
if(e4 && e4->f < 3) e4->f++;
efa->f= 1;
}
else if(faceselectedOR(efa, flag)) {
e1= efa->e1;
e2= efa->e2;
e3= efa->e3;
e4= efa->e4;
if( (e1->v1->f & flag) && (e1->v2->f & flag) ) e1->f1= 2;
if( (e2->v1->f & flag) && (e2->v2->f & flag) ) e2->f1= 2;
if( (e3->v1->f & flag) && (e3->v2->f & flag) ) e3->f1= 2;
if( e4 && (e4->v1->f & flag) && (e4->v2->f & flag) ) e4->f1= 2;
}
efa= efa->next;
}
/* set direction of edges */
efa= em->faces.first;
while(efa) {
if(efa->f== 0) {
if(efa->e1->f==2) {
if(efa->e1->v1 == efa->v1) efa->e1->dir= 0;
else efa->e1->dir= 1;
}
if(efa->e2->f==2) {
if(efa->e2->v1 == efa->v2) efa->e2->dir= 0;
else efa->e2->dir= 1;
}
if(efa->e3->f==2) {
if(efa->e3->v1 == efa->v3) efa->e3->dir= 0;
else efa->e3->dir= 1;
}
if(efa->e4 && efa->e4->f==2) {
if(efa->e4->v1 == efa->v4) efa->e4->dir= 0;
else efa->e4->dir= 1;
}
}
efa= efa->next;
}
/* the current state now is:
eve->f1==1: loose selected vertex
eed->f==0 : edge is not selected, no extrude
eed->f==1 : edge selected, is not part of a face, extrude
eed->f==2 : edge selected, is part of 1 face, extrude
eed->f==3 : edge selected, is part of more faces, no extrude
eed->f1==0: new edge
eed->f1==1: edge selected, is part of selected face, when eed->f==3: remove
eed->f1==2: edge selected, is not part of a selected face
efa->f==1 : duplicate this face
*/
/* copy all selected vertices, */
/* write pointer to new vert in old struct at eve->vn */
eve= em->verts.last;
while(eve) {
eve->f&= ~128; /* clear, for later test for loose verts */
if(eve->f & flag) {
sel= 1;
v1= addvertlist(0);
VECCOPY(v1->co, eve->co);
v1->f= eve->f;
eve->f-= flag;
eve->vn= v1;
}
else eve->vn= 0;
eve= eve->prev;
}
if(sel==0) return 0;
/* all edges with eed->f==1 or eed->f==2 become faces */
/* if deloud==1 then edges with eed->f>2 are removed */
eed= em->edges.last;
while(eed) {
nexted= eed->prev;
if( eed->f<3) {
eed->v1->f|=128; /* = no loose vert! */
eed->v2->f|=128;
}
if( (eed->f==1 || eed->f==2) ) {
if(eed->f1==2) deloud=1;
if(eed->dir==1) efa2= addfacelist(eed->v1, eed->v2, eed->v2->vn, eed->v1->vn, NULL);
else efa2= addfacelist(eed->v2, eed->v1, eed->v1->vn, eed->v2->vn, NULL);
if (smooth) efa2->flag |= ME_SMOOTH;
/* Needs smarter adaption of existing creases.
* If addedgelist is used, make sure seams are set to 0 on these
* new edges, since we do not want to add any seams on extrusion.
*/
efa2->e1->crease= eed->crease;
efa2->e2->crease= eed->crease;
efa2->e3->crease= eed->crease;
if(efa2->e4) efa2->e4->crease= eed->crease;
}
eed= nexted;
}
if(deloud) {
eed= em->edges.first;
while(eed) {
nexted= eed->next;
if(eed->f==3 && eed->f1==1) {
remedge(eed);
free_editedge(eed);
}
eed= nexted;
}
}
/* duplicate faces, if necessart remove old ones */
efa= em->faces.first;
while(efa) {
nextvl= efa->next;
if(efa->f & 1) {
v1= efa->v1->vn;
v2= efa->v2->vn;
v3= efa->v3->vn;
if(efa->v4) v4= efa->v4->vn; else v4= 0;
efa2= addfacelist(v1, v2, v3, v4, efa);
if(deloud) {
BLI_remlink(&em->faces, efa);
free_editface(efa);
}
if (smooth) efa2->flag |= ME_SMOOTH;
}
efa= nextvl;
}
/* for all vertices with eve->vn!=0
if eve->f1==1: make edge
if flag!=128 : if deloud==1: remove
*/
eve= em->verts.last;
while(eve) {
nextve= eve->prev;
if(eve->vn) {
if(eve->f1==1) addedgelist(eve, eve->vn, NULL);
else if( (eve->f & 128)==0) {
if(deloud) {
BLI_remlink(&em->verts,eve);
free_editvert(eve);
eve= NULL;
}
}
}
if(eve) eve->f&= ~128;
eve= nextve;
}
return 1;
}
void rotateflag(short flag, float *cent, float rotmat[][3])
{
/* all verts with (flag & 'flag') rotate */
EditMesh *em = G.editMesh;
EditVert *eve;
eve= em->verts.first;
while(eve) {
if(eve->f & flag) {
eve->co[0]-=cent[0];
eve->co[1]-=cent[1];
eve->co[2]-=cent[2];
Mat3MulVecfl(rotmat,eve->co);
eve->co[0]+=cent[0];
eve->co[1]+=cent[1];
eve->co[2]+=cent[2];
}
eve= eve->next;
}
}
void translateflag(short flag, float *vec)
{
/* all verts with (flag & 'flag') translate */
EditMesh *em = G.editMesh;
EditVert *eve;
eve= em->verts.first;
while(eve) {
if(eve->f & flag) {
eve->co[0]+=vec[0];
eve->co[1]+=vec[1];
eve->co[2]+=vec[2];
}
eve= eve->next;
}
}
void delfaceflag(int flag)
{
EditMesh *em = G.editMesh;
/* delete all faces with 'flag', including edges and loose vertices */
/* in vertices the 'flag' is cleared */
EditVert *eve,*nextve;
EditEdge *eed, *nexted;
EditFace *efa,*nextvl;
eed= em->edges.first;
while(eed) {
eed->f= 0;
eed= eed->next;
}
efa= em->faces.first;
while(efa) {
nextvl= efa->next;
if(faceselectedAND(efa, flag)) {
efa->e1->f= 1;
efa->e2->f= 1;
efa->e3->f= 1;
if(efa->e4) {
efa->e4->f= 1;
}
BLI_remlink(&em->faces, efa);
free_editface(efa);
}
efa= nextvl;
}
/* all faces with 1, 2 (3) vertices selected: make sure we keep the edges */
efa= em->faces.first;
while(efa) {
efa->e1->f= 0;
efa->e2->f= 0;
efa->e3->f= 0;
if(efa->e4) {
efa->e4->f= 0;
}
efa= efa->next;
}
/* test all edges for vertices with 'flag', and clear */
eed= em->edges.first;
while(eed) {
nexted= eed->next;
if(eed->f==1) {
remedge(eed);
free_editedge(eed);
}
else if( (eed->v1->f & flag) || (eed->v2->f & flag) ) {
eed->v1->f&= ~flag;
eed->v2->f&= ~flag;
}
eed= nexted;
}
/* vertices with 'flag' now are the loose ones, and will be removed */
eve= em->verts.first;
while(eve) {
nextve= eve->next;
if(eve->f & flag) {
BLI_remlink(&em->verts, eve);
free_editvert(eve);
}
eve= nextve;
}
}
/* ********************* */
static int contrpuntnorm(float *n, float *puno) /* dutch: check vertex normal */
{
float inp;
inp= n[0]*puno[0]+n[1]*puno[1]+n[2]*puno[2];
/* angles 90 degrees: dont flip */
if(inp> -0.000001) return 0;
return 1;
}
void vertexnormals(int testflip)
{
EditMesh *em = G.editMesh;
Mesh *me;
EditVert *eve;
EditFace *efa;
float n1[3], n2[3], n3[3], n4[3], co[4], fac1, fac2, fac3, fac4, *temp;
float *f1, *f2, *f3, *f4, xn, yn, zn;
float len;
if(G.obedit && G.obedit->type==OB_MESH) {
me= G.obedit->data;
if((me->flag & ME_TWOSIDED)==0) testflip= 0;
}
if(G.totvert==0) return;
if(G.totface==0) {
/* fake vertex normals for 'halo puno'! */
eve= em->verts.first;
while(eve) {
VECCOPY(eve->no, eve->co);
Normalise( (float *)eve->no);
eve= eve->next;
}
return;
}
/* clear normals */
eve= em->verts.first;
while(eve) {
eve->no[0]= eve->no[1]= eve->no[2]= 0.0;
eve= eve->next;
}
/* calculate cosine angles and add to vertex normal */
efa= em->faces.first;
while(efa) {
VecSubf(n1, efa->v2->co, efa->v1->co);
VecSubf(n2, efa->v3->co, efa->v2->co);
Normalise(n1);
Normalise(n2);
if(efa->v4==0) {
VecSubf(n3, efa->v1->co, efa->v3->co);
Normalise(n3);
co[0]= saacos(-n3[0]*n1[0]-n3[1]*n1[1]-n3[2]*n1[2]);
co[1]= saacos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]);
co[2]= saacos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]);
}
else {
VecSubf(n3, efa->v4->co, efa->v3->co);
VecSubf(n4, efa->v1->co, efa->v4->co);
Normalise(n3);
Normalise(n4);
co[0]= saacos(-n4[0]*n1[0]-n4[1]*n1[1]-n4[2]*n1[2]);
co[1]= saacos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]);
co[2]= saacos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]);
co[3]= saacos(-n3[0]*n4[0]-n3[1]*n4[1]-n3[2]*n4[2]);
}
temp= efa->v1->no;
if(testflip && contrpuntnorm(efa->n, temp) ) co[0]= -co[0];
temp[0]+= co[0]*efa->n[0];
temp[1]+= co[0]*efa->n[1];
temp[2]+= co[0]*efa->n[2];
temp= efa->v2->no;
if(testflip && contrpuntnorm(efa->n, temp) ) co[1]= -co[1];
temp[0]+= co[1]*efa->n[0];
temp[1]+= co[1]*efa->n[1];
temp[2]+= co[1]*efa->n[2];
temp= efa->v3->no;
if(testflip && contrpuntnorm(efa->n, temp) ) co[2]= -co[2];
temp[0]+= co[2]*efa->n[0];
temp[1]+= co[2]*efa->n[1];
temp[2]+= co[2]*efa->n[2];
if(efa->v4) {
temp= efa->v4->no;
if(testflip && contrpuntnorm(efa->n, temp) ) co[3]= -co[3];
temp[0]+= co[3]*efa->n[0];
temp[1]+= co[3]*efa->n[1];
temp[2]+= co[3]*efa->n[2];
}
efa= efa->next;
}
/* normalise vertex normals */
eve= em->verts.first;
while(eve) {
len= Normalise(eve->no);
if(len==0.0) {
VECCOPY(eve->no, eve->co);
Normalise( eve->no);
}
eve= eve->next;
}
/* vertex normal flip-flags for shade (render) */
efa= em->faces.first;
while(efa) {
efa->f=0;
if(testflip) {
f1= efa->v1->no;
f2= efa->v2->no;
f3= efa->v3->no;
fac1= efa->n[0]*f1[0] + efa->n[1]*f1[1] + efa->n[2]*f1[2];
if(fac1<0.0) {
efa->f = ME_FLIPV1;
}
fac2= efa->n[0]*f2[0] + efa->n[1]*f2[1] + efa->n[2]*f2[2];
if(fac2<0.0) {
efa->f += ME_FLIPV2;
}
fac3= efa->n[0]*f3[0] + efa->n[1]*f3[1] + efa->n[2]*f3[2];
if(fac3<0.0) {
efa->f += ME_FLIPV3;
}
if(efa->v4) {
f4= efa->v4->no;
fac4= efa->n[0]*f4[0] + efa->n[1]*f4[1] + efa->n[2]*f4[2];
if(fac4<0.0) {
efa->f += ME_FLIPV4;
}
}
}
/* projection for cubemap! */
xn= fabs(efa->n[0]);
yn= fabs(efa->n[1]);
zn= fabs(efa->n[2]);
if(zn>xn && zn>yn) efa->f += ME_PROJXY;
else if(yn>xn && yn>zn) efa->f += ME_PROJXZ;
else efa->f += ME_PROJYZ;
efa= efa->next;
}
}
void flipface(EditFace *efa)
{
if(efa->v4) {
SWAP(EditVert *, efa->v2, efa->v4);
SWAP(EditEdge *, efa->e1, efa->e4);
SWAP(EditEdge *, efa->e2, efa->e3);
SWAP(unsigned int, efa->tf.col[1], efa->tf.col[3]);
SWAP(float, efa->tf.uv[1][0], efa->tf.uv[3][0]);
SWAP(float, efa->tf.uv[1][1], efa->tf.uv[3][1]);
}
else {
SWAP(EditVert *, efa->v2, efa->v3);
SWAP(EditEdge *, efa->e1, efa->e3);
SWAP(unsigned int, efa->tf.col[1], efa->tf.col[2]);
efa->e2->dir= 1-efa->e2->dir;
SWAP(float, efa->tf.uv[1][0], efa->tf.uv[2][0]);
SWAP(float, efa->tf.uv[1][1], efa->tf.uv[2][1]);
}
if(efa->v4) CalcNormFloat4(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co, efa->n);
else CalcNormFloat(efa->v1->co, efa->v2->co, efa->v3->co, efa->n);
}
void flip_editnormals(void)
{
EditMesh *em = G.editMesh;
EditFace *efa;
efa= em->faces.first;
while(efa) {
if( faceselectedAND(efa, 1) ) {
flipface(efa);
}
efa= efa->next;
}
}
void recalc_editnormals(void)
{
EditMesh *em = G.editMesh;
EditFace *efa;
efa= em->faces.first;
while(efa) {
if(efa->v4) CalcNormFloat4(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co, efa->n);
else CalcNormFloat(efa->v1->co, efa->v2->co, efa->v3->co, efa->n);
efa= efa->next;
}
}
int faceselectedOR(EditFace *efa, int flag)
{
if(efa->v1->f & flag) return 1;
if(efa->v2->f & flag) return 1;
if(efa->v3->f & flag) return 1;
if(efa->v4 && (efa->v4->f & 1)) return 1;
return 0;
}
int faceselectedAND(EditFace *efa, int flag)
{
if(efa->v1->f & flag) {
if(efa->v2->f & flag) {
if(efa->v3->f & flag) {
if(efa->v4) {
if(efa->v4->f & flag) return 1;
}
else return 1;
}
}
}
return 0;
}
int compareface(EditFace *vl1, EditFace *vl2)
{
EditVert *v1, *v2, *v3, *v4;
if(vl1->v4 && vl2->v4) {
v1= vl2->v1;
v2= vl2->v2;
v3= vl2->v3;
v4= vl2->v4;
if(vl1->v1==v1 || vl1->v2==v1 || vl1->v3==v1 || vl1->v4==v1) {
if(vl1->v1==v2 || vl1->v2==v2 || vl1->v3==v2 || vl1->v4==v2) {
if(vl1->v1==v3 || vl1->v2==v3 || vl1->v3==v3 || vl1->v4==v3) {
if(vl1->v1==v4 || vl1->v2==v4 || vl1->v3==v4 || vl1->v4==v4) {
return 1;
}
}
}
}
}
else if(vl1->v4==0 && vl2->v4==0) {
v1= vl2->v1;
v2= vl2->v2;
v3= vl2->v3;
if(vl1->v1==v1 || vl1->v2==v1 || vl1->v3==v1) {
if(vl1->v1==v2 || vl1->v2==v2 || vl1->v3==v2) {
if(vl1->v1==v3 || vl1->v2==v3 || vl1->v3==v3) {
return 1;
}
}
}
}
return 0;
}
int exist_face(EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4)
{
EditMesh *em = G.editMesh;
EditFace *efa, efatest;
efatest.v1= v1;
efatest.v2= v2;
efatest.v3= v3;
efatest.v4= v4;
efa= em->faces.first;
while(efa) {
if(compareface(&efatest, efa)) return 1;
efa= efa->next;
}
return 0;
}
float convex(float *v1, float *v2, float *v3, float *v4)
{
float cross[3], test[3];
float inpr;
CalcNormFloat(v1, v2, v3, cross);
CalcNormFloat(v1, v3, v4, test);
inpr= cross[0]*test[0]+cross[1]*test[1]+cross[2]*test[2];
return inpr;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -95,6 +95,7 @@
#include "BIF_editview.h"
#include "BIF_interface.h"
#include "BIF_mainqueue.h"
#include "BIF_meshtools.h"
#include "BIF_poseobject.h"
#include "BIF_renderwin.h"
#include "BIF_resources.h"

@ -0,0 +1,883 @@
/**
* $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 *****
*/
/*
meshtools.c: no editmode, tools operating on meshes
void join_mesh(void);
void make_sticky(void);
void fasterdraw(void);
void slowerdraw(void);
void vertexnormals_mesh(Mesh *me, float *extverts);
void sort_faces(void);
*/
#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_material_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 "BKE_displist.h"
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_material.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 "mydevice.h"
#include "blendef.h"
#include "render.h" // bad level call (ton)
/* * ********************** no editmode!!! *********** */
/** tests whether selected mesh objects have tfaces */
static int testSelected_TfaceMesh(void)
{
Base *base;
Mesh *me;
base = FIRSTBASE;
while (base) {
if TESTBASE(base) {
if(base->object->type==OB_MESH) {
me= base->object->data;
if (me->tface)
return 1;
}
}
base= base->next;
}
return 0;
}
void join_mesh(void)
{
Base *base, *nextb;
Object *ob;
Material **matar, *ma;
Mesh *me;
MVert *mvert, *mvertmain;
MEdge *medge = NULL, *medgemain;
MFace *mface = NULL, *mfacemain;
TFace *tface = NULL, *tfacemain;
unsigned int *mcol=NULL, *mcolmain;
float imat[4][4], cmat[4][4];
int a, b, totcol, totedge=0, totvert=0, totface=0, ok=0, vertofs, map[MAXMAT];
int hasedges=0;
int i, j, index, haskey=0;
bDeformGroup *dg, *odg;
MDeformVert *dvert, *dvertmain;
if(G.obedit) return;
ob= OBACT;
if(!ob || ob->type!=OB_MESH) return;
/* count */
base= FIRSTBASE;
while(base) {
if TESTBASE(base) {
if(base->object->type==OB_MESH) {
me= base->object->data;
totvert+= me->totvert;
totface+= me->totface;
if(me->medge) hasedges= 1;
if(base->object == ob) ok= 1;
if(me->key) {
haskey= 1;
break;
}
}
}
base= base->next;
}
if(haskey) {
error("Can't join meshes with vertex keys");
return;
}
/* that way the active object is always selected */
if(ok==0) return;
if(totvert==0 || totvert>MESH_MAX_VERTS) return;
if(okee("Join selected meshes")==0) return;
/* if needed add edges to other meshes */
if(hasedges) {
for(base= FIRSTBASE; base; base= base->next) {
if TESTBASE(base) {
if(base->object->type==OB_MESH) {
me= base->object->data;
if(me->medge==NULL) make_edges(me);
totedge += me->totedge;
}
}
}
}
/* new material indices and material array */
matar= MEM_callocN(sizeof(void *)*MAXMAT, "join_mesh");
totcol= ob->totcol;
/* obact materials in new main array, is nicer start! */
for(a=1; a<=ob->totcol; a++) {
matar[a-1]= give_current_material(ob, a);
id_us_plus((ID *)matar[a-1]);
/* increase id->us : will be lowered later */
}
base= FIRSTBASE;
while(base) {
if TESTBASE(base) {
if(ob!=base->object && base->object->type==OB_MESH) {
me= base->object->data;
// Join this object's vertex groups to the base one's
for (dg=base->object->defbase.first; dg; dg=dg->next){
/* See if this group exists in the object */
for (odg=ob->defbase.first; odg; odg=odg->next){
if (!strcmp(odg->name, dg->name)){
break;
}
}
if (!odg){
odg = MEM_callocN (sizeof(bDeformGroup), "deformGroup");
memcpy (odg, dg, sizeof(bDeformGroup));
BLI_addtail(&ob->defbase, odg);
}
}
if (ob->defbase.first && ob->actdef==0)
ob->actdef=1;
if(me->totvert) {
for(a=1; a<=base->object->totcol; a++) {
ma= give_current_material(base->object, a);
if(ma) {
for(b=0; b<totcol; b++) {
if(ma == matar[b]) break;
}
if(b==totcol) {
matar[b]= ma;
ma->id.us++;
totcol++;
}
if(totcol>=MAXMAT-1) break;
}
}
}
}
if(totcol>=MAXMAT-1) break;
}
base= base->next;
}
me= ob->data;
mvert= mvertmain= MEM_mallocN(totvert*sizeof(MVert), "joinmesh vert");
if(totedge) medge= medgemain= MEM_callocN(totedge*sizeof(MEdge), "joinmesh edge");
else medgemain= NULL;
if (totface) mface= mfacemain= MEM_mallocN(totface*sizeof(MFace), "joinmesh face");
else mfacemain= NULL;
if(me->mcol) mcol= mcolmain= MEM_callocN(totface*4*sizeof(int), "joinmesh mcol");
else mcolmain= NULL;
/* if active object doesn't have Tfaces, but one in the selection does,
make TFaces for active, so we don't lose texture information in the
join process */
if(me->tface || testSelected_TfaceMesh()) tface= tfacemain= MEM_callocN(totface*4*sizeof(TFace), "joinmesh4");
else tfacemain= NULL;
if(me->dvert)
dvert= dvertmain= MEM_callocN(totvert*sizeof(MDeformVert), "joinmesh5");
else dvert=dvertmain= NULL;
vertofs= 0;
/* inverse transorm all selected meshes in this object */
Mat4Invert(imat, ob->obmat);
base= FIRSTBASE;
while(base) {
nextb= base->next;
if TESTBASE(base) {
if(base->object->type==OB_MESH) {
me= base->object->data;
if(me->totvert) {
memcpy(mvert, me->mvert, me->totvert*sizeof(MVert));
copy_dverts(dvert, me->dvert, me->totvert);
/* NEW VERSION */
if (dvertmain){
for (i=0; i<me->totvert; i++){
for (j=0; j<dvert[i].totweight; j++){
// Find the old vertex group
odg = BLI_findlink (&base->object->defbase, dvert[i].dw[j].def_nr);
if(odg) {
// Search for a match in the new object
for (dg=ob->defbase.first, index=0; dg; dg=dg->next, index++){
if (!strcmp(dg->name, odg->name)){
dvert[i].dw[j].def_nr = index;
break;
}
}
}
}
}
dvert+=me->totvert;
}
if(base->object != ob) {
/* watch this: switch matmul order really goes wrong */
Mat4MulMat4(cmat, base->object->obmat, imat);
a= me->totvert;
while(a--) {
Mat4MulVecfl(cmat, mvert->co);
mvert++;
}
}
else mvert+= me->totvert;
if(mcolmain) {
if(me->mcol) memcpy(mcol, me->mcol, me->totface*4*4);
mcol+= 4*me->totface;
}
}
if(me->totface) {
/* make mapping for materials */
memset(map, 0, 4*MAXMAT);
for(a=1; a<=base->object->totcol; a++) {
ma= give_current_material(base->object, a);
if(ma) {
for(b=0; b<totcol; b++) {
if(ma == matar[b]) {
map[a-1]= b;
break;
}
}
}
}
memcpy(mface, me->mface, me->totface*sizeof(MFace));
a= me->totface;
while(a--) {
mface->v1+= vertofs;
mface->v2+= vertofs;
if(mface->v3) mface->v3+= vertofs;
if(mface->v4) mface->v4+= vertofs;
mface->mat_nr= map[(int)mface->mat_nr];
mface++;
}
if(tfacemain) {
if(me->tface) memcpy(tface, me->tface, me->totface*sizeof(TFace));
tface+= me->totface;
}
}
if(me->totedge) {
memcpy(medge, me->medge, me->totedge*sizeof(MEdge));
a= me->totedge;
while(a--) {
medge->v1+= vertofs;
medge->v2+= vertofs;
medge++;
}
}
vertofs+= me->totvert;
if(base->object!=ob) {
free_and_unlink_base(base);
}
}
}
base= nextb;
}
me= ob->data;
if(me->mvert) MEM_freeN(me->mvert);
me->mvert= mvertmain;
if(me->medge) MEM_freeN(me->medge);
me->medge= medgemain;
if(me->mface) MEM_freeN(me->mface);
me->mface= mfacemain;
if(me->dvert) free_dverts(me->dvert, me->totvert);
me->dvert = dvertmain;
if(me->mcol) MEM_freeN(me->mcol);
me->mcol= (MCol *)mcolmain;
if(me->tface) MEM_freeN(me->tface);
me->tface= tfacemain;
me->totvert= totvert;
me->totedge= totedge;
me->totface= totface;
/* old material array */
for(a=1; a<=ob->totcol; a++) {
ma= ob->mat[a-1];
if(ma) ma->id.us--;
}
for(a=1; a<=me->totcol; a++) {
ma= me->mat[a-1];
if(ma) ma->id.us--;
}
if(ob->mat) MEM_freeN(ob->mat);
if(me->mat) MEM_freeN(me->mat);
ob->mat= me->mat= 0;
if(totcol) {
me->mat= matar;
ob->mat= MEM_callocN(sizeof(void *)*totcol, "join obmatar");
}
else MEM_freeN(matar);
ob->totcol= me->totcol= totcol;
ob->colbits= 0;
/* other mesh users */
test_object_materials((ID *)me);
enter_editmode();
exit_editmode(1); // freedata, but no undo
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWBUTSSHADING, 0);
makeDispList(ob);
BIF_undo_push("Join Mesh");
}
void make_sticky(void)
{
Object *ob;
Base *base;
MVert *mvert;
Mesh *me;
MSticky *ms;
float ho[4], mat[4][4];
int a;
if(G.scene->camera==0) return;
if(G.obedit) {
error("Unable to make sticky in Edit Mode");
return;
}
base= FIRSTBASE;
while(base) {
if TESTBASELIB(base) {
if(base->object->type==OB_MESH) {
ob= base->object;
me= ob->data;
mvert= me->mvert;
if(me->msticky) MEM_freeN(me->msticky);
me->msticky= MEM_mallocN(me->totvert*sizeof(MSticky), "sticky");
/* like convert to render data */
R.r= G.scene->r;
R.r.xsch= (R.r.size*R.r.xsch)/100;
R.r.ysch= (R.r.size*R.r.ysch)/100;
R.afmx= R.r.xsch/2;
R.afmy= R.r.ysch/2;
R.ycor= ( (float)R.r.yasp)/( (float)R.r.xasp);
R.rectx= R.r.xsch;
R.recty= R.r.ysch;
R.xstart= -R.afmx;
R.ystart= -R.afmy;
R.xend= R.xstart+R.rectx-1;
R.yend= R.ystart+R.recty-1;
where_is_object(G.scene->camera);
Mat4CpyMat4(R.viewinv, G.scene->camera->obmat);
Mat4Ortho(R.viewinv);
Mat4Invert(R.viewmat, R.viewinv);
RE_setwindowclip(1, -1);
where_is_object(ob);
Mat4MulMat4(mat, ob->obmat, R.viewmat);
ms= me->msticky;
for(a=0; a<me->totvert; a++, ms++, mvert++) {
VECCOPY(ho, mvert->co);
Mat4MulVecfl(mat, ho);
RE_projectverto(ho, ho);
ms->co[0]= ho[0]/ho[3];
ms->co[1]= ho[1]/ho[3];
}
}
}
base= base->next;
}
allqueue(REDRAWBUTSEDIT, 0);
}
void fasterdraw(void)
{
Base *base;
Mesh *me;
MFace *mface;
int toggle, a;
if(G.obedit) return;
/* reset flags */
me= G.main->mesh.first;
while(me) {
me->flag &= ~ME_ISDONE;
me= me->id.next;
}
base= FIRSTBASE;
while(base) {
if( TESTBASELIB(base) && (base->object->type==OB_MESH)) {
me= base->object->data;
if(me->id.lib==0 && (me->flag & ME_ISDONE)==0) {
me->flag |= ME_ISDONE;
mface= me->mface;
toggle= 0;
for(a=0; a<me->totface; a++) {
if( (mface->edcode & ME_V1V2) && ( (toggle++) & 1) ) {
mface->edcode-= ME_V1V2;
}
if( (mface->edcode & ME_V2V3) && ( (toggle++) & 1)) {
mface->edcode-= ME_V2V3;
}
if( (mface->edcode & ME_V3V1) && ( (toggle++) & 1)) {
mface->edcode-= ME_V3V1;
}
if( (mface->edcode & ME_V4V1) && ( (toggle++) & 1)) {
mface->edcode-= ME_V4V1;
}
if( (mface->edcode & ME_V3V4) && ( (toggle++) & 1)) {
mface->edcode-= ME_V3V4;
}
mface++;
}
}
}
base= base->next;
}
/* important?: reset flags again */
me= G.main->mesh.first;
while(me) {
me->flag &= ~ME_ISDONE;
me= me->id.next;
}
allqueue(REDRAWVIEW3D, 0);
}
void slowerdraw(void) /* reset fasterdraw */
{
Base *base;
Mesh *me;
MFace *mface;
int a;
if(G.obedit) return;
base= FIRSTBASE;
while(base) {
if( TESTBASELIB(base) && (base->object->type==OB_MESH)) {
me= base->object->data;
if(me->id.lib==0) {
mface= me->mface;
for(a=0; a<me->totface; a++) {
mface->edcode |= ME_V1V2|ME_V2V3;
mface++;
}
}
}
base= base->next;
}
allqueue(REDRAWVIEW3D, 0);
}
/* ***************** */
/* this one for NOT in editmode
(only used by external modules, that is, until now by the
python NMesh module)
TODO: Probably it's better to convert the mesh into a EditMesh, call
vertexnormals() and convert it back to a Mesh again.
*/
static int contrpuntnorm(float *n, float *puno) /* dutch: check vertex normal */
{
float inp;
inp= n[0]*puno[0]+n[1]*puno[1]+n[2]*puno[2];
/* angles 90 degrees: dont flip */
if(inp> -0.000001) return 0;
return 1;
}
void vertexnormals_mesh(Mesh *me, float *extverts)
{
MVert *mvert;
MFace *mface;
float n1[3], n2[3], n3[3], n4[3], co[4], fac1, fac2, fac3, fac4, *temp;
float *f1, *f2, *f3, *f4, xn, yn, zn, *normals;
float *v1, *v2, *v3, *v4, len, vnor[3];
int a, testflip;
if(me->totvert==0) return;
testflip= (me->flag & ME_NOPUNOFLIP)==0;
if((me->flag & ME_TWOSIDED)==0) testflip= 0; /* large angles */
if(me->totface==0) {
/* fake vertex normals for 'halopuno' (render option) */
mvert= me->mvert;
for(a=0; a<me->totvert; a++, mvert++) {
VECCOPY(n1, mvert->co);
Normalise(n1);
mvert->no[0]= 32767.0*n1[0];
mvert->no[1]= 32767.0*n1[1];
mvert->no[2]= 32767.0*n1[2];
}
return;
}
normals= MEM_callocN(me->totvert*3*sizeof(float), "normals");
/* calculate cosine angles, and add to vertex normal */
mface= me->mface;
mvert= me->mvert;
for(a=0; a<me->totface; a++, mface++) {
if(mface->v3==0) continue;
if(extverts) {
v1= extverts+3*mface->v1;
v2= extverts+3*mface->v2;
v3= extverts+3*mface->v3;
v4= extverts+3*mface->v4;
}
else {
v1= (mvert+mface->v1)->co;
v2= (mvert+mface->v2)->co;
v3= (mvert+mface->v3)->co;
v4= (mvert+mface->v4)->co;
}
VecSubf(n1, v2, v1);
VecSubf(n2, v3, v2);
Normalise(n1);
Normalise(n2);
if(mface->v4==0) {
VecSubf(n3, v1, v3);
Normalise(n3);
co[0]= saacos(-n3[0]*n1[0]-n3[1]*n1[1]-n3[2]*n1[2]);
co[1]= saacos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]);
co[2]= saacos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]);
}
else {
VecSubf(n3, v4, v3);
VecSubf(n4, v1, v4);
Normalise(n3);
Normalise(n4);
co[0]= saacos(-n4[0]*n1[0]-n4[1]*n1[1]-n4[2]*n1[2]);
co[1]= saacos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]);
co[2]= saacos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]);
co[3]= saacos(-n3[0]*n4[0]-n3[1]*n4[1]-n3[2]*n4[2]);
}
CalcNormFloat(v1, v2, v3, vnor);
temp= normals+3*mface->v1;
if(testflip && contrpuntnorm(vnor, temp) ) co[0]= -co[0];
temp[0]+= co[0]*vnor[0];
temp[1]+= co[0]*vnor[1];
temp[2]+= co[0]*vnor[2];
temp= normals+3*mface->v2;
if(testflip && contrpuntnorm(vnor, temp) ) co[1]= -co[1];
temp[0]+= co[1]*vnor[0];
temp[1]+= co[1]*vnor[1];
temp[2]+= co[1]*vnor[2];
temp= normals+3*mface->v3;
if(testflip && contrpuntnorm(vnor, temp) ) co[2]= -co[2];
temp[0]+= co[2]*vnor[0];
temp[1]+= co[2]*vnor[1];
temp[2]+= co[2]*vnor[2];
if(mface->v4) {
temp= normals+3*mface->v4;
if(testflip && contrpuntnorm(vnor, temp) ) co[3]= -co[3];
temp[0]+= co[3]*vnor[0];
temp[1]+= co[3]*vnor[1];
temp[2]+= co[3]*vnor[2];
}
}
/* normalize vertex normals */
mvert= me->mvert;
for(a=0; a<me->totvert; a++, mvert++) {
len= Normalise(normals+3*a);
if(len!=0.0) {
VECCOPY(n1, normals+3*a);
Normalise(n1);
mvert->no[0]= 32767.0*n1[0];
mvert->no[1]= 32767.0*n1[1];
mvert->no[2]= 32767.0*n1[2];
}
}
/* vertex normal flipping flags, for during render */
mface= me->mface;
mvert= me->mvert;
for(a=0; a<me->totface; a++, mface++) {
mface->puno=0;
if(mface->v3==0) continue;
if(extverts) {
v1= extverts+3*mface->v1;
v2= extverts+3*mface->v2;
v3= extverts+3*mface->v3;
}
else {
v1= (mvert+mface->v1)->co;
v2= (mvert+mface->v2)->co;
v3= (mvert+mface->v3)->co;
}
CalcNormFloat(v1, v2, v3, vnor);
if(testflip) {
f1= normals + 3*mface->v1;
f2= normals + 3*mface->v2;
f3= normals + 3*mface->v3;
fac1= vnor[0]*f1[0] + vnor[1]*f1[1] + vnor[2]*f1[2];
if(fac1<0.0) {
mface->puno = ME_FLIPV1;
}
fac2= vnor[0]*f2[0] + vnor[1]*f2[1] + vnor[2]*f2[2];
if(fac2<0.0) {
mface->puno += ME_FLIPV2;
}
fac3= vnor[0]*f3[0] + vnor[1]*f3[1] + vnor[2]*f3[2];
if(fac3<0.0) {
mface->puno += ME_FLIPV3;
}
if(mface->v4) {
f4= normals + 3*mface->v4;
fac4= vnor[0]*f4[0] + vnor[1]*f4[1] + vnor[2]*f4[2];
if(fac4<0.0) {
mface->puno += ME_FLIPV4;
}
}
}
/* proj for cubemap! */
xn= fabs(vnor[0]);
yn= fabs(vnor[1]);
zn= fabs(vnor[2]);
if(zn>xn && zn>yn) mface->puno += ME_PROJXY;
else if(yn>xn && yn>zn) mface->puno += ME_PROJXZ;
else mface->puno += ME_PROJYZ;
}
MEM_freeN(normals);
}
/* ********************** SORT FACES ******************* */
static void permutate(void *list, int num, int size, int *index)
{
void *buf;
int len;
int i;
len = num * size;
buf = MEM_mallocN(len, "permutate");
memcpy(buf, list, len);
for (i = 0; i < num; i++) {
memcpy((char *)list + (i * size), (char *)buf + (index[i] * size), size);
}
MEM_freeN(buf);
}
static MVert *mvertbase;
static MFace *mfacebase;
static int verg_mface(const void *v1, const void *v2)
{
MFace *x1, *x2;
MVert *ve1, *ve2;
int i1, i2;
i1 = ((int *) v1)[0];
i2 = ((int *) v2)[0];
x1 = mfacebase + i1;
x2 = mfacebase + i2;
ve1= mvertbase+x1->v1;
ve2= mvertbase+x2->v1;
if( ve1->co[2] > ve2->co[2] ) return 1;
else if( ve1->co[2] < ve2->co[2]) return -1;
return 0;
}
void sort_faces(void)
{
Object *ob= OBACT;
Mesh *me;
int i, *index;
if(ob==0) return;
if(G.obedit) return;
if(ob->type!=OB_MESH) return;
if(okee("Sort faces in Z axis")==0) return;
me= ob->data;
if(me->totface==0) return;
/* create index list */
index = (int *) MEM_mallocN(sizeof(int) * me->totface, "sort faces");
for (i = 0; i < me->totface; i++) {
index[i] = i;
}
mvertbase= me->mvert;
mfacebase = me->mface;
/* sort index list instead of faces itself
and apply this permutation to the face list plus
to the texture faces */
qsort(index, me->totface, sizeof(int), verg_mface);
permutate(mfacebase, me->totface, sizeof(MFace), index);
if (me->tface)
permutate(me->tface, me->totface, sizeof(TFace), index);
MEM_freeN(index);
allqueue(REDRAWVIEW3D, 0);
makeDispList(G.obedit);
}

@ -100,6 +100,7 @@
#include "BIF_gl.h"
#include "BIF_imasel.h"
#include "BIF_interface.h"
#include "BIF_meshtools.h"
#include "BIF_mywindow.h"
#include "BIF_oops.h"
#include "BIF_resources.h"

@ -564,7 +564,6 @@ void exit_usiblender(void)
free_posebuf();
free_blender(); /* blender.c, does entire library */
free_hashedgetab();
free_matcopybuf();
free_ipocopybuf();
freefastshade();