= Multires =
[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
1986                 MEM_freeN(deformedVerts);
1987         } else if (dm) {
1988                 *final_r = dm;
1989         } else if (cage_r && *cage_r) {
1990                 *final_r = *cage_r;
1991         } else {
1992                 *final_r = getEditMeshDerivedMesh(em, ob, deformedVerts);
1993         }
1994 }
1995
1996 /***/
1997
1998
1999         /* Something of a hack, at the moment deal with weightpaint
2000          * by tucking into colors during modifier eval, only in
2001          * wpaint mode. Works ok but need to make sure recalc
2002          * happens on enter/exit wpaint.
2003          */
2004
2005 void weight_to_rgb(float input, float *fr, float *fg, float *fb)
2006 {
2007         float blend;
2008         
2009         blend= ((input/2.0f)+0.5f);
2010         
2011         if (input<=0.25f){      // blue->cyan
2012                 *fr= 0.0f;
2013                 *fg= blend*input*4.0f;
2014                 *fb= blend;
2015         }
2016         else if (input<=0.50f){ // cyan->green
2017                 *fr= 0.0f;
2018                 *fg= blend;
2019                 *fb= blend*(1.0f-((input-0.25f)*4.0f)); 
2020         }
2021         else if (input<=0.75){  // green->yellow
2022                 *fr= blend * ((input-0.50f)*4.0f);
2023                 *fg= blend;
2024                 *fb= 0.0f;
2025         }
2026         else if (input<=1.0){ // yellow->red
2027                 *fr= blend;
2028                 *fg= blend * (1.0f-((input-0.75f)*4.0f)); 
2029                 *fb= 0.0f;
2030         }
2031 }
2032 static void calc_weightpaint_vert_color(Object *ob, int vert, unsigned char *col)
2033 {
2034         Mesh *me = ob->data;
2035         float fr, fg, fb, input = 0.0f;
2036         int i;
2037
2038         if (me->dvert) {
2039                 for (i=0; i<me->dvert[vert].totweight; i++)
2040                         if (me->dvert[vert].dw[i].def_nr==ob->actdef-1)
2041                                 input+=me->dvert[vert].dw[i].weight;            
2042         }
2043
2044         CLAMP(input, 0.0f, 1.0f);
2045         
2046         weight_to_rgb(input, &fr, &fg, &fb);
2047         
2048         col[3] = (unsigned char)(fr * 255.0f);
2049         col[2] = (unsigned char)(fg * 255.0f);
2050         col[1] = (unsigned char)(fb * 255.0f);
2051         col[0] = 255;
2052 }
2053 static unsigned char *calc_weightpaint_colors(Object *ob) 
2054 {
2055         Mesh *me = ob->data;
2056         MFace *mf = me->mface;
2057         unsigned char *wtcol;
2058         int i;
2059         
2060         wtcol = MEM_callocN (sizeof (unsigned char) * me->totface*4*4, "weightmap");
2061         
2062         memset(wtcol, 0x55, sizeof (unsigned char) * me->totface*4*4);
2063         for (i=0; i<me->totface; i++, mf++){
2064                 calc_weightpaint_vert_color(ob, mf->v1, &wtcol[(i*4 + 0)*4]); 
2065                 calc_weightpaint_vert_color(ob, mf->v2, &wtcol[(i*4 + 1)*4]); 
2066                 calc_weightpaint_vert_color(ob, mf->v3, &wtcol[(i*4 + 2)*4]); 
2067                 if (mf->v4)
2068                         calc_weightpaint_vert_color(ob, mf->v4, &wtcol[(i*4 + 3)*4]); 
2069         }
2070         
2071         return wtcol;
2072 }
2073
2074 static void clear_mesh_caches(Object *ob)
2075 {
2076         Mesh *me= ob->data;
2077
2078                 /* also serves as signal to remake texspace */
2079         if (me->bb) {
2080                 MEM_freeN(me->bb);
2081                 me->bb = NULL;
2082         }
2083
2084         freedisplist(&ob->disp);
2085
2086         if (ob->derivedFinal) {
2087                 ob->derivedFinal->needsFree = 1;
2088                 ob->derivedFinal->release(ob->derivedFinal);
2089                 ob->derivedFinal= NULL;
2090         }
2091         if (ob->derivedDeform) {
2092                 ob->derivedDeform->needsFree = 1;
2093                 ob->derivedDeform->release(ob->derivedDeform);
2094                 ob->derivedDeform= NULL;
2095         }
2096 }
2097
2098 static void mesh_build_data(Object *ob, CustomDataMask dataMask)
2099 {
2100         Mesh *me = ob->data;
2101         float min[3], max[3];
2102
2103         clear_mesh_caches(ob);
2104
2105         if(ob!=G.obedit) {
2106                 Object *obact = G.scene->basact?G.scene->basact->object:NULL;
2107                 int editing = (G.f & (G_FACESELECT|G_WEIGHTPAINT|G_VERTEXPAINT|G_TEXTUREPAINT));
2108                 int needMapping = editing && (ob==obact);
2109
2110                 if( (G.f & G_WEIGHTPAINT) && ob==obact ) {
2111                         MCol *wpcol = (MCol*)calc_weightpaint_colors(ob);
2112                         int layernum = CustomData_number_of_layers(&me->fdata, CD_MCOL);
2113
2114                         /* ugly hack here, we temporarily add a new active mcol layer with
2115                            weightpaint colors in it, that is then duplicated in CDDM_from_mesh */
2116                         CustomData_add_layer(&me->fdata, CD_MCOL, CD_ASSIGN, wpcol, me->totface);
2117                         CustomData_set_layer_active(&me->fdata, CD_MCOL, layernum);
2118
2119                         mesh_calc_modifiers(ob, NULL, &ob->derivedDeform,
2120                                             &ob->derivedFinal, 0, 1,
2121                                             needMapping, dataMask);
2122
2123                         CustomData_free_layer_active(&me->fdata, CD_MCOL, me->totface);
2124                 } else {
2125                         mesh_calc_modifiers(ob, NULL, &ob->derivedDeform,
2126                                             &ob->derivedFinal, 0, 1,
2127                                             needMapping, dataMask);
2128                 }
2129
2130                 INIT_MINMAX(min, max);
2131
2132                 ob->derivedFinal->getMinMax(ob->derivedFinal, min, max);
2133
2134                 boundbox_set_from_min_max(mesh_get_bb(ob->data), min, max);
2135
2136                 ob->derivedFinal->needsFree = 0;
2137                 ob->derivedDeform->needsFree = 0;
2138                 ob->lastDataMask = dataMask;
2139         }
2140 }
2141
2142 static void editmesh_build_data(CustomDataMask dataMask)
2143 {
2144         float min[3], max[3];
2145
2146         EditMesh *em = G.editMesh;
2147
2148         clear_mesh_caches(G.obedit);
2149
2150         if (em->derivedFinal) {
2151                 if (em->derivedFinal!=em->derivedCage) {
2152                         em->derivedFinal->needsFree = 1;
2153                         em->derivedFinal->release(em->derivedFinal);
2154                 }
2155                 em->derivedFinal = NULL;
2156         }
2157         if (em->derivedCage) {
2158                 em->derivedCage->needsFree = 1;
2159                 em->derivedCage->release(em->derivedCage);
2160                 em->derivedCage = NULL;
2161         }
2162
2163         editmesh_calc_modifiers(&em->derivedCage, &em->derivedFinal, dataMask);
2164         em->lastDataMask = dataMask;
2165
2166         INIT_MINMAX(min, max);
2167
2168         em->derivedFinal->getMinMax(em->derivedFinal, min, max);
2169
2170         boundbox_set_from_min_max(mesh_get_bb(G.obedit->data), min, max);
2171
2172         em->derivedFinal->needsFree = 0;
2173         em->derivedCage->needsFree = 0;
2174 }
2175
2176 void makeDerivedMesh(Object *ob, CustomDataMask dataMask)
2177 {
2178         if (ob==G.obedit) {
2179                 editmesh_build_data(dataMask);
2180         } else {
2181                 PartEff *paf= give_parteff(ob);
2182                 
2183                 mesh_build_data(ob, dataMask);
2184                 
2185                 if(paf) {
2186                         if((paf->flag & PAF_STATIC) || (ob->recalc & OB_RECALC_TIME)==0)
2187                                 build_particle_system(ob);
2188                 }
2189         }
2190 }
2191
2192 /***/
2193
2194 DerivedMesh *mesh_get_derived_final(Object *ob, CustomDataMask dataMask)
2195 {
2196         /* if there's no derived mesh or the last data mask used doesn't include
2197          * the data we need, rebuild the derived mesh
2198          */
2199         if(!ob->derivedFinal || (dataMask & ob->lastDataMask) != dataMask)
2200                 mesh_build_data(ob, dataMask);
2201
2202         return ob->derivedFinal;
2203 }
2204
2205 DerivedMesh *mesh_get_derived_deform(Object *ob, CustomDataMask dataMask)
2206 {
2207         /* if there's no derived mesh or the last data mask used doesn't include
2208          * the data we need, rebuild the derived mesh
2209          */
2210         if(!ob->derivedDeform || (dataMask & ob->lastDataMask) != dataMask)
2211                 mesh_build_data(ob, dataMask);
2212
2213         return ob->derivedDeform;
2214 }
2215
2216 /* Move to multires Pin level, returns a copy of the original vertex coords. */
2217 float *multires_render_pin(Object *ob, Mesh *me, int *orig_lvl)
2218 {
2219         float *vert_copy= NULL;
2220
2221         if(me->mr) {
2222                 MultiresLevel *lvl= NULL;
2223                 int i;
2224         
2225                 /* Copy the highest level of multires verts */
2226                 *orig_lvl= me->mr->current;
2227                 lvl= multires_level_n(me->mr, BLI_countlist(&me->mr->levels));
2228                 vert_copy= MEM_callocN(sizeof(float)*3*lvl->totvert, "multires vert_copy");
2229                 for(i=0; i<lvl->totvert; ++i)
2230                         VecCopyf(&vert_copy[i*3], lvl->verts[i].co);
2231         
2232                 /* Goto the pin level for multires */
2233                 me->mr->newlvl= me->mr->pinlvl;
2234                 multires_set_level(ob, me);
2235         }
2236         
2237         return vert_copy;
2238 }
2239
2240 /* Propagate the changes to render level - fails if mesh topology changed */
2241 void multires_render_final(Object *ob, Mesh *me, DerivedMesh **dm, float *vert_copy, const int orig_lvl)
2242 {
2243         if(me->mr) {
2244                 if((*dm)->getNumVerts(*dm) == me->totvert &&
2245                    (*dm)->getNumFaces(*dm) == me->totface) {
2246                         MultiresLevel *lvl= multires_level_n(me->mr, BLI_countlist(&me->mr->levels));
2247                         DerivedMesh *old= NULL;
2248                         int i;
2249
2250                         (*dm)->copyVertArray(*dm, me->mvert);
2251                         (*dm)->release(*dm);
2252
2253                         me->mr->newlvl= me->mr->renderlvl;
2254                         multires_set_level(ob, me);
2255                         (*dm)= getMeshDerivedMesh(me, ob, NULL);
2256
2257                         /* Some of the data in dm is referenced externally, so make a copy */
2258                         old= *dm;
2259                         (*dm)= CDDM_copy(old);
2260                         old->release(old);
2261
2262                         /* Restore the original verts */
2263                         me->mr->newlvl= BLI_countlist(&me->mr->levels);
2264                         multires_set_level(ob, me);
2265                         for(i=0; i<lvl->totvert; ++i)
2266                                 VecCopyf(me->mvert[i].co, &vert_copy[i*3]);
2267                 }
2268                 
2269                 if(vert_copy)
2270                         MEM_freeN(vert_copy);
2271                         
2272                 me->mr->newlvl= orig_lvl;
2273                 multires_set_level(ob, me);
2274         }
2275 }
2276
2277 /* Multires note - if mesh has multires enabled, mesh is first set to the Pin level,
2278    where all modifiers are applied, then if the topology hasn't changed, the changes
2279    from modifiers are propagated up to the Render level. */
2280 DerivedMesh *mesh_create_derived_render(Object *ob, CustomDataMask dataMask)
2281 {
2282         DerivedMesh *final;
2283         Mesh *me= get_mesh(ob);
2284         float *vert_copy= NULL;
2285         int orig_lvl= 0;
2286         
2287         vert_copy= multires_render_pin(ob, me, &orig_lvl);
2288         mesh_calc_modifiers(ob, NULL, NULL, &final, 1, 1, 0, dataMask);
2289         multires_render_final(ob, me, &final, vert_copy, orig_lvl);
2290
2291         return final;
2292 }
2293
2294 DerivedMesh *mesh_create_derived_view(Object *ob, CustomDataMask dataMask)
2295 {
2296         DerivedMesh *final;
2297
2298         mesh_calc_modifiers(ob, NULL, NULL, &final, 0, 1, 0, dataMask);
2299
2300         return final;
2301 }
2302
2303 DerivedMesh *mesh_create_derived_no_deform(Object *ob, float (*vertCos)[3],
2304                                            CustomDataMask dataMask)
2305 {
2306         DerivedMesh *final;
2307         
2308         mesh_calc_modifiers(ob, vertCos, NULL, &final, 0, 0, 0, dataMask);
2309
2310         return final;
2311 }
2312
2313 DerivedMesh *mesh_create_derived_no_deform_render(Object *ob,
2314                                                   float (*vertCos)[3],
2315                                                   CustomDataMask dataMask)
2316 {
2317         DerivedMesh *final;
2318         Mesh *me= get_mesh(ob);
2319         float *vert_copy= NULL;
2320         int orig_lvl= 0;
2321
2322         vert_copy= multires_render_pin(ob, me, &orig_lvl);
2323         mesh_calc_modifiers(ob, vertCos, NULL, &final, 1, 0, 0, dataMask);
2324         multires_render_final(ob, me, &final, vert_copy, orig_lvl);
2325
2326         return final;
2327 }
2328
2329 /***/
2330
2331 DerivedMesh *editmesh_get_derived_cage_and_final(DerivedMesh **final_r,
2332                                                  CustomDataMask dataMask)
2333 {
2334         /* if there's no derived mesh or the last data mask used doesn't include
2335          * the data we need, rebuild the derived mesh
2336          */
2337         if(!G.editMesh->derivedCage ||
2338            (G.editMesh->lastDataMask & dataMask) != dataMask)
2339                 editmesh_build_data(dataMask);
2340
2341         *final_r = G.editMesh->derivedFinal;
2342         return G.editMesh->derivedCage;
2343 }
2344
2345 DerivedMesh *editmesh_get_derived_cage(CustomDataMask dataMask)
2346 {
2347         /* if there's no derived mesh or the last data mask used doesn't include
2348          * the data we need, rebuild the derived mesh
2349          */
2350         if(!G.editMesh->derivedCage ||
2351            (G.editMesh->lastDataMask & dataMask) != dataMask)
2352                 editmesh_build_data(dataMask);
2353
2354         return G.editMesh->derivedCage;
2355 }
2356
2357 DerivedMesh *editmesh_get_derived_base(void)
2358 {
2359         return getEditMeshDerivedMesh(G.editMesh, G.obedit, NULL);
2360 }
2361
2362
2363 /* ********* For those who don't grasp derived stuff! (ton) :) *************** */
2364
2365 static void make_vertexcosnos__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
2366 {
2367         float *vec = userData;
2368         
2369         vec+= 6*index;
2370
2371         /* check if we've been here before (normal should not be 0) */
2372         if(vec[3] || vec[4] || vec[5]) return;
2373
2374         VECCOPY(vec, co);
2375         vec+= 3;
2376         if(no_f) {
2377                 VECCOPY(vec, no_f);
2378         }
2379         else {
2380                 VECCOPY(vec, no_s);
2381         }
2382 }
2383
2384 /* always returns original amount me->totvert of vertices and normals, but fully deformed and subsurfered */
2385 /* this is needed for all code using vertexgroups (no subsurf support) */
2386 /* it stores the normals as floats, but they can still be scaled as shorts (32767 = unit) */
2387 /* in use now by vertex/weight paint and particle generating */
2388
2389 float *mesh_get_mapped_verts_nors(Object *ob)
2390 {
2391         Mesh *me= ob->data;
2392         DerivedMesh *dm;
2393         float *vertexcosnos;
2394         
2395         /* lets prevent crashing... */
2396         if(ob->type!=OB_MESH || me->totvert==0)
2397                 return NULL;
2398         
2399         dm= mesh_get_derived_final(ob, CD_MASK_BAREMESH);
2400         vertexcosnos= MEM_callocN(6*sizeof(float)*me->totvert, "vertexcosnos map");
2401         
2402         if(dm->foreachMappedVert) {
2403                 dm->foreachMappedVert(dm, make_vertexcosnos__mapFunc, vertexcosnos);
2404         }
2405         else {
2406                 float *fp= vertexcosnos;
2407                 int a;
2408                 
2409                 for(a=0; a< me->totvert; a++, fp+=6) {
2410                         dm->getVertCo(dm, a, fp);
2411                         dm->getVertNo(dm, a, fp+3);
2412                 }
2413         }
2414         
2415         dm->release(dm);
2416         return vertexcosnos;
2417 }
2418
2419
2420 /* ************************* fluidsim bobj file handling **************************** */
2421
2422 #ifndef DISABLE_ELBEEM
2423
2424 #ifdef WIN32
2425 #ifndef snprintf
2426 #define snprintf _snprintf
2427 #endif
2428 #endif
2429
2430 /* write .bobj.gz file for a mesh object */
2431 void writeBobjgz(char *filename, struct Object *ob, int useGlobalCoords, int append, float time) 
2432 {
2433         char debugStrBuffer[256];
2434         int wri,i,j,totvert,totface;
2435         float wrf;
2436         gzFile gzf;
2437         DerivedMesh *dm;
2438         float vec[3];
2439         float rotmat[3][3];
2440         MVert *mvert;
2441         MFace *mface;
2442         //if(append)return; // DEBUG
2443
2444         if(!ob->data || (ob->type!=OB_MESH)) {
2445                 snprintf(debugStrBuffer,256,"Writing GZ_BOBJ Invalid object %s ...\n", ob->id.name); 
2446                 elbeemDebugOut(debugStrBuffer);
2447                 return;
2448         }
2449         if((ob->size[0]<0.0) || (ob->size[0]<0.0) || (ob->size[0]<0.0) ) {
2450                 snprintf(debugStrBuffer,256,"\nfluidSim::writeBobjgz:: Warning object %s has negative scaling - check triangle ordering...?\n\n", ob->id.name); 
2451                 elbeemDebugOut(debugStrBuffer);
2452         }
2453
2454         snprintf(debugStrBuffer,256,"Writing GZ_BOBJ '%s' ... ",filename); elbeemDebugOut(debugStrBuffer); 
2455         if(append) gzf = gzopen(filename, "a+b9");
2456         else       gzf = gzopen(filename, "wb9");
2457         if (!gzf) {
2458                 snprintf(debugStrBuffer,256,"writeBobjgz::error - Unable to open file for writing '%s'\n", filename);
2459                 elbeemDebugOut(debugStrBuffer);
2460                 return;
2461         }
2462
2463         dm = mesh_create_derived_render(ob, CD_MASK_BAREMESH);
2464         //dm = mesh_create_derived_no_deform(ob,NULL);
2465
2466         mvert = dm->getVertArray(dm);
2467         mface = dm->getFaceArray(dm);
2468         totvert = dm->getNumVerts(dm);
2469         totface = dm->getNumFaces(dm);
2470
2471         // write time value for appended anim mesh
2472         if(append) {
2473                 gzwrite(gzf, &time, sizeof(time));
2474         }
2475
2476         // continue with verts/norms
2477         if(sizeof(wri)!=4) { snprintf(debugStrBuffer,256,"Writing GZ_BOBJ, Invalid int size %d...\n", wri); elbeemDebugOut(debugStrBuffer); return; } // paranoia check
2478         wri = dm->getNumVerts(dm);
2479         mvert = dm->getVertArray(dm);
2480         gzwrite(gzf, &wri, sizeof(wri));
2481         for(i=0; i<wri;i++) {
2482                 VECCOPY(vec, mvert[i].co);
2483                 if(useGlobalCoords) { Mat4MulVecfl(ob->obmat, vec); }
2484                 for(j=0; j<3; j++) {
2485                         wrf = vec[j]; 
2486                         gzwrite(gzf, &wrf, sizeof( wrf )); 
2487                 }
2488         }
2489
2490         // should be the same as Vertices.size
2491         wri = totvert;
2492         gzwrite(gzf, &wri, sizeof(wri));
2493         EulToMat3(ob->rot, rotmat);
2494         for(i=0; i<wri;i++) {
2495                 VECCOPY(vec, mvert[i].no);
2496                 Normalise(vec);
2497                 if(useGlobalCoords) { Mat3MulVecfl(rotmat, vec); }
2498                 for(j=0; j<3; j++) {
2499                         wrf = vec[j];
2500                         gzwrite(gzf, &wrf, sizeof( wrf )); 
2501                 }
2502         }
2503
2504         // append only writes verts&norms 
2505         if(!append) {
2506                 //float side1[3],side2[3],norm1[3],norm2[3];
2507                 //float inpf;
2508         
2509                 // compute no. of triangles 
2510                 wri = 0;
2511                 for(i=0; i<totface; i++) {
2512                         wri++;
2513                         if(mface[i].v4) { wri++; }
2514                 }
2515                 gzwrite(gzf, &wri, sizeof(wri));
2516                 for(i=0; i<totface; i++) {
2517
2518                         int face[4];
2519                         face[0] = mface[i].v1;
2520                         face[1] = mface[i].v2;
2521                         face[2] = mface[i].v3;
2522                         face[3] = mface[i].v4;
2523                         //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);
2524                         //VecSubf(side1, mvert[face[1]].co,mvert[face[0]].co);
2525                         //VecSubf(side2, mvert[face[2]].co,mvert[face[0]].co);
2526                         //Crossf(norm1,side1,side2);
2527                         gzwrite(gzf, &(face[0]), sizeof( face[0] )); 
2528                         gzwrite(gzf, &(face[1]), sizeof( face[1] )); 
2529                         gzwrite(gzf, &(face[2]), sizeof( face[2] )); 
2530                         if(face[3]) { 
2531                                 //VecSubf(side1, mvert[face[2]].co,mvert[face[0]].co);
2532                                 //VecSubf(side2, mvert[face[3]].co,mvert[face[0]].co);
2533                                 //Crossf(norm2,side1,side2);
2534                                 //inpf = Inpf(norm1,norm2);
2535                                 //if(inpf>0.) {
2536                                 gzwrite(gzf, &(face[0]), sizeof( face[0] )); 
2537                                 gzwrite(gzf, &(face[2]), sizeof( face[2] )); 
2538                                 gzwrite(gzf, &(face[3]), sizeof( face[3] )); 
2539                                 //} else {
2540                                         //gzwrite(gzf, &(face[0]), sizeof( face[0] )); 
2541                                         //gzwrite(gzf, &(face[3]), sizeof( face[3] )); 
2542                                         //gzwrite(gzf, &(face[2]), sizeof( face[2] )); 
2543                                 //}
2544                         } // quad
2545                 }
2546         }
2547
2548         snprintf(debugStrBuffer,256,"Done. #Vertices: %d, #Triangles: %d\n", totvert, totface ); 
2549         elbeemDebugOut(debugStrBuffer);
2550         
2551         gzclose( gzf );
2552         dm->release(dm);
2553 }
2554
2555 void initElbeemMesh(struct Object *ob, 
2556                 int *numVertices, float **vertices, 
2557                 int *numTriangles, int **triangles,
2558                 int useGlobalCoords) 
2559 {
2560         DerivedMesh *dm = NULL;
2561         MVert *mvert;
2562         MFace *mface;
2563         int countTris=0, i, totvert, totface;
2564         float *verts;
2565         int *tris;
2566
2567         dm = mesh_create_derived_render(ob, CD_MASK_BAREMESH);
2568         //dm = mesh_create_derived_no_deform(ob,NULL);
2569
2570         mvert = dm->getVertArray(dm);
2571         mface = dm->getFaceArray(dm);
2572         totvert = dm->getNumVerts(dm);
2573         totface = dm->getNumFaces(dm);
2574
2575         *numVertices = totvert;
2576         verts = MEM_callocN( totvert*3*sizeof(float), "elbeemmesh_vertices");
2577         for(i=0; i<totvert; i++) {
2578                 VECCOPY( &verts[i*3], mvert[i].co);
2579                 if(useGlobalCoords) { Mat4MulVecfl(ob->obmat, &verts[i*3]); }
2580         }
2581         *vertices = verts;
2582
2583         for(i=0; i<totface; i++) {
2584                 countTris++;
2585                 if(mface[i].v4) { countTris++; }
2586         }
2587         *numTriangles = countTris;
2588         tris = MEM_callocN( countTris*3*sizeof(int), "elbeemmesh_triangles");
2589         countTris = 0;
2590         for(i=0; i<totface; i++) {
2591                 int face[4];
2592                 face[0] = mface[i].v1;
2593                 face[1] = mface[i].v2;
2594                 face[2] = mface[i].v3;
2595                 face[3] = mface[i].v4;
2596
2597                 tris[countTris*3+0] = face[0]; 
2598                 tris[countTris*3+1] = face[1]; 
2599                 tris[countTris*3+2] = face[2]; 
2600                 countTris++;
2601                 if(face[3]) { 
2602                         tris[countTris*3+0] = face[0]; 
2603                         tris[countTris*3+1] = face[2]; 
2604                         tris[countTris*3+2] = face[3]; 
2605                         countTris++;
2606                 }
2607         }
2608         *triangles = tris;
2609
2610         dm->release(dm);
2611 }
2612
2613 /* read .bobj.gz file into a fluidsimDerivedMesh struct */
2614 Mesh* readBobjgz(char *filename, Mesh *orgmesh, float* bbstart, float *bbsize) //, fluidsimDerivedMesh *fsdm)
2615 {
2616         int wri,i,j;
2617         char debugStrBuffer[256];
2618         float wrf;
2619         Mesh *newmesh; 
2620         const int debugBobjRead = 1;
2621         // init data from old mesh (materials,flags)
2622         MFace *origMFace = &((MFace*) orgmesh->mface)[0];
2623         int mat_nr = -1;
2624         int flag = -1;
2625         MFace *fsface = NULL;
2626         int gotBytes;
2627         gzFile gzf;
2628
2629         if(!orgmesh) return NULL;
2630         if(!origMFace) return NULL;
2631         mat_nr = origMFace->mat_nr;
2632         flag = origMFace->flag;
2633
2634         // similar to copy_mesh
2635         newmesh = MEM_dupallocN(orgmesh);
2636         newmesh->mat= orgmesh->mat;
2637
2638         newmesh->mvert= NULL;
2639         newmesh->medge= NULL;
2640         newmesh->mface= NULL;
2641         newmesh->mtface= NULL;
2642
2643         newmesh->dvert = NULL;
2644
2645         newmesh->mcol= NULL;
2646         newmesh->msticky= NULL;
2647         newmesh->texcomesh= NULL;
2648         memset(&newmesh->vdata, 0, sizeof(newmesh->vdata));
2649         memset(&newmesh->edata, 0, sizeof(newmesh->edata));
2650         memset(&newmesh->fdata, 0, sizeof(newmesh->fdata));
2651
2652         newmesh->key= NULL;
2653         newmesh->totface = 0;
2654         newmesh->totvert = 0;
2655         newmesh->totedge = 0;
2656         newmesh->medge = NULL;
2657
2658
2659         snprintf(debugStrBuffer,256,"Reading '%s' GZ_BOBJ... ",filename); elbeemDebugOut(debugStrBuffer); 
2660         gzf = gzopen(filename, "rb");
2661         // gzf = fopen(filename, "rb");
2662         // debug: fread(b,c,1,a) = gzread(a,b,c)
2663         if (!gzf) {
2664                 //snprintf(debugStrBuffer,256,"readBobjgz::error - Unable to open file for reading '%s'\n", filename); // DEBUG
2665                 MEM_freeN(newmesh);
2666                 return NULL;
2667         }
2668
2669         //if(sizeof(wri)!=4) { snprintf(debugStrBuffer,256,"Reading GZ_BOBJ, Invalid int size %d...\n", wri); return NULL; } // paranoia check
2670         gotBytes = gzread(gzf, &wri, sizeof(wri));
2671         newmesh->totvert = wri;
2672         newmesh->mvert = CustomData_add_layer(&newmesh->vdata, CD_MVERT, CD_CALLOC, NULL, newmesh->totvert);
2673         if(debugBobjRead){ snprintf(debugStrBuffer,256,"#vertices %d ", newmesh->totvert); elbeemDebugOut(debugStrBuffer); } //DEBUG
2674         for(i=0; i<newmesh->totvert;i++) {
2675                 //if(debugBobjRead) snprintf(debugStrBuffer,256,"V %d = ",i);
2676                 for(j=0; j<3; j++) {
2677                         gotBytes = gzread(gzf, &wrf, sizeof( wrf )); 
2678                         newmesh->mvert[i].co[j] = wrf;
2679                         //if(debugBobjRead) snprintf(debugStrBuffer,256,"%25.20f ", wrf);
2680                 }
2681                 //if(debugBobjRead) snprintf(debugStrBuffer,256,"\n");
2682         }
2683
2684         // should be the same as Vertices.size
2685         gotBytes = gzread(gzf, &wri, sizeof(wri));
2686         if(wri != newmesh->totvert) {
2687                 // complain #vertices has to be equal to #normals, reset&abort
2688                 CustomData_free_layer_active(&newmesh->vdata, CD_MVERT, newmesh->totvert);
2689                 MEM_freeN(newmesh);
2690                 snprintf(debugStrBuffer,256,"Reading GZ_BOBJ, #normals=%d, #vertices=%d, aborting...\n", wri,newmesh->totvert );
2691                 return NULL;
2692         }
2693         for(i=0; i<newmesh->totvert;i++) {
2694                 for(j=0; j<3; j++) {
2695                         gotBytes = gzread(gzf, &wrf, sizeof( wrf )); 
2696                         newmesh->mvert[i].no[j] = (short)(wrf*32767.0f);
2697                         //newmesh->mvert[i].no[j] = 0.5; // DEBUG tst
2698                 }
2699         //fprintf(stderr,"  DEBDPCN nm%d, %d = %d,%d,%d \n",
2700                         //(int)(newmesh->mvert), i, newmesh->mvert[i].no[0], newmesh->mvert[i].no[1], newmesh->mvert[i].no[2]);
2701         }
2702         //fprintf(stderr,"  DPCN 0 = %d,%d,%d \n", newmesh->mvert[0].no[0], newmesh->mvert[0].no[1], newmesh->mvert[0].no[2]);
2703
2704         
2705         /* compute no. of triangles */
2706         gotBytes = gzread(gzf, &wri, sizeof(wri));
2707         newmesh->totface = wri;
2708         newmesh->mface = CustomData_add_layer(&newmesh->fdata, CD_MFACE, CD_CALLOC, NULL, newmesh->totface);
2709         if(debugBobjRead){ snprintf(debugStrBuffer,256,"#faces %d ", newmesh->totface); elbeemDebugOut(debugStrBuffer); } //DEBUG
2710         fsface = newmesh->mface;
2711         for(i=0; i<newmesh->totface; i++) {
2712                 int face[4];
2713
2714                 gotBytes = gzread(gzf, &(face[0]), sizeof( face[0] )); 
2715                 gotBytes = gzread(gzf, &(face[1]), sizeof( face[1] )); 
2716                 gotBytes = gzread(gzf, &(face[2]), sizeof( face[2] )); 
2717                 face[3] = 0;
2718
2719                 fsface[i].v1 = face[0];
2720                 fsface[i].v2 = face[1];
2721                 fsface[i].v3 = face[2];
2722                 fsface[i].v4 = face[3];
2723         }
2724
2725         // correct triangles with v3==0 for blender, cycle verts
2726         for(i=0; i<newmesh->totface; i++) {
2727                 if(!fsface[i].v3) {
2728                         int temp = fsface[i].v1;
2729                         fsface[i].v1 = fsface[i].v2;
2730                         fsface[i].v2 = fsface[i].v3;
2731                         fsface[i].v3 = temp;
2732                 }
2733         }
2734         
2735         gzclose( gzf );
2736         for(i=0;i<newmesh->totface;i++) { 
2737                 fsface[i].mat_nr = mat_nr;
2738                 fsface[i].flag = flag;
2739                 fsface[i].edcode = ME_V1V2 | ME_V2V3 | ME_V3V1;
2740                 //snprintf(debugStrBuffer,256,"%d : %d,%d,%d\n", i,fsface[i].mat_nr, fsface[i].flag, fsface[i].edcode );
2741         }
2742
2743         snprintf(debugStrBuffer,256," (%d,%d) done\n", newmesh->totvert,newmesh->totface); elbeemDebugOut(debugStrBuffer); //DEBUG
2744         return newmesh;
2745 }
2746
2747 /* read zipped fluidsim velocities into the co's of the fluidsimsettings normals struct */
2748 void readVelgz(char *filename, Object *srcob)
2749 {
2750         char debugStrBuffer[256];
2751         int wri, i, j;
2752         float wrf;
2753         gzFile gzf;
2754         MVert *vverts = srcob->fluidsimSettings->meshSurfNormals;
2755         int len = strlen(filename);
2756         Mesh *mesh = srcob->data;
2757         // mesh and vverts have to be valid from loading...
2758
2759         // clean up in any case
2760         for(i=0; i<mesh->totvert;i++) { 
2761                 for(j=0; j<3; j++) {
2762                         vverts[i].co[j] = 0.; 
2763                 } 
2764         } 
2765         if(srcob->fluidsimSettings->domainNovecgen>0) return;
2766
2767         if(len<7) { 
2768                 //printf("readVelgz Eror: invalid filename '%s'\n",filename); // DEBUG
2769                 return; 
2770         }
2771
2772         // .bobj.gz , correct filename
2773         // 87654321
2774         filename[len-6] = 'v';
2775         filename[len-5] = 'e';
2776         filename[len-4] = 'l';
2777
2778         snprintf(debugStrBuffer,256,"Reading '%s' GZ_VEL... ",filename); elbeemDebugOut(debugStrBuffer); 
2779         gzf = gzopen(filename, "rb");
2780         if (!gzf) { 
2781                 //printf("readVelgz Eror: unable to open file '%s'\n",filename); // DEBUG
2782                 return; 
2783         }
2784
2785         gzread(gzf, &wri, sizeof( wri ));
2786         if(wri != mesh->totvert) {
2787                 //printf("readVelgz Eror: invalid no. of velocities %d vs. %d aborting.\n" ,wri ,mesh->totvert ); // DEBUG
2788                 return; 
2789         }
2790
2791         for(i=0; i<mesh->totvert;i++) {
2792                 for(j=0; j<3; j++) {
2793                         gzread(gzf, &wrf, sizeof( wrf )); 
2794                         vverts[i].co[j] = wrf;
2795                 }
2796                 //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
2797         }
2798
2799         gzclose(gzf);
2800 }
2801
2802
2803 /* ***************************** fluidsim derived mesh ***************************** */
2804
2805 /* check which file to load, and replace old mesh of the object with it */
2806 /* this replacement is undone at the end of mesh_calc_modifiers */
2807 void loadFluidsimMesh(Object *srcob, int useRenderParams)
2808 {
2809         Mesh *mesh = NULL;
2810         float *bbStart = NULL, *bbSize = NULL;
2811         float lastBB[3];
2812         int displaymode = 0;
2813         int curFrame = G.scene->r.cfra - 1 /*G.scene->r.sfra*/; /* start with 0 at start frame */
2814         char targetDir[FILE_MAXFILE+FILE_MAXDIR], targetFile[FILE_MAXFILE+FILE_MAXDIR];
2815         char debugStrBuffer[256];
2816         //snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d)\n", srcob->id.name, useRenderParams); // debug
2817
2818         if((!srcob)||(!srcob->fluidsimSettings)) {
2819                 snprintf(debugStrBuffer,256,"DEBUG - Invalid loadFluidsimMesh call, rp %d, dm %d)\n", useRenderParams, displaymode); // debug
2820                 elbeemDebugOut(debugStrBuffer); // debug
2821                 return;
2822         }
2823         // make sure the original mesh data pointer is stored
2824         if(!srcob->fluidsimSettings->orgMesh) {
2825                 srcob->fluidsimSettings->orgMesh = srcob->data;
2826         }
2827
2828         // free old mesh, if there is one (todo, check if it's still valid?)
2829         if(srcob->fluidsimSettings->meshSurface) {
2830                 Mesh *freeFsMesh = srcob->fluidsimSettings->meshSurface;
2831
2832                 // similar to free_mesh(...) , but no things like unlink...
2833                 CustomData_free(&freeFsMesh->vdata, freeFsMesh->totvert);
2834                 CustomData_free(&freeFsMesh->edata, freeFsMesh->totedge);
2835                 CustomData_free(&freeFsMesh->fdata, freeFsMesh->totface);
2836                 MEM_freeN(freeFsMesh);
2837                 
2838                 if(srcob->data == srcob->fluidsimSettings->meshSurface)
2839                  srcob->data = srcob->fluidsimSettings->orgMesh;
2840                 srcob->fluidsimSettings->meshSurface = NULL;
2841
2842                 if(srcob->fluidsimSettings->meshSurfNormals) MEM_freeN(srcob->fluidsimSettings->meshSurfNormals);
2843                 srcob->fluidsimSettings->meshSurfNormals = NULL;
2844         } 
2845
2846         // init bounding box
2847         bbStart = srcob->fluidsimSettings->bbStart; 
2848         bbSize = srcob->fluidsimSettings->bbSize;
2849         lastBB[0] = bbSize[0];  // TEST
2850         lastBB[1] = bbSize[1]; 
2851         lastBB[2] = bbSize[2];
2852         fluidsimGetAxisAlignedBB(srcob->fluidsimSettings->orgMesh, srcob->obmat, bbStart, bbSize, &srcob->fluidsimSettings->meshBB);
2853         // check free fsmesh... TODO
2854         
2855         if(!useRenderParams) {
2856                 displaymode = srcob->fluidsimSettings->guiDisplayMode;
2857         } else {
2858                 displaymode = srcob->fluidsimSettings->renderDisplayMode;
2859         }
2860         
2861         snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d, dm %d), curFra=%d, sFra=%d #=%d \n", 
2862                         srcob->id.name, useRenderParams, displaymode, G.scene->r.cfra, G.scene->r.sfra, curFrame ); // debug
2863         elbeemDebugOut(debugStrBuffer); // debug
2864
2865         strncpy(targetDir, srcob->fluidsimSettings->surfdataPath, FILE_MAXDIR);
2866         // use preview or final mesh?
2867         if(displaymode==1) {
2868                 // just display original object
2869                 srcob->data = srcob->fluidsimSettings->orgMesh;
2870                 return;
2871         } else if(displaymode==2) {
2872                 strcat(targetDir,"fluidsurface_preview_#");
2873         } else { // 3
2874                 strcat(targetDir,"fluidsurface_final_#");
2875         }
2876         BLI_convertstringcode(targetDir, G.sce, curFrame); // fixed #frame-no 
2877         strcpy(targetFile,targetDir);
2878         strcat(targetFile, ".bobj.gz");
2879
2880         snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d, dm %d) '%s' \n", srcob->id.name, useRenderParams, displaymode, targetFile);  // debug
2881         elbeemDebugOut(debugStrBuffer); // debug
2882
2883         if(displaymode!=2) { // dont add bounding box for final
2884                 mesh = readBobjgz(targetFile, srcob->fluidsimSettings->orgMesh ,NULL,NULL);
2885         } else {
2886                 mesh = readBobjgz(targetFile, srcob->fluidsimSettings->orgMesh, bbSize,bbSize );
2887         }
2888         if(!mesh) {
2889                 // switch, abort background rendering when fluidsim mesh is missing
2890                 const char *strEnvName2 = "BLENDER_ELBEEMBOBJABORT"; // from blendercall.cpp
2891                 if(G.background==1) {
2892                         if(getenv(strEnvName2)) {
2893                                 int elevel = atoi(getenv(strEnvName2));
2894                                 if(elevel>0) {
2895                                         printf("Env. var %s set, fluid sim mesh '%s' not found, aborting render...\n",strEnvName2, targetFile);
2896                                         exit(1);
2897                                 }
2898                         }
2899                 }
2900                 
2901                 // display org. object upon failure
2902                 srcob->data = srcob->fluidsimSettings->orgMesh;
2903                 return;
2904         }
2905
2906         if((mesh)&&(mesh->totvert>0)) {
2907                 make_edges(mesh, 0);    // 0 = make all edges draw
2908         }
2909         srcob->fluidsimSettings->meshSurface = mesh;
2910         srcob->data = mesh;
2911         srcob->fluidsimSettings->meshSurfNormals = MEM_dupallocN(mesh->mvert);
2912
2913         // load vertex velocities, if they exist...
2914         // TODO? use generate flag as loading flag as well?
2915         // warning, needs original .bobj.gz mesh loading filename
2916         if(displaymode==3) {
2917                 readVelgz(targetFile, srcob);
2918         } else {
2919                 // no data for preview, only clear...
2920                 int i,j;
2921                 for(i=0; i<mesh->totvert;i++) { for(j=0; j<3; j++) { srcob->fluidsimSettings->meshSurfNormals[i].co[j] = 0.; }} 
2922         }
2923
2924         //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]);
2925         return;
2926 }
2927
2928 /* helper function */
2929 /* init axis aligned BB for mesh object */
2930 void fluidsimGetAxisAlignedBB(struct Mesh *mesh, float obmat[][4],
2931                  /*RET*/ float start[3], /*RET*/ float size[3], /*RET*/ struct Mesh **bbmesh )
2932 {
2933         float bbsx=0.0, bbsy=0.0, bbsz=0.0;
2934         float bbex=1.0, bbey=1.0, bbez=1.0;
2935         int i;
2936         float vec[3];
2937
2938         VECCOPY(vec, mesh->mvert[0].co); 
2939         Mat4MulVecfl(obmat, vec);
2940         bbsx = vec[0]; bbsy = vec[1]; bbsz = vec[2];
2941         bbex = vec[0]; bbey = vec[1]; bbez = vec[2];
2942
2943         for(i=1; i<mesh->totvert;i++) {
2944                 VECCOPY(vec, mesh->mvert[i].co);
2945                 Mat4MulVecfl(obmat, vec);
2946
2947                 if(vec[0] < bbsx){ bbsx= vec[0]; }
2948                 if(vec[1] < bbsy){ bbsy= vec[1]; }
2949                 if(vec[2] < bbsz){ bbsz= vec[2]; }
2950                 if(vec[0] > bbex){ bbex= vec[0]; }
2951                 if(vec[1] > bbey){ bbey= vec[1]; }
2952                 if(vec[2] > bbez){ bbez= vec[2]; }
2953         }
2954
2955         // return values...
2956         if(start) {
2957                 start[0] = bbsx;
2958                 start[1] = bbsy;
2959                 start[2] = bbsz;
2960         } 
2961         if(size) {
2962                 size[0] = bbex-bbsx;
2963                 size[1] = bbey-bbsy;
2964                 size[2] = bbez-bbsz;
2965         }
2966
2967         // init bounding box mesh?
2968         if(bbmesh) {
2969                 int i,j;
2970                 Mesh *newmesh = NULL;
2971                 if(!(*bbmesh)) { newmesh = MEM_callocN(sizeof(Mesh), "fluidsimGetAxisAlignedBB_meshbb"); }
2972                 else {           newmesh = *bbmesh; }
2973
2974                 newmesh->totvert = 8;
2975                 if(!newmesh->mvert)
2976                         newmesh->mvert = CustomData_add_layer(&newmesh->vdata, CD_MVERT, CD_CALLOC, NULL, newmesh->totvert);
2977                 for(i=0; i<8; i++) {
2978                         for(j=0; j<3; j++) newmesh->mvert[i].co[j] = start[j]; 
2979                 }
2980
2981                 newmesh->totface = 6;
2982                 if(!newmesh->mface)
2983                         newmesh->mface = CustomData_add_layer(&newmesh->fdata, CD_MFACE, CD_CALLOC, NULL, newmesh->totface);
2984
2985                 *bbmesh = newmesh;
2986         }
2987 }
2988
2989 #else // DISABLE_ELBEEM
2990
2991 /* dummy for mesh_calc_modifiers */
2992 void loadFluidsimMesh(Object *srcob, int useRenderParams) {
2993 }
2994
2995 #endif // DISABLE_ELBEEM
2996