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