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