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