soc-2008-mxcurioni: merged changes to revision 15441
[blender.git] / source / blender / blenkernel / intern / cdderivedmesh.c
1 /*
2 * $Id$
3 *
4 * ***** BEGIN GPL 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.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software  Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19 *
20 * The Original Code is Copyright (C) 2006 Blender Foundation.
21 * All rights reserved.
22 *
23 * The Original Code is: all of this file.
24 *
25 * Contributor(s): Ben Batt <benbatt@gmail.com>
26 *
27 * ***** END GPL LICENSE BLOCK *****
28 *
29 * Implementation of CDDerivedMesh.
30 *
31 * BKE_cdderivedmesh.h contains the function prototypes for this file.
32 *
33 */ 
34
35 /* TODO maybe BIF_gl.h should include string.h? */
36 #include <string.h>
37 #include "BIF_gl.h"
38
39 #include "BKE_cdderivedmesh.h"
40 #include "BKE_customdata.h"
41 #include "BKE_DerivedMesh.h"
42 #include "BKE_displist.h"
43 #include "BKE_global.h"
44 #include "BKE_mesh.h"
45 #include "BKE_utildefines.h"
46
47 #include "BLI_arithb.h"
48 #include "BLI_blenlib.h"
49 #include "BLI_edgehash.h"
50 #include "BLI_editVert.h"
51 #include "BLI_ghash.h"
52
53 #include "DNA_mesh_types.h"
54 #include "DNA_meshdata_types.h"
55 #include "DNA_object_fluidsim.h"
56 #include "DNA_object_types.h"
57 #include "DNA_scene_types.h"
58
59 #include "MEM_guardedalloc.h"
60
61 #include <string.h>
62 #include <limits.h>
63
64 typedef struct {
65         DerivedMesh dm;
66
67         /* these point to data in the DerivedMesh custom data layers,
68            they are only here for efficiency and convenience **/
69         MVert *mvert;
70         MEdge *medge;
71         MFace *mface;
72 } CDDerivedMesh;
73
74 /**************** DerivedMesh interface functions ****************/
75 static int cdDM_getNumVerts(DerivedMesh *dm)
76 {
77         return dm->numVertData;
78 }
79
80 static int cdDM_getNumEdges(DerivedMesh *dm)
81 {
82         return dm->numEdgeData;
83 }
84
85 static int cdDM_getNumFaces(DerivedMesh *dm)
86 {
87         return dm->numFaceData;
88 }
89
90 static void cdDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
91 {
92         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
93         *vert_r = cddm->mvert[index];
94 }
95
96 static void cdDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
97 {
98         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
99         *edge_r = cddm->medge[index];
100 }
101
102 static void cdDM_getFace(DerivedMesh *dm, int index, MFace *face_r)
103 {
104         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
105         *face_r = cddm->mface[index];
106 }
107
108 static void cdDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
109 {
110         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
111         memcpy(vert_r, cddm->mvert, sizeof(*vert_r) * dm->numVertData);
112 }
113
114 static void cdDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
115 {
116         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
117         memcpy(edge_r, cddm->medge, sizeof(*edge_r) * dm->numEdgeData);
118 }
119
120 void cdDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
121 {
122         CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
123         memcpy(face_r, cddm->mface, sizeof(*face_r) * dm->numFaceData);
124 }
125
126 static void cdDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
127 {
128         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
129         int i;
130
131         if (dm->numVertData) {
132                 for (i=0; i<dm->numVertData; i++) {
133                         DO_MINMAX(cddm->mvert[i].co, min_r, max_r);
134                 }
135         } else {
136                 min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
137         }
138 }
139
140 static void cdDM_getVertCo(DerivedMesh *dm, int index, float co_r[3])
141 {
142         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
143
144         VECCOPY(co_r, cddm->mvert[index].co);
145 }
146
147 static void cdDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
148 {
149         MVert *mv = CDDM_get_verts(dm);
150         int i;
151
152         for(i = 0; i < dm->numVertData; i++, mv++)
153                 VECCOPY(cos_r[i], mv->co);
154 }
155
156 static void cdDM_getVertNo(DerivedMesh *dm, int index, float no_r[3])
157 {
158         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
159         short *no = cddm->mvert[index].no;
160
161         no_r[0] = no[0]/32767.f;
162         no_r[1] = no[1]/32767.f;
163         no_r[2] = no[2]/32767.f;
164 }
165
166 static void cdDM_drawVerts(DerivedMesh *dm)
167 {
168         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
169         MVert *mv = cddm->mvert;
170         int i;
171
172         glBegin(GL_POINTS);
173         for(i = 0; i < dm->numVertData; i++, mv++)
174                 glVertex3fv(mv->co);
175         glEnd();
176 }
177
178 static void cdDM_drawUVEdges(DerivedMesh *dm)
179 {
180         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
181         MFace *mf = cddm->mface;
182         MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
183         int i;
184
185         if(mf) {
186                 glBegin(GL_LINES);
187                 for(i = 0; i < dm->numFaceData; i++, mf++, tf++) {
188                         if(!(mf->flag&ME_HIDE)) {
189                                 glVertex2fv(tf->uv[0]);
190                                 glVertex2fv(tf->uv[1]);
191
192                                 glVertex2fv(tf->uv[1]);
193                                 glVertex2fv(tf->uv[2]);
194
195                                 if(!mf->v4) {
196                                         glVertex2fv(tf->uv[2]);
197                                         glVertex2fv(tf->uv[0]);
198                                 } else {
199                                         glVertex2fv(tf->uv[2]);
200                                         glVertex2fv(tf->uv[3]);
201
202                                         glVertex2fv(tf->uv[3]);
203                                         glVertex2fv(tf->uv[0]);
204                                 }
205                         }
206                 }
207                 glEnd();
208         }
209 }
210
211 static void cdDM_drawEdges(DerivedMesh *dm, int drawLooseEdges)
212 {
213         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
214         MVert *mvert = cddm->mvert;
215         MEdge *medge = cddm->medge;
216         int i;
217                 
218         glBegin(GL_LINES);
219         for(i = 0; i < dm->numEdgeData; i++, medge++) {
220                 if((medge->flag&ME_EDGEDRAW)
221                    && (drawLooseEdges || !(medge->flag&ME_LOOSEEDGE))) {
222                         glVertex3fv(mvert[medge->v1].co);
223                         glVertex3fv(mvert[medge->v2].co);
224                 }
225         }
226         glEnd();
227 }
228
229 static void cdDM_drawLooseEdges(DerivedMesh *dm)
230 {
231         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
232         MVert *mvert = cddm->mvert;
233         MEdge *medge = cddm->medge;
234         int i;
235
236         glBegin(GL_LINES);
237         for(i = 0; i < dm->numEdgeData; i++, medge++) {
238                 if(medge->flag&ME_LOOSEEDGE) {
239                         glVertex3fv(mvert[medge->v1].co);
240                         glVertex3fv(mvert[medge->v2].co);
241                 }
242         }
243         glEnd();
244 }
245
246 static void cdDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int))
247 {
248         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
249         MVert *mvert = cddm->mvert;
250         MFace *mface = cddm->mface;
251         float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
252         int a, glmode = -1, shademodel = -1, matnr = -1, drawCurrentMat = 1;
253
254 #define PASSVERT(index) {                                               \
255         if(shademodel == GL_SMOOTH) {                           \
256                 short *no = mvert[index].no;                    \
257                 glNormal3sv(no);                                                \
258         }                                                                                       \
259         glVertex3fv(mvert[index].co);   \
260 }
261
262         glBegin(glmode = GL_QUADS);
263         for(a = 0; a < dm->numFaceData; a++, mface++) {
264                 int new_glmode, new_matnr, new_shademodel;
265
266                 new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
267                 new_matnr = mface->mat_nr + 1;
268                 new_shademodel = (mface->flag & ME_SMOOTH)?GL_SMOOTH:GL_FLAT;
269                 
270                 if(new_glmode != glmode || new_matnr != matnr
271                    || new_shademodel != shademodel) {
272                         glEnd();
273
274                         drawCurrentMat = setMaterial(matnr = new_matnr);
275
276                         glShadeModel(shademodel = new_shademodel);
277                         glBegin(glmode = new_glmode);
278                 } 
279                 
280                 if(drawCurrentMat) {
281                         if(shademodel == GL_FLAT) {
282                                 if (nors) {
283                                         glNormal3fv(nors);
284                                 }
285                                 else {
286                                         /* TODO make this better (cache facenormals as layer?) */
287                                         float nor[3];
288                                         if(mface->v4) {
289                                                 CalcNormFloat4(mvert[mface->v1].co, mvert[mface->v2].co,
290                                                                            mvert[mface->v3].co, mvert[mface->v4].co,
291                                                                            nor);
292                                         } else {
293                                                 CalcNormFloat(mvert[mface->v1].co, mvert[mface->v2].co,
294                                                                           mvert[mface->v3].co, nor);
295                                         }
296                                         glNormal3fv(nor);
297                                 }
298                         }
299
300                         PASSVERT(mface->v1);
301                         PASSVERT(mface->v2);
302                         PASSVERT(mface->v3);
303                         if(mface->v4) {
304                                 PASSVERT(mface->v4);
305                         }
306                 }
307
308                 if(nors) nors += 3;
309         }
310         glEnd();
311
312         glShadeModel(GL_FLAT);
313 #undef PASSVERT
314 }
315
316 static void cdDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2)
317 {
318         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
319         int a, glmode;
320         unsigned char *cp1, *cp2;
321         MVert *mvert = cddm->mvert;
322         MFace *mface = cddm->mface;
323
324         cp1 = col1;
325         if(col2) {
326                 cp2 = col2;
327         } else {
328                 cp2 = NULL;
329                 useTwoSided = 0;
330         }
331
332         /* there's a conflict here... twosided colors versus culling...? */
333         /* defined by history, only texture faces have culling option */
334         /* we need that as mesh option builtin, next to double sided lighting */
335         if(col1 && col2)
336                 glEnable(GL_CULL_FACE);
337         
338         glShadeModel(GL_SMOOTH);
339         glBegin(glmode = GL_QUADS);
340         for(a = 0; a < dm->numFaceData; a++, mface++, cp1 += 16) {
341                 int new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
342
343                 if(new_glmode != glmode) {
344                         glEnd();
345                         glBegin(glmode = new_glmode);
346                 }
347                         
348                 glColor3ub(cp1[0], cp1[1], cp1[2]);
349                 glVertex3fv(mvert[mface->v1].co);
350                 glColor3ub(cp1[4], cp1[5], cp1[6]);
351                 glVertex3fv(mvert[mface->v2].co);
352                 glColor3ub(cp1[8], cp1[9], cp1[10]);
353                 glVertex3fv(mvert[mface->v3].co);
354                 if(mface->v4) {
355                         glColor3ub(cp1[12], cp1[13], cp1[14]);
356                         glVertex3fv(mvert[mface->v4].co);
357                 }
358                         
359                 if(useTwoSided) {
360                         glColor3ub(cp2[8], cp2[9], cp2[10]);
361                         glVertex3fv(mvert[mface->v3].co );
362                         glColor3ub(cp2[4], cp2[5], cp2[6]);
363                         glVertex3fv(mvert[mface->v2].co );
364                         glColor3ub(cp2[0], cp2[1], cp2[2]);
365                         glVertex3fv(mvert[mface->v1].co );
366                         if(mface->v4) {
367                                 glColor3ub(cp2[12], cp2[13], cp2[14]);
368                                 glVertex3fv(mvert[mface->v4].co );
369                         }
370                 }
371                 if(col2) cp2 += 16;
372         }
373         glEnd();
374
375         glShadeModel(GL_FLAT);
376         glDisable(GL_CULL_FACE);
377 }
378
379 static void cdDM_drawFacesTex_common(DerivedMesh *dm,
380                int (*drawParams)(MTFace *tface, MCol *mcol, int matnr),
381                int (*drawParamsMapped)(void *userData, int index),
382                void *userData) 
383 {
384         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
385         MVert *mv = cddm->mvert;
386         MFace *mf = cddm->mface;
387         MCol *mcol = dm->getFaceDataArray(dm, CD_MCOL);
388         float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
389         MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
390         int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
391
392         for(i = 0; i < dm->numFaceData; i++, mf++) {
393                 MVert *mvert;
394                 int flag;
395                 unsigned char *cp = NULL;
396
397                 if(drawParams) {
398                         flag = drawParams(tf? &tf[i]: NULL, mcol? &mcol[i*4]: NULL, mf->mat_nr);
399                 }
400                 else {
401                         if(index) {
402                                 orig = *index++;
403                                 if(orig == ORIGINDEX_NONE)              { if(nors) nors += 3; continue; }
404                                 if(drawParamsMapped) flag = drawParamsMapped(userData, orig);
405                                 else    { if(nors) nors += 3; continue; }
406                         }
407                         else
408                                 if(drawParamsMapped) flag = drawParamsMapped(userData, i);
409                                 else    { if(nors) nors += 3; continue; }
410                 }
411                 
412                 if(flag != 0) { /* if the flag is 0 it means the face is hidden or invisible */
413                         if (flag==1 && mcol)
414                                 cp= (unsigned char*) &mcol[i*4];
415
416                         if(!(mf->flag&ME_SMOOTH)) {
417                                 if (nors) {
418                                         glNormal3fv(nors);
419                                 }
420                                 else {
421                                         /* TODO make this better (cache facenormals as layer?) */
422                                         float nor[3];
423                                         if(mf->v4) {
424                                                 CalcNormFloat4(mv[mf->v1].co, mv[mf->v2].co,
425                                                                            mv[mf->v3].co, mv[mf->v4].co,
426                                                                            nor);
427                                         } else {
428                                                 CalcNormFloat(mv[mf->v1].co, mv[mf->v2].co,
429                                                                           mv[mf->v3].co, nor);
430                                         }
431                                         glNormal3fv(nor);
432                                 }
433                         }
434
435                         glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
436                         if(tf) glTexCoord2fv(tf[i].uv[0]);
437                         if(cp) glColor3ub(cp[3], cp[2], cp[1]);
438                         mvert = &mv[mf->v1];
439                         if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
440                         glVertex3fv(mvert->co);
441                                 
442                         if(tf) glTexCoord2fv(tf[i].uv[1]);
443                         if(cp) glColor3ub(cp[7], cp[6], cp[5]);
444                         mvert = &mv[mf->v2];
445                         if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
446                         glVertex3fv(mvert->co);
447
448                         if(tf) glTexCoord2fv(tf[i].uv[2]);
449                         if(cp) glColor3ub(cp[11], cp[10], cp[9]);
450                         mvert = &mv[mf->v3];
451                         if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
452                         glVertex3fv(mvert->co);
453
454                         if(mf->v4) {
455                                 if(tf) glTexCoord2fv(tf[i].uv[3]);
456                                 if(cp) glColor3ub(cp[15], cp[14], cp[13]);
457                                 mvert = &mv[mf->v4];
458                                 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
459                                 glVertex3fv(mvert->co);
460                         }
461                         glEnd();
462                 }
463                 
464                 if(nors) nors += 3;
465         }
466 }
467
468 static void cdDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, MCol *mcol, int matnr))
469 {
470         cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
471 }
472
473 static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors)
474 {
475         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
476         MVert *mv = cddm->mvert;
477         MFace *mf = cddm->mface;
478         MCol *mc = DM_get_face_data_layer(dm, CD_MCOL);
479         float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
480         int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
481
482         for(i = 0; i < dm->numFaceData; i++, mf++) {
483                 int drawSmooth = (mf->flag & ME_SMOOTH);
484
485                 if(index) {
486                         orig = *index++;
487                         if(setDrawOptions && orig == ORIGINDEX_NONE)
488                                 { if(nors) nors += 3; continue; }
489                 }
490                 else
491                         orig = i;
492
493                 if(!setDrawOptions || setDrawOptions(userData, orig, &drawSmooth)) {
494                         unsigned char *cp = NULL;
495
496                         if(useColors && mc)
497                                 cp = (unsigned char *)&mc[i * 4];
498
499                         glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
500                         glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
501
502                         if (!drawSmooth) {
503                                 if (nors) {
504                                         glNormal3fv(nors);
505                                 }
506                                 else {
507                                         /* TODO make this better (cache facenormals as layer?) */
508                                         float nor[3];
509                                         if(mf->v4) {
510                                                 CalcNormFloat4(mv[mf->v1].co, mv[mf->v2].co,
511                                                                            mv[mf->v3].co, mv[mf->v4].co,
512                                                                            nor);
513                                         } else {
514                                                 CalcNormFloat(mv[mf->v1].co, mv[mf->v2].co,
515                                                                           mv[mf->v3].co, nor);
516                                         }
517                                         glNormal3fv(nor);
518                                 }
519
520                                 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
521                                 glVertex3fv(mv[mf->v1].co);
522                                 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
523                                 glVertex3fv(mv[mf->v2].co);
524                                 if(cp) glColor3ub(cp[11], cp[10], cp[9]);
525                                 glVertex3fv(mv[mf->v3].co);
526                                 if(mf->v4) {
527                                         if(cp) glColor3ub(cp[15], cp[14], cp[13]);
528                                         glVertex3fv(mv[mf->v4].co);
529                                 }
530                         } else {
531                                 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
532                                 glNormal3sv(mv[mf->v1].no);
533                                 glVertex3fv(mv[mf->v1].co);
534                                 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
535                                 glNormal3sv(mv[mf->v2].no);
536                                 glVertex3fv(mv[mf->v2].co);
537                                 if(cp) glColor3ub(cp[11], cp[10], cp[9]);
538                                 glNormal3sv(mv[mf->v3].no);
539                                 glVertex3fv(mv[mf->v3].co);
540                                 if(mf->v4) {
541                                         if(cp) glColor3ub(cp[15], cp[14], cp[13]);
542                                         glNormal3sv(mv[mf->v4].no);
543                                         glVertex3fv(mv[mf->v4].co);
544                                 }
545                         }
546
547                         glEnd();
548                 }
549                 
550                 if (nors) nors += 3;
551         }
552 }
553
554 static void cdDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
555 {
556         cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
557 }
558
559 static void cdDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
560 {
561         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
562         MVert *vert = cddm->mvert;
563         MEdge *edge = cddm->medge;
564         int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
565
566         glBegin(GL_LINES);
567         for(i = 0; i < dm->numEdgeData; i++, edge++) {
568                 if(index) {
569                         orig = *index++;
570                         if(setDrawOptions && orig == ORIGINDEX_NONE) continue;
571                 }
572                 else
573                         orig = i;
574
575                 if(!setDrawOptions || setDrawOptions(userData, orig)) {
576                         glVertex3fv(vert[edge->v1].co);
577                         glVertex3fv(vert[edge->v2].co);
578                 }
579         }
580         glEnd();
581 }
582
583 static void cdDM_foreachMappedVert(
584                            DerivedMesh *dm,
585                            void (*func)(void *userData, int index, float *co,
586                                         float *no_f, short *no_s),
587                            void *userData)
588 {
589         MVert *mv = CDDM_get_verts(dm);
590         int i, orig, *index = DM_get_vert_data_layer(dm, CD_ORIGINDEX);
591
592         for(i = 0; i < dm->numVertData; i++, mv++) {
593                 if(index) {
594                         orig = *index++;
595                         if(orig == ORIGINDEX_NONE) continue;
596                         func(userData, orig, mv->co, NULL, mv->no);
597                 }
598                 else
599                         func(userData, i, mv->co, NULL, mv->no);
600         }
601 }
602
603 static void cdDM_foreachMappedEdge(
604                            DerivedMesh *dm,
605                            void (*func)(void *userData, int index,
606                                         float *v0co, float *v1co),
607                            void *userData)
608 {
609         CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
610         MVert *mv = cddm->mvert;
611         MEdge *med = cddm->medge;
612         int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
613
614         for(i = 0; i < dm->numEdgeData; i++, med++) {
615                 if (index) {
616                         orig = *index++;
617                         if(orig == ORIGINDEX_NONE) continue;
618                         func(userData, orig, mv[med->v1].co, mv[med->v2].co);
619                 }
620                 else
621                         func(userData, i, mv[med->v1].co, mv[med->v2].co);
622         }
623 }
624
625 static void cdDM_foreachMappedFaceCenter(
626                            DerivedMesh *dm,
627                            void (*func)(void *userData, int index,
628                                         float *cent, float *no),
629                            void *userData)
630 {
631         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
632         MVert *mv = cddm->mvert;
633         MFace *mf = cddm->mface;
634         int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
635
636         for(i = 0; i < dm->numFaceData; i++, mf++) {
637                 float cent[3];
638                 float no[3];
639
640                 if (index) {
641                         orig = *index++;
642                         if(orig == ORIGINDEX_NONE) continue;
643                 }
644                 else
645                         orig = i;
646
647                 VECCOPY(cent, mv[mf->v1].co);
648                 VecAddf(cent, cent, mv[mf->v2].co);
649                 VecAddf(cent, cent, mv[mf->v3].co);
650
651                 if (mf->v4) {
652                         CalcNormFloat4(mv[mf->v1].co, mv[mf->v2].co,
653                                        mv[mf->v3].co, mv[mf->v4].co, no);
654                         VecAddf(cent, cent, mv[mf->v4].co);
655                         VecMulf(cent, 0.25f);
656                 } else {
657                         CalcNormFloat(mv[mf->v1].co, mv[mf->v2].co,
658                                       mv[mf->v3].co, no);
659                         VecMulf(cent, 0.33333333333f);
660                 }
661
662                 func(userData, orig, cent, no);
663         }
664 }
665
666 static void cdDM_release(DerivedMesh *dm)
667 {
668         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
669
670         if (DM_release(dm))
671                 MEM_freeN(cddm);
672 }
673
674 /**************** CDDM interface functions ****************/
675 static CDDerivedMesh *cdDM_create(const char *desc)
676 {
677         CDDerivedMesh *cddm;
678         DerivedMesh *dm;
679
680         cddm = MEM_callocN(sizeof(*cddm), desc);
681         dm = &cddm->dm;
682
683         dm->getMinMax = cdDM_getMinMax;
684
685         dm->getNumVerts = cdDM_getNumVerts;
686         dm->getNumFaces = cdDM_getNumFaces;
687         dm->getNumEdges = cdDM_getNumEdges;
688
689         dm->getVert = cdDM_getVert;
690         dm->getEdge = cdDM_getEdge;
691         dm->getFace = cdDM_getFace;
692         dm->copyVertArray = cdDM_copyVertArray;
693         dm->copyEdgeArray = cdDM_copyEdgeArray;
694         dm->copyFaceArray = cdDM_copyFaceArray;
695         dm->getVertData = DM_get_vert_data;
696         dm->getEdgeData = DM_get_edge_data;
697         dm->getFaceData = DM_get_face_data;
698         dm->getVertDataArray = DM_get_vert_data_layer;
699         dm->getEdgeDataArray = DM_get_edge_data_layer;
700         dm->getFaceDataArray = DM_get_face_data_layer;
701
702         dm->getVertCos = cdDM_getVertCos;
703         dm->getVertCo = cdDM_getVertCo;
704         dm->getVertNo = cdDM_getVertNo;
705
706         dm->drawVerts = cdDM_drawVerts;
707
708         dm->drawUVEdges = cdDM_drawUVEdges;
709         dm->drawEdges = cdDM_drawEdges;
710         dm->drawLooseEdges = cdDM_drawLooseEdges;
711         dm->drawMappedEdges = cdDM_drawMappedEdges;
712
713         dm->drawFacesSolid = cdDM_drawFacesSolid;
714         dm->drawFacesColored = cdDM_drawFacesColored;
715         dm->drawFacesTex = cdDM_drawFacesTex;
716         dm->drawMappedFaces = cdDM_drawMappedFaces;
717         dm->drawMappedFacesTex = cdDM_drawMappedFacesTex;
718
719         dm->foreachMappedVert = cdDM_foreachMappedVert;
720         dm->foreachMappedEdge = cdDM_foreachMappedEdge;
721         dm->foreachMappedFaceCenter = cdDM_foreachMappedFaceCenter;
722
723         dm->release = cdDM_release;
724
725         return cddm;
726 }
727
728 DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces)
729 {
730         CDDerivedMesh *cddm = cdDM_create("CDDM_new dm");
731         DerivedMesh *dm = &cddm->dm;
732
733         DM_init(dm, numVerts, numEdges, numFaces);
734
735         CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
736         CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
737         CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
738
739         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
740         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
741         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
742
743         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
744         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
745         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
746
747         return dm;
748 }
749
750 DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *ob)
751 {
752         CDDerivedMesh *cddm = cdDM_create("CDDM_from_mesh dm");
753         DerivedMesh *dm = &cddm->dm;
754         int i, *index, alloctype;
755
756         /* this does a referenced copy, the only new layers being ORIGINDEX,
757          * with an exception for fluidsim */
758
759         DM_init(dm, mesh->totvert, mesh->totedge, mesh->totface);
760
761         CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totvert);
762         CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totedge);
763         CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, mesh->totface);
764
765         dm->deformedOnly = 1;
766
767         if(ob && ob->fluidsimSettings && ob->fluidsimSettings->meshSurface)
768                 alloctype= CD_DUPLICATE;
769         else
770                 alloctype= CD_REFERENCE;
771
772         CustomData_merge(&mesh->vdata, &dm->vertData, CD_MASK_MESH, alloctype,
773                          mesh->totvert);
774         CustomData_merge(&mesh->edata, &dm->edgeData, CD_MASK_MESH, alloctype,
775                          mesh->totedge);
776         CustomData_merge(&mesh->fdata, &dm->faceData, CD_MASK_MESH, alloctype,
777                          mesh->totface);
778
779         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
780         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
781         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
782
783         index = CustomData_get_layer(&dm->vertData, CD_ORIGINDEX);
784         for(i = 0; i < mesh->totvert; ++i, ++index)
785                 *index = i;
786
787         index = CustomData_get_layer(&dm->edgeData, CD_ORIGINDEX);
788         for(i = 0; i < mesh->totedge; ++i, ++index)
789                 *index = i;
790
791         index = CustomData_get_layer(&dm->faceData, CD_ORIGINDEX);
792         for(i = 0; i < mesh->totface; ++i, ++index)
793                 *index = i;
794         
795         /* works in conjunction with hack during modifier calc, where active mcol
796            layer with weight paint colors is temporarily added */
797         if ((G.f & G_WEIGHTPAINT) &&
798                 (ob && ob==(G.scene->basact?G.scene->basact->object:NULL)))
799                 CustomData_duplicate_referenced_layer(&dm->faceData, CD_MCOL);
800
801         return dm;
802 }
803
804 DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *me)
805 {
806         DerivedMesh *dm = CDDM_new(BLI_countlist(&em->verts),
807                                    BLI_countlist(&em->edges),
808                                    BLI_countlist(&em->faces));
809         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
810         EditVert *eve;
811         EditEdge *eed;
812         EditFace *efa;
813         MVert *mvert = cddm->mvert;
814         MEdge *medge = cddm->medge;
815         MFace *mface = cddm->mface;
816         int i, *index;
817
818         dm->deformedOnly = 1;
819
820         CustomData_merge(&em->vdata, &dm->vertData, CD_MASK_DERIVEDMESH,
821                          CD_CALLOC, dm->numVertData);
822         /* CustomData_merge(&em->edata, &dm->edgeData, CD_MASK_DERIVEDMESH,
823                          CD_CALLOC, dm->numEdgeData); */
824         CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
825                          CD_CALLOC, dm->numFaceData);
826
827         /* set eve->hash to vert index */
828         for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i)
829                 eve->tmp.l = i;
830
831         /* Need to be able to mark loose edges */
832         for(eed = em->edges.first; eed; eed = eed->next) {
833                 eed->f2 = 0;
834         }
835         for(efa = em->faces.first; efa; efa = efa->next) {
836                 efa->e1->f2 = 1;
837                 efa->e2->f2 = 1;
838                 efa->e3->f2 = 1;
839                 if(efa->e4) efa->e4->f2 = 1;
840         }
841
842         index = dm->getVertDataArray(dm, CD_ORIGINDEX);
843         for(i = 0, eve = em->verts.first; i < dm->numVertData;
844             i++, eve = eve->next, index++) {
845                 MVert *mv = &mvert[i];
846
847                 VECCOPY(mv->co, eve->co);
848
849                 mv->no[0] = eve->no[0] * 32767.0;
850                 mv->no[1] = eve->no[1] * 32767.0;
851                 mv->no[2] = eve->no[2] * 32767.0;
852                 mv->bweight = (unsigned char) (eve->bweight * 255.0f);
853
854                 mv->mat_nr = 0;
855                 mv->flag = 0;
856
857                 *index = i;
858
859                 CustomData_from_em_block(&em->vdata, &dm->vertData, eve->data, i);
860         }
861
862         index = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
863         for(i = 0, eed = em->edges.first; i < dm->numEdgeData;
864             i++, eed = eed->next, index++) {
865                 MEdge *med = &medge[i];
866
867                 med->v1 = eed->v1->tmp.l;
868                 med->v2 = eed->v2->tmp.l;
869                 med->crease = (unsigned char) (eed->crease * 255.0f);
870                 med->bweight = (unsigned char) (eed->bweight * 255.0f);
871                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
872                 
873                 if(eed->seam) med->flag |= ME_SEAM;
874                 if(eed->sharp) med->flag |= ME_SHARP;
875                 if(!eed->f2) med->flag |= ME_LOOSEEDGE;
876
877                 *index = i;
878
879                 /* CustomData_from_em_block(&em->edata, &dm->edgeData, eed->data, i); */
880         }
881
882         index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
883         for(i = 0, efa = em->faces.first; i < dm->numFaceData;
884             i++, efa = efa->next, index++) {
885                 MFace *mf = &mface[i];
886
887                 mf->v1 = efa->v1->tmp.l;
888                 mf->v2 = efa->v2->tmp.l;
889                 mf->v3 = efa->v3->tmp.l;
890                 mf->v4 = efa->v4 ? efa->v4->tmp.l : 0;
891                 mf->mat_nr = efa->mat_nr;
892                 mf->flag = efa->flag;
893
894                 *index = i;
895
896                 CustomData_from_em_block(&em->fdata, &dm->faceData, efa->data, i);
897                 test_index_face(mf, &dm->faceData, i, efa->v4?4:3);
898         }
899
900         return dm;
901 }
902
903 DerivedMesh *CDDM_copy(DerivedMesh *source)
904 {
905         CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm");
906         DerivedMesh *dm = &cddm->dm;
907         int numVerts = source->numVertData;
908         int numEdges = source->numEdgeData;
909         int numFaces = source->numFaceData;
910
911         /* this initializes dm, and copies all non mvert/medge/mface layers */
912         DM_from_template(dm, source, numVerts, numEdges, numFaces);
913         dm->deformedOnly = source->deformedOnly;
914
915         CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts);
916         CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges);
917         CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numFaces);
918
919         /* now add mvert/medge/mface layers */
920         cddm->mvert = source->dupVertArray(source);
921         cddm->medge = source->dupEdgeArray(source);
922         cddm->mface = source->dupFaceArray(source);
923
924         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts);
925         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges);
926         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numFaces);
927
928         return dm;
929 }
930
931 DerivedMesh *CDDM_from_template(DerivedMesh *source,
932                                 int numVerts, int numEdges, int numFaces)
933 {
934         CDDerivedMesh *cddm = cdDM_create("CDDM_from_template dest");
935         DerivedMesh *dm = &cddm->dm;
936
937         /* this does a copy of all non mvert/medge/mface layers */
938         DM_from_template(dm, source, numVerts, numEdges, numFaces);
939
940         /* now add mvert/medge/mface layers */
941         CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
942         CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
943         CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
944
945         cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
946         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
947         cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
948
949         return dm;
950 }
951
952 void CDDM_apply_vert_coords(DerivedMesh *dm, float (*vertCoords)[3])
953 {
954         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
955         MVert *vert;
956         int i;
957
958         /* this will just return the pointer if it wasn't a referenced layer */
959         vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
960         cddm->mvert = vert;
961
962         for(i = 0; i < dm->numVertData; ++i, ++vert)
963                 VECCOPY(vert->co, vertCoords[i]);
964 }
965
966 void CDDM_apply_vert_normals(DerivedMesh *dm, short (*vertNormals)[3])
967 {
968         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
969         MVert *vert;
970         int i;
971
972         /* this will just return the pointer if it wasn't a referenced layer */
973         vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
974         cddm->mvert = vert;
975
976         for(i = 0; i < dm->numVertData; ++i, ++vert)
977                 VECCOPY(vert->no, vertNormals[i]);
978 }
979
980 /* adapted from mesh_calc_normals */
981 void CDDM_calc_normals(DerivedMesh *dm)
982 {
983         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
984         float (*temp_nors)[3];
985         float (*face_nors)[3];
986         int i;
987         int numVerts = dm->numVertData;
988         int numFaces = dm->numFaceData;
989         MFace *mf;
990         MVert *mv;
991
992         if(numVerts == 0) return;
993
994         temp_nors = MEM_callocN(numVerts * sizeof(*temp_nors),
995                                 "CDDM_calc_normals temp_nors");
996
997         /* we don't want to overwrite any referenced layers */
998         mv = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
999         cddm->mvert = mv;
1000
1001         /* make a face normal layer if not present */
1002         face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
1003         if(!face_nors)
1004                 face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC,
1005                                                  NULL, dm->numFaceData);
1006
1007         /* calculate face normals and add to vertex normals */
1008         mf = CDDM_get_faces(dm);
1009         for(i = 0; i < numFaces; i++, mf++) {
1010                 float *f_no = face_nors[i];
1011
1012                 if(mf->v4)
1013                         CalcNormFloat4(mv[mf->v1].co, mv[mf->v2].co,
1014                                        mv[mf->v3].co, mv[mf->v4].co, f_no);
1015                 else
1016                         CalcNormFloat(mv[mf->v1].co, mv[mf->v2].co,
1017                                       mv[mf->v3].co, f_no);
1018                 
1019                 VecAddf(temp_nors[mf->v1], temp_nors[mf->v1], f_no);
1020                 VecAddf(temp_nors[mf->v2], temp_nors[mf->v2], f_no);
1021                 VecAddf(temp_nors[mf->v3], temp_nors[mf->v3], f_no);
1022                 if(mf->v4)
1023                         VecAddf(temp_nors[mf->v4], temp_nors[mf->v4], f_no);
1024         }
1025
1026         /* normalize vertex normals and assign */
1027         for(i = 0; i < numVerts; i++, mv++) {
1028                 float *no = temp_nors[i];
1029                 
1030                 if (Normalize(no) == 0.0) {
1031                         VECCOPY(no, mv->co);
1032                         Normalize(no);
1033                 }
1034
1035                 mv->no[0] = (short)(no[0] * 32767.0);
1036                 mv->no[1] = (short)(no[1] * 32767.0);
1037                 mv->no[2] = (short)(no[2] * 32767.0);
1038         }
1039         
1040         MEM_freeN(temp_nors);
1041 }
1042
1043 void CDDM_calc_edges(DerivedMesh *dm)
1044 {
1045         CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1046         CustomData edgeData;
1047         EdgeHashIterator *ehi;
1048         MFace *mf = cddm->mface;
1049         MEdge *med;
1050         EdgeHash *eh = BLI_edgehash_new();
1051         int i, *index, numEdges, maxFaces = dm->numFaceData;
1052
1053         for (i = 0; i < maxFaces; i++, mf++) {
1054                 if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
1055                         BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
1056                 if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
1057                         BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);
1058                 
1059                 if (mf->v4) {
1060                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
1061                                 BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
1062                         if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
1063                                 BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
1064                 } else {
1065                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
1066                                 BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
1067                 }
1068         }
1069
1070         numEdges = BLI_edgehash_size(eh);
1071
1072         /* write new edges into a temporary CustomData */
1073         memset(&edgeData, 0, sizeof(edgeData));
1074         CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1075         CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1076
1077         ehi = BLI_edgehashIterator_new(eh);
1078         med = CustomData_get_layer(&edgeData, CD_MEDGE);
1079         index = CustomData_get_layer(&edgeData, CD_ORIGINDEX);
1080         for(i = 0; !BLI_edgehashIterator_isDone(ehi);
1081             BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) {
1082                 BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
1083
1084                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1085                 *index = ORIGINDEX_NONE;
1086         }
1087         BLI_edgehashIterator_free(ehi);
1088
1089         /* free old CustomData and assign new one */
1090         CustomData_free(&dm->edgeData, dm->numVertData);
1091         dm->edgeData = edgeData;
1092         dm->numEdgeData = numEdges;
1093
1094         cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1095
1096         BLI_edgehash_free(eh, NULL);
1097 }
1098
1099 void CDDM_lower_num_verts(DerivedMesh *dm, int numVerts)
1100 {
1101         if (numVerts < dm->numVertData)
1102                 CustomData_free_elem(&dm->vertData, numVerts, dm->numVertData-numVerts);
1103
1104         dm->numVertData = numVerts;
1105 }
1106
1107 void CDDM_lower_num_edges(DerivedMesh *dm, int numEdges)
1108 {
1109         if (numEdges < dm->numEdgeData)
1110                 CustomData_free_elem(&dm->edgeData, numEdges, dm->numEdgeData-numEdges);
1111
1112         dm->numEdgeData = numEdges;
1113 }
1114
1115 void CDDM_lower_num_faces(DerivedMesh *dm, int numFaces)
1116 {
1117         if (numFaces < dm->numFaceData)
1118                 CustomData_free_elem(&dm->faceData, numFaces, dm->numFaceData-numFaces);
1119
1120         dm->numFaceData = numFaces;
1121 }
1122
1123 MVert *CDDM_get_vert(DerivedMesh *dm, int index)
1124 {
1125         return &((CDDerivedMesh*)dm)->mvert[index];
1126 }
1127
1128 MEdge *CDDM_get_edge(DerivedMesh *dm, int index)
1129 {
1130         return &((CDDerivedMesh*)dm)->medge[index];
1131 }
1132
1133 MFace *CDDM_get_face(DerivedMesh *dm, int index)
1134 {
1135         return &((CDDerivedMesh*)dm)->mface[index];
1136 }
1137
1138 MVert *CDDM_get_verts(DerivedMesh *dm)
1139 {
1140         return ((CDDerivedMesh*)dm)->mvert;
1141 }
1142
1143 MEdge *CDDM_get_edges(DerivedMesh *dm)
1144 {
1145         return ((CDDerivedMesh*)dm)->medge;
1146 }
1147
1148 MFace *CDDM_get_faces(DerivedMesh *dm)
1149 {
1150         return ((CDDerivedMesh*)dm)->mface;
1151 }
1152