Bugfix #4051
[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) && (ob->fluidsimFlag & OB_FLUIDSIM_ENABLE)) {
1535                 if(ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN) {
1536                         loadFluidsimMesh(ob,useRenderParams);
1537                         fluidsimMeshUsed = 1;
1538                         /* might have changed... */
1539                         me = ob->data;
1540                         numVerts = me->totvert;
1541                 }
1542         }
1543
1544         if (useDeform) {
1545                 if(do_ob_key(ob))       /* shape key makes deform verts */
1546                         deformedVerts = mesh_getVertexCos(me, &numVerts);
1547                 
1548                         /* Apply all leading deforming modifiers */
1549                 for (; md; md=md->next) {
1550                         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1551
1552                         if (!(md->mode&(1<<useRenderParams))) continue;
1553                         if (mti->isDisabled && mti->isDisabled(md)) continue;
1554
1555                         if (mti->type==eModifierTypeType_OnlyDeform) {
1556                                 if (!deformedVerts) deformedVerts = mesh_getVertexCos(me, &numVerts);
1557                                 mti->deformVerts(md, ob, NULL, deformedVerts, numVerts);
1558                         } else {
1559                                 break;
1560                         }
1561                 }
1562
1563                         /* Result of all leading deforming modifiers is cached for
1564                          * places that wish to use the original mesh but with deformed
1565                          * coordinates (vpaint, etc.)
1566                          */
1567                 if (deform_r) *deform_r = getMeshDerivedMesh(me, ob, deformedVerts);
1568         } else {
1569                 if(!fluidsimMeshUsed) {
1570                         // default behaviour for meshes
1571                         deformedVerts = inputVertexCos;
1572                 } else {
1573                         // the fluid sim mesh might have more vertices than the original 
1574                         // one, so inputVertexCos shouldnt be used
1575                         deformedVerts = mesh_getVertexCos(me, &numVerts);
1576                 }
1577         }
1578
1579
1580                 /* Now apply all remaining modifiers. If useDeform is off then skip
1581                  * OnlyDeform ones. 
1582                  */
1583         dm = NULL;
1584         for (; md; md=md->next) {
1585                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1586
1587                 if (!(md->mode&(1<<useRenderParams))) continue;
1588                 if (mti->type==eModifierTypeType_OnlyDeform && !useDeform) continue;
1589                 if ((mti->flags&eModifierTypeFlag_RequiresOriginalData) && dm) {
1590                         modifier_setError(md, "Internal error, modifier requires original data (bad stack position).");
1591                         continue;
1592                 }
1593                 if (mti->isDisabled && mti->isDisabled(md)) continue;
1594                 if (needMapping && !modifier_supportsMapping(md)) continue;
1595
1596                         /* How to apply modifier depends on (a) what we already have as
1597                          * a result of previous modifiers (could be a DerivedMesh or just
1598                          * deformed vertices) and (b) what type the modifier is.
1599                          */
1600
1601                 if (mti->type==eModifierTypeType_OnlyDeform) {
1602                                 /* No existing verts to deform, need to build them. */
1603                         if (!deformedVerts) {
1604                                 if (dm) {
1605                                                 /* Deforming a derived mesh, read the vertex locations out of the mesh and
1606                                                  * deform them. Once done with this run of deformers verts will be written back.
1607                                                  */
1608                                         numVerts = dm->getNumVerts(dm);
1609                                         deformedVerts = MEM_mallocN(sizeof(*deformedVerts)*numVerts, "dfmv");
1610                                         dm->getVertCos(dm, deformedVerts);
1611                                 } else {
1612                                         deformedVerts = mesh_getVertexCos(me, &numVerts);
1613                                 }
1614                         }
1615
1616                         mti->deformVerts(md, ob, dm, deformedVerts, numVerts);
1617                 } else {
1618                                 /* There are 4 cases here (have deform? have dm?) but they all are handled
1619                                  * by the modifier apply function, which will also free the DerivedMesh if
1620                                  * it exists.
1621                                  */
1622                         DerivedMesh *ndm = mti->applyModifier(md, ob, dm, deformedVerts, useRenderParams, !inputVertexCos);
1623
1624                         if (ndm) {
1625                                 if (dm) dm->release(dm);
1626
1627                                 dm = ndm;
1628
1629                                 if (deformedVerts) {
1630                                         if (deformedVerts!=inputVertexCos) {
1631                                                 MEM_freeN(deformedVerts);
1632                                         }
1633                                         deformedVerts = NULL;
1634                                 }
1635                         } 
1636                 }
1637         }
1638
1639                 /* Yay, we are done. If we have a DerivedMesh and deformed vertices need to apply
1640                  * these back onto the DerivedMesh. If we have no DerivedMesh then we need to build
1641                  * one.
1642                  */
1643         if (dm && deformedVerts) {
1644                 DispListMesh *dlm = dm->convertToDispListMesh(dm, 0);
1645
1646                 dm->release(dm);
1647
1648                 *final_r = derivedmesh_from_displistmesh(dlm, deformedVerts);
1649         } else if (dm) {
1650                 *final_r = dm;
1651         } else {
1652                 *final_r = getMeshDerivedMesh(me, ob, deformedVerts);
1653         }
1654
1655         if (deformedVerts && deformedVerts!=inputVertexCos) {
1656                 MEM_freeN(deformedVerts);
1657         }
1658         // restore mesh in any case
1659         if(fluidsimMeshUsed) ob->data = ob->fluidsimSettings->orgMesh;
1660 }
1661
1662 static float (*editmesh_getVertexCos(EditMesh *em, int *numVerts_r))[3]
1663 {
1664         int i, numVerts = *numVerts_r = BLI_countlist(&em->verts);
1665         float (*cos)[3];
1666         EditVert *eve;
1667
1668         cos = MEM_mallocN(sizeof(*cos)*numVerts, "vertexcos");
1669         for (i=0,eve=em->verts.first; i<numVerts; i++,eve=eve->next) {
1670                 VECCOPY(cos[i], eve->co);
1671         }
1672
1673         return cos;
1674 }
1675
1676 static void editmesh_calc_modifiers(DerivedMesh **cage_r, DerivedMesh **final_r)
1677 {
1678         Object *ob = G.obedit;
1679         EditMesh *em = G.editMesh;
1680         ModifierData *md;
1681         float (*deformedVerts)[3] = NULL;
1682         DerivedMesh *dm;
1683         int i, numVerts = 0, cageIndex = modifiers_getCageIndex(ob, NULL);
1684
1685         modifiers_clearErrors(ob);
1686
1687         if (cage_r && cageIndex==-1) {
1688                 *cage_r = getEditMeshDerivedMesh(em, NULL);
1689         }
1690
1691         dm = NULL;
1692         for (i=0,md= ob->modifiers.first; md; i++,md=md->next) {
1693                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1694
1695                 if (!(md->mode&eModifierMode_Realtime)) continue;
1696                 if (!(md->mode&eModifierMode_Editmode)) continue;
1697                 if ((mti->flags&eModifierTypeFlag_RequiresOriginalData) && dm) {
1698                         modifier_setError(md, "Internal error, modifier requires original data (bad stack position).");
1699                         continue;
1700                 }
1701                 if (mti->isDisabled && mti->isDisabled(md)) continue;
1702                 if (!(mti->flags&eModifierTypeFlag_SupportsEditmode)) continue;
1703
1704                         /* How to apply modifier depends on (a) what we already have as
1705                          * a result of previous modifiers (could be a DerivedMesh or just
1706                          * deformed vertices) and (b) what type the modifier is.
1707                          */
1708
1709                 if (mti->type==eModifierTypeType_OnlyDeform) {
1710                                 /* No existing verts to deform, need to build them. */
1711                         if (!deformedVerts) {
1712                                 if (dm) {
1713                                                 /* Deforming a derived mesh, read the vertex locations out of the mesh and
1714                                                  * deform them. Once done with this run of deformers verts will be written back.
1715                                                  */
1716                                         numVerts = dm->getNumVerts(dm);
1717                                         deformedVerts = MEM_mallocN(sizeof(*deformedVerts)*numVerts, "dfmv");
1718                                         dm->getVertCos(dm, deformedVerts);
1719                                 } else {
1720                                         deformedVerts = editmesh_getVertexCos(em, &numVerts);
1721                                 }
1722                         }
1723
1724                         mti->deformVertsEM(md, ob, em, dm, deformedVerts, numVerts);
1725                 } else {
1726                                 /* There are 4 cases here (have deform? have dm?) but they all are handled
1727                                  * by the modifier apply function, which will also free the DerivedMesh if
1728                                  * it exists.
1729                                  */
1730                         DerivedMesh *ndm = mti->applyModifierEM(md, ob, em, dm, deformedVerts);
1731
1732                         if (ndm) {
1733                                 if (dm && (!cage_r || dm!=*cage_r)) dm->release(dm);
1734
1735                                 dm = ndm;
1736
1737                                 if (deformedVerts) {
1738                                         MEM_freeN(deformedVerts);
1739                                         deformedVerts = NULL;
1740                                 }
1741                         }
1742                 }
1743
1744                 if (cage_r && i==cageIndex) {
1745                         if (dm && deformedVerts) {
1746                                 DispListMesh *dlm;
1747
1748                                 dlm = dm->convertToDispListMesh(dm, 0);
1749
1750                                 *cage_r = derivedmesh_from_displistmesh(dlm, deformedVerts);
1751                         } else if (dm) {
1752                                 *cage_r = dm;
1753                         } else {
1754                                 *cage_r = getEditMeshDerivedMesh(em, deformedVerts?MEM_dupallocN(deformedVerts):NULL);
1755                         }
1756                 }
1757         }
1758
1759                 /* Yay, we are done. If we have a DerivedMesh and deformed vertices need to apply
1760                  * these back onto the DerivedMesh. If we have no DerivedMesh then we need to build
1761                  * one.
1762                  */
1763         if (dm && deformedVerts) {
1764                 DispListMesh *dlm = dm->convertToDispListMesh(dm, 0);
1765
1766                 if (!cage_r || dm!=*cage_r) dm->release(dm);
1767
1768                 *final_r = derivedmesh_from_displistmesh(dlm, deformedVerts);
1769                 MEM_freeN(deformedVerts);
1770         } else if (dm) {
1771                 *final_r = dm;
1772         } else {
1773                 *final_r = getEditMeshDerivedMesh(em, deformedVerts);
1774         }
1775 }
1776
1777 /***/
1778
1779
1780         /* Something of a hack, at the moment deal with weightpaint
1781          * by tucking into colors during modifier eval, only in
1782          * wpaint mode. Works ok but need to make sure recalc
1783          * happens on enter/exit wpaint.
1784          */
1785
1786 static void weight_to_rgb(float input, float *fr, float *fg, float *fb)
1787 {
1788         float blend;
1789         
1790         blend= ((input/2.0f)+0.5f);
1791         
1792         if (input<=0.25f){      // blue->cyan
1793                 *fr= 0.0f;
1794                 *fg= blend*input*4.0f;
1795                 *fb= blend;
1796         }
1797         else if (input<=0.50f){ // cyan->green
1798                 *fr= 0.0f;
1799                 *fg= blend;
1800                 *fb= blend*(1.0f-((input-0.25f)*4.0f)); 
1801         }
1802         else if (input<=0.75){  // green->yellow
1803                 *fr= blend * ((input-0.50f)*4.0f);
1804                 *fg= blend;
1805                 *fb= 0.0f;
1806         }
1807         else if (input<=1.0){ // yellow->red
1808                 *fr= blend;
1809                 *fg= blend * (1.0f-((input-0.75f)*4.0f)); 
1810                 *fb= 0.0f;
1811         }
1812 }
1813 static void calc_weightpaint_vert_color(Object *ob, int vert, unsigned char *col)
1814 {
1815         Mesh *me = ob->data;
1816         float fr, fg, fb, input = 0.0f;
1817         int i;
1818
1819         if (me->dvert) {
1820                 for (i=0; i<me->dvert[vert].totweight; i++)
1821                         if (me->dvert[vert].dw[i].def_nr==ob->actdef-1)
1822                                 input+=me->dvert[vert].dw[i].weight;            
1823         }
1824
1825         CLAMP(input, 0.0f, 1.0f);
1826         
1827         weight_to_rgb(input, &fr, &fg, &fb);
1828         
1829         col[3] = (unsigned char)(fr * 255.0f);
1830         col[2] = (unsigned char)(fg * 255.0f);
1831         col[1] = (unsigned char)(fb * 255.0f);
1832         col[0] = 255;
1833 }
1834 static unsigned char *calc_weightpaint_colors(Object *ob) 
1835 {
1836         Mesh *me = ob->data;
1837         MFace *mf = me->mface;
1838         unsigned char *wtcol;
1839         int i;
1840         
1841         wtcol = MEM_callocN (sizeof (unsigned char) * me->totface*4*4, "weightmap");
1842         
1843         memset(wtcol, 0x55, sizeof (unsigned char) * me->totface*4*4);
1844         for (i=0; i<me->totface; i++, mf++){
1845                 calc_weightpaint_vert_color(ob, mf->v1, &wtcol[(i*4 + 0)*4]); 
1846                 calc_weightpaint_vert_color(ob, mf->v2, &wtcol[(i*4 + 1)*4]); 
1847                 calc_weightpaint_vert_color(ob, mf->v3, &wtcol[(i*4 + 2)*4]); 
1848                 if (mf->v4)
1849                         calc_weightpaint_vert_color(ob, mf->v4, &wtcol[(i*4 + 3)*4]); 
1850         }
1851         
1852         return wtcol;
1853 }
1854
1855 static void clear_mesh_caches(Object *ob)
1856 {
1857         Mesh *me= ob->data;
1858
1859                 /* also serves as signal to remake texspace */
1860         if (me->bb) {
1861                 MEM_freeN(me->bb);
1862                 me->bb = NULL;
1863         }
1864
1865         freedisplist(&ob->disp);
1866
1867         if (ob->derivedFinal) {
1868                 ob->derivedFinal->release(ob->derivedFinal);
1869                 ob->derivedFinal= NULL;
1870         }
1871         if (ob->derivedDeform) {
1872                 ob->derivedDeform->release(ob->derivedDeform);
1873                 ob->derivedDeform= NULL;
1874         }
1875 }
1876
1877 static void mesh_build_data(Object *ob)
1878 {
1879         Mesh *me = ob->data;
1880         float min[3], max[3];
1881
1882         clear_mesh_caches(ob);
1883
1884         if(ob!=G.obedit) {
1885                 Object *obact = G.scene->basact?G.scene->basact->object:NULL;
1886                 int editing = (G.f & (G_FACESELECT|G_WEIGHTPAINT|G_VERTEXPAINT|G_TEXTUREPAINT));
1887                 int needMapping = editing && (ob==obact);
1888
1889                 if( (G.f & G_WEIGHTPAINT) && ob==obact ) {
1890                         MCol *mcol = me->mcol;
1891                         TFace *tface =  me->tface;
1892
1893                         me->tface = NULL;
1894                         me->mcol = (MCol*) calc_weightpaint_colors(ob);
1895
1896                         mesh_calc_modifiers(ob, NULL, &ob->derivedDeform, &ob->derivedFinal, 0, 1,
1897                                             needMapping);
1898
1899                         MEM_freeN(me->mcol);
1900                         me->mcol = mcol;
1901                         me->tface = tface;
1902                 } else {
1903                         mesh_calc_modifiers(ob, NULL, &ob->derivedDeform, &ob->derivedFinal, 0, 1,
1904                                             needMapping);
1905                 }
1906
1907                 INIT_MINMAX(min, max);
1908
1909                 ob->derivedFinal->getMinMax(ob->derivedFinal, min, max);
1910
1911                 boundbox_set_from_min_max(mesh_get_bb(ob->data), min, max);
1912         }
1913 }
1914
1915 static void editmesh_build_data(void)
1916 {
1917         float min[3], max[3];
1918
1919         EditMesh *em = G.editMesh;
1920
1921         clear_mesh_caches(G.obedit);
1922
1923         if (em->derivedFinal) {
1924                 if (em->derivedFinal!=em->derivedCage) {
1925                         em->derivedFinal->release(em->derivedFinal);
1926                 }
1927                 em->derivedFinal = NULL;
1928         }
1929         if (em->derivedCage) {
1930                 em->derivedCage->release(em->derivedCage);
1931                 em->derivedCage = NULL;
1932         }
1933
1934         editmesh_calc_modifiers(&em->derivedCage, &em->derivedFinal);
1935
1936         INIT_MINMAX(min, max);
1937
1938         em->derivedFinal->getMinMax(em->derivedFinal, min, max);
1939
1940         boundbox_set_from_min_max(mesh_get_bb(G.obedit->data), min, max);
1941 }
1942
1943 void makeDispListMesh(Object *ob)
1944 {
1945         if (ob==G.obedit) {
1946                 editmesh_build_data();
1947         } else {
1948                 mesh_build_data(ob);
1949
1950                 build_particle_system(ob);
1951         }
1952 }
1953
1954 /***/
1955
1956 DerivedMesh *mesh_get_derived_final(Object *ob, int *needsFree_r)
1957 {
1958         if (!ob->derivedFinal) {
1959                 mesh_build_data(ob);
1960         }
1961
1962         *needsFree_r = 0;
1963         return ob->derivedFinal;
1964 }
1965
1966 DerivedMesh *mesh_get_derived_deform(Object *ob, int *needsFree_r)
1967 {
1968         if (!ob->derivedDeform) {
1969                 mesh_build_data(ob);
1970         } 
1971
1972         *needsFree_r = 0;
1973         return ob->derivedDeform;
1974 }
1975
1976 DerivedMesh *mesh_create_derived_render(Object *ob)
1977 {
1978         DerivedMesh *final;
1979
1980         mesh_calc_modifiers(ob, NULL, NULL, &final, 1, 1, 0);
1981
1982         return final;
1983 }
1984
1985 DerivedMesh *mesh_create_derived_no_deform(Object *ob, float (*vertCos)[3])
1986 {
1987         DerivedMesh *final;
1988
1989         mesh_calc_modifiers(ob, vertCos, NULL, &final, 0, 0, 0);
1990
1991         return final;
1992 }
1993
1994 DerivedMesh *mesh_create_derived_no_deform_render(Object *ob, float (*vertCos)[3])
1995 {
1996         DerivedMesh *final;
1997
1998         mesh_calc_modifiers(ob, vertCos, NULL, &final, 1, 0, 0);
1999
2000         return final;
2001 }
2002
2003 /***/
2004
2005 DerivedMesh *editmesh_get_derived_cage_and_final(DerivedMesh **final_r, int *cageNeedsFree_r, int *finalNeedsFree_r)
2006 {
2007         *cageNeedsFree_r = *finalNeedsFree_r = 0;
2008
2009         if (!G.editMesh->derivedCage)
2010                 editmesh_build_data();
2011
2012         *final_r = G.editMesh->derivedFinal;
2013         return G.editMesh->derivedCage;
2014 }
2015
2016 DerivedMesh *editmesh_get_derived_cage(int *needsFree_r)
2017 {
2018         *needsFree_r = 0;
2019
2020         if (!G.editMesh->derivedCage)
2021                 editmesh_build_data();
2022
2023         return G.editMesh->derivedCage;
2024 }
2025
2026 DerivedMesh *editmesh_get_derived_base(void)
2027 {
2028         return getEditMeshDerivedMesh(G.editMesh, NULL);
2029 }
2030
2031
2032 /* ********* For those who don't grasp derived stuff! (ton) :) *************** */
2033
2034 static void make_vertexcosnos__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
2035 {
2036         float *vec = userData;
2037         
2038         vec+= 6*index;
2039         VECCOPY(vec, co);
2040         vec+= 3;
2041         if(no_f) {
2042                 VECCOPY(vec, no_f);
2043         }
2044         else {
2045                 VECCOPY(vec, no_s);
2046         }
2047 }
2048
2049 /* always returns original amount me->totvert of vertices and normals, but fully deformed and subsurfered */
2050 /* this is needed for all code using vertexgroups (no subsurf support) */
2051 /* it stores the normals as floats, but they can still be scaled as shorts (32767 = unit) */
2052 /* in use now by vertex/weight paint and particle generating */
2053
2054 float *mesh_get_mapped_verts_nors(Object *ob)
2055 {
2056         Mesh *me= ob->data;
2057         DerivedMesh *dm;
2058         float *vertexcosnos;
2059         int needsFree;
2060         
2061         /* lets prevent crashing... */
2062         if(ob->type!=OB_MESH || me->totvert==0)
2063                 return NULL;
2064         
2065         dm= mesh_get_derived_final(ob, &needsFree);
2066         vertexcosnos= MEM_mallocN(6*sizeof(float)*me->totvert, "vertexcosnos map");
2067         
2068         if(dm->foreachMappedVert) {
2069                 dm->foreachMappedVert(dm, make_vertexcosnos__mapFunc, vertexcosnos);
2070         }
2071         else {
2072                 float *fp= vertexcosnos;
2073                 int a;
2074                 
2075                 for(a=0; a< me->totvert; a++, fp+=6) {
2076                         dm->getVertCo(dm, a, fp);
2077                         dm->getVertNo(dm, a, fp+3);
2078                 }
2079         }
2080         
2081         if (needsFree) dm->release(dm);
2082         return vertexcosnos;
2083 }
2084
2085
2086 /* ************************* fluidsim bobj file handling **************************** */
2087
2088 #ifdef WIN32
2089 #ifndef snprintf
2090 #define snprintf _snprintf
2091 #endif
2092 #endif
2093
2094 /* write .bobj.gz file for a mesh object */
2095 void writeBobjgz(char *filename, struct Object *ob) 
2096 {
2097         // const int debugBobjWrite = 0; // now handled by global debug level
2098         char debugStrBuffer[256];
2099         int wri,i,j;
2100         float wrf;
2101         gzFile gzf;
2102         DispListMesh *dlm = NULL;
2103         DerivedMesh *dm;
2104         float vec[3];
2105         float rotmat[3][3];
2106         MFace *mface = NULL;
2107
2108         if(!ob->data || (ob->type!=OB_MESH)) {
2109                 snprintf(debugStrBuffer,256,"Writing GZ_BOBJ Invalid object %s ...\n", ob->id.name); 
2110                 elbeemDebugOut(debugStrBuffer);
2111                 return;
2112         }
2113         if((ob->size[0]<0.0) || (ob->size[0]<0.0) || (ob->size[0]<0.0) ) {
2114                 snprintf(debugStrBuffer,256,"\nfluidSim::writeBobjgz:: Warning object %s has negative scaling - check triangle ordering...?\n\n", ob->id.name); 
2115                 elbeemDebugOut(debugStrBuffer);
2116         }
2117
2118         snprintf(debugStrBuffer,256,"Writing GZ_BOBJ '%s' ... ",filename); elbeemDebugOut(debugStrBuffer); 
2119         gzf = gzopen(filename, "wb9");
2120         if (!gzf) {
2121                 snprintf(debugStrBuffer,256,"writeBobjgz::error - Unable to open file for writing '%s'\n", filename);
2122                 elbeemDebugOut(debugStrBuffer);
2123                 return;
2124         }
2125
2126         dm = mesh_create_derived_render(ob);
2127         dlm = dm->convertToDispListMesh(dm, 1);
2128         mface = dlm->mface;
2129
2130         if(sizeof(wri)!=4) { snprintf(debugStrBuffer,256,"Writing GZ_BOBJ, Invalid int size %d...\n", wri); elbeemDebugOut(debugStrBuffer); return; } // paranoia check
2131         wri = dlm->totvert;
2132         gzwrite(gzf, &wri, sizeof(wri));
2133         for(i=0; i<wri;i++) {
2134                 VECCOPY(vec, dlm->mvert[i].co);
2135         //VECCOPY(vec, dlm->mvert[i].co); /* get transformed point */
2136         //Mat4MulVecfl(ob->obmat, vec);
2137                 for(j=0; j<3; j++) {
2138                         wrf = vec[j]; 
2139                         gzwrite(gzf, &wrf, sizeof( wrf )); 
2140                 }
2141         }
2142
2143         // should be the same as Vertices.size
2144         wri = dlm->totvert;
2145         gzwrite(gzf, &wri, sizeof(wri));
2146         EulToMat3(ob->rot, rotmat);
2147         for(i=0; i<wri;i++) {
2148                 VECCOPY(vec, dlm->mvert[i].no);
2149                 // FIXME divide? mv->no[0]= (short)(no[0]*32767.0);
2150         //VECCOPY(vec, dlm->mvert[i].no);
2151         //Mat3MulVecfl(rotmat, vec); 
2152                 Normalise(vec);
2153                 for(j=0; j<3; j++) {
2154                         wrf = vec[j];
2155                         gzwrite(gzf, &wrf, sizeof( wrf )); 
2156                 }
2157         }
2158
2159         
2160         /* compute no. of triangles */
2161         wri = 0;
2162         for(i=0; i<dlm->totface; i++) {
2163                 wri++;
2164                 if(mface[i].v4) { wri++; }
2165         }
2166         gzwrite(gzf, &wri, sizeof(wri));
2167         for(i=0; i<dlm->totface; i++) {
2168
2169                 int face[4];
2170                 face[0] = mface[i].v1;
2171                 face[1] = mface[i].v2;
2172                 face[2] = mface[i].v3;
2173                 face[3] = mface[i].v4;
2174                 //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);
2175
2176                 gzwrite(gzf, &(face[0]), sizeof( face[0] )); 
2177                 gzwrite(gzf, &(face[1]), sizeof( face[1] )); 
2178                 gzwrite(gzf, &(face[2]), sizeof( face[2] )); 
2179                 if(face[3]) { 
2180                         gzwrite(gzf, &(face[0]), sizeof( face[0] )); 
2181                         gzwrite(gzf, &(face[2]), sizeof( face[2] )); 
2182                         gzwrite(gzf, &(face[3]), sizeof( face[3] )); 
2183                 }
2184         }
2185
2186         snprintf(debugStrBuffer,256,"Done. #Vertices: %d, #Triangles: %d\n", dlm->totvert, dlm->totface ); 
2187         elbeemDebugOut(debugStrBuffer);
2188         
2189         gzclose( gzf );
2190         if(dlm) displistmesh_free(dlm);
2191         dm->release(dm);
2192 }
2193
2194 void initElbeemMesh(struct Object *ob, 
2195                 int *numVertices, float **vertices, 
2196                 int *numTriangles, int **triangles) 
2197 {
2198         DispListMesh *dlm = NULL;
2199         DerivedMesh *dm = NULL;
2200         MFace *mface = NULL;
2201         int countTris=0, i;
2202         float *verts;
2203         int *tris;
2204
2205         dm = mesh_create_derived_render(ob);
2206         if(!dm) { *numVertices = *numTriangles = 0; *triangles=NULL; *vertices=NULL; }
2207         dlm = dm->convertToDispListMesh(dm, 1);
2208         if(!dlm) { dm->release(dm); *numVertices = *numTriangles = 0; *triangles=NULL; *vertices=NULL; }
2209         mface = dlm->mface;
2210
2211         *numVertices = dlm->totvert;
2212         verts = MEM_callocN( dlm->totvert*3*sizeof(float), "elbeemmesh_vertices");
2213         for(i=0; i<dlm->totvert; i++) {
2214                 VECCOPY( &verts[i*3], dlm->mvert[i].co);
2215         }
2216         *vertices = verts;
2217
2218         for(i=0; i<dlm->totface; i++) {
2219                 countTris++;
2220                 if(mface[i].v4) { countTris++; }
2221         }
2222         *numTriangles = countTris;
2223         tris = MEM_callocN( countTris*3*sizeof(int), "elbeemmesh_triangles");
2224         countTris = 0;
2225         for(i=0; i<dlm->totface; i++) {
2226                 int face[4];
2227                 face[0] = mface[i].v1;
2228                 face[1] = mface[i].v2;
2229                 face[2] = mface[i].v3;
2230                 face[3] = mface[i].v4;
2231
2232                 tris[countTris*3+0] = face[0]; 
2233                 tris[countTris*3+1] = face[1]; 
2234                 tris[countTris*3+2] = face[2]; 
2235                 countTris++;
2236                 if(face[3]) { 
2237                         tris[countTris*3+0] = face[0]; 
2238                         tris[countTris*3+1] = face[2]; 
2239                         tris[countTris*3+2] = face[3]; 
2240                         countTris++;
2241                 }
2242         }
2243         *triangles = tris;
2244
2245         if(dlm) displistmesh_free(dlm);
2246         dm->release(dm);
2247 }
2248
2249 /* read .bobj.gz file into a fluidsimDerivedMesh struct */
2250 Mesh* readBobjgz(char *filename, Mesh *orgmesh, float* bbstart, float *bbsize) //, fluidsimDerivedMesh *fsdm)
2251 {
2252         int wri,i,j;
2253         char debugStrBuffer[256];
2254         float wrf;
2255         Mesh *newmesh; 
2256         const int debugBobjRead = 1;
2257         // init data from old mesh (materials,flags)
2258         MFace *origMFace = &((MFace*) orgmesh->mface)[0];
2259         int mat_nr = -1;
2260         int flag = -1;
2261         MFace *fsface = NULL;
2262         int gotBytes;
2263         gzFile gzf;
2264
2265         if(!orgmesh) return NULL;
2266         if(!origMFace) return NULL;
2267         mat_nr = origMFace->mat_nr;
2268         flag = origMFace->flag;
2269
2270         // similar to copy_mesh
2271         newmesh = MEM_dupallocN(orgmesh);
2272         newmesh->mat= orgmesh->mat;
2273
2274         newmesh->mvert= NULL;
2275         newmesh->medge= NULL;
2276         newmesh->mface= NULL;
2277         newmesh->tface= NULL;
2278         newmesh->dface= NULL;
2279
2280         newmesh->dvert = NULL;
2281
2282         newmesh->mcol= NULL;
2283         newmesh->msticky= NULL;
2284         newmesh->texcomesh= NULL;
2285
2286         newmesh->key= NULL;
2287         newmesh->totface = 0;
2288         newmesh->totvert = 0;
2289         newmesh->totedge = 0;
2290         newmesh->medge = NULL;
2291
2292
2293         snprintf(debugStrBuffer,256,"Reading '%s' GZ_BOBJ... ",filename); elbeemDebugOut(debugStrBuffer); 
2294         gzf = gzopen(filename, "rb");
2295         // gzf = fopen(filename, "rb");
2296         // debug: fread(b,c,1,a) = gzread(a,b,c)
2297         if (!gzf) {
2298                 //snprintf(debugStrBuffer,256,"readBobjgz::error - Unable to open file for reading '%s'\n", filename); // DEBUG
2299                 MEM_freeN(newmesh);
2300                 return NULL;
2301         }
2302
2303         //if(sizeof(wri)!=4) { snprintf(debugStrBuffer,256,"Reading GZ_BOBJ, Invalid int size %d...\n", wri); return NULL; } // paranoia check
2304         gotBytes = gzread(gzf, &wri, sizeof(wri));
2305         newmesh->totvert = wri;
2306         newmesh->mvert = MEM_callocN(sizeof(MVert)*newmesh->totvert, "fluidsimDerivedMesh_bobjvertices");
2307         if(debugBobjRead){ snprintf(debugStrBuffer,256,"#vertices %d ", newmesh->totvert); elbeemDebugOut(debugStrBuffer); } //DEBUG
2308         for(i=0; i<newmesh->totvert;i++) {
2309                 //if(debugBobjRead) snprintf(debugStrBuffer,256,"V %d = ",i);
2310                 for(j=0; j<3; j++) {
2311                         gotBytes = gzread(gzf, &wrf, sizeof( wrf )); 
2312                         newmesh->mvert[i].co[j] = wrf;
2313                         //if(debugBobjRead) snprintf(debugStrBuffer,256,"%25.20f ", wrf);
2314                 }
2315                 //if(debugBobjRead) snprintf(debugStrBuffer,256,"\n");
2316         }
2317
2318         // should be the same as Vertices.size
2319         gotBytes = gzread(gzf, &wri, sizeof(wri));
2320         if(wri != newmesh->totvert) {
2321                 // complain #vertices has to be equal to #normals, reset&abort
2322                 MEM_freeN(newmesh->mvert);
2323                 MEM_freeN(newmesh);
2324                 snprintf(debugStrBuffer,256,"Reading GZ_BOBJ, #normals=%d, #vertices=%d, aborting...\n", wri,newmesh->totvert );
2325                 return NULL;
2326         }
2327         for(i=0; i<newmesh->totvert;i++) {
2328                 for(j=0; j<3; j++) {
2329                         gotBytes = gzread(gzf, &wrf, sizeof( wrf )); 
2330                         newmesh->mvert[i].no[j] = (short)(wrf*32767.0f);
2331                         //newmesh->mvert[i].no[j] = 0.5; // DEBUG tst
2332                 }
2333         //fprintf(stderr,"  DEBDPCN nm%d, %d = %d,%d,%d \n",
2334                         //(int)(newmesh->mvert), i, newmesh->mvert[i].no[0], newmesh->mvert[i].no[1], newmesh->mvert[i].no[2]);
2335         }
2336         //fprintf(stderr,"  DPCN 0 = %d,%d,%d \n", newmesh->mvert[0].no[0], newmesh->mvert[0].no[1], newmesh->mvert[0].no[2]);
2337
2338         
2339         /* compute no. of triangles */
2340         gotBytes = gzread(gzf, &wri, sizeof(wri));
2341         newmesh->totface = wri;
2342         newmesh->mface = MEM_callocN(sizeof(MFace)*newmesh->totface, "fluidsimDerivedMesh_bobjfaces");
2343         if(debugBobjRead){ snprintf(debugStrBuffer,256,"#faces %d ", newmesh->totface); elbeemDebugOut(debugStrBuffer); } //DEBUG
2344         fsface = newmesh->mface;
2345         for(i=0; i<newmesh->totface; i++) {
2346                 int face[4];
2347
2348                 gotBytes = gzread(gzf, &(face[0]), sizeof( face[0] )); 
2349                 gotBytes = gzread(gzf, &(face[1]), sizeof( face[1] )); 
2350                 gotBytes = gzread(gzf, &(face[2]), sizeof( face[2] )); 
2351                 face[3] = 0;
2352
2353                 fsface[i].v1 = face[0];
2354                 fsface[i].v2 = face[1];
2355                 fsface[i].v3 = face[2];
2356                 fsface[i].v4 = face[3];
2357         }
2358
2359         // correct triangles with v3==0 for blender, cycle verts
2360         for(i=0; i<newmesh->totface; i++) {
2361                 if(!fsface[i].v3) {
2362                         int temp = fsface[i].v1;
2363                         fsface[i].v1 = fsface[i].v2;
2364                         fsface[i].v2 = fsface[i].v3;
2365                         fsface[i].v3 = temp;
2366                 }
2367         }
2368         
2369         gzclose( gzf );
2370         for(i=0;i<newmesh->totface;i++) { 
2371                 fsface[i].mat_nr = mat_nr;
2372                 fsface[i].flag = flag;
2373                 fsface[i].edcode = ME_V1V2 | ME_V2V3 | ME_V3V1;
2374                 //snprintf(debugStrBuffer,256,"%d : %d,%d,%d\n", i,fsface[i].mat_nr, fsface[i].flag, fsface[i].edcode );
2375         }
2376
2377         snprintf(debugStrBuffer,256," (%d,%d) done\n", newmesh->totvert,newmesh->totface); elbeemDebugOut(debugStrBuffer); //DEBUG
2378         return newmesh;
2379 }
2380
2381 /* read zipped fluidsim velocities into the co's of the fluidsimsettings normals struct */
2382 void readVelgz(char *filename, Object *srcob)
2383 {
2384         char debugStrBuffer[256];
2385         int wri, i, j;
2386         float wrf;
2387         gzFile gzf;
2388         MVert *vverts = srcob->fluidsimSettings->meshSurfNormals;
2389         int len = strlen(filename);
2390         Mesh *mesh = srcob->data;
2391         // mesh and vverts have to be valid from loading...
2392
2393         // clean up in any case
2394         for(i=0; i<mesh->totvert;i++) { 
2395                 for(j=0; j<3; j++) {
2396                         vverts[i].co[j] = 0.; 
2397                 } 
2398         } 
2399         if(srcob->fluidsimSettings->domainNovecgen>0) return;
2400
2401         if(len<7) { 
2402                 //printf("readVelgz Eror: invalid filename '%s'\n",filename); // DEBUG
2403                 return; 
2404         }
2405
2406         // .bobj.gz , correct filename
2407         // 87654321
2408         filename[len-6] = 'v';
2409         filename[len-5] = 'e';
2410         filename[len-4] = 'l';
2411
2412         snprintf(debugStrBuffer,256,"Reading '%s' GZ_VEL... ",filename); elbeemDebugOut(debugStrBuffer); 
2413         gzf = gzopen(filename, "rb");
2414         if (!gzf) { 
2415                 //printf("readVelgz Eror: unable to open file '%s'\n",filename); // DEBUG
2416                 return; 
2417         }
2418
2419         gzread(gzf, &wri, sizeof( wri ));
2420         if(wri != mesh->totvert) {
2421                 //printf("readVelgz Eror: invalid no. of velocities %d vs. %d aborting.\n" ,wri ,mesh->totvert ); // DEBUG
2422                 return; 
2423         }
2424
2425         for(i=0; i<mesh->totvert;i++) {
2426                 for(j=0; j<3; j++) {
2427                         gzread(gzf, &wrf, sizeof( wrf )); 
2428                         vverts[i].co[j] = wrf;
2429                 }
2430                 //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
2431         }
2432
2433         gzclose(gzf);
2434 }
2435
2436
2437 /* ***************************** fluidsim derived mesh ***************************** */
2438
2439 /* check which file to load, and replace old mesh of the object with it */
2440 /* this replacement is undone at the end of mesh_calc_modifiers */
2441 void loadFluidsimMesh(Object *srcob, int useRenderParams)
2442 {
2443         Mesh *mesh = NULL;
2444         float *bbStart = NULL, *bbSize = NULL;
2445         float lastBB[3];
2446         int displaymode = 0;
2447         int curFrame = G.scene->r.cfra - 1 /*G.scene->r.sfra*/; /* start with 0 at start frame */
2448         char targetDir[FILE_MAXFILE+FILE_MAXDIR], targetFile[FILE_MAXFILE+FILE_MAXDIR];
2449         char debugStrBuffer[256];
2450         //snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d)\n", srcob->id.name, useRenderParams); // debug
2451
2452         if((!srcob)||(!srcob->fluidsimSettings)) {
2453                 snprintf(debugStrBuffer,256,"DEBUG - Invalid loadFluidsimMesh call, rp %d, dm %d)\n", useRenderParams, displaymode); // debug
2454                 elbeemDebugOut(debugStrBuffer); // debug
2455                 return;
2456         }
2457         // make sure the original mesh data pointer is stored
2458         if(!srcob->fluidsimSettings->orgMesh) {
2459                 srcob->fluidsimSettings->orgMesh = srcob->data;
2460         }
2461
2462         // free old mesh, if there is one (todo, check if it's still valid?)
2463         if(srcob->fluidsimSettings->meshSurface) {
2464                 Mesh *freeFsMesh = srcob->fluidsimSettings->meshSurface;
2465
2466                 // similar to free_mesh(...) , but no things like unlink...
2467                 if(freeFsMesh->mvert) MEM_freeN(freeFsMesh->mvert);
2468                 if(freeFsMesh->medge) MEM_freeN(freeFsMesh->medge);
2469                 if(freeFsMesh->mface) MEM_freeN(freeFsMesh->mface);
2470                 MEM_freeN(freeFsMesh);
2471                 
2472                 if(srcob->data == srcob->fluidsimSettings->meshSurface)
2473                  srcob->data = srcob->fluidsimSettings->orgMesh;
2474                 srcob->fluidsimSettings->meshSurface = NULL;
2475
2476                 if(srcob->fluidsimSettings->meshSurfNormals) MEM_freeN(srcob->fluidsimSettings->meshSurfNormals);
2477                 srcob->fluidsimSettings->meshSurfNormals = NULL;
2478         } 
2479
2480         // init bounding box
2481         bbStart = srcob->fluidsimSettings->bbStart; 
2482         bbSize = srcob->fluidsimSettings->bbSize;
2483         lastBB[0] = bbSize[0];  // TEST
2484         lastBB[1] = bbSize[1]; 
2485         lastBB[2] = bbSize[2];
2486         fluidsimGetAxisAlignedBB(srcob->fluidsimSettings->orgMesh, srcob->obmat, bbStart, bbSize, &srcob->fluidsimSettings->meshBB);
2487         // check free fsmesh... TODO
2488         
2489         if(!useRenderParams) {
2490                 displaymode = srcob->fluidsimSettings->guiDisplayMode;
2491         } else {
2492                 displaymode = srcob->fluidsimSettings->renderDisplayMode;
2493         }
2494         
2495         snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d, dm %d), curFra=%d, sFra=%d #=%d \n", 
2496                         srcob->id.name, useRenderParams, displaymode, G.scene->r.cfra, G.scene->r.sfra, curFrame ); // debug
2497         elbeemDebugOut(debugStrBuffer); // debug
2498
2499         strncpy(targetDir, srcob->fluidsimSettings->surfdataPath, FILE_MAXDIR);
2500         // use preview or final mesh?
2501         if(displaymode==1) {
2502                 // just display original object
2503                 srcob->data = srcob->fluidsimSettings->orgMesh;
2504                 return;
2505         } else if(displaymode==2) {
2506                 strcat(targetDir,"fluidsurface_preview_#");
2507         } else { // 3
2508                 strcat(targetDir,"fluidsurface_final_#");
2509         }
2510         BLI_convertstringcode(targetDir, G.sce, curFrame); // fixed #frame-no 
2511         strcpy(targetFile,targetDir);
2512         strcat(targetFile, ".bobj.gz");
2513
2514         snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d, dm %d) '%s' \n", srcob->id.name, useRenderParams, displaymode, targetFile);  // debug
2515         elbeemDebugOut(debugStrBuffer); // debug
2516
2517         if(displaymode!=2) { // dont add bounding box for final
2518                 mesh = readBobjgz(targetFile, srcob->fluidsimSettings->orgMesh ,NULL,NULL);
2519         } else {
2520                 mesh = readBobjgz(targetFile, srcob->fluidsimSettings->orgMesh, bbSize,bbSize );
2521         }
2522         if(!mesh) {
2523                 // switch, abort background rendering when fluidsim mesh is missing
2524                 const char *strEnvName2 = "BLENDER_ELBEEMBOBJABORT"; // from blendercall.cpp
2525                 if(G.background==1) {
2526                         if(getenv(strEnvName2)) {
2527                                 int elevel = atoi(getenv(strEnvName2));
2528                                 if(elevel>0) {
2529                                         printf("Env. var %s set, fluid sim mesh not found, aborting render...\n",strEnvName2);
2530                                         exit(1);
2531                                 }
2532                         }
2533                 }
2534                 
2535                 // display org. object upon failure
2536                 srcob->data = srcob->fluidsimSettings->orgMesh;
2537                 return;
2538         }
2539
2540         if((mesh)&&(mesh->totvert>0)) {
2541                 make_edges(mesh, 0);    // 0 = make all edges draw
2542         }
2543         srcob->fluidsimSettings->meshSurface = mesh;
2544         srcob->data = mesh;
2545         srcob->fluidsimSettings->meshSurfNormals = MEM_dupallocN(mesh->mvert);
2546
2547         // load vertex velocities, if they exist...
2548         // TODO? use generate flag as loading flag as well?
2549         // warning, needs original .bobj.gz mesh loading filename
2550         if(displaymode==3) {
2551                 readVelgz(targetFile, srcob);
2552         } else {
2553                 // no data for preview, only clear...
2554                 int i,j;
2555                 for(i=0; i<mesh->totvert;i++) { for(j=0; j<3; j++) { srcob->fluidsimSettings->meshSurfNormals[i].co[j] = 0.; }} 
2556         }
2557
2558         //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]);
2559         return;
2560 }
2561
2562 /* helper function */
2563 /* init axis aligned BB for mesh object */
2564 void fluidsimGetAxisAlignedBB(struct Mesh *mesh, float obmat[][4],
2565                  /*RET*/ float start[3], /*RET*/ float size[3], /*RET*/ struct Mesh **bbmesh )
2566 {
2567         float bbsx=0.0, bbsy=0.0, bbsz=0.0;
2568         float bbex=1.0, bbey=1.0, bbez=1.0;
2569         int i;
2570         float vec[3];
2571
2572         VECCOPY(vec, mesh->mvert[0].co); 
2573         Mat4MulVecfl(obmat, vec);
2574         bbsx = vec[0]; bbsy = vec[1]; bbsz = vec[2];
2575         bbex = vec[0]; bbey = vec[1]; bbez = vec[2];
2576
2577         for(i=1; i<mesh->totvert;i++) {
2578                 VECCOPY(vec, mesh->mvert[i].co);
2579                 Mat4MulVecfl(obmat, vec);
2580
2581                 if(vec[0] < bbsx){ bbsx= vec[0]; }
2582                 if(vec[1] < bbsy){ bbsy= vec[1]; }
2583                 if(vec[2] < bbsz){ bbsz= vec[2]; }
2584                 if(vec[0] > bbex){ bbex= vec[0]; }
2585                 if(vec[1] > bbey){ bbey= vec[1]; }
2586                 if(vec[2] > bbez){ bbez= vec[2]; }
2587         }
2588
2589         // return values...
2590         if(start) {
2591                 start[0] = bbsx;
2592                 start[1] = bbsy;
2593                 start[2] = bbsz;
2594         } 
2595         if(size) {
2596                 size[0] = bbex-bbsx;
2597                 size[1] = bbey-bbsy;
2598                 size[2] = bbez-bbsz;
2599         }
2600
2601         // init bounding box mesh?
2602         if(bbmesh) {
2603                 int i,j;
2604                 Mesh *newmesh = NULL;
2605                 if(!(*bbmesh)) { newmesh = MEM_callocN(sizeof(Mesh), "fluidsimGetAxisAlignedBB_meshbb"); }
2606                 else {           newmesh = *bbmesh; }
2607
2608                 newmesh->totvert = 8;
2609                 if(!newmesh->mvert) newmesh->mvert = MEM_callocN(sizeof(MVert)*newmesh->totvert, "fluidsimBBMesh_bobjvertices");
2610                 for(i=0; i<8; i++) {
2611                         for(j=0; j<3; j++) newmesh->mvert[i].co[j] = start[j]; 
2612                 }
2613
2614                 newmesh->totface = 6;
2615                 if(!newmesh->mface) newmesh->mface = MEM_callocN(sizeof(MFace)*newmesh->totface, "fluidsimBBMesh_bobjfaces");
2616
2617                 *bbmesh = newmesh;
2618         }
2619 }
2620
2621