~ubuntu-branches/ubuntu/gutsy/blender/gutsy-security

« back to all changes in this revision

Viewing changes to source/blender/src/meshtools.c

  • Committer: Bazaar Package Importer
  • Author(s): Florian Ernst
  • Date: 2005-11-06 12:40:03 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051106124003-3pgs7tcg5rox96xg
Tags: 2.37a-1.1
* Non-maintainer upload.
* Split out parts of 01_SConstruct_debian.dpatch again: root_build_dir
  really needs to get adjusted before the clean target runs - closes: #333958,
  see #288882 for reference

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * $Id: 
 
3
 *
 
4
 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU General Public License
 
8
 * as published by the Free Software Foundation; either version 2
 
9
 * of the License, or (at your option) any later version. The Blender
 
10
 * Foundation also sells licenses for use in proprietary software under
 
11
 * the Blender License.  See http://www.blender.org/BL/ for information
 
12
 * about this.
 
13
 *
 
14
 * This program is distributed in the hope that it will be useful,
 
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
 * GNU General Public License for more details.
 
18
 *
 
19
 * You should have received a copy of the GNU General Public License
 
20
 * along with this program; if not, write to the Free Software Foundation,
 
21
 * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
22
 *
 
23
 * The Original Code is Copyright (C) 2004 by NaN Holding BV.
 
24
 * All rights reserved.
 
25
 *
 
26
 * The Original Code is: all of this file.
 
27
 *
 
28
 * Contributor(s): none yet.
 
29
 *
 
30
 * ***** END GPL/BL DUAL LICENSE BLOCK *****
 
31
 */
 
32
 
 
33
/*
 
34
 
 
35
meshtools.c: no editmode, tools operating on meshes
 
36
 
 
37
void join_mesh(void);
 
38
 
 
39
void fasterdraw(void);
 
40
void slowerdraw(void);
 
41
 
 
42
void vertexnormals_mesh(Mesh *me, float *extverts);
 
43
void sort_faces(void);
 
44
 
 
45
*/
 
46
 
 
47
#include <stdlib.h>
 
48
#include <string.h>
 
49
#include <math.h>
 
50
 
 
51
#ifdef HAVE_CONFIG_H
 
52
#include <config.h>
 
53
#endif
 
54
 
 
55
#include "MEM_guardedalloc.h"
 
56
 
 
57
#include "DNA_mesh_types.h"
 
58
#include "DNA_meshdata_types.h"
 
59
#include "DNA_object_types.h"
 
60
#include "DNA_material_types.h"
 
61
#include "DNA_scene_types.h"
 
62
#include "DNA_screen_types.h"
 
63
#include "DNA_view3d_types.h"
 
64
 
 
65
#include "BLI_blenlib.h"
 
66
#include "BLI_arithb.h"
 
67
 
 
68
#include "BKE_displist.h"
 
69
#include "BKE_global.h"
 
70
#include "BKE_library.h"
 
71
#include "BKE_main.h"
 
72
#include "BKE_mesh.h"
 
73
#include "BKE_material.h"
 
74
#include "BKE_object.h"
 
75
#include "BKE_utildefines.h"
 
76
 
 
77
#include "BIF_editmesh.h"
 
78
#include "BIF_graphics.h"
 
79
#include "BIF_mywindow.h"
 
80
#include "BIF_screen.h"
 
81
#include "BIF_space.h"
 
82
#include "BIF_toolbox.h"
 
83
#include "BIF_editconstraint.h"
 
84
 
 
85
#include "BDR_editobject.h" 
 
86
#include "BDR_editface.h" 
 
87
 
 
88
#include "mydevice.h"
 
89
#include "blendef.h"
 
90
 
 
91
#include "BIF_meshtools.h" /* include ourself for prototypes */
 
92
 
 
93
 
 
94
/* * ********************** no editmode!!! *********** */
 
95
 
 
96
 
 
97
/** tests whether selected mesh objects have tfaces */
 
98
static int testSelected_TfaceMesh(void)
 
99
{
 
100
        Base *base;
 
101
        Mesh *me;
 
102
 
 
103
        base = FIRSTBASE;
 
104
        while (base) {
 
105
                if TESTBASE(base) {
 
106
                        if(base->object->type==OB_MESH) {
 
107
                                me= base->object->data;
 
108
                                if (me->tface) 
 
109
                                        return 1;
 
110
                        }               
 
111
                }                       
 
112
                base= base->next;
 
113
        }       
 
114
        return 0;
 
115
}       
 
