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:
883
source/blender/src/meshtools.c
Normal file
883
source/blender/src/meshtools.c
Normal 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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user