More properly coded version for adding edges... now only do_versions()
[blender.git] / source / blender / blenkernel / intern / DerivedMesh.c
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) 2005 Blender Foundation.
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 #include <string.h>
34
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38
39 #include <zlib.h>
40
41 #include "PIL_time.h"
42
43 #include "MEM_guardedalloc.h"
44
45 #include "DNA_effect_types.h"
46 #include "DNA_mesh_types.h"
47 #include "DNA_meshdata_types.h"
48 #include "DNA_modifier_types.h"
49 #include "DNA_object_types.h"
50 #include "DNA_object_force.h"
51 #include "DNA_object_fluidsim.h" // N_T
52 #include "DNA_scene_types.h" // N_T
53
54 #include "BLI_arithb.h"
55 #include "BLI_blenlib.h"
56 #include "BLI_editVert.h"
57
58 #include "BKE_utildefines.h"
59 #include "BKE_DerivedMesh.h"
60 #include "BKE_displist.h"
61 #include "BKE_effect.h"
62 #include "BKE_global.h"
63 #include "BKE_material.h"
64 #include "BKE_mesh.h"
65 #include "BKE_object.h"
66 #include "BKE_subsurf.h"
67 #include "LBM_fluidsim.h"
68 #include "BKE_deform.h"
69 #include "BKE_modifier.h"
70 #include "BKE_key.h"
71
72 #include "BIF_gl.h"
73 #include "BIF_glutil.h"
74
75 ///////////////////////////////////
76 ///////////////////////////////////
77
78 typedef struct {
79         DerivedMesh dm;
80
81         Object *ob;
82         Mesh *me;
83         MVert *verts;
84         float *nors;
85         MCol *wpaintMCol;
86
87         int freeNors, freeVerts;
88 } MeshDerivedMesh;
89
90 static DispListMesh *meshDM_convertToDispListMesh(DerivedMesh *dm, int allowShared)
91 {
92         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
93         Mesh *me = mdm->me;
94         DispListMesh *dlm = MEM_callocN(sizeof(*dlm), "dlm");
95
96         dlm->totvert = me->totvert;
97         dlm->totedge = me->totedge;
98         dlm->totface = me->totface;
99         dlm->mvert = mdm->verts;
100         dlm->medge = me->medge;
101         dlm->mface = me->mface;
102         dlm->tface = me->tface;
103         dlm->mcol = me->mcol;
104         dlm->nors = mdm->nors;
105         dlm->dontFreeVerts = dlm->dontFreeOther = dlm->dontFreeNors = 1;
106
107         if (!allowShared) {
108                 dlm->mvert = MEM_dupallocN(dlm->mvert);
109                 if (dlm->nors) dlm->nors = MEM_dupallocN(dlm->nors);
110
111                 dlm->dontFreeVerts = dlm->dontFreeNors = 0;
112         }
113
114         return dlm;
115 }
116
117 static void meshDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
118 {
119         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
120         Mesh *me = mdm->me;
121         int i;
122
123         if (me->totvert) {
124                 for (i=0; i<me->totvert; i++) {
125                         DO_MINMAX(mdm->verts[i].co, min_r, max_r);
126                 }
127         } else {
128                 min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
129         }
130 }
131
132 static void meshDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
133 {
134         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
135         Mesh *me = mdm->me;
136         int i;
137
138         for (i=0; i<me->totvert; i++) {
139                 cos_r[i][0] = mdm->verts[i].co[0];
140                 cos_r[i][1] = mdm->verts[i].co[1];
141                 cos_r[i][2] = mdm->verts[i].co[2];
142         }
143 }
144
145 static void meshDM_getVertCo(DerivedMesh *dm, int index, float co_r[3])
146 {
147         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
148
149         VECCOPY(co_r, mdm->verts[index].co);
150 }
151
152 static void meshDM_getVertNo(DerivedMesh *dm, int index, float no_r[3])
153 {
154         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
155         short *no = mdm->verts[index].no;
156
157         no_r[0] = no[0]/32767.f;
158         no_r[1] = no[1]/32767.f;
159         no_r[2] = no[2]/32767.f;
160 }
161
162 static void meshDM_drawVerts(DerivedMesh *dm)
163 {
164         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
165         Mesh *me = mdm->me;
166         int i;
167
168         glBegin(GL_POINTS);
169         for(i=0; i<me->totvert; i++) {
170                 glVertex3fv(mdm->verts[i].co);
171         }
172         glEnd();
173 }
174 static void meshDM_drawUVEdges(DerivedMesh *dm)
175 {
176         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
177         Mesh *me = mdm->me;
178         int i;
179
180         if (me->tface) {
181                 glBegin(GL_LINES);
182                 for (i=0; i<me->totface; i++) {
183                         TFace *tf = &me->tface[i];
184
185                         if (!(tf->flag&TF_HIDE)) {
186                                 glVertex2fv(tf->uv[0]);
187                                 glVertex2fv(tf->uv[1]);
188
189                                 glVertex2fv(tf->uv[1]);
190                                 glVertex2fv(tf->uv[2]);
191
192                                 if (!me->mface[i].v4) {
193                                         glVertex2fv(tf->uv[2]);
194                                         glVertex2fv(tf->uv[0]);
195                                 } else {
196                                         glVertex2fv(tf->uv[2]);
197                                         glVertex2fv(tf->uv[3]);
198
199                                         glVertex2fv(tf->uv[3]);
200                                         glVertex2fv(tf->uv[0]);
201                                 }
202                         }
203                 }
204                 glEnd();
205         }
206 }
207 static void meshDM_drawEdges(DerivedMesh *dm, int drawLooseEdges)
208 {
209         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
210         Mesh *me= mdm->me;
211         MEdge *medge= me->medge;
212         int i;
213                 
214         glBegin(GL_LINES);
215         for(i=0; i<me->totedge; i++, medge++) {
216                 if ((medge->flag&ME_EDGEDRAW) && (drawLooseEdges || !(medge->flag&ME_LOOSEEDGE))) {
217                         glVertex3fv(mdm->verts[medge->v1].co);
218                         glVertex3fv(mdm->verts[medge->v2].co);
219                 }
220         }
221         glEnd();
222 }
223 static void meshDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
224 {
225         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
226         Mesh *me= mdm->me;
227         int i;
228                 
229         glBegin(GL_LINES);
230         for (i=0; i<me->totedge; i++) {
231                 if (!setDrawOptions || setDrawOptions(userData, i)) {
232                         glVertex3fv(mdm->verts[me->medge[i].v1].co);
233                         glVertex3fv(mdm->verts[me->medge[i].v2].co);
234                 }
235         }
236         glEnd();
237 }
238 static void meshDM_drawLooseEdges(DerivedMesh *dm)
239 {
240         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
241         Mesh *me= mdm->me;
242         MEdge *medge= me->medge;
243         int i;
244
245         glBegin(GL_LINES);
246         for (i=0; i<me->totedge; i++, medge++) {
247                 if (medge->flag&ME_LOOSEEDGE) {
248                         glVertex3fv(mdm->verts[medge->v1].co);
249                         glVertex3fv(mdm->verts[medge->v2].co);
250                 }
251         }
252         glEnd();
253 }
254 static void meshDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int))
255 {
256         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
257         Mesh *me = mdm->me;
258         MVert *mvert= mdm->verts;
259         MFace *mface= me->mface;
260         float *nors = mdm->nors;
261         int a;
262         int glmode=-1, shademodel=-1, matnr=-1, drawCurrentMat=1;
263
264 #define PASSVERT(index) {                                               \
265         if (shademodel==GL_SMOOTH) {                            \
266                 short *no = mvert[index].no;                    \
267                 glNormal3sv(no);                                                \
268         }                                                                                       \
269         glVertex3fv(mvert[index].co);   \
270 }
271
272         glBegin(glmode=GL_QUADS);
273         for(a=0; a<me->totface; a++, mface++, nors+=3) {
274                 int new_glmode, new_matnr, new_shademodel;
275                         
276                 new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
277                 new_matnr = mface->mat_nr+1;
278                 new_shademodel = (!(me->flag&ME_AUTOSMOOTH) && (mface->flag & ME_SMOOTH))?GL_SMOOTH:GL_FLAT;
279                 
280                 if (new_glmode!=glmode || new_matnr!=matnr || new_shademodel!=shademodel) {
281                         glEnd();
282
283                         drawCurrentMat = setMaterial(matnr=new_matnr);
284
285                         glShadeModel(shademodel=new_shademodel);
286                         glBegin(glmode=new_glmode);
287                 } 
288                 
289                 if (drawCurrentMat) {
290                         if(shademodel==GL_FLAT) 
291                                 glNormal3fv(nors);
292
293                         PASSVERT(mface->v1);
294                         PASSVERT(mface->v2);
295                         PASSVERT(mface->v3);
296                         if (mface->v4) {
297                                 PASSVERT(mface->v4);
298                         }
299                 }
300         }
301         glEnd();
302
303         glShadeModel(GL_FLAT);
304 #undef PASSVERT
305 }
306
307 static void meshDM_drawFacesColored(DerivedMesh *dm, int useTwoSide, unsigned char *col1, unsigned char *col2)
308 {
309         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
310         Mesh *me= mdm->me;
311         MFace *mface= me->mface;
312         int a, glmode;
313         unsigned char *cp1, *cp2;
314
315         cp1= col1;
316         if(col2) {
317                 cp2= col2;
318         } else {
319                 cp2= NULL;
320                 useTwoSide= 0;
321         }
322
323         /* there's a conflict here... twosided colors versus culling...? */
324         /* defined by history, only texture faces have culling option */
325         /* we need that as mesh option builtin, next to double sided lighting */
326         if(col1 && col2)
327                 glEnable(GL_CULL_FACE);
328         
329         glShadeModel(GL_SMOOTH);
330         glBegin(glmode=GL_QUADS);
331         for(a=0; a<me->totface; a++, mface++, cp1+= 16) {
332                 int new_glmode= mface->v4?GL_QUADS:GL_TRIANGLES;
333
334                 if (new_glmode!=glmode) {
335                         glEnd();
336                         glBegin(glmode= new_glmode);
337                 }
338                         
339                 glColor3ub(cp1[3], cp1[2], cp1[1]);
340                 glVertex3fv( mdm->verts[mface->v1].co );
341                 glColor3ub(cp1[7], cp1[6], cp1[5]);
342                 glVertex3fv( mdm->verts[mface->v2].co );
343                 glColor3ub(cp1[11], cp1[10], cp1[9]);
344                 glVertex3fv( mdm->verts[mface->v3].co );
345                 if(mface->v4) {
346                         glColor3ub(cp1[15], cp1[14], cp1[13]);
347                         glVertex3fv( mdm->verts[mface->v4].co );
348                 }
349                         
350                 if(useTwoSide) {
351                         glColor3ub(cp2[11], cp2[10], cp2[9]);
352                         glVertex3fv( mdm->verts[mface->v3].co );
353                         glColor3ub(cp2[7], cp2[6], cp2[5]);
354                         glVertex3fv( mdm->verts[mface->v2].co );
355                         glColor3ub(cp2[3], cp2[2], cp2[1]);
356                         glVertex3fv( mdm->verts[mface->v1].co );
357                         if(mface->v4) {
358                                 glColor3ub(cp2[15], cp2[14], cp2[13]);
359                                 glVertex3fv( mdm->verts[mface->v4].co );
360                         }
361                 }
362                 if(col2) cp2+= 16;
363         }
364         glEnd();
365
366         glShadeModel(GL_FLAT);
367         glDisable(GL_CULL_FACE);
368 }
369 static void meshDM_drawFacesTex(DerivedMesh *dm, int (*setDrawParams)(TFace *tf, int matnr)) 
370 {
371         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
372         Mesh *me = mdm->me;
373         MVert *mvert= mdm->verts;
374         MFace *mface= me->mface;
375         TFace *tface = me->tface;
376         float *nors = mdm->nors;
377         int i;
378
379         for (i=0; i<me->totface; i++) {
380                 MFace *mf= &mface[i];
381                 TFace *tf = tface?&tface[i]:NULL;
382                 int flag;
383                 unsigned char *cp= NULL;
384                 
385                 flag = setDrawParams(tf, mf->mat_nr);
386
387                 if (flag==0) {
388                         continue;
389                 } else if (flag==1) {
390                         if (mdm->wpaintMCol) {
391                                 cp= (unsigned char*) &mdm->wpaintMCol[i*4];
392                         } else if (tf) {
393                                 cp= (unsigned char*) tf->col;
394                         } else if (me->mcol) {
395                                 cp= (unsigned char*) &me->mcol[i*4];
396                         }
397                 }
398
399                 if (!(mf->flag&ME_SMOOTH)) {
400                         glNormal3fv(&nors[i*3]);
401                 }
402
403                 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
404                 if (tf) glTexCoord2fv(tf->uv[0]);
405                 if (cp) glColor3ub(cp[3], cp[2], cp[1]);
406                 if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v1].no);
407                 glVertex3fv(mvert[mf->v1].co);
408                         
409                 if (tf) glTexCoord2fv(tf->uv[1]);
410                 if (cp) glColor3ub(cp[7], cp[6], cp[5]);
411                 if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v2].no);
412                 glVertex3fv(mvert[mf->v2].co);
413
414                 if (tf) glTexCoord2fv(tf->uv[2]);
415                 if (cp) glColor3ub(cp[11], cp[10], cp[9]);
416                 if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v3].no);
417                 glVertex3fv(mvert[mf->v3].co);
418
419                 if(mf->v4) {
420                         if (tf) glTexCoord2fv(tf->uv[3]);
421                         if (cp) glColor3ub(cp[15], cp[14], cp[13]);
422                         if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v4].no);
423                         glVertex3fv(mvert[mf->v4].co);
424                 }
425                 glEnd();
426         }
427 }
428 static void meshDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors) 
429 {
430         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
431         Mesh *me = mdm->me;
432         MVert *mvert= mdm->verts;
433         MFace *mface= me->mface;
434         float *nors= mdm->nors;
435         int i;
436
437         for (i=0; i<me->totface; i++) {
438                 MFace *mf= &mface[i];
439                 int drawSmooth = 1;
440
441                 if (!setDrawOptions || setDrawOptions(userData, i, &drawSmooth)) {
442                         unsigned char *cp = NULL;
443
444                         if (useColors) {
445                                 if (mdm->wpaintMCol) {
446                                         cp= (unsigned char*) &mdm->wpaintMCol[i*4];
447                                 } else if (me->tface) {
448                                         cp= (unsigned char*) me->tface[i].col;
449                                 } else if (me->mcol) {
450                                         cp= (unsigned char*) &me->mcol[i*4];
451                                 }
452                         }
453
454                         glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
455                         glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
456
457                         if (!drawSmooth) {
458                                 glNormal3fv(&nors[i*3]);
459
460                                 if (cp) glColor3ub(cp[3], cp[2], cp[1]);
461                                 glVertex3fv(mvert[mf->v1].co);
462                                 if (cp) glColor3ub(cp[7], cp[6], cp[5]);
463                                 glVertex3fv(mvert[mf->v2].co);
464                                 if (cp) glColor3ub(cp[11], cp[10], cp[9]);
465                                 glVertex3fv(mvert[mf->v3].co);
466                                 if(mf->v4) {
467                                         if (cp) glColor3ub(cp[15], cp[14], cp[13]);
468                                         glVertex3fv(mvert[mf->v4].co);
469                                 }
470                         } else {
471                                 if (cp) glColor3ub(cp[3], cp[2], cp[1]);
472                                 glNormal3sv(mvert[mf->v1].no);
473                                 glVertex3fv(mvert[mf->v1].co);
474                                 if (cp) glColor3ub(cp[7], cp[6], cp[5]);
475                                 glNormal3sv(mvert[mf->v2].no);
476                                 glVertex3fv(mvert[mf->v2].co);
477                                 if (cp) glColor3ub(cp[11], cp[10], cp[9]);
478                                 glNormal3sv(mvert[mf->v3].no);
479                                 glVertex3fv(mvert[mf->v3].co);
480                                 if(mf->v4) {
481                                         if (cp) glColor3ub(cp[15], cp[14], cp[13]);
482                                         glNormal3sv(mvert[mf->v4].no);
483                                         glVertex3fv(mvert[mf->v4].co);
484                                 }
485                         }
486
487                         glEnd();
488                 }
489         }
490 }
491 static int meshDM_getNumVerts(DerivedMesh *dm)
492 {
493         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
494         Mesh *me = mdm->me;
495
496         return me->totvert;
497 }
498 static int meshDM_getNumFaces(DerivedMesh *dm)
499 {
500         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
501         Mesh *me = mdm->me;
502
503         return me->totface;
504 }
505
506 static void meshDM_release(DerivedMesh *dm)
507 {
508         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
509
510         if (mdm->wpaintMCol) MEM_freeN(mdm->wpaintMCol);
511         if (mdm->freeNors) MEM_freeN(mdm->nors);
512         if (mdm->freeVerts) MEM_freeN(mdm->verts);
513         MEM_freeN(mdm);
514 }
515
516 static DerivedMesh *getMeshDerivedMesh(Mesh *me, Object *ob, float (*vertCos)[3])
517 {
518         MeshDerivedMesh *mdm = MEM_callocN(sizeof(*mdm), "mdm");
519
520         mdm->dm.getMinMax = meshDM_getMinMax;
521
522         mdm->dm.convertToDispListMesh = meshDM_convertToDispListMesh;
523         mdm->dm.getNumVerts = meshDM_getNumVerts;
524         mdm->dm.getNumFaces = meshDM_getNumFaces;
525
526         mdm->dm.getVertCos = meshDM_getVertCos;
527         mdm->dm.getVertCo = meshDM_getVertCo;
528         mdm->dm.getVertNo = meshDM_getVertNo;
529
530         mdm->dm.drawVerts = meshDM_drawVerts;
531
532         mdm->dm.drawUVEdges = meshDM_drawUVEdges;
533         mdm->dm.drawEdges = meshDM_drawEdges;
534         mdm->dm.drawLooseEdges = meshDM_drawLooseEdges;
535         
536         mdm->dm.drawFacesSolid = meshDM_drawFacesSolid;
537         mdm->dm.drawFacesColored = meshDM_drawFacesColored;
538         mdm->dm.drawFacesTex = meshDM_drawFacesTex;
539         mdm->dm.drawMappedFaces = meshDM_drawMappedFaces;
540
541         mdm->dm.drawMappedEdges = meshDM_drawMappedEdges;
542         mdm->dm.drawMappedFaces = meshDM_drawMappedFaces;
543
544         mdm->dm.release = meshDM_release;
545
546                 /* Works in conjunction with hack during modifier calc */
547         if (G.f & G_WEIGHTPAINT) {
548                 mdm->wpaintMCol = MEM_dupallocN(me->mcol);
549         }
550
551         mdm->ob = ob;
552         mdm->me = me;
553         mdm->verts = me->mvert;
554         mdm->nors = NULL;
555         mdm->freeNors = 0;
556         mdm->freeVerts = 0;
557
558         if (vertCos) {
559                 int i;
560
561                 mdm->verts = MEM_mallocN(sizeof(*mdm->verts)*me->totvert, "deformedVerts");
562                 for (i=0; i<me->totvert; i++) {
563                         VECCOPY(mdm->verts[i].co, vertCos[i]);
564                 }
565                 mesh_calc_normals(mdm->verts, me->totvert, me->mface, me->totface, &mdm->nors);
566                 mdm->freeNors = 1;
567                 mdm->freeVerts = 1;
568         } else {
569                         // XXX this is kinda hacky because we shouldn't really be editing
570                         // the mesh here, however, we can't just call mesh_build_faceNormals(ob)
571                         // because in the case when a key is applied to a mesh the vertex normals
572                         // would never be correctly computed.
573                 mesh_calc_normals(mdm->verts, me->totvert, me->mface, me->totface, &mdm->nors);
574                 mdm->freeNors = 1;
575         }
576
577         return (DerivedMesh*) mdm;
578 }
579
580 ///
581
582 typedef struct {
583         DerivedMesh dm;
584
585         EditMesh *em;
586         float (*vertexCos)[3];
587         float (*vertexNos)[3];
588         float (*faceNos)[3];
589 } EditMeshDerivedMesh;
590
591 static void emDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData)
592 {
593         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
594         EditVert *eve;
595         int i;
596
597         for (i=0,eve= emdm->em->verts.first; eve; i++,eve=eve->next) {
598                 if (emdm->vertexCos) {
599                         func(userData, i, emdm->vertexCos[i], emdm->vertexNos[i], NULL);
600                 } else {
601                         func(userData, i, eve->co, eve->no, NULL);
602                 }
603         }
604 }
605 static void emDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData)
606 {
607         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
608         EditEdge *eed;
609         int i;
610
611         if (emdm->vertexCos) {
612                 EditVert *eve, *preveve;
613
614                 for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
615                         eve->prev = (EditVert*) i++;
616                 for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next)
617                         func(userData, i, emdm->vertexCos[(int) eed->v1->prev], emdm->vertexCos[(int) eed->v2->prev]);
618                 for (preveve=NULL, eve=emdm->em->verts.first; eve; preveve=eve, eve= eve->next)
619                         eve->prev = preveve;
620         } else {
621                 for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next)
622                         func(userData, i, eed->v1->co, eed->v2->co);
623         }
624 }
625 static void emDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) 
626 {
627         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
628         EditEdge *eed;
629         int i;
630
631         if (emdm->vertexCos) {
632                 EditVert *eve, *preveve;
633
634                 for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
635                         eve->prev = (EditVert*) i++;
636
637                 glBegin(GL_LINES);
638                 for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
639                         if(!setDrawOptions || setDrawOptions(userData, i)) {
640                                 glVertex3fv(emdm->vertexCos[(int) eed->v1->prev]);
641                                 glVertex3fv(emdm->vertexCos[(int) eed->v2->prev]);
642                         }
643                 }
644                 glEnd();
645
646                 for (preveve=NULL, eve=emdm->em->verts.first; eve; preveve=eve, eve= eve->next)
647                         eve->prev = preveve;
648         } else {
649                 glBegin(GL_LINES);
650                 for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
651                         if(!setDrawOptions || setDrawOptions(userData, i)) {
652                                 glVertex3fv(eed->v1->co);
653                                 glVertex3fv(eed->v2->co);
654                         }
655                 }
656                 glEnd();
657         }
658 }
659 static void emDM_drawEdges(DerivedMesh *dm, int drawLooseEdges)
660 {
661         emDM_drawMappedEdges(dm, NULL, NULL);
662 }
663 static void emDM_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void (*setDrawInterpOptions)(void *userData, int index, float t), void *userData) 
664 {
665         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
666         EditEdge *eed;
667         int i;
668
669         if (emdm->vertexCos) {
670                 EditVert *eve, *preveve;
671
672                 for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
673                         eve->prev = (EditVert*) i++;
674
675                 glBegin(GL_LINES);
676                 for (i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
677                         if(!setDrawOptions || setDrawOptions(userData, i)) {
678                                 setDrawInterpOptions(userData, i, 0.0);
679                                 glVertex3fv(emdm->vertexCos[(int) eed->v1->prev]);
680                                 setDrawInterpOptions(userData, i, 1.0);
681                                 glVertex3fv(emdm->vertexCos[(int) eed->v2->prev]);
682                         }
683                 }
684                 glEnd();
685
686                 for (preveve=NULL, eve=emdm->em->verts.first; eve; preveve=eve, eve= eve->next)
687                         eve->prev = preveve;
688         } else {
689                 glBegin(GL_LINES);
690                 for (i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
691                         if(!setDrawOptions || setDrawOptions(userData, i)) {
692                                 setDrawInterpOptions(userData, i, 0.0);
693                                 glVertex3fv(eed->v1->co);
694                                 setDrawInterpOptions(userData, i, 1.0);
695                                 glVertex3fv(eed->v2->co);
696                         }
697                 }
698                 glEnd();
699         }
700 }
701 static void emDM__calcFaceCent(EditFace *efa, float cent[3], float (*vertexCos)[3])
702 {
703         if (vertexCos) {
704                 VECCOPY(cent, vertexCos[(int) efa->v1->prev]);
705                 VecAddf(cent, cent, vertexCos[(int) efa->v2->prev]);
706                 VecAddf(cent, cent, vertexCos[(int) efa->v3->prev]);
707                 if (efa->v4) VecAddf(cent, cent, vertexCos[(int) efa->v4->prev]);
708         } else {
709                 VECCOPY(cent, efa->v1->co);
710                 VecAddf(cent, cent, efa->v2->co);
711                 VecAddf(cent, cent, efa->v3->co);
712                 if (efa->v4) VecAddf(cent, cent, efa->v4->co);
713         }
714
715         if (efa->v4) {
716                 VecMulf(cent, 0.25f);
717         } else {
718                 VecMulf(cent, 0.33333333333f);
719         }
720 }
721 static void emDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData)
722 {
723         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
724         EditVert *eve, *preveve;
725         EditFace *efa;
726         float cent[3];
727         int i;
728
729         if (emdm->vertexCos) {
730                 for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
731                         eve->prev = (EditVert*) i++;
732         }
733
734         for(i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) {
735                 emDM__calcFaceCent(efa, cent, emdm->vertexCos);
736                 func(userData, i, cent, emdm->vertexCos?emdm->faceNos[i]:efa->n);
737         }
738
739         if (emdm->vertexCos) {
740                 for (preveve=NULL, eve=emdm->em->verts.first; eve; preveve=eve, eve= eve->next)
741                         eve->prev = preveve;
742         }
743 }
744 static void emDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors)
745 {
746         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
747         EditFace *efa;
748         int i;
749
750         if (emdm->vertexCos) {
751                 EditVert *eve, *preveve;
752                 int drawSmooth = 1;
753
754                 for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
755                         eve->prev = (EditVert*) i++;
756
757                 for (i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) {
758                         if(!setDrawOptions || setDrawOptions(userData, i, &drawSmooth)) {
759                                 glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
760
761                                 glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
762                                 if (!drawSmooth) {
763                                         glNormal3fv(emdm->faceNos[i]);
764                                         glVertex3fv(emdm->vertexCos[(int) efa->v1->prev]);
765                                         glVertex3fv(emdm->vertexCos[(int) efa->v2->prev]);
766                                         glVertex3fv(emdm->vertexCos[(int) efa->v3->prev]);
767                                         if(efa->v4) glVertex3fv(emdm->vertexCos[(int) efa->v4->prev]);
768                                 } else {
769                                         glNormal3fv(emdm->vertexNos[(int) efa->v1->prev]);
770                                         glVertex3fv(emdm->vertexCos[(int) efa->v1->prev]);
771                                         glNormal3fv(emdm->vertexNos[(int) efa->v2->prev]);
772                                         glVertex3fv(emdm->vertexCos[(int) efa->v2->prev]);
773                                         glNormal3fv(emdm->vertexNos[(int) efa->v3->prev]);
774                                         glVertex3fv(emdm->vertexCos[(int) efa->v3->prev]);
775                                         if(efa->v4) {
776                                                 glNormal3fv(emdm->vertexNos[(int) efa->v4->prev]);
777                                                 glVertex3fv(emdm->vertexCos[(int) efa->v4->prev]);
778                                         }
779                                 }
780                                 glEnd();
781                         }
782                 }
783
784                 for (preveve=NULL, eve=emdm->em->verts.first; eve; preveve=eve, eve= eve->next)
785                         eve->prev = preveve;
786         } else {
787                 int drawSmooth = 1;
788
789                 for (i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) {
790                         if(!setDrawOptions || setDrawOptions(userData, i, &drawSmooth)) {
791                                 glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
792
793                                 glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
794                                 if (!drawSmooth) {
795                                         glNormal3fv(efa->n);
796                                         glVertex3fv(efa->v1->co);
797                                         glVertex3fv(efa->v2->co);
798                                         glVertex3fv(efa->v3->co);
799                                         if(efa->v4) glVertex3fv(efa->v4->co);
800                                 } else {
801                                         glNormal3fv(efa->v1->no);
802                                         glVertex3fv(efa->v1->co);
803                                         glNormal3fv(efa->v2->no);
804                                         glVertex3fv(efa->v2->co);
805                                         glNormal3fv(efa->v3->no);
806                                         glVertex3fv(efa->v3->co);
807                                         if(efa->v4) {
808                                                 glNormal3fv(efa->v4->no);
809                                                 glVertex3fv(efa->v4->co);
810                                         }
811                                 }
812                                 glEnd();
813                         }
814                 }
815         }
816 }
817
818 static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
819 {
820         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
821         EditVert *eve;
822         int i;
823
824         if (emdm->em->verts.first) {
825                 for (i=0,eve= emdm->em->verts.first; eve; i++,eve= eve->next) {
826                         if (emdm->vertexCos) {
827                                 DO_MINMAX(emdm->vertexCos[i], min_r, max_r);
828                         } else {
829                                 DO_MINMAX(eve->co, min_r, max_r);
830                         }
831                 }
832         } else {
833                 min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
834         }
835 }
836 static int emDM_getNumVerts(DerivedMesh *dm)
837 {
838         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
839
840         return BLI_countlist(&emdm->em->verts);
841 }
842 static int emDM_getNumFaces(DerivedMesh *dm)
843 {
844         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
845
846         return BLI_countlist(&emdm->em->faces);
847 }
848
849 static void emDM_release(DerivedMesh *dm)
850 {
851         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
852
853         if (emdm->vertexCos) {
854                 MEM_freeN(emdm->vertexCos);
855                 MEM_freeN(emdm->vertexNos);
856                 MEM_freeN(emdm->faceNos);
857         }
858
859         MEM_freeN(emdm);
860 }
861
862 static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em, float (*vertexCos)[3])
863 {
864         EditMeshDerivedMesh *emdm = MEM_callocN(sizeof(*emdm), "emdm");
865
866         emdm->dm.getMinMax = emDM_getMinMax;
867
868         emdm->dm.getNumVerts = emDM_getNumVerts;
869         emdm->dm.getNumFaces = emDM_getNumFaces;
870         emdm->dm.foreachMappedVert = emDM_foreachMappedVert;
871         emdm->dm.foreachMappedEdge = emDM_foreachMappedEdge;
872         emdm->dm.foreachMappedFaceCenter = emDM_foreachMappedFaceCenter;
873
874         emdm->dm.drawEdges = emDM_drawEdges;
875         emdm->dm.drawMappedEdges = emDM_drawMappedEdges;
876         emdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp;
877         emdm->dm.drawMappedFaces = emDM_drawMappedFaces;
878
879         emdm->dm.release = emDM_release;
880         
881         emdm->em = em;
882         emdm->vertexCos = vertexCos;
883
884         if (vertexCos) {
885                 EditVert *eve, *preveve;
886                 EditFace *efa;
887                 int totface = BLI_countlist(&em->faces);
888                 int i;
889
890                 for (i=0,eve=em->verts.first; eve; eve= eve->next)
891                         eve->prev = (EditVert*) i++;
892
893                 emdm->vertexNos = MEM_callocN(sizeof(*emdm->vertexNos)*i, "emdm_vno");
894                 emdm->faceNos = MEM_mallocN(sizeof(*emdm->faceNos)*totface, "emdm_vno");
895
896                 for(i=0, efa= em->faces.first; efa; i++, efa=efa->next) {
897                         float *v1 = vertexCos[(int) efa->v1->prev];
898                         float *v2 = vertexCos[(int) efa->v2->prev];
899                         float *v3 = vertexCos[(int) efa->v3->prev];
900                         float *no = emdm->faceNos[i];
901                         
902                         if(efa->v4) {
903                                 float *v4 = vertexCos[(int) efa->v3->prev];
904
905                                 CalcNormFloat4(v1, v2, v3, v4, no);
906                                 VecAddf(emdm->vertexNos[(int) efa->v4->prev], emdm->vertexNos[(int) efa->v4->prev], no);
907                         }
908                         else {
909                                 CalcNormFloat(v1, v2, v3, no);
910                         }
911
912                         VecAddf(emdm->vertexNos[(int) efa->v1->prev], emdm->vertexNos[(int) efa->v1->prev], no);
913                         VecAddf(emdm->vertexNos[(int) efa->v2->prev], emdm->vertexNos[(int) efa->v2->prev], no);
914                         VecAddf(emdm->vertexNos[(int) efa->v3->prev], emdm->vertexNos[(int) efa->v3->prev], no);
915                 }
916
917                 for(i=0, eve= em->verts.first; eve; i++, eve=eve->next) {
918                         float *no = emdm->vertexNos[i];
919
920                         if (Normalise(no)==0.0) {
921                                 VECCOPY(no, vertexCos[i]);
922                                 Normalise(no);
923                         }
924                 }
925
926                 for (preveve=NULL, eve=emdm->em->verts.first; eve; preveve=eve, eve= eve->next)
927                         eve->prev = preveve;
928         }
929
930         return (DerivedMesh*) emdm;
931 }
932
933 ///
934
935 typedef struct {
936         DerivedMesh dm;
937
938         DispListMesh *dlm;
939 } SSDerivedMesh;
940
941 static void ssDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData)
942 {
943         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
944         DispListMesh *dlm = ssdm->dlm;
945         int i, index=-1;
946
947         for (i=0; i<dlm->totvert; i++) {
948                 MVert *mv = &dlm->mvert[i];
949
950                 if (mv->flag&ME_VERT_STEPINDEX) index++;
951
952                 if (index!=-1) {
953                         func(userData, index, mv->co, NULL, mv->no);
954                 }
955         }
956 }
957 static void ssDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData)
958 {
959         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
960         DispListMesh *dlm = ssdm->dlm;
961         int i, index=-1;
962
963         for (i=0; i<dlm->totedge; i++) {
964                 MEdge *med = &dlm->medge[i];
965
966                 if (med->flag&ME_EDGE_STEPINDEX) index++;
967
968                 if (index!=-1) {
969                         func(userData, index, dlm->mvert[med->v1].co, dlm->mvert[med->v2].co);
970                 }
971         }
972 }
973 static void ssDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) 
974 {
975         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
976         DispListMesh *dlm = ssdm->dlm;
977         int i, index=-1;
978
979         glBegin(GL_LINES);
980         for(i=0; i<dlm->totedge; i++) {
981                 MEdge *med = &dlm->medge[i];
982
983                 if (med->flag&ME_EDGE_STEPINDEX) index++;
984
985                 if (index!=-1 && (!setDrawOptions || setDrawOptions(userData, index))) {
986                         glVertex3fv(dlm->mvert[med->v1].co);
987                         glVertex3fv(dlm->mvert[med->v2].co);
988                 }
989         }
990         glEnd();
991 }
992
993 static void ssDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData)
994 {
995         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
996         DispListMesh *dlm = ssdm->dlm;
997         int i, index=-1;
998
999         for (i=0; i<dlm->totface; i++) {
1000                 MFace *mf = &dlm->mface[i];
1001
1002                 if (mf->flag&ME_FACE_STEPINDEX) index++;
1003
1004                 if(index!=-1) {
1005                         float cent[3];
1006                         float no[3];
1007
1008                         VECCOPY(cent, dlm->mvert[mf->v1].co);
1009                         VecAddf(cent, cent, dlm->mvert[mf->v2].co);
1010                         VecAddf(cent, cent, dlm->mvert[mf->v3].co);
1011
1012                         if (mf->v4) {
1013                                 CalcNormFloat4(dlm->mvert[mf->v1].co, dlm->mvert[mf->v2].co, dlm->mvert[mf->v3].co, dlm->mvert[mf->v4].co, no);
1014                                 VecAddf(cent, cent, dlm->mvert[mf->v4].co);
1015                                 VecMulf(cent, 0.25f);
1016                         } else {
1017                                 CalcNormFloat(dlm->mvert[mf->v1].co, dlm->mvert[mf->v2].co, dlm->mvert[mf->v3].co, no);
1018                                 VecMulf(cent, 0.33333333333f);
1019                         }
1020
1021                         func(userData, index, cent, no);
1022                 }
1023         }
1024 }
1025 static void ssDM_drawVerts(DerivedMesh *dm)
1026 {
1027         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1028         DispListMesh *dlm = ssdm->dlm;
1029         MVert *mvert= dlm->mvert;
1030         int i;
1031
1032         bglBegin(GL_POINTS);
1033         for (i=0; i<dlm->totvert; i++) {
1034                 bglVertex3fv(mvert[i].co);
1035         }
1036         bglEnd();
1037 }
1038 static void ssDM_drawUVEdges(DerivedMesh *dm)
1039 {
1040         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1041         DispListMesh *dlm = ssdm->dlm;
1042         int i;
1043
1044         if (dlm->tface) {
1045                 glBegin(GL_LINES);
1046                 for (i=0; i<dlm->totface; i++) {
1047                         TFace *tf = &dlm->tface[i];
1048
1049                         if (!(tf->flag&TF_HIDE)) {
1050                                 glVertex2fv(tf->uv[0]);
1051                                 glVertex2fv(tf->uv[1]);
1052
1053                                 glVertex2fv(tf->uv[1]);
1054                                 glVertex2fv(tf->uv[2]);
1055
1056                                 if (!dlm->mface[i].v4) {
1057                                         glVertex2fv(tf->uv[2]);
1058                                         glVertex2fv(tf->uv[0]);
1059                                 } else {
1060                                         glVertex2fv(tf->uv[2]);
1061                                         glVertex2fv(tf->uv[3]);
1062
1063                                         glVertex2fv(tf->uv[3]);
1064                                         glVertex2fv(tf->uv[0]);
1065                                 }
1066                         }
1067                 }
1068                 glEnd();
1069         }
1070 }
1071 static void ssDM_drawLooseEdges(DerivedMesh *dm) 
1072 {
1073         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1074         DispListMesh *dlm = ssdm->dlm;
1075         MVert *mvert = dlm->mvert;
1076         MEdge *medge= dlm->medge;
1077         int i;
1078
1079         glBegin(GL_LINES);
1080         for (i=0; i<dlm->totedge; i++, medge++) {
1081                 if (medge->flag&ME_LOOSEEDGE) {
1082                         glVertex3fv(mvert[medge->v1].co); 
1083                         glVertex3fv(mvert[medge->v2].co);
1084                 }
1085         }
1086         glEnd();
1087 }
1088 static void ssDM_drawEdges(DerivedMesh *dm, int drawLooseEdges) 
1089 {
1090         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1091         DispListMesh *dlm = ssdm->dlm;
1092         MVert *mvert= dlm->mvert;
1093         MEdge *medge= dlm->medge;
1094         int i;
1095         
1096         glBegin(GL_LINES);
1097         for (i=0; i<dlm->totedge; i++, medge++) {
1098                 if ((medge->flag&ME_EDGEDRAW) && (drawLooseEdges || !(medge->flag&ME_LOOSEEDGE))) {
1099                         glVertex3fv(mvert[medge->v1].co); 
1100                         glVertex3fv(mvert[medge->v2].co);
1101                 }
1102         }
1103         glEnd();
1104 }
1105 static void ssDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int))
1106 {
1107         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1108         DispListMesh *dlm = ssdm->dlm;
1109         float *nors = dlm->nors;
1110         int glmode=-1, shademodel=-1, matnr=-1, drawCurrentMat=1;
1111         int i;
1112
1113 #define PASSVERT(ind) {                                         \
1114         if (shademodel==GL_SMOOTH)                              \
1115                 glNormal3sv(dlm->mvert[(ind)].no);      \
1116         glVertex3fv(dlm->mvert[(ind)].co);              \
1117 }
1118
1119         glBegin(glmode=GL_QUADS);
1120         for (i=0; i<dlm->totface; i++) {
1121                 MFace *mf= &dlm->mface[i];
1122                 int new_glmode = mf->v4?GL_QUADS:GL_TRIANGLES;
1123                 int new_shademodel = (mf->flag&ME_SMOOTH)?GL_SMOOTH:GL_FLAT;
1124                 int new_matnr = mf->mat_nr+1;
1125                 
1126                 if(new_glmode!=glmode || new_shademodel!=shademodel || new_matnr!=matnr) {
1127                         glEnd();
1128
1129                         drawCurrentMat = setMaterial(matnr=new_matnr);
1130
1131                         glShadeModel(shademodel=new_shademodel);
1132                         glBegin(glmode=new_glmode);
1133                 }
1134                 
1135                 if (drawCurrentMat) {
1136                         if (shademodel==GL_FLAT)
1137                                 glNormal3fv(&nors[i*3]);
1138                                 
1139                         PASSVERT(mf->v1);
1140                         PASSVERT(mf->v2);
1141                         PASSVERT(mf->v3);
1142                         if (mf->v4)
1143                                 PASSVERT(mf->v4);
1144                 }
1145         }
1146         glEnd();
1147         
1148 #undef PASSVERT
1149 }
1150 static void ssDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *vcols1, unsigned char *vcols2)
1151 {
1152         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1153         DispListMesh *dlm = ssdm->dlm;
1154         int i, lmode;
1155         
1156         glShadeModel(GL_SMOOTH);
1157         if (vcols2) {
1158                 glEnable(GL_CULL_FACE);
1159         } else {
1160                 useTwoSided = 0;
1161         }
1162                 
1163 #define PASSVERT(vidx, fidx) {                                  \
1164         unsigned char *col= &colbase[fidx*4];           \
1165         glColor3ub(col[3], col[2], col[1]);                     \
1166         glVertex3fv(dlm->mvert[(vidx)].co);                     \
1167 }
1168
1169         glBegin(lmode= GL_QUADS);
1170         for (i=0; i<dlm->totface; i++) {
1171                 MFace *mf= &dlm->mface[i];
1172                 int nmode= mf->v4?GL_QUADS:GL_TRIANGLES;
1173                 unsigned char *colbase= &vcols1[i*16];
1174                 
1175                 if (nmode!=lmode) {
1176                         glEnd();
1177                         glBegin(lmode= nmode);
1178                 }
1179                 
1180                 PASSVERT(mf->v1, 0);
1181                 PASSVERT(mf->v2, 1);
1182                 PASSVERT(mf->v3, 2);
1183                 if (mf->v4)
1184                         PASSVERT(mf->v4, 3);
1185                 
1186                 if (useTwoSided) {
1187                         unsigned char *colbase= &vcols2[i*16];
1188
1189                         if (mf->v4)
1190                                 PASSVERT(mf->v4, 3);
1191                         PASSVERT(mf->v3, 2);
1192                         PASSVERT(mf->v2, 1);
1193                         PASSVERT(mf->v1, 0);
1194                 }
1195         }
1196         glEnd();
1197
1198         if (vcols2)
1199                 glDisable(GL_CULL_FACE);
1200         
1201 #undef PASSVERT
1202 }
1203 static void ssDM_drawFacesTex(DerivedMesh *dm, int (*setDrawParams)(TFace *tf, int matnr)) 
1204 {
1205         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1206         DispListMesh *dlm = ssdm->dlm;
1207         MVert *mvert= dlm->mvert;
1208         MFace *mface= dlm->mface;
1209         TFace *tface = dlm->tface;
1210         float *nors = dlm->nors;
1211         int a;
1212         
1213         for (a=0; a<dlm->totface; a++) {
1214                 MFace *mf= &mface[a];
1215                 TFace *tf = tface?&tface[a]:NULL;
1216                 int flag;
1217                 unsigned char *cp= NULL;
1218                 
1219                 flag = setDrawParams(tf, mf->mat_nr);
1220
1221                 if (flag==0) {
1222                         continue;
1223                 } else if (flag==1) {
1224                         if (tf) {
1225                                 cp= (unsigned char*) tf->col;
1226                         } else if (dlm->mcol) {
1227                                 cp= (unsigned char*) &dlm->mcol[a*4];
1228                         }
1229                 }
1230
1231                 if (!(mf->flag&ME_SMOOTH)) {
1232                         glNormal3fv(&nors[a*3]);
1233                 }
1234
1235                 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
1236                 if (tf) glTexCoord2fv(tf->uv[0]);
1237                 if (cp) glColor3ub(cp[3], cp[2], cp[1]);
1238                 if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v1].no);
1239                 glVertex3fv((mvert+mf->v1)->co);
1240                         
1241                 if (tf) glTexCoord2fv(tf->uv[1]);
1242                 if (cp) glColor3ub(cp[7], cp[6], cp[5]);
1243                 if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v2].no);
1244                 glVertex3fv((mvert+mf->v2)->co);
1245
1246                 if (tf) glTexCoord2fv(tf->uv[2]);
1247                 if (cp) glColor3ub(cp[11], cp[10], cp[9]);
1248                 if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v3].no);
1249                 glVertex3fv((mvert+mf->v3)->co);
1250
1251                 if(mf->v4) {
1252                         if (tf) glTexCoord2fv(tf->uv[3]);
1253                         if (cp) glColor3ub(cp[15], cp[14], cp[13]);
1254                         if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v4].no);
1255                         glVertex3fv((mvert+mf->v4)->co);
1256                 }
1257                 glEnd();
1258         }
1259 }
1260 static void ssDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors) 
1261 {
1262         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1263         DispListMesh *dlm = ssdm->dlm;
1264         MVert *mvert= dlm->mvert;
1265         MFace *mface= dlm->mface;
1266         float *nors = dlm->nors;
1267         int i, index=-1;
1268
1269         for (i=0; i<dlm->totface; i++) {
1270                 MFace *mf = &mface[i];
1271                 int drawSmooth = 1;
1272
1273                 if (mf->flag&ME_FACE_STEPINDEX) index++;
1274
1275                 if (index!=-1 && (!setDrawOptions || setDrawOptions(userData, index, &drawSmooth))) {
1276                         unsigned char *cp = NULL;
1277
1278                         if (useColors) {
1279                                 if (dlm->tface) {
1280                                         cp= (unsigned char*) dlm->tface[i].col;
1281                                 } else if (dlm->mcol) {
1282                                         cp= (unsigned char*) &dlm->mcol[i*4];
1283                                 }
1284                         }
1285
1286                         glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
1287                         glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
1288
1289                         if (!drawSmooth) {
1290                                 glNormal3fv(&nors[i*3]);
1291
1292                                 if (cp) glColor3ub(cp[3], cp[2], cp[1]);
1293                                 glVertex3fv(mvert[mf->v1].co);
1294                                 if (cp) glColor3ub(cp[7], cp[6], cp[5]);
1295                                 glVertex3fv(mvert[mf->v2].co);
1296                                 if (cp) glColor3ub(cp[11], cp[10], cp[9]);
1297                                 glVertex3fv(mvert[mf->v3].co);
1298                                 if(mf->v4) {
1299                                         if (cp) glColor3ub(cp[15], cp[14], cp[13]);
1300                                         glVertex3fv(mvert[mf->v4].co);
1301                                 }
1302                         } else {
1303                                 if (cp) glColor3ub(cp[3], cp[2], cp[1]);
1304                                 glNormal3sv(mvert[mf->v1].no);
1305                                 glVertex3fv(mvert[mf->v1].co);
1306                                 if (cp) glColor3ub(cp[7], cp[6], cp[5]);
1307                                 glNormal3sv(mvert[mf->v2].no);
1308                                 glVertex3fv(mvert[mf->v2].co);
1309                                 if (cp) glColor3ub(cp[11], cp[10], cp[9]);
1310                                 glNormal3sv(mvert[mf->v3].no);
1311                                 glVertex3fv(mvert[mf->v3].co);
1312                                 if(mf->v4) {
1313                                         if (cp) glColor3ub(cp[15], cp[14], cp[13]);
1314                                         glNormal3sv(mvert[mf->v4].no);
1315                                         glVertex3fv(mvert[mf->v4].co);
1316                                 }
1317                         }
1318
1319                         glEnd();
1320                 }
1321         }
1322 }
1323 static void ssDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
1324 {
1325         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1326         int i;
1327
1328         if (ssdm->dlm->totvert) {
1329                 for (i=0; i<ssdm->dlm->totvert; i++) {
1330                         DO_MINMAX(ssdm->dlm->mvert[i].co, min_r, max_r);
1331                 }
1332         } else {
1333                 min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
1334         }
1335 }
1336
1337 static void ssDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
1338 {
1339         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1340         int i;
1341
1342         for (i=0; i<ssdm->dlm->totvert; i++) {
1343                 cos_r[i][0] = ssdm->dlm->mvert[i].co[0];
1344                 cos_r[i][1] = ssdm->dlm->mvert[i].co[1];
1345                 cos_r[i][2] = ssdm->dlm->mvert[i].co[2];
1346         }
1347 }
1348
1349 static int ssDM_getNumVerts(DerivedMesh *dm)
1350 {
1351         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1352
1353         return ssdm->dlm->totvert;
1354 }
1355 static int ssDM_getNumFaces(DerivedMesh *dm)
1356 {
1357         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1358
1359         return ssdm->dlm->totface;
1360 }
1361
1362 static DispListMesh *ssDM_convertToDispListMesh(DerivedMesh *dm, int allowShared)
1363 {
1364         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1365
1366         if (allowShared) {
1367                 return displistmesh_copyShared(ssdm->dlm);
1368         } else {
1369                 return displistmesh_copy(ssdm->dlm);
1370         }
1371 }
1372
1373 static void ssDM_release(DerivedMesh *dm)
1374 {
1375         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1376
1377         displistmesh_free(ssdm->dlm);
1378
1379         MEM_freeN(dm);
1380 }
1381
1382 DerivedMesh *derivedmesh_from_displistmesh(DispListMesh *dlm, float (*vertexCos)[3])
1383 {
1384         SSDerivedMesh *ssdm = MEM_callocN(sizeof(*ssdm), "ssdm");
1385
1386         ssdm->dm.getMinMax = ssDM_getMinMax;
1387
1388         ssdm->dm.getNumVerts = ssDM_getNumVerts;
1389         ssdm->dm.getNumFaces = ssDM_getNumFaces;
1390         ssdm->dm.convertToDispListMesh = ssDM_convertToDispListMesh;
1391
1392         ssdm->dm.getVertCos = ssDM_getVertCos;
1393
1394         ssdm->dm.drawVerts = ssDM_drawVerts;
1395
1396         ssdm->dm.drawUVEdges = ssDM_drawUVEdges;
1397         ssdm->dm.drawEdges = ssDM_drawEdges;
1398         ssdm->dm.drawLooseEdges = ssDM_drawLooseEdges;
1399         
1400         ssdm->dm.drawFacesSolid = ssDM_drawFacesSolid;
1401         ssdm->dm.drawFacesColored = ssDM_drawFacesColored;
1402         ssdm->dm.drawFacesTex = ssDM_drawFacesTex;
1403         ssdm->dm.drawMappedFaces = ssDM_drawMappedFaces;
1404
1405                 /* EM functions */
1406         
1407         ssdm->dm.foreachMappedVert = ssDM_foreachMappedVert;
1408         ssdm->dm.foreachMappedEdge = ssDM_foreachMappedEdge;
1409         ssdm->dm.foreachMappedFaceCenter = ssDM_foreachMappedFaceCenter;
1410         
1411         ssdm->dm.drawMappedEdges = ssDM_drawMappedEdges;
1412         ssdm->dm.drawMappedEdgesInterp = NULL; // no way to implement this one
1413         
1414         ssdm->dm.release = ssDM_release;
1415         
1416         ssdm->dlm = dlm;
1417
1418         if (vertexCos) {
1419                 int i;
1420
1421                 for (i=0; i<dlm->totvert; i++) {
1422                         VECCOPY(dlm->mvert[i].co, vertexCos[i]);
1423                 }
1424
1425                 if (dlm->nors && !dlm->dontFreeNors) {
1426                         MEM_freeN(dlm->nors);
1427                         dlm->nors = 0;
1428                 }
1429
1430                 mesh_calc_normals(dlm->mvert, dlm->totvert, dlm->mface, dlm->totface, &dlm->nors);
1431         }
1432
1433         return (DerivedMesh*) ssdm;
1434 }
1435
1436 /***/
1437
1438
1439 DerivedMesh *mesh_create_derived_for_modifier(Object *ob, ModifierData *md)
1440 {
1441         Mesh *me = ob->data;
1442         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1443         DerivedMesh *dm;
1444
1445         if (!(md->mode&eModifierMode_Realtime)) return NULL;
1446         if (mti->isDisabled && mti->isDisabled(md)) return NULL;
1447
1448         if (mti->type==eModifierTypeType_OnlyDeform) {
1449                 int numVerts;
1450                 float (*deformedVerts)[3] = mesh_getVertexCos(me, &numVerts);
1451
1452                 mti->deformVerts(md, ob, NULL, deformedVerts, numVerts);
1453                 
1454                 dm = getMeshDerivedMesh(me, ob, deformedVerts);
1455                 MEM_freeN(deformedVerts);
1456         } else {
1457                 dm = mti->applyModifier(md, ob, NULL, NULL, 0, 0);
1458         }
1459
1460         return dm;
1461 }
1462
1463 static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], DerivedMesh **deform_r, DerivedMesh **final_r, int useRenderParams, int useDeform)
1464 {
1465         Mesh *me = ob->data;
1466         ModifierData *md= modifiers_getVirtualModifierList(ob);
1467         float (*deformedVerts)[3] = NULL;
1468         DerivedMesh *dm;
1469         int numVerts = me->totvert;
1470
1471         modifiers_clearErrors(ob);
1472
1473         if (deform_r) *deform_r = NULL;
1474         *final_r = NULL;
1475
1476         // N_T 
1477         if((G.obedit!=ob) && (ob->fluidsimFlag & OB_FLUIDSIM_ENABLE)) {
1478                 if(ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN) {
1479                         *final_r = getFluidsimDerivedMesh(ob,useRenderParams, NULL,NULL);                                       
1480                         if(*final_r) return;
1481                 }
1482         }
1483
1484         if (useDeform) {
1485                 do_mesh_key(me);
1486
1487                         /* Apply all leading deforming modifiers */
1488                 for (; md; md=md->next) {
1489                         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1490
1491                         if (!(md->mode&(1<<useRenderParams))) continue;
1492                         if (mti->isDisabled && mti->isDisabled(md)) continue;
1493
1494                         if (mti->type==eModifierTypeType_OnlyDeform) {
1495                                 if (!deformedVerts) deformedVerts = mesh_getVertexCos(me, &numVerts);
1496                                 mti->deformVerts(md, ob, NULL, deformedVerts, numVerts);
1497                         } else {
1498                                 break;
1499                         }
1500                 }
1501
1502                         /* Result of all leading deforming modifiers is cached for
1503                          * places that wish to use the original mesh but with deformed
1504                          * coordinates (vpaint, etc.)
1505                          */
1506                 if (deform_r) *deform_r = getMeshDerivedMesh(me, ob, deformedVerts);
1507         } else {
1508                 deformedVerts = inputVertexCos;
1509         }
1510
1511                 /* Now apply all remaining modifiers. If useDeform is off then skip
1512                  * OnlyDeform ones. 
1513                  */
1514         dm = NULL;
1515         for (; md; md=md->next) {
1516                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1517
1518                 if (!(md->mode&(1<<useRenderParams))) continue;
1519                 if (mti->type==eModifierTypeType_OnlyDeform && !useDeform) continue;
1520                 if ((mti->flags&eModifierTypeFlag_RequiresOriginalData) && dm) {
1521                         modifier_setError(md, "Internal error, modifier requires original data (bad stack position).");
1522                         continue;
1523                 }
1524                 if (mti->isDisabled && mti->isDisabled(md)) continue;
1525
1526                         /* How to apply modifier depends on (a) what we already have as
1527                          * a result of previous modifiers (could be a DerivedMesh or just
1528                          * deformed vertices) and (b) what type the modifier is.
1529                          */
1530
1531                 if (mti->type==eModifierTypeType_OnlyDeform) {
1532                                 /* No existing verts to deform, need to build them. */
1533                         if (!deformedVerts) {
1534                                 if (dm) {
1535                                                 /* Deforming a derived mesh, read the vertex locations out of the mesh and
1536                                                  * deform them. Once done with this run of deformers verts will be written back.
1537                                                  */
1538                                         numVerts = dm->getNumVerts(dm);
1539                                         deformedVerts = MEM_mallocN(sizeof(*deformedVerts)*numVerts, "dfmv");
1540                                         dm->getVertCos(dm, deformedVerts);
1541                                 } else {
1542                                         deformedVerts = mesh_getVertexCos(me, &numVerts);
1543                                 }
1544                         }
1545
1546                         mti->deformVerts(md, ob, dm, deformedVerts, numVerts);
1547                 } else {
1548                                 /* There are 4 cases here (have deform? have dm?) but they all are handled
1549                                  * by the modifier apply function, which will also free the DerivedMesh if
1550                                  * it exists.
1551                                  */
1552                         DerivedMesh *ndm = mti->applyModifier(md, ob, dm, deformedVerts, useRenderParams, !inputVertexCos);
1553
1554                         if (ndm) {
1555                                 if (dm) dm->release(dm);
1556
1557                                 dm = ndm;
1558
1559                                 if (deformedVerts) {
1560                                         if (deformedVerts!=inputVertexCos) {
1561                                                 MEM_freeN(deformedVerts);
1562                                         }
1563                                         deformedVerts = NULL;
1564                                 }
1565                         } 
1566                 }
1567         }
1568
1569                 /* Yay, we are done. If we have a DerivedMesh and deformed vertices need to apply
1570                  * these back onto the DerivedMesh. If we have no DerivedMesh then we need to build
1571                  * one.
1572                  */
1573         if (dm && deformedVerts) {
1574                 DispListMesh *dlm = dm->convertToDispListMesh(dm, 0);
1575
1576                 dm->release(dm);
1577
1578                 *final_r = derivedmesh_from_displistmesh(dlm, deformedVerts);
1579         } else if (dm) {
1580                 *final_r = dm;
1581         } else {
1582                 *final_r = getMeshDerivedMesh(me, ob, deformedVerts);
1583         }
1584
1585         if (deformedVerts && deformedVerts!=inputVertexCos) {
1586                 MEM_freeN(deformedVerts);
1587         }
1588 }
1589
1590 static vec3f *editmesh_getVertexCos(EditMesh *em, int *numVerts_r)
1591 {
1592         int i, numVerts = *numVerts_r = BLI_countlist(&em->verts);
1593         float (*cos)[3];
1594         EditVert *eve;
1595
1596         cos = MEM_mallocN(sizeof(*cos)*numVerts, "vertexcos");
1597         for (i=0,eve=em->verts.first; i<numVerts; i++,eve=eve->next) {
1598                 VECCOPY(cos[i], eve->co);
1599         }
1600
1601         return cos;
1602 }
1603
1604 static void editmesh_calc_modifiers(DerivedMesh **cage_r, DerivedMesh **final_r)
1605 {
1606         Object *ob = G.obedit;
1607         EditMesh *em = G.editMesh;
1608         ModifierData *md;
1609         float (*deformedVerts)[3] = NULL;
1610         DerivedMesh *dm;
1611         int i, numVerts, cageIndex = modifiers_getCageIndex(ob, NULL);
1612
1613         modifiers_clearErrors(ob);
1614
1615         if (cage_r && cageIndex==-1) {
1616                 *cage_r = getEditMeshDerivedMesh(em, NULL);
1617         }
1618
1619         dm = NULL;
1620         for (i=0,md= ob->modifiers.first; md; i++,md=md->next) {
1621                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1622
1623                 if (!(md->mode&eModifierMode_Realtime)) continue;
1624                 if (!(md->mode&eModifierMode_Editmode)) continue;
1625                 if ((mti->flags&eModifierTypeFlag_RequiresOriginalData) && dm) {
1626                         modifier_setError(md, "Internal error, modifier requires original data (bad stack position).");
1627                         continue;
1628                 }
1629                 if (mti->isDisabled && mti->isDisabled(md)) continue;
1630                 if (!(mti->flags&eModifierTypeFlag_SupportsEditmode)) continue;
1631
1632                         /* How to apply modifier depends on (a) what we already have as
1633                          * a result of previous modifiers (could be a DerivedMesh or just
1634                          * deformed vertices) and (b) what type the modifier is.
1635                          */
1636
1637                 if (mti->type==eModifierTypeType_OnlyDeform) {
1638                                 /* No existing verts to deform, need to build them. */
1639                         if (!deformedVerts) {
1640                                 if (dm) {
1641                                                 /* Deforming a derived mesh, read the vertex locations out of the mesh and
1642                                                  * deform them. Once done with this run of deformers verts will be written back.
1643                                                  */
1644                                         numVerts = dm->getNumVerts(dm);
1645                                         deformedVerts = MEM_mallocN(sizeof(*deformedVerts)*numVerts, "dfmv");
1646                                         dm->getVertCos(dm, deformedVerts);
1647                                 } else {
1648                                         deformedVerts = editmesh_getVertexCos(em, &numVerts);
1649                                 }
1650                         }
1651
1652                         mti->deformVertsEM(md, ob, em, dm, deformedVerts, numVerts);
1653                 } else {
1654                                 /* There are 4 cases here (have deform? have dm?) but they all are handled
1655                                  * by the modifier apply function, which will also free the DerivedMesh if
1656                                  * it exists.
1657                                  */
1658                         DerivedMesh *ndm = mti->applyModifierEM(md, ob, em, dm, deformedVerts);
1659
1660                         if (ndm) {
1661                                 if (dm && (!cage_r || dm!=*cage_r)) dm->release(dm);
1662
1663                                 dm = ndm;
1664
1665                                 if (deformedVerts) {
1666                                         MEM_freeN(deformedVerts);
1667                                         deformedVerts = NULL;
1668                                 }
1669                         }
1670                 }
1671
1672                 if (cage_r && i==cageIndex) {
1673                         if (dm && deformedVerts) {
1674                                 DispListMesh *dlm;
1675
1676                                 dlm = dm->convertToDispListMesh(dm, 0);
1677
1678                                 *cage_r = derivedmesh_from_displistmesh(dlm, deformedVerts);
1679                         } else if (dm) {
1680                                 *cage_r = dm;
1681                         } else {
1682                                 *cage_r = getEditMeshDerivedMesh(em, deformedVerts?MEM_dupallocN(deformedVerts):NULL);
1683                         }
1684                 }
1685         }
1686
1687                 /* Yay, we are done. If we have a DerivedMesh and deformed vertices need to apply
1688                  * these back onto the DerivedMesh. If we have no DerivedMesh then we need to build
1689                  * one.
1690                  */
1691         if (dm && deformedVerts) {
1692                 DispListMesh *dlm = dm->convertToDispListMesh(dm, 0);
1693
1694                 if (!cage_r || dm!=*cage_r) dm->release(dm);
1695
1696                 *final_r = derivedmesh_from_displistmesh(dlm, deformedVerts);
1697                 MEM_freeN(deformedVerts);
1698         } else if (dm) {
1699                 *final_r = dm;
1700         } else {
1701                 *final_r = getEditMeshDerivedMesh(em, deformedVerts);
1702         }
1703 }
1704
1705 /***/
1706
1707
1708         /* Something of a hack, at the moment deal with weightpaint
1709          * by tucking into colors during modifier eval, only in
1710          * wpaint mode. Works ok but need to make sure recalc
1711          * happens on enter/exit wpaint.
1712          */
1713
1714 static void weight_to_rgb(float input, float *fr, float *fg, float *fb)
1715 {
1716         float blend;
1717         
1718         blend= ((input/2.0f)+0.5f);
1719         
1720         if (input<=0.25f){      // blue->cyan
1721                 *fr= 0.0f;
1722                 *fg= blend*input*4.0f;
1723                 *fb= blend;
1724         }
1725         else if (input<=0.50f){ // cyan->green
1726                 *fr= 0.0f;
1727                 *fg= blend;
1728                 *fb= blend*(1.0f-((input-0.25f)*4.0f)); 
1729         }
1730         else if (input<=0.75){  // green->yellow
1731                 *fr= blend * ((input-0.50f)*4.0f);
1732                 *fg= blend;
1733                 *fb= 0.0f;
1734         }
1735         else if (input<=1.0){ // yellow->red
1736                 *fr= blend;
1737                 *fg= blend * (1.0f-((input-0.75f)*4.0f)); 
1738                 *fb= 0.0f;
1739         }
1740 }
1741 static void calc_weightpaint_vert_color(Object *ob, int vert, unsigned char *col)
1742 {
1743         Mesh *me = ob->data;
1744         float fr, fg, fb, input = 0.0f;
1745         int i;
1746
1747         if (me->dvert) {
1748                 for (i=0; i<me->dvert[vert].totweight; i++)
1749                         if (me->dvert[vert].dw[i].def_nr==ob->actdef-1)
1750                                 input+=me->dvert[vert].dw[i].weight;            
1751         }
1752
1753         CLAMP(input, 0.0f, 1.0f);
1754         
1755         weight_to_rgb(input, &fr, &fg, &fb);
1756         
1757         col[3] = (unsigned char)(fr * 255.0f);
1758         col[2] = (unsigned char)(fg * 255.0f);
1759         col[1] = (unsigned char)(fb * 255.0f);
1760         col[0] = 255;
1761 }
1762 static unsigned char *calc_weightpaint_colors(Object *ob) 
1763 {
1764         Mesh *me = ob->data;
1765         MFace *mf = me->mface;
1766         unsigned char *wtcol;
1767         int i;
1768         
1769         wtcol = MEM_callocN (sizeof (unsigned char) * me->totface*4*4, "weightmap");
1770         
1771         memset(wtcol, 0x55, sizeof (unsigned char) * me->totface*4*4);
1772         for (i=0; i<me->totface; i++, mf++){
1773                 calc_weightpaint_vert_color(ob, mf->v1, &wtcol[(i*4 + 0)*4]); 
1774                 calc_weightpaint_vert_color(ob, mf->v2, &wtcol[(i*4 + 1)*4]); 
1775                 calc_weightpaint_vert_color(ob, mf->v3, &wtcol[(i*4 + 2)*4]); 
1776                 if (mf->v4)
1777                         calc_weightpaint_vert_color(ob, mf->v4, &wtcol[(i*4 + 3)*4]); 
1778         }
1779         
1780         return wtcol;
1781 }
1782
1783 static void clear_mesh_caches(Object *ob)
1784 {
1785         Mesh *me= ob->data;
1786
1787                 /* also serves as signal to remake texspace */
1788         if (me->bb) {
1789                 MEM_freeN(me->bb);
1790                 me->bb = NULL;
1791         }
1792
1793         freedisplist(&ob->disp);
1794
1795         if (ob->derivedFinal) {
1796                 ob->derivedFinal->release(ob->derivedFinal);
1797                 ob->derivedFinal= NULL;
1798         }
1799         if (ob->derivedDeform) {
1800                 ob->derivedDeform->release(ob->derivedDeform);
1801                 ob->derivedDeform= NULL;
1802         }
1803 }
1804
1805 static void mesh_build_data(Object *ob)
1806 {
1807         Mesh *me = ob->data;
1808         float min[3], max[3];
1809
1810         if(ob->flag&OB_FROMDUPLI) return;
1811
1812         clear_mesh_caches(ob);
1813
1814         if( (G.f & G_WEIGHTPAINT)) {
1815                 MCol *mcol = me->mcol;
1816                 TFace *tface =  me->tface;
1817
1818                 me->tface = NULL;
1819                 me->mcol = (MCol*) calc_weightpaint_colors(ob);
1820
1821                 mesh_calc_modifiers(ob, NULL, &ob->derivedDeform, &ob->derivedFinal, 0, 1);
1822
1823                 MEM_freeN(me->mcol);
1824                 me->mcol = mcol;
1825                 me->tface = tface;
1826         } else {
1827                 mesh_calc_modifiers(ob, NULL, &ob->derivedDeform, &ob->derivedFinal, 0, 1);
1828         }
1829
1830         INIT_MINMAX(min, max);
1831
1832         ob->derivedFinal->getMinMax(ob->derivedFinal, min, max);
1833
1834         boundbox_set_from_min_max(mesh_get_bb(ob->data), min, max);
1835 }
1836
1837 static void editmesh_build_data(void)
1838 {
1839         float min[3], max[3];
1840
1841         EditMesh *em = G.editMesh;
1842
1843         clear_mesh_caches(G.obedit);
1844
1845         if (em->derivedFinal) {
1846                 if (em->derivedFinal!=em->derivedCage) {
1847                         em->derivedFinal->release(em->derivedFinal);
1848                 }
1849                 em->derivedFinal = NULL;
1850         }
1851         if (em->derivedCage) {
1852                 em->derivedCage->release(em->derivedCage);
1853                 em->derivedCage = NULL;
1854         }
1855
1856         editmesh_calc_modifiers(&em->derivedCage, &em->derivedFinal);
1857
1858         INIT_MINMAX(min, max);
1859
1860         em->derivedFinal->getMinMax(em->derivedFinal, min, max);
1861
1862         boundbox_set_from_min_max(mesh_get_bb(G.obedit->data), min, max);
1863 }
1864
1865 void makeDispListMesh(Object *ob)
1866 {
1867         if (ob==G.obedit) {
1868                 editmesh_build_data();
1869         } else {
1870                 mesh_build_data(ob);
1871
1872                 build_particle_system(ob);
1873         }
1874 }
1875
1876 /***/
1877
1878 DerivedMesh *mesh_get_derived_final(Object *ob, int *needsFree_r)
1879 {
1880         if (!ob->derivedFinal) {
1881                 mesh_build_data(ob);
1882         }
1883
1884         *needsFree_r = 0;
1885         return ob->derivedFinal;
1886 }
1887
1888 DerivedMesh *mesh_get_derived_deform(Object *ob, int *needsFree_r)
1889 {
1890         if (!ob->derivedDeform) {
1891                 mesh_build_data(ob);
1892         } 
1893
1894         *needsFree_r = 0;
1895         return ob->derivedDeform;
1896 }
1897
1898 DerivedMesh *mesh_create_derived_render(Object *ob)
1899 {
1900         DerivedMesh *final;
1901
1902         mesh_calc_modifiers(ob, NULL, NULL, &final, 1, 1);
1903
1904         return final;
1905 }
1906
1907 DerivedMesh *mesh_create_derived_no_deform(Object *ob, float (*vertCos)[3])
1908 {
1909         DerivedMesh *final;
1910
1911         mesh_calc_modifiers(ob, vertCos, NULL, &final, 0, 0);
1912
1913         return final;
1914 }
1915
1916 DerivedMesh *mesh_create_derived_no_deform_render(Object *ob, float (*vertCos)[3])
1917 {
1918         DerivedMesh *final;
1919
1920         mesh_calc_modifiers(ob, vertCos, NULL, &final, 1, 0);
1921
1922         return final;
1923 }
1924
1925 /***/
1926
1927 DerivedMesh *editmesh_get_derived_cage_and_final(DerivedMesh **final_r, int *cageNeedsFree_r, int *finalNeedsFree_r)
1928 {
1929         *cageNeedsFree_r = *finalNeedsFree_r = 0;
1930
1931         if (!G.editMesh->derivedCage)
1932                 editmesh_build_data();
1933
1934         *final_r = G.editMesh->derivedFinal;
1935         return G.editMesh->derivedCage;
1936 }
1937
1938 DerivedMesh *editmesh_get_derived_cage(int *needsFree_r)
1939 {
1940         *needsFree_r = 0;
1941
1942         if (!G.editMesh->derivedCage)
1943                 editmesh_build_data();
1944
1945         return G.editMesh->derivedCage;
1946 }
1947
1948 DerivedMesh *editmesh_get_derived_base(void)
1949 {
1950         return getEditMeshDerivedMesh(G.editMesh, NULL);
1951 }
1952
1953 // N_T fluidsim declarations
1954 typedef struct {
1955         MeshDerivedMesh mdm;
1956
1957         /* release whole mesh? */
1958         char freeMesh;
1959 } FluidsimDerivedMesh;
1960
1961
1962 /***/
1963 // N_T fluidsim interface
1964 #ifdef WIN32
1965 #ifndef snprintf
1966 #define snprintf _snprintf
1967 #endif
1968 #endif
1969
1970
1971 static void fluidsimDM_release(DerivedMesh *dm)
1972 {
1973         FluidsimDerivedMesh *fsdm = (FluidsimDerivedMesh*) dm;
1974         if(fsdm->freeMesh) {
1975                 // similar to free_mesh(fsdm->mdm.me) , but no things like unlink...
1976                 if(fsdm->mdm.me->mvert) MEM_freeN(fsdm->mdm.me->mvert);
1977                 if(fsdm->mdm.me->medge) MEM_freeN(fsdm->mdm.me->medge);
1978                 if(fsdm->mdm.me->mface) MEM_freeN(fsdm->mdm.me->mface);
1979                 MEM_freeN(fsdm->mdm.me);
1980         }
1981
1982         if (fsdm->mdm.freeNors) MEM_freeN(fsdm->mdm.nors);
1983         if (fsdm->mdm.freeVerts) MEM_freeN(fsdm->mdm.verts);
1984         MEM_freeN(fsdm);
1985 }
1986
1987 DerivedMesh *getFluidsimDerivedMesh(Object *srcob, int useRenderParams, float *extverts, float *nors) {
1988         //fprintf(stderr,"getFluidsimDerivedMesh call (obid '%s', rp %d)\n", srcob->id.name, useRenderParams); // debug
1989         int i;
1990         Mesh *mesh = NULL; // srcob->ata; 
1991         FluidsimDerivedMesh *fsdm;
1992         MeshDerivedMesh *mdm = NULL;
1993         float (*vertCos)[3];
1994         int displaymode = 0;
1995         int curFrame = G.scene->r.cfra - 1; /* start with 0 */
1996         char filename[FILE_MAXFILE],filepath[FILE_MAXFILE+FILE_MAXDIR];
1997         char curWd[FILE_MAXDIR];
1998
1999         if(!useRenderParams) {
2000                 displaymode = srcob->fluidsimSettings->guiDisplayMode;
2001         } else {
2002                 displaymode = srcob->fluidsimSettings->renderDisplayMode;
2003         }
2004         
2005         //fprintf(stderr,"getFluidsimDerivedMesh call (obid '%s', rp %d, dm %d)\n", srcob->id.name, useRenderParams, displaymode); // debug
2006         if((displaymode==1) || (G.obedit==srcob)) {
2007                 mesh = srcob->data;                     
2008                 return getMeshDerivedMesh(mesh , srcob, NULL);
2009         } 
2010
2011         // init preview frame
2012         if(displaymode==2) {
2013                 // use preview
2014                 snprintf(filename,FILE_MAXFILE,"%s_surface_preview_%04d.bobj.gz", srcob->fluidsimSettings->surfdataPrefix, curFrame);
2015         } else {
2016                 // load final mesh
2017                 snprintf(filename,FILE_MAXFILE,"%s_surface_final_%04d.bobj.gz", srcob->fluidsimSettings->surfdataPrefix, curFrame);
2018         }
2019         BLI_getwdN(curWd);
2020         BLI_make_file_string(G.sce, filepath, srcob->fluidsimSettings->surfdataDir, filename);
2021         
2022         //fprintf(stderr,"getFluidsimDerivedMesh call (obid '%s', rp %d, dm %d) %s \n", srcob->id.name, useRenderParams, displaymode, filepath); // debug
2023         mesh = readBobjgz(filepath, (Mesh*)(srcob->data) );
2024         if(!mesh) {
2025                 // display org. object upon failure
2026                 mesh = srcob->data;                     
2027                 return getMeshDerivedMesh(mesh , srcob, NULL);
2028         }
2029         if((mesh)&&(mesh->totvert>0)) {
2030                 make_edges(mesh, 0);    // 0 = make all edges draw
2031         }
2032
2033         // WARNING copied from getMeshDerivedMesh
2034         fsdm = MEM_callocN(sizeof(*fsdm), "getFluidsimDerivedMesh_fsdm");
2035         fsdm->freeMesh = 1;
2036         mdm = &fsdm->mdm;
2037         vertCos = NULL;
2038
2039         mdm->dm.getMinMax = meshDM_getMinMax;
2040         mdm->dm.convertToDispListMesh = meshDM_convertToDispListMesh;
2041         mdm->dm.getNumVerts = meshDM_getNumVerts;
2042         mdm->dm.getNumFaces = meshDM_getNumFaces;
2043         mdm->dm.getVertCos = meshDM_getVertCos;
2044         mdm->dm.getVertCo = meshDM_getVertCo;
2045         mdm->dm.getVertNo = meshDM_getVertNo;
2046         mdm->dm.drawVerts = meshDM_drawVerts;
2047         mdm->dm.drawUVEdges = meshDM_drawUVEdges;
2048         mdm->dm.drawEdges = meshDM_drawEdges;
2049         mdm->dm.drawLooseEdges = meshDM_drawLooseEdges;
2050         mdm->dm.drawFacesSolid = meshDM_drawFacesSolid;
2051         mdm->dm.drawFacesColored = meshDM_drawFacesColored;
2052         mdm->dm.drawFacesTex = meshDM_drawFacesTex;
2053         mdm->dm.drawMappedFaces = meshDM_drawMappedFaces;
2054         mdm->dm.drawMappedEdges = meshDM_drawMappedEdges;
2055         mdm->dm.drawMappedFaces = meshDM_drawMappedFaces;
2056
2057         // use own release function
2058         mdm->dm.release = fluidsimDM_release;
2059         
2060         mdm->ob = srcob;
2061         mdm->me = mesh;
2062         mdm->verts = mesh->mvert;
2063         mdm->nors = NULL;
2064         mdm->freeNors = 0;
2065         mdm->freeVerts = 0;
2066         
2067         //fprintf(stderr,"fsdm loc %f,%f,%f; size %f,%f,%f; rot %f,%f,%f \n",
2068                         //mesh->loc[0], mesh->loc[1], mesh->loc[2],
2069                         //mesh->size[0], mesh->size[1], mesh->size[2],
2070                         //mesh->rot[0], mesh->rot[1], mesh->rot[2]);
2071
2072         if (vertCos) {
2073                 int i;
2074
2075                 mdm->verts = MEM_mallocN(sizeof(*mdm->verts)*mdm->me->totvert, "deformedVerts");
2076                 for (i=0; i<mdm->me->totvert; i++) {
2077                         mdm->verts[i].co[0] = vertCos[i][0];
2078                         mdm->verts[i].co[1] = vertCos[i][1];
2079                         mdm->verts[i].co[2] = vertCos[i][2];
2080                 }
2081                 mesh_calc_normals(mdm->verts, mdm->me->totvert, mdm->me->mface, mdm->me->totface, &mdm->nors);
2082                 mdm->freeNors = 1;
2083                 mdm->freeVerts = 1;
2084         } else {
2085                 // XXX this is kinda ... see getMeshDerivedMesh
2086                 mesh_calc_normals(mdm->verts, mdm->me->totvert, mdm->me->mface, mdm->me->totface, &mdm->nors);
2087                 mdm->freeNors = 1;
2088         }
2089
2090         return (DerivedMesh*) mdm;
2091 }
2092
2093
2094 /* ***************************** bobj file handling ***************************** */
2095
2096 /* write .bobj.gz file for a mesh object */
2097
2098 void writeBobjgz(char *filename, struct Object *ob) 
2099 {
2100         int wri,i,j;
2101         float wrf;
2102         gzFile gzf;
2103         DispListMesh *dlm = NULL;
2104         DerivedMesh *dm;
2105         float vec[3];
2106         float rotmat[3][3];
2107         MFace *mface = NULL;
2108
2109         if(!ob->data || (ob->type!=OB_MESH)) {
2110                 fprintf(stderr,"Writing GZ_BOBJ Invalid object %s ...\n", ob->id.name); 
2111                 return;
2112         }
2113         if((ob->size[0]<0.0) || (ob->size[0]<0.0) || (ob->size[0]<0.0) ) {
2114                 fprintf(stderr,"\nfluidSim::writeBobjgz:: Warning object %s has negative scaling - check triangle ordering...?\n\n", ob->id.name); 
2115         }
2116
2117         fprintf(stderr,"Writing GZ_BOBJ '%s' ... ",filename);
2118         gzf = gzopen(filename, "wb9");
2119         if (!gzf) {
2120                 fprintf(stderr,"writeBobjgz::error - Unable to open file for writing '%s'\n", filename);
2121                 return;
2122         }
2123
2124         dm = mesh_create_derived_render(ob);
2125         dlm = dm->convertToDispListMesh(dm, 1);
2126         mface = dlm->mface;
2127
2128         if(sizeof(wri)!=4) { fprintf(stderr,"Writing GZ_BOBJ, Invalid int size %d...\n", wri); return; } // paranoia check
2129         wri = dlm->totvert;
2130         gzwrite(gzf, &wri, sizeof(wri));
2131         for(i=0; i<wri;i++) {
2132                 VECCOPY(vec, dlm->mvert[i].co); /* get transformed point */
2133                 Mat4MulVecfl(ob->obmat, vec);
2134                 //fprintf(stderr,"VTEST %d = %f,%f,%f\n",i,vec[0],vec[1],vec[2]); // DEBUG
2135                 for(j=0; j<3; j++) {
2136                         wrf = vec[j]; 
2137                         gzwrite(gzf, &wrf, sizeof( wrf )); 
2138                 }
2139         }
2140
2141         // should be the same as Vertices.size
2142         wri = dlm->totvert;
2143         gzwrite(gzf, &wri, sizeof(wri));
2144         EulToMat3(ob->rot, rotmat);
2145         for(i=0; i<wri;i++) {
2146                 VECCOPY(vec, dlm->mvert[i].no);
2147                 // FIXME divide? mv->no[0]= (short)(no[0]*32767.0);
2148                 Mat3MulVecfl(rotmat, vec); 
2149                 Normalise(vec);
2150                 //fprintf(stderr, "N %s normrot %d %f %f %f\n",ob->id.name,  i,vec[0],vec[1],vec[2]); // DEBUG
2151                 for(j=0; j<3; j++) {
2152                         wrf = vec[j]; //dlm->normals[i][j];
2153                         gzwrite(gzf, &wrf, sizeof( wrf )); 
2154                 }
2155         }
2156
2157         
2158         /* compute no. of triangles */
2159         wri = 0;
2160         for(i=0; i<dlm->totface; i++) {
2161                 wri++;
2162                 if(mface[i].v4) { wri++; }
2163         }
2164         gzwrite(gzf, &wri, sizeof(wri));
2165         for(i=0; i<dlm->totface; i++) {
2166
2167                 int face[4];
2168                 face[0] = mface[i].v1;
2169                 face[1] = mface[i].v2;
2170                 face[2] = mface[i].v3;
2171                 face[3] = mface[i].v4;
2172                 //fprintf(stderr,"F %s %d = %d,%d,%d,%d \n",ob->id.name, i, face[0],face[1],face[2],face[3] ); 
2173
2174                 gzwrite(gzf, &(face[0]), sizeof( face[0] )); 
2175                 gzwrite(gzf, &(face[1]), sizeof( face[1] )); 
2176                 gzwrite(gzf, &(face[2]), sizeof( face[2] )); 
2177                 if(face[3]) { 
2178                         gzwrite(gzf, &(face[0]), sizeof( face[0] )); 
2179                         gzwrite(gzf, &(face[2]), sizeof( face[2] )); 
2180                         gzwrite(gzf, &(face[3]), sizeof( face[3] )); 
2181                 }
2182         }
2183         
2184         gzclose( gzf );
2185         if(dlm) displistmesh_free(dlm);
2186         dm->release(dm);
2187
2188         //fprintf(stderr,"done. #Vertices: %d, #Normals: %d, #Triangles: %d\n", dlm->vertices.size(), dlm->normals.size(), dlm->faces.size() );
2189 }
2190
2191 /* security macro for readgin bobjs */
2192 #define CHECK_GOTBYTES(b,s) \
2193         if((b)!=4) { \
2194                 if(newmesh->mvert) MEM_freeN(newmesh->mvert); \
2195                 if(newmesh->mface) MEM_freeN(newmesh->mface); \
2196                 if(newmesh) MEM_freeN(newmesh); \
2197                 return NULL; \
2198         }
2199 /* read .bobj.gz file into a fluidsimDerivedMesh struct */
2200 Mesh* readBobjgz(char *filename, Mesh *orgmesh) //, fluidsimDerivedMesh *fsdm)
2201 {
2202         int wri,i,j;
2203         float wrf;
2204         gzFile gzf;
2205         Mesh *newmesh; 
2206         const int debugOutput = 0;
2207         // init data from old mesh (materials,flags)
2208         MFace *origMFace = &((MFace*) orgmesh->mface)[0];
2209         int mat_nr = origMFace->mat_nr;
2210         int flag = origMFace->flag;
2211         MFace *fsface = NULL;
2212         int gotBytes;
2213
2214         if(!orgmesh) return NULL;
2215
2216         // similar to copy_mesh
2217         newmesh = MEM_dupallocN(orgmesh);
2218         newmesh->mat= orgmesh->mat; //MEM_dupallocN(orgmesh->mat); // use original?
2219
2220         newmesh->mvert= NULL;
2221         newmesh->medge= NULL;
2222         newmesh->mface= NULL;
2223         newmesh->tface= NULL;
2224         newmesh->dface= NULL;
2225
2226         newmesh->dvert = NULL; //MEM_mallocN (sizeof (MDeformVert)*orgmesh->totvert, "MDeformVert");
2227
2228         newmesh->mcol= NULL; //MEM_dupallocN(orgmesh->mcol);
2229         newmesh->msticky= NULL; //MEM_dupallocN(orgmesh->msticky);
2230         newmesh->texcomesh= NULL;
2231
2232         newmesh->key= NULL; //copy_key(orgmesh->key);
2233         newmesh->totface = 0;
2234         newmesh->totvert = 0;
2235         newmesh->totedge = 0;
2236         newmesh->medge = NULL; //? MEM_mallocN(sizeof(MEdge)*fsdm->fstotedge, "fluidsimDerivedMesh_edges");
2237
2238
2239         if(debugOutput) fprintf(stderr,"Reading '%s' GZ_BOBJ... ",filename);
2240         gzf = gzopen(filename, "rb");
2241         if (!gzf) {
2242                 //fprintf(stderr,"readBobjgz::error - Unable to open file for reading '%s'\n", filename); // DEBUG
2243                 MEM_freeN(newmesh);
2244                 return NULL;
2245         }
2246
2247         //if(sizeof(wri)!=4) { fprintf(stderr,"Reading GZ_BOBJ, Invalid int size %d...\n", wri); return NULL; } // paranoia check
2248
2249         gotBytes = gzread(gzf, &wri, sizeof(wri));
2250         CHECK_GOTBYTES(gotBytes, "numverts");
2251         newmesh->totvert = wri;
2252         newmesh->mvert = MEM_mallocN(sizeof(MVert)*newmesh->totvert, "fluidsimDerivedMesh_bobjvertices");
2253         if(debugOutput) fprintf(stderr,"#vertices %d ", newmesh->totvert); //DEBUG
2254         for(i=0; i<newmesh->totvert;i++) {
2255                 for(j=0; j<3; j++) {
2256                         gotBytes = gzread(gzf, &wrf, sizeof( wrf )); 
2257                         CHECK_GOTBYTES(gotBytes, "vert");
2258                         newmesh->mvert[i].co[j] = wrf;
2259                 }
2260                 //fprintf(stderr,"VTEST %d = %f,%f,%f\n",i,newmesh->mvert[i].co[0],newmesh->mvert[i].co[1],newmesh->mvert[i].co[2]); // DEBUG
2261         }
2262
2263         // should be the same as Vertices.size
2264         gotBytes = gzread(gzf, &wri, sizeof(wri));
2265         CHECK_GOTBYTES(gotBytes, "numnorms");
2266         if(wri != newmesh->totvert) {
2267                 // complain #vertices has to be equal to #normals, reset&abort
2268                 MEM_freeN(newmesh->mvert);
2269                 MEM_freeN(newmesh);
2270                 fprintf(stderr,"Reading GZ_BOBJ, #normals=%d, #vertices=%d, aborting...\n", wri,newmesh->totvert );
2271                 return NULL;
2272         }
2273         for(i=0; i<newmesh->totvert;i++) {
2274                 for(j=0; j<3; j++) {
2275                         gotBytes = gzread(gzf, &wrf, sizeof( wrf )); 
2276                         CHECK_GOTBYTES(gotBytes, "norm");
2277                         newmesh->mvert[i].no[j] = wrf*32767.0;
2278                 }
2279         }
2280
2281         
2282         /* compute no. of triangles */
2283         gotBytes = gzread(gzf, &wri, sizeof(wri));
2284         CHECK_GOTBYTES(gotBytes, "numfaces");
2285         newmesh->totface = wri;
2286         newmesh->mface = MEM_mallocN(sizeof(MFace)*newmesh->totface, "fluidsimDerivedMesh_bobjfaces");
2287         if(debugOutput) fprintf(stderr,"#faces %d ", newmesh->totface); // DEBUG
2288         fsface = newmesh->mface;
2289         for(i=0; i<newmesh->totface; i++) {
2290                 int face[4];
2291
2292                 gotBytes = gzread(gzf, &(face[0]), sizeof( face[0] )); 
2293                 CHECK_GOTBYTES(gotBytes, "f1");
2294                 gotBytes = gzread(gzf, &(face[1]), sizeof( face[1] )); 
2295                 CHECK_GOTBYTES(gotBytes, "f2");
2296                 gotBytes = gzread(gzf, &(face[2]), sizeof( face[2] )); 
2297                 CHECK_GOTBYTES(gotBytes, "f3");
2298                 face[3] = 0;
2299
2300                 fsface[i].v1 = face[0];
2301                 fsface[i].v2 = face[1];
2302                 fsface[i].v3 = face[2];
2303                 fsface[i].v4 = face[3];
2304                 //fprintf(stderr,"F %s %d = %d,%d,%d,%d \n",newmesh->ob->id.name, i, face[0],face[1],face[2],face[3] ); 
2305         }
2306         
2307         gzclose( gzf );
2308
2309         for(i=0;i<newmesh->totface;i++) { 
2310                 fsface[i].mat_nr = mat_nr;
2311                 fsface[i].flag = flag;
2312         }
2313
2314 //      if(debugOutput) fprintf(stderr," done\n");
2315         return newmesh;
2316 }
2317