116
 
 
117
void join_mesh(void)
 
118
{
 
119
        Base *base, *nextb;
 
120
        Object *ob;
 
121
        Material **matar, *ma;
 
122
        Mesh *me;
 
123
        MVert *mvert, *mvertmain;
 
124
        MEdge *medge = NULL, *medgemain;
 
125
        MFace *mface = NULL, *mfacemain;
 
126
        TFace *tface = NULL, *tfacemain;
 
127
        unsigned int *mcol=NULL, *mcolmain;
 
128
        float imat[4][4], cmat[4][4];
 
129
        int a, b, totcol, totedge=0, totvert=0, totface=0, ok=0, vertofs, map[MAXMAT];
 
130
        int hasedges=0;
 
131
        int     i, j, index, haskey=0, hasdefgroup=0;
 
132
        bDeformGroup *dg, *odg;
 
133
        MDeformVert *dvert, *dvertmain;
 
134
        
 
135
        if(G.obedit) return;
 
136
        
 
137
        ob= OBACT;
 
138
        if(!ob || ob->type!=OB_MESH) return;
 
139
        
 
140
        /* count */
 
141
        base= FIRSTBASE;
 
142
        while(base) {
 
143
                if TESTBASELIB(base) {
 
144
                        if(base->object->type==OB_MESH) {
 
145
                                me= base->object->data;
 
146
                                totvert+= me->totvert;
 
147
                                totface+= me->totface;
 
148
                                if(me->medge) hasedges= 1;
 
149
 
 
150
                                if(base->object == ob) ok= 1;
 
151
 
 
152
                                if(me->key) {
 
153
                                        haskey= 1;
 
154
                                        break;
 
155
                                }
 
156
                        }
 
157
                }
 
158
                base= base->next;
 
159
        }
 
160
        
 
161
        if(haskey) {
 
162
                error("Can't join meshes with vertex keys");
 
163
                return;
 
164
        }
 
165
        /* that way the active object is always selected */ 
 
166
        if(ok==0) return;
 
167
        
 
168
        if(totvert==0 || totvert>MESH_MAX_VERTS) return;
 
169
        
 
170
        if(okee("Join selected meshes")==0) return;
 
171
 
 
172
 
 
173
        /* if needed add edges to other meshes */
 
174
        if(hasedges) {
 
175
                for(base= FIRSTBASE; base; base= base->next) {
 
176
                        if TESTBASELIB(base) {
 
177
                                if(base->object->type==OB_MESH) {
 
178
                                        me= base->object->data;
 
179
                                        if(me->medge==NULL) make_edges(me);
 
180
                                        totedge += me->totedge;
 
181
                                }
 
182
                        }
 
183
                }
 
184
        }
 
185
        
 
186
        /* new material indices and material array */
 
187
        matar= MEM_callocN(sizeof(void *)*MAXMAT, "join_mesh");
 
188
        totcol= ob->totcol;
 
189
        
 
190
        /* obact materials in new main array, is nicer start! */
 
191
        for(a=1; a<=ob->totcol; a++) {
 
192
                matar[a-1]= give_current_material(ob, a);
 
193
                id_us_plus((ID *)matar[a-1]);
 
194
                /* increase id->us : will be lowered later */
 
195
        }
 
196
        
 
197
        base= FIRSTBASE;
 
198
        while(base) {
 
199
                if TESTBASELIB(base) {
 
200
                        if(ob!=base->object && base->object->type==OB_MESH) {
 
201
                                me= base->object->data;
 
202
 
 
203
                                // Join this object's vertex groups to the base one's
 
204
                                for (dg=base->object->defbase.first; dg; dg=dg->next){
 
205
                                        hasdefgroup= 1;
 
206
                                        
 
207
                                        /* See if this group exists in the object */
 
208
                                        for (odg=ob->defbase.first; odg; odg=odg->next){
 
209
                                                if (!strcmp(odg->name, dg->name)){
 
210
                                                        break;
 
211
                                                }
 
212
                                        }
 
213
                                        if (!odg){
 
214
                                                odg = MEM_callocN (sizeof(bDeformGroup), "deformGroup");
 
215
                                                memcpy (odg, dg, sizeof(bDeformGroup));
 
216
                                                BLI_addtail(&ob->defbase, odg);
 
217
                                        }
 
218
 
 
219
                                }
 
220
                                if (ob->defbase.first && ob->actdef==0)
 
221
                                        ob->actdef=1;
 
222
 
 
223
                                if(me->totvert) {
 
224
                                        for(a=1; a<=base->object->totcol; a++) {
 
225
                                                ma= give_current_material(base->object, a);
 
226
                                                if(ma) {
 
227
                                                        for(b=0; b<totcol; b++) {
 
228
                                                                if(ma == matar[b]) break;
 
229
                                                        }
 
230
                                                        if(b==totcol) {
 
231
                                                                matar[b]= ma;
 
232
                                                                ma->id.us++;
 
233
                                                                totcol++;
 
234
                                                        }
 
235
                                                        if(totcol>=MAXMAT-1) break;
 
236
                                                }
 
237
                                        }
 
238
                                }
 
239
                        }
 
240
                        if(totcol>=MAXMAT-1) break;
 
241
                }
 
242
                base= base->next;
 
243
        }
 
244
 
 
245
        me= ob->data;
 
246
        mvert= mvertmain= MEM_mallocN(totvert*sizeof(MVert), "joinmesh vert");
 
247
 
 
248
        if(totedge) medge= medgemain= MEM_callocN(totedge*sizeof(MEdge), "joinmesh edge");
 
249
        else medgemain= NULL;
 
250
        
 
251
        if (totface) mface= mfacemain= MEM_mallocN(totface*sizeof(MFace), "joinmesh face");
 
252
        else mfacemain= NULL;
 
253
 
 
254
        if(me->mcol) mcol= mcolmain= MEM_callocN(totface*4*sizeof(int), "joinmesh mcol");
 
255
        else mcolmain= NULL;
 
256
 
 
257
        /* if active object doesn't have Tfaces, but one in the selection does,
 
258
           make TFaces for active, so we don't lose texture information in the
 
259
           join process */
 
260
        if(me->tface || testSelected_TfaceMesh()) tface= tfacemain= MEM_callocN(totface*4*sizeof(TFace), "joinmesh4");
 
261
        else tfacemain= NULL;
 
262
 
 
263
        if(me->dvert || hasdefgroup)
 
264
                dvert= dvertmain= MEM_callocN(totvert*sizeof(MDeformVert), "joinmesh5");
 
265
        else dvert=dvertmain= NULL;
 
266
 
 
267
        vertofs= 0;
 
268
        
 
269
        /* inverse transorm all selected meshes in this object */
 
270
        Mat4Invert(imat, ob->obmat);
 
271
        
 
272
        base= FIRSTBASE;
 
273
        while(base) {
 
274
                nextb= base->next;
 
275
                if TESTBASELIB(base) {
 
276
                        if(base->object->type==OB_MESH) {
 
277
                                
 
278
                                me= base->object->data;
 
279
                                
 
280
                                if(me->totvert) {
 
281
                                        
 
282
                                        memcpy(mvert, me->mvert, me->totvert*sizeof(MVert));
 
283
                                        
 
284
                                        copy_dverts(dvert, me->dvert, me->totvert);
 
285
 
 
286
                                        /* NEW VERSION */
 
287
                                        if (dvertmain){
 
288
                                                for (i=0; i<me->totvert; i++){
 
289
                                                        for (j=0; j<dvert[i].totweight; j++){
 
290
                                                                //      Find the old vertex group
 
291
                                                                odg = BLI_findlink (&base->object->defbase, dvert[i].dw[j].def_nr);
 
292
                                                                if(odg) {
 
293
                                                                        //      Search for a match in the new object
 
294
                                                                        for (dg=ob->defbase.first, index=0; dg; dg=dg->next, index++){
 
295
                                                                                if (!strcmp(dg->name, odg->name)){
 
296
                                                                                        dvert[i].dw[j].def_nr = index;
 
297
                                                                                        break;
 
298
                                                                                }
 
299
                                                                        }
 
300
                                                                }
 
301
                                                        }
 
302
                                                }
 
303
                                                dvert+=me->totvert;
 
304
                                        }
 
305
 
 
306
                                        if(base->object != ob) {
 
307
                                                /* watch this: switch matmul order really goes wrong */
 
308
                                                Mat4MulMat4(cmat, base->object->obmat, imat);
 
309
                                                
 
310
                                                a= me->totvert;
 
311
                                                while(a--) {
 
312
                                                        Mat4MulVecfl(cmat, mvert->co);
 
313
                                                        mvert++;
 
314
                                                }
 
315
                                        }
 
316
                                        else mvert+= me->totvert;
 
317
                                        
 
318
                                        if(mcolmain) {
 
319
                                                if(me->mcol) memcpy(mcol, me->mcol, me->totface*4*4);
 
320
                                                mcol+= 4*me->totface;
 
321
                                        }
 
322
                                }
 
323
                                if(me->totface) {
 
324
                                
 
325
                                        /* make mapping for materials */
 
326
                                        memset(map, 0, 4*MAXMAT);
 
327
                                        for(a=1; a<=base->object->totcol; a++) {
 
328
                                                ma= give_current_material(base->object, a);
 
329
                                                if(ma) {
 
330
                                                        for(b=0; b<totcol; b++) {
 
331
                                                                if(ma == matar[b]) {
 
332
                                                                        map[a-1]= b;
 
333
                                                                        break;
 
334
                                                                }
 
335
                                                        }
 
336
                                                }
 
337
                                        }
 
338
 
 
339
                                        memcpy(mface, me->mface, me->totface*sizeof(MFace));
 
340
                                        
 
341
                                        a= me->totface;
 
342
                                        while(a--) {
 
343
                                                mface->v1+= vertofs;
 
344
                                                mface->v2+= vertofs;
 
345
                                                if(mface->v3) mface->v3+= vertofs;
 
346
                                                if(mface->v4) mface->v4+= vertofs;
 
347
                                                
 
348
                                                mface->mat_nr= map[(int)mface->mat_nr];
 
349
                                                
 
350
                                                mface++;
 
351
                                        }
 
352
                                        
 
353
                                        if(tfacemain) {
 
354
                                                if(me->tface) {
 
355
                                                        memcpy(tface, me->tface, me->totface*sizeof(TFace));
 
356
                                                        tface+= me->totface;
 
357
                                                }
 
358
                                                else {
 
359
                                                        for(a=0; a<me->totface; a++, tface++) {
 
360
                                                                default_tface(tface);
 
361
                                                        }
 
362
                                                }
 
363
                                        }
 
364
                                        
 
365
                                }
 
366
                                
 
367
                                if(me->totedge) {
 
368
                                        memcpy(medge, me->medge, me->totedge*sizeof(MEdge));
 
369
                                        
 
370
                                        a= me->totedge;
 
371
                                        while(a--) {
 
372
                                                medge->v1+= vertofs;
 
373
                                                medge->v2+= vertofs;
 
374
                                                medge++;
 
375
                                        }
 
376
                                }
 
377
                                
 
378
                                vertofs+= me->totvert;
 
379
                                
 
380
                                if(base->object!=ob) {
 
381
                                        free_and_unlink_base(base);
 
382
                                }
 
383
                        }
 
384
                }
 
385
                base= nextb;
 
386
        }
 
387
        
 
388
        me= ob->data;
 
389
        
 
390
        if(me->mvert) MEM_freeN(me->mvert);
 
391
        me->mvert= mvertmain;
 
392
 
 
393
        if(me->medge) MEM_freeN(me->medge);
 
394
        me->medge= medgemain;
 
395
 
 
396
        if(me->mface) MEM_freeN(me->mface);
 
397
        me->mface= mfacemain;
 
398
 
 
399
        if(me->dvert) free_dverts(me->dvert, me->totvert);
 
400
        me->dvert = dvertmain;
 
401
 
 
402
        if(me->mcol) MEM_freeN(me->mcol);
 
403
        me->mcol= (MCol *)mcolmain;
 
404
        
 
405
        if(me->tface) MEM_freeN(me->tface);
 
406
        me->tface= tfacemain;
 
407
        
 
408
        me->totvert= totvert;
 
409
        me->totedge= totedge;
 
410
        me->totface= totface;
 
411
        
 
412
        /* old material array */
 
413
        for(a=1; a<=ob->totcol; a++) {
 
414
                ma= ob->mat[a-1];
 
415
                if(ma) ma->id.us--;
 
416
        }
 
417
        for(a=1; a<=me->totcol; a++) {
 
418
                ma= me->mat[a-1];
 
419
                if(ma) ma->id.us--;
 
420
        }
 
421
        if(ob->mat) MEM_freeN(ob->mat);
 
422
        if(me->mat) MEM_freeN(me->mat);
 
423
        ob->mat= me->mat= 0;
 
424
        
 
425
        if(totcol) {
 
426
                me->mat= matar;
 
427
                ob->mat= MEM_callocN(sizeof(void *)*totcol, "join obmatar");
 
428
        }
 
429
        else MEM_freeN(matar);
 
430
        
 
431
        ob->totcol= me->totcol= totcol;
 
432
        ob->colbits= 0;
 
433
        
 
434
        /* other mesh users */
 
435
        test_object_materials((ID *)me);
 
436
        
 
437
        enter_editmode();
 
438
        exit_editmode(1);       // freedata, but no undo
 
439
        
 
440
        test_scene_constraints(); // always call after delete object (stupid!)
 
441
 
 
442
        allqueue(REDRAWVIEW3D, 0);
 
443
        allqueue(REDRAWBUTSSHADING, 0);
 
444
        makeDispList(ob);
 
445
 
 
446
        BIF_undo_push("Join Mesh");
 
447
}
 
