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:
2004-09-19 11:47:49 +00:00
parent dab46067bf
commit ca5b7386e5
15 changed files with 9449 additions and 8819 deletions

View File

@@ -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,115 +42,11 @@ 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);
/* 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.c */
extern void make_editMesh(void);
extern void load_editMesh(void);
extern void free_editMesh(void);
extern void remake_editMesh(void);
/* Editmesh Undo code */
void undo_free_mesh(struct Mesh *me);
@@ -158,21 +56,90 @@ void undo_redo_mesh(void);
void undo_clear_mesh(void);
void undo_menu_mesh(void);
extern void separatemenu(void);
extern void separate_mesh(void);
extern void separate_mesh_loose(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);
/* ******************* 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);
/* ******************* 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 */
void select_non_manifold(void);
void select_more(void);
void select_less(void);
void selectrandom_mesh(void);
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);
void Edge_Menu(void);
extern void Edge_Menu(void);
extern void editmesh_mark_seam(int clear);
void editmesh_select_by_material(int index);
void editmesh_deselect_by_material(int index);
/* ******************* editmesh_loop.c */
void editmesh_mark_seam(int clear);
#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

View File

@@ -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

View File

@@ -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

View File

@@ -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>

View File

@@ -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

View File

@@ -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");
}

View File

@@ -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

View File

@@ -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"

View File

@@ -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);
}

View File

@@ -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"

View File

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