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