448
 
 
449
 
 
450
void fasterdraw(void)
 
451
{
 
452
        Base *base;
 
453
        Mesh *me;
 
454
        MFace *mface;
 
455
        int toggle, a;
 
456
 
 
457
        if(G.obedit) return;
 
458
 
 
459
        /* reset flags */
 
460
        me= G.main->mesh.first;
 
461
        while(me) {
 
462
                me->flag &= ~ME_ISDONE;
 
463
                me= me->id.next;
 
464
        }
 
465
 
 
466
        base= FIRSTBASE;
 
467
        while(base) {
 
468
                if( TESTBASELIB(base) && (base->object->type==OB_MESH)) {
 
469
                        me= base->object->data;
 
470
                        if(me->id.lib==0 && (me->flag & ME_ISDONE)==0) {
 
471
                                me->flag |= ME_ISDONE;
 
472
                                mface= me->mface;
 
473
                                toggle= 0;
 
474
                                for(a=0; a<me->totface; a++) {
 
475
                                        if( (mface->edcode & ME_V1V2) && ( (toggle++) & 1) ) {
 
476
                                                mface->edcode-= ME_V1V2;
 
477
                                        }
 
478
                                        if( (mface->edcode & ME_V2V3) && ( (toggle++) & 1)) {
 
479
                                                mface->edcode-= ME_V2V3;
 
480
                                        }
 
481
                                        if( (mface->edcode & ME_V3V1) && ( (toggle++) & 1)) {
 
482
                                                mface->edcode-= ME_V3V1;
 
483
                                        }
 
484
                                        if( (mface->edcode & ME_V4V1) && ( (toggle++) & 1)) {
 
485
                                                mface->edcode-= ME_V4V1;
 
486
                                        }
 
487
                                        if( (mface->edcode & ME_V3V4) && ( (toggle++) & 1)) {
 
488
                                                mface->edcode-= ME_V3V4;
 
489
                                        }
 
490
                                        mface++;
 
491
                                }
 
492
                        }
 
493
                }
 
494
                base= base->next;
 
495
        }
 
496
 
 
497
        /* important?: reset flags again */
 
498
        me= G.main->mesh.first;
 
499
        while(me) {
 
500
                me->flag &= ~ME_ISDONE;
 
501
                me= me->id.next;
 
502
        }
 
503
 
 
504
        allqueue(REDRAWVIEW3D, 0);
 
505
}
 
