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