- modified patch #4681, for scons compiling
[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 "BKE_deform.h"
68 #include "BKE_modifier.h"
69 #include "BKE_key.h"
70
71 #ifdef WITH_VERSE
72 #include "BKE_verse.h"
73 #endif
74
75 #include "BIF_gl.h"
76 #include "BIF_glutil.h"
77
78 // headers for fluidsim bobj meshes
79 #include <stdlib.h>
80 #include "LBM_fluidsim.h"
81 #include "elbeem.h"
82
83 ///////////////////////////////////
84 ///////////////////////////////////
85
86 typedef struct {
87         DerivedMesh dm;
88
89         Object *ob;
90         Mesh *me;
91         MVert *verts;
92         float *nors;
93         MCol *wpaintMCol;
94
95         int freeNors, freeVerts;
96 } MeshDerivedMesh;
97
98 static DispListMesh *meshDM_convertToDispListMesh(DerivedMesh *dm, int allowShared)
99 {
100         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
101         Mesh *me = mdm->me;
102         DispListMesh *dlm = MEM_callocN(sizeof(*dlm), "dlm");
103
104         dlm->totvert = me->totvert;
105         dlm->totedge = me->totedge;
106         dlm->totface = me->totface;
107         dlm->mvert = mdm->verts;
108         dlm->medge = me->medge;
109         dlm->mface = me->mface;
110         dlm->tface = me->tface;
111         dlm->mcol = me->mcol;
112         dlm->nors = mdm->nors;
113         dlm->dontFreeVerts = dlm->dontFreeOther = dlm->dontFreeNors = 1;
114
115         if (!allowShared) {
116                 dlm->mvert = MEM_dupallocN(dlm->mvert);
117                 if (dlm->nors) dlm->nors = MEM_dupallocN(dlm->nors);
118
119                 dlm->dontFreeVerts = dlm->dontFreeNors = 0;
120         }
121
122         return dlm;
123 }
124
125 static void meshDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
126 {
127         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
128         Mesh *me = mdm->me;
129         int i;
130
131         if (me->totvert) {
132                 for (i=0; i<me->totvert; i++) {
133                         DO_MINMAX(mdm->verts[i].co, min_r, max_r);
134                 }
135         } else {
136                 min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
137         }
138 }
139
140 static void meshDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
141 {
142         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
143         Mesh *me = mdm->me;
144         int i;
145
146         for (i=0; i<me->totvert; i++) {
147                 cos_r[i][0] = mdm->verts[i].co[0];
148                 cos_r[i][1] = mdm->verts[i].co[1];
149                 cos_r[i][2] = mdm->verts[i].co[2];
150         }
151 }
152
153 static void meshDM_getVertCo(DerivedMesh *dm, int index, float co_r[3])
154 {
155         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
156
157         VECCOPY(co_r, mdm->verts[index].co);
158 }
159
160 static void meshDM_getVertNo(DerivedMesh *dm, int index, float no_r[3])
161 {
162         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
163         short *no = mdm->verts[index].no;
164
165         no_r[0] = no[0]/32767.f;
166         no_r[1] = no[1]/32767.f;
167         no_r[2] = no[2]/32767.f;
168 }
169
170 static void meshDM_drawVerts(DerivedMesh *dm)
171 {
172         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
173         Mesh *me = mdm->me;
174         int i;
175
176         glBegin(GL_POINTS);
177         for(i=0; i<me->totvert; i++) {
178                 glVertex3fv(mdm->verts[i].co);
179         }
180         glEnd();
181 }
182 static void meshDM_drawUVEdges(DerivedMesh *dm)
183 {
184         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
185         Mesh *me = mdm->me;
186         int i;
187
188         if (me->tface) {
189                 glBegin(GL_LINES);
190                 for (i=0; i<me->totface; i++) {
191                         TFace *tf = &me->tface[i];
192
193                         if (!(tf->flag&TF_HIDE)) {
194                                 glVertex2fv(tf->uv[0]);
195                                 glVertex2fv(tf->uv[1]);
196
197                                 glVertex2fv(tf->uv[1]);
198                                 glVertex2fv(tf->uv[2]);
199
200                                 if (!me->mface[i].v4) {
201                                         glVertex2fv(tf->uv[2]);
202                                         glVertex2fv(tf->uv[0]);
203                                 } else {
204                                         glVertex2fv(tf->uv[2]);
205                                         glVertex2fv(tf->uv[3]);
206
207                                         glVertex2fv(tf->uv[3]);
208                                         glVertex2fv(tf->uv[0]);
209                                 }
210                         }
211                 }
212                 glEnd();
213         }
214 }
215 static void meshDM_drawEdges(DerivedMesh *dm, int drawLooseEdges)
216 {
217         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
218         Mesh *me= mdm->me;
219         MEdge *medge= me->medge;
220         int i;
221                 
222         glBegin(GL_LINES);
223         for(i=0; i<me->totedge; i++, medge++) {
224                 if ((medge->flag&ME_EDGEDRAW) && (drawLooseEdges || !(medge->flag&ME_LOOSEEDGE))) {
225                         glVertex3fv(mdm->verts[medge->v1].co);
226                         glVertex3fv(mdm->verts[medge->v2].co);
227                 }
228         }
229         glEnd();
230 }
231 static void meshDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
232 {
233         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
234         Mesh *me= mdm->me;
235         int i;
236                 
237         glBegin(GL_LINES);
238         for (i=0; i<me->totedge; i++) {
239                 if (!setDrawOptions || setDrawOptions(userData, i)) {
240                         glVertex3fv(mdm->verts[me->medge[i].v1].co);
241                         glVertex3fv(mdm->verts[me->medge[i].v2].co);
242                 }
243         }
244         glEnd();
245 }
246 static void meshDM_drawLooseEdges(DerivedMesh *dm)
247 {
248         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
249         Mesh *me= mdm->me;
250         MEdge *medge= me->medge;
251         int i;
252
253         glBegin(GL_LINES);
254         for (i=0; i<me->totedge; i++, medge++) {
255                 if (medge->flag&ME_LOOSEEDGE) {
256                         glVertex3fv(mdm->verts[medge->v1].co);
257                         glVertex3fv(mdm->verts[medge->v2].co);
258                 }
259         }
260         glEnd();
261 }
262 static void meshDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int))
263 {
264         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
265         Mesh *me = mdm->me;
266         MVert *mvert= mdm->verts;
267         MFace *mface= me->mface;
268         float *nors = mdm->nors;
269         int a;
270         int glmode=-1, shademodel=-1, matnr=-1, drawCurrentMat=1;
271
272 #define PASSVERT(index) {                                               \
273         if (shademodel==GL_SMOOTH) {                            \
274                 short *no = mvert[index].no;                    \
275                 glNormal3sv(no);                                                \
276         }                                                                                       \
277         glVertex3fv(mvert[index].co);   \
278 }
279
280         glBegin(glmode=GL_QUADS);
281         for(a=0; a<me->totface; a++, mface++, nors+=3) {
282                 int new_glmode, new_matnr, new_shademodel;
283                         
284                 new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
285                 new_matnr = mface->mat_nr+1;
286                 new_shademodel = (mface->flag & ME_SMOOTH)?GL_SMOOTH:GL_FLAT;
287                 
288                 if (new_glmode!=glmode || new_matnr!=matnr || new_shademodel!=shademodel) {
289                         glEnd();
290
291                         drawCurrentMat = setMaterial(matnr=new_matnr);
292
293                         glShadeModel(shademodel=new_shademodel);
294                         glBegin(glmode=new_glmode);
295                 } 
296                 
297                 if (drawCurrentMat) {
298                         if(shademodel==GL_FLAT) 
299                                 glNormal3fv(nors);
300
301                         PASSVERT(mface->v1);
302                         PASSVERT(mface->v2);
303                         PASSVERT(mface->v3);
304                         if (mface->v4) {
305                                 PASSVERT(mface->v4);
306                         }
307                 }
308         }
309         glEnd();
310
311         glShadeModel(GL_FLAT);
312 #undef PASSVERT
313 }
314
315 static void meshDM_drawFacesColored(DerivedMesh *dm, int useTwoSide, unsigned char *col1, unsigned char *col2)
316 {
317         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
318         Mesh *me= mdm->me;
319         MFace *mface= me->mface;
320         int a, glmode;
321         unsigned char *cp1, *cp2;
322
323         cp1= col1;
324         if(col2) {
325                 cp2= col2;
326         } else {
327                 cp2= NULL;
328                 useTwoSide= 0;
329         }
330
331         /* there's a conflict here... twosided colors versus culling...? */
332         /* defined by history, only texture faces have culling option */
333         /* we need that as mesh option builtin, next to double sided lighting */
334         if(col1 && col2)
335                 glEnable(GL_CULL_FACE);
336         
337         glShadeModel(GL_SMOOTH);
338         glBegin(glmode=GL_QUADS);
339         for(a=0; a<me->totface; a++, mface++, cp1+= 16) {
340                 int new_glmode= mface->v4?GL_QUADS:GL_TRIANGLES;
341
342                 if (new_glmode!=glmode) {
343                         glEnd();
344                         glBegin(glmode= new_glmode);
345                 }
346                         
347                 glColor3ub(cp1[3], cp1[2], cp1[1]);
348                 glVertex3fv( mdm->verts[mface->v1].co );
349                 glColor3ub(cp1[7], cp1[6], cp1[5]);
350                 glVertex3fv( mdm->verts[mface->v2].co );
351                 glColor3ub(cp1[11], cp1[10], cp1[9]);
352                 glVertex3fv( mdm->verts[mface->v3].co );
353                 if(mface->v4) {
354                         glColor3ub(cp1[15], cp1[14], cp1[13]);
355                         glVertex3fv( mdm->verts[mface->v4].co );
356                 }
357                         
358                 if(useTwoSide) {
359                         glColor3ub(cp2[11], cp2[10], cp2[9]);
360                         glVertex3fv( mdm->verts[mface->v3].co );
361                         glColor3ub(cp2[7], cp2[6], cp2[5]);
362                         glVertex3fv( mdm->verts[mface->v2].co );
363                         glColor3ub(cp2[3], cp2[2], cp2[1]);
364                         glVertex3fv( mdm->verts[mface->v1].co );
365                         if(mface->v4) {
366                                 glColor3ub(cp2[15], cp2[14], cp2[13]);
367                                 glVertex3fv( mdm->verts[mface->v4].co );
368                         }
369                 }
370                 if(col2) cp2+= 16;
371         }
372         glEnd();
373
374         glShadeModel(GL_FLAT);
375         glDisable(GL_CULL_FACE);
376 }
377
378 static void meshDM_drawFacesTex_common(DerivedMesh *dm, int (*drawParams)(TFace *tface, int matnr), int (*drawParamsMapped)(void *userData, int index), void *userData) 
379 {
380         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
381         Mesh *me = mdm->me;
382         MVert *mvert= mdm->verts;
383         MFace *mface= me->mface;
384         TFace *tface = me->tface;
385         float *nors = mdm->nors;
386         int i;
387
388         for (i=0; i<me->totface; i++) {
389                 MFace *mf= &mface[i];
390                 TFace *tf = tface?&tface[i]:NULL;
391                 int flag;
392                 unsigned char *cp= NULL;
393                 
394                 if (drawParams)
395                         flag = drawParams(tf, mf->mat_nr);
396                 else
397                         flag = drawParamsMapped(userData, i);
398
399                 if (flag==0) {
400                         continue;
401                 } else if (flag==1) {
402                         if (mdm->wpaintMCol) {
403                                 cp= (unsigned char*) &mdm->wpaintMCol[i*4];
404                         } else if (tf) {
405                                 cp= (unsigned char*) tf->col;
406                         } else if (me->mcol) {
407                                 cp= (unsigned char*) &me->mcol[i*4];
408                         }
409                 }
410
411                 if (!(mf->flag&ME_SMOOTH)) {
412                         glNormal3fv(&nors[i*3]);
413                 }
414
415                 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
416                 if (tf) glTexCoord2fv(tf->uv[0]);
417                 if (cp) glColor3ub(cp[3], cp[2], cp[1]);
418                 if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v1].no);
419                 glVertex3fv(mvert[mf->v1].co);
420                         
421                 if (tf) glTexCoord2fv(tf->uv[1]);
422                 if (cp) glColor3ub(cp[7], cp[6], cp[5]);
423                 if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v2].no);
424                 glVertex3fv(mvert[mf->v2].co);
425
426                 if (tf) glTexCoord2fv(tf->uv[2]);
427                 if (cp) glColor3ub(cp[11], cp[10], cp[9]);
428                 if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v3].no);
429                 glVertex3fv(mvert[mf->v3].co);
430
431                 if(mf->v4) {
432                         if (tf) glTexCoord2fv(tf->uv[3]);
433                         if (cp) glColor3ub(cp[15], cp[14], cp[13]);
434                         if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v4].no);
435                         glVertex3fv(mvert[mf->v4].co);
436                 }
437                 glEnd();
438         }
439 }
440 static void meshDM_drawFacesTex(DerivedMesh *dm, int (*setDrawParams)(TFace *tface, int matnr)) 
441 {
442         meshDM_drawFacesTex_common(dm, setDrawParams, NULL, NULL);
443 }
444 static void meshDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawParams)(void *userData, int index), void *userData) 
445 {
446         meshDM_drawFacesTex_common(dm, NULL, setDrawParams, userData);
447 }
448
449 static void meshDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors) 
450 {
451         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
452         Mesh *me = mdm->me;
453         MVert *mvert= mdm->verts;
454         MFace *mface= me->mface;
455         float *nors= mdm->nors;
456         int i;
457
458         for (i=0; i<me->totface; i++) {
459                 MFace *mf= &mface[i];
460                 int drawSmooth = 1;
461
462                 if (!setDrawOptions || setDrawOptions(userData, i, &drawSmooth)) {
463                         unsigned char *cp = NULL;
464
465                         if (useColors) {
466                                 if (mdm->wpaintMCol) {
467                                         cp= (unsigned char*) &mdm->wpaintMCol[i*4];
468                                 } else if (me->tface) {
469                                         cp= (unsigned char*) me->tface[i].col;
470                                 } else if (me->mcol) {
471                                         cp= (unsigned char*) &me->mcol[i*4];
472                                 }
473                         }
474
475                         glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
476                         glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
477
478                         if (!drawSmooth) {
479                                 glNormal3fv(&nors[i*3]);
480
481                                 if (cp) glColor3ub(cp[3], cp[2], cp[1]);
482                                 glVertex3fv(mvert[mf->v1].co);
483                                 if (cp) glColor3ub(cp[7], cp[6], cp[5]);
484                                 glVertex3fv(mvert[mf->v2].co);
485                                 if (cp) glColor3ub(cp[11], cp[10], cp[9]);
486                                 glVertex3fv(mvert[mf->v3].co);
487                                 if(mf->v4) {
488                                         if (cp) glColor3ub(cp[15], cp[14], cp[13]);
489                                         glVertex3fv(mvert[mf->v4].co);
490                                 }
491                         } else {
492                                 if (cp) glColor3ub(cp[3], cp[2], cp[1]);
493                                 glNormal3sv(mvert[mf->v1].no);
494                                 glVertex3fv(mvert[mf->v1].co);
495                                 if (cp) glColor3ub(cp[7], cp[6], cp[5]);
496                                 glNormal3sv(mvert[mf->v2].no);
497                                 glVertex3fv(mvert[mf->v2].co);
498                                 if (cp) glColor3ub(cp[11], cp[10], cp[9]);
499                                 glNormal3sv(mvert[mf->v3].no);
500                                 glVertex3fv(mvert[mf->v3].co);
501                                 if(mf->v4) {
502                                         if (cp) glColor3ub(cp[15], cp[14], cp[13]);
503                                         glNormal3sv(mvert[mf->v4].no);
504                                         glVertex3fv(mvert[mf->v4].co);
505                                 }
506                         }
507
508                         glEnd();
509                 }
510         }
511 }
512 static int meshDM_getNumVerts(DerivedMesh *dm)
513 {
514         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
515         Mesh *me = mdm->me;
516
517         return me->totvert;
518 }
519 static int meshDM_getNumFaces(DerivedMesh *dm)
520 {
521         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
522         Mesh *me = mdm->me;
523
524         return me->totface;
525 }
526
527 static void meshDM_release(DerivedMesh *dm)
528 {
529         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
530
531         if (mdm->wpaintMCol) MEM_freeN(mdm->wpaintMCol);
532         if (mdm->freeNors) MEM_freeN(mdm->nors);
533         if (mdm->freeVerts) MEM_freeN(mdm->verts);
534         MEM_freeN(mdm);
535 }
536
537 static DerivedMesh *getMeshDerivedMesh(Mesh *me, Object *ob, float (*vertCos)[3])
538 {
539         MeshDerivedMesh *mdm = MEM_callocN(sizeof(*mdm), "mdm");
540
541         mdm->dm.getMinMax = meshDM_getMinMax;
542
543         mdm->dm.convertToDispListMesh = meshDM_convertToDispListMesh;
544         mdm->dm.getNumVerts = meshDM_getNumVerts;
545         mdm->dm.getNumFaces = meshDM_getNumFaces;
546
547         mdm->dm.getVertCos = meshDM_getVertCos;
548         mdm->dm.getVertCo = meshDM_getVertCo;
549         mdm->dm.getVertNo = meshDM_getVertNo;
550
551         mdm->dm.drawVerts = meshDM_drawVerts;
552
553         mdm->dm.drawUVEdges = meshDM_drawUVEdges;
554         mdm->dm.drawEdges = meshDM_drawEdges;
555         mdm->dm.drawLooseEdges = meshDM_drawLooseEdges;
556         
557         mdm->dm.drawFacesSolid = meshDM_drawFacesSolid;
558         mdm->dm.drawFacesColored = meshDM_drawFacesColored;
559         mdm->dm.drawFacesTex = meshDM_drawFacesTex;
560         mdm->dm.drawMappedFaces = meshDM_drawMappedFaces;
561         mdm->dm.drawMappedFacesTex = meshDM_drawMappedFacesTex;
562
563         mdm->dm.drawMappedEdges = meshDM_drawMappedEdges;
564         mdm->dm.drawMappedFaces = meshDM_drawMappedFaces;
565
566         mdm->dm.release = meshDM_release;
567
568                 /* Works in conjunction with hack during modifier calc */
569         if ((G.f & G_WEIGHTPAINT) && ob==(G.scene->basact?G.scene->basact->object:NULL)) {
570                 mdm->wpaintMCol = MEM_dupallocN(me->mcol);
571         }
572
573         mdm->ob = ob;
574         mdm->me = me;
575         mdm->verts = me->mvert;
576         mdm->nors = NULL;
577         mdm->freeNors = 0;
578         mdm->freeVerts = 0;
579
580         if((ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) &&
581                  (ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN)&&
582            (ob->fluidsimSettings->meshSurface) &&
583                  (me->totvert == ((Mesh *)(ob->fluidsimSettings->meshSurface))->totvert) ) {
584                 // dont recompute for fluidsim mesh, use from readBobjgz
585                 // TODO? check for modifiers!?
586                 int i;
587                 mesh_calc_normals(mdm->verts, me->totvert, me->mface, me->totface, &mdm->nors);
588                 mdm->freeNors = 1;
589                 for (i=0; i<me->totvert; i++) {
590                         MVert *mv= &mdm->verts[i];
591                         MVert *fsv; 
592                         fsv = &ob->fluidsimSettings->meshSurfNormals[i];
593                         VECCOPY(mv->no, fsv->no);
594                         //mv->no[0]= 30000; mv->no[1]= mv->no[2]= 0; // DEBUG fixed test normals
595                 }
596         } else {
597                 // recompute normally
598
599                 if (vertCos) {
600                         int i;
601
602                         /* copy the original verts to preserve flag settings; if this is too
603                          * costly, must at least use MEM_callocN to clear flags */
604                         mdm->verts = MEM_dupallocN( me->mvert );
605                         for (i=0; i<me->totvert; i++) {
606                                 VECCOPY(mdm->verts[i].co, vertCos[i]);
607                         }
608                         mesh_calc_normals(mdm->verts, me->totvert, me->mface, me->totface, &mdm->nors);
609                         mdm->freeNors = 1;
610                         mdm->freeVerts = 1;
611                 } else {
612                         // XXX this is kinda hacky because we shouldn't really be editing
613                         // the mesh here, however, we can't just call mesh_build_faceNormals(ob)
614                         // because in the case when a key is applied to a mesh the vertex normals
615                         // would never be correctly computed.
616                         mesh_calc_normals(mdm->verts, me->totvert, me->mface, me->totface, &mdm->nors);
617                         mdm->freeNors = 1;
618                 }
619         } // fs TEST
620
621         return (DerivedMesh*) mdm;
622 }
623
624 ///
625
626 typedef struct {
627         DerivedMesh dm;
628
629         EditMesh *em;
630         float (*vertexCos)[3];
631         float (*vertexNos)[3];
632         float (*faceNos)[3];
633 } EditMeshDerivedMesh;
634
635 static void emDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData)
636 {
637         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
638         EditVert *eve;
639         int i;
640
641         for (i=0,eve= emdm->em->verts.first; eve; i++,eve=eve->next) {
642                 if (emdm->vertexCos) {
643                         func(userData, i, emdm->vertexCos[i], emdm->vertexNos[i], NULL);
644                 } else {
645                         func(userData, i, eve->co, eve->no, NULL);
646                 }
647         }
648 }
649 static void emDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData)
650 {
651         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
652         EditEdge *eed;
653         int i;
654
655         if (emdm->vertexCos) {
656                 EditVert *eve, *preveve;
657
658                 for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
659                         eve->prev = (EditVert*) i++;
660                 for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next)
661                         func(userData, i, emdm->vertexCos[(int) eed->v1->prev], emdm->vertexCos[(int) eed->v2->prev]);
662                 for (preveve=NULL, eve=emdm->em->verts.first; eve; preveve=eve, eve= eve->next)
663                         eve->prev = preveve;
664         } else {
665                 for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next)
666                         func(userData, i, eed->v1->co, eed->v2->co);
667         }
668 }
669 static void emDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) 
670 {
671         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
672         EditEdge *eed;
673         int i;
674
675         if (emdm->vertexCos) {
676                 EditVert *eve, *preveve;
677
678                 for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
679                         eve->prev = (EditVert*) i++;
680
681                 glBegin(GL_LINES);
682                 for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
683                         if(!setDrawOptions || setDrawOptions(userData, i)) {
684                                 glVertex3fv(emdm->vertexCos[(int) eed->v1->prev]);
685                                 glVertex3fv(emdm->vertexCos[(int) eed->v2->prev]);
686                         }
687                 }
688                 glEnd();
689
690                 for (preveve=NULL, eve=emdm->em->verts.first; eve; preveve=eve, eve= eve->next)
691                         eve->prev = preveve;
692         } else {
693                 glBegin(GL_LINES);
694                 for(i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
695                         if(!setDrawOptions || setDrawOptions(userData, i)) {
696                                 glVertex3fv(eed->v1->co);
697                                 glVertex3fv(eed->v2->co);
698                         }
699                 }
700                 glEnd();
701         }
702 }
703 static void emDM_drawEdges(DerivedMesh *dm, int drawLooseEdges)
704 {
705         emDM_drawMappedEdges(dm, NULL, NULL);
706 }
707 static void emDM_drawMappedEdgesInterp(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void (*setDrawInterpOptions)(void *userData, int index, float t), void *userData) 
708 {
709         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
710         EditEdge *eed;
711         int i;
712
713         if (emdm->vertexCos) {
714                 EditVert *eve, *preveve;
715
716                 for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
717                         eve->prev = (EditVert*) i++;
718
719                 glBegin(GL_LINES);
720                 for (i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
721                         if(!setDrawOptions || setDrawOptions(userData, i)) {
722                                 setDrawInterpOptions(userData, i, 0.0);
723                                 glVertex3fv(emdm->vertexCos[(int) eed->v1->prev]);
724                                 setDrawInterpOptions(userData, i, 1.0);
725                                 glVertex3fv(emdm->vertexCos[(int) eed->v2->prev]);
726                         }
727                 }
728                 glEnd();
729
730                 for (preveve=NULL, eve=emdm->em->verts.first; eve; preveve=eve, eve= eve->next)
731                         eve->prev = preveve;
732         } else {
733                 glBegin(GL_LINES);
734                 for (i=0,eed= emdm->em->edges.first; eed; i++,eed= eed->next) {
735                         if(!setDrawOptions || setDrawOptions(userData, i)) {
736                                 setDrawInterpOptions(userData, i, 0.0);
737                                 glVertex3fv(eed->v1->co);
738                                 setDrawInterpOptions(userData, i, 1.0);
739                                 glVertex3fv(eed->v2->co);
740                         }
741                 }
742                 glEnd();
743         }
744 }
745 static void emDM__calcFaceCent(EditFace *efa, float cent[3], float (*vertexCos)[3])
746 {
747         if (vertexCos) {
748                 VECCOPY(cent, vertexCos[(int) efa->v1->prev]);
749                 VecAddf(cent, cent, vertexCos[(int) efa->v2->prev]);
750                 VecAddf(cent, cent, vertexCos[(int) efa->v3->prev]);
751                 if (efa->v4) VecAddf(cent, cent, vertexCos[(int) efa->v4->prev]);
752         } else {
753                 VECCOPY(cent, efa->v1->co);
754                 VecAddf(cent, cent, efa->v2->co);
755                 VecAddf(cent, cent, efa->v3->co);
756                 if (efa->v4) VecAddf(cent, cent, efa->v4->co);
757         }
758
759         if (efa->v4) {
760                 VecMulf(cent, 0.25f);
761         } else {
762                 VecMulf(cent, 0.33333333333f);
763         }
764 }
765 static void emDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData)
766 {
767         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
768         EditVert *eve, *preveve;
769         EditFace *efa;
770         float cent[3];
771         int i;
772
773         if (emdm->vertexCos) {
774                 for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
775                         eve->prev = (EditVert*) i++;
776         }
777
778         for(i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) {
779                 emDM__calcFaceCent(efa, cent, emdm->vertexCos);
780                 func(userData, i, cent, emdm->vertexCos?emdm->faceNos[i]:efa->n);
781         }
782
783         if (emdm->vertexCos) {
784                 for (preveve=NULL, eve=emdm->em->verts.first; eve; preveve=eve, eve= eve->next)
785                         eve->prev = preveve;
786         }
787 }
788 static void emDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors)
789 {
790         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
791         EditFace *efa;
792         int i;
793
794         if (emdm->vertexCos) {
795                 EditVert *eve, *preveve;
796                 int drawSmooth = 1;
797
798                 for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
799                         eve->prev = (EditVert*) i++;
800
801                 for (i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) {
802                         if(!setDrawOptions || setDrawOptions(userData, i, &drawSmooth)) {
803                                 glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
804
805                                 glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
806                                 if (!drawSmooth) {
807                                         glNormal3fv(emdm->faceNos[i]);
808                                         glVertex3fv(emdm->vertexCos[(int) efa->v1->prev]);
809                                         glVertex3fv(emdm->vertexCos[(int) efa->v2->prev]);
810                                         glVertex3fv(emdm->vertexCos[(int) efa->v3->prev]);
811                                         if(efa->v4) glVertex3fv(emdm->vertexCos[(int) efa->v4->prev]);
812                                 } else {
813                                         glNormal3fv(emdm->vertexNos[(int) efa->v1->prev]);
814                                         glVertex3fv(emdm->vertexCos[(int) efa->v1->prev]);
815                                         glNormal3fv(emdm->vertexNos[(int) efa->v2->prev]);
816                                         glVertex3fv(emdm->vertexCos[(int) efa->v2->prev]);
817                                         glNormal3fv(emdm->vertexNos[(int) efa->v3->prev]);
818                                         glVertex3fv(emdm->vertexCos[(int) efa->v3->prev]);
819                                         if(efa->v4) {
820                                                 glNormal3fv(emdm->vertexNos[(int) efa->v4->prev]);
821                                                 glVertex3fv(emdm->vertexCos[(int) efa->v4->prev]);
822                                         }
823                                 }
824                                 glEnd();
825                         }
826                 }
827
828                 for (preveve=NULL, eve=emdm->em->verts.first; eve; preveve=eve, eve= eve->next)
829                         eve->prev = preveve;
830         } else {
831                 int drawSmooth = 1;
832
833                 for (i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) {
834                         if(!setDrawOptions || setDrawOptions(userData, i, &drawSmooth)) {
835                                 glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
836
837                                 glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
838                                 if (!drawSmooth) {
839                                         glNormal3fv(efa->n);
840                                         glVertex3fv(efa->v1->co);
841                                         glVertex3fv(efa->v2->co);
842                                         glVertex3fv(efa->v3->co);
843                                         if(efa->v4) glVertex3fv(efa->v4->co);
844                                 } else {
845                                         glNormal3fv(efa->v1->no);
846                                         glVertex3fv(efa->v1->co);
847                                         glNormal3fv(efa->v2->no);
848                                         glVertex3fv(efa->v2->co);
849                                         glNormal3fv(efa->v3->no);
850                                         glVertex3fv(efa->v3->co);
851                                         if(efa->v4) {
852                                                 glNormal3fv(efa->v4->no);
853                                                 glVertex3fv(efa->v4->co);
854                                         }
855                                 }
856                                 glEnd();
857                         }
858                 }
859         }
860 }
861
862 static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
863 {
864         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
865         EditVert *eve;
866         int i;
867
868         if (emdm->em->verts.first) {
869                 for (i=0,eve= emdm->em->verts.first; eve; i++,eve= eve->next) {
870                         if (emdm->vertexCos) {
871                                 DO_MINMAX(emdm->vertexCos[i], min_r, max_r);
872                         } else {
873                                 DO_MINMAX(eve->co, min_r, max_r);
874                         }
875                 }
876         } else {
877                 min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
878         }
879 }
880 static int emDM_getNumVerts(DerivedMesh *dm)
881 {
882         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
883
884         return BLI_countlist(&emdm->em->verts);
885 }
886 static int emDM_getNumFaces(DerivedMesh *dm)
887 {
888         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
889
890         return BLI_countlist(&emdm->em->faces);
891 }
892
893 static void emDM_release(DerivedMesh *dm)
894 {
895         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
896
897         if (emdm->vertexCos) {
898                 MEM_freeN(emdm->vertexCos);
899                 MEM_freeN(emdm->vertexNos);
900                 MEM_freeN(emdm->faceNos);
901         }
902
903         MEM_freeN(emdm);
904 }
905
906 static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em, float (*vertexCos)[3])
907 {
908         EditMeshDerivedMesh *emdm = MEM_callocN(sizeof(*emdm), "emdm");
909
910         emdm->dm.getMinMax = emDM_getMinMax;
911
912         emdm->dm.getNumVerts = emDM_getNumVerts;
913         emdm->dm.getNumFaces = emDM_getNumFaces;
914         emdm->dm.foreachMappedVert = emDM_foreachMappedVert;
915         emdm->dm.foreachMappedEdge = emDM_foreachMappedEdge;
916         emdm->dm.foreachMappedFaceCenter = emDM_foreachMappedFaceCenter;
917
918         emdm->dm.drawEdges = emDM_drawEdges;
919         emdm->dm.drawMappedEdges = emDM_drawMappedEdges;
920         emdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp;
921         emdm->dm.drawMappedFaces = emDM_drawMappedFaces;
922
923         emdm->dm.release = emDM_release;
924         
925         emdm->em = em;
926         emdm->vertexCos = vertexCos;
927
928         if (vertexCos) {
929                 EditVert *eve, *preveve;
930                 EditFace *efa;
931                 int totface = BLI_countlist(&em->faces);
932                 int i;
933
934                 for (i=0,eve=em->verts.first; eve; eve= eve->next)
935                         eve->prev = (EditVert*) i++;
936
937                 emdm->vertexNos = MEM_callocN(sizeof(*emdm->vertexNos)*i, "emdm_vno");
938                 emdm->faceNos = MEM_mallocN(sizeof(*emdm->faceNos)*totface, "emdm_vno");
939
940                 for(i=0, efa= em->faces.first; efa; i++, efa=efa->next) {
941                         float *v1 = vertexCos[(int) efa->v1->prev];
942                         float *v2 = vertexCos[(int) efa->v2->prev];
943                         float *v3 = vertexCos[(int) efa->v3->prev];
944                         float *no = emdm->faceNos[i];
945                         
946                         if(efa->v4) {
947                                 float *v4 = vertexCos[(int) efa->v3->prev];
948
949                                 CalcNormFloat4(v1, v2, v3, v4, no);
950                                 VecAddf(emdm->vertexNos[(int) efa->v4->prev], emdm->vertexNos[(int) efa->v4->prev], no);
951                         }
952                         else {
953                                 CalcNormFloat(v1, v2, v3, no);
954                         }
955
956                         VecAddf(emdm->vertexNos[(int) efa->v1->prev], emdm->vertexNos[(int) efa->v1->prev], no);
957                         VecAddf(emdm->vertexNos[(int) efa->v2->prev], emdm->vertexNos[(int) efa->v2->prev], no);
958                         VecAddf(emdm->vertexNos[(int) efa->v3->prev], emdm->vertexNos[(int) efa->v3->prev], no);
959                 }
960
961                 for(i=0, eve= em->verts.first; eve; i++, eve=eve->next) {
962                         float *no = emdm->vertexNos[i];
963                         /* following Mesh convention; we use vertex coordinate itself for normal in this case */
964                         if (Normalise(no)==0.0) {
965                                 VECCOPY(no, vertexCos[i]);
966                                 Normalise(no);
967                         }
968                 }
969
970                 for (preveve=NULL, eve=emdm->em->verts.first; eve; preveve=eve, eve= eve->next)
971                         eve->prev = preveve;
972         }
973
974         return (DerivedMesh*) emdm;
975 }
976
977 ///
978
979 typedef struct {
980         DerivedMesh dm;
981
982         DispListMesh *dlm;
983 } SSDerivedMesh;
984
985 static void ssDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData)
986 {
987         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
988         DispListMesh *dlm = ssdm->dlm;
989         int i, index=-1;
990
991         for (i=0; i<dlm->totvert; i++) {
992                 MVert *mv = &dlm->mvert[i];
993
994                 if (mv->flag&ME_VERT_STEPINDEX) {
995                         index++;
996
997                         func(userData, index, mv->co, NULL, mv->no);
998                 }
999         }
1000 }
1001 static void ssDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData)
1002 {
1003         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1004         DispListMesh *dlm = ssdm->dlm;
1005         int i, index=-1;
1006
1007         for (i=0; i<dlm->totedge; i++) {
1008                 MEdge *med = &dlm->medge[i];
1009
1010                 if (med->flag&ME_EDGE_STEPINDEX) index++;
1011
1012                 if (index!=-1) {
1013                         func(userData, index, dlm->mvert[med->v1].co, dlm->mvert[med->v2].co);
1014                 }
1015         }
1016 }
1017 static void ssDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) 
1018 {
1019         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1020         DispListMesh *dlm = ssdm->dlm;
1021         int i, index=-1;
1022
1023         glBegin(GL_LINES);
1024         for(i=0; i<dlm->totedge; i++) {
1025                 MEdge *med = &dlm->medge[i];
1026
1027                 if (med->flag&ME_EDGE_STEPINDEX) index++;
1028
1029                 if (index!=-1 && (!setDrawOptions || setDrawOptions(userData, index))) {
1030                         glVertex3fv(dlm->mvert[med->v1].co);
1031                         glVertex3fv(dlm->mvert[med->v2].co);
1032                 }
1033         }
1034         glEnd();
1035 }
1036
1037 static void ssDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no), void *userData)
1038 {
1039         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1040         DispListMesh *dlm = ssdm->dlm;
1041         int i, index=-1;
1042
1043         for (i=0; i<dlm->totface; i++) {
1044                 MFace *mf = &dlm->mface[i];
1045
1046                 if (mf->flag&ME_FACE_STEPINDEX) index++;
1047
1048                 if(index!=-1) {
1049                         float cent[3];
1050                         float no[3];
1051
1052                         VECCOPY(cent, dlm->mvert[mf->v1].co);
1053                         VecAddf(cent, cent, dlm->mvert[mf->v2].co);
1054                         VecAddf(cent, cent, dlm->mvert[mf->v3].co);
1055
1056                         if (mf->v4) {
1057                                 CalcNormFloat4(dlm->mvert[mf->v1].co, dlm->mvert[mf->v2].co, dlm->mvert[mf->v3].co, dlm->mvert[mf->v4].co, no);
1058                                 VecAddf(cent, cent, dlm->mvert[mf->v4].co);
1059                                 VecMulf(cent, 0.25f);
1060                         } else {
1061                                 CalcNormFloat(dlm->mvert[mf->v1].co, dlm->mvert[mf->v2].co, dlm->mvert[mf->v3].co, no);
1062                                 VecMulf(cent, 0.33333333333f);
1063                         }
1064
1065                         func(userData, index, cent, no);
1066                 }
1067         }
1068 }
1069 static void ssDM_drawVerts(DerivedMesh *dm)
1070 {
1071         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1072         DispListMesh *dlm = ssdm->dlm;
1073         MVert *mvert= dlm->mvert;
1074         int i;
1075
1076         bglBegin(GL_POINTS);
1077         for (i=0; i<dlm->totvert; i++) {
1078                 bglVertex3fv(mvert[i].co);
1079         }
1080         bglEnd();
1081 }
1082 static void ssDM_drawUVEdges(DerivedMesh *dm)
1083 {
1084         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1085         DispListMesh *dlm = ssdm->dlm;
1086         int i;
1087
1088         if (dlm->tface) {
1089                 glBegin(GL_LINES);
1090                 for (i=0; i<dlm->totface; i++) {
1091                         TFace *tf = &dlm->tface[i];
1092
1093                         if (!(tf->flag&TF_HIDE)) {
1094                                 glVertex2fv(tf->uv[0]);
1095                                 glVertex2fv(tf->uv[1]);
1096
1097                                 glVertex2fv(tf->uv[1]);
1098                                 glVertex2fv(tf->uv[2]);
1099
1100                                 if (!dlm->mface[i].v4) {
1101                                         glVertex2fv(tf->uv[2]);
1102                                         glVertex2fv(tf->uv[0]);
1103                                 } else {
1104                                         glVertex2fv(tf->uv[2]);
1105                                         glVertex2fv(tf->uv[3]);
1106
1107                                         glVertex2fv(tf->uv[3]);
1108                                         glVertex2fv(tf->uv[0]);
1109                                 }
1110                         }
1111                 }
1112                 glEnd();
1113         }
1114 }
1115 static void ssDM_drawLooseEdges(DerivedMesh *dm) 
1116 {
1117         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1118         DispListMesh *dlm = ssdm->dlm;
1119         MVert *mvert = dlm->mvert;
1120         MEdge *medge= dlm->medge;
1121         int i;
1122
1123         glBegin(GL_LINES);
1124         for (i=0; i<dlm->totedge; i++, medge++) {
1125                 if (medge->flag&ME_LOOSEEDGE) {
1126                         glVertex3fv(mvert[medge->v1].co); 
1127                         glVertex3fv(mvert[medge->v2].co);
1128                 }
1129         }
1130         glEnd();
1131 }
1132 static void ssDM_drawEdges(DerivedMesh *dm, int drawLooseEdges) 
1133 {
1134         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1135         DispListMesh *dlm = ssdm->dlm;
1136         MVert *mvert= dlm->mvert;
1137         MEdge *medge= dlm->medge;
1138         int i;
1139         
1140         glBegin(GL_LINES);
1141         for (i=0; i<dlm->totedge; i++, medge++) {
1142                 if ((medge->flag&ME_EDGEDRAW) && (drawLooseEdges || !(medge->flag&ME_LOOSEEDGE))) {
1143                         glVertex3fv(mvert[medge->v1].co); 
1144                         glVertex3fv(mvert[medge->v2].co);
1145                 }
1146         }
1147         glEnd();
1148 }
1149 static void ssDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int))
1150 {
1151         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1152         DispListMesh *dlm = ssdm->dlm;
1153         float *nors = dlm->nors;
1154         int glmode=-1, shademodel=-1, matnr=-1, drawCurrentMat=1;
1155         int i;
1156
1157 #define PASSVERT(ind) {                                         \
1158         if (shademodel==GL_SMOOTH)                              \
1159                 glNormal3sv(dlm->mvert[(ind)].no);      \
1160         glVertex3fv(dlm->mvert[(ind)].co);              \
1161 }
1162
1163         glBegin(glmode=GL_QUADS);
1164         for (i=0; i<dlm->totface; i++) {
1165                 MFace *mf= &dlm->mface[i];
1166                 int new_glmode = mf->v4?GL_QUADS:GL_TRIANGLES;
1167                 int new_shademodel = (mf->flag&ME_SMOOTH)?GL_SMOOTH:GL_FLAT;
1168                 int new_matnr = mf->mat_nr+1;
1169                 
1170                 if(new_glmode!=glmode || new_shademodel!=shademodel || new_matnr!=matnr) {
1171                         glEnd();
1172
1173                         drawCurrentMat = setMaterial(matnr=new_matnr);
1174
1175                         glShadeModel(shademodel=new_shademodel);
1176                         glBegin(glmode=new_glmode);
1177                 }
1178                 
1179                 if (drawCurrentMat) {
1180                         if (shademodel==GL_FLAT)
1181                                 glNormal3fv(&nors[i*3]);
1182                                 
1183                         PASSVERT(mf->v1);
1184                         PASSVERT(mf->v2);
1185                         PASSVERT(mf->v3);
1186                         if (mf->v4)
1187                                 PASSVERT(mf->v4);
1188                 }
1189         }
1190         glEnd();
1191         
1192 #undef PASSVERT
1193 }
1194 static void ssDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *vcols1, unsigned char *vcols2)
1195 {
1196         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1197         DispListMesh *dlm = ssdm->dlm;
1198         int i, lmode;
1199         
1200         glShadeModel(GL_SMOOTH);
1201         if (vcols2) {
1202                 glEnable(GL_CULL_FACE);
1203         } else {
1204                 useTwoSided = 0;
1205         }
1206                 
1207 #define PASSVERT(vidx, fidx) {                                  \
1208         unsigned char *col= &colbase[fidx*4];           \
1209         glColor3ub(col[3], col[2], col[1]);                     \
1210         glVertex3fv(dlm->mvert[(vidx)].co);                     \
1211 }
1212
1213         glBegin(lmode= GL_QUADS);
1214         for (i=0; i<dlm->totface; i++) {
1215                 MFace *mf= &dlm->mface[i];
1216                 int nmode= mf->v4?GL_QUADS:GL_TRIANGLES;
1217                 unsigned char *colbase= &vcols1[i*16];
1218                 
1219                 if (nmode!=lmode) {
1220                         glEnd();
1221                         glBegin(lmode= nmode);
1222                 }
1223                 
1224                 PASSVERT(mf->v1, 0);
1225                 PASSVERT(mf->v2, 1);
1226                 PASSVERT(mf->v3, 2);
1227                 if (mf->v4)
1228                         PASSVERT(mf->v4, 3);
1229                 
1230                 if (useTwoSided) {
1231                         unsigned char *colbase= &vcols2[i*16];
1232
1233                         if (mf->v4)
1234                                 PASSVERT(mf->v4, 3);
1235                         PASSVERT(mf->v3, 2);
1236                         PASSVERT(mf->v2, 1);
1237                         PASSVERT(mf->v1, 0);
1238                 }
1239         }
1240         glEnd();
1241
1242         if (vcols2)
1243                 glDisable(GL_CULL_FACE);
1244         
1245 #undef PASSVERT
1246 }
1247
1248 static void ssDM_drawFacesTex_common(DerivedMesh *dm, int (*drawParams)(TFace *tface, int matnr), int (*drawParamsMapped)(void *userData, int index), void *userData) 
1249 {
1250         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1251         DispListMesh *dlm = ssdm->dlm;
1252         MVert *mvert= dlm->mvert;
1253         MFace *mface= dlm->mface;
1254         TFace *tface = dlm->tface;
1255         float *nors = dlm->nors;
1256         int a, index=-1;
1257         
1258         for (a=0; a<dlm->totface; a++) {
1259                 MFace *mf= &mface[a];
1260                 TFace *tf = tface?&tface[a]:NULL;
1261                 int flag;
1262                 unsigned char *cp= NULL;
1263                 
1264                 if (drawParams) {
1265                         flag = drawParams(tf, mf->mat_nr);
1266                 }
1267                 else {
1268                         if (mf->flag&ME_FACE_STEPINDEX) index++;
1269                         flag = drawParamsMapped(userData, index);
1270                 }
1271
1272                 if (flag==0) {
1273                         continue;
1274                 } else if (flag==1) {
1275                         if (tf) {
1276                                 cp= (unsigned char*) tf->col;
1277                         } else if (dlm->mcol) {
1278                                 cp= (unsigned char*) &dlm->mcol[a*4];
1279                         }
1280                 }
1281
1282                 if (!(mf->flag&ME_SMOOTH)) {
1283                         glNormal3fv(&nors[a*3]);
1284                 }
1285
1286                 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
1287                 if (tf) glTexCoord2fv(tf->uv[0]);
1288                 if (cp) glColor3ub(cp[3], cp[2], cp[1]);
1289                 if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v1].no);
1290                 glVertex3fv((mvert+mf->v1)->co);
1291                         
1292                 if (tf) glTexCoord2fv(tf->uv[1]);
1293                 if (cp) glColor3ub(cp[7], cp[6], cp[5]);
1294                 if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v2].no);
1295                 glVertex3fv((mvert+mf->v2)->co);
1296
1297                 if (tf) glTexCoord2fv(tf->uv[2]);
1298                 if (cp) glColor3ub(cp[11], cp[10], cp[9]);
1299                 if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v3].no);
1300                 glVertex3fv((mvert+mf->v3)->co);
1301
1302                 if(mf->v4) {
1303                         if (tf) glTexCoord2fv(tf->uv[3]);
1304                         if (cp) glColor3ub(cp[15], cp[14], cp[13]);
1305                         if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v4].no);
1306                         glVertex3fv((mvert+mf->v4)->co);
1307                 }
1308                 glEnd();
1309         }
1310 }
1311 static void ssDM_drawFacesTex(DerivedMesh *dm, int (*setDrawParams)(TFace *tface, int matnr))
1312 {
1313         ssDM_drawFacesTex_common(dm, setDrawParams, NULL, NULL);
1314 }
1315 static void ssDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawParams)(void *userData, int index), void *userData) 
1316 {
1317         ssDM_drawFacesTex_common(dm, NULL, setDrawParams, userData);
1318 }
1319
1320 static void ssDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors) 
1321 {
1322         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1323         DispListMesh *dlm = ssdm->dlm;
1324         MVert *mvert= dlm->mvert;
1325         MFace *mface= dlm->mface;
1326         float *nors = dlm->nors;
1327         int i, index=-1;
1328
1329         for (i=0; i<dlm->totface; i++) {
1330                 MFace *mf = &mface[i];
1331                 int drawSmooth = 1;
1332
1333                 if (mf->flag&ME_FACE_STEPINDEX) index++;
1334
1335                 if (index!=-1 && (!setDrawOptions || setDrawOptions(userData, index, &drawSmooth))) {
1336                         unsigned char *cp = NULL;
1337
1338                         if (useColors) {
1339                                 if (dlm->tface) {
1340                                         cp= (unsigned char*) dlm->tface[i].col;
1341                                 } else if (dlm->mcol) {
1342                                         cp= (unsigned char*) &dlm->mcol[i*4];
1343                                 }
1344                         }
1345
1346                         glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
1347                         glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
1348
1349                         if (!drawSmooth) {
1350                                 glNormal3fv(&nors[i*3]);
1351
1352                                 if (cp) glColor3ub(cp[3], cp[2], cp[1]);
1353                                 glVertex3fv(mvert[mf->v1].co);
1354                                 if (cp) glColor3ub(cp[7], cp[6], cp[5]);
1355                                 glVertex3fv(mvert[mf->v2].co);
1356                                 if (cp) glColor3ub(cp[11], cp[10], cp[9]);
1357                                 glVertex3fv(mvert[mf->v3].co);
1358                                 if(mf->v4) {
1359                                         if (cp) glColor3ub(cp[15], cp[14], cp[13]);
1360                                         glVertex3fv(mvert[mf->v4].co);
1361                                 }
1362                         } else {
1363                                 if (cp) glColor3ub(cp[3], cp[2], cp[1]);
1364                                 glNormal3sv(mvert[mf->v1].no);
1365                                 glVertex3fv(mvert[mf->v1].co);
1366                                 if (cp) glColor3ub(cp[7], cp[6], cp[5]);
1367                                 glNormal3sv(mvert[mf->v2].no);
1368                                 glVertex3fv(mvert[mf->v2].co);
1369                                 if (cp) glColor3ub(cp[11], cp[10], cp[9]);
1370                                 glNormal3sv(mvert[mf->v3].no);
1371                                 glVertex3fv(mvert[mf->v3].co);
1372                                 if(mf->v4) {
1373                                         if (cp) glColor3ub(cp[15], cp[14], cp[13]);
1374                                         glNormal3sv(mvert[mf->v4].no);
1375                                         glVertex3fv(mvert[mf->v4].co);
1376                                 }
1377                         }
1378
1379                         glEnd();
1380                 }
1381         }
1382 }
1383 static void ssDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
1384 {
1385         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1386         int i;
1387
1388         if (ssdm->dlm->totvert) {
1389                 for (i=0; i<ssdm->dlm->totvert; i++) {
1390                         DO_MINMAX(ssdm->dlm->mvert[i].co, min_r, max_r);
1391                 }
1392         } else {
1393                 min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
1394         }
1395 }
1396
1397 static void ssDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
1398 {
1399         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1400         int i;
1401
1402         for (i=0; i<ssdm->dlm->totvert; i++) {
1403                 cos_r[i][0] = ssdm->dlm->mvert[i].co[0];
1404                 cos_r[i][1] = ssdm->dlm->mvert[i].co[1];
1405                 cos_r[i][2] = ssdm->dlm->mvert[i].co[2];
1406         }
1407 }
1408
1409 static int ssDM_getNumVerts(DerivedMesh *dm)
1410 {
1411         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1412
1413         return ssdm->dlm->totvert;
1414 }
1415 static int ssDM_getNumFaces(DerivedMesh *dm)
1416 {
1417         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1418
1419         return ssdm->dlm->totface;
1420 }
1421
1422 static DispListMesh *ssDM_convertToDispListMesh(DerivedMesh *dm, int allowShared)
1423 {
1424         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1425
1426         if (allowShared) {
1427                 return displistmesh_copyShared(ssdm->dlm);
1428         } else {
1429                 return displistmesh_copy(ssdm->dlm);
1430         }
1431 }
1432
1433 static void ssDM_release(DerivedMesh *dm)
1434 {
1435         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1436
1437         displistmesh_free(ssdm->dlm);
1438
1439         MEM_freeN(dm);
1440 }
1441
1442 DerivedMesh *derivedmesh_from_displistmesh(DispListMesh *dlm, float (*vertexCos)[3])
1443 {
1444         SSDerivedMesh *ssdm = MEM_callocN(sizeof(*ssdm), "ssdm");
1445
1446         ssdm->dm.getMinMax = ssDM_getMinMax;
1447
1448         ssdm->dm.getNumVerts = ssDM_getNumVerts;
1449         ssdm->dm.getNumFaces = ssDM_getNumFaces;
1450         ssdm->dm.convertToDispListMesh = ssDM_convertToDispListMesh;
1451
1452         ssdm->dm.getVertCos = ssDM_getVertCos;
1453
1454         ssdm->dm.drawVerts = ssDM_drawVerts;
1455
1456         ssdm->dm.drawUVEdges = ssDM_drawUVEdges;
1457         ssdm->dm.drawEdges = ssDM_drawEdges;
1458         ssdm->dm.drawLooseEdges = ssDM_drawLooseEdges;
1459         
1460         ssdm->dm.drawFacesSolid = ssDM_drawFacesSolid;
1461         ssdm->dm.drawFacesColored = ssDM_drawFacesColored;
1462         ssdm->dm.drawFacesTex = ssDM_drawFacesTex;
1463         ssdm->dm.drawMappedFaces = ssDM_drawMappedFaces;
1464         ssdm->dm.drawMappedFacesTex = ssDM_drawMappedFacesTex;
1465
1466                 /* EM functions */
1467         
1468         ssdm->dm.foreachMappedVert = ssDM_foreachMappedVert;
1469         ssdm->dm.foreachMappedEdge = ssDM_foreachMappedEdge;
1470         ssdm->dm.foreachMappedFaceCenter = ssDM_foreachMappedFaceCenter;
1471         
1472         ssdm->dm.drawMappedEdges = ssDM_drawMappedEdges;
1473         ssdm->dm.drawMappedEdgesInterp = NULL; // no way to implement this one
1474         
1475         ssdm->dm.release = ssDM_release;
1476         
1477         ssdm->dlm = dlm;
1478
1479         if (vertexCos) {
1480                 int i;
1481
1482                 for (i=0; i<dlm->totvert; i++) {
1483                         VECCOPY(dlm->mvert[i].co, vertexCos[i]);
1484                 }
1485
1486                 if (dlm->nors && !dlm->dontFreeNors) {
1487                         MEM_freeN(dlm->nors);
1488                         dlm->nors = 0;
1489                 }
1490
1491                 mesh_calc_normals(dlm->mvert, dlm->totvert, dlm->mface, dlm->totface, &dlm->nors);
1492         }
1493
1494         return (DerivedMesh*) ssdm;
1495 }
1496
1497 #ifdef WITH_VERSE
1498
1499 /* verse derived mesh */
1500 typedef struct {
1501         struct DerivedMesh dm;
1502         struct VNode *vnode;
1503         struct VLayer *vertex_layer;
1504         struct VLayer *polygon_layer;
1505         float (*verts)[3];
1506 } VDerivedMesh;
1507
1508 /* this function set up border points of verse mesh bounding box */
1509 static void vDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
1510 {
1511         VDerivedMesh *vdm = (VDerivedMesh*)dm;
1512         struct VerseVert *vvert;
1513
1514         if(!vdm->vertex_layer) return;
1515
1516         vvert = (VerseVert*)vdm->vertex_layer->dl.lb.first;
1517
1518         if(vdm->vertex_layer->dl.da.count > 0) {
1519                 while(vvert) {
1520                         DO_MINMAX(vdm->verts ? vvert->cos : vvert->co, min_r, max_r);
1521                         vvert = vvert->next;
1522                 }
1523         }
1524         else {
1525                 min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
1526         }
1527 }
1528
1529 /* this function return number of vertexes in vertex layer */
1530 static int vDM_getNumVerts(DerivedMesh *dm)
1531 {
1532         VDerivedMesh *vdm = (VDerivedMesh*)dm;
1533
1534         if(!vdm->vertex_layer) return 0;
1535         else return vdm->vertex_layer->dl.da.count;
1536 }
1537
1538 /* this function returns number of polygons in polygon layer */
1539 static int vDM_getNumFaces(DerivedMesh *dm)
1540 {
1541         VDerivedMesh *vdm = (VDerivedMesh*)dm;
1542
1543         if(!vdm->polygon_layer) return 0;
1544         else return vdm->polygon_layer->dl.da.count;
1545 }
1546
1547 /* create diplist mesh from verse mesh */
1548 static DispListMesh* vDM_convertToDispListMesh(DerivedMesh *dm, int allowShared)
1549 {
1550         VDerivedMesh *vdm = (VDerivedMesh*)dm;
1551         DispListMesh *dlm = MEM_callocN(sizeof(*dlm), "dlm");
1552         struct VerseVert *vvert;
1553         struct VerseFace *vface;
1554         struct MVert *mvert=NULL;
1555         struct MFace *mface=NULL;
1556         float *norms;
1557         unsigned int i;
1558
1559         if(!vdm->vertex_layer || !vdm->polygon_layer) {
1560                 dlm->totvert = 0;
1561                 dlm->totedge = 0;
1562                 dlm->totface = 0;
1563                 dlm->dontFreeVerts = dlm->dontFreeOther = dlm->dontFreeNors = 0;
1564
1565                 return dlm;
1566         };
1567         
1568         /* number of vertexes, edges and faces */
1569         dlm->totvert = vdm->vertex_layer->dl.da.count;
1570         dlm->totedge = 0;
1571         dlm->totface = vdm->polygon_layer->dl.da.count;
1572
1573         /* create dynamic array of mverts */
1574         mvert = (MVert*)MEM_mallocN(sizeof(MVert)*dlm->totvert, "dlm verts");
1575         dlm->mvert = mvert;
1576         vvert = (VerseVert*)vdm->vertex_layer->dl.lb.first;
1577         i = 0;
1578         while(vvert) {
1579                 VECCOPY(mvert->co, vdm->verts ? vvert->cos : vvert->co);
1580                 VECCOPY(mvert->no, vvert->no);
1581                 mvert->mat_nr = 0;
1582                 mvert->flag = 0;
1583
1584                 vvert->tmp.index = i++;
1585                 mvert++;
1586                 vvert = vvert->next;
1587         }
1588
1589         /* verse doesn't support edges */
1590         dlm->medge = NULL;
1591
1592         /* create dynamic array of faces */
1593         mface = (MFace*)MEM_mallocN(sizeof(MFace)*dlm->totface, "dlm faces");
1594         dlm->mface = mface;
1595         vface = (VerseFace*)vdm->polygon_layer->dl.lb.first;
1596         i = 0;
1597         while(vface) {
1598                 mface->v1 = vface->vvert0->tmp.index;
1599                 mface->v2 = vface->vvert1->tmp.index;
1600                 mface->v3 = vface->vvert2->tmp.index;
1601                 if(vface->vvert3) mface->v4 = vface->vvert3->tmp.index;
1602                 else mface->v4 = 0;
1603
1604                 mface->pad = 0;
1605                 mface->mat_nr = 0;
1606                 mface->flag = 0;
1607                 mface->edcode = 0;
1608
1609                 test_index_face(mface, NULL, NULL, vface->vvert3?4:3);
1610
1611                 mface++;
1612                 vface = vface->next;
1613         }
1614
1615         /* textures and verex colors aren't supported yet */
1616         dlm->tface = NULL;
1617         dlm->mcol = NULL;
1618
1619         /* faces normals */
1620         norms = (float*)MEM_mallocN(sizeof(float)*3*dlm->totface, "dlm norms");
1621         dlm->nors = norms;
1622
1623         vface = (VerseFace*)vdm->polygon_layer->dl.lb.first;
1624         while(vface){
1625                 VECCOPY(norms, vface->no);
1626                 norms += 3;
1627                 vface = vface->next;
1628         }
1629
1630         /* free everything, nothing is shared */
1631         dlm->dontFreeVerts = dlm->dontFreeOther = dlm->dontFreeNors = 0;
1632
1633         return dlm;
1634 }
1635
1636 /* return coordination of vertex with index ... I suppose, that it will
1637  * be very hard to do, becuase there can be holes in access array */
1638 static void vDM_getVertCo(DerivedMesh *dm, int index, float co_r[3])
1639 {
1640         VDerivedMesh *vdm = (VDerivedMesh*)dm;
1641         struct VerseVert *vvert = NULL;
1642
1643         if(!vdm->vertex_layer) return;
1644
1645         vvert = BLI_dlist_find_link(&(vdm->vertex_layer->dl), index);
1646         if(vvert) {
1647                 VECCOPY(co_r, vdm->verts ? vvert->cos : vvert->co);
1648         }
1649         else {
1650                 co_r[0] = co_r[1] = co_r[2] = 0.0;
1651         }
1652 }
1653
1654 /* return array of vertex coordiantions */
1655 static void vDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
1656 {
1657         VDerivedMesh *vdm = (VDerivedMesh*)dm;
1658         struct VerseVert *vvert;
1659         int i = 0;
1660
1661         if(!vdm->vertex_layer) return;
1662
1663         vvert = vdm->vertex_layer->dl.lb.first;
1664         while(vvert) {
1665                 VECCOPY(cos_r[i], vdm->verts ? vvert->cos : vvert->co);
1666                 i++;
1667                 vvert = vvert->next;
1668         }
1669 }
1670
1671 /* return normal of vertex with index ... again, it will be hard to
1672  * implemente, because access array */
1673 static void vDM_getVertNo(DerivedMesh *dm, int index, float no_r[3])
1674 {
1675         VDerivedMesh *vdm = (VDerivedMesh*)dm;
1676         struct VerseVert *vvert = NULL;
1677
1678         if(!vdm->vertex_layer) return;
1679
1680         vvert = BLI_dlist_find_link(&(vdm->vertex_layer->dl), index);
1681         if(vvert) {
1682                 VECCOPY(no_r, vvert->no);
1683         }
1684         else {
1685                 no_r[0] = no_r[1] = no_r[2] = 0.0;
1686         }
1687 }
1688
1689 /* draw all VerseVertexes */
1690 static void vDM_drawVerts(DerivedMesh *dm)
1691 {
1692         VDerivedMesh *vdm = (VDerivedMesh*)dm;
1693         struct VerseVert *vvert;
1694
1695         if(!vdm->vertex_layer) return;
1696
1697         vvert = vdm->vertex_layer->dl.lb.first;
1698
1699         bglBegin(GL_POINTS);
1700         while(vvert) {
1701                 bglVertex3fv(vdm->verts ? vvert->cos : vvert->co);
1702                 vvert = vvert->next;
1703         }
1704         bglEnd();
1705 }
1706
1707 /* draw all edges of VerseFaces ... it isn't optimal, because verse
1708  * specification doesn't support edges :-( ... bother eskil ;-)
1709  * ... some edges (most of edges) are drawn twice */
1710 static void vDM_drawEdges(DerivedMesh *dm, int drawLooseEdges)
1711 {
1712         VDerivedMesh *vdm = (VDerivedMesh*)dm;
1713         struct VerseFace *vface;
1714
1715         if(!vdm->polygon_layer) return;
1716
1717         vface = vdm->polygon_layer->dl.lb.first;
1718
1719         while(vface) {
1720                 glBegin(GL_LINE_LOOP);
1721                 glVertex3fv(vdm->verts ? vface->vvert0->cos : vface->vvert0->co);
1722                 glVertex3fv(vdm->verts ? vface->vvert1->cos : vface->vvert1->co);
1723                 glVertex3fv(vdm->verts ? vface->vvert2->cos : vface->vvert2->co);
1724                 if(vface->vvert3) glVertex3fv(vdm->verts ? vface->vvert3->cos : vface->vvert3->co);
1725                 glEnd();
1726
1727                 vface = vface->next;
1728         }
1729 }
1730
1731 /* verse spec doesn't support edges ... loose edges can't exist */
1732 void vDM_drawLooseEdges(DerivedMesh *dm)
1733 {
1734 }
1735
1736 /* draw uv edges, not supported yet */
1737 static void vDM_drawUVEdges(DerivedMesh *dm)
1738 {
1739 }
1740
1741 /* draw all VerseFaces */
1742 static void vDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int))
1743 {
1744         VDerivedMesh *vdm = (VDerivedMesh*)dm;
1745         struct VerseFace *vface;
1746
1747         if(!vdm->polygon_layer) return;
1748
1749         vface = vdm->polygon_layer->dl.lb.first;
1750
1751         while(vface) {
1752 /*              if((vface->smooth) && (vface->smooth->value)){
1753                         glShadeModel(GL_SMOOTH);
1754                         glBegin(vface->vvert3?GL_QUADS:GL_TRIANGLES);
1755                         glNormal3fv(vface->vvert0->no);
1756                         glVertex3fv(vdm->verts ? vface->vvert0->cos : vface->vvert0->co);
1757                         glNormal3fv(vface->vvert1->no);
1758                         glVertex3fv(vdm->verts ? vface->vvert1->cos : vface->vvert1->co);
1759                         glNormal3fv(vface->vvert2->no);
1760                         glVertex3fv(vdm->verts ? vface->vvert2->cos : vface->vvert2->co);
1761                         if(vface->vvert3){
1762                                 glNormal3fv(vface->vvert3->no);
1763                                 glVertex3fv(vdm->verts ? vface->vvert3->cos : vface->vvert3->co);
1764                         }
1765                         glEnd();
1766                 }
1767                 else { */
1768                         glShadeModel(GL_FLAT);
1769                         glBegin(vface->vvert3?GL_QUADS:GL_TRIANGLES);
1770                         glNormal3fv(vface->no);
1771                         glVertex3fv(vdm->verts ? vface->vvert0->cos : vface->vvert0->co);
1772                         glVertex3fv(vdm->verts ? vface->vvert1->cos : vface->vvert1->co);
1773                         glVertex3fv(vdm->verts ? vface->vvert2->cos : vface->vvert2->co);
1774                         if(vface->vvert3)
1775                                 glVertex3fv(vdm->verts ? vface->vvert3->cos : vface->vvert3->co);
1776                         glEnd();
1777 /*              } */
1778
1779                 vface = vface->next;
1780         }
1781         glShadeModel(GL_FLAT);
1782 }
1783
1784 /* thsi function should draw mesh with mapped texture, but it isn't supported yet */
1785 static void vDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(struct TFace *tface, int matnr))
1786 {
1787         VDerivedMesh *vdm = (VDerivedMesh*)dm;
1788         struct VerseFace *vface;
1789
1790         if(!vdm->polygon_layer) return;
1791
1792         vface = vdm->polygon_layer->dl.lb.first;
1793
1794         while(vface) {
1795                 glBegin(vface->vvert3?GL_QUADS:GL_TRIANGLES);
1796                 glVertex3fv(vdm->verts ? vface->vvert0->cos : vface->vvert0->co);
1797                 glVertex3fv(vdm->verts ? vface->vvert1->cos : vface->vvert1->co);
1798                 glVertex3fv(vdm->verts ? vface->vvert2->cos : vface->vvert2->co);
1799                 if(vface->vvert3)
1800                         glVertex3fv(vdm->verts ? vface->vvert3->cos : vface->vvert3->co);
1801                 glEnd();
1802
1803                 vface = vface->next;
1804         }
1805 }
1806
1807 /* this function should draw mesh with colored faces (weight paint, vertex
1808  * colors, etc.), but it isn't supported yet */
1809 static void vDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2)
1810 {
1811         VDerivedMesh *vdm = (VDerivedMesh*)dm;
1812         struct VerseFace *vface;
1813
1814         if(!vdm->polygon_layer) return;
1815
1816         vface = vdm->polygon_layer->dl.lb.first;
1817
1818         while(vface) {
1819                 glBegin(vface->vvert3?GL_QUADS:GL_TRIANGLES);
1820                 glVertex3fv(vdm->verts ? vface->vvert0->cos : vface->vvert0->co);
1821                 glVertex3fv(vdm->verts ? vface->vvert1->cos : vface->vvert1->co);
1822                 glVertex3fv(vdm->verts ? vface->vvert2->cos : vface->vvert2->co);
1823                 if(vface->vvert3)
1824                         glVertex3fv(vdm->verts ? vface->vvert3->cos : vface->vvert3->co);
1825                 glEnd();
1826
1827                 vface = vface->next;
1828         }
1829 }
1830
1831 /**/
1832 static void vDM_foreachMappedVert(
1833                 DerivedMesh *dm,
1834                 void (*func)(void *userData, int index, float *co, float *no_f, short *no_s),
1835                 void *userData)
1836 {
1837 }
1838
1839 /**/
1840 static void vDM_foreachMappedEdge(
1841                 DerivedMesh *dm,
1842                 void (*func)(void *userData, int index, float *v0co, float *v1co),
1843                 void *userData)
1844 {
1845 }
1846
1847 /**/
1848 static void vDM_foreachMappedFaceCenter(
1849                 DerivedMesh *dm,
1850                 void (*func)(void *userData, int index, float *cent, float *no),
1851                 void *userData)
1852 {
1853 }
1854
1855 /**/
1856 static void vDM_drawMappedFacesTex(
1857                 DerivedMesh *dm,
1858                 int (*setDrawOptions)(void *userData, int index, int matnr),
1859                 void *userData)
1860 {
1861 }
1862
1863 /**/
1864 static void vDM_drawMappedFaces(
1865                 DerivedMesh *dm,
1866                 int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r),
1867                 void *userData,
1868                 int useColors)
1869 {
1870 }
1871
1872 /**/
1873 static void vDM_drawMappedEdges(
1874                 DerivedMesh *dm,
1875                 int (*setDrawOptions)(void *userData, int index),
1876                 void *userData)
1877 {
1878 }
1879
1880 /**/
1881 static void vDM_drawMappedEdgesInterp(
1882                 DerivedMesh *dm, 
1883                 int (*setDrawOptions)(void *userData, int index), 
1884                 void (*setDrawInterpOptions)(void *userData, int index, float t),
1885                 void *userData)
1886 {
1887 }
1888
1889 /* free all DerivedMesh data */
1890 static void vDM_release(DerivedMesh *dm)
1891 {
1892         VDerivedMesh *vdm = (VDerivedMesh*)dm;
1893
1894         if(vdm->verts) MEM_freeN(vdm->verts);
1895         MEM_freeN(vdm);
1896 }
1897
1898 /* create derived mesh from verse mesh ... it is used in object mode, when some other client can
1899  * change shared data and want to see this changes in real time too */
1900 DerivedMesh *derivedmesh_from_versemesh(VNode *vnode, float (*vertexCos)[3])
1901 {
1902         VDerivedMesh *vdm = MEM_callocN(sizeof(*vdm), "vdm");
1903         struct VerseVert *vvert;
1904
1905         vdm->vnode = vnode;
1906         vdm->vertex_layer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER);
1907         vdm->polygon_layer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER);
1908
1909         vdm->dm.getMinMax = vDM_getMinMax;
1910
1911         vdm->dm.getNumVerts = vDM_getNumVerts;
1912         vdm->dm.getNumFaces = vDM_getNumFaces;
1913
1914         vdm->dm.foreachMappedVert = vDM_foreachMappedVert;
1915         vdm->dm.foreachMappedEdge = vDM_foreachMappedEdge;
1916         vdm->dm.foreachMappedFaceCenter = vDM_foreachMappedFaceCenter;
1917
1918         vdm->dm.convertToDispListMesh = vDM_convertToDispListMesh;
1919
1920         vdm->dm.getVertCos = vDM_getVertCos;
1921         vdm->dm.getVertCo = vDM_getVertCo;
1922         vdm->dm.getVertNo = vDM_getVertNo;
1923
1924         vdm->dm.drawVerts = vDM_drawVerts;
1925
1926         vdm->dm.drawEdges = vDM_drawEdges;
1927         vdm->dm.drawLooseEdges = vDM_drawLooseEdges;
1928         vdm->dm.drawUVEdges = vDM_drawUVEdges;
1929
1930         vdm->dm.drawFacesSolid = vDM_drawFacesSolid;
1931         vdm->dm.drawFacesTex = vDM_drawFacesTex;
1932         vdm->dm.drawFacesColored = vDM_drawFacesColored;
1933
1934         vdm->dm.drawMappedFacesTex = vDM_drawMappedFacesTex;
1935         vdm->dm.drawMappedFaces = vDM_drawMappedFaces;
1936         vdm->dm.drawMappedEdges = vDM_drawMappedEdges;
1937         vdm->dm.drawMappedEdgesInterp = vDM_drawMappedEdgesInterp;
1938
1939         vdm->dm.release = vDM_release;
1940
1941         if(vdm->vertex_layer) {
1942                 if(vertexCos) {
1943                         int i;
1944
1945                         vdm->verts = MEM_mallocN(sizeof(float)*3*vdm->vertex_layer->dl.da.count, "verse mod vertexes");
1946                         vvert = vdm->vertex_layer->dl.lb.first;
1947
1948                         for(i=0; i<vdm->vertex_layer->dl.da.count && vvert; i++, vvert = vvert->next) {
1949                                 VECCOPY(vdm->verts[i], vertexCos[i]);
1950                                 vvert->cos = vdm->verts[i];
1951                         }
1952                 }
1953                 else {
1954                         vdm->verts = NULL;
1955                         vvert = vdm->vertex_layer->dl.lb.first;
1956
1957                         while(vvert) {
1958                                 vvert->cos = NULL;
1959                                 vvert = vvert->next;
1960                         }
1961                 }
1962         }
1963
1964         return (DerivedMesh*) vdm;
1965 }
1966
1967 #endif
1968
1969 /***/
1970
1971 DerivedMesh *mesh_create_derived_for_modifier(Object *ob, ModifierData *md)
1972 {
1973         Mesh *me = ob->data;
1974         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1975         DerivedMesh *dm;
1976
1977         if (!(md->mode&eModifierMode_Realtime)) return NULL;
1978         if (mti->isDisabled && mti->isDisabled(md)) return NULL;
1979
1980         if (mti->type==eModifierTypeType_OnlyDeform) {
1981                 int numVerts;
1982                 float (*deformedVerts)[3] = mesh_getVertexCos(me, &numVerts);
1983
1984                 mti->deformVerts(md, ob, NULL, deformedVerts, numVerts);
1985 #ifdef WITH_VERSE
1986                 if(me->vnode) dm = derivedmesh_from_versemesh(me->vnode, deformedVerts);
1987                 else dm = getMeshDerivedMesh(me, ob, deformedVerts);
1988 #else
1989                 dm = getMeshDerivedMesh(me, ob, deformedVerts);
1990 #endif
1991
1992                 MEM_freeN(deformedVerts);
1993         } else {
1994                 dm = mti->applyModifier(md, ob, NULL, NULL, 0, 0);
1995         }
1996
1997         return dm;
1998 }
1999
2000 static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], DerivedMesh **deform_r, DerivedMesh **final_r, int useRenderParams, int useDeform, int needMapping)
2001 {
2002         Mesh *me = ob->data;
2003         ModifierData *md= modifiers_getVirtualModifierList(ob);
2004         float (*deformedVerts)[3] = NULL;
2005         DerivedMesh *dm;
2006         int numVerts = me->totvert;
2007         int fluidsimMeshUsed = 0;
2008
2009         modifiers_clearErrors(ob);
2010
2011         if (deform_r) *deform_r = NULL;
2012         *final_r = NULL;
2013
2014         /* replace original mesh by fluidsim surface mesh for fluidsim domain objects */
2015         if((G.obedit!=ob) && !needMapping) {
2016                 if (ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) {
2017                         if(ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN) {
2018                                 loadFluidsimMesh(ob,useRenderParams);
2019                                 fluidsimMeshUsed = 1;
2020                                 /* might have changed... */
2021                                 me = ob->data;
2022                                 numVerts = me->totvert;
2023                         }
2024                 }
2025         }
2026         
2027         if (useDeform) {
2028                 if(do_ob_key(ob))       /* shape key makes deform verts */
2029                         deformedVerts = mesh_getVertexCos(me, &numVerts);
2030                 
2031                         /* Apply all leading deforming modifiers */
2032                 for (; md; md=md->next) {
2033                         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
2034
2035                         if (!(md->mode&(1<<useRenderParams))) continue;
2036                         if (mti->isDisabled && mti->isDisabled(md)) continue;
2037
2038                         if (mti->type==eModifierTypeType_OnlyDeform) {
2039                                 if (!deformedVerts) deformedVerts = mesh_getVertexCos(me, &numVerts);
2040                                 mti->deformVerts(md, ob, NULL, deformedVerts, numVerts);
2041                         } else {
2042                                 break;
2043                         }
2044                 }
2045
2046                         /* Result of all leading deforming modifiers is cached for
2047                          * places that wish to use the original mesh but with deformed
2048                          * coordinates (vpaint, etc.)
2049                          */
2050                 if (deform_r)
2051 #ifdef WITH_VERSE
2052                         if(me->vnode) *deform_r = derivedmesh_from_versemesh(me->vnode, deformedVerts);
2053                         else *deform_r = getMeshDerivedMesh(me, ob, deformedVerts);
2054 #else
2055                         *deform_r = getMeshDerivedMesh(me, ob, deformedVerts);
2056 #endif
2057         } else {
2058                 if(!fluidsimMeshUsed) {
2059                         // default behaviour for meshes
2060                         deformedVerts = inputVertexCos;
2061                 } else {
2062                         // the fluid sim mesh might have more vertices than the original 
2063                         // one, so inputVertexCos shouldnt be used
2064                         deformedVerts = mesh_getVertexCos(me, &numVerts);
2065                 }
2066         }
2067
2068
2069                 /* Now apply all remaining modifiers. If useDeform is off then skip
2070                  * OnlyDeform ones. 
2071                  */
2072         dm = NULL;
2073         for (; md; md=md->next) {
2074                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
2075
2076                 if (!(md->mode&(1<<useRenderParams))) continue;
2077                 if (mti->type==eModifierTypeType_OnlyDeform && !useDeform) continue;
2078                 if ((mti->flags&eModifierTypeFlag_RequiresOriginalData) && dm) {
2079                         modifier_setError(md, "Internal error, modifier requires original data (bad stack position).");
2080                         continue;
2081                 }
2082                 if (mti->isDisabled && mti->isDisabled(md)) continue;
2083                 if (needMapping && !modifier_supportsMapping(md)) continue;
2084
2085                         /* How to apply modifier depends on (a) what we already have as
2086                          * a result of previous modifiers (could be a DerivedMesh or just
2087                          * deformed vertices) and (b) what type the modifier is.
2088                          */
2089
2090                 if (mti->type==eModifierTypeType_OnlyDeform) {
2091                                 /* No existing verts to deform, need to build them. */
2092                         if (!deformedVerts) {
2093                                 if (dm) {
2094                                                 /* Deforming a derived mesh, read the vertex locations out of the mesh and
2095                                                  * deform them. Once done with this run of deformers verts will be written back.
2096                                                  */
2097                                         numVerts = dm->getNumVerts(dm);
2098                                         deformedVerts = MEM_mallocN(sizeof(*deformedVerts)*numVerts, "dfmv");
2099                                         dm->getVertCos(dm, deformedVerts);
2100                                 } else {
2101                                         deformedVerts = mesh_getVertexCos(me, &numVerts);
2102                                 }
2103                         }
2104
2105                         mti->deformVerts(md, ob, dm, deformedVerts, numVerts);
2106                 } else {
2107                                 /* There are 4 cases here (have deform? have dm?) but they all are handled
2108                                  * by the modifier apply function, which will also free the DerivedMesh if
2109                                  * it exists.
2110                                  */
2111                         DerivedMesh *ndm = mti->applyModifier(md, ob, dm, deformedVerts, useRenderParams, !inputVertexCos);
2112
2113                         if (ndm) {
2114                                 if (dm) dm->release(dm);
2115
2116                                 dm = ndm;
2117
2118                                 if (deformedVerts) {
2119                                         if (deformedVerts!=inputVertexCos) {
2120                                                 MEM_freeN(deformedVerts);
2121                                         }
2122                                         deformedVerts = NULL;
2123                                 }
2124                         } 
2125                 }
2126         }
2127
2128                 /* Yay, we are done. If we have a DerivedMesh and deformed vertices need to apply
2129                  * these back onto the DerivedMesh. If we have no DerivedMesh then we need to build
2130                  * one.
2131                  */
2132         if (dm && deformedVerts) {
2133                 DispListMesh *dlm = dm->convertToDispListMesh(dm, 0);
2134
2135                 dm->release(dm);
2136
2137                 *final_r = derivedmesh_from_displistmesh(dlm, deformedVerts);
2138         } else if (dm) {
2139                 *final_r = dm;
2140         } else {
2141 #ifdef WITH_VERSE
2142                 if(me->vnode) *final_r = derivedmesh_from_versemesh(me->vnode, deformedVerts);
2143                 else *final_r = getMeshDerivedMesh(me, ob, deformedVerts);
2144 #else
2145                 *final_r = getMeshDerivedMesh(me, ob, deformedVerts);
2146 #endif
2147         }
2148
2149         if (deformedVerts && deformedVerts!=inputVertexCos) {
2150                 MEM_freeN(deformedVerts);
2151         }
2152         // restore mesh in any case
2153         if(fluidsimMeshUsed) ob->data = ob->fluidsimSettings->orgMesh;
2154 }
2155
2156 static float (*editmesh_getVertexCos(EditMesh *em, int *numVerts_r))[3]
2157 {
2158         int i, numVerts = *numVerts_r = BLI_countlist(&em->verts);
2159         float (*cos)[3];
2160         EditVert *eve;
2161
2162         cos = MEM_mallocN(sizeof(*cos)*numVerts, "vertexcos");
2163         for (i=0,eve=em->verts.first; i<numVerts; i++,eve=eve->next) {
2164                 VECCOPY(cos[i], eve->co);
2165         }
2166
2167         return cos;
2168 }
2169
2170 static void editmesh_calc_modifiers(DerivedMesh **cage_r, DerivedMesh **final_r)
2171 {
2172         Object *ob = G.obedit;
2173         EditMesh *em = G.editMesh;
2174         ModifierData *md;
2175         float (*deformedVerts)[3] = NULL;
2176         DerivedMesh *dm;
2177         int i, numVerts = 0, cageIndex = modifiers_getCageIndex(ob, NULL);
2178
2179         modifiers_clearErrors(ob);
2180
2181         if (cage_r && cageIndex==-1) {
2182                 *cage_r = getEditMeshDerivedMesh(em, NULL);
2183         }
2184
2185         dm = NULL;
2186         for (i=0,md= ob->modifiers.first; md; i++,md=md->next) {
2187                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
2188
2189                 if (!(md->mode&eModifierMode_Realtime)) continue;
2190                 if (!(md->mode&eModifierMode_Editmode)) continue;
2191                 if ((mti->flags&eModifierTypeFlag_RequiresOriginalData) && dm) {
2192                         modifier_setError(md, "Internal error, modifier requires original data (bad stack position).");
2193                         continue;
2194                 }
2195                 if (mti->isDisabled && mti->isDisabled(md)) continue;
2196                 if (!(mti->flags&eModifierTypeFlag_SupportsEditmode)) continue;
2197
2198                         /* How to apply modifier depends on (a) what we already have as
2199                          * a result of previous modifiers (could be a DerivedMesh or just
2200                          * deformed vertices) and (b) what type the modifier is.
2201                          */
2202
2203                 if (mti->type==eModifierTypeType_OnlyDeform) {
2204                                 /* No existing verts to deform, need to build them. */
2205                         if (!deformedVerts) {
2206                                 if (dm) {
2207                                                 /* Deforming a derived mesh, read the vertex locations out of the mesh and
2208                                                  * deform them. Once done with this run of deformers verts will be written back.
2209                                                  */
2210                                         numVerts = dm->getNumVerts(dm);
2211                                         deformedVerts = MEM_mallocN(sizeof(*deformedVerts)*numVerts, "dfmv");
2212                                         dm->getVertCos(dm, deformedVerts);
2213                                 } else {
2214                                         deformedVerts = editmesh_getVertexCos(em, &numVerts);
2215                                 }
2216                         }
2217
2218                         mti->deformVertsEM(md, ob, em, dm, deformedVerts, numVerts);
2219                 } else {
2220                                 /* There are 4 cases here (have deform? have dm?) but they all are handled
2221                                  * by the modifier apply function, which will also free the DerivedMesh if
2222                                  * it exists.
2223                                  */
2224                         DerivedMesh *ndm = mti->applyModifierEM(md, ob, em, dm, deformedVerts);
2225
2226                         if (ndm) {
2227                                 if (dm && (!cage_r || dm!=*cage_r)) dm->release(dm);
2228
2229                                 dm = ndm;
2230
2231                                 if (deformedVerts) {
2232                                         MEM_freeN(deformedVerts);
2233                                         deformedVerts = NULL;
2234                                 }
2235                         }
2236                 }
2237
2238                 if (cage_r && i==cageIndex) {
2239                         if (dm && deformedVerts) {
2240                                 DispListMesh *dlm;
2241
2242                                 dlm = dm->convertToDispListMesh(dm, 0);
2243
2244                                 *cage_r = derivedmesh_from_displistmesh(dlm, deformedVerts);
2245                         } else if (dm) {
2246                                 *cage_r = dm;
2247                         } else {
2248                                 *cage_r = getEditMeshDerivedMesh(em, deformedVerts?MEM_dupallocN(deformedVerts):NULL);
2249                         }
2250                 }
2251         }
2252
2253                 /* Yay, we are done. If we have a DerivedMesh and deformed vertices need to apply
2254                  * these back onto the DerivedMesh. If we have no DerivedMesh then we need to build
2255                  * one.
2256                  */
2257         if (dm && deformedVerts) {
2258                 DispListMesh *dlm = dm->convertToDispListMesh(dm, 0);
2259
2260                 if (!cage_r || dm!=*cage_r) dm->release(dm);
2261
2262                 *final_r = derivedmesh_from_displistmesh(dlm, deformedVerts);
2263                 MEM_freeN(deformedVerts);
2264         } else if (dm) {
2265                 *final_r = dm;
2266         } else {
2267                 *final_r = getEditMeshDerivedMesh(em, deformedVerts);
2268         }
2269 }
2270
2271 /***/
2272
2273
2274         /* Something of a hack, at the moment deal with weightpaint
2275          * by tucking into colors during modifier eval, only in
2276          * wpaint mode. Works ok but need to make sure recalc
2277          * happens on enter/exit wpaint.
2278          */
2279
2280 static void weight_to_rgb(float input, float *fr, float *fg, float *fb)
2281 {
2282         float blend;
2283         
2284         blend= ((input/2.0f)+0.5f);
2285         
2286         if (input<=0.25f){      // blue->cyan
2287                 *fr= 0.0f;
2288                 *fg= blend*input*4.0f;
2289                 *fb= blend;
2290         }
2291         else if (input<=0.50f){ // cyan->green
2292                 *fr= 0.0f;
2293                 *fg= blend;
2294                 *fb= blend*(1.0f-((input-0.25f)*4.0f)); 
2295         }
2296         else if (input<=0.75){  // green->yellow
2297                 *fr= blend * ((input-0.50f)*4.0f);
2298                 *fg= blend;
2299                 *fb= 0.0f;
2300         }
2301         else if (input<=1.0){ // yellow->red
2302                 *fr= blend;
2303                 *fg= blend * (1.0f-((input-0.75f)*4.0f)); 
2304                 *fb= 0.0f;
2305         }
2306 }
2307 static void calc_weightpaint_vert_color(Object *ob, int vert, unsigned char *col)
2308 {
2309         Mesh *me = ob->data;
2310         float fr, fg, fb, input = 0.0f;
2311         int i;
2312
2313         if (me->dvert) {
2314                 for (i=0; i<me->dvert[vert].totweight; i++)
2315                         if (me->dvert[vert].dw[i].def_nr==ob->actdef-1)
2316                                 input+=me->dvert[vert].dw[i].weight;            
2317         }
2318
2319         CLAMP(input, 0.0f, 1.0f);
2320         
2321         weight_to_rgb(input, &fr, &fg, &fb);
2322         
2323         col[3] = (unsigned char)(fr * 255.0f);
2324         col[2] = (unsigned char)(fg * 255.0f);
2325         col[1] = (unsigned char)(fb * 255.0f);
2326         col[0] = 255;
2327 }
2328 static unsigned char *calc_weightpaint_colors(Object *ob) 
2329 {
2330         Mesh *me = ob->data;
2331         MFace *mf = me->mface;
2332         unsigned char *wtcol;
2333         int i;
2334         
2335         wtcol = MEM_callocN (sizeof (unsigned char) * me->totface*4*4, "weightmap");
2336         
2337         memset(wtcol, 0x55, sizeof (unsigned char) * me->totface*4*4);
2338         for (i=0; i<me->totface; i++, mf++){
2339                 calc_weightpaint_vert_color(ob, mf->v1, &wtcol[(i*4 + 0)*4]); 
2340                 calc_weightpaint_vert_color(ob, mf->v2, &wtcol[(i*4 + 1)*4]); 
2341                 calc_weightpaint_vert_color(ob, mf->v3, &wtcol[(i*4 + 2)*4]); 
2342                 if (mf->v4)
2343                         calc_weightpaint_vert_color(ob, mf->v4, &wtcol[(i*4 + 3)*4]); 
2344         }
2345         
2346         return wtcol;
2347 }
2348
2349 static void clear_mesh_caches(Object *ob)
2350 {
2351         Mesh *me= ob->data;
2352
2353                 /* also serves as signal to remake texspace */
2354         if (me->bb) {
2355                 MEM_freeN(me->bb);
2356                 me->bb = NULL;
2357         }
2358
2359         freedisplist(&ob->disp);
2360
2361         if (ob->derivedFinal) {
2362                 ob->derivedFinal->release(ob->derivedFinal);
2363                 ob->derivedFinal= NULL;
2364         }
2365         if (ob->derivedDeform) {
2366                 ob->derivedDeform->release(ob->derivedDeform);
2367                 ob->derivedDeform= NULL;
2368         }
2369 }
2370
2371 static void mesh_build_data(Object *ob)
2372 {
2373         Mesh *me = ob->data;
2374         float min[3], max[3];
2375
2376         clear_mesh_caches(ob);
2377
2378         if(ob!=G.obedit) {
2379                 Object *obact = G.scene->basact?G.scene->basact->object:NULL;
2380                 int editing = (G.f & (G_FACESELECT|G_WEIGHTPAINT|G_VERTEXPAINT|G_TEXTUREPAINT));
2381                 int needMapping = editing && (ob==obact);
2382
2383                 if( (G.f & G_WEIGHTPAINT) && ob==obact ) {
2384                         MCol *mcol = me->mcol;
2385                         TFace *tface =  me->tface;
2386
2387                         me->tface = NULL;
2388                         me->mcol = (MCol*) calc_weightpaint_colors(ob);
2389
2390                         mesh_calc_modifiers(ob, NULL, &ob->derivedDeform, &ob->derivedFinal, 0, 1,
2391                                             needMapping);
2392
2393                         MEM_freeN(me->mcol);
2394                         me->mcol = mcol;
2395                         me->tface = tface;
2396                 } else {
2397                         mesh_calc_modifiers(ob, NULL, &ob->derivedDeform, &ob->derivedFinal, 0, 1,
2398                                             needMapping);
2399                 }
2400
2401                 INIT_MINMAX(min, max);
2402
2403                 ob->derivedFinal->getMinMax(ob->derivedFinal, min, max);
2404
2405                 boundbox_set_from_min_max(mesh_get_bb(ob->data), min, max);
2406         }
2407 }
2408
2409 static void editmesh_build_data(void)
2410 {
2411         float min[3], max[3];
2412
2413         EditMesh *em = G.editMesh;
2414
2415         clear_mesh_caches(G.obedit);
2416
2417         if (em->derivedFinal) {
2418                 if (em->derivedFinal!=em->derivedCage) {
2419                         em->derivedFinal->release(em->derivedFinal);
2420                 }
2421                 em->derivedFinal = NULL;
2422         }
2423         if (em->derivedCage) {
2424                 em->derivedCage->release(em->derivedCage);
2425                 em->derivedCage = NULL;
2426         }
2427
2428         editmesh_calc_modifiers(&em->derivedCage, &em->derivedFinal);
2429
2430         INIT_MINMAX(min, max);
2431
2432         em->derivedFinal->getMinMax(em->derivedFinal, min, max);
2433
2434         boundbox_set_from_min_max(mesh_get_bb(G.obedit->data), min, max);
2435 }
2436
2437 void makeDispListMesh(Object *ob)
2438 {
2439         if (ob==G.obedit) {
2440                 editmesh_build_data();
2441         } else {
2442                 PartEff *paf= give_parteff(ob);
2443                 
2444                 mesh_build_data(ob);
2445                 
2446                 if(paf) {
2447                         printf("ob %s %d\n", ob->id.name, ob->recalc);
2448                         if((paf->flag & PAF_STATIC) || (ob->recalc & OB_RECALC_TIME)==0)
2449                                 build_particle_system(ob);
2450                 }
2451         }
2452 }
2453
2454 /***/
2455
2456 DerivedMesh *mesh_get_derived_final(Object *ob, int *needsFree_r)
2457 {
2458         if (!ob->derivedFinal) {
2459                 mesh_build_data(ob);
2460         }
2461
2462         *needsFree_r = 0;
2463         return ob->derivedFinal;
2464 }
2465
2466 DerivedMesh *mesh_get_derived_deform(Object *ob, int *needsFree_r)
2467 {
2468         if (!ob->derivedDeform) {
2469                 mesh_build_data(ob);
2470         } 
2471
2472         *needsFree_r = 0;
2473         return ob->derivedDeform;
2474 }
2475
2476 DerivedMesh *mesh_create_derived_render(Object *ob)
2477 {
2478         DerivedMesh *final;
2479
2480         mesh_calc_modifiers(ob, NULL, NULL, &final, 1, 1, 0);
2481
2482         return final;
2483 }
2484
2485 DerivedMesh *mesh_create_derived_no_deform(Object *ob, float (*vertCos)[3])
2486 {
2487         DerivedMesh *final;
2488
2489         mesh_calc_modifiers(ob, vertCos, NULL, &final, 0, 0, 0);
2490
2491         return final;
2492 }
2493
2494 DerivedMesh *mesh_create_derived_no_deform_render(Object *ob, float (*vertCos)[3])
2495 {
2496         DerivedMesh *final;
2497
2498         mesh_calc_modifiers(ob, vertCos, NULL, &final, 1, 0, 0);
2499
2500         return final;
2501 }
2502
2503 /***/
2504
2505 DerivedMesh *editmesh_get_derived_cage_and_final(DerivedMesh **final_r, int *cageNeedsFree_r, int *finalNeedsFree_r)
2506 {
2507         *cageNeedsFree_r = *finalNeedsFree_r = 0;
2508
2509         if (!G.editMesh->derivedCage)
2510                 editmesh_build_data();
2511
2512         *final_r = G.editMesh->derivedFinal;
2513         return G.editMesh->derivedCage;
2514 }
2515
2516 DerivedMesh *editmesh_get_derived_cage(int *needsFree_r)
2517 {
2518         *needsFree_r = 0;
2519
2520         if (!G.editMesh->derivedCage)
2521                 editmesh_build_data();
2522
2523         return G.editMesh->derivedCage;
2524 }
2525
2526 DerivedMesh *editmesh_get_derived_base(void)
2527 {
2528         return getEditMeshDerivedMesh(G.editMesh, NULL);
2529 }
2530
2531
2532 /* ********* For those who don't grasp derived stuff! (ton) :) *************** */
2533
2534 static void make_vertexcosnos__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
2535 {
2536         float *vec = userData;
2537         
2538         vec+= 6*index;
2539         VECCOPY(vec, co);
2540         vec+= 3;
2541         if(no_f) {
2542                 VECCOPY(vec, no_f);
2543         }
2544         else {
2545                 VECCOPY(vec, no_s);
2546         }
2547 }
2548
2549 /* always returns original amount me->totvert of vertices and normals, but fully deformed and subsurfered */
2550 /* this is needed for all code using vertexgroups (no subsurf support) */
2551 /* it stores the normals as floats, but they can still be scaled as shorts (32767 = unit) */
2552 /* in use now by vertex/weight paint and particle generating */
2553
2554 float *mesh_get_mapped_verts_nors(Object *ob)
2555 {
2556         Mesh *me= ob->data;
2557         DerivedMesh *dm;
2558         float *vertexcosnos;
2559         int needsFree;
2560         
2561         /* lets prevent crashing... */
2562         if(ob->type!=OB_MESH || me->totvert==0)
2563                 return NULL;
2564         
2565         dm= mesh_get_derived_final(ob, &needsFree);
2566         vertexcosnos= MEM_mallocN(6*sizeof(float)*me->totvert, "vertexcosnos map");
2567         
2568         if(dm->foreachMappedVert) {
2569                 dm->foreachMappedVert(dm, make_vertexcosnos__mapFunc, vertexcosnos);
2570         }
2571         else {
2572                 float *fp= vertexcosnos;
2573                 int a;
2574                 
2575                 for(a=0; a< me->totvert; a++, fp+=6) {
2576                         dm->getVertCo(dm, a, fp);
2577                         dm->getVertNo(dm, a, fp+3);
2578                 }
2579         }
2580         
2581         if (needsFree) dm->release(dm);
2582         return vertexcosnos;
2583 }
2584
2585
2586 /* ************************* fluidsim bobj file handling **************************** */
2587
2588 #ifndef DISABLE_ELBEEM
2589
2590 #ifdef WIN32
2591 #ifndef snprintf
2592 #define snprintf _snprintf
2593 #endif
2594 #endif
2595
2596 /* write .bobj.gz file for a mesh object */
2597 void writeBobjgz(char *filename, struct Object *ob, int useGlobalCoords, int append, float time) 
2598 {
2599         char debugStrBuffer[256];
2600         int wri,i,j;
2601         float wrf;
2602         gzFile gzf;
2603         DispListMesh *dlm = NULL;
2604         DerivedMesh *dm;
2605         float vec[3];
2606         float rotmat[3][3];
2607         MFace *mface = NULL;
2608         //if(append)return; // DEBUG
2609
2610         if(!ob->data || (ob->type!=OB_MESH)) {
2611                 snprintf(debugStrBuffer,256,"Writing GZ_BOBJ Invalid object %s ...\n", ob->id.name); 
2612                 elbeemDebugOut(debugStrBuffer);
2613                 return;
2614         }
2615         if((ob->size[0]<0.0) || (ob->size[0]<0.0) || (ob->size[0]<0.0) ) {
2616                 snprintf(debugStrBuffer,256,"\nfluidSim::writeBobjgz:: Warning object %s has negative scaling - check triangle ordering...?\n\n", ob->id.name); 
2617                 elbeemDebugOut(debugStrBuffer);
2618         }
2619
2620         snprintf(debugStrBuffer,256,"Writing GZ_BOBJ '%s' ... ",filename); elbeemDebugOut(debugStrBuffer); 
2621         if(append) gzf = gzopen(filename, "a+b9");
2622         else       gzf = gzopen(filename, "wb9");
2623         if (!gzf) {
2624                 snprintf(debugStrBuffer,256,"writeBobjgz::error - Unable to open file for writing '%s'\n", filename);
2625                 elbeemDebugOut(debugStrBuffer);
2626                 return;
2627         }
2628
2629         dm = mesh_create_derived_render(ob);
2630         //dm = mesh_create_derived_no_deform(ob,NULL);
2631         dlm = dm->convertToDispListMesh(dm, 1);
2632         mface = dlm->mface;
2633
2634         // write time value for appended anim mesh
2635         if(append) {
2636                 gzwrite(gzf, &time, sizeof(time));
2637         }
2638
2639         // continue with verts/norms
2640         if(sizeof(wri)!=4) { snprintf(debugStrBuffer,256,"Writing GZ_BOBJ, Invalid int size %d...\n", wri); elbeemDebugOut(debugStrBuffer); return; } // paranoia check
2641         wri = dlm->totvert;
2642         gzwrite(gzf, &wri, sizeof(wri));
2643         for(i=0; i<wri;i++) {
2644                 VECCOPY(vec, dlm->mvert[i].co);
2645                 if(useGlobalCoords) { Mat4MulVecfl(ob->obmat, vec); }
2646                 for(j=0; j<3; j++) {
2647                         wrf = vec[j]; 
2648                         gzwrite(gzf, &wrf, sizeof( wrf )); 
2649                 }
2650         }
2651
2652         // should be the same as Vertices.size
2653         wri = dlm->totvert;
2654         gzwrite(gzf, &wri, sizeof(wri));
2655         EulToMat3(ob->rot, rotmat);
2656         for(i=0; i<wri;i++) {
2657                 VECCOPY(vec, dlm->mvert[i].no);
2658                 Normalise(vec);
2659                 if(useGlobalCoords) { Mat3MulVecfl(rotmat, vec); }
2660                 for(j=0; j<3; j++) {
2661                         wrf = vec[j];
2662                         gzwrite(gzf, &wrf, sizeof( wrf )); 
2663                 }
2664         }
2665
2666         // append only writes verts&norms 
2667         if(!append) {
2668                 //float side1[3],side2[3],norm1[3],norm2[3];
2669                 //float inpf;
2670         
2671                 // compute no. of triangles 
2672                 wri = 0;
2673                 for(i=0; i<dlm->totface; i++) {
2674                         wri++;
2675                         if(mface[i].v4) { wri++; }
2676                 }
2677                 gzwrite(gzf, &wri, sizeof(wri));
2678                 for(i=0; i<dlm->totface; i++) {
2679
2680                         int face[4];
2681                         face[0] = mface[i].v1;
2682                         face[1] = mface[i].v2;
2683                         face[2] = mface[i].v3;
2684                         face[3] = mface[i].v4;
2685                         //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);
2686                         //VecSubf(side1, dlm->mvert[face[1]].co,dlm->mvert[face[0]].co);
2687                         //VecSubf(side2, dlm->mvert[face[2]].co,dlm->mvert[face[0]].co);
2688                         //Crossf(norm1,side1,side2);
2689                         gzwrite(gzf, &(face[0]), sizeof( face[0] )); 
2690                         gzwrite(gzf, &(face[1]), sizeof( face[1] )); 
2691                         gzwrite(gzf, &(face[2]), sizeof( face[2] )); 
2692                         if(face[3]) { 
2693                                 //VecSubf(side1, dlm->mvert[face[2]].co,dlm->mvert[face[0]].co);
2694                                 //VecSubf(side2, dlm->mvert[face[3]].co,dlm->mvert[face[0]].co);
2695                                 //Crossf(norm2,side1,side2);
2696                                 //inpf = Inpf(norm1,norm2);
2697                                 //if(inpf>0.) {
2698                                 gzwrite(gzf, &(face[0]), sizeof( face[0] )); 
2699                                 gzwrite(gzf, &(face[2]), sizeof( face[2] )); 
2700                                 gzwrite(gzf, &(face[3]), sizeof( face[3] )); 
2701                                 //} else {
2702                                         //gzwrite(gzf, &(face[0]), sizeof( face[0] )); 
2703                                         //gzwrite(gzf, &(face[3]), sizeof( face[3] )); 
2704                                         //gzwrite(gzf, &(face[2]), sizeof( face[2] )); 
2705                                 //}
2706                         } // quad
2707                 }
2708         }
2709
2710         snprintf(debugStrBuffer,256,"Done. #Vertices: %d, #Triangles: %d\n", dlm->totvert, dlm->totface ); 
2711         elbeemDebugOut(debugStrBuffer);
2712         
2713         gzclose( gzf );
2714         if(dlm) displistmesh_free(dlm);
2715         dm->release(dm);
2716 }
2717
2718 void initElbeemMesh(struct Object *ob, 
2719                 int *numVertices, float **vertices, 
2720                 int *numTriangles, int **triangles,
2721                 int useGlobalCoords) 
2722 {
2723         DispListMesh *dlm = NULL;
2724         DerivedMesh *dm = NULL;
2725         MFace *mface = NULL;
2726         int countTris=0, i;
2727         float *verts;
2728         int *tris;
2729
2730         dm = mesh_create_derived_render(ob);
2731         //dm = mesh_create_derived_no_deform(ob,NULL);
2732         if(!dm) { *numVertices = *numTriangles = 0; *triangles=NULL; *vertices=NULL; }
2733         dlm = dm->convertToDispListMesh(dm, 1);
2734         if(!dlm) { dm->release(dm); *numVertices = *numTriangles = 0; *triangles=NULL; *vertices=NULL; }
2735         mface = dlm->mface;
2736
2737         *numVertices = dlm->totvert;
2738         verts = MEM_callocN( dlm->totvert*3*sizeof(float), "elbeemmesh_vertices");
2739         for(i=0; i<dlm->totvert; i++) {
2740                 VECCOPY( &verts[i*3], dlm->mvert[i].co);
2741                 if(useGlobalCoords) { Mat4MulVecfl(ob->obmat, &verts[i*3]); }
2742         }
2743         *vertices = verts;
2744
2745         for(i=0; i<dlm->totface; i++) {
2746                 countTris++;
2747                 if(mface[i].v4) { countTris++; }
2748         }
2749         *numTriangles = countTris;
2750         tris = MEM_callocN( countTris*3*sizeof(int), "elbeemmesh_triangles");
2751         countTris = 0;
2752         for(i=0; i<dlm->totface; i++) {
2753                 int face[4];
2754                 face[0] = mface[i].v1;
2755                 face[1] = mface[i].v2;
2756                 face[2] = mface[i].v3;
2757                 face[3] = mface[i].v4;
2758
2759                 tris[countTris*3+0] = face[0]; 
2760                 tris[countTris*3+1] = face[1]; 
2761                 tris[countTris*3+2] = face[2]; 
2762                 countTris++;
2763                 if(face[3]) { 
2764                         tris[countTris*3+0] = face[0]; 
2765                         tris[countTris*3+1] = face[2]; 
2766                         tris[countTris*3+2] = face[3]; 
2767                         countTris++;
2768                 }
2769         }
2770         *triangles = tris;
2771
2772         if(dlm) displistmesh_free(dlm);
2773         dm->release(dm);
2774 }
2775
2776 /* read .bobj.gz file into a fluidsimDerivedMesh struct */
2777 Mesh* readBobjgz(char *filename, Mesh *orgmesh, float* bbstart, float *bbsize) //, fluidsimDerivedMesh *fsdm)
2778 {
2779         int wri,i,j;
2780         char debugStrBuffer[256];
2781         float wrf;
2782         Mesh *newmesh; 
2783         const int debugBobjRead = 1;
2784         // init data from old mesh (materials,flags)
2785         MFace *origMFace = &((MFace*) orgmesh->mface)[0];
2786         int mat_nr = -1;
2787         int flag = -1;
2788         MFace *fsface = NULL;
2789         int gotBytes;
2790         gzFile gzf;
2791
2792         if(!orgmesh) return NULL;
2793         if(!origMFace) return NULL;
2794         mat_nr = origMFace->mat_nr;
2795         flag = origMFace->flag;
2796
2797         // similar to copy_mesh
2798         newmesh = MEM_dupallocN(orgmesh);
2799         newmesh->mat= orgmesh->mat;
2800
2801         newmesh->mvert= NULL;
2802         newmesh->medge= NULL;
2803         newmesh->mface= NULL;
2804         newmesh->tface= NULL;
2805         newmesh->dface= NULL;
2806
2807         newmesh->dvert = NULL;
2808
2809         newmesh->mcol= NULL;
2810         newmesh->msticky= NULL;
2811         newmesh->texcomesh= NULL;
2812
2813         newmesh->key= NULL;
2814         newmesh->totface = 0;
2815         newmesh->totvert = 0;
2816         newmesh->totedge = 0;
2817         newmesh->medge = NULL;
2818
2819
2820         snprintf(debugStrBuffer,256,"Reading '%s' GZ_BOBJ... ",filename); elbeemDebugOut(debugStrBuffer); 
2821         gzf = gzopen(filename, "rb");
2822         // gzf = fopen(filename, "rb");
2823         // debug: fread(b,c,1,a) = gzread(a,b,c)
2824         if (!gzf) {
2825                 //snprintf(debugStrBuffer,256,"readBobjgz::error - Unable to open file for reading '%s'\n", filename); // DEBUG
2826                 MEM_freeN(newmesh);
2827                 return NULL;
2828         }
2829
2830         //if(sizeof(wri)!=4) { snprintf(debugStrBuffer,256,"Reading GZ_BOBJ, Invalid int size %d...\n", wri); return NULL; } // paranoia check
2831         gotBytes = gzread(gzf, &wri, sizeof(wri));
2832         newmesh->totvert = wri;
2833         newmesh->mvert = MEM_callocN(sizeof(MVert)*newmesh->totvert, "fluidsimDerivedMesh_bobjvertices");
2834         if(debugBobjRead){ snprintf(debugStrBuffer,256,"#vertices %d ", newmesh->totvert); elbeemDebugOut(debugStrBuffer); } //DEBUG
2835         for(i=0; i<newmesh->totvert;i++) {
2836                 //if(debugBobjRead) snprintf(debugStrBuffer,256,"V %d = ",i);
2837                 for(j=0; j<3; j++) {
2838                         gotBytes = gzread(gzf, &wrf, sizeof( wrf )); 
2839                         newmesh->mvert[i].co[j] = wrf;
2840                         //if(debugBobjRead) snprintf(debugStrBuffer,256,"%25.20f ", wrf);
2841                 }
2842                 //if(debugBobjRead) snprintf(debugStrBuffer,256,"\n");
2843         }
2844
2845         // should be the same as Vertices.size
2846         gotBytes = gzread(gzf, &wri, sizeof(wri));
2847         if(wri != newmesh->totvert) {
2848                 // complain #vertices has to be equal to #normals, reset&abort
2849                 MEM_freeN(newmesh->mvert);
2850                 MEM_freeN(newmesh);
2851                 snprintf(debugStrBuffer,256,"Reading GZ_BOBJ, #normals=%d, #vertices=%d, aborting...\n", wri,newmesh->totvert );
2852                 return NULL;
2853         }
2854         for(i=0; i<newmesh->totvert;i++) {
2855                 for(j=0; j<3; j++) {
2856                         gotBytes = gzread(gzf, &wrf, sizeof( wrf )); 
2857                         newmesh->mvert[i].no[j] = (short)(wrf*32767.0f);
2858                         //newmesh->mvert[i].no[j] = 0.5; // DEBUG tst
2859                 }
2860         //fprintf(stderr,"  DEBDPCN nm%d, %d = %d,%d,%d \n",
2861                         //(int)(newmesh->mvert), i, newmesh->mvert[i].no[0], newmesh->mvert[i].no[1], newmesh->mvert[i].no[2]);
2862         }
2863         //fprintf(stderr,"  DPCN 0 = %d,%d,%d \n", newmesh->mvert[0].no[0], newmesh->mvert[0].no[1], newmesh->mvert[0].no[2]);
2864
2865         
2866         /* compute no. of triangles */
2867         gotBytes = gzread(gzf, &wri, sizeof(wri));
2868         newmesh->totface = wri;
2869         newmesh->mface = MEM_callocN(sizeof(MFace)*newmesh->totface, "fluidsimDerivedMesh_bobjfaces");
2870         if(debugBobjRead){ snprintf(debugStrBuffer,256,"#faces %d ", newmesh->totface); elbeemDebugOut(debugStrBuffer); } //DEBUG
2871         fsface = newmesh->mface;
2872         for(i=0; i<newmesh->totface; i++) {
2873                 int face[4];
2874
2875                 gotBytes = gzread(gzf, &(face[0]), sizeof( face[0] )); 
2876                 gotBytes = gzread(gzf, &(face[1]), sizeof( face[1] )); 
2877                 gotBytes = gzread(gzf, &(face[2]), sizeof( face[2] )); 
2878                 face[3] = 0;
2879
2880                 fsface[i].v1 = face[0];
2881                 fsface[i].v2 = face[1];
2882                 fsface[i].v3 = face[2];
2883                 fsface[i].v4 = face[3];
2884         }
2885
2886         // correct triangles with v3==0 for blender, cycle verts
2887         for(i=0; i<newmesh->totface; i++) {
2888                 if(!fsface[i].v3) {
2889                         int temp = fsface[i].v1;
2890                         fsface[i].v1 = fsface[i].v2;
2891                         fsface[i].v2 = fsface[i].v3;
2892                         fsface[i].v3 = temp;
2893                 }
2894         }
2895         
2896         gzclose( gzf );
2897         for(i=0;i<newmesh->totface;i++) { 
2898                 fsface[i].mat_nr = mat_nr;
2899                 fsface[i].flag = flag;
2900                 fsface[i].edcode = ME_V1V2 | ME_V2V3 | ME_V3V1;
2901                 //snprintf(debugStrBuffer,256,"%d : %d,%d,%d\n", i,fsface[i].mat_nr, fsface[i].flag, fsface[i].edcode );
2902         }
2903
2904         snprintf(debugStrBuffer,256," (%d,%d) done\n", newmesh->totvert,newmesh->totface); elbeemDebugOut(debugStrBuffer); //DEBUG
2905         return newmesh;
2906 }
2907
2908 /* read zipped fluidsim velocities into the co's of the fluidsimsettings normals struct */
2909 void readVelgz(char *filename, Object *srcob)
2910 {
2911         char debugStrBuffer[256];
2912         int wri, i, j;
2913         float wrf;
2914         gzFile gzf;
2915         MVert *vverts = srcob->fluidsimSettings->meshSurfNormals;
2916         int len = strlen(filename);
2917         Mesh *mesh = srcob->data;
2918         // mesh and vverts have to be valid from loading...
2919
2920         // clean up in any case
2921         for(i=0; i<mesh->totvert;i++) { 
2922                 for(j=0; j<3; j++) {
2923                         vverts[i].co[j] = 0.; 
2924                 } 
2925         } 
2926         if(srcob->fluidsimSettings->domainNovecgen>0) return;
2927
2928         if(len<7) { 
2929                 //printf("readVelgz Eror: invalid filename '%s'\n",filename); // DEBUG
2930                 return; 
2931         }
2932
2933         // .bobj.gz , correct filename
2934         // 87654321
2935         filename[len-6] = 'v';
2936         filename[len-5] = 'e';
2937         filename[len-4] = 'l';
2938
2939         snprintf(debugStrBuffer,256,"Reading '%s' GZ_VEL... ",filename); elbeemDebugOut(debugStrBuffer); 
2940         gzf = gzopen(filename, "rb");
2941         if (!gzf) { 
2942                 //printf("readVelgz Eror: unable to open file '%s'\n",filename); // DEBUG
2943                 return; 
2944         }
2945
2946         gzread(gzf, &wri, sizeof( wri ));
2947         if(wri != mesh->totvert) {
2948                 //printf("readVelgz Eror: invalid no. of velocities %d vs. %d aborting.\n" ,wri ,mesh->totvert ); // DEBUG
2949                 return; 
2950         }
2951
2952         for(i=0; i<mesh->totvert;i++) {
2953                 for(j=0; j<3; j++) {
2954                         gzread(gzf, &wrf, sizeof( wrf )); 
2955                         vverts[i].co[j] = wrf;
2956                 }
2957                 //if(i<20) fprintf(stderr, "GZ_VELload %d = %f,%f,%f  \n",i,vverts[i].co[0],vverts[i].co[1],vverts[i].co[2]); // DEBUG
2958         }
2959
2960         gzclose(gzf);
2961 }
2962
2963
2964 /* ***************************** fluidsim derived mesh ***************************** */
2965
2966 /* check which file to load, and replace old mesh of the object with it */
2967 /* this replacement is undone at the end of mesh_calc_modifiers */
2968 void loadFluidsimMesh(Object *srcob, int useRenderParams)
2969 {
2970         Mesh *mesh = NULL;
2971         float *bbStart = NULL, *bbSize = NULL;
2972         float lastBB[3];
2973         int displaymode = 0;
2974         int curFrame = G.scene->r.cfra - 1 /*G.scene->r.sfra*/; /* start with 0 at start frame */
2975         char targetDir[FILE_MAXFILE+FILE_MAXDIR], targetFile[FILE_MAXFILE+FILE_MAXDIR];
2976         char debugStrBuffer[256];
2977         //snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d)\n", srcob->id.name, useRenderParams); // debug
2978
2979         if((!srcob)||(!srcob->fluidsimSettings)) {
2980                 snprintf(debugStrBuffer,256,"DEBUG - Invalid loadFluidsimMesh call, rp %d, dm %d)\n", useRenderParams, displaymode); // debug
2981                 elbeemDebugOut(debugStrBuffer); // debug
2982                 return;
2983         }
2984         // make sure the original mesh data pointer is stored
2985         if(!srcob->fluidsimSettings->orgMesh) {
2986                 srcob->fluidsimSettings->orgMesh = srcob->data;
2987         }
2988
2989         // free old mesh, if there is one (todo, check if it's still valid?)
2990         if(srcob->fluidsimSettings->meshSurface) {
2991                 Mesh *freeFsMesh = srcob->fluidsimSettings->meshSurface;
2992
2993                 // similar to free_mesh(...) , but no things like unlink...
2994                 if(freeFsMesh->mvert){ MEM_freeN(freeFsMesh->mvert); freeFsMesh->mvert=NULL; }
2995                 if(freeFsMesh->medge){ MEM_freeN(freeFsMesh->medge); freeFsMesh->medge=NULL; }
2996                 if(freeFsMesh->mface){ MEM_freeN(freeFsMesh->mface); freeFsMesh->mface=NULL; }
2997                 MEM_freeN(freeFsMesh);
2998                 
2999                 if(srcob->data == srcob->fluidsimSettings->meshSurface)
3000                  srcob->data = srcob->fluidsimSettings->orgMesh;
3001                 srcob->fluidsimSettings->meshSurface = NULL;
3002
3003                 if(srcob->fluidsimSettings->meshSurfNormals) MEM_freeN(srcob->fluidsimSettings->meshSurfNormals);
3004                 srcob->fluidsimSettings->meshSurfNormals = NULL;
3005         } 
3006
3007         // init bounding box
3008         bbStart = srcob->fluidsimSettings->bbStart; 
3009         bbSize = srcob->fluidsimSettings->bbSize;
3010         lastBB[0] = bbSize[0];  // TEST
3011         lastBB[1] = bbSize[1]; 
3012         lastBB[2] = bbSize[2];
3013         fluidsimGetAxisAlignedBB(srcob->fluidsimSettings->orgMesh, srcob->obmat, bbStart, bbSize, &srcob->fluidsimSettings->meshBB);
3014         // check free fsmesh... TODO
3015         
3016         if(!useRenderParams) {
3017                 displaymode = srcob->fluidsimSettings->guiDisplayMode;
3018         } else {
3019                 displaymode = srcob->fluidsimSettings->renderDisplayMode;
3020         }
3021         
3022         snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d, dm %d), curFra=%d, sFra=%d #=%d \n", 
3023                         srcob->id.name, useRenderParams, displaymode, G.scene->r.cfra, G.scene->r.sfra, curFrame ); // debug
3024         elbeemDebugOut(debugStrBuffer); // debug
3025
3026         strncpy(targetDir, srcob->fluidsimSettings->surfdataPath, FILE_MAXDIR);
3027         // use preview or final mesh?
3028         if(displaymode==1) {
3029                 // just display original object
3030                 srcob->data = srcob->fluidsimSettings->orgMesh;
3031                 return;
3032         } else if(displaymode==2) {
3033                 strcat(targetDir,"fluidsurface_preview_#");
3034         } else { // 3
3035                 strcat(targetDir,"fluidsurface_final_#");
3036         }
3037         BLI_convertstringcode(targetDir, G.sce, curFrame); // fixed #frame-no 
3038         strcpy(targetFile,targetDir);
3039         strcat(targetFile, ".bobj.gz");
3040
3041         snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d, dm %d) '%s' \n", srcob->id.name, useRenderParams, displaymode, targetFile);  // debug
3042         elbeemDebugOut(debugStrBuffer); // debug
3043
3044         if(displaymode!=2) { // dont add bounding box for final
3045                 mesh = readBobjgz(targetFile, srcob->fluidsimSettings->orgMesh ,NULL,NULL);
3046         } else {
3047                 mesh = readBobjgz(targetFile, srcob->fluidsimSettings->orgMesh, bbSize,bbSize );
3048         }
3049         if(!mesh) {
3050                 // switch, abort background rendering when fluidsim mesh is missing
3051                 const char *strEnvName2 = "BLENDER_ELBEEMBOBJABORT"; // from blendercall.cpp
3052                 if(G.background==1) {
3053                         if(getenv(strEnvName2)) {
3054                                 int elevel = atoi(getenv(strEnvName2));
3055                                 if(elevel>0) {
3056                                         printf("Env. var %s set, fluid sim mesh '%s' not found, aborting render...\n",strEnvName2, targetFile);
3057                                         exit(1);
3058                                 }
3059                         }
3060                 }
3061                 
3062                 // display org. object upon failure
3063                 srcob->data = srcob->fluidsimSettings->orgMesh;
3064                 return;
3065         }
3066
3067         if((mesh)&&(mesh->totvert>0)) {
3068                 make_edges(mesh, 0);    // 0 = make all edges draw
3069         }
3070         srcob->fluidsimSettings->meshSurface = mesh;
3071         srcob->data = mesh;
3072         srcob->fluidsimSettings->meshSurfNormals = MEM_dupallocN(mesh->mvert);
3073
3074         // load vertex velocities, if they exist...
3075         // TODO? use generate flag as loading flag as well?
3076         // warning, needs original .bobj.gz mesh loading filename
3077         if(displaymode==3) {
3078                 readVelgz(targetFile, srcob);
3079         } else {
3080                 // no data for preview, only clear...
3081                 int i,j;
3082                 for(i=0; i<mesh->totvert;i++) { for(j=0; j<3; j++) { srcob->fluidsimSettings->meshSurfNormals[i].co[j] = 0.; }} 
3083         }
3084
3085         //fprintf(stderr,"LOADFLM DEBXHCH fs=%d 3:%d,%d,%d \n", (int)mesh, ((Mesh *)(srcob->fluidsimSettings->meshSurface))->mvert[3].no[0], ((Mesh *)(srcob->fluidsimSettings->meshSurface))->mvert[3].no[1], ((Mesh *)(srcob->fluidsimSettings->meshSurface))->mvert[3].no[2]);
3086         return;
3087 }
3088
3089 /* helper function */
3090 /* init axis aligned BB for mesh object */
3091 void fluidsimGetAxisAlignedBB(struct Mesh *mesh, float obmat[][4],
3092                  /*RET*/ float start[3], /*RET*/ float size[3], /*RET*/ struct Mesh **bbmesh )
3093 {
3094         float bbsx=0.0, bbsy=0.0, bbsz=0.0;
3095         float bbex=1.0, bbey=1.0, bbez=1.0;
3096         int i;
3097         float vec[3];
3098
3099         VECCOPY(vec, mesh->mvert[0].co); 
3100         Mat4MulVecfl(obmat, vec);
3101         bbsx = vec[0]; bbsy = vec[1]; bbsz = vec[2];
3102         bbex = vec[0]; bbey = vec[1]; bbez = vec[2];
3103
3104         for(i=1; i<mesh->totvert;i++) {
3105                 VECCOPY(vec, mesh->mvert[i].co);
3106                 Mat4MulVecfl(obmat, vec);
3107
3108                 if(vec[0] < bbsx){ bbsx= vec[0]; }
3109                 if(vec[1] < bbsy){ bbsy= vec[1]; }
3110                 if(vec[2] < bbsz){ bbsz= vec[2]; }
3111                 if(vec[0] > bbex){ bbex= vec[0]; }
3112                 if(vec[1] > bbey){ bbey= vec[1]; }
3113                 if(vec[2] > bbez){ bbez= vec[2]; }
3114         }
3115
3116         // return values...
3117         if(start) {
3118                 start[0] = bbsx;
3119                 start[1] = bbsy;
3120                 start[2] = bbsz;
3121         } 
3122         if(size) {
3123                 size[0] = bbex-bbsx;
3124                 size[1] = bbey-bbsy;
3125                 size[2] = bbez-bbsz;
3126         }
3127
3128         // init bounding box mesh?
3129         if(bbmesh) {
3130                 int i,j;
3131                 Mesh *newmesh = NULL;
3132                 if(!(*bbmesh)) { newmesh = MEM_callocN(sizeof(Mesh), "fluidsimGetAxisAlignedBB_meshbb"); }
3133                 else {           newmesh = *bbmesh; }
3134
3135                 newmesh->totvert = 8;
3136                 if(!newmesh->mvert) newmesh->mvert = MEM_callocN(sizeof(MVert)*newmesh->totvert, "fluidsimBBMesh_bobjvertices");
3137                 for(i=0; i<8; i++) {
3138                         for(j=0; j<3; j++) newmesh->mvert[i].co[j] = start[j]; 
3139                 }
3140
3141                 newmesh->totface = 6;
3142                 if(!newmesh->mface) newmesh->mface = MEM_callocN(sizeof(MFace)*newmesh->totface, "fluidsimBBMesh_bobjfaces");
3143
3144                 *bbmesh = newmesh;
3145         }
3146 }
3147
3148 #else // DISABLE_ELBEEM
3149
3150 /* dummy for mesh_calc_modifiers */
3151 void loadFluidsimMesh(Object *srcob, int useRenderParams) {
3152 }
3153
3154 #endif // DISABLE_ELBEEM
3155