506
 
 
507
void slowerdraw(void)           /* reset fasterdraw */
 
508
{
 
509
        Base *base;
 
510
        Mesh *me;
 
511
        MFace *mface;
 
512
        int a;
 
513
 
 
514
        if(G.obedit) return;
 
515
 
 
516
        base= FIRSTBASE;
 
517
        while(base) {
 
518
                if( TESTBASELIB(base) && (base->object->type==OB_MESH)) {
 
519
                        me= base->object->data;
 
520
                        if(me->id.lib==0) {
 
521
                                
 
522
                                mface= me->mface;
 
523
                                
 
524
                                for(a=0; a<me->totface; a++) {
 
525
                                
 
526
                                        mface->edcode |= ME_V1V2|ME_V2V3;
 
527
                                        mface++;
 
528
                                }
 
529
                        }
 
530
                }
 
531
                base= base->next;
 
532
        }
 
533
 
 
534
        allqueue(REDRAWVIEW3D, 0);
 
535
}
 
536
 
 
537
/* ***************** */
 
538
 
 
539
/* this one for NOT in editmode 
 
540
 
 
541
(only used by external modules, that is, until now by the 
 
542
python NMesh module) 
 
543
 
 
544
TODO: Probably it's better to convert the mesh into a EditMesh, call
 
545
vertexnormals() and convert it back to a Mesh again.
 
546
 
 
547
*/
 
