Orange; merger with bf-blender.
[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 = (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) && ob==(G.scene->basact?G.scene->basact->object:NULL)) {
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                 /* copy the original verts to preserve flag settings; if this is too
562                  * costly, must at least use MEM_callocN to clear flags */
563                 mdm->verts = MEM_dupallocN( me->mvert );
564                 for (i=0; i<me->totvert; i++) {
565                         VECCOPY(mdm->verts[i].co, vertCos[i]);
566                 }
567                 mesh_calc_normals(mdm->verts, me->totvert, me->mface, me->totface, &mdm->nors);
568                 mdm->freeNors = 1;
569                 mdm->freeVerts = 1;
570         } else {
571                         // XXX this is kinda hacky because we shouldn't really be editing
572                         // the mesh here, however, we can't just call mesh_build_faceNormals(ob)
573                         // because in the case when a key is applied to a mesh the vertex normals
574                         // would never be correctly computed.
575                 mesh_calc_normals(mdm->verts, me->totvert, me->mface, me->totface, &mdm->nors);
576                 mdm->freeNors = 1;
577         }
578
579         return (DerivedMesh*) mdm;
580 }
581
582 ///
583
584 typedef struct {
585         DerivedMesh dm;
586
587         EditMesh *em;
588         float (*vertexCos)[3];
589         float (*vertexNos)[3];
590         float (*faceNos)[3];
591 } EditMeshDerivedMesh;
592
593 static void emDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData)
594 {
595         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
596         EditVert *eve;
597         int i;
598
599         for (i=0,eve= emdm->em->verts.first; eve; i++,eve=eve->next) {
600                 if (emdm->vertexCos) {
601                         func(userData, i, emdm->vertexCos[i], emdm->vertexNos[i], NULL);
602                 } else {
603                         func(userData, i, eve->co, eve->no, NULL);
604                 }
605         }
606 }
607 static void emDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData)
608 {
609         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
610         EditEdge *eed;
611         int i;
612
613         if (emdm->vertexCos) {
614                 EditVert *eve, *preveve;
615
616                 for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
617                         eve->prev = (EditVert*) i++;
618                 for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next)
619                         func(userData, i, emdm->vertexCos[(int) eed->v1->prev], emdm->vertexCos[(int) eed->v2->prev]);
620                 for (preveve=NULL, eve=emdm->em->verts.first; eve; preveve=eve, eve= eve->next)
621                         eve->prev = preveve;
622         } else {
623                 for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next)
624                         func(userData, i, eed->v1->co, eed->v2->co);
625         }
626 }
627 static void emDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) 
628 {
629         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
630         EditEdge *eed;
631         int i;
632
633         if (emdm->vertexCos) {
634                 EditVert *eve, *preveve;
635
636                 for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
637                         eve->prev = (EditVert*) i++;
638
639                 glBegin(GL_LINES);
640                 for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
641                         if(!setDrawOptions || setDrawOptions(userData, i)) {
642                                 glVertex3fv(emdm->vertexCos[(int) eed->v1->prev]);
643                                 glVertex3fv(emdm->vertexCos[(int) eed->v2->prev]);
644                         }
645                 }
646                 glEnd();
647
648                 for (preveve=NULL, eve=emdm->em->verts.first; eve; preveve=eve, eve= eve->next)
649                         eve->prev = preveve;
650         } else {
651                 glBegin(GL_LINES);
652                 for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
653                         if(!setDrawOptions || setDrawOptions(userData, i)) {
654                                 glVertex3fv(eed->v1->co);
655                                 glVertex3fv(eed->v2->co);
656                         }
657                 }
658                 glEnd();
659         }
660 }
661 static void emDM_drawEdges(DerivedMesh *dm, int drawLooseEdges)
662 {
663         emDM_drawMappedEdges(dm, NULL, NULL);
664 }
665 static void emDM_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void (*setDrawInterpOptions)(void *userData, int index, float t), void *userData) 
666 {
667         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
668         EditEdge *eed;
669         int i;
670
671         if (emdm->vertexCos) {
672                 EditVert *eve, *preveve;
673
674                 for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
675                         eve->prev = (EditVert*) i++;
676
677                 glBegin(GL_LINES);
678                 for (i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
679                         if(!setDrawOptions || setDrawOptions(userData, i)) {
680                                 setDrawInterpOptions(userData, i, 0.0);
681                                 glVertex3fv(emdm->vertexCos[(int) eed->v1->prev]);
682                                 setDrawInterpOptions(userData, i, 1.0);
683                                 glVertex3fv(emdm->vertexCos[(int) eed->v2->prev]);
684                         }
685                 }
686                 glEnd();
687
688                 for (preveve=NULL, eve=emdm->em->verts.first; eve; preveve=eve, eve= eve->next)
689                         eve->prev = preveve;
690         } else {
691                 glBegin(GL_LINES);
692                 for (i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
693                         if(!setDrawOptions || setDrawOptions(userData, i)) {
694                                 setDrawInterpOptions(userData, i, 0.0);
695                                 glVertex3fv(eed->v1->co);
696                                 setDrawInterpOptions(userData, i, 1.0);
697                                 glVertex3fv(eed->v2->co);
698                         }
699                 }
700                 glEnd();
701         }
702 }
703 static void emDM__calcFaceCent(EditFace *efa, float cent[3], float (*vertexCos)[3])
704 {
705         if (vertexCos) {
706                 VECCOPY(cent, vertexCos[(int) efa->v1->prev]);
707                 VecAddf(cent, cent, vertexCos[(int) efa->v2->prev]);
708                 VecAddf(cent, cent, vertexCos[(int) efa->v3->prev]);
709                 if (efa->v4) VecAddf(cent, cent, vertexCos[(int) efa->v4->prev]);
710         } else {
711                 VECCOPY(cent, efa->v1->co);
712                 VecAddf(cent, cent, efa->v2->co);
713                 VecAddf(cent, cent, efa->v3->co);
714                 if (efa->v4) VecAddf(cent, cent, efa->v4->co);
715         }
716
717         if (efa->v4) {
718                 VecMulf(cent, 0.25f);
719         } else {
720                 VecMulf(cent, 0.33333333333f);
721         }
722 }
723 static void emDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData)
724 {
725         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
726         EditVert *eve, *preveve;
727         EditFace *efa;
728         float cent[3];
729         int i;
730
731         if (emdm->vertexCos) {
732                 for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
733                         eve->prev = (EditVert*) i++;
734         }
735
736         for(i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) {
737                 emDM__calcFaceCent(efa, cent, emdm->vertexCos);
738                 func(userData, i, cent, emdm->vertexCos?emdm->faceNos[i]:efa->n);
739         }
740
741         if (emdm->vertexCos) {
742                 for (preveve=NULL, eve=emdm->em->verts.first; eve; preveve=eve, eve= eve->next)
743                         eve->prev = preveve;
744         }
745 }
746 static void emDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors)
747 {
748         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
749         EditFace *efa;
750         int i;
751
752         if (emdm->vertexCos) {
753                 EditVert *eve, *preveve;
754                 int drawSmooth = 1;
755
756                 for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
757                         eve->prev = (EditVert*) i++;
758
759                 for (i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) {
760                         if(!setDrawOptions || setDrawOptions(userData, i, &drawSmooth)) {
761                                 glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
762
763                                 glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
764                                 if (!drawSmooth) {
765                                         glNormal3fv(emdm->faceNos[i]);
766                                         glVertex3fv(emdm->vertexCos[(int) efa->v1->prev]);
767                                         glVertex3fv(emdm->vertexCos[(int) efa->v2->prev]);
768                                         glVertex3fv(emdm->vertexCos[(int) efa->v3->prev]);
769                                         if(efa->v4) glVertex3fv(emdm->vertexCos[(int) efa->v4->prev]);
770                                 } else {
771                                         glNormal3fv(emdm->vertexNos[(int) efa->v1->prev]);
772                                         glVertex3fv(emdm->vertexCos[(int) efa->v1->prev]);
773                                         glNormal3fv(emdm->vertexNos[(int) efa->v2->prev]);
774                                         glVertex3fv(emdm->vertexCos[(int) efa->v2->prev]);
775                                         glNormal3fv(emdm->vertexNos[(int) efa->v3->prev]);
776                                         glVertex3fv(emdm->vertexCos[(int) efa->v3->prev]);
777                                         if(efa->v4) {
778                                                 glNormal3fv(emdm->vertexNos[(int) efa->v4->prev]);
779                                                 glVertex3fv(emdm->vertexCos[(int) efa->v4->prev]);
780                                         }
781                                 }
782                                 glEnd();
783                         }
784                 }
785
786                 for (preveve=NULL, eve=emdm->em->verts.first; eve; preveve=eve, eve= eve->next)
787                         eve->prev = preveve;
788         } else {
789                 int drawSmooth = 1;
790
791                 for (i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) {
792                         if(!setDrawOptions || setDrawOptions(userData, i, &drawSmooth)) {
793                                 glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
794
795                                 glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
796                                 if (!drawSmooth) {
797                                         glNormal3fv(efa->n);
798                                         glVertex3fv(efa->v1->co);
799                                         glVertex3fv(efa->v2->co);
800                                         glVertex3fv(efa->v3->co);
801                                         if(efa->v4) glVertex3fv(efa->v4->co);
802                                 } else {
803                                         glNormal3fv(efa->v1->no);
804                                         glVertex3fv(efa->v1->co);
805                                         glNormal3fv(efa->v2->no);
806                                         glVertex3fv(efa->v2->co);
807                                         glNormal3fv(efa->v3->no);
808                                         glVertex3fv(efa->v3->co);
809                                         if(efa->v4) {
810                                                 glNormal3fv(efa->v4->no);
811                                                 glVertex3fv(efa->v4->co);
812                                         }
813                                 }
814                                 glEnd();
815                         }
816                 }
817         }
818 }
819
820 static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
821 {
822         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
823         EditVert *eve;
824         int i;
825
826         if (emdm->em->verts.first) {
827                 for (i=0,eve= emdm->em->verts.first; eve; i++,eve= eve->next) {
828                         if (emdm->vertexCos) {
829                                 DO_MINMAX(emdm->vertexCos[i], min_r, max_r);
830                         } else {
831                                 DO_MINMAX(eve->co, min_r, max_r);
832                         }
833                 }
834         } else {
835                 min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
836         }
837 }
838 static int emDM_getNumVerts(DerivedMesh *dm)
839 {
840         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
841
842         return BLI_countlist(&emdm->em->verts);
843 }
844 static int emDM_getNumFaces(DerivedMesh *dm)
845 {
846         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
847
848         return BLI_countlist(&emdm->em->faces);
849 }
850
851 static void emDM_release(DerivedMesh *dm)
852 {
853         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
854
855         if (emdm->vertexCos) {
856                 MEM_freeN(emdm->vertexCos);
857                 MEM_freeN(emdm->vertexNos);
858                 MEM_freeN(emdm->faceNos);
859         }
860
861         MEM_freeN(emdm);
862 }
863
864 static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em, float (*vertexCos)[3])
865 {
866         EditMeshDerivedMesh *emdm = MEM_callocN(sizeof(*emdm), "emdm");
867
868         emdm->dm.getMinMax = emDM_getMinMax;
869
870         emdm->dm.getNumVerts = emDM_getNumVerts;
871         emdm->dm.getNumFaces = emDM_getNumFaces;
872         emdm->dm.foreachMappedVert = emDM_foreachMappedVert;
873         emdm->dm.foreachMappedEdge = emDM_foreachMappedEdge;
874         emdm->dm.foreachMappedFaceCenter = emDM_foreachMappedFaceCenter;
875
876         emdm->dm.drawEdges = emDM_drawEdges;
877         emdm->dm.drawMappedEdges = emDM_drawMappedEdges;
878         emdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp;
879         emdm->dm.drawMappedFaces = emDM_drawMappedFaces;
880
881         emdm->dm.release = emDM_release;
882         
883         emdm->em = em;
884         emdm->vertexCos = vertexCos;
885
886         if (vertexCos) {
887                 EditVert *eve, *preveve;
888                 EditFace *efa;
889                 int totface = BLI_countlist(&em->faces);
890                 int i;
891
892                 for (i=0,eve=em->verts.first; eve; eve= eve->next)
893                         eve->prev = (EditVert*) i++;
894
895                 emdm->vertexNos = MEM_callocN(sizeof(*emdm->vertexNos)*i, "emdm_vno");
896                 emdm->faceNos = MEM_mallocN(sizeof(*emdm->faceNos)*totface, "emdm_vno");
897
898                 for(i=0, efa= em->faces.first; efa; i++, efa=efa->next) {
899                         float *v1 = vertexCos[(int) efa->v1->prev];
900                         float *v2 = vertexCos[(int) efa->v2->prev];
901                         float *v3 = vertexCos[(int) efa->v3->prev];
902                         float *no = emdm->faceNos[i];
903                         
904                         if(efa->v4) {
905                                 float *v4 = vertexCos[(int) efa->v3->prev];
906
907                                 CalcNormFloat4(v1, v2, v3, v4, no);
908                                 VecAddf(emdm->vertexNos[(int) efa->v4->prev], emdm->vertexNos[(int) efa->v4->prev], no);
909                         }
910                         else {
911                                 CalcNormFloat(v1, v2, v3, no);
912                         }
913
914                         VecAddf(emdm->vertexNos[(int) efa->v1->prev], emdm->vertexNos[(int) efa->v1->prev], no);
915                         VecAddf(emdm->vertexNos[(int) efa->v2->prev], emdm->vertexNos[(int) efa->v2->prev], no);
916                         VecAddf(emdm->vertexNos[(int) efa->v3->prev], emdm->vertexNos[(int) efa->v3->prev], no);
917                 }
918
919                 for(i=0, eve= em->verts.first; eve; i++, eve=eve->next) {
920                         float *no = emdm->vertexNos[i];
921
922                         if (Normalise(no)==0.0) {
923                                 VECCOPY(no, vertexCos[i]);
924                                 Normalise(no);
925                         }
926                 }
927
928                 for (preveve=NULL, eve=emdm->em->verts.first; eve; preveve=eve, eve= eve->next)
929                         eve->prev = preveve;
930         }
931
932         return (DerivedMesh*) emdm;
933 }
934
935 ///
936
937 typedef struct {
938         DerivedMesh dm;
939
940         DispListMesh *dlm;
941 } SSDerivedMesh;
942
943 static void ssDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData)
944 {
945         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
946         DispListMesh *dlm = ssdm->dlm;
947         int i, index=-1;
948
949         for (i=0; i<dlm->totvert; i++) {
950                 MVert *mv = &dlm->mvert[i];
951
952                 if (mv->flag&ME_VERT_STEPINDEX) {
953                         index++;
954
955                         func(userData, index, mv->co, NULL, mv->no);
956                 }
957         }
958 }
959 static void ssDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData)
960 {
961         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
962         DispListMesh *dlm = ssdm->dlm;
963         int i, index=-1;
964
965         for (i=0; i<dlm->totedge; i++) {
966                 MEdge *med = &dlm->medge[i];
967
968                 if (med->flag&ME_EDGE_STEPINDEX) index++;
969
970                 if (index!=-1) {
971                         func(userData, index, dlm->mvert[med->v1].co, dlm->mvert[med->v2].co);
972                 }
973         }
974 }
975 static void ssDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) 
976 {
977         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
978         DispListMesh *dlm = ssdm->dlm;
979         int i, index=-1;
980
981         glBegin(GL_LINES);
982         for(i=0; i<dlm->totedge; i++) {
983                 MEdge *med = &dlm->medge[i];
984
985                 if (med->flag&ME_EDGE_STEPINDEX) index++;
986
987                 if (index!=-1 && (!setDrawOptions || setDrawOptions(userData, index))) {
988                         glVertex3fv(dlm->mvert[med->v1].co);
989                         glVertex3fv(dlm->mvert[med->v2].co);
990                 }
991         }
992         glEnd();
993 }
994
995 static void ssDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData)
996 {
997         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
998         DispListMesh *dlm = ssdm->dlm;
999         int i, index=-1;
1000
1001         for (i=0; i<dlm->totface; i++) {
1002                 MFace *mf = &dlm->mface[i];
1003
1004                 if (mf->flag&ME_FACE_STEPINDEX) index++;
1005
1006                 if(index!=-1) {
1007                         float cent[3];
1008                         float no[3];
1009
1010                         VECCOPY(cent, dlm->mvert[mf->v1].co);
1011                         VecAddf(cent, cent, dlm->mvert[mf->v2].co);
1012                         VecAddf(cent, cent, dlm->mvert[mf->v3].co);
1013
1014                         if (mf->v4) {
1015                                 CalcNormFloat4(dlm->mvert[mf->v1].co, dlm->mvert[mf->v2].co, dlm->mvert[mf->v3].co, dlm->mvert[mf->v4].co, no);
1016                                 VecAddf(cent, cent, dlm->mvert[mf->v4].co);
1017                                 VecMulf(cent, 0.25f);
1018                         } else {
1019                                 CalcNormFloat(dlm->mvert[mf->v1].co, dlm->mvert[mf->v2].co, dlm->mvert[mf->v3].co, no);
1020                                 VecMulf(cent, 0.33333333333f);
1021                         }
1022
1023                         func(userData, index, cent, no);
1024                 }
1025         }
1026 }
1027 static void ssDM_drawVerts(DerivedMesh *dm)
1028 {
1029         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1030         DispListMesh *dlm = ssdm->dlm;
1031         MVert *mvert= dlm->mvert;
1032         int i;
1033
1034         bglBegin(GL_POINTS);
1035         for (i=0; i<dlm->totvert; i++) {
1036                 bglVertex3fv(mvert[i].co);
1037         }
1038         bglEnd();
1039 }
1040 static void ssDM_drawUVEdges(DerivedMesh *dm)
1041 {
1042         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1043         DispListMesh *dlm = ssdm->dlm;
1044         int i;
1045
1046         if (dlm->tface) {
1047                 glBegin(GL_LINES);
1048                 for (i=0; i<dlm->totface; i++) {
1049                         TFace *tf = &dlm->tface[i];
1050
1051                         if (!(tf->flag&TF_HIDE)) {
1052                                 glVertex2fv(tf->uv[0]);
1053                                 glVertex2fv(tf->uv[1]);
1054
1055                                 glVertex2fv(tf->uv[1]);
1056                                 glVertex2fv(tf->uv[2]);
1057
1058                                 if (!dlm->mface[i].v4) {
1059                                         glVertex2fv(tf->uv[2]);
1060                                         glVertex2fv(tf->uv[0]);
1061                                 } else {
1062                                         glVertex2fv(tf->uv[2]);
1063                                         glVertex2fv(tf->uv[3]);
1064
1065                                         glVertex2fv(tf->uv[3]);
1066                                         glVertex2fv(tf->uv[0]);
1067                                 }
1068                         }
1069                 }
1070                 glEnd();
1071         }
1072 }
1073 static void ssDM_drawLooseEdges(DerivedMesh *dm) 
1074 {
1075         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1076         DispListMesh *dlm = ssdm->dlm;
1077         MVert *mvert = dlm->mvert;
1078         MEdge *medge= dlm->medge;
1079         int i;
1080
1081         glBegin(GL_LINES);
1082         for (i=0; i<dlm->totedge; i++, medge++) {
1083                 if (medge->flag&ME_LOOSEEDGE) {
1084                         glVertex3fv(mvert[medge->v1].co); 
1085                         glVertex3fv(mvert[medge->v2].co);
1086                 }
1087         }
1088         glEnd();
1089 }
1090 static void ssDM_drawEdges(DerivedMesh *dm, int drawLooseEdges) 
1091 {
1092         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1093         DispListMesh *dlm = ssdm->dlm;
1094         MVert *mvert= dlm->mvert;
1095         MEdge *medge= dlm->medge;
1096         int i;
1097         
1098         glBegin(GL_LINES);
1099         for (i=0; i<dlm->totedge; i++, medge++) {
1100                 if ((medge->flag&ME_EDGEDRAW) && (drawLooseEdges || !(medge->flag&ME_LOOSEEDGE))) {
1101                         glVertex3fv(mvert[medge->v1].co); 
1102                         glVertex3fv(mvert[medge->v2].co);
1103                 }
1104         }
1105         glEnd();
1106 }
1107 static void ssDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int))
1108 {
1109         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1110         DispListMesh *dlm = ssdm->dlm;
1111         float *nors = dlm->nors;
1112         int glmode=-1, shademodel=-1, matnr=-1, drawCurrentMat=1;
1113         int i;
1114
1115 #define PASSVERT(ind) {                                         \
1116         if (shademodel==GL_SMOOTH)                              \
1117                 glNormal3sv(dlm->mvert[(ind)].no);      \
1118         glVertex3fv(dlm->mvert[(ind)].co);              \
1119 }
1120
1121         glBegin(glmode=GL_QUADS);
1122         for (i=0; i<dlm->totface; i++) {
1123                 MFace *mf= &dlm->mface[i];
1124                 int new_glmode = mf->v4?GL_QUADS:GL_TRIANGLES;
1125                 int new_shademodel = (mf->flag&ME_SMOOTH)?GL_SMOOTH:GL_FLAT;
1126                 int new_matnr = mf->mat_nr+1;
1127                 
1128                 if(new_glmode!=glmode || new_shademodel!=shademodel || new_matnr!=matnr) {
1129                         glEnd();
1130
1131                         drawCurrentMat = setMaterial(matnr=new_matnr);
1132
1133                         glShadeModel(shademodel=new_shademodel);
1134                         glBegin(glmode=new_glmode);
1135                 }
1136                 
1137                 if (drawCurrentMat) {
1138                         if (shademodel==GL_FLAT)
1139                                 glNormal3fv(&nors[i*3]);
1140                                 
1141                         PASSVERT(mf->v1);
1142                         PASSVERT(mf->v2);
1143                         PASSVERT(mf->v3);
1144                         if (mf->v4)
1145                                 PASSVERT(mf->v4);
1146                 }
1147         }
1148         glEnd();
1149         
1150 #undef PASSVERT
1151 }
1152 static void ssDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *vcols1, unsigned char *vcols2)
1153 {
1154         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1155         DispListMesh *dlm = ssdm->dlm;
1156         int i, lmode;
1157         
1158         glShadeModel(GL_SMOOTH);
1159         if (vcols2) {
1160                 glEnable(GL_CULL_FACE);
1161         } else {
1162                 useTwoSided = 0;
1163         }
1164                 
1165 #define PASSVERT(vidx, fidx) {                                  \
1166         unsigned char *col= &colbase[fidx*4];           \
1167         glColor3ub(col[3], col[2], col[1]);                     \
1168         glVertex3fv(dlm->mvert[(vidx)].co);                     \
1169 }
1170
1171         glBegin(lmode= GL_QUADS);
1172         for (i=0; i<dlm->totface; i++) {
1173                 MFace *mf= &dlm->mface[i];
1174                 int nmode= mf->v4?GL_QUADS:GL_TRIANGLES;
1175                 unsigned char *colbase= &vcols1[i*16];
1176                 
1177                 if (nmode!=lmode) {
1178                         glEnd();
1179                         glBegin(lmode= nmode);
1180                 }
1181                 
1182                 PASSVERT(mf->v1, 0);
1183                 PASSVERT(mf->v2, 1);
1184                 PASSVERT(mf->v3, 2);
1185                 if (mf->v4)
1186                         PASSVERT(mf->v4, 3);
1187                 
1188                 if (useTwoSided) {
1189                         unsigned char *colbase= &vcols2[i*16];
1190
1191                         if (mf->v4)
1192                                 PASSVERT(mf->v4, 3);
1193                         PASSVERT(mf->v3, 2);
1194                         PASSVERT(mf->v2, 1);
1195                         PASSVERT(mf->v1, 0);
1196                 }
1197         }
1198         glEnd();
1199
1200         if (vcols2)
1201                 glDisable(GL_CULL_FACE);
1202         
1203 #undef PASSVERT
1204 }
1205 static void ssDM_drawFacesTex(DerivedMesh *dm, int (*setDrawParams)(TFace *tf, int matnr)) 
1206 {
1207         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1208         DispListMesh *dlm = ssdm->dlm;
1209         MVert *mvert= dlm->mvert;
1210         MFace *mface= dlm->mface;
1211         TFace *tface = dlm->tface;
1212         float *nors = dlm->nors;
1213         int a;
1214         
1215         for (a=0; a<dlm->totface; a++) {
1216                 MFace *mf= &mface[a];
1217                 TFace *tf = tface?&tface[a]:NULL;
1218                 int flag;
1219                 unsigned char *cp= NULL;
1220                 
1221                 flag = setDrawParams(tf, mf->mat_nr);
1222
1223                 if (flag==0) {
1224                         continue;
1225                 } else if (flag==1) {
1226                         if (tf) {
1227                                 cp= (unsigned char*) tf->col;
1228                         } else if (dlm->mcol) {
1229                                 cp= (unsigned char*) &dlm->mcol[a*4];
1230                         }
1231                 }
1232
1233                 if (!(mf->flag&ME_SMOOTH)) {
1234                         glNormal3fv(&nors[a*3]);
1235                 }
1236
1237                 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
1238                 if (tf) glTexCoord2fv(tf->uv[0]);
1239                 if (cp) glColor3ub(cp[3], cp[2], cp[1]);
1240                 if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v1].no);
1241                 glVertex3fv((mvert+mf->v1)->co);
1242                         
1243                 if (tf) glTexCoord2fv(tf->uv[1]);
1244                 if (cp) glColor3ub(cp[7], cp[6], cp[5]);
1245                 if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v2].no);
1246                 glVertex3fv((mvert+mf->v2)->co);
1247
1248                 if (tf) glTexCoord2fv(tf->uv[2]);
1249                 if (cp) glColor3ub(cp[11], cp[10], cp[9]);
1250                 if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v3].no);
1251                 glVertex3fv((mvert+mf->v3)->co);
1252
1253                 if(mf->v4) {
1254                         if (tf) glTexCoord2fv(tf->uv[3]);
1255                         if (cp) glColor3ub(cp[15], cp[14], cp[13]);
1256                         if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v4].no);
1257                         glVertex3fv((mvert+mf->v4)->co);
1258                 }
1259                 glEnd();
1260         }
1261 }
1262 static void ssDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors) 
1263 {
1264         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1265         DispListMesh *dlm = ssdm->dlm;
1266         MVert *mvert= dlm->mvert;
1267         MFace *mface= dlm->mface;
1268         float *nors = dlm->nors;
1269         int i, index=-1;
1270
1271         for (i=0; i<dlm->totface; i++) {
1272                 MFace *mf = &mface[i];
1273                 int drawSmooth = 1;
1274
1275                 if (mf->flag&ME_FACE_STEPINDEX) index++;
1276
1277                 if (index!=-1 && (!setDrawOptions || setDrawOptions(userData, index, &drawSmooth))) {
1278                         unsigned char *cp = NULL;
1279
1280                         if (useColors) {
1281                                 if (dlm->tface) {
1282                                         cp= (unsigned char*) dlm->tface[i].col;
1283                                 } else if (dlm->mcol) {
1284                                         cp= (unsigned char*) &dlm->mcol[i*4];
1285                                 }
1286                         }
1287
1288                         glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
1289                         glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
1290
1291                         if (!drawSmooth) {
1292                                 glNormal3fv(&nors[i*3]);
1293
1294                                 if (cp) glColor3ub(cp[3], cp[2], cp[1]);
1295                                 glVertex3fv(mvert[mf->v1].co);
1296                                 if (cp) glColor3ub(cp[7], cp[6], cp[5]);
1297                                 glVertex3fv(mvert[mf->v2].co);
1298                                 if (cp) glColor3ub(cp[11], cp[10], cp[9]);
1299                                 glVertex3fv(mvert[mf->v3].co);
1300                                 if(mf->v4) {
1301                                         if (cp) glColor3ub(cp[15], cp[14], cp[13]);
1302                                         glVertex3fv(mvert[mf->v4].co);
1303                                 }
1304                         } else {
1305                                 if (cp) glColor3ub(cp[3], cp[2], cp[1]);
1306                                 glNormal3sv(mvert[mf->v1].no);
1307                                 glVertex3fv(mvert[mf->v1].co);
1308                                 if (cp) glColor3ub(cp[7], cp[6], cp[5]);
1309                                 glNormal3sv(mvert[mf->v2].no);
1310                                 glVertex3fv(mvert[mf->v2].co);
1311                                 if (cp) glColor3ub(cp[11], cp[10], cp[9]);
1312                                 glNormal3sv(mvert[mf->v3].no);
1313                                 glVertex3fv(mvert[mf->v3].co);
1314                                 if(mf->v4) {
1315                                         if (cp) glColor3ub(cp[15], cp[14], cp[13]);
1316                                         glNormal3sv(mvert[mf->v4].no);
1317                                         glVertex3fv(mvert[mf->v4].co);
1318                                 }
1319                         }
1320
1321                         glEnd();
1322                 }
1323         }
1324 }
1325 static void ssDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
1326 {
1327         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1328         int i;
1329
1330         if (ssdm->dlm->totvert) {
1331                 for (i=0; i<ssdm->dlm->totvert; i++) {
1332                         DO_MINMAX(ssdm->dlm->mvert[i].co, min_r, max_r);
1333                 }
1334         } else {
1335                 min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
1336         }
1337 }
1338
1339 static void ssDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
1340 {
1341         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1342         int i;
1343
1344         for (i=0; i<ssdm->dlm->totvert; i++) {
1345                 cos_r[i][0] = ssdm->dlm->mvert[i].co[0];
1346                 cos_r[i][1] = ssdm->dlm->mvert[i].co[1];
1347                 cos_r[i][2] = ssdm->dlm->mvert[i].co[2];
1348         }
1349 }
1350
1351 static int ssDM_getNumVerts(DerivedMesh *dm)
1352 {
1353         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1354
1355         return ssdm->dlm->totvert;
1356 }
1357 static int ssDM_getNumFaces(DerivedMesh *dm)
1358 {
1359         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1360
1361         return ssdm->dlm->totface;
1362 }
1363
1364 static DispListMesh *ssDM_convertToDispListMesh(DerivedMesh *dm, int allowShared)
1365 {
1366         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1367
1368         if (allowShared) {
1369                 return displistmesh_copyShared(ssdm->dlm);
1370         } else {
1371                 return displistmesh_copy(ssdm->dlm);
1372         }
1373 }
1374
1375 static void ssDM_release(DerivedMesh *dm)
1376 {
1377         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1378
1379         displistmesh_free(ssdm->dlm);
1380
1381         MEM_freeN(dm);
1382 }
1383
1384 DerivedMesh *derivedmesh_from_displistmesh(DispListMesh *dlm, float (*vertexCos)[3])
1385 {
1386         SSDerivedMesh *ssdm = MEM_callocN(sizeof(*ssdm), "ssdm");
1387
1388         ssdm->dm.getMinMax = ssDM_getMinMax;
1389
1390         ssdm->dm.getNumVerts = ssDM_getNumVerts;
1391         ssdm->dm.getNumFaces = ssDM_getNumFaces;
1392         ssdm->dm.convertToDispListMesh = ssDM_convertToDispListMesh;
1393
1394         ssdm->dm.getVertCos = ssDM_getVertCos;
1395
1396         ssdm->dm.drawVerts = ssDM_drawVerts;
1397
1398         ssdm->dm.drawUVEdges = ssDM_drawUVEdges;
1399         ssdm->dm.drawEdges = ssDM_drawEdges;
1400         ssdm->dm.drawLooseEdges = ssDM_drawLooseEdges;
1401         
1402         ssdm->dm.drawFacesSolid = ssDM_drawFacesSolid;
1403         ssdm->dm.drawFacesColored = ssDM_drawFacesColored;
1404         ssdm->dm.drawFacesTex = ssDM_drawFacesTex;
1405         ssdm->dm.drawMappedFaces = ssDM_drawMappedFaces;
1406
1407                 /* EM functions */
1408         
1409         ssdm->dm.foreachMappedVert = ssDM_foreachMappedVert;
1410         ssdm->dm.foreachMappedEdge = ssDM_foreachMappedEdge;
1411         ssdm->dm.foreachMappedFaceCenter = ssDM_foreachMappedFaceCenter;
1412         
1413         ssdm->dm.drawMappedEdges = ssDM_drawMappedEdges;
1414         ssdm->dm.drawMappedEdgesInterp = NULL; // no way to implement this one
1415         
1416         ssdm->dm.release = ssDM_release;
1417         
1418         ssdm->dlm = dlm;
1419
1420         if (vertexCos) {
1421                 int i;
1422
1423                 for (i=0; i<dlm->totvert; i++) {
1424                         VECCOPY(dlm->mvert[i].co, vertexCos[i]);
1425                 }
1426
1427                 if (dlm->nors && !dlm->dontFreeNors) {
1428                         MEM_freeN(dlm->nors);
1429                         dlm->nors = 0;
1430                 }
1431
1432                 mesh_calc_normals(dlm->mvert, dlm->totvert, dlm->mface, dlm->totface, &dlm->nors);
1433         }
1434
1435         return (DerivedMesh*) ssdm;
1436 }
1437
1438 /***/
1439
1440 DerivedMesh *mesh_create_derived_for_modifier(Object *ob, ModifierData *md)
1441 {
1442         Mesh *me = ob->data;
1443         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1444         DerivedMesh *dm;
1445
1446         if (!(md->mode&eModifierMode_Realtime)) return NULL;
1447         if (mti->isDisabled && mti->isDisabled(md)) return NULL;
1448
1449         if (mti->type==eModifierTypeType_OnlyDeform) {
1450                 int numVerts;
1451                 float (*deformedVerts)[3] = mesh_getVertexCos(me, &numVerts);
1452
1453                 mti->deformVerts(md, ob, NULL, deformedVerts, numVerts);
1454                 
1455                 dm = getMeshDerivedMesh(me, ob, deformedVerts);
1456                 MEM_freeN(deformedVerts);
1457         } else {
1458                 dm = mti->applyModifier(md, ob, NULL, NULL, 0, 0);
1459         }
1460
1461         return dm;
1462 }
1463
1464 static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], DerivedMesh **deform_r, DerivedMesh **final_r, int useRenderParams, int useDeform)
1465 {
1466         Mesh *me = ob->data;
1467         ModifierData *md= modifiers_getVirtualModifierList(ob);
1468         float (*deformedVerts)[3] = NULL;
1469         DerivedMesh *dm;
1470         int numVerts = me->totvert;
1471         int fluidsimMeshUsed = 0;
1472
1473         modifiers_clearErrors(ob);
1474
1475         if (deform_r) *deform_r = NULL;
1476         *final_r = NULL;
1477
1478         /* replace original mesh by fluidsim surface mesh for fluidsim domain objects */
1479         if((G.obedit!=ob) && (ob->fluidsimFlag & OB_FLUIDSIM_ENABLE)) {
1480                 if(ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN) {
1481                         loadFluidsimMesh(ob,useRenderParams);
1482                         fluidsimMeshUsed = 1;
1483                         /* might have changed... */
1484                         me = ob->data;
1485                         numVerts = me->totvert;
1486                 }
1487         }
1488
1489         if (useDeform) {
1490                 if(do_ob_key(ob))       /* shape key makes deform verts */
1491                         deformedVerts = mesh_getVertexCos(me, &numVerts);
1492                 
1493                         /* Apply all leading deforming modifiers */
1494                 for (; md; md=md->next) {
1495                         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1496
1497                         if (!(md->mode&(1<<useRenderParams))) continue;
1498                         if (mti->isDisabled && mti->isDisabled(md)) continue;
1499
1500                         if (mti->type==eModifierTypeType_OnlyDeform) {
1501                                 if (!deformedVerts) deformedVerts = mesh_getVertexCos(me, &numVerts);
1502                                 mti->deformVerts(md, ob, NULL, deformedVerts, numVerts);
1503                         } else {
1504                                 break;
1505                         }
1506                 }
1507
1508                         /* Result of all leading deforming modifiers is cached for
1509                          * places that wish to use the original mesh but with deformed
1510                          * coordinates (vpaint, etc.)
1511                          */
1512                 if (deform_r) *deform_r = getMeshDerivedMesh(me, ob, deformedVerts);
1513         } else {
1514                 if(!fluidsimMeshUsed) {
1515                         // default behaviour for meshes
1516                         deformedVerts = inputVertexCos;
1517                 } else {
1518                         // the fluid sim mesh might have more vertices than the original 
1519                         // one, so inputVertexCos shouldnt be used
1520                         deformedVerts = mesh_getVertexCos(me, &numVerts);
1521                 }
1522         }
1523
1524
1525                 /* Now apply all remaining modifiers. If useDeform is off then skip
1526                  * OnlyDeform ones. 
1527                  */
1528         dm = NULL;
1529         for (; md; md=md->next) {
1530                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1531
1532                 if (!(md->mode&(1<<useRenderParams))) continue;
1533                 if (mti->type==eModifierTypeType_OnlyDeform && !useDeform) continue;
1534                 if ((mti->flags&eModifierTypeFlag_RequiresOriginalData) && dm) {
1535                         modifier_setError(md, "Internal error, modifier requires original data (bad stack position).");
1536                         continue;
1537                 }
1538                 if (mti->isDisabled && mti->isDisabled(md)) continue;
1539
1540                         /* How to apply modifier depends on (a) what we already have as
1541                          * a result of previous modifiers (could be a DerivedMesh or just
1542                          * deformed vertices) and (b) what type the modifier is.
1543                          */
1544
1545                 if (mti->type==eModifierTypeType_OnlyDeform) {
1546                                 /* No existing verts to deform, need to build them. */
1547                         if (!deformedVerts) {
1548                                 if (dm) {
1549                                                 /* Deforming a derived mesh, read the vertex locations out of the mesh and
1550                                                  * deform them. Once done with this run of deformers verts will be written back.
1551                                                  */
1552                                         numVerts = dm->getNumVerts(dm);
1553                                         deformedVerts = MEM_mallocN(sizeof(*deformedVerts)*numVerts, "dfmv");
1554                                         dm->getVertCos(dm, deformedVerts);
1555                                 } else {
1556                                         deformedVerts = mesh_getVertexCos(me, &numVerts);
1557                                 }
1558                         }
1559
1560                         mti->deformVerts(md, ob, dm, deformedVerts, numVerts);
1561                 } else {
1562                                 /* There are 4 cases here (have deform? have dm?) but they all are handled
1563                                  * by the modifier apply function, which will also free the DerivedMesh if
1564                                  * it exists.
1565                                  */
1566                         DerivedMesh *ndm = mti->applyModifier(md, ob, dm, deformedVerts, useRenderParams, !inputVertexCos);
1567
1568                         if (ndm) {
1569                                 if (dm) dm->release(dm);
1570
1571                                 dm = ndm;
1572
1573                                 if (deformedVerts) {
1574                                         if (deformedVerts!=inputVertexCos) {
1575                                                 MEM_freeN(deformedVerts);
1576                                         }
1577                                         deformedVerts = NULL;
1578                                 }
1579                         } 
1580                 }
1581         }
1582
1583                 /* Yay, we are done. If we have a DerivedMesh and deformed vertices need to apply
1584                  * these back onto the DerivedMesh. If we have no DerivedMesh then we need to build
1585                  * one.
1586                  */
1587         if (dm && deformedVerts) {
1588                 DispListMesh *dlm = dm->convertToDispListMesh(dm, 0);
1589
1590                 dm->release(dm);
1591
1592                 *final_r = derivedmesh_from_displistmesh(dlm, deformedVerts);
1593         } else if (dm) {
1594                 *final_r = dm;
1595         } else {
1596                 *final_r = getMeshDerivedMesh(me, ob, deformedVerts);
1597         }
1598
1599         if (deformedVerts && deformedVerts!=inputVertexCos) {
1600                 MEM_freeN(deformedVerts);
1601         }
1602         // restore mesh in any case
1603         if(fluidsimMeshUsed) ob->data = ob->fluidsimSettings->orgMesh;
1604 }
1605
1606 static float (*editmesh_getVertexCos(EditMesh *em, int *numVerts_r))[3]
1607 {
1608         int i, numVerts = *numVerts_r = BLI_countlist(&em->verts);
1609         float (*cos)[3];
1610         EditVert *eve;
1611
1612         cos = MEM_mallocN(sizeof(*cos)*numVerts, "vertexcos");
1613         for (i=0,eve=em->verts.first; i<numVerts; i++,eve=eve->next) {
1614                 VECCOPY(cos[i], eve->co);
1615         }
1616
1617         return cos;
1618 }
1619
1620 static void editmesh_calc_modifiers(DerivedMesh **cage_r, DerivedMesh **final_r)
1621 {
1622         Object *ob = G.obedit;
1623         EditMesh *em = G.editMesh;
1624         ModifierData *md;
1625         float (*deformedVerts)[3] = NULL;
1626         DerivedMesh *dm;
1627         int i, numVerts, cageIndex = modifiers_getCageIndex(ob, NULL);
1628
1629         modifiers_clearErrors(ob);
1630
1631         if (cage_r && cageIndex==-1) {
1632                 *cage_r = getEditMeshDerivedMesh(em, NULL);
1633         }
1634
1635         dm = NULL;
1636         for (i=0,md= ob->modifiers.first; md; i++,md=md->next) {
1637                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1638
1639                 if (!(md->mode&eModifierMode_Realtime)) continue;
1640                 if (!(md->mode&eModifierMode_Editmode)) continue;
1641                 if ((mti->flags&eModifierTypeFlag_RequiresOriginalData) && dm) {
1642                         modifier_setError(md, "Internal error, modifier requires original data (bad stack position).");
1643                         continue;
1644                 }
1645                 if (mti->isDisabled && mti->isDisabled(md)) continue;
1646                 if (!(mti->flags&eModifierTypeFlag_SupportsEditmode)) continue;
1647
1648                         /* How to apply modifier depends on (a) what we already have as
1649                          * a result of previous modifiers (could be a DerivedMesh or just
1650                          * deformed vertices) and (b) what type the modifier is.
1651                          */
1652
1653                 if (mti->type==eModifierTypeType_OnlyDeform) {
1654                                 /* No existing verts to deform, need to build them. */
1655                         if (!deformedVerts) {
1656                                 if (dm) {
1657                                                 /* Deforming a derived mesh, read the vertex locations out of the mesh and
1658                                                  * deform them. Once done with this run of deformers verts will be written back.
1659                                                  */
1660                                         numVerts = dm->getNumVerts(dm);
1661                                         deformedVerts = MEM_mallocN(sizeof(*deformedVerts)*numVerts, "dfmv");
1662                                         dm->getVertCos(dm, deformedVerts);
1663                                 } else {
1664                                         deformedVerts = editmesh_getVertexCos(em, &numVerts);
1665                                 }
1666                         }
1667
1668                         mti->deformVertsEM(md, ob, em, dm, deformedVerts, numVerts);
1669                 } else {
1670                                 /* There are 4 cases here (have deform? have dm?) but they all are handled
1671                                  * by the modifier apply function, which will also free the DerivedMesh if
1672                                  * it exists.
1673                                  */
1674                         DerivedMesh *ndm = mti->applyModifierEM(md, ob, em, dm, deformedVerts);
1675
1676                         if (ndm) {
1677                                 if (dm && (!cage_r || dm!=*cage_r)) dm->release(dm);
1678
1679                                 dm = ndm;
1680
1681                                 if (deformedVerts) {
1682                                         MEM_freeN(deformedVerts);
1683                                         deformedVerts = NULL;
1684                                 }
1685                         }
1686                 }
1687
1688                 if (cage_r && i==cageIndex) {
1689                         if (dm && deformedVerts) {
1690                                 DispListMesh *dlm;
1691
1692                                 dlm = dm->convertToDispListMesh(dm, 0);
1693
1694                                 *cage_r = derivedmesh_from_displistmesh(dlm, deformedVerts);
1695                         } else if (dm) {
1696                                 *cage_r = dm;
1697                         } else {
1698                                 *cage_r = getEditMeshDerivedMesh(em, deformedVerts?MEM_dupallocN(deformedVerts):NULL);
1699                         }
1700                 }
1701         }
1702
1703                 /* Yay, we are done. If we have a DerivedMesh and deformed vertices need to apply
1704                  * these back onto the DerivedMesh. If we have no DerivedMesh then we need to build
1705                  * one.
1706                  */
1707         if (dm && deformedVerts) {
1708                 DispListMesh *dlm = dm->convertToDispListMesh(dm, 0);
1709
1710                 if (!cage_r || dm!=*cage_r) dm->release(dm);
1711
1712                 *final_r = derivedmesh_from_displistmesh(dlm, deformedVerts);
1713                 MEM_freeN(deformedVerts);
1714         } else if (dm) {
1715                 *final_r = dm;
1716         } else {
1717                 *final_r = getEditMeshDerivedMesh(em, deformedVerts);
1718         }
1719 }
1720
1721 /***/
1722
1723
1724         /* Something of a hack, at the moment deal with weightpaint
1725          * by tucking into colors during modifier eval, only in
1726          * wpaint mode. Works ok but need to make sure recalc
1727          * happens on enter/exit wpaint.
1728          */
1729
1730 static void weight_to_rgb(float input, float *fr, float *fg, float *fb)
1731 {
1732         float blend;
1733         
1734         blend= ((input/2.0f)+0.5f);
1735         
1736         if (input<=0.25f){      // blue->cyan
1737                 *fr= 0.0f;
1738                 *fg= blend*input*4.0f;
1739                 *fb= blend;
1740         }
1741         else if (input<=0.50f){ // cyan->green
1742                 *fr= 0.0f;
1743                 *fg= blend;
1744                 *fb= blend*(1.0f-((input-0.25f)*4.0f)); 
1745         }
1746         else if (input<=0.75){  // green->yellow
1747                 *fr= blend * ((input-0.50f)*4.0f);
1748                 *fg= blend;
1749                 *fb= 0.0f;
1750         }
1751         else if (input<=1.0){ // yellow->red
1752                 *fr= blend;
1753                 *fg= blend * (1.0f-((input-0.75f)*4.0f)); 
1754                 *fb= 0.0f;
1755         }
1756 }
1757 static void calc_weightpaint_vert_color(Object *ob, int vert, unsigned char *col)
1758 {
1759         Mesh *me = ob->data;
1760         float fr, fg, fb, input = 0.0f;
1761         int i;
1762
1763         if (me->dvert) {
1764                 for (i=0; i<me->dvert[vert].totweight; i++)
1765                         if (me->dvert[vert].dw[i].def_nr==ob->actdef-1)
1766                                 input+=me->dvert[vert].dw[i].weight;            
1767         }
1768
1769         CLAMP(input, 0.0f, 1.0f);
1770         
1771         weight_to_rgb(input, &fr, &fg, &fb);
1772         
1773         col[3] = (unsigned char)(fr * 255.0f);
1774         col[2] = (unsigned char)(fg * 255.0f);
1775         col[1] = (unsigned char)(fb * 255.0f);
1776         col[0] = 255;
1777 }
1778 static unsigned char *calc_weightpaint_colors(Object *ob) 
1779 {
1780         Mesh *me = ob->data;
1781         MFace *mf = me->mface;
1782         unsigned char *wtcol;
1783         int i;
1784         
1785         wtcol = MEM_callocN (sizeof (unsigned char) * me->totface*4*4, "weightmap");
1786         
1787         memset(wtcol, 0x55, sizeof (unsigned char) * me->totface*4*4);
1788         for (i=0; i<me->totface; i++, mf++){
1789                 calc_weightpaint_vert_color(ob, mf->v1, &wtcol[(i*4 + 0)*4]); 
1790                 calc_weightpaint_vert_color(ob, mf->v2, &wtcol[(i*4 + 1)*4]); 
1791                 calc_weightpaint_vert_color(ob, mf->v3, &wtcol[(i*4 + 2)*4]); 
1792                 if (mf->v4)
1793                         calc_weightpaint_vert_color(ob, mf->v4, &wtcol[(i*4 + 3)*4]); 
1794         }
1795         
1796         return wtcol;
1797 }
1798
1799 static void clear_mesh_caches(Object *ob)
1800 {
1801         Mesh *me= ob->data;
1802
1803                 /* also serves as signal to remake texspace */
1804         if (me->bb) {
1805                 MEM_freeN(me->bb);
1806                 me->bb = NULL;
1807         }
1808
1809         freedisplist(&ob->disp);
1810
1811         if (ob->derivedFinal) {
1812                 ob->derivedFinal->release(ob->derivedFinal);
1813                 ob->derivedFinal= NULL;
1814         }
1815         if (ob->derivedDeform) {
1816                 ob->derivedDeform->release(ob->derivedDeform);
1817                 ob->derivedDeform= NULL;
1818         }
1819 }
1820
1821 static void mesh_build_data(Object *ob)
1822 {
1823         Mesh *me = ob->data;
1824         float min[3], max[3];
1825
1826         clear_mesh_caches(ob);
1827
1828         if(ob!=G.obedit) {
1829                 if( (G.f & G_WEIGHTPAINT) && ob==(G.scene->basact?G.scene->basact->object:NULL)) {
1830                         MCol *mcol = me->mcol;
1831                         TFace *tface =  me->tface;
1832
1833                         me->tface = NULL;
1834                         me->mcol = (MCol*) calc_weightpaint_colors(ob);
1835
1836                         mesh_calc_modifiers(ob, NULL, &ob->derivedDeform, &ob->derivedFinal, 0, 1);
1837
1838                         MEM_freeN(me->mcol);
1839                         me->mcol = mcol;
1840                         me->tface = tface;
1841                 } else {
1842                         mesh_calc_modifiers(ob, NULL, &ob->derivedDeform, &ob->derivedFinal, 0, 1);
1843                 }
1844
1845                 INIT_MINMAX(min, max);
1846
1847                 ob->derivedFinal->getMinMax(ob->derivedFinal, min, max);
1848
1849                 boundbox_set_from_min_max(mesh_get_bb(ob->data), min, max);
1850         }
1851 }
1852
1853 static void editmesh_build_data(void)
1854 {
1855         float min[3], max[3];
1856
1857         EditMesh *em = G.editMesh;
1858
1859         clear_mesh_caches(G.obedit);
1860
1861         if (em->derivedFinal) {
1862                 if (em->derivedFinal!=em->derivedCage) {
1863                         em->derivedFinal->release(em->derivedFinal);
1864                 }
1865                 em->derivedFinal = NULL;
1866         }
1867         if (em->derivedCage) {
1868                 em->derivedCage->release(em->derivedCage);
1869                 em->derivedCage = NULL;
1870         }
1871
1872         editmesh_calc_modifiers(&em->derivedCage, &em->derivedFinal);
1873
1874         INIT_MINMAX(min, max);
1875
1876         em->derivedFinal->getMinMax(em->derivedFinal, min, max);
1877
1878         boundbox_set_from_min_max(mesh_get_bb(G.obedit->data), min, max);
1879 }
1880
1881 void makeDispListMesh(Object *ob)
1882 {
1883         if (ob==G.obedit) {
1884                 editmesh_build_data();
1885         } else {
1886                 mesh_build_data(ob);
1887
1888                 build_particle_system(ob);
1889         }
1890 }
1891
1892 /***/
1893
1894 DerivedMesh *mesh_get_derived_final(Object *ob, int *needsFree_r)
1895 {
1896         if (!ob->derivedFinal) {
1897                 mesh_build_data(ob);
1898         }
1899
1900         *needsFree_r = 0;
1901         return ob->derivedFinal;
1902 }
1903
1904 DerivedMesh *mesh_get_derived_deform(Object *ob, int *needsFree_r)
1905 {
1906         if (!ob->derivedDeform) {
1907                 mesh_build_data(ob);
1908         } 
1909
1910         *needsFree_r = 0;
1911         return ob->derivedDeform;
1912 }
1913
1914 DerivedMesh *mesh_create_derived_render(Object *ob)
1915 {
1916         DerivedMesh *final;
1917
1918         mesh_calc_modifiers(ob, NULL, NULL, &final, 1, 1);
1919
1920         return final;
1921 }
1922
1923 DerivedMesh *mesh_create_derived_no_deform(Object *ob, float (*vertCos)[3])
1924 {
1925         DerivedMesh *final;
1926
1927         mesh_calc_modifiers(ob, vertCos, NULL, &final, 0, 0);
1928
1929         return final;
1930 }
1931
1932 DerivedMesh *mesh_create_derived_no_deform_render(Object *ob, float (*vertCos)[3])
1933 {
1934         DerivedMesh *final;
1935
1936         mesh_calc_modifiers(ob, vertCos, NULL, &final, 1, 0);
1937
1938         return final;
1939 }
1940
1941 /***/
1942
1943 DerivedMesh *editmesh_get_derived_cage_and_final(DerivedMesh **final_r, int *cageNeedsFree_r, int *finalNeedsFree_r)
1944 {
1945         *cageNeedsFree_r = *finalNeedsFree_r = 0;
1946
1947         if (!G.editMesh->derivedCage)
1948                 editmesh_build_data();
1949
1950         *final_r = G.editMesh->derivedFinal;
1951         return G.editMesh->derivedCage;
1952 }
1953
1954 DerivedMesh *editmesh_get_derived_cage(int *needsFree_r)
1955 {
1956         *needsFree_r = 0;
1957
1958         if (!G.editMesh->derivedCage)
1959                 editmesh_build_data();
1960
1961         return G.editMesh->derivedCage;
1962 }
1963
1964 DerivedMesh *editmesh_get_derived_base(void)
1965 {
1966         return getEditMeshDerivedMesh(G.editMesh, NULL);
1967 }
1968
1969
1970 /* ********* For those who don't grasp derived stuff! (ton) :) *************** */
1971
1972 static void make_vertexcosnos__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1973 {
1974         float *vec = userData;
1975         
1976         vec+= 6*index;
1977         VECCOPY(vec, co);
1978         vec+= 3;
1979         if(no_f) {
1980                 VECCOPY(vec, no_f);
1981         }
1982         else {
1983                 VECCOPY(vec, no_s);
1984         }
1985 }
1986
1987 /* always returns original amount me->totvert of vertices and normals, but fully deformed and subsurfered */
1988 /* this is needed for all code using vertexgroups (no subsurf support) */
1989 /* it stores the normals as floats, but they can still be scaled as shorts (32767 = unit) */
1990 /* in use now by vertex/weight paint and particle generating */
1991
1992 float *mesh_get_mapped_verts_nors(Object *ob)
1993 {
1994         Mesh *me= ob->data;
1995         DerivedMesh *dm;
1996         float *vertexcosnos;
1997         int needsFree;
1998         
1999         /* lets prevent crashing... */
2000         if(ob->type!=OB_MESH || me->totvert==0)
2001                 return NULL;
2002         
2003         dm= mesh_get_derived_final(ob, &needsFree);
2004         vertexcosnos= MEM_mallocN(6*sizeof(float)*me->totvert, "vertexcosnos map");
2005         
2006         if(dm->foreachMappedVert) {
2007                 dm->foreachMappedVert(dm, make_vertexcosnos__mapFunc, vertexcosnos);
2008         }
2009         else {
2010                 float *fp= vertexcosnos;
2011                 int a;
2012                 
2013                 for(a=0; a< me->totvert; a++, fp+=6) {
2014                         dm->getVertCo(dm, a, fp);
2015                         dm->getVertNo(dm, a, fp+3);
2016                 }
2017         }
2018         
2019         if (needsFree) dm->release(dm);
2020         return vertexcosnos;
2021 }
2022
2023
2024 /* ************************* fluidsim bobj file handling **************************** */
2025
2026 #ifdef WIN32
2027 #ifndef snprintf
2028 #define snprintf _snprintf
2029 #endif
2030 #endif
2031
2032 /* write .bobj.gz file for a mesh object */
2033 void writeBobjgz(char *filename, struct Object *ob) 
2034 {
2035         // const int debugBobjWrite = 0; // now handled by global debug level
2036         char debugStrBuffer[256];
2037         int wri,i,j;
2038         float wrf;
2039         gzFile gzf;
2040         DispListMesh *dlm = NULL;
2041         DerivedMesh *dm;
2042         float vec[3];
2043         float rotmat[3][3];
2044         MFace *mface = NULL;
2045
2046         if(!ob->data || (ob->type!=OB_MESH)) {
2047                 snprintf(debugStrBuffer,256,"Writing GZ_BOBJ Invalid object %s ...\n", ob->id.name); 
2048                 elbeemDebugOut(debugStrBuffer);
2049                 return;
2050         }
2051         if((ob->size[0]<0.0) || (ob->size[0]<0.0) || (ob->size[0]<0.0) ) {
2052                 snprintf(debugStrBuffer,256,"\nfluidSim::writeBobjgz:: Warning object %s has negative scaling - check triangle ordering...?\n\n", ob->id.name); 
2053                 elbeemDebugOut(debugStrBuffer);
2054         }
2055
2056         snprintf(debugStrBuffer,256,"Writing GZ_BOBJ '%s' ... ",filename); elbeemDebugOut(debugStrBuffer); 
2057         gzf = gzopen(filename, "wb9");
2058         if (!gzf) {
2059                 snprintf(debugStrBuffer,256,"writeBobjgz::error - Unable to open file for writing '%s'\n", filename);
2060                 elbeemDebugOut(debugStrBuffer);
2061                 return;
2062         }
2063
2064         dm = mesh_create_derived_render(ob);
2065         dlm = dm->convertToDispListMesh(dm, 1);
2066         mface = dlm->mface;
2067
2068         if(sizeof(wri)!=4) { snprintf(debugStrBuffer,256,"Writing GZ_BOBJ, Invalid int size %d...\n", wri); elbeemDebugOut(debugStrBuffer); return; } // paranoia check
2069         wri = dlm->totvert;
2070         gzwrite(gzf, &wri, sizeof(wri));
2071         for(i=0; i<wri;i++) {
2072                 VECCOPY(vec, dlm->mvert[i].co); /* get transformed point */
2073                 Mat4MulVecfl(ob->obmat, vec);
2074                 for(j=0; j<3; j++) {
2075                         wrf = vec[j]; 
2076                         gzwrite(gzf, &wrf, sizeof( wrf )); 
2077                 }
2078         }
2079
2080         // should be the same as Vertices.size
2081         wri = dlm->totvert;
2082         gzwrite(gzf, &wri, sizeof(wri));
2083         EulToMat3(ob->rot, rotmat);
2084         for(i=0; i<wri;i++) {
2085                 VECCOPY(vec, dlm->mvert[i].no);
2086                 // FIXME divide? mv->no[0]= (short)(no[0]*32767.0);
2087                 Mat3MulVecfl(rotmat, vec); 
2088                 Normalise(vec);
2089                 for(j=0; j<3; j++) {
2090                         wrf = vec[j];
2091                         gzwrite(gzf, &wrf, sizeof( wrf )); 
2092                 }
2093         }
2094
2095         
2096         /* compute no. of triangles */
2097         wri = 0;
2098         for(i=0; i<dlm->totface; i++) {
2099                 wri++;
2100                 if(mface[i].v4) { wri++; }
2101         }
2102         gzwrite(gzf, &wri, sizeof(wri));
2103         for(i=0; i<dlm->totface; i++) {
2104
2105                 int face[4];
2106                 face[0] = mface[i].v1;
2107                 face[1] = mface[i].v2;
2108                 face[2] = mface[i].v3;
2109                 face[3] = mface[i].v4;
2110                 //snprintf(debugStrBuffer,256,"F %s %d = %d,%d,%d,%d \n",ob->id.name, i, face[0],face[1],face[2],face[3] ); elbeemDebugOut(debugStrBuffer);
2111
2112                 gzwrite(gzf, &(face[0]), sizeof( face[0] )); 
2113                 gzwrite(gzf, &(face[1]), sizeof( face[1] )); 
2114                 gzwrite(gzf, &(face[2]), sizeof( face[2] )); 
2115                 if(face[3]) { 
2116                         gzwrite(gzf, &(face[0]), sizeof( face[0] )); 
2117                         gzwrite(gzf, &(face[2]), sizeof( face[2] )); 
2118                         gzwrite(gzf, &(face[3]), sizeof( face[3] )); 
2119                 }
2120         }
2121
2122         snprintf(debugStrBuffer,256,"Done. #Vertices: %d, #Triangles: %d\n", dlm->totvert, dlm->totface ); 
2123         elbeemDebugOut(debugStrBuffer);
2124         
2125         gzclose( gzf );
2126         if(dlm) displistmesh_free(dlm);
2127         dm->release(dm);
2128 }
2129
2130 /* read .bobj.gz file into a fluidsimDerivedMesh struct */
2131 Mesh* readBobjgz(char *filename, Mesh *orgmesh) //, fluidsimDerivedMesh *fsdm)
2132 {
2133         int wri,i,j;
2134         char debugStrBuffer[256];
2135         float wrf;
2136         Mesh *newmesh; 
2137         const int debugBobjRead = 1;
2138         // init data from old mesh (materials,flags)
2139         MFace *origMFace = &((MFace*) orgmesh->mface)[0];
2140         int mat_nr = -1;
2141         int flag = -1;
2142         MFace *fsface = NULL;
2143         int gotBytes;
2144         gzFile gzf;
2145
2146         if(!orgmesh) return NULL;
2147         if(!origMFace) return NULL;
2148         mat_nr = origMFace->mat_nr;
2149         flag = origMFace->flag;
2150
2151         // similar to copy_mesh
2152         newmesh = MEM_dupallocN(orgmesh);
2153         newmesh->mat= orgmesh->mat;
2154
2155         newmesh->mvert= NULL;
2156         newmesh->medge= NULL;
2157         newmesh->mface= NULL;
2158         newmesh->tface= NULL;
2159         newmesh->dface= NULL;
2160
2161         newmesh->dvert = NULL;
2162
2163         newmesh->mcol= NULL;
2164         newmesh->msticky= NULL;
2165         newmesh->texcomesh= NULL;
2166
2167         newmesh->key= NULL;
2168         newmesh->totface = 0;
2169         newmesh->totvert = 0;
2170         newmesh->totedge = 0;
2171         newmesh->medge = NULL;
2172
2173
2174         snprintf(debugStrBuffer,256,"Reading '%s' GZ_BOBJ... ",filename); elbeemDebugOut(debugStrBuffer); 
2175         gzf = gzopen(filename, "rb");
2176         // gzf = fopen(filename, "rb");
2177         // debug: fread(b,c,1,a) = gzread(a,b,c)
2178         if (!gzf) {
2179                 //snprintf(debugStrBuffer,256,"readBobjgz::error - Unable to open file for reading '%s'\n", filename); // DEBUG
2180                 MEM_freeN(newmesh);
2181                 return NULL;
2182         }
2183
2184         //if(sizeof(wri)!=4) { snprintf(debugStrBuffer,256,"Reading GZ_BOBJ, Invalid int size %d...\n", wri); return NULL; } // paranoia check
2185         gotBytes = gzread(gzf, &wri, sizeof(wri));
2186         newmesh->totvert = wri;
2187         newmesh->mvert = MEM_callocN(sizeof(MVert)*newmesh->totvert, "fluidsimDerivedMesh_bobjvertices");
2188         if(debugBobjRead){ snprintf(debugStrBuffer,256,"#vertices %d ", newmesh->totvert); elbeemDebugOut(debugStrBuffer); } //DEBUG
2189         for(i=0; i<newmesh->totvert;i++) {
2190                 //if(debugBobjRead) snprintf(debugStrBuffer,256,"V %d = ",i);
2191                 for(j=0; j<3; j++) {
2192                         gotBytes = gzread(gzf, &wrf, sizeof( wrf )); 
2193                         newmesh->mvert[i].co[j] = wrf;
2194                         //if(debugBobjRead) snprintf(debugStrBuffer,256,"%25.20f ", wrf);
2195                 }
2196                 //if(debugBobjRead) snprintf(debugStrBuffer,256,"\n");
2197         }
2198
2199         // should be the same as Vertices.size
2200         gotBytes = gzread(gzf, &wri, sizeof(wri));
2201         if(wri != newmesh->totvert) {
2202                 // complain #vertices has to be equal to #normals, reset&abort
2203                 MEM_freeN(newmesh->mvert);
2204                 MEM_freeN(newmesh);
2205                 snprintf(debugStrBuffer,256,"Reading GZ_BOBJ, #normals=%d, #vertices=%d, aborting...\n", wri,newmesh->totvert );
2206                 return NULL;
2207         }
2208         for(i=0; i<newmesh->totvert;i++) {
2209                 for(j=0; j<3; j++) {
2210                         gotBytes = gzread(gzf, &wrf, sizeof( wrf )); 
2211                         newmesh->mvert[i].no[j] = wrf*32767.0;
2212                 }
2213         }
2214
2215         
2216         /* compute no. of triangles */
2217         gotBytes = gzread(gzf, &wri, sizeof(wri));
2218         newmesh->totface = wri;
2219         newmesh->mface = MEM_callocN(sizeof(MFace)*newmesh->totface, "fluidsimDerivedMesh_bobjfaces");
2220         if(debugBobjRead){ snprintf(debugStrBuffer,256,"#faces %d ", newmesh->totface); elbeemDebugOut(debugStrBuffer); } //DEBUG
2221         fsface = newmesh->mface;
2222         for(i=0; i<newmesh->totface; i++) {
2223                 int face[4];
2224
2225                 gotBytes = gzread(gzf, &(face[0]), sizeof( face[0] )); 
2226                 gotBytes = gzread(gzf, &(face[1]), sizeof( face[1] )); 
2227                 gotBytes = gzread(gzf, &(face[2]), sizeof( face[2] )); 
2228                 face[3] = 0;
2229
2230                 fsface[i].v1 = face[0];
2231                 fsface[i].v2 = face[1];
2232                 fsface[i].v3 = face[2];
2233                 fsface[i].v4 = face[3];
2234         }
2235
2236         // correct triangles with v3==0 for blender, cycle verts
2237         for(i=0; i<newmesh->totface; i++) {
2238                 if(!fsface[i].v3) {
2239                         int temp = fsface[i].v1;
2240                         fsface[i].v1 = fsface[i].v2;
2241                         fsface[i].v2 = fsface[i].v3;
2242                         fsface[i].v3 = temp;
2243                 }
2244         }
2245         
2246         gzclose( gzf );
2247         for(i=0;i<newmesh->totface;i++) { 
2248                 fsface[i].mat_nr = mat_nr;
2249                 fsface[i].flag = flag;
2250                 fsface[i].edcode = ME_V1V2 | ME_V2V3 | ME_V3V1;
2251                 //snprintf(debugStrBuffer,256,"%d : %d,%d,%d\n", i,fsface[i].mat_nr, fsface[i].flag, fsface[i].edcode );
2252         }
2253
2254         snprintf(debugStrBuffer,256," (%d,%d) done\n", newmesh->totvert,newmesh->totface); elbeemDebugOut(debugStrBuffer); //DEBUG
2255         return newmesh;
2256 }
2257
2258
2259 /* ***************************** fluidsim derived mesh ***************************** */
2260
2261 /* check which file to load, and replace old mesh of the object with it */
2262 /* this replacement is undone at the end of mesh_calc_modifiers */
2263 void loadFluidsimMesh(Object *srcob, int useRenderParams)
2264 {
2265         Mesh *mesh = NULL;
2266         float *bbStart = NULL, *bbSize = NULL;
2267         float lastBB[3];
2268         int displaymode = 0;
2269         int curFrame = G.scene->r.cfra - G.scene->r.sfra; /* start with 0 at start frame */
2270         char targetDir[FILE_MAXFILE+FILE_MAXDIR], targetFile[FILE_MAXFILE+FILE_MAXDIR];
2271         char debugStrBuffer[256];
2272         //snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d)\n", srcob->id.name, useRenderParams); // debug
2273
2274         if((!srcob)||(!srcob->fluidsimSettings)) {
2275                 snprintf(debugStrBuffer,256,"DEBUG - Invalid loadFluidsimMesh call, rp %d, dm %d)\n", useRenderParams, displaymode); // debug
2276                 elbeemDebugOut(debugStrBuffer); // debug
2277                 return;
2278         }
2279         // make sure the original mesh data pointer is stored
2280         if(!srcob->fluidsimSettings->orgMesh) {
2281                 srcob->fluidsimSettings->orgMesh = srcob->data;
2282         }
2283
2284         // free old mesh, if there is one (todo, check if it's still valid?)
2285         if(srcob->fluidsimSettings->meshSurface) {
2286                 Mesh *freeFsMesh = srcob->fluidsimSettings->meshSurface;
2287
2288                 // similar to free_mesh(...) , but no things like unlink...
2289                 if(freeFsMesh->mvert) MEM_freeN(freeFsMesh->mvert);
2290                 if(freeFsMesh->medge) MEM_freeN(freeFsMesh->medge);
2291                 if(freeFsMesh->mface) MEM_freeN(freeFsMesh->mface);
2292                 MEM_freeN(freeFsMesh);
2293                 
2294                 if(srcob->data == srcob->fluidsimSettings->meshSurface)
2295                  srcob->data = srcob->fluidsimSettings->orgMesh;
2296                 srcob->fluidsimSettings->meshSurface = NULL;
2297         } 
2298
2299         // init bounding box
2300         bbStart = srcob->fluidsimSettings->bbStart; 
2301         bbSize = srcob->fluidsimSettings->bbSize;
2302         lastBB[0] = bbSize[0];  // TEST
2303         lastBB[1] = bbSize[1]; 
2304         lastBB[2] = bbSize[2];
2305         fluidsimGetAxisAlignedBB(srcob->fluidsimSettings->orgMesh, srcob->obmat, bbStart, bbSize);
2306         // check free fsmesh... TODO
2307         
2308         if(!useRenderParams) {
2309                 displaymode = srcob->fluidsimSettings->guiDisplayMode;
2310         } else {
2311                 displaymode = srcob->fluidsimSettings->renderDisplayMode;
2312         }
2313         
2314         snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d, dm %d)\n", srcob->id.name, useRenderParams, displaymode); // debug
2315         elbeemDebugOut(debugStrBuffer); // debug
2316
2317         strncpy(targetDir, srcob->fluidsimSettings->surfdataPath, FILE_MAXDIR);
2318         // use preview or final mesh?
2319         if(displaymode==1) {
2320                 // just display original object
2321                 srcob->data = srcob->fluidsimSettings->orgMesh;
2322                 return;
2323         } else if(displaymode==2) {
2324                 strcat(targetDir,"fluidsurface_preview_#");
2325         } else { // 3
2326                 strcat(targetDir,"fluidsurface_final_#");
2327         }
2328         BLI_convertstringcode(targetDir, G.sce, curFrame); // fixed #frame-no 
2329         strcpy(targetFile,targetDir);
2330         strcat(targetFile, ".bobj.gz");
2331
2332         snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d, dm %d) '%s' \n", srcob->id.name, useRenderParams, displaymode, targetFile);  // debug
2333         elbeemDebugOut(debugStrBuffer); // debug
2334
2335         mesh = readBobjgz(targetFile, srcob->fluidsimSettings->orgMesh );
2336         if(!mesh) {
2337                 // display org. object upon failure
2338                 srcob->data = srcob->fluidsimSettings->orgMesh;
2339                 return;
2340         }
2341
2342         if((mesh)&&(mesh->totvert>0)) {
2343                 make_edges(mesh, 0);    // 0 = make all edges draw
2344         }
2345         srcob->fluidsimSettings->meshSurface = mesh;
2346         srcob->data = mesh;
2347         return;
2348 }
2349
2350 /* helper function */
2351 /* init axis aligned BB for mesh object */
2352 void fluidsimGetAxisAlignedBB(struct Mesh *mesh, float obmat[][4],
2353                  /*RET*/ float start[3], /*RET*/ float size[3] )
2354 {
2355         float bbsx=0.0, bbsy=0.0, bbsz=0.0;
2356         float bbex=1.0, bbey=1.0, bbez=1.0;
2357         int i;
2358         float vec[3];
2359
2360         VECCOPY(vec, mesh->mvert[0].co); 
2361         Mat4MulVecfl(obmat, vec);
2362         bbsx = vec[0]; bbsy = vec[1]; bbsz = vec[2];
2363         bbex = vec[0]; bbey = vec[1]; bbez = vec[2];
2364
2365         for(i=1; i<mesh->totvert;i++) {
2366                 VECCOPY(vec, mesh->mvert[i].co);
2367                 Mat4MulVecfl(obmat, vec);
2368
2369                 if(vec[0] < bbsx){ bbsx= vec[0]; }
2370                 if(vec[1] < bbsy){ bbsy= vec[1]; }
2371                 if(vec[2] < bbsz){ bbsz= vec[2]; }
2372                 if(vec[0] > bbex){ bbex= vec[0]; }
2373                 if(vec[1] > bbey){ bbey= vec[1]; }
2374                 if(vec[2] > bbez){ bbez= vec[2]; }
2375         }
2376
2377         // return values...
2378         if(start) {
2379                 start[0] = bbsx;
2380                 start[1] = bbsy;
2381                 start[2] = bbsz;
2382         } 
2383         if(size) {
2384                 size[0] = bbex-bbsx;
2385                 size[1] = bbey-bbsy;
2386                 size[2] = bbez-bbsz;
2387         }
2388 }
2389
2390