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