548
 
 
549
static int contrpuntnorm(float *n, float *puno)  /* dutch: check vertex normal */
 
550
{
 
551
        float inp;
 
552
 
 
553
        inp= n[0]*puno[0]+n[1]*puno[1]+n[2]*puno[2];
 
554
 
 
555
        /* angles 90 degrees: dont flip */
 
556
        if(inp> -0.000001) return 0;
 
557
 
 
558
        return 1;
 
559
}
 
560
 
 
561
void vertexnormals_mesh(Mesh *me, float *extverts)
 
562
{
 
563
        MVert *mvert;
 
564
        MFace *mface;
 
565
        float n1[3], n2[3], n3[3], n4[3], co[4], fac1, fac2, fac3, fac4, *temp;
 
566
        float *f1, *f2, *f3, *f4, xn, yn, zn, *normals;
 
567
        float *v1, *v2, *v3, *v4, len, vnor[3];
 
568
        int a, testflip;
 
569
 
 
570
        if(me->totvert==0) return;
 
571
 
 
572
        testflip= (me->flag & ME_NOPUNOFLIP)==0;
 
573
        if((me->flag & ME_TWOSIDED)==0) testflip= 0;    /* large angles */
 
574
        
 
575
        if(me->totface==0) {
 
576
                /* fake vertex normals for 'halopuno' (render option) */
 
577
                mvert= me->mvert;
 
578
                for(a=0; a<me->totvert; a++, mvert++) {
 
579
                        VECCOPY(n1, mvert->co);
 
580
                        Normalise(n1);
 
581
                        mvert->no[0]= 32767.0*n1[0];
 
582
                        mvert->no[1]= 32767.0*n1[1];
 
583
                        mvert->no[2]= 32767.0*n1[2];
 
584
                }
 
585
                return;
 
586
        }
 
587
 
 
588
        normals= MEM_callocN(me->totvert*3*sizeof(float), "normals");
 
589
        
 
590
        /* calculate cosine angles, and add to vertex normal */
 
591
        mface= me->mface;
 
592
        mvert= me->mvert;
 
593
        for(a=0; a<me->totface; a++, mface++) {
 
594
                
 
595
                if(mface->v3==0) continue;
 
596
                
 
597
                if(extverts) {
 
598
                        v1= extverts+3*mface->v1;
 
599
                        v2= extverts+3*mface->v2;
 
600
                        v3= extverts+3*mface->v3;
 
601
                        v4= extverts+3*mface->v4;
 
602
                }
 
603
                else {          
 
604
                        v1= (mvert+mface->v1)->co;
 
605
                        v2= (mvert+mface->v2)->co;
 
606
                        v3= (mvert+mface->v3)->co;
 
607
                        v4= (mvert+mface->v4)->co;
 
608
                }
 
609
                
 
610
                VecSubf(n1, v2, v1);
 
611
                VecSubf(n2, v3, v2);
 
612
                Normalise(n1);
 
613
                Normalise(n2);
 
614
 
 
615
                if(mface->v4==0) {
 
616
                        VecSubf(n3, v1, v3);
 
617
                        Normalise(n3);
 
618
                        
 
619
                        co[0]= saacos(-n3[0]*n1[0]-n3[1]*n1[1]-n3[2]*n1[2]);
 
620
                        co[1]= saacos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]);
 
621
                        co[2]= saacos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]);
 
