This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/src/editmesh.c
Kent Mein fd05cdbaad Ok this should have probably been three seperate things but I figured
some people are getting sick of the email and the comments are small.

editmesh.c I added casts in a couple of places to remove a few warnings.

Then I cleaned up configure.ac a bit specifically the checks for
--with-ssl etc... so they work a little nicer.

I also modified source/Makefile.am to add targets for the player
Still needs some work I'm sure but its a start.

Kent
--
mein@cs.umn.edu
2002-12-03 18:31:50 +00:00

6392 lines
133 KiB
C

/**
* $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 *****
*/
#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 "BLI_blenlib.h"
#include "BLI_arithb.h"
#include "BLI_editVert.h"
#include "BLI_rand.h"
#include "MTC_matrixops.h"
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "DNA_key_types.h"
#include "DNA_scene_types.h"
#include "DNA_view3d_types.h"
#include "DNA_material_types.h"
#include "DNA_texture_types.h"
#include "BKE_utildefines.h"
#include "BKE_key.h"
#include "BKE_object.h"
#include "BKE_texture.h"
#include "BKE_displist.h"
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
#include "BIF_gl.h"
#include "BIF_graphics.h"
#include "BIF_editkey.h"
#include "BIF_space.h"
#include "BIF_toolbox.h"
#include "BIF_screen.h"
#include "BIF_interface.h"
#include "BIF_editmesh.h"
#include "BIF_mywindow.h"
#include "BSE_view.h"
#include "BSE_edit.h"
#include "BSE_trans_types.h"
#include "BDR_drawobject.h"
#include "BDR_editobject.h"
#include "BDR_editface.h"
#include "BDR_vpaint.h"
#include "mydevice.h"
#include "blendef.h"
#include "interface.h" /* MAART: for NUM and FLO types */
#include "nla.h" /* For __NLA : Important - Do not remove! */
#include "render.h"
/****/
static void free_editverts(ListBase *edve);
static float convex(float *v1, float *v2, float *v3, float *v4);
/****/
/* extern ListBase fillvertbase, filledgebase; */ /* scanfill.c, in
the lib... already in BLI_blenlib.h */
/* voor debug:
#define free(a) freeN(a)
#define malloc(a) mallocN(a, "malloc")
#define calloc(a, b) callocN((a)*(b), "calloc")
#define freelist(a) freelistN(a)
*/
extern short editbutflag;
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 icovlak[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}
};
/* DEFINES */
#define UVCOPY(t, s) memcpy(t, s, 2 * sizeof(float));
#define TEST_EDITMESH if(G.obedit==0) return; \
if( (G.vd->lay & G.obedit->lay)==0 ) return;
#define FACE_MARKCLEAR(f) (f->f1 = 1)
/* ***************** HASH ********************* */
/* HASH struct voor snel opzoeken edges */
struct HashEdge {
struct EditEdge *eed;
struct HashEdge *next;
};
struct HashEdge *hashedgetab=0;
/********* qsort routines *********/
struct xvertsort {
float x;
EditVert *v1;
};
/* Functions */
static int vergxco(const void *v1, const void *v2)
{
const struct xvertsort *x1=v1, *x2=v2;
if( x1->x > x2->x ) return 1;
else if( x1->x < x2->x) return -1;
return 0;
}
struct vlaksort {
long x;
struct EditVlak *evl;
};
static int vergvlak(const void *v1, const void *v2)
{
const struct vlaksort *x1=v1, *x2=v2;
if( x1->x > x2->x ) return 1;
else if( x1->x < x2->x) return -1;
return 0;
}
/* ************ ADD / REMOVE / FIND ****************** */
#define EDHASH(a, b) ( (a)*256 + (b) )
#define EDHASHSIZE 65536
#if 0
static void check_hashedge(void)
{
int i, i2, doubedge=0;
struct HashEdge *he, *he2;
for (i=0; i<64; i++) {
he= hashedgetab+i;
while (he && he->eed) {
for (i2=i+1; i2<64; i2++) {
he2= hashedgetab+i2;
while (he2) {
if (he->eed == he2->eed) doubedge++;
he2= he2->next;
}
}
he= he->next;
}
}
if (doubedge) printf("%d double edges!\n", doubedge);
}
#endif
EditVert *addvertlist(float *vec)
{
EditVert *eve;
static unsigned char hashnr= 0;
eve= calloc(sizeof(EditVert),1);
BLI_addtail(&G.edve, eve);
if(vec) VECCOPY(eve->co, vec);
eve->hash= hashnr++;
return eve;
}
EditEdge *findedgelist(EditVert *v1, EditVert *v2)
{
EditVert *v3;
struct HashEdge *he;
if(hashedgetab==0) {
hashedgetab= MEM_callocN(EDHASHSIZE*sizeof(struct HashEdge), "hashedgetab");
}
/* swap ? */
if( (long)v1 > (long)v2) {
v3= v2;
v2= v1;
v1= v3;
}
/* eerst even op de flip-plek kijken */
/* he= hashedgetab + EDHASH(v2->hash, v1->hash); */
/* if(he->eed && he->eed->v1==v1 && he->eed->v2==v2) return he->eed; */
he= hashedgetab + EDHASH(v1->hash, v2->hash);
while(he) {
if(he->eed && he->eed->v1==v1 && he->eed->v2==v2) return he->eed;
he= he->next;
}
return 0;
}
static void insert_hashedge(EditEdge *eed)
{
/* er van uitgaande dat eed nog niet in lijst zit, en eerst een find is gedaan */
struct HashEdge *first, *he;
/* eerst even op de flip-plek kijken */
/* he= hashedgetab + EDHASH(eed->v2->hash, eed->v1->hash); */
/* if(he->eed==0) { */
/* he->eed= eed; */
/* return; */
/* } */
first= hashedgetab + EDHASH(eed->v1->hash, eed->v2->hash);
if( first->eed==0 ) {
first->eed= eed;
}
else {
he= (struct HashEdge *)malloc(sizeof(struct HashEdge));
he->eed= eed;
he->next= first->next;
first->next= he;
}
}
static void remove_hashedge(EditEdge *eed)
{
/* er van uitgaande dat eed in lijst zit */
struct HashEdge *first, *he, *prev=NULL;
/* eerst even op de flip-plek kijken */
/* first= hashedgetab + EDHASH(eed->v2->hash, eed->v1->hash); */
/* if(first->eed==eed) { */
/* uit lijst verwijderen */
/* if(first->next) { */
/* he= first->next; */
/* first->eed= he->eed; */
/* first->next= he->next; */
/* free(he); */
/* } */
/* else first->eed= 0; */
/* return; */
/* } */
he=first= hashedgetab + EDHASH(eed->v1->hash, eed->v2->hash);
while(he) {
if(he->eed == eed) {
/* uit lijst verwijderen */
if(he==first) {
if(first->next) {
he= first->next;
first->eed= he->eed;
first->next= he->next;
free(he);
}
else he->eed= 0;
}
else {
prev->next= he->next;
free(he);
}
return;
}
prev= he;
he= he->next;
}
}
void free_hashedgetab(void)
{
struct HashEdge *he, *first, *hen;
int a;
/* int test[30], nr, toted=0; */
/* for(a=0; a<30; a++) test[a]=0; */
if(hashedgetab) {
first= hashedgetab;
for(a=0; a<EDHASHSIZE; a++, first++) {
he= first->next;
/* nr= 0; */
/* if(first->eed) toted++; */
/* if(first->eed) nr++; */
while(he) {
hen= he->next;
free(he);
he= hen;
/* nr++; */
}
/* if(nr>29) nr= 29; */
/* test[nr]++; */
}
MEM_freeN(hashedgetab);
hashedgetab= 0;
/* printf("toted %d\n", toted); */
/* toted= 0; */
/* for(a=0; a<30; a++) { */
/* printf("tab %d %d\n", a, test[a]); */
/* } */
}
}
EditEdge *addedgelist(EditVert *v1, EditVert *v2)
{
EditVert *v3;
EditEdge *eed;
int swap= 0;
/* swap ? */
if(v1>v2) {
v3= v2;
v2= v1;
v1= v3;
swap= 1;
}
if(v1==v2) return 0;
if(v1==0 || v2==0) return 0;
/* opzoeken in hashlijst */
eed= findedgelist(v1, v2);
if(eed==0) {
eed= (EditEdge *)calloc(sizeof(EditEdge), 1);
eed->v1= v1;
eed->v2= v2;
BLI_addtail(&G.eded, eed);
eed->dir= swap;
insert_hashedge(eed);
}
return eed;
}
void remedge(EditEdge *eed)
{
BLI_remlink(&G.eded, eed);
remove_hashedge(eed);
}
static void freevlak(EditVlak *evl)
{
free(evl);
}
static void freevlaklist(ListBase *lb)
{
EditVlak *evl, *next;
evl= lb->first;
while(evl) {
next= evl->next;
freevlak(evl);
evl= next;
}
lb->first= lb->last= 0;
}
EditVlak *addvlaklist(EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4, EditVlak *example)
{
EditVlak *evl;
EditEdge *e1, *e2=0, *e3=0, *e4=0;
/* voeg vlak toe aan lijst en doe meteen de edges */
e1= addedgelist(v1, v2);
if(v3) e2= addedgelist(v2, v3);
if(v4) e3= addedgelist(v3, v4); else e3= addedgelist(v3, v1);
if(v4) e4= addedgelist(v4, v1);
if(v1==v2 || v2==v3 || v1==v3) return 0;
if(e2==0) return 0;
evl= (EditVlak *)calloc(sizeof(EditVlak), 1);
evl->v1= v1;
evl->v2= v2;
evl->v3= v3;
evl->v4= v4;
evl->e1= e1;
evl->e2= e2;
evl->e3= e3;
evl->e4= e4;
if(example) {
evl->mat_nr= example->mat_nr;
evl->tface= example->tface;
evl->flag= example->flag;
memcpy(evl->col, example->col, sizeof(example->col));
memcpy(evl->uv, example->uv, sizeof(example->uv));
}
else {
if (G.obedit && G.obedit->actcol)
evl->mat_nr= G.obedit->actcol-1;
default_uv(evl->uv, 1.0);
/* Initialize colors */
evl->col[0]= evl->col[1]= evl->col[2]= evl->col[3]= vpaint_get_current_col();
}
BLI_addtail(&G.edvl, evl);
if(evl->v4) CalcNormFloat4(v1->co, v2->co, v3->co, v4->co, evl->n);
else CalcNormFloat(v1->co, v2->co, v3->co, evl->n);
return evl;
}
static int comparevlak(EditVlak *vl1, EditVlak *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;
}
#if 0
static int dubbelvlak(EditVlak *evltest)
{
EditVlak *evl;
evl= G.edvl.first;
while(evl) {
if(evl!=evltest) {
if(comparevlak(evltest, evl)) return 1;
}
evl= evl->next;
}
return 0;
}
#endif
static int exist_vlak(EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4)
{
EditVlak *evl, evltest;
evltest.v1= v1;
evltest.v2= v2;
evltest.v3= v3;
evltest.v4= v4;
evl= G.edvl.first;
while(evl) {
if(comparevlak(&evltest, evl)) return 1;
evl= evl->next;
}
return 0;
}
static int vlakselectedOR(EditVlak *evl, int flag)
{
if(evl->v1->f & flag) return 1;
if(evl->v2->f & flag) return 1;
if(evl->v3->f & flag) return 1;
if(evl->v4 && (evl->v4->f & 1)) return 1;
return 0;
}
int vlakselectedAND(EditVlak *evl, int flag)
{
if(evl->v1->f & flag) {
if(evl->v2->f & flag) {
if(evl->v3->f & flag) {
if(evl->v4) {
if(evl->v4->f & flag) return 1;
}
else return 1;
}
}
}
return 0;
}
void recalc_editnormals(void)
{
EditVlak *evl;
evl= G.edvl.first;
while(evl) {
if(evl->v4) CalcNormFloat4(evl->v1->co, evl->v2->co, evl->v3->co, evl->v4->co, evl->n);
else CalcNormFloat(evl->v1->co, evl->v2->co, evl->v3->co, evl->n);
evl= evl->next;
}
}
static void flipvlak(EditVlak *evl)
{
if(evl->v4) {
SWAP(EditVert *, evl->v2, evl->v4);
SWAP(EditEdge *, evl->e1, evl->e4);
SWAP(EditEdge *, evl->e2, evl->e3);
SWAP(unsigned int, evl->col[1], evl->col[3]);
if(evl->tface) {
SWAP(float, evl->uv[1][0], evl->uv[3][0]);
SWAP(float, evl->uv[1][1], evl->uv[3][1]);
}
}
else {
SWAP(EditVert *, evl->v2, evl->v3);
SWAP(EditEdge *, evl->e1, evl->e3);
SWAP(unsigned int, evl->col[1], evl->col[2]);
evl->e2->dir= 1-evl->e2->dir;
if(evl->tface) {
SWAP(float, evl->uv[1][0], evl->uv[2][0]);
SWAP(float, evl->uv[1][1], evl->uv[2][1]);
}
}
if(evl->v4) CalcNormFloat4(evl->v1->co, evl->v2->co, evl->v3->co, evl->v4->co, evl->n);
else CalcNormFloat(evl->v1->co, evl->v2->co, evl->v3->co, evl->n);
}
void flip_editnormals(void)
{
EditVlak *evl;
evl= G.edvl.first;
while(evl) {
if( vlakselectedAND(evl, 1) ) {
flipvlak(evl);
}
evl= evl->next;
}
}
/* ************************ IN & OUT ***************************** */
static void edge_normal_compare(EditEdge *eed, EditVlak *evl1)
{
EditVlak *evl2;
float cent1[3], cent2[3];
float inp;
evl2= (EditVlak *)eed->vn;
if(evl1==evl2) return;
inp= evl1->n[0]*evl2->n[0] + evl1->n[1]*evl2->n[1] + evl1->n[2]*evl2->n[2];
if(inp<0.999 && inp >-0.999) eed->f= 1;
if(evl1->v4) CalcCent4f(cent1, evl1->v1->co, evl1->v2->co, evl1->v3->co, evl1->v4->co);
else CalcCent3f(cent1, evl1->v1->co, evl1->v2->co, evl1->v3->co);
if(evl2->v4) CalcCent4f(cent2, evl2->v1->co, evl2->v2->co, evl2->v3->co, evl2->v4->co);
else CalcCent3f(cent2, evl2->v1->co, evl2->v2->co, evl2->v3->co);
VecSubf(cent1, cent2, cent1);
Normalise(cent1);
inp= cent1[0]*evl1->n[0] + cent1[1]*evl1->n[1] + cent1[2]*evl1->n[2];
if(inp < -0.001 ) eed->f1= 1;
}
static void edge_drawflags(void)
{
EditVert *eve;
EditEdge *eed, *e1, *e2, *e3, *e4;
EditVlak *evl;
/* - tel aantal keren in vlakken gebruikt: 0 en 1 is tekenen
* - edges meer dan 1 keer: in *vn zit pointer naar (eerste) vlak
* - loop alle vlakken af, is normaal te afwijkend: tekenen (flag wordt 1)
*/
recalc_editnormals();
/* init */
eve= G.edve.first;
while(eve) {
eve->f1= 1; /* wordt bij test op nul gezet */
eve= eve->next;
}
eed= G.eded.first;
while(eed) {
eed->f= eed->f1= 0;
eed->vn= 0;
eed= eed->next;
}
evl= G.edvl.first;
while(evl) {
e1= evl->e1;
e2= evl->e2;
e3= evl->e3;
e4= evl->e4;
if(e1->f<3) e1->f+= 1;
if(e2->f<3) e2->f+= 1;
if(e3->f<3) e3->f+= 1;
if(e4 && e4->f<3) e4->f+= 1;
if(e1->vn==0) e1->vn= (EditVert *)evl;
if(e2->vn==0) e2->vn= (EditVert *)evl;
if(e3->vn==0) e3->vn= (EditVert *)evl;
if(e4 && e4->vn==0) e4->vn= (EditVert *)evl;
evl= evl->next;
}
if(G.f & G_ALLEDGES) {
evl= G.edvl.first;
while(evl) {
if(evl->e1->f>=2) evl->e1->f= 1;
if(evl->e2->f>=2) evl->e2->f= 1;
if(evl->e3->f>=2) evl->e3->f= 1;
if(evl->e4 && evl->e4->f>=2) evl->e4->f= 1;
evl= evl->next;
}
}
else {
/* single-edges afvangen voor cylinder flag */
eed= G.eded.first;
while(eed) {
if(eed->f==1) eed->f1= 1;
eed= eed->next;
}
/* alle vlakken, alle edges met flag==2: vergelijk normaal */
evl= G.edvl.first;
while(evl) {
if(evl->e1->f==2) edge_normal_compare(evl->e1, evl);
if(evl->e2->f==2) edge_normal_compare(evl->e2, evl);
if(evl->e3->f==2) edge_normal_compare(evl->e3, evl);
if(evl->e4 && evl->e4->f==2) edge_normal_compare(evl->e4, evl);
evl= evl->next;
}
/* sphere collision flag */
eed= G.eded.first;
while(eed) {
if(eed->f1!=1) {
eed->v1->f1= eed->v2->f1= 0;
}
eed= eed->next;
}
}
}
static int contrpuntnorm(float *n, float *puno)
{
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)
{
Mesh *me;
EditVert *eve;
EditVlak *evl;
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 opp, 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) {
/* namaak puno's voor halopuno! */
eve= G.edve.first;
while(eve) {
VECCOPY(eve->no, eve->co);
Normalise( (float *)eve->no);
eve= eve->next;
}
return;
}
/* clear normals */
eve= G.edve.first;
while(eve) {
eve->no[0]= eve->no[1]= eve->no[2]= 0.0;
eve= eve->next;
}
/* berekenen cos hoeken en oppervlakte en optellen bij puno */
evl= G.edvl.first;
while(evl) {
VecSubf(n1, evl->v2->co, evl->v1->co);
VecSubf(n2, evl->v3->co, evl->v2->co);
Normalise(n1);
Normalise(n2);
if(evl->v4==0) {
VecSubf(n3, evl->v1->co, evl->v3->co);
Normalise(n3);
/* opp= AreaT3Dfl(evl->v1->co, evl->v2->co, evl->v3->co); */
/* if(opp!=0.0) opp=1.0/opp; */
/* opp= sqrt(opp); */
/* for smooth subdivide...*/
opp= 1.0;
co[0]= opp*saacos(-n3[0]*n1[0]-n3[1]*n1[1]-n3[2]*n1[2]);
co[1]= opp*saacos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]);
co[2]= opp*saacos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]);
}
else {
VecSubf(n3, evl->v4->co, evl->v3->co);
VecSubf(n4, evl->v1->co, evl->v4->co);
Normalise(n3);
Normalise(n4);
/* opp= AreaQ3Dfl(evl->v1->co, evl->v2->co, evl->v3->co, evl->v4->co); */
/* if(opp!=0.0) opp=1.0/opp; */
/* opp= sqrt(opp); */
/* for smooth subdivide...*/
opp= 1.0;
co[0]= opp*saacos(-n4[0]*n1[0]-n4[1]*n1[1]-n4[2]*n1[2]);
co[1]= opp*saacos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]);
co[2]= opp*saacos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]);
co[3]= opp*saacos(-n3[0]*n4[0]-n3[1]*n4[1]-n3[2]*n4[2]);
}
temp= evl->v1->no;
if(testflip && contrpuntnorm(evl->n, temp) ) co[0]= -co[0];
temp[0]+= co[0]*evl->n[0];
temp[1]+= co[0]*evl->n[1];
temp[2]+= co[0]*evl->n[2];
temp= evl->v2->no;
if(testflip && contrpuntnorm(evl->n, temp) ) co[1]= -co[1];
temp[0]+= co[1]*evl->n[0];
temp[1]+= co[1]*evl->n[1];
temp[2]+= co[1]*evl->n[2];
temp= evl->v3->no;
if(testflip && contrpuntnorm(evl->n, temp) ) co[2]= -co[2];
temp[0]+= co[2]*evl->n[0];
temp[1]+= co[2]*evl->n[1];
temp[2]+= co[2]*evl->n[2];
if(evl->v4) {
temp= evl->v4->no;
if(testflip && contrpuntnorm(evl->n, temp) ) co[3]= -co[3];
temp[0]+= co[3]*evl->n[0];
temp[1]+= co[3]*evl->n[1];
temp[2]+= co[3]*evl->n[2];
}
evl= evl->next;
}
/* normaliseren puntnormalen */
eve= G.edve.first;
while(eve) {
len= Normalise(eve->no);
if(len==0.0) {
VECCOPY(eve->no, eve->co);
Normalise( eve->no);
}
eve= eve->next;
}
/* puntnormaal omklap-vlaggen voor bij shade */
evl= G.edvl.first;
while(evl) {
evl->f=0;
if(testflip) {
f1= evl->v1->no;
f2= evl->v2->no;
f3= evl->v3->no;
fac1= evl->n[0]*f1[0] + evl->n[1]*f1[1] + evl->n[2]*f1[2];
if(fac1<0.0) {
evl->f = ME_FLIPV1;
}
fac2= evl->n[0]*f2[0] + evl->n[1]*f2[1] + evl->n[2]*f2[2];
if(fac2<0.0) {
evl->f += ME_FLIPV2;
}
fac3= evl->n[0]*f3[0] + evl->n[1]*f3[1] + evl->n[2]*f3[2];
if(fac3<0.0) {
evl->f += ME_FLIPV3;
}
if(evl->v4) {
f4= evl->v4->no;
fac4= evl->n[0]*f4[0] + evl->n[1]*f4[1] + evl->n[2]*f4[2];
if(fac4<0.0) {
evl->f += ME_FLIPV4;
}
}
}
/* proj voor cubemap! */
xn= fabs(evl->n[0]);
yn= fabs(evl->n[1]);
zn= fabs(evl->n[2]);
if(zn>xn && zn>yn) evl->f += ME_PROJXY;
else if(yn>xn && yn>zn) evl->f += ME_PROJXZ;
else evl->f += ME_PROJYZ;
evl= evl->next;
}
}
void free_editMesh(void)
{
// if(G.edve.first) BLI_freelist(&G.edve);
if(G.edve.first) free_editverts(&G.edve);
if(G.eded.first) BLI_freelist(&G.eded);
if(G.edvl.first) freevlaklist(&G.edvl);
free_hashedgetab();
G.totvert= G.totface= 0;
}
static void free_editverts(ListBase *edve) {
#ifdef __NLA
EditVert *eve;
#endif
if (!edve)
return;
if (!edve->first)
return;
#ifdef __NLA
for (eve= edve->first; eve; eve=eve->next){
if (eve->dw)
MEM_freeN (eve->dw);
}
#endif
BLI_freelist (edve);
}
static void free_editvert (EditVert *eve)
{
#ifdef __NLA
if (eve->dw)
MEM_freeN (eve->dw);
#endif
free (eve);
}
void make_editMesh(void)
{
Mesh *me;
MFace *mface;
TFace *tface;
MVert *mvert;
KeyBlock *actkey=0;
EditVert *eve, **evlist, *eve1, *eve2, *eve3, *eve4;
EditVlak *evl;
int tot, a;
if(G.obedit==0) return;
/* ivm reload */
free_editMesh();
me= get_mesh(G.obedit);
G.totvert= tot= me->totvert;
if(tot==0) {
countall();
return;
}
waitcursor(1);
/* keys? */
if(me->key) {
actkey= me->key->block.first;
while(actkey) {
if(actkey->flag & SELECT) break;
actkey= actkey->next;
}
}
if(actkey) {
key_to_mesh(actkey, me);
tot= actkey->totelem;
}
/* editverts aanmaken */
mvert= me->mvert;
evlist= (EditVert **)MEM_mallocN(tot*sizeof(void *),"evlist");
for(a=0; a<tot; a++, mvert++) {
eve= addvertlist(mvert->co);
evlist[a]= eve;
eve->no[0]= mvert->no[0]/32767.0;
eve->no[1]= mvert->no[1]/32767.0;
eve->no[2]= mvert->no[2]/32767.0;
#ifdef __NLA
/* OLD VERSION */
/*
eve->totweight = mvert->totweight;
if (mvert->dw){
eve->dw = BLI_callocN (sizeof(MDeformWeight) * mvert->totweight, "deformWeight");
memcpy (eve->dw, mvert->dw, sizeof(MDeformWeight) * mvert->totweight);
}
*/
/* NEW VERSION */
if (me->dvert){
eve->totweight = me->dvert[a].totweight;
if (me->dvert[a].dw){
eve->dw = MEM_callocN (sizeof(MDeformWeight) * me->dvert[a].totweight, "deformWeight");
memcpy (eve->dw, me->dvert[a].dw, sizeof(MDeformWeight) * me->dvert[a].totweight);
}
}
#endif
}
if(actkey && actkey->totelem!=me->totvert);
else {
unsigned int *mcol;
/* edges en vlakken maken */
mface= me->mface;
tface= me->tface;
mcol= (unsigned int *)me->mcol;
for(a=0; a<me->totface; a++, mface++) {
eve1= evlist[mface->v1];
eve2= evlist[mface->v2];
if(mface->v3) eve3= evlist[mface->v3]; else eve3= 0;
if(mface->v4) eve4= evlist[mface->v4]; else eve4= 0;
evl= addvlaklist(eve1, eve2, eve3, eve4, NULL);
if(evl) {
if(mcol) memcpy(evl->col, mcol, 4*sizeof(int));
if(me->tface) {
memcpy(evl->col, tface->col, sizeof(tface->col));
memcpy(evl->uv, tface->uv, sizeof(tface->uv));
if( tface->flag & TF_SELECT) {
if(G.f & G_FACESELECT) {
eve1->f |= 1;
eve2->f |= 1;
if(eve3) eve3->f |= 1;
if(eve4) eve4->f |= 1;
}
}
}
evl->mat_nr= mface->mat_nr;
evl->flag= mface->flag;
evl->tface= tface;
}
if(me->tface) tface++;
if(mcol) mcol+=4;
}
}
MEM_freeN(evlist);
countall();
if (mesh_uses_displist(me))
makeDispList(G.obedit);
waitcursor(0);
}
/** Rotates MFace and UVFace vertices in case the last
* vertex index is = 0.
* This function is a hack and may only be called in the
* conversion from EditMesh to Mesh data.
* This function is similar to test_index_mface in
* blenkernel/intern/mesh.c.
* To not clutter the blenkernel code with more bad level
* calls/structures, this function resides here.
*/
static void fix_faceindices(MFace *mface, EditVlak *evl, int nr)
{
int a;
float tmpuv[2];
unsigned int tmpcol;
/*
mface = ((MFace *) me->mface) + index;
tface = ((TFace *) me->tface) + index;
*/
/* first test if the face is legal */
if(mface->v3 && mface->v3==mface->v4) {
mface->v4= 0;
nr--;
}
if(mface->v2 && mface->v2==mface->v3) {
mface->v3= mface->v4;
mface->v4= 0;
nr--;
}
if(mface->v1==mface->v2) {
mface->v2= mface->v3;
mface->v3= mface->v4;
mface->v4= 0;
nr--;
}
/* voorkom dat een nul op de verkeerde plek staat */
if(nr==2) {
if(mface->v2==0) SWAP(int, mface->v1, mface->v2);
}
else if(nr==3) {
if(mface->v3==0) {
SWAP(int, mface->v1, mface->v2);
SWAP(int, mface->v2, mface->v3);
/* rotate face UV coordinates, too */
UVCOPY(tmpuv, evl->uv[0]);
UVCOPY(evl->uv[0], evl->uv[1]);
UVCOPY(evl->uv[1], evl->uv[2]);
UVCOPY(evl->uv[2], tmpuv);
/* same with vertex colours */
tmpcol = evl->col[0];
evl->col[0] = evl->col[1];
evl->col[1] = evl->col[2];
evl->col[2] = tmpcol;
a= mface->edcode;
mface->edcode= 0;
if(a & ME_V1V2) mface->edcode |= ME_V3V1;
if(a & ME_V2V3) mface->edcode |= ME_V1V2;
if(a & ME_V3V1) mface->edcode |= ME_V2V3;
a= mface->puno;
mface->puno &= ~15;
if(a & ME_FLIPV1) mface->puno |= ME_FLIPV2;
if(a & ME_FLIPV2) mface->puno |= ME_FLIPV3;
if(a & ME_FLIPV3) mface->puno |= ME_FLIPV1;
}
}
else if(nr==4) {
if(mface->v3==0 || mface->v4==0) {
SWAP(int, mface->v1, mface->v3);
SWAP(int, mface->v2, mface->v4);
/* swap UV coordinates */
UVCOPY(tmpuv, evl->uv[0]);
UVCOPY(evl->uv[0], evl->uv[2]);
UVCOPY(evl->uv[2], tmpuv);
UVCOPY(tmpuv, evl->uv[1]);
UVCOPY(evl->uv[1], evl->uv[3]);
UVCOPY(evl->uv[3], tmpuv);
/* swap vertex colours */
tmpcol = evl->col[0];
evl->col[0] = evl->col[2];
evl->col[2] = tmpcol;
tmpcol = evl->col[1];
evl->col[1] = evl->col[3];
evl->col[3] = tmpcol;
a= mface->edcode;
mface->edcode= 0;
if(a & ME_V1V2) mface->edcode |= ME_V3V4;
if(a & ME_V2V3) mface->edcode |= ME_V2V3;
if(a & ME_V3V4) mface->edcode |= ME_V1V2;
if(a & ME_V4V1) mface->edcode |= ME_V4V1;
a= mface->puno;
mface->puno &= ~15;
if(a & ME_FLIPV1) mface->puno |= ME_FLIPV3;
if(a & ME_FLIPV2) mface->puno |= ME_FLIPV4;
if(a & ME_FLIPV3) mface->puno |= ME_FLIPV1;
if(a & ME_FLIPV4) mface->puno |= ME_FLIPV2;
}
}
}
/* load from EditMode to Mesh */
void load_editMesh(void)
{
Mesh *me;
MFace *mface;
MVert *mvert;
MSticky *ms;
KeyBlock *actkey=0;
EditVert *eve;
EditVlak *evl;
EditEdge *eed;
float *fp, nor[3];
int i, a, ototvert;
#ifdef __NLA
MDeformVert *dvert;
int usedDvert = 0;
#endif
waitcursor(1);
countall();
me= get_mesh(G.obedit);
ototvert= me->totvert;
/* zijn er keys? */
if(me->key) {
actkey= me->key->block.first;
while(actkey) {
if(actkey->flag & SELECT) break;
actkey= actkey->next;
}
}
if(actkey && me->key->refkey!=actkey) {
/* aktieve key && niet de refkey: alleen vertices */
if(G.totvert) {
if(actkey->data) MEM_freeN(actkey->data);
fp=actkey->data= MEM_callocN(me->key->elemsize*G.totvert, "actkey->data");
actkey->totelem= G.totvert;
eve= G.edve.first;
while(eve) {
VECCOPY(fp, eve->co);
fp+= 3;
eve= eve->next;
}
}
}
else if(me->key && actkey==0) {
/* er zijn keys, alleen veranderingen in mverts schrijven */
/* als aantal vertices verschillen, beetje onvoorspelbaar */
eve= G.edve.first;
mvert= me->mvert;
for(a=0; a<me->totvert; a++, mvert++) {
VECCOPY(mvert->co, eve->co);
eve= eve->next;
if(eve==0) break;
}
}
else {
/* als er keys zijn: de refkey, anders gewoon de me */
/* deze telt ook of edges niet in vlakken zitten: */
/* eed->f==0 niet in vlak, f==1 is tekenen */
/* eed->f1 : flag voor dynaface (cylindertest) */
/* eve->f1 : flag voor dynaface (sphere test) */
edge_drawflags();
/* LET OP: op evl->f de punoflag */
vertexnormals( (me->flag & ME_NOPUNOFLIP)==0 );
eed= G.eded.first;
while(eed) {
if(eed->f==0) G.totface++;
eed= eed->next;
}
/* nieuw Face blok */
if(G.totface==0) mface= 0;
else mface= MEM_callocN(G.totface*sizeof(MFace), "loadeditMesh1");
/* nieuw Vertex blok */
if(G.totvert==0) mvert= 0;
else mvert= MEM_callocN(G.totvert*sizeof(MVert), "loadeditMesh2");
#ifdef __NLA
if (G.totvert==0) dvert=0;
else dvert = MEM_callocN(G.totvert*sizeof(MDeformVert), "loadeditMesh3");
if (me->dvert) free_dverts(me->dvert, me->totvert);
me->dvert=dvert;
#endif
if(me->mvert) MEM_freeN(me->mvert);
me->mvert= mvert;
if(me->mface) MEM_freeN(me->mface);
me->mface= mface;
me->totvert= G.totvert;
me->totface= G.totface;
/* de vertices, gebruik ->vn als teller */
eve= G.edve.first;
a=0;
while(eve) {
VECCOPY(mvert->co, eve->co);
mvert->mat_nr= 255; /* waarvoor ook al weer, haloos? */
/* puno */
VECCOPY(nor, eve->no);
VecMulf(nor, 32767.0);
VECCOPY(mvert->no, nor);
#ifdef __NLA
/* OLD VERSION */
/* mvert->totweight = eve->totweight;
if (eve->dw){
int cv;
mvert->dw = BLI_callocN (sizeof(MDeformWeight)*eve->totweight, "deformWeight");
memcpy (mvert->dw, eve->dw, sizeof(MDeformWeight)*eve->totweight);
}
*/
/* NEW VERSION */
if (dvert){
dvert->totweight=eve->totweight;
if (eve->dw){
dvert->dw = MEM_callocN (sizeof(MDeformWeight)*eve->totweight, "deformWeight");
memcpy (dvert->dw, eve->dw, sizeof(MDeformWeight)*eve->totweight);
usedDvert++;
}
}
#endif
eve->vn= (EditVert *)(long)(a++); /* teller */
mvert->flag= 0;
if(eve->f1==1) mvert->flag |= ME_SPHERETEST;
eve= eve->next;
mvert++;
#ifdef __NLA
dvert++;
#endif
}
#ifdef __NLA
/* If we didn't actually need the dverts, get rid of them */
if (!usedDvert){
free_dverts(me->dvert, G.totvert);
me->dvert=NULL;
}
#endif
/* de vlakken */
evl= G.edvl.first;
i = 0;
while(evl) {
mface= &((MFace *) me->mface)[i];
mface->v1= (unsigned int) evl->v1->vn;
mface->v2= (unsigned int) evl->v2->vn;
mface->v3= (unsigned int) evl->v3->vn;
if(evl->v4) mface->v4= (unsigned int) evl->v4->vn;
mface->mat_nr= evl->mat_nr;
mface->puno= evl->f;
mface->flag= evl->flag;
/* mat_nr in vertex */
if(me->totcol>1) {
mvert= me->mvert+mface->v1;
if(mvert->mat_nr == (char)255) mvert->mat_nr= mface->mat_nr;
mvert= me->mvert+mface->v2;
if(mvert->mat_nr == (char)255) mvert->mat_nr= mface->mat_nr;
mvert= me->mvert+mface->v3;
if(mvert->mat_nr == (char)255) mvert->mat_nr= mface->mat_nr;
if(mface->v4) {
mvert= me->mvert+mface->v4;
if(mvert->mat_nr == (char)255) mvert->mat_nr= mface->mat_nr;
}
}
/* dyna cilinder flag minder kritisch testen: 'dubbel' in vlakken laten zitten.
* gaat anders fout bij scherpe hoeken (inpspeed voor een wel, ander niet!)
* Mogelijk oplossen door volgorde aan te passen: sphere-cyl-face. Kost te veel?
*/
/* letop: evl->e1->f==0 is losse edge */
if(evl->e1->f==1) {
mface->edcode |= ME_V1V2;
evl->e1->f= 2;
}
if(evl->e2->f==1) {
mface->edcode |= ME_V2V3;
evl->e2->f= 2;
}
if(evl->e3->f==1) {
if(evl->v4) {
mface->edcode |= ME_V3V4;
}
else {
mface->edcode |= ME_V3V1;
}
evl->e3->f= 2;
}
if(evl->e4 && evl->e4->f==1) {
mface->edcode |= ME_V4V1;
evl->e4->f= 2;
}
/* geen index '0' op plek 3 of 4 */
if(evl->v4) fix_faceindices(mface, evl, 4);
else fix_faceindices(mface, evl, 3);
i++;
evl= evl->next;
}
/* losse edges als vlak toevoegen */
eed= G.eded.first;
while(eed) {
if( eed->f==0 ) {
mface= &((MFace *) me->mface)[i];
mface->v1= (unsigned int) eed->v1->vn;
mface->v2= (unsigned int) eed->v2->vn;
test_index_mface(mface, 2);
mface->edcode= ME_V1V2;
i++;
}
eed= eed->next;
}
tex_space_mesh(me);
if(actkey) mesh_to_key(me, actkey);
/* texmesh: ahv ->tface alles opnieuw maken */
if(me->tface && me->totface) {
TFace *tfn, *tf;
tf=tfn= MEM_callocN(sizeof(TFace)*me->totface, "tface");
evl= G.edvl.first;
while(evl) {
if(evl->tface) *tf= *(evl->tface);
else default_tface(tf);
memcpy(tf->col, evl->col, sizeof(tf->col));
memcpy(tf->uv, evl->uv, sizeof(tf->uv));
if(G.f & G_FACESELECT) {
if( vlakselectedAND(evl, 1) ) tf->flag |= TF_SELECT;
else tf->flag &= ~TF_SELECT;
}
/* sometimes editmode doesn't free (before render) */
evl->tface= tf;
tf++;
evl= evl->next;
}
MEM_freeN(me->tface);
me->tface= tfn;
}
else if(me->tface) {
/* freeN(me->tface); */
/* me->tface= 0; */
}
/* mcol: ahv indexnrs opnieuw maken */
if(me->mcol && me->totface) {
unsigned int *mcn, *mc;
mc=mcn= MEM_mallocN(4*sizeof(int)*me->totface, "mcol");
evl= G.edvl.first;
while(evl) {
memcpy(mc, evl->col, 4*sizeof(int));
mc+=4;
evl= evl->next;
}
MEM_freeN(me->mcol);
me->mcol= (MCol *)mcn;
}
else if(me->mcol) {
MEM_freeN(me->mcol);
me->mcol= 0;
}
}
if(actkey) do_spec_key(me->key);
/* voor zekerheid: ->vn pointers wissen */
eve= G.edve.first;
while(eve) {
eve->vn= 0;
eve= eve->next;
}
/* displisten van alle users, ook deze */
freedisplist(&me->disp);
freedisplist(&G.obedit->disp);
/* sticky */
if(me->msticky) {
if (ototvert<me->totvert) {
ms= MEM_callocN(me->totvert*sizeof(MSticky), "msticky");
memcpy(ms, me->msticky, ototvert*sizeof(MSticky));
MEM_freeN(me->msticky);
me->msticky= ms;
error("Sticky was too small");
}
}
waitcursor(0);
}
void remake_editMesh(void)
{
if(okee("Reload Original data")==0) return;
make_editMesh();
allqueue(REDRAWVIEW3D, 0);
makeDispList(G.obedit);
}
/* ********************* TOOLS ********************* */
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 perform function in EditMode");
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");
/* stukje roteerscene */
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;
/* vlaggen resetten */
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;
}
/* belangrijk?: vlaggen weer resetten */
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);
}
void convert_to_triface(int all)
{
EditVlak *evl, *evln, *next;
evl= G.edvl.first;
while(evl) {
next= evl->next;
if(evl->v4) {
if(all || vlakselectedAND(evl, 1) ) {
evln= addvlaklist(evl->v1, evl->v2, evl->v3, 0, evl);
evln= addvlaklist(evl->v1, evl->v3, evl->v4, 0, evl);
if(evl->tface) {
evln->uv[1][0]= evln->uv[2][0];
evln->uv[1][1]= evln->uv[2][1];
evln->uv[2][0]= evln->uv[3][0];
evln->uv[2][1]= evln->uv[3][1];
}
evln->col[1]= evln->col[2];
evln->col[2]= evln->col[3];
BLI_remlink(&G.edvl, evl);
freevlak(evl);
}
}
evl= next;
}
}
void deselectall_mesh(void) /* toggle */
{
EditVert *eve;
int a;
if(G.obedit->lay & G.vd->lay) {
a= 0;
eve= G.edve.first;
while(eve) {
if(eve->f & 1) {
a= 1;
break;
}
eve= eve->next;
}
eve= G.edve.first;
while(eve) {
if(eve->h==0) {
if(a) eve->f&= -2;
else eve->f|= 1;
}
eve= eve->next;
}
tekenvertices_ext(a==0);
}
countall();
}
void righthandfaces(int select) /* maakt vlakken rechtsdraaiend */
{
EditEdge *eed, *ed1, *ed2, *ed3, *ed4;
EditVlak *evl, *startvl;
float maxx, nor[3], cent[3];
int totsel, found, foundone, direct, turn;
/* op basis selectconnected om losse objecten te onderscheiden */
/* tel per edge hoeveel vlakken het heeft */
/* vind het meest linkse, voorste, bovenste vlak */
/* zet normaal naar buiten en de eerste richtings vlaggen in de edges */
/* loop object af en zet richtingen / richtingsvlaggen: alleen bij edges van 1 of 2 vlakken */
/* dit is in feit de select connected */
/* indien nog (selected) vlakken niet gedaan: opnieuw vind de meest linkse ... */
waitcursor(1);
eed= G.eded.first;
while(eed) {
eed->f= 0;
eed->f1= 0;
eed= eed->next;
}
/* vlakken en edges tellen */
totsel= 0;
evl= G.edvl.first;
while(evl) {
if(select==0 || vlakselectedAND(evl, 1) ) {
evl->f= 1;
totsel++;
evl->e1->f1++;
evl->e2->f1++;
evl->e3->f1++;
if(evl->v4) evl->e4->f1++;
}
else evl->f= 0;
evl= evl->next;
}
while(totsel>0) {
/* van buiten naar binnen */
evl= G.edvl.first;
startvl= 0;
maxx= -1.0e10;
while(evl) {
if(evl->f) {
CalcCent3f(cent, evl->v1->co, evl->v2->co, evl->v3->co);
cent[0]= fabs(cent[0])+fabs(cent[1])+fabs(cent[2]);
if(cent[0]>maxx) {
maxx= cent[0];
startvl= evl;
}
}
evl= evl->next;
}
/* eerste vlak goedzetten: normaal berekenen */
CalcNormFloat(startvl->v1->co, startvl->v2->co, startvl->v3->co, nor);
CalcCent3f(cent, startvl->v1->co, startvl->v2->co, startvl->v3->co);
/* eerste normaal staat zus of zo */
if(select) {
if(select==2) {
if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] > 0.0) flipvlak(startvl);
}
else {
if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] < 0.0) flipvlak(startvl);
}
}
else if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] < 0.0) flipvlak(startvl);
eed= startvl->e1;
if(eed->v1==startvl->v1) eed->f= 1;
else eed->f= 2;
eed= startvl->e2;
if(eed->v1==startvl->v2) eed->f= 1;
else eed->f= 2;
eed= startvl->e3;
if(eed->v1==startvl->v3) eed->f= 1;
else eed->f= 2;
eed= startvl->e4;
if(eed) {
if(eed->v1==startvl->v4) eed->f= 1;
else eed->f= 2;
}
startvl->f= 0;
totsel--;
/* de normalen testen */
found= 1;
direct= 1;
while(found) {
found= 0;
if(direct) evl= G.edvl.first;
else evl= G.edvl.last;
while(evl) {
if(evl->f) {
turn= 0;
foundone= 0;
ed1= evl->e1;
ed2= evl->e2;
ed3= evl->e3;
ed4= evl->e4;
if(ed1->f) {
if(ed1->v1==evl->v1 && ed1->f==1) turn= 1;
if(ed1->v2==evl->v1 && ed1->f==2) turn= 1;
foundone= 1;
}
else if(ed2->f) {
if(ed2->v1==evl->v2 && ed2->f==1) turn= 1;
if(ed2->v2==evl->v2 && ed2->f==2) turn= 1;
foundone= 1;
}
else if(ed3->f) {
if(ed3->v1==evl->v3 && ed3->f==1) turn= 1;
if(ed3->v2==evl->v3 && ed3->f==2) turn= 1;
foundone= 1;
}
else if(ed4 && ed4->f) {
if(ed4->v1==evl->v4 && ed4->f==1) turn= 1;
if(ed4->v2==evl->v4 && ed4->f==2) turn= 1;
foundone= 1;
}
if(foundone) {
found= 1;
totsel--;
evl->f= 0;
if(turn) {
if(ed1->v1==evl->v1) ed1->f= 2;
else ed1->f= 1;
if(ed2->v1==evl->v2) ed2->f= 2;
else ed2->f= 1;
if(ed3->v1==evl->v3) ed3->f= 2;
else ed3->f= 1;
if(ed4) {
if(ed4->v1==evl->v4) ed4->f= 2;
else ed4->f= 1;
}
flipvlak(evl);
}
else {
if(ed1->v1== evl->v1) ed1->f= 1;
else ed1->f= 2;
if(ed2->v1==evl->v2) ed2->f= 1;
else ed2->f= 2;
if(ed3->v1==evl->v3) ed3->f= 1;
else ed3->f= 2;
if(ed4) {
if(ed4->v1==evl->v4) ed4->f= 1;
else ed4->f= 2;
}
}
}
}
if(direct) evl= evl->next;
else evl= evl->prev;
}
direct= 1-direct;
}
}
recalc_editnormals();
makeDispList(G.obedit);
waitcursor(0);
}
static EditVert *findnearestvert(short sel)
{
/* als sel==1 krijgen vertices met flag==1 een nadeel */
EditVert *eve,*act=0;
static EditVert *acto=0;
short dist=100,temp,mval[2];
if(G.edve.first==0) return 0;
/* projektie doen */
calc_meshverts_ext(); /* drawobject.c */
/* er wordt geteld van acto->next tot last en van first tot acto */
/* bestaat acto ? */
eve= G.edve.first;
while(eve) {
if(eve==acto) break;
eve= eve->next;
}
if(eve==0) acto= G.edve.first;
if(acto==0) return 0;
/* is er een aangegeven vertex? deel 1 */
getmouseco_areawin(mval);
eve= acto->next;
while(eve) {
if(eve->h==0) {
temp= abs(mval[0]- eve->xs)+ abs(mval[1]- eve->ys);
if( (eve->f & 1)==sel ) temp+=5;
if(temp<dist) {
act= eve;
dist= temp;
if(dist<4) break;
}
}
eve= eve->next;
}
/* is er een aangegeven vertex? deel 2 */
if(dist>3) {
eve= G.edve.first;
while(eve) {
if(eve->h==0) {
temp= abs(mval[0]- eve->xs)+ abs(mval[1]- eve->ys);
if( (eve->f & 1)==sel ) temp+=5;
if(temp<dist) {
act= eve;
if(temp<4) break;
dist= temp;
}
if(eve== acto) break;
}
eve= eve->next;
}
}
acto= act;
return act;
}
static void tekenvertices_special(int mode, EditVert *act)
{
/* voor speciale gevallen:
* mode 0: deselect geselecteerde, teken ze, behalve act
* mode 1: teken alleen act
*/
ScrArea *tempsa, *sa;
View3D *vd;
EditVert *eve;
float mat[4][4];
int doit=0;
/* eerst testen of er wel special vertices zijn */
eve= (EditVert *)G.edve.first;
while(eve) {
eve->f1= 0;
if(eve->h==0) {
if(mode==0) {
if(eve!=act && eve->f & 1) {
doit= 1;
eve->f1= 1;
eve->f -= 1;
}
}
else if(mode==1) {
if(eve==act) eve->f1= 1;
doit= 1;
}
}
eve= eve->next;
}
if(doit==0) return;
if(G.f & (G_FACESELECT+G_DRAWFACES)) {
scrarea_queue_winredraw(curarea);
return;
}
if(G.zbuf) glDisable(GL_DEPTH_TEST);
glDrawBuffer(GL_FRONT);
/* alle views aflopen */
tempsa= curarea;
sa= G.curscreen->areabase.first;
while(sa) {
if(sa->spacetype==SPACE_VIEW3D) {
vd= sa->spacedata.first;
if(G.obedit->lay & vd->lay) {
areawinset(sa->win);
mymultmatrix(G.obedit->obmat);
MTC_Mat4SwapMat4(G.vd->persmat, mat);
mygetsingmatrix(G.vd->persmat);
tekenvertices(0);
tekenvertices(1);
MTC_Mat4SwapMat4(G.vd->persmat, mat);
sa->win_swap= WIN_FRONT_OK;
myloadmatrix(G.vd->viewmat);
}
}
sa= sa->next;
}
if(curarea!=tempsa) areawinset(tempsa->win);
glDrawBuffer(GL_BACK);
if(G.zbuf) glEnable(GL_DEPTH_TEST);
}
void mouse_mesh(void)
{
EditVert *act=0;
act= findnearestvert(1);
if(act) {
if((G.qual & LR_SHIFTKEY)==0) {
tekenvertices_special(0, act);
}
if( (act->f & 1)==0) act->f+= 1;
else if(G.qual & LR_SHIFTKEY) act->f-= 1;
tekenvertices_special(1, act);
countall();
}
rightmouse_transform();
}
static void selectconnectedAll(void)
{
EditVert *v1,*v2;
EditEdge *eed;
short flag=1,toggle=0;
if(G.eded.first==0) return;
while(flag==1) {
flag= 0;
toggle++;
if(toggle & 1) eed= G.eded.first;
else eed= G.eded.last;
while(eed) {
v1= eed->v1;
v2= eed->v2;
if(eed->h==0) {
if(v1->f & 1) {
if( (v2->f & 1)==0 ) {
v2->f |= 1;
flag= 1;
}
}
else if(v2->f & 1) {
if( (v1->f & 1)==0 ) {
v1->f |= 1;
flag= 1;
}
}
}
if(toggle & 1) eed= eed->next;
else eed= eed->prev;
}
}
countall();
tekenvertices_ext(1);
}
void selectconnected_mesh(void)
{
EditVert *eve,*v1,*v2,*act= 0;
EditEdge *eed;
short flag=1,sel,toggle=0;
if(G.eded.first==0) return;
if(G.qual & LR_CTRLKEY) {
selectconnectedAll();
return;
}
sel= 3;
if(G.qual & LR_SHIFTKEY) sel=2;
act= findnearestvert(sel-2);
if(act==0) {
error(" Nothing indicated ");
return;
}
/* testflaggen wissen */
eve= G.edve.first;
while(eve) {
eve->f&= ~2;
eve= eve->next;
}
act->f= (act->f & ~3) | sel;
while(flag==1) {
flag= 0;
toggle++;
if(toggle & 1) eed= G.eded.first;
else eed= G.eded.last;
while(eed) {
v1= eed->v1;
v2= eed->v2;
if(eed->h==0) {
if(v1->f & 2) {
if( (v2->f & 2)==0 ) {
v2->f= (v2->f & ~3) | sel;
flag= 1;
}
}
else if(v2->f & 2) {
if( (v1->f & 2)==0 ) {
v1->f= (v1->f & ~3) | sel;
flag= 1;
}
}
}
if(toggle & 1) eed= eed->next;
else eed= eed->prev;
}
}
countall();
tekenvertices_ext( sel==3 );
}
short extrudeflag(short flag,short type)
{
/* als type=1 worden oude extrudevlakken verwijderd (ivm spin etc) */
/* alle verts met (flag & 'flag') extrude */
/* van oude wordt flag 'flag' gewist, van nieuwe gezet */
EditVert *eve, *v1, *v2, *v3, *v4, *nextve;
EditEdge *eed, *e1, *e2, *e3, *e4, *nexted;
EditVlak *evl, *nextvl;
short sel=0, deloud= 0;
if(G.obedit==0 || get_mesh(G.obedit)==0) return 0;
/* de vert flag f1 wissen, hiermee test op losse geselecteerde vert */
eve= G.edve.first;
while(eve) {
if(eve->f & flag) eve->f1= 1;
else eve->f1= 0;
eve= eve->next;
}
/* de edges tellerflag wissen, als selected op 1 zetten */
eed= G.eded.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; /* aangeven is 'oude' edge (er worden in deze routine nieuwe gemaakt */
eed= eed->next;
}
/* in alle vlak sel een dupl.flag zetten en bijhorende edgeflags ophogen */
evl= G.edvl.first;
while(evl) {
evl->f= 0;
if(vlakselectedAND(evl, flag)) {
e1= evl->e1;
e2= evl->e2;
e3= evl->e3;
e4= evl->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++;
evl->f= 1;
}
else if(vlakselectedOR(evl, flag)) {
e1= evl->e1;
e2= evl->e2;
e3= evl->e3;
e4= evl->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;
}
evl= evl->next;
}
/* set direction of edges */
evl= G.edvl.first;
while(evl) {
if(evl->f== 0) {
if(evl->e1->f==2) {
if(evl->e1->v1 == evl->v1) evl->e1->dir= 0;
else evl->e1->dir= 1;
}
if(evl->e2->f==2) {
if(evl->e2->v1 == evl->v2) evl->e2->dir= 0;
else evl->e2->dir= 1;
}
if(evl->e3->f==2) {
if(evl->e3->v1 == evl->v3) evl->e3->dir= 0;
else evl->e3->dir= 1;
}
if(evl->e4 && evl->e4->f==2) {
if(evl->e4->v1 == evl->v4) evl->e4->dir= 0;
else evl->e4->dir= 1;
}
}
evl= evl->next;
}
/* de stand van zaken nu:
eve->f1==1: losse selected vertex
eed->f==0 : edge niet selected, geen extrude
eed->f==1 : edge selected, komt niet in vlak voor, extrude
eed->f==2 : edge selected, komt 1 keer in vlak voor, extrude
eed->f==3 : edge selected, komt in meer vlakken voor, geen extrude
eed->f1==0: nieuwe edge
eed->f1==1: edge selected, komt in selected vlak voor, als f==3: remove
eed->f1==2: edge selected, komt in NIET selected vlak voor
evl->f==1 : vlak dupliceren
*/
/* alle geselecteerde vertices kopieeren, */
/* de pointer naar nieuwe vert in oude struct schrijven op eve->vn */
eve= G.edve.last;
while(eve) {
eve->f&= ~128; /* wissen voor test later op losse 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;
/* alle edges met eed->f==1 of eed->f==2 worden vlakken */
/* als deloud==1 worden edges eed->f>2 verwijderd */
eed= G.eded.last;
while(eed) {
nexted= eed->prev;
if( eed->f<3) {
eed->v1->f|=128; /* =geen losse vert! */
eed->v2->f|=128;
}
if( (eed->f==1 || eed->f==2) ) {
if(eed->f1==2) deloud=1;
/* that dir thing does work somewhat... */
if(eed->dir==1) addvlaklist(eed->v1, eed->v2, eed->v2->vn, eed->v1->vn, NULL);
else addvlaklist(eed->v2, eed->v1, eed->v1->vn, eed->v2->vn, NULL);
}
eed= nexted;
}
if(deloud) {
eed= G.eded.first;
while(eed) {
nexted= eed->next;
if(eed->f==3 && eed->f1==1) {
remedge(eed);
free(eed);
}
eed= nexted;
}
}
/* de vlakken dupliceren, eventueel oude verwijderen */
evl= G.edvl.first;
while(evl) {
nextvl= evl->next;
if(evl->f & 1) {
v1= evl->v1->vn;
v2= evl->v2->vn;
v3= evl->v3->vn;
if(evl->v4) v4= evl->v4->vn; else v4= 0;
addvlaklist(v1, v2, v3, v4, evl);
if(deloud) {
BLI_remlink(&G.edvl, evl);
freevlak(evl);
}
}
evl= nextvl;
}
/* alle verts met eve->vn!=0
als eve->f1==1: edge maken
als flag!=128 :als deloud==1: verwijderen
*/
eve= G.edve.last;
while(eve) {
nextve= eve->prev;
if(eve->vn) {
if(eve->f1==1) addedgelist(eve,eve->vn);
else if( (eve->f & 128)==0) {
if(deloud) {
BLI_remlink(&G.edve,eve);
// free(eve);
free_editvert(eve);
eve= NULL;
}
}
}
if(eve) eve->f&= ~128;
eve= nextve;
}
/* debug temp: testen op consistente:
evl= G.edvl.first;
while(evl) {
e1= findedgelist(evl->v1, evl->v2);
e2= findedgelist(evl->v2, evl->v3);
e3= findedgelist(evl->v3, evl->v1);
if(e1==0 || e2==0 || e3==0) {
error("edge not in edgelist");
break;
}
evl= evl->next;
}
*/
return 1;
}
void rotateflag(short flag, float *cent, float rotmat[][3])
{
/* alle verts met (flag & 'flag') rotate */
EditVert *eve;
eve= G.edve.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)
{
/* alle verts met (flag & 'flag') translate */
EditVert *eve;
eve= G.edve.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;
}
}
short removedoublesflag(short flag, float limit) /* return aantal */
{
/* alle verts met (flag & 'flag') worden getest */
EditVert *eve, *v1, *nextve;
EditEdge *eed, *e1, *nexted;
EditVlak *evl, *nextvl;
struct xvertsort *sortblock, *sb, *sb1;
struct vlaksort *vlsortblock, *vsb, *vsb1;
float dist;
int a, b, test, aantal;
/* flag 128 wordt gewist, aantal tellen */
eve= G.edve.first;
aantal= 0;
while(eve) {
eve->f&= ~128;
if(eve->f & flag) aantal++;
eve= eve->next;
}
if(aantal==0) return 0;
/* geheugen reserveren en qsorten */
sb= sortblock= (struct xvertsort *)MEM_mallocN(sizeof(struct xvertsort)*aantal,"sortremovedoub");
eve= G.edve.first;
while(eve) {
if(eve->f & flag) {
sb->x= eve->co[0]+eve->co[1]+eve->co[2];
sb->v1= eve;
sb++;
}
eve= eve->next;
}
qsort(sortblock, aantal, sizeof(struct xvertsort), vergxco);
/* testen op doubles */
sb= sortblock;
for(a=0; a<aantal; a++) {
eve= sb->v1;
if( (eve->f & 128)==0 ) {
sb1= sb+1;
for(b=a+1; b<aantal; b++) {
/* eerste test: simpel dist */
dist= sb1->x - sb->x;
if(dist > limit) break;
/* tweede test: is vertex toegestaan */
v1= sb1->v1;
if( (v1->f & 128)==0 ) {
dist= fabs(v1->co[0]-eve->co[0]);
if(dist<=limit) {
dist= fabs(v1->co[1]-eve->co[1]);
if(dist<=limit) {
dist= fabs(v1->co[2]-eve->co[2]);
if(dist<=limit) {
v1->f|= 128;
v1->vn= eve;
}
}
}
}
sb1++;
}
}
sb++;
}
MEM_freeN(sortblock);
/* edges testen en opnieuw invoegen */
eed= G.eded.first;
while(eed) {
eed->f= 0;
eed= eed->next;
}
eed= G.eded.last;
while(eed) {
nexted= eed->prev;
if(eed->f==0) {
if( (eed->v1->f & 128) || (eed->v2->f & 128) ) {
remedge(eed);
if(eed->v1->f & 128) eed->v1= eed->v1->vn;
if(eed->v2->f & 128) eed->v2= eed->v2->vn;
e1= addedgelist(eed->v1,eed->v2);
if(e1) e1->f= 1;
if(e1!=eed) free(eed);
}
}
eed= nexted;
}
/* eerst aantal testvlakken tellen */
evl= (struct EditVlak *)G.edvl.first;
aantal= 0;
while(evl) {
evl->f= 0;
if(evl->v1->f & 128) evl->f= 1;
else if(evl->v2->f & 128) evl->f= 1;
else if(evl->v3->f & 128) evl->f= 1;
else if(evl->v4 && (evl->v4->f & 128)) evl->f= 1;
if(evl->f==1) aantal++;
evl= evl->next;
}
/* vlakken testen op dubbele punten en eventueel verwijderen */
evl= (struct EditVlak *)G.edvl.first;
while(evl) {
nextvl= evl->next;
if(evl->f==1) {
if(evl->v1->f & 128) evl->v1= evl->v1->vn;
if(evl->v2->f & 128) evl->v2= evl->v2->vn;
if(evl->v3->f & 128) evl->v3= evl->v3->vn;
if(evl->v4 && (evl->v4->f & 128)) evl->v4= evl->v4->vn;
test= 0;
if(evl->v1==evl->v2) test+=1;
if(evl->v2==evl->v3) test+=2;
if(evl->v3==evl->v1) test+=4;
if(evl->v4==evl->v1) test+=8;
if(evl->v3==evl->v4) test+=16;
if(evl->v2==evl->v4) test+=32;
if(test) {
if(evl->v4) {
if(test==1 || test==2) {
evl->v2= evl->v3;
evl->v3= evl->v4;
evl->v4= 0;
test= 0;
}
else if(test==8 || test==16) {
evl->v4= 0;
test= 0;
}
else {
BLI_remlink(&G.edvl, evl);
freevlak(evl);
aantal--;
}
}
else {
BLI_remlink(&G.edvl, evl);
freevlak(evl);
aantal--;
}
}
if(test==0) {
/* edgepointers goedzetten */
evl->e1= findedgelist(evl->v1, evl->v2);
evl->e2= findedgelist(evl->v2, evl->v3);
if(evl->v4==0) {
evl->e3= findedgelist(evl->v3, evl->v1);
evl->e4= 0;
}
else {
evl->e3= findedgelist(evl->v3, evl->v4);
evl->e4= findedgelist(evl->v4, evl->v1);
}
}
}
evl= nextvl;
}
/* dubbele vlakken: sortblock */
/* opnieuw tellen, nu alle selected vlakken */
aantal= 0;
evl= G.edvl.first;
while(evl) {
evl->f= 0;
if(vlakselectedAND(evl, 1)) {
evl->f= 1;
aantal++;
}
evl= evl->next;
}
if(aantal) {
/* dubbele vlakken: sortblock */
vsb= vlsortblock= MEM_mallocN(sizeof(struct vlaksort)*aantal, "sortremovedoub");
evl= G.edvl.first;
while(evl) {
if(evl->f & 1) {
if(evl->v4) vsb->x= (long) MIN4( (long)evl->v1, (long)evl->v2, (long)evl->v3, (long)evl->v4);
else vsb->x= (long) MIN3( (long)evl->v1, (long)evl->v2, (long)evl->v3);
vsb->evl= evl;
vsb++;
}
evl= evl->next;
}
qsort(vlsortblock, aantal, sizeof(struct vlaksort), vergvlak);
vsb= vlsortblock;
for(a=0; a<aantal; a++) {
evl= vsb->evl;
if( (evl->f & 128)==0 ) {
vsb1= vsb+1;
for(b=a+1; b<aantal; b++) {
/* eerste test: zelfde poin? */
if(vsb->x != vsb1->x) break;
/* tweede test: is test toegestaan */
evl= vsb1->evl;
if( (evl->f & 128)==0 ) {
if( comparevlak(evl, vsb->evl)) evl->f |= 128;
}
vsb1++;
}
}
vsb++;
}
MEM_freeN(vlsortblock);
/* dubbele vlakken eruit */
evl= (struct EditVlak *)G.edvl.first;
while(evl) {
nextvl= evl->next;
if(evl->f & 128) {
BLI_remlink(&G.edvl, evl);
freevlak(evl);
}
evl= nextvl;
}
}
/* dubbele vertices eruit */
a= 0;
eve= (struct EditVert *)G.edve.first;
while(eve) {
nextve= eve->next;
if(eve->f & flag) {
if(eve->f & 128) {
a++;
BLI_remlink(&G.edve, eve);
// free(eve);
free_editvert(eve);
}
}
eve= nextve;
}
return a; /* aantal */
}
void xsortvert_flag(int flag)
//short flag;
{
/* alle verts met (flag & 'flag') worden gesorteerd */
EditVert *eve;
struct xvertsort *sortblock, *sb;
ListBase tbase;
int aantal;
/* aantal tellen */
eve= G.edve.first;
aantal= 0;
while(eve) {
if(eve->f & flag) aantal++;
eve= eve->next;
}
if(aantal==0) return;
/* geheugen reserveren en qsorten */
sb= sortblock= (struct xvertsort *)MEM_mallocN(sizeof(struct xvertsort)*aantal,"sortremovedoub");
eve= G.edve.first;
while(eve) {
if(eve->f & flag) {
sb->x= eve->xs;
sb->v1= eve;
sb++;
}
eve= eve->next;
}
qsort(sortblock, aantal, sizeof(struct xvertsort), vergxco);
/* tijdelijke listbase maken */
tbase.first= tbase.last= 0;
sb= sortblock;
while(aantal--) {
eve= sb->v1;
BLI_remlink(&G.edve, eve);
BLI_addtail(&tbase, eve);
sb++;
}
addlisttolist(&G.edve, &tbase);
MEM_freeN(sortblock);
}
void hashvert_flag(int flag)
{
EditVert *eve;
struct xvertsort *sortblock, *sb, onth, *newsort;
ListBase tbase;
int aantal, a, b;
/* aantal tellen */
eve= G.edve.first;
aantal= 0;
while(eve) {
if(eve->f & flag) aantal++;
eve= eve->next;
}
if(aantal==0) return;
/* geheugen reserveren */
sb= sortblock= (struct xvertsort *)MEM_mallocN(sizeof(struct xvertsort)*aantal,"sortremovedoub");
eve= G.edve.first;
while(eve) {
if(eve->f & flag) {
sb->v1= eve;
sb++;
}
eve= eve->next;
}
BLI_srand(1);
sb= sortblock;
for(a=0; a<aantal; a++, sb++) {
b= aantal*BLI_drand();
if(b>=0 && b<aantal) {
newsort= sortblock+b;
onth= *sb;
*sb= *newsort;
*newsort= onth;
}
}
/* tijdelijke listbase maken */
tbase.first= tbase.last= 0;
sb= sortblock;
while(aantal--) {
eve= sb->v1;
BLI_remlink(&G.edve, eve);
BLI_addtail(&tbase, eve);
sb++;
}
addlisttolist(&G.edve, &tbase);
MEM_freeN(sortblock);
}
static unsigned int cpack_half(unsigned int col1, unsigned int col2)
{
char *cp1, *cp2, *cp;
unsigned int col=0;
cp1= (char *)&col1;
cp2= (char *)&col2;
cp= (char *)&col;
cp[0]= (cp1[0]+cp2[0])>>1;
cp[1]= (cp1[1]+cp2[1])>>1;
cp[2]= (cp1[2]+cp2[2])>>1;
cp[3]= (cp1[3]+cp2[3])>>1;
return col;
}
static void uv_half(float *uv, float *uv1, float *uv2)
{
uv[0]= (uv1[0]+uv2[0])/2.0;
uv[1]= (uv1[1]+uv2[1])/2.0;
}
static void uv_quart(float *uv, float *uv1)
{
uv[0]= (uv1[0]+uv1[2]+uv1[4]+uv1[6])/4.0;
uv[1]= (uv1[1]+uv1[3]+uv1[5]+uv1[7])/4.0;
}
static void set_wuv(int tot, EditVlak *evl, int v1, int v2, int v3, int v4)
{
/* deze vreemde fie alleen bij de subdiv te gebruiken, de 'w' in de naam slaat nergens op! */
float *uv, uvo[4][2];
unsigned int *col, colo[4], col1, col2;
int a, v;
memcpy(uvo, evl->uv, sizeof(uvo));
uv= evl->uv[0];
memcpy(colo, evl->col, sizeof(colo));
col= evl->col;
if(tot==4) {
for(a=0; a<4; a++, uv+=2, col++) {
if(a==0) v= v1;
else if(a==1) v= v2;
else if(a==2) v= v3;
else v= v4;
if(a==3 && v4==0) break;
if(v<=4) {
uv[0]= uvo[v-1][0];
uv[1]= uvo[v-1][1];
*col= colo[v-1];
}
else if(v==8) {
uv_half(uv, uvo[3], uvo[0]);
*col= cpack_half(colo[3], colo[0]);
}
else if(v==9) {
uv_quart(uv, uvo[0]);
col1= cpack_half(colo[1], colo[0]);
col2= cpack_half(colo[2], colo[3]);
*col= cpack_half(col1, col2);
}
else {
uv_half(uv, uvo[v-5], uvo[v-4]);
*col= cpack_half(colo[v-5], colo[v-4]);
}
}
}
else {
for(a=0; a<3; a++, uv+=2, col++) {
if(a==0) v= v1;
else if(a==1) v= v2;
else v= v3;
if(v<=4) {
uv[0]= uvo[v-1][0];
uv[1]= uvo[v-1][1];
*col= colo[v-1];
}
else if(v==7) {
uv_half(uv, uvo[2], uvo[0]);
*col= cpack_half(colo[2], colo[0]);
}
else {
uv_half(uv, uvo[v-5], uvo[v-4]);
*col= cpack_half(colo[v-5], colo[v-4]);
}
}
}
}
static EditVert *vert_from_number(EditVlak *evl, int nr)
{
switch(nr) {
case 0:
return 0;
case 1:
return evl->v1;
case 2:
return evl->v2;
case 3:
return evl->v3;
case 4:
return evl->v4;
case 5:
return evl->e1->vn;
case 6:
return evl->e2->vn;
case 7:
return evl->e3->vn;
case 8:
return evl->e4->vn;
}
return NULL;
}
static void addvlak_subdiv(EditVlak *evl, int val1, int val2, int val3, int val4, EditVert *eve)
{
EditVlak *w;
EditVert *v1, *v2, *v3, *v4;
if(val1==9) v1= eve;
else v1= vert_from_number(evl, val1);
if(val2==9) v2= eve;
else v2= vert_from_number(evl, val2);
if(val3==9) v3= eve;
else v3= vert_from_number(evl, val3);
if(val4==9) v4= eve;
else v4= vert_from_number(evl, val4);
w= addvlaklist(v1, v2, v3, v4, evl);
if(w) {
if(evl->v4) set_wuv(4, w, val1, val2, val3, val4);
else set_wuv(3, w, val1, val2, val3, val4);
}
}
static float smoothperc= 0.0;
static void smooth_subdiv_vec(float *v1, float *v2, float *n1, float *n2, float *vec)
{
float len, fac, nor[3], nor1[3], nor2[3];
VecSubf(nor, v1, v2);
len= 0.5*Normalise(nor);
VECCOPY(nor1, n1);
VECCOPY(nor2, n2);
/* cosine angle */
fac= nor[0]*nor1[0] + nor[1]*nor1[1] + nor[2]*nor1[2] ;
vec[0]= fac*nor1[0];
vec[1]= fac*nor1[1];
vec[2]= fac*nor1[2];
/* cosine angle */
fac= -nor[0]*nor2[0] - nor[1]*nor2[1] - nor[2]*nor2[2] ;
vec[0]+= fac*nor2[0];
vec[1]+= fac*nor2[1];
vec[2]+= fac*nor2[2];
vec[0]*= smoothperc*len;
vec[1]*= smoothperc*len;
vec[2]*= smoothperc*len;
}
static void smooth_subdiv_quad(EditVlak *evl, float *vec)
{
float nor1[3], nor2[3];
float vec1[3], vec2[3];
float cent[3];
/* vlr->e1->vn is new vertex inbetween v1 / v2 */
VecMidf(nor1, evl->v1->no, evl->v2->no);
Normalise(nor1);
VecMidf(nor2, evl->v3->no, evl->v4->no);
Normalise(nor2);
smooth_subdiv_vec( evl->e1->vn->co, evl->e3->vn->co, nor1, nor2, vec1);
VecMidf(nor1, evl->v2->no, evl->v3->no);
Normalise(nor1);
VecMidf(nor2, evl->v4->no, evl->v1->no);
Normalise(nor2);
smooth_subdiv_vec( evl->e2->vn->co, evl->e4->vn->co, nor1, nor2, vec2);
VecAddf(vec1, vec1, vec2);
CalcCent4f(cent, evl->v1->co, evl->v2->co, evl->v3->co, evl->v4->co);
VecAddf(vec, cent, vec1);
}
void subdivideflag(int flag, float rad, int beauty)
{
/* divide alle vlakken met (vertflag & flag) */
/* als rad>0.0 zet dan nieuw vert op afstand rad van 0,0,0 */
extern float doublimit;
EditVert *eve;
EditEdge *eed, *e1, *e2, *e3, *e4, *nexted;
EditVlak *evl;
float fac, vec[3], vec1[3], len1, len2, len3;
short test;
if(beauty & B_SMOOTH) {
short perc= 100;
if(button(&perc, 10, 500, "Percentage:")==0) return;
smoothperc= 0.292*perc/100.0;
}
/* edgeflags */
eed= G.eded.first;
while(eed) {
if( (eed->v1->f & flag) && (eed->v2->f & flag) ) eed->f= flag;
else eed->f= 0;
eed= eed->next;
}
/* als beauty: opp testen en edgeflags wissen van 'lelijke' edges */
if(beauty & B_BEAUTY) {
evl= G.edvl.first;
while(evl) {
if( vlakselectedAND(evl, flag) ) {
if(evl->v4) {
/* opp */
len1= AreaQ3Dfl(evl->v1->co, evl->v2->co, evl->v3->co, evl->v4->co);
if(len1 <= doublimit) {
evl->e1->f = 0;
evl->e2->f = 0;
evl->e3->f = 0;
evl->e4->f = 0;
}
else {
len1= VecLenf(evl->v1->co, evl->v2->co) + VecLenf(evl->v3->co, evl->v4->co);
len2= VecLenf(evl->v2->co, evl->v3->co) + VecLenf(evl->v1->co, evl->v4->co);
if(len1 < len2) {
evl->e1->f = 0;
evl->e3->f = 0;
}
else if(len1 > len2) {
evl->e2->f = 0;
evl->e4->f = 0;
}
}
}
else {
/* opp */
len1= AreaT3Dfl(evl->v1->co, evl->v2->co, evl->v3->co);
if(len1 <= doublimit) {
evl->e1->f = 0;
evl->e2->f = 0;
evl->e3->f = 0;
}
else {
len1= VecLenf(evl->v1->co, evl->v2->co) ;
len2= VecLenf(evl->v2->co, evl->v3->co) ;
len3= VecLenf(evl->v3->co, evl->v1->co) ;
if(len1<len2 && len1<len3) {
evl->e1->f = 0;
}
else if(len2<len3 && len2<len1) {
evl->e2->f = 0;
}
else if(len3<len2 && len3<len1) {
evl->e3->f = 0;
}
}
}
}
evl= evl->next;
}
}
if(beauty & B_SMOOTH) {
vertexnormals(0); /* no1*/
}
/* nieuw punt maken en in edge wegschrijven, flag wissen! is voor vlakkenmaak stuk nodig */
eed= G.eded.first;
while(eed) {
if(eed->f & flag) {
vec[0]= (eed->v1->co[0]+eed->v2->co[0])/2.0;
vec[1]= (eed->v1->co[1]+eed->v2->co[1])/2.0;
vec[2]= (eed->v1->co[2]+eed->v2->co[2])/2.0;
if(rad > 0.0) { /* perf sph */
Normalise(vec);
vec[0]*= rad;
vec[1]*= rad;
vec[2]*= rad;
}
else if(rad< 0.0) { /* fract */
fac= rad* VecLenf(eed->v1->co, eed->v2->co);
vec1[0]= fac*BLI_drand();
vec1[1]= fac*BLI_drand();
vec1[2]= fac*BLI_drand();
VecAddf(vec, vec, vec1);
}
if(beauty & B_SMOOTH) {
smooth_subdiv_vec(eed->v1->co, eed->v2->co, eed->v1->no, eed->v2->no, vec1);
VecAddf(vec, vec, vec1);
}
eed->vn= addvertlist(vec);
eed->vn->f= eed->v1->f;
}
else eed->vn= 0;
eed->f= 0; /* moet! */
eed= eed->next;
}
/* alle vlakken testen op subdiv edges, 8 of 16 gevallen! */
evl= G.edvl.last;
while(evl) {
if( vlakselectedOR(evl, flag) ) {
e1= evl->e1;
e2= evl->e2;
e3= evl->e3;
e4= evl->e4;
test= 0;
if(e1 && e1->vn) {
test+= 1;
e1->f= 1;
}
if(e2 && e2->vn) {
test+= 2;
e2->f= 1;
}
if(e3 && e3->vn) {
test+= 4;
e3->f= 1;
}
if(e4 && e4->vn) {
test+= 8;
e4->f= 1;
}
if(test) {
if(evl->v4==0) {
if((test & 3)==3) addvlak_subdiv(evl, 2, 2+4, 1+4, 0, 0);
if((test & 6)==6) addvlak_subdiv(evl, 3, 3+4, 2+4, 0, 0);
if((test & 5)==5) addvlak_subdiv(evl, 1, 1+4, 3+4, 0, 0);
if(test==7) { /* vier nieuwe vlakken, oude vernieuwt */
evl->v1= e1->vn;
evl->v2= e2->vn;
evl->v3= e3->vn;
set_wuv(3, evl, 1+4, 2+4, 3+4, 0);
}
else if(test==3) {
addvlak_subdiv(evl, 1+4, 2+4, 3, 0, 0);
evl->v2= e1->vn;
set_wuv(3, evl, 1, 1+4, 3, 0);
}
else if(test==6) {
addvlak_subdiv(evl, 2+4, 3+4, 1, 0, 0);
evl->v3= e2->vn;
set_wuv(3, evl, 1, 2, 2+4, 0);
}
else if(test==5) {
addvlak_subdiv(evl, 3+4, 1+4, 2, 0, 0);
evl->v1= e3->vn;
set_wuv(3, evl, 3+4, 2, 3, 0);
}
else if(test==1) {
addvlak_subdiv(evl, 1+4, 2, 3, 0, 0);
evl->v2= e1->vn;
set_wuv(3, evl, 1, 1+4, 3, 0);
}
else if(test==2) {
addvlak_subdiv(evl, 2+4, 3, 1, 0, 0);
evl->v3= e2->vn;
set_wuv(3, evl, 1, 2, 2+4, 0);
}
else if(test==4) {
addvlak_subdiv(evl, 3+4, 1, 2, 0, 0);
evl->v1= e3->vn;
set_wuv(3, evl, 3+4, 2, 3, 0);
}
evl->e1= addedgelist(evl->v1, evl->v2);
evl->e2= addedgelist(evl->v2, evl->v3);
evl->e3= addedgelist(evl->v3, evl->v1);
}
else {
if(test==15) {
/* nog een nieuw punt toevoegen */
CalcCent4f(vec, evl->v1->co, evl->v2->co, evl->v3->co, evl->v4->co);
if(beauty & B_SMOOTH) {
smooth_subdiv_quad(evl, vec); /* adds */
}
eve= addvertlist(vec);
eve->f |= flag;
addvlak_subdiv(evl, 2, 2+4, 9, 1+4, eve);
addvlak_subdiv(evl, 3, 3+4, 9, 2+4, eve);
addvlak_subdiv(evl, 4, 4+4, 9, 3+4, eve);
evl->v2= e1->vn;
evl->v3= eve;
evl->v4= e4->vn;
set_wuv(4, evl, 1, 1+4, 9, 4+4);
}
else {
/* kleine hoekpunten */
if((test & 3)==3) addvlak_subdiv(evl, 1+4, 2, 2+4, 0, 0);
if((test & 6)==6) addvlak_subdiv(evl, 2+4, 3, 3+4, 0, 0);
if((test & 12)==12) addvlak_subdiv(evl, 3+4, 4, 4+4, 0, 0);
if((test & 9)==9) addvlak_subdiv(evl, 4+4, 1, 1+4, 0, 0);
if(test==1) {
addvlak_subdiv(evl, 1+4, 2, 3, 0, 0);
addvlak_subdiv(evl, 1+4, 3, 4, 0, 0);
evl->v2= e1->vn;
evl->v3= evl->v4;
evl->v4= 0;
set_wuv(4, evl, 1, 1+4, 4, 0);
}
else if(test==2) {
addvlak_subdiv(evl, 2+4, 3, 4, 0, 0);
addvlak_subdiv(evl, 2+4, 4, 1, 0, 0);
evl->v3= e2->vn;
evl->v4= 0;
set_wuv(4, evl, 1, 2, 2+4, 0);
}
else if(test==4) {
addvlak_subdiv(evl, 3+4, 4, 1, 0, 0);
addvlak_subdiv(evl, 3+4, 1, 2, 0, 0);
evl->v1= evl->v2;
evl->v2= evl->v3;
evl->v3= e3->vn;
evl->v4= 0;
set_wuv(4, evl, 2, 3, 3+4, 0);
}
else if(test==8) {
addvlak_subdiv(evl, 4+4, 1, 2, 0, 0);
addvlak_subdiv(evl, 4+4, 2, 3, 0, 0);
evl->v1= evl->v3;
evl->v2= evl->v4;
evl->v3= e4->vn;
evl->v4= 0;
set_wuv(4, evl, 3, 4, 4+4, 0);
}
else if(test==3) {
addvlak_subdiv(evl, 1+4, 2+4, 4, 0, 0);
addvlak_subdiv(evl, 2+4, 3, 4, 0, 0);
evl->v2= e1->vn;
evl->v3= evl->v4;
evl->v4= 0;
set_wuv(4, evl, 1, 1+4, 4, 0);
}
else if(test==6) {
addvlak_subdiv(evl, 2+4, 3+4, 1, 0, 0);
addvlak_subdiv(evl, 3+4, 4, 1, 0, 0);
evl->v3= e2->vn;
evl->v4= 0;
set_wuv(4, evl, 1, 2, 2+4, 0);
}
else if(test==12) {
addvlak_subdiv(evl, 3+4, 4+4, 2, 0, 0);
addvlak_subdiv(evl, 4+4, 1, 2, 0, 0);
evl->v1= evl->v2;
evl->v2= evl->v3;
evl->v3= e3->vn;
evl->v4= 0;
set_wuv(4, evl, 2, 3, 3+4, 0);
}
else if(test==9) {
addvlak_subdiv(evl, 4+4, 1+4, 3, 0, 0);
addvlak_subdiv(evl, 1+4, 2, 3, 0, 0);
evl->v1= evl->v3;
evl->v2= evl->v4;
evl->v3= e4->vn;
evl->v4= 0;
set_wuv(4, evl, 3, 4, 4+4, 0);
}
else if(test==5) {
addvlak_subdiv(evl, 1+4, 2, 3, 3+4, 0);
evl->v2= e1->vn;
evl->v3= e3->vn;
set_wuv(4, evl, 1, 1+4, 3+4, 4);
}
else if(test==10) {
addvlak_subdiv(evl, 2+4, 3, 4, 4+4, 0);
evl->v3= e2->vn;
evl->v4= e4->vn;
set_wuv(4, evl, 1, 2, 2+4, 4+4);
}
else if(test==7) {
addvlak_subdiv(evl, 1+4, 2+4, 3+4, 0, 0);
evl->v2= e1->vn;
evl->v3= e3->vn;
set_wuv(4, evl, 1, 1+4, 3+4, 4);
}
else if(test==14) {
addvlak_subdiv(evl, 2+4, 3+4, 4+4, 0, 0);
evl->v3= e2->vn;
evl->v4= e4->vn;
set_wuv(4, evl, 1, 2, 2+4, 4+4);
}
else if(test==13) {
addvlak_subdiv(evl, 3+4, 4+4, 1+4, 0, 0);
evl->v4= e3->vn;
evl->v1= e1->vn;
set_wuv(4, evl, 1+4, 3, 3, 3+4);
}
else if(test==11) {
addvlak_subdiv(evl, 4+4, 1+4, 2+4, 0, 0);
evl->v1= e4->vn;
evl->v2= e2->vn;
set_wuv(4, evl, 4+4, 2+4, 3, 4);
}
}
evl->e1= addedgelist(evl->v1, evl->v2);
evl->e2= addedgelist(evl->v2, evl->v3);
if(evl->v4) evl->e3= addedgelist(evl->v3, evl->v4);
else evl->e3= addedgelist(evl->v3, evl->v1);
if(evl->v4) evl->e4= addedgelist(evl->v4, evl->v1);
else evl->e4= 0;
}
}
}
evl= evl->prev;
}
/* alle oude edges verwijderen, eventueel nog nieuwe maken */
eed= G.eded.first;
while(eed) {
nexted= eed->next;
if( eed->vn ) {
if(eed->f==0) { /* niet gebruikt in vlak */
addedgelist(eed->v1,eed->vn);
addedgelist(eed->vn,eed->v2);
}
remedge(eed);
free(eed);
}
eed= nexted;
}
countall();
allqueue(REDRAWVIEW3D, 0);
makeDispList(G.obedit);
}
void adduplicateflag(int flag)
{
/* oude verts hebben flag 128 gezet en flag 'flag' gewist
nieuwe verts hebben flag 'flag' gezet */
EditVert *eve, *v1, *v2, *v3, *v4;
EditEdge *eed;
EditVlak *evl;
/* eerst vertices */
eve= G.edve.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= G.eded.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->next;
}
/* tenslotte de vlakken dupliceren */
evl= G.edvl.first;
while(evl) {
if( (evl->v1->f & 128) && (evl->v2->f & 128) && (evl->v3->f & 128) ) {
if(evl->v4) {
if(evl->v4->f & 128) {
v1= evl->v1->vn;
v2= evl->v2->vn;
v3= evl->v3->vn;
v4= evl->v4->vn;
addvlaklist(v1, v2, v3, v4, evl);
}
}
else {
v1= evl->v1->vn;
v2= evl->v2->vn;
v3= evl->v3->vn;
addvlaklist(v1, v2, v3, 0, evl);
}
}
evl= evl->next;
}
}
static void delvlakflag(int flag)
{
/* alle vlak 3/4 verts flag + edges + losse vertices deleten */
/* van alle verts wordt 'flag' gewist */
EditVert *eve,*nextve;
EditEdge *eed, *nexted;
EditVlak *evl,*nextvl;
eed= G.eded.first;
while(eed) {
eed->f= 0;
eed= eed->next;
}
evl= G.edvl.first;
while(evl) {
nextvl= evl->next;
if(vlakselectedAND(evl, flag)) {
evl->e1->f= 1;
evl->e2->f= 1;
evl->e3->f= 1;
if(evl->e4) {
evl->e4->f= 1;
}
BLI_remlink(&G.edvl, evl);
freevlak(evl);
}
evl= nextvl;
}
/* alle vlakken 1, 2 (3) verts select edges behouden */
evl= G.edvl.first;
while(evl) {
evl->e1->f= 0;
evl->e2->f= 0;
evl->e3->f= 0;
if(evl->e4) {
evl->e4->f= 0;
}
evl= evl->next;
}
/* alle edges testen op vertices met flag en wissen */
eed= G.eded.first;
while(eed) {
nexted= eed->next;
if(eed->f==1) {
remedge(eed);
free(eed);
}
else if( (eed->v1->f & flag) || (eed->v2->f & flag) ) {
eed->v1->f&= ~flag;
eed->v2->f&= ~flag;
}
eed= nexted;
}
/* vertices met flag nog gezet zijn losse en worden verwijderd */
eve= G.edve.first;
while(eve) {
nextve= eve->next;
if(eve->f & flag) {
BLI_remlink(&G.edve, eve);
// free(eve);
free_editvert(eve);
}
eve= nextve;
}
}
void extrude_mesh(void)
{
short a;
TEST_EDITMESH
if(okee("Extrude")==0) return;
waitcursor(1);
a= extrudeflag(1,1);
waitcursor(0);
if(a==0) {
error("Can't extrude");
}
else {
countall(); /* voor G.totvert in calc_meshverts() */
calc_meshverts();
transform('d');
}
}
void adduplicate_mesh(void)
{
TEST_EDITMESH
waitcursor(1);
adduplicateflag(1);
waitcursor(0);
countall(); /* voor G.totvert in calc_meshverts() */
transform('d');
}
void split_mesh(void)
{
TEST_EDITMESH
if(okee(" Split ")==0) return;
waitcursor(1);
/* eerst duplicate maken */
adduplicateflag(1);
/* oude vlakken hebben 3x flag 128 gezet, deze deleten */
delvlakflag(128);
waitcursor(0);
countall();
allqueue(REDRAWVIEW3D, 0);
makeDispList(G.obedit);
}
void separate_mesh(void)
{
EditVert *eve, *v1;
EditEdge *eed, *e1;
EditVlak *evl, *vl1;
Object *oldob;
Mesh *me, *men;
Base *base, *oldbase;
ListBase edve, eded, edvl;
float trans[9];
int ok, flag;
TEST_EDITMESH
if(okee("Separate")==0) return;
waitcursor(1);
me= get_mesh(G.obedit);
if(me->key) {
error("Can't separate with vertex keys");
return;
}
/* we gaan de zaak als volgt neppen:
* 1. duplicate object: dit wordt de nieuwe, oude pointer onthouden
* 2: split doen als modig.
* 3. alle NIET geselecteerde verts, edges, vlakken apart zetten
* 4. loadobeditdata(): dit is de nieuwe ob
* 5. freelist en oude verts, eds, vlakken weer terughalen
*/
/* alleen obedit geselecteerd */
base= FIRSTBASE;
while(base) {
if(base->lay & G.vd->lay) {
if(base->object==G.obedit) base->flag |= SELECT;
else base->flag &= ~SELECT;
}
base= base->next;
}
/* testen of split */
ok= 0;
eed= G.eded.first;
while(eed) {
flag= (eed->v1->f & 1)+(eed->v2->f & 1);
if(flag==1) {
ok= 1;
break;
}
eed= eed->next;
}
if(ok) {
/* SPLIT: eerst duplicate maken */
adduplicateflag(1);
/* SPLIT: oude vlakken hebben 3x flag 128 gezet, deze deleten */
delvlakflag(128);
}
/* apart zetten: alles wat maar enigszins NIET select is */
edve.first= edve.last= eded.first= eded.last= edvl.first= edvl.last= 0;
eve= G.edve.first;
while(eve) {
v1= eve->next;
if((eve->f & 1)==0) {
BLI_remlink(&G.edve, eve);
BLI_addtail(&edve, eve);
}
eve= v1;
}
eed= G.eded.first;
while(eed) {
e1= eed->next;
if( (eed->v1->f & 1)==0 || (eed->v2->f & 1)==0 ) {
BLI_remlink(&G.eded, eed);
BLI_addtail(&eded, eed);
}
eed= e1;
}
evl= G.edvl.first;
while(evl) {
vl1= evl->next;
if( (evl->v1->f & 1)==0 || (evl->v2->f & 1)==0 || (evl->v3->f & 1)==0 ) {
BLI_remlink(&G.edvl, evl);
BLI_addtail(&edvl, evl);
}
evl= vl1;
}
oldob= G.obedit;
oldbase= BASACT;
trans[0]=trans[1]=trans[2]=trans[3]=trans[4]=trans[5]= 0.0;
trans[6]=trans[7]=trans[8]= 1.0;
G.qual |= LR_ALTKEY; /* patch om zeker te zijn van gelinkte dupli */
adduplicate(trans);
G.qual &= ~LR_ALTKEY;
G.obedit= BASACT->object; /* basact wordt in adduplicate() gezet */
men= copy_mesh(me);
set_mesh(G.obedit, men);
/* omdat nieuwe mesh een kopie is: aantal users verlagen */
men->id.us--;
load_editMesh();
BASACT->flag &= ~SELECT;
makeDispList(G.obedit);
free_editMesh();
G.edve= edve;
G.eded= eded;
G.edvl= edvl;
/* hashedges are freed now, make new! */
eed= G.eded.first;
while(eed) {
if( findedgelist(eed->v1, eed->v2)==NULL )
insert_hashedge(eed);
eed= eed->next;
}
G.obedit= oldob;
BASACT= oldbase;
BASACT->flag |= SELECT;
waitcursor(0);
countall();
allqueue(REDRAWVIEW3D, 0);
makeDispList(G.obedit);
}
void extrude_repeat_mesh(int steps, float offs)
{
float dvec[3], tmat[3][3], bmat[3][3];
/* float phi; */
short a,ok;
TEST_EDITMESH
waitcursor(1);
/* dvec */
dvec[0]= G.vd->persinv[2][0];
dvec[1]= G.vd->persinv[2][1];
dvec[2]= G.vd->persinv[2][2];
Normalise(dvec);
dvec[0]*= offs;
dvec[1]*= offs;
dvec[2]*= offs;
/* base correctie */
Mat3CpyMat4(bmat, G.obedit->obmat);
/* phi= ((struct ObData *)G.obedit->d)->vv->ws; */
/* Mat3MulFloat(bmat, phi); */
Mat3Inv(tmat, bmat);
Mat3MulVecfl(tmat, dvec);
for(a=0;a<steps;a++) {
ok= extrudeflag(1,1);
if(ok==0) {
error("Can't extrude");
break;
}
translateflag(1, dvec);
}
countall();
allqueue(REDRAWVIEW3D, 0);
makeDispList(G.obedit);
waitcursor(0);
}
void spin_mesh(int steps,int degr,float *dvec, int mode)
{
EditVert *eve,*nextve;
float *curs, si,n[3],q[4],cmat[3][3],imat[3][3], tmat[3][3];
float cent[3],bmat[3][3];
float phi;
short a,ok;
TEST_EDITMESH
waitcursor(1);
/* imat en centrum en afmeting */
Mat3CpyMat4(bmat, G.obedit->obmat);
Mat3Inv(imat,bmat);
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];
Mat3MulVecfl(imat, cent);
phi= degr*M_PI/360.0;
phi/= steps;
if(editbutflag & B_CLOCKWISE) phi= -phi;
if(dvec) {
n[0]=n[1]= 0.0;
n[2]= 1.0;
} else {
n[0]= G.vd->viewinv[2][0];
n[1]= G.vd->viewinv[2][1];
n[2]= G.vd->viewinv[2][2];
Normalise(n);
}
q[0]= cos(phi);
si= sin(phi);
q[1]= n[0]*si;
q[2]= n[1]*si;
q[3]= n[2]*si;
QuatToMat3(q, cmat);
Mat3MulMat3(tmat,cmat,bmat);
Mat3MulMat3(bmat,imat,tmat);
if(mode==0) if(editbutflag & B_KEEPORIG) adduplicateflag(1);
ok= 1;
for(a=0;a<steps;a++) {
if(mode==0) ok= extrudeflag(1,1);
else adduplicateflag(1);
if(ok==0) {
error("Can't spin");
break;
}
rotateflag(1, cent, bmat);
if(dvec) {
Mat3MulVecfl(bmat,dvec);
translateflag(1,dvec);
}
}
waitcursor(0);
if(ok==0) {
/* geen of alleen losse verts select, dups verwijderen */
eve= G.edve.first;
while(eve) {
nextve= eve->next;
if(eve->f & 1) {
BLI_remlink(&G.edve,eve);
// free(eve);
free_editvert(eve);
}
eve= nextve;
}
}
countall();
recalc_editnormals();
allqueue(REDRAWVIEW3D, 0);
makeDispList(G.obedit);
}
void screw_mesh(int steps,int turns)
{
EditVert *eve,*v1=0,*v2=0;
EditEdge *eed;
float dvec[3], nor[3];
TEST_EDITMESH
/* eerste voorwaarde: frontview! */
if(G.vd->view!=1) {
error("Only in frontview!");
return;
}
/* flags wissen */
eve= G.edve.first;
while(eve) {
eve->f1= 0;
eve= eve->next;
}
/* edges zetten flags in verts */
eed= G.eded.first;
while(eed) {
if(eed->v1->f & 1) {
if(eed->v2->f & 1) {
/* oppassen f1 is een byte */
if(eed->v1->f1<2) eed->v1->f1++;
if(eed->v2->f1<2) eed->v2->f1++;
}
}
eed= eed->next;
}
/* vind twee vertices met eve->f1==1, meer of minder is fout */
eve= G.edve.first;
while(eve) {
if(eve->f1==1) {
if(v1==0) v1= eve;
else if(v2==0) v2= eve;
else {
v1=0;
break;
}
}
eve= eve->next;
}
if(v1==0 || v2==0) {
error("No curve selected");
return;
}
/* bereken dvec */
dvec[0]= ( (v1->co[0]- v2->co[0]) )/(steps);
dvec[1]= ( (v1->co[1]- v2->co[1]) )/(steps);
dvec[2]= ( (v1->co[2]- v2->co[2]) )/(steps);
VECCOPY(nor, G.obedit->obmat[2]);
if(nor[0]*dvec[0]+nor[1]*dvec[1]+nor[2]*dvec[2]>0.000) {
dvec[0]= -dvec[0];
dvec[1]= -dvec[1];
dvec[2]= -dvec[2];
}
spin_mesh(turns*steps, turns*360, dvec, 0);
}
void selectswap_mesh(void)
{
EditVert *eve;
eve= G.edve.first;
while(eve) {
if(eve->h==0) {
if(eve->f & 1) eve->f&= ~1;
else eve->f|= 1;
}
eve= eve->next;
}
countall();
allqueue(REDRAWVIEW3D, 0);
}
/* ******************************* ADD ********************* */
void addvert_mesh(void)
{
EditVert *eve,*v1=0;
float *curs, mat[3][3],imat[3][3];
TEST_EDITMESH
Mat3CpyMat4(mat, G.obedit->obmat);
Mat3Inv(imat, mat);
v1= G.edve.first;
while(v1) {
if(v1->f & 1) break;
v1= v1->next;
}
eve= v1; /* voorkomen dat er nog meer select zijn */
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);
v1->f= 0;
}
countall();
allqueue(REDRAWVIEW3D, 0);
makeDispList(G.obedit);
while(get_mbut()&R_MOUSE);
}
void addedgevlak_mesh(void)
{
EditVert *eve, *neweve[4];
EditVlak *evl;
float con1, con2, con3;
short aantal=0;
if( (G.vd->lay & G.obedit->lay)==0 ) return;
/* hoeveel geselecteerd ? */
eve= G.edve.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]);
allqueue(REDRAWVIEW3D, 0);
makeDispList(G.obedit);
return;
}
if(aantal<2 || aantal>4) {
error("Can't make edge/face");
return;
}
evl= NULL; // check later
if(aantal==3) {
if(exist_vlak(neweve[0], neweve[1], neweve[2], 0)==0) {
evl= addvlaklist(neweve[0], neweve[1], neweve[2], 0, NULL);
}
else error("Already a face");
}
else if(aantal==4) {
if(exist_vlak(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)
evl= addvlaklist(neweve[0], neweve[1], neweve[2], neweve[3], NULL);
else if(con2>=con1 && con2>=con3)
evl= addvlaklist(neweve[0], neweve[2], neweve[3], neweve[1], NULL);
else
evl= addvlaklist(neweve[0], neweve[2], neweve[1], neweve[3], NULL);
}
else error("Already a face");
}
if(evl) { // now we're calculating direction of normal
float inp;
/* dot product view mat with normal, should give info! */
CalcNormFloat(evl->v1->co, evl->v2->co, evl->v3->co, evl->n);
inp= evl->n[0]*G.vd->viewmat[0][2] + evl->n[1]*G.vd->viewmat[1][2] + evl->n[2]*G.vd->viewmat[2][2];
if(inp < 0.0) flipvlak(evl);
}
countall();
allqueue(REDRAWVIEW3D, 0);
makeDispList(G.obedit);
}
static void erase_edges(ListBase *l)
{
EditEdge *ed, *nexted;
ed = (EditEdge *) l->first;
while(ed) {
nexted= ed->next;
if( (ed->v1->f & 1) || (ed->v2->f & 1) ) {
remedge(ed);
free(ed);
}
ed= nexted;
}
}
static void erase_faces(ListBase *l)
{
EditVlak *f, *nextf;
f = (EditVlak *) l->first;
while(f) {
nextf= f->next;
if( vlakselectedOR(f, 1) ) {
BLI_remlink(l, f);
freevlak(f);
}
f = nextf;
}
}
static void erase_vertices(ListBase *l)
{
EditVert *v, *nextv;
v = (EditVert *) l->first;
while(v) {
nextv= v->next;
if(v->f & 1) {
BLI_remlink(l, v);
free_editvert(v);
}
v = nextv;
}
}
void delete_mesh(void)
{
EditVlak *evl, *nextvl;
EditVert *eve,*nextve;
EditEdge *eed,*nexted;
short event;
int count;
TEST_EDITMESH
event= pupmenu("ERASE %t|Vertices%x10|Edges%x1|Faces%x2|All%x3|Edges & Faces%x4|Only Faces%x5");
if(event<1) return;
if(event==10 ) {
erase_edges(&G.eded);
erase_faces(&G.edvl);
erase_vertices(&G.edve);
}
else if(event==4) {
evl= G.edvl.first;
while(evl) {
nextvl= evl->next;
/* delete only faces with 2 or more vertices selected */
count= 0;
if(evl->v1->f & 1) count++;
if(evl->v2->f & 1) count++;
if(evl->v3->f & 1) count++;
if(evl->v4 && (evl->v4->f & 1)) count++;
if(count>1) {
BLI_remlink(&G.edvl, evl);
freevlak(evl);
}
evl= nextvl;
}
eed= G.eded.first;
while(eed) {
nexted= eed->next;
if( (eed->v1->f & 1) && (eed->v2->f & 1) ) {
remedge(eed);
free(eed);
}
eed= nexted;
}
evl= G.edvl.first;
while(evl) {
nextvl= evl->next;
event=0;
if( evl->v1->f & 1) event++;
if( evl->v2->f & 1) event++;
if( evl->v3->f & 1) event++;
if(evl->v4 && (evl->v4->f & 1)) event++;
if(event>1) {
BLI_remlink(&G.edvl, evl);
freevlak(evl);
}
evl= nextvl;
}
}
else if(event==1) {
eed= G.eded.first;
while(eed) {
nexted= eed->next;
if( (eed->v1->f & 1) && (eed->v2->f & 1) ) {
remedge(eed);
free(eed);
}
eed= nexted;
}
evl= G.edvl.first;
while(evl) {
nextvl= evl->next;
event=0;
if( evl->v1->f & 1) event++;
if( evl->v2->f & 1) event++;
if( evl->v3->f & 1) event++;
if(evl->v4 && (evl->v4->f & 1)) event++;
if(event>1) {
BLI_remlink(&G.edvl, evl);
freevlak(evl);
}
evl= nextvl;
}
/* om losse vertices te wissen: */
eed= G.eded.first;
while(eed) {
if( eed->v1->f & 1) eed->v1->f-=1;
if( eed->v2->f & 1) eed->v2->f-=1;
eed= eed->next;
}
eve= G.edve.first;
while(eve) {
nextve= eve->next;
if(eve->f & 1) {
BLI_remlink(&G.edve,eve);
// free(eve);
free_editvert(eve);
}
eve= nextve;
}
}
else if(event==2) delvlakflag(1);
else if(event==3) {
// if(G.edve.first) BLI_freelist(&G.edve);
if(G.edve.first) free_editverts(&G.edve);
if(G.eded.first) BLI_freelist(&G.eded);
if(G.edvl.first) freevlaklist(&G.edvl);
}
else if(event==5) {
evl= G.edvl.first;
while(evl) {
nextvl= evl->next;
if(vlakselectedAND(evl, 1)) {
BLI_remlink(&G.edvl, evl);
freevlak(evl);
}
evl= nextvl;
}
}
countall();
allqueue(REDRAWVIEW3D, 0);
makeDispList(G.obedit);
}
void add_primitiveMesh(int type)
{
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;
check_editmode(OB_MESH);
G.f &= ~(G_VERTEXPAINT+G_FACESELECT+G_TEXTUREPAINT);
setcursor_space(SPACE_VIEW3D, CURSOR_STD);
/* als geen obedit: nieuw object en in editmode gaan */
if(G.obedit==0) {
/* add_object actually returns an object ! :-)
But it also stores the added object struct in
G.scene->basact->object (BASACT->object) */
add_object(OB_MESH);
base_init_from_view3d(BASACT, G.vd);
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= G.edve.first;
while(eve) {
if(eve->f & 1) eve->f&= ~1;
eve= eve->next;
}
totoud= tot; /* onthouden en terugzetten als cube/plane */
/* imat en centrum en afmeting */
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==aantal verts 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) { /* alles behalve grid of sphere */
if(ext==0 && type!=7) d= 0;
/* de 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;
}
/* centrum 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;
/* boven en ondervlak */
if(fill) {
if(tot==4 && (type==0 || type==1)) {
v3= v1->next->next;
if(ext) v4= v2->next->next;
addvlaklist(v3, v1->next, v1, v3->next, NULL);
if(ext) addvlaklist(v2, v2->next, v4, v4->next, NULL);
}
else {
v3= v1;
v4= v2;
for(a=1; a<tot; a++) {
addvlaklist(vdown, v3, v3->next, 0, NULL);
v3= v3->next;
if(ext) {
addvlaklist(vtop, v4, v4->next, 0, NULL);
v4= v4->next;
}
}
if(type>1) {
addvlaklist(vdown, v3, v1, 0, NULL);
if(ext) addvlaklist(vtop, v4, v2, 0, NULL);
}
}
}
else if(type==4) { /* wel edges bij circle */
v3= v1;
for(a=1;a<tot;a++) {
addedgelist(v3,v3->next);
v3= v3->next;
}
addedgelist(v3,v1);
}
/* zijvlakken */
if(ext) {
v3= v1;
v4= v2;
for(a=1; a<tot; a++) {
addvlaklist(v3, v3->next, v4->next, v4, NULL);
v3= v3->next;
v4= v4->next;
}
addvlaklist(v3, v1, v2, v4, NULL);
}
else if(type==7) { /* cone */
v3= v1;
for(a=1; a<tot; a++) {
addvlaklist(vtop, v3->next, v3, 0, NULL);
v3= v3->next;
}
addvlaklist(vtop, v1, v3, 0, NULL);
}
if(type<2) tot= totoud;
}
else if(type==10) { /* grid */
/* alle flags wissen */
eve= G.edve.first;
while(eve) {
eve->f= 0;
eve= eve->next;
}
dia= G.vd->grid;
/* eerst een segment: 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);
phi+=phid;
}
/* extruden en transleren */
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];
/* alle flags wissen */
eve= G.edve.first;
while(eve) {
eve->f= 0;
eve= eve->next;
}
/* eerst een segment */
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);
phi+= phid;
}
/* extruden en roteren */
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.01);
}
else if(type==12) { /* Icosphere */
EditVert *eva[12];
/* alle flags wissen */
eve= G.edve.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[ icovlak[a][0] ];
v2= eva[ icovlak[a][1] ];
v3= eva[ icovlak[a][2] ];
addvlaklist(v1, v2, v3, 0, NULL);
}
dia*=200;
for(a=1; a<subdiv; a++) subdivideflag(2, dia, 0);
/* nu pas met imat */
eve= G.edve.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++) {
addvlaklist(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);
addvlaklist(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(REDRAWVIEW3D, 0);
allqueue(REDRAWIPO, 0);
allqueue(REDRAWHEADERS, 0);
allqueue(REDRAWINFO, 1); /* 1, want header->win==0! */
allqueue(REDRAWBUTSEDIT, 0);
makeDispList(G.obedit);
if (type==13) notice("Oooh Oooh Oooh");
}
void vertexsmooth(void)
{
struct EditVert *eve;
struct EditEdge *eed;
float *adror, *adr, fac;
float fvec[3];
int teller=0;
if(G.obedit==0) return;
/* aantal tellen */
eve= G.edve.first;
while(eve) {
if(eve->f & 1) teller++;
eve= eve->next;
}
if(teller==0) return;
adr=adror= (float *)MEM_callocN(3*sizeof(float *)*teller, "vertsmooth");
eve= G.edve.first;
while(eve) {
if(eve->f & 1) {
eve->vn= (EditVert *)adr;
eve->f1= 0;
adr+= 3;
}
eve= eve->next;
}
eed= G.eded.first;
while(eed) {
if( (eed->v1->f & 1) || (eed->v2->f & 1) ) {
fvec[0]= (eed->v1->co[0]+eed->v2->co[0])/2.0;
fvec[1]= (eed->v1->co[1]+eed->v2->co[1])/2.0;
fvec[2]= (eed->v1->co[2]+eed->v2->co[2])/2.0;
if((eed->v1->f & 1) && eed->v1->f1<255) {
eed->v1->f1++;
VecAddf((float *)eed->v1->vn, (float *)eed->v1->vn, fvec);
}
if((eed->v2->f & 1) && eed->v2->f1<255) {
eed->v2->f1++;
VecAddf((float *)eed->v2->vn, (float *)eed->v2->vn, fvec);
}
}
eed= eed->next;
}
eve= G.edve.first;
while(eve) {
if(eve->f & 1) {
if(eve->f1) {
adr= (float *)eve->vn;
fac= 0.5/(float)eve->f1;
eve->co[0]= 0.5*eve->co[0]+fac*adr[0];
eve->co[1]= 0.5*eve->co[1]+fac*adr[1];
eve->co[2]= 0.5*eve->co[2]+fac*adr[2];
}
eve->vn= 0;
}
eve= eve->next;
}
MEM_freeN(adror);
allqueue(REDRAWVIEW3D, 0);
makeDispList(G.obedit);
}
void vertexnoise(void)
{
extern float Tin;
Material *ma;
Tex *tex;
EditVert *eve;
float b2, ofs, vec[3];
if(G.obedit==0) return;
ma= give_current_material(G.obedit, G.obedit->actcol);
if(ma==0 || ma->mtex[0]==0 || ma->mtex[0]->tex==0) {
return;
}
tex= ma->mtex[0]->tex;
ofs= tex->turbul/200.0;
eve= (struct EditVert *)G.edve.first;
while(eve) {
if(eve->f & 1) {
if(tex->type==TEX_STUCCI) {
b2= BLI_hnoise(tex->noisesize, eve->co[0], eve->co[1], eve->co[2]);
if(tex->stype) ofs*=(b2*b2);
vec[0]= 0.2*(b2-BLI_hnoise(tex->noisesize, eve->co[0]+ofs, eve->co[1], eve->co[2]));
vec[1]= 0.2*(b2-BLI_hnoise(tex->noisesize, eve->co[0], eve->co[1]+ofs, eve->co[2]));
vec[2]= 0.2*(b2-BLI_hnoise(tex->noisesize, eve->co[0], eve->co[1], eve->co[2]+ofs));
VecAddf(eve->co, eve->co, vec);
}
else {
externtex(ma->mtex[0], eve->co);
eve->co[2]+= 0.05*Tin;
}
}
eve= eve->next;
}
allqueue(REDRAWVIEW3D, 0);
makeDispList(G.obedit);
}
void hide_mesh(int swap)
{
struct EditVert *eve;
struct EditEdge *eed;
if(G.obedit==0) return;
if(swap) {
eve= G.edve.first;
while(eve) {
if((eve->f & 1)==0) {
eve->xs= 3200;
eve->h= 1;
}
eve= eve->next;
}
}
else {
eve= G.edve.first;
while(eve) {
if(eve->f & 1) {
eve->f-=1;
eve->xs= 3200;
eve->h= 1;
}
eve= eve->next;
}
}
eed= G.eded.first;
while(eed) {
if(eed->v1->h || eed->v2->h) eed->h= 1;
else eed->h= 0;
eed= eed->next;
}
allqueue(REDRAWVIEW3D, 0);
makeDispList(G.obedit);
}
void reveal_mesh(void)
{
struct EditVert *eve;
struct EditEdge *eed;
if(G.obedit==0) return;
eve= G.edve.first;
while(eve) {
if(eve->h) {
eve->h= 0;
eve->f|=1;
}
eve= eve->next;
}
eed= G.eded.first;
while(eed) {
eed->h= 0;
eed= eed->next;
}
allqueue(REDRAWVIEW3D, 0);
makeDispList(G.obedit);
}
static 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;
}
/* returns vertices of two adjacent triangles forming a quad
- can be righthand or lefthand
4-----3
|\ |
| \ 2 | <- evl1
| \ |
evl-> | 1 \ |
| \|
1-----2
*/
#define VTEST(face, num, other) \
(face->v##num != other->v1 && face->v##num != other->v2 && face->v##num != other->v3)
static void givequadverts(EditVlak *evl, EditVlak *evl1, EditVert **v1, EditVert **v2, EditVert **v3, EditVert **v4, float **uv, unsigned int *col)
{
if VTEST(evl, 1, evl1) {
//if(evl->v1!=evl1->v1 && evl->v1!=evl1->v2 && evl->v1!=evl1->v3) {
*v1= evl->v1;
*v2= evl->v2;
uv[0] = evl->uv[0];
uv[1] = evl->uv[1];
col[0] = evl->col[0];
col[1] = evl->col[1];
}
else if VTEST(evl, 2, evl1) {
//else if(evl->v2!=evl1->v1 && evl->v2!=evl1->v2 && evl->v2!=evl1->v3) {
*v1= evl->v2;
*v2= evl->v3;
uv[0] = evl->uv[1];
uv[1] = evl->uv[2];
col[0] = evl->col[1];
col[1] = evl->col[2];
}
else if VTEST(evl, 3, evl1) {
// else if(evl->v3!=evl1->v1 && evl->v3!=evl1->v2 && evl->v3!=evl1->v3) {
*v1= evl->v3;
*v2= evl->v1;
uv[0] = evl->uv[2];
uv[1] = evl->uv[0];
col[0] = evl->col[2];
col[1] = evl->col[0];
}
if VTEST(evl1, 1, evl) {
// if(evl1->v1!=evl->v1 && evl1->v1!=evl->v2 && evl1->v1!=evl->v3) {
*v3= evl1->v1;
uv[2] = evl1->uv[0];
col[2] = evl1->col[0];
*v4= evl1->v2;
uv[3] = evl1->uv[1];
col[3] = evl1->col[1];
/*
if(evl1->v2== *v2) {
*v4= evl1->v3;
uv[3] = evl1->uv[2];
} else {
*v4= evl1->v2;
uv[3] = evl1->uv[1];
}
*/
}
else if VTEST(evl1, 2, evl) {
// else if(evl1->v2!=evl->v1 && evl1->v2!=evl->v2 && evl1->v2!=evl->v3) {
*v3= evl1->v2;
uv[2] = evl1->uv[1];
col[2] = evl1->col[1];
*v4= evl1->v3;
uv[3] = evl1->uv[2];
col[3] = evl1->col[2];
/*
if(evl1->v3== *v2) {
*v4= evl1->v1;
uv[3] = evl1->uv[0];
} else {
*v4= evl1->v3;
uv[3] = evl1->uv[2];
}
*/
}
else if VTEST(evl1, 3, evl) {
// else if(evl1->v3!=evl->v1 && evl1->v3!=evl->v2 && evl1->v3!=evl->v3) {
*v3= evl1->v3;
uv[2] = evl1->uv[2];
col[2] = evl1->col[2];
*v4= evl1->v1;
uv[3] = evl1->uv[0];
col[3] = evl1->col[0];
/*
if(evl1->v1== *v2) {
*v4= evl1->v2;
uv[3] = evl1->uv[3];
} else {
*v4= evl1->v1;
uv[3] = evl1->uv[0];
}
*/
}
else {
pupmenu("Wanna crash?%t|Yes Please!%x1");
return;
}
}
/* ook weer twee zeer vreemde 'patch' functies om de uv van tfaces te bewaren */
/*
static float *set_correct_uv(EditVert *eve, EditVlak **evla)
{
if(eve== evla[1]->v3) return evla[1]->uv[2];
if(eve== evla[0]->v3) return evla[0]->uv[2];
if(eve== evla[1]->v2) return evla[1]->uv[1];
if(eve== evla[0]->v2) return evla[0]->uv[1];
if(eve== evla[1]->v1) return evla[1]->uv[0];
if(eve== evla[0]->v1) return evla[0]->uv[0];
return 0;
}
crazy code commented out..
static void restore_wuv(EditVlak *evl, void **evla)
{
int *lp;
lp= (int *)set_correct_uv(evl->v1, (EditVlak **)evla);
((int *)(evl->uv[0]))[0]= lp[0];
((int *)(evl->uv[0]))[4]= lp[4];
lp= (int *)set_correct_uv(evl->v2, (EditVlak **)evla);
((int *)(evl->uv[1]))[0]= lp[0];
((int *)(evl->uv[1]))[4]= lp[4];
lp= (int *)set_correct_uv(evl->v3, (EditVlak **)evla);
((int *)(evl->uv[2]))[0]= lp[0];
((int *)(evl->uv[2]))[4]= lp[4];
}
*/
/* Helper functions for edge/quad edit features*/
/*
*/
static void untag_edges(EditVlak *f)
{
f->e1->f = 0;
f->e2->f = 0;
if (f->e3) f->e3->f = 0;
if (f->e4) f->e4->f = 0;
}
#if 0
static void mark_clear_edges(EditVlak *f)
{
f->e1->f1 = 1;
f->e2->f1 = 1;
if (f->e3) f->e3->f1 = 1;
if (f->e4) f->e4->f1 = 1;
}
#endif
static int count_edges(EditEdge *ed)
{
int totedge = 0;
while(ed) {
ed->vn= 0;
if( (ed->v1->f & 1) && (ed->v2->f & 1) ) totedge++;
ed= ed->next;
}
return totedge;
}
/** remove and free list of tagged edges */
static void free_tagged_edgelist(EditEdge *eed)
{
EditEdge *nexted;
while(eed) {
nexted= eed->next;
if(eed->f1) {
remedge(eed);
free(eed);
}
eed= nexted;
}
}
/** remove and free list of tagged faces */
static void free_tagged_facelist(EditVlak *evl)
{
EditVlak *nextvl;
while(evl) {
nextvl= evl->next;
if(evl->f1) {
BLI_remlink(&G.edvl, evl);
freevlak(evl);
}
evl= nextvl;
}
}
typedef EditVlak *EVPtr;
typedef EVPtr EVPTuple[2];
/** builds EVPTuple array evla of face tuples (in fact pointers to EditVlaks)
sharing one edge.
arguments: selected edge list, face list.
Edges will also be tagged accordingly (see eed->f) */
static int collect_quadedges(EVPTuple *evla, EditEdge *eed, EditVlak *evl)
{
int i = 0;
EditEdge *e1, *e2, *e3;
EVPtr *evp;
/* run through edges, if selected, set pointer edge-> facearray */
while(eed) {
eed->f= 0;
eed->f1= 0;
if( (eed->v1->f & 1) && (eed->v2->f & 1) ) {
eed->vn= (EditVert *) (&evla[i]);
i++;
}
eed= eed->next;
}
/* find edges pointing to 2 faces by procedure:
- run through faces and their edges, increase
face counter e->f for each face
*/
while(evl) {
evl->f1= 0;
if(evl->v4==0) { /* if triangle */
if(vlakselectedAND(evl, 1)) {
e1= evl->e1;
e2= evl->e2;
e3= evl->e3;
if(e1->f<3) {
if(e1->f<2) {
evp= (EVPtr *) e1->vn;
evp[(int)e1->f]= evl;
}
e1->f+= 1;
}
if(e2->f<3) {
if(e2->f<2) {
evp= (EVPtr *) e2->vn;
evp[(int)e2->f]= evl;
}
e2->f+= 1;
}
if(e3->f<3) {
if(e3->f<2) {
evp= (EVPtr *) e3->vn;
evp[(int)e3->f]= evl;
}
e3->f+= 1;
}
}
}
evl= evl->next;
}
return i;
}
void join_triangles(void)
{
EditVert *v1, *v2, *v3, *v4;
EditVlak *evl, *w;
EVPTuple *evlar;
EVPtr *evla;
EditEdge *eed, *nexted;
int totedge, ok;
float *uv[4];
unsigned int col[4];
totedge = count_edges(G.eded.first);
if(totedge==0) return;
evlar= (EVPTuple *) MEM_callocN(totedge * sizeof(EVPTuple), "jointris");
ok = collect_quadedges(evlar, G.eded.first, G.edvl.first);
if (G.f & G_DEBUG) {
printf("edges selected: %d\n", ok);
}
eed= G.eded.first;
while(eed) {
nexted= eed->next;
if(eed->f==2) { /* points to 2 faces */
evla= (EVPtr *) eed->vn;
/* don't do it if flagged */
ok= 1;
evl= evla[0];
if(evl->e1->f1 || evl->e2->f1 || evl->e3->f1) ok= 0;
evl= evla[1];
if(evl->e1->f1 || evl->e2->f1 || evl->e3->f1) ok= 0;
if(ok) {
/* test convex */
givequadverts(evla[0], evla[1], &v1, &v2, &v3, &v4, uv, col);
/*
4-----3 4-----3
|\ | | |
| \ 1 | | |
| \ | -> | |
| 0 \ | | |
| \| | |
1-----2 1-----2
*/
/* make new faces */
if( convex(v1->co, v2->co, v3->co, v4->co) > 0.01) {
if(exist_vlak(v1, v2, v3, v4)==0) {
w = addvlaklist(v1, v2, v3, v4, evla[0]);
untag_edges(w);
if (w->tface) {
UVCOPY(w->uv[0], uv[0]);
UVCOPY(w->uv[1], uv[1]);
UVCOPY(w->uv[2], uv[2]);
UVCOPY(w->uv[3], uv[3]);
}
memcpy(w->col, col, sizeof(w->col));
}
/* tag as to-be-removed */
FACE_MARKCLEAR(evla[0]);
FACE_MARKCLEAR(evla[1]);
eed->f1 = 1;
} /* endif test convex */
}
}
eed= nexted;
}
free_tagged_edgelist(G.eded.first);
free_tagged_facelist(G.edvl.first);
MEM_freeN(evlar);
allqueue(REDRAWVIEW3D, 0);
makeDispList(G.obedit);
}
/* quick hack, basically a copy of beauty_fill */
void edge_flip(void)
{
EditVert *v1, *v2, *v3, *v4;
EditEdge *eed, *nexted;
EditVlak *evl, *w;
//void **evlar, **evla;
EVPTuple *evlar;
EVPtr *evla;
float *uv[4];
unsigned int col[4];
int totedge, ok;
/* - alle geselecteerde edges met 2 vlakken
* - vind die vlakken: opslaan in edges (extra datablok)
* - per edge: - test convex
* - test edge: flip?
- zoja: remedge, addedge, alle randedges nieuwe vlakpointers
*/
totedge = count_edges(G.eded.first);
if(totedge==0) return;
/* temporary array for : edge -> face[1], face[2] */
evlar= (EVPTuple *) MEM_callocN(totedge * sizeof(EVPTuple), "edgeflip");
ok = collect_quadedges(evlar, G.eded.first, G.edvl.first);
eed= G.eded.first;
while(eed) {
nexted= eed->next;
if(eed->f==2) { /* points to 2 faces */
evla= (EVPtr *) eed->vn;
/* don't do it if flagged */
ok= 1;
evl= evla[0];
if(evl->e1->f1 || evl->e2->f1 || evl->e3->f1) ok= 0;
evl= evla[1];
if(evl->e1->f1 || evl->e2->f1 || evl->e3->f1) ok= 0;
if(ok) {
/* test convex */
givequadverts(evla[0], evla[1], &v1, &v2, &v3, &v4, uv, col);
/*
4-----3 4-----3
|\ | | /|
| \ 1 | | 1 / |
| \ | -> | / |
| 0 \ | | / 0 |
| \| |/ |
1-----2 1-----2
*/
/* make new faces */
if (v1 && v2 && v3){
if( convex(v1->co, v2->co, v3->co, v4->co) > 0.01) {
if(exist_vlak(v1, v2, v3, v4)==0) {
w = addvlaklist(v1, v2, v3, 0, evla[1]);
untag_edges(w);
if (w->tface) {
UVCOPY(w->uv[0], uv[0]);
UVCOPY(w->uv[1], uv[1]);
UVCOPY(w->uv[2], uv[2]);
}
w->col[0] = col[0]; w->col[1] = col[1]; w->col[2] = col[2];
w = addvlaklist(v1, v3, v4, 0, evla[1]);
untag_edges(w);
if (w->tface) {
UVCOPY(w->uv[0], uv[0]);
UVCOPY(w->uv[1], uv[2]);
UVCOPY(w->uv[2], uv[3]);
}
w->col[0] = col[0]; w->col[1] = col[2]; w->col[2] = col[3];
/* erase old faces and edge */
}
/* tag as to-be-removed */
FACE_MARKCLEAR(evla[1]);
FACE_MARKCLEAR(evla[0]);
eed->f1 = 1;
} /* endif test convex */
}
}
}
eed= nexted;
}
/* clear tagged edges and faces: */
free_tagged_edgelist(G.eded.first);
free_tagged_facelist(G.edvl.first);
MEM_freeN(evlar);
allqueue(REDRAWVIEW3D, 0);
makeDispList(G.obedit);
}
void beauty_fill(void)
{
EditVert *v1, *v2, *v3, *v4;
EditEdge *eed, *nexted;
EditEdge dia1, dia2;
EditVlak *evl, *w;
// void **evlar, **evla;
EVPTuple *evlar;
EVPtr *evla;
float *uv[4];
unsigned int col[4];
float len1, len2, len3, len4, len5, len6, opp1, opp2, fac1, fac2;
int totedge, ok, notbeauty=8, onedone;
/* - alle geselecteerde edges met 2 vlakken
* - vind die vlakken: opslaan in edges (extra datablok)
* - per edge: - test convex
* - test edge: flip?
- zoja: remedge, addedge, alle randedges nieuwe vlakpointers
*/
totedge = count_edges(G.eded.first);
if(totedge==0) return;
if(okee("Beauty Fill")==0) return;
/* tempblok met vlakpointers */
evlar= (EVPTuple *) MEM_callocN(totedge * sizeof(EVPTuple), "beautyfill");
while (notbeauty) {
notbeauty--;
ok = collect_quadedges(evlar, G.eded.first, G.edvl.first);
/* gaatie */
onedone= 0;
eed= G.eded.first;
while(eed) {
nexted= eed->next;
if(eed->f==2) {
evla = (EVPtr *) eed->vn;
/* geen van de vlakken mag al gedaan zijn */
ok= 1;
evl= evla[0];
if(evl->e1->f1 || evl->e2->f1 || evl->e3->f1) ok= 0;
evl= evla[1];
if(evl->e1->f1 || evl->e2->f1 || evl->e3->f1) ok= 0;
if(ok) {
/* test convex */
givequadverts(evla[0], evla[1], &v1, &v2, &v3, &v4, uv, col);
if( convex(v1->co, v2->co, v3->co, v4->co) > -0.5) {
/* test edges */
if( ((long)v1) > ((long)v3) ) {
dia1.v1= v3;
dia1.v2= v1;
}
else {
dia1.v1= v1;
dia1.v2= v3;
}
if( ((long)v2) > ((long)v4) ) {
dia2.v1= v4;
dia2.v2= v2;
}
else {
dia2.v1= v2;
dia2.v2= v4;
}
/* testregel:
* de oppervlakte gedeeld door de totale edgelengte
*
*/
len1= VecLenf(v1->co, v2->co);
len2= VecLenf(v2->co, v3->co);
len3= VecLenf(v3->co, v4->co);
len4= VecLenf(v4->co, v1->co);
len5= VecLenf(v1->co, v3->co);
len6= VecLenf(v2->co, v4->co);
opp1= AreaT3Dfl(v1->co, v2->co, v3->co);
opp2= AreaT3Dfl(v1->co, v3->co, v4->co);
fac1= opp1/(len1+len2+len5) + opp2/(len3+len4+len5);
opp1= AreaT3Dfl(v2->co, v3->co, v4->co);
opp2= AreaT3Dfl(v2->co, v4->co, v1->co);
fac2= opp1/(len2+len3+len6) + opp2/(len4+len1+len6);
ok= 0;
if(fac1 > fac2) {
if(dia2.v1==eed->v1 && dia2.v2==eed->v2) {
eed->f1= 1;
evl= evla[0];
evl->f1= 1;
evl= evla[1];
evl->f1= 1;
w= addvlaklist(v1, v2, v3, 0, evl);
if (w->tface) {
UVCOPY(w->uv[0], uv[0]);
UVCOPY(w->uv[1], uv[1]);
UVCOPY(w->uv[2], uv[2]);
}
w->col[0] = col[0]; w->col[1] = col[1]; w->col[2] = col[2];
w= addvlaklist(v1, v3, v4, 0, evl);
if (w->tface) {
UVCOPY(w->uv[0], uv[0]);
UVCOPY(w->uv[1], uv[2]);
UVCOPY(w->uv[2], uv[3]);
}
w->col[0] = col[0]; w->col[1] = col[2]; w->col[2] = col[3];
onedone= 1;
}
}
else if(fac1 < fac2) {
if(dia1.v1==eed->v1 && dia1.v2==eed->v2) {
eed->f1= 1;
evl= evla[0];
evl->f1= 1;
evl= evla[1];
evl->f1= 1;
w= addvlaklist(v2, v3, v4, 0, evl);
if (w->tface) {
UVCOPY(w->uv[0], uv[1]);
UVCOPY(w->uv[1], uv[3]);
UVCOPY(w->uv[2], uv[4]);
}
w= addvlaklist(v1, v2, v4, 0, evl);
if (w->tface) {
UVCOPY(w->uv[0], uv[0]);
UVCOPY(w->uv[1], uv[1]);
UVCOPY(w->uv[2], uv[3]);
}
onedone= 1;
}
}
}
}
}
eed= nexted;
}
free_tagged_edgelist(G.eded.first);
free_tagged_facelist(G.edvl.first);
if(onedone==0) break;
}
MEM_freeN(evlar);
allqueue(REDRAWVIEW3D, 0);
makeDispList(G.obedit);
}
/** 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;
MFace *mface = NULL, *mfacemain;
TFace *tface = NULL, *tfacemain;
unsigned int *mcol=NULL, *mcolmain;
float imat[4][4], cmat[4][4];
int a, b, totcol, totvert=0, totface=0, ok=0, vertofs, map[MAXMAT];
#ifdef __NLA
int i, j, index;
bDeformGroup *dg, *odg;
MDeformVert *dvert, *dvertmain;
#endif
if(G.obedit) return;
ob= OBACT;
if(!ob || ob->type!=OB_MESH) return;
/* tellen */
base= FIRSTBASE;
while(base) {
if TESTBASE(base) {
if(base->object->type==OB_MESH) {
me= base->object->data;
totvert+= me->totvert;
totface+= me->totface;
if(base->object == ob) ok= 1;
}
}
base= base->next;
}
/* zodoende is het aktieve object altijd select */
if(ok==0) return;
if(totvert==0 || totvert>65000) return;
if(okee("Join selected Meshes")==0) return;
/* nieuwe materiaal indexen en hoofdarray */
matar= MEM_callocN(sizeof(void *)*MAXMAT, "join_mesh");
totcol= ob->totcol;
/* obact materials in nieuw hoofdarray, is mooiere start! */
for(a=1; a<=ob->totcol; a++) {
matar[a-1]= give_current_material(ob, a);
id_us_plus((ID *)matar[a-1]);
/* id->us ophogen: wordt ook verlaagd */
}
base= FIRSTBASE;
while(base) {
if TESTBASE(base) {
if(ob!=base->object && base->object->type==OB_MESH) {
me= base->object->data;
#ifdef __NLA
// 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;
#endif
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), "joinmesh1");
if (totface) mface= mfacemain= MEM_mallocN(totface*sizeof(MFace), "joinmesh2");
else mfacemain= 0;
if(me->mcol) mcol= mcolmain= MEM_callocN(totface*4*sizeof(int), "joinmesh3");
else mcolmain= 0;
/* 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= 0;
#ifdef __NLA
if(me->dvert)
dvert= dvertmain= MEM_callocN(totvert*sizeof(MDeformVert), "joinmesh5");
else dvert=dvertmain= NULL;
#endif
vertofs= 0;
/* alle geselecteerde meshes invers transformen in obact */
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));
#ifdef __NLA
copy_dverts(dvert, me->dvert, me->totvert);
/* >>>>> FIXME: Ensure that deformation groups are updated correctly */
/* OLD VERSION */
/*
for (i=0; i<me->totvert; i++){
for (j=0; j<mvert[i].totweight; j++){
// Find the old vertex group
odg = BLI_findlink (&base->object->defbase, mvert[i].dw[j].def_nr);
// 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)){
mvert[i].dw[j].def_nr = index;
break;
}
}
}
}
*/
/* 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);
// 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;
}
#endif
if(base->object != ob) {
/* let op: matmul omkeren is ECHT fout */
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) {
/* mapping maken voor materialen */
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;
}
}
vertofs+= me->totvert;
if(base->object!=ob) {
free_and_unlink_base(base);
}
}
}
base= nextb;
}
me= ob->data;
if(me->mface) MEM_freeN(me->mface);
me->mface= mfacemain;
if(me->mvert) MEM_freeN(me->mvert);
#ifdef __NLA
if(me->dvert) free_dverts(me->dvert, me->totvert);
me->dvert = dvertmain;
#endif
me->mvert= mvertmain;
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->totface= totface;
/* oude 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;
/* andere mesh gebruikers */
test_object_materials((ID *)me);
enter_editmode();
exit_editmode(1);
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWBUTSMAT, 0);
makeDispList(G.obedit);
}
void clever_numbuts_mesh(void)
{
EditVert *eve;
eve= G.edve.first;
while(eve) {
if(eve->f & 1) break;
eve= eve->next;
}
if(eve==0) return;
add_numbut(0, NUM|FLO, "LocX:", -G.vd->far, G.vd->far, eve->co, 0);
add_numbut(1, NUM|FLO, "LocY:", -G.vd->far, G.vd->far, eve->co+1, 0);
add_numbut(2, NUM|FLO, "LocZ:", -G.vd->far, G.vd->far, eve->co+2, 0);
do_clever_numbuts("Active Vertex", 3, REDRAW);
}
/* never used, see CVS */
/* static void insert_radiogour(char *str) */
static void permutate(void *list, int num, int size, int *index)
{
void *buf;
int len;
int i;
len = num * size;
buf = malloc(len);
memcpy(buf, list, len);
for (i = 0; i < num; i++) {
memcpy((char *)list + (i * size), (char *)buf + (index[i] * size), size);
}
free(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")==0) return;
me= ob->data;
if(me->totface==0) return;
/* create index list */
index = (int *) malloc(sizeof(int) * me->totface);
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);
free(index);
allqueue(REDRAWVIEW3D, 0);
makeDispList(G.obedit);
}
void vertices_to_sphere(void)
{
EditVert *eve;
Object *ob= OBACT;
float *curs, len, vec[3], cent[3], fac, facm, imat[3][3], bmat[3][3];
int tot;
short perc=100;
if(ob==0) return;
TEST_EDITMESH
if(button(&perc, 1, 100, "Percentage:")==0) return;
fac= perc/100.0;
facm= 1.0-fac;
Mat3CpyMat4(bmat, ob->obmat);
Mat3Inv(imat, bmat);
/* centrum */
curs= give_cursor();
cent[0]= curs[0]-ob->obmat[3][0];
cent[1]= curs[1]-ob->obmat[3][1];
cent[2]= curs[2]-ob->obmat[3][2];
Mat3MulVecfl(imat, cent);
len= 0.0;
tot= 0;
eve= G.edve.first;
while(eve) {
if(eve->f & 1) {
tot++;
len+= VecLenf(cent, eve->co);
}
eve= eve->next;
}
len/=tot;
if(len==0.0) len= 10.0;
eve= G.edve.first;
while(eve) {
if(eve->f & 1) {
vec[0]= eve->co[0]-cent[0];
vec[1]= eve->co[1]-cent[1];
vec[2]= eve->co[2]-cent[2];
Normalise(vec);
eve->co[0]= fac*(cent[0]+vec[0]*len) + facm*eve->co[0];
eve->co[1]= fac*(cent[1]+vec[1]*len) + facm*eve->co[1];
eve->co[2]= fac*(cent[2]+vec[2]*len) + facm*eve->co[2];
}
eve= eve->next;
}
allqueue(REDRAWVIEW3D, 0);
makeDispList(G.obedit);
}
/* Got this from scanfill.c. You will need to juggle around the
* callbacks for the scanfill.c code a bit for this to work. */
void fill_mesh(void)
{
EditVert *eve,*v1;
EditEdge *eed,*e1,*nexted;
EditVlak *evl,*nextvl;
short ok;
if(G.obedit==0 || (G.obedit->type!=OB_MESH)) return;
waitcursor(1);
/* alle selected vertices kopieeren */
eve= G.edve.first;
while(eve) {
if(eve->f & 1) {
v1= BLI_addfillvert(eve->co);
eve->vn= v1;
v1->vn= eve;
v1->h= 0;
}
eve= eve->next;
}
/* alle selected edges kopieeren */
eed= G.eded.first;
while(eed) {
if( (eed->v1->f & 1) && (eed->v2->f & 1) ) {
e1= BLI_addfilledge(eed->v1->vn, eed->v2->vn);
e1->v1->h++;
e1->v2->h++;
}
eed= eed->next;
}
/* van alle selected vlakken vertices en edges verwijderen om dubbels te voorkomen */
/* alle edges tellen punten op, vlakken trekken af,
edges met vertices ->h<2 verwijderen */
evl= G.edvl.first;
ok= 0;
while(evl) {
nextvl= evl->next;
if( vlakselectedAND(evl, 1) ) {
evl->v1->vn->h--;
evl->v2->vn->h--;
evl->v3->vn->h--;
if(evl->v4) evl->v4->vn->h--;
ok= 1;
}
evl= nextvl;
}
if(ok) { /* er zijn vlakken geselecteerd */
eed= filledgebase.first;
while(eed) {
nexted= eed->next;
if(eed->v1->h<2 || eed->v2->h<2) {
BLI_remlink(&filledgebase,eed);
}
eed= nexted;
}
}
/* tijd=clock(); */
/* to make edgefill work */
BLI_setScanFillObjectRef(G.obedit);
BLI_setScanFillColourRef(&G.obedit->actcol);
ok= BLI_edgefill(0);
/* printf("time: %d\n",(clock()-tijd)/1000); */
if(ok) {
evl= fillvlakbase.first;
while(evl) {
addvlaklist(evl->v1->vn, evl->v2->vn, evl->v3->vn, 0, evl);
evl= evl->next;
}
}
/* else printf("fill error\n"); */
BLI_end_edgefill();
waitcursor(0);
countall();
allqueue(REDRAWVIEW3D, 0);
makeDispList(G.obedit);
}
/* ***************** */
/* 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.
*/
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; /* grote hoeken */
if(me->totface==0) {
/* namaak puno's voor halopuno! */
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");
/* berekenen cos hoeken en oppervlakte en optellen bij puno */
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];
}
}
/* normaliseren puntnormalen */
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];
}
}
/* puntnormaal omklap-vlaggen voor bij shade */
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 voor 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);
}
/***/
static int editmesh_nfaces_selected(void)
{
EditVlak *evl;
int count= 0;
for (evl= G.edvl.first; evl; evl= evl->next)
if (vlakselectedAND(evl, SELECT))
count++;
return count;
}
static int editmesh_nvertices_selected(void)
{
EditVert *eve;
int count= 0;
for (eve= G.edve.first; eve; eve= eve->next)
if (eve->f & SELECT)
count++;
return count;
}
static void editmesh_calc_selvert_center(float cent_r[3])
{
EditVert *eve;
int nsel= 0;
cent_r[0]= cent_r[1]= cent_r[0]= 0.0;
for (eve= G.edve.first; eve; eve= eve->next) {
if (eve->f & SELECT) {
cent_r[0]+= eve->co[0];
cent_r[1]+= eve->co[1];
cent_r[2]+= eve->co[2];
nsel++;
}
}
if (nsel) {
cent_r[0]/= nsel;
cent_r[1]/= nsel;
cent_r[2]/= nsel;
}
}
static int tface_is_selected(TFace *tf)
{
return (!(tf->flag & TF_HIDE) && (tf->flag & TF_SELECT));
}
static int faceselect_nfaces_selected(Mesh *me)
{
int i, count= 0;
for (i=0; i<me->totface; i++) {
MFace *mf= ((MFace*) me->mface) + i;
TFace *tf= ((TFace*) me->tface) + i;
if (mf->v3 && tface_is_selected(tf))
count++;
}
return count;
}
/* XXX, code for both these functions should be abstract,
* then unified, then written for other things (like objects,
* which would use same as vertices method), then added
* to interface! Hoera! - zr
*/
void faceselect_align_view_to_selected(View3D *v3d, Mesh *me, int axis)
{
if (!faceselect_nfaces_selected(me)) {
error("No faces selected.");
} else {
float norm[3];
int i;
norm[0]= norm[1]= norm[2]= 0.0;
for (i=0; i<me->totface; i++) {
MFace *mf= ((MFace*) me->mface) + i;
TFace *tf= ((TFace*) me->tface) + i;
if (mf->v3 && tface_is_selected(tf)) {
float *v1, *v2, *v3, fno[3];
v1= me->mvert[mf->v1].co;
v2= me->mvert[mf->v2].co;
v3= me->mvert[mf->v3].co;
if (mf->v4) {
float *v4= me->mvert[mf->v4].co;
CalcNormFloat4(v1, v2, v3, v4, fno);
} else {
CalcNormFloat(v1, v2, v3, fno);
}
norm[0]+= fno[0];
norm[1]+= fno[1];
norm[2]+= fno[2];
}
}
view3d_align_axis_to_vector(v3d, axis, norm);
}
}
void editmesh_align_view_to_selected(View3D *v3d, int axis)
{
int nselverts= editmesh_nvertices_selected();
if (nselverts<3) {
if (nselverts==0) {
error("No faces or vertices selected.");
} else {
error("At least one face or three vertices must be selected.");
}
} else if (editmesh_nfaces_selected()) {
float norm[3];
EditVlak *evl;
norm[0]= norm[1]= norm[2]= 0.0;
for (evl= G.edvl.first; evl; evl= evl->next) {
if (vlakselectedAND(evl, SELECT)) {
float fno[3];
if (evl->v4) CalcNormFloat4(evl->v1->co, evl->v2->co, evl->v3->co, evl->v4->co, fno);
else CalcNormFloat(evl->v1->co, evl->v2->co, evl->v3->co, fno);
/* XXX, fixme, should be flipped intp a
* consistent direction. -zr
*/
norm[0]+= fno[0];
norm[1]+= fno[1];
norm[2]+= fno[2];
}
}
view3d_align_axis_to_vector(v3d, axis, norm);
} else {
float cent[3], norm[3];
EditVert *eve, *leve= NULL;
norm[0]= norm[1]= norm[2]= 0.0;
editmesh_calc_selvert_center(cent);
for (eve= G.edve.first; eve; eve= eve->next) {
if (eve->f & SELECT) {
if (leve) {
float tno[3];
CalcNormFloat(cent, leve->co, eve->co, tno);
/* XXX, fixme, should be flipped intp a
* consistent direction. -zr
*/
norm[0]+= tno[0];
norm[1]+= tno[1];
norm[2]+= tno[2];
}
leve= eve;
}
}
view3d_align_axis_to_vector(v3d, axis, norm);
}
}