622
                        
 
623
                }
 
624
                else {
 
625
                        VecSubf(n3, v4, v3);
 
626
                        VecSubf(n4, v1, v4);
 
627
                        Normalise(n3);
 
628
                        Normalise(n4);
 
629
 
 
630
                        co[0]= saacos(-n4[0]*n1[0]-n4[1]*n1[1]-n4[2]*n1[2]);
 
631
                        co[1]= saacos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]);
 
632
                        co[2]= saacos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]);
 
633
                        co[3]= saacos(-n3[0]*n4[0]-n3[1]*n4[1]-n3[2]*n4[2]);
 
634
                }
 
635
                
 
636
                CalcNormFloat(v1, v2, v3, vnor);
 
637
                
 
638
                temp= normals+3*mface->v1;
 
639
                if(testflip && contrpuntnorm(vnor, temp) ) co[0]= -co[0];
 
640
                temp[0]+= co[0]*vnor[0];
 
641
                temp[1]+= co[0]*vnor[1];
 
642
                temp[2]+= co[0]*vnor[2];
 
643
                
 
644
                temp= normals+3*mface->v2;
 
645
                if(testflip && contrpuntnorm(vnor, temp) ) co[1]= -co[1];
 
646
                temp[0]+= co[1]*vnor[0];
 
647
                temp[1]+= co[1]*vnor[1];
 
648
                temp[2]+= co[1]*vnor[2];
 
649
                
 
650
                temp= normals+3*mface->v3;
 
651
                if(testflip && contrpuntnorm(vnor, temp) ) co[2]= -co[2];
 
652
                temp[0]+= co[2]*vnor[0];
 
653
                temp[1]+= co[2]*vnor[1];
 
654
                temp[2]+= co[2]*vnor[2];
 
655
                
 
656
                if(mface->v4) {
 
657
                        temp= normals+3*mface->v4;
 
658
                        if(testflip && contrpuntnorm(vnor, temp) ) co[3]= -co[3];
 
659
                        temp[0]+= co[3]*vnor[0];
 
660
                        temp[1]+= co[3]*vnor[1];
 
661
                        temp[2]+= co[3]*vnor[2];
 
662
                }
 
663
        }
 
664
 
 
665
        /* normalize vertex normals */
 
666
        mvert= me->mvert;
 
667
        for(a=0; a<me->totvert; a++, mvert++) {
 
668
                len= Normalise(normals+3*a);
 
669
                if(len!=0.0) {
 
670
                        VECCOPY(n1, normals+3*a);
 
671
                        Normalise(n1);
 
672
 
 
673
                        mvert->no[0]= 32767.0*n1[0];
 
674
                        mvert->no[1]= 32767.0*n1[1];
 
675
                        mvert->no[2]= 32767.0*n1[2];
 
676
                }
 
677
        }
 
678
        
 
679
        /* vertex normal flipping flags, for during render */
 
680
        mface= me->mface;
 
681
        mvert= me->mvert;
 
682
        for(a=0; a<me->totface; a++, mface++) {
 
683
                mface->puno=0;                  
 
684
                
 
685
                if(mface->v3==0) continue;
 
686
                
 
687
                if(extverts) {
 
688
                        v1= extverts+3*mface->v1;
 
689
                        v2= extverts+3*mface->v2;
 
690
                        v3= extverts+3*mface->v3;
 
691
                }
 
692
                else {          
 
693
                        v1= (mvert+mface->v1)->co;
 
694
                        v2= (mvert+mface->v2)->co;
 
695
                        v3= (mvert+mface->v3)->co;
 
696
                }
 
697
 
 
698
                CalcNormFloat(v1, v2, v3, vnor);
 
699
 
 
700
                if(testflip) {
 
701
                        f1= normals + 3*mface->v1;
 
702
                        f2= normals + 3*mface->v2;
 
703
                        f3= normals + 3*mface->v3;
 
704
 
 
705
                        fac1= vnor[0]*f1[0] + vnor[1]*f1[1] + vnor[2]*f1[2];
 
706
                        if(fac1<0.0) {
 
707
                                mface->puno = ME_FLIPV1;
 
708
                        }
 
709
                        fac2= vnor[0]*f2[0] + vnor[1]*f2[1] + vnor[2]*f2[2];
 
710
                        if(fac2<0.0) {
 
711
                                mface->puno += ME_FLIPV2;
 
712
                        }
 
713
                        fac3= vnor[0]*f3[0] + vnor[1]*f3[1] + vnor[2]*f3[2];
 
714
                        if(fac3<0.0) {
 
715
                                mface->puno += ME_FLIPV3;
 
716
                        }
 
717
                        if(mface->v4) {
 
718
                                f4= normals + 3*mface->v4;
 
719
                                fac4= vnor[0]*f4[0] + vnor[1]*f4[1] + vnor[2]*f4[2];
 
720
                                if(fac4<0.0) {
 
721
                                        mface->puno += ME_FLIPV4;
 
722
                                }
 
723
                        }
 
724
                }
 
725
                /* proj for cubemap! */
 
726
                xn= fabs(vnor[0]);
 
727
                yn= fabs(vnor[1]);
 
728
                zn= fabs(vnor[2]);
 
729
                
 
730
                if(zn>xn && zn>yn) mface->puno += ME_PROJXY;
 
731
                else if(yn>xn && yn>zn) mface->puno += ME_PROJXZ;
 
732
                else mface->puno += ME_PROJYZ;
 
733
                
 
734
        }
 
735
        
 
736
        MEM_freeN(normals);
 
737
}
 
738
 
 
739
 
 
740
 
 
741
/* ********************** SORT FACES ******************* */
 
742
 
 
743
static void permutate(void *list, int num, int size, int *index)
 
744
{
 
745
        void *buf;
 
746
        int len;
 
747
        int i;
 
748
 
 
749
        len = num * size;
 
750
 
 
751
        buf = MEM_mallocN(len, "permutate");
 
752
        memcpy(buf, list, len);
 
753
        
 
754
        for (i = 0; i < num; i++) {
 
755
                memcpy((char *)list + (i * size), (char *)buf + (index[i] * size), size);
 
756
        }
 
757
        MEM_freeN(buf);
 
758
}
 
759
 
 
760
static MVert *mvertbase;
 
761
static MFace *mfacebase;
 
762
 
 
763
static int verg_mface(const void *v1, const void *v2)
 
764
{
 
765
        MFace *x1, *x2;
 
766
 
 
767
        MVert *ve1, *ve2;
 
768
        int i1, i2;
 
769
 
 
770
        i1 = ((int *) v1)[0];
 
771
        i2 = ((int *) v2)[0];
 
772
        
 
773
        x1 = mfacebase + i1;
 
774
        x2 = mfacebase + i2;
 
775
 
 
776
        ve1= mvertbase+x1->v1;
 
777
        ve2= mvertbase+x2->v1;
 
778
        
 
779
        if( ve1->co[2] > ve2->co[2] ) return 1;
 
780
        else if( ve1->co[2] < ve2->co[2]) return -1;
 
781
        return 0;
 
782
}
 
783
 
 
784
 
 
785
void sort_faces(void)
 
786
{
 
787
        Object *ob= OBACT;
 
788
        Mesh *me;
 
789
        
 
790
        int i, *index;
 
791
        
 
792
        if(ob==0) return;
 
793
        if(G.obedit) return;
 
794
        if(ob->type!=OB_MESH) return;
 
795
        
 
796
        if(okee("Sort faces in Z axis")==0) return;
 
797
        me= ob->data;
 
798
        if(me->totface==0) return;
 
799
 
 
800
/*      create index list */
 
801
        index = (int *) MEM_mallocN(sizeof(int) * me->totface, "sort faces");
 
802
        for (i = 0; i < me->totface; i++) {
 
803
                index[i] = i;
 
804
        }
 
805
        mvertbase= me->mvert;
 
806
        mfacebase = me->mface;
 
807
 
 
808
/* sort index list instead of faces itself 
 
809
   and apply this permutation to the face list plus
 
810
   to the texture faces */
 
811
        qsort(index, me->totface, sizeof(int), verg_mface);
 
812
 
 
813
        permutate(mfacebase, me->totface, sizeof(MFace), index);
 
814
        if (me->tface) 
 
815
                permutate(me->tface, me->totface, sizeof(TFace), index);
 
816
 
 
817
        MEM_freeN(index);
 
818
 
 
819
        allqueue(REDRAWVIEW3D, 0);
 
820
        makeDispList(G.obedit);
 
821
}
 
822
 
 
823