Fix for bug #5220: crash on edgeloop delete.
[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_mesh.h"
44 #include "BKE_utildefines.h"
45
46 #include "BLI_arithb.h"
47 #include "BLI_blenlib.h"
48 #include "BLI_edgehash.h"
49 #include "BLI_editVert.h"
50 #include "BLI_ghash.h"
51
52 #include "DNA_mesh_types.h"
53 #include "DNA_meshdata_types.h"
54
55 #include "MEM_guardedalloc.h"
56
57 #include <string.h>
58 #include <limits.h>
59
60
61 /**************** DerivedMesh interface functions ****************/
62 static int cdDM_getNumVerts(DerivedMesh *dm)
63 {
64         return dm->vertData.numElems;
65 }
66
67 static int cdDM_getNumFaces(DerivedMesh *dm)
68 {
69         return dm->faceData.numElems;
70 }
71
72 static int cdDM_getNumEdges(DerivedMesh *dm)
73 {
74         return dm->edgeData.numElems;
75 }
76
77 static void cdDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
78 {
79         *vert_r = *CDDM_get_vert(dm, index);
80 }
81
82 static void cdDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
83 {
84         *edge_r = *CDDM_get_edge(dm, index);
85 }
86
87 static void cdDM_getFace(DerivedMesh *dm, int index, MFace *face_r)
88 {
89         *face_r = *CDDM_get_face(dm, index);
90 }
91
92 static void cdDM_getVertArray(DerivedMesh *dm, MVert *vert_r)
93 {
94         memcpy(vert_r, CDDM_get_verts(dm), sizeof(*vert_r) * dm->getNumVerts(dm));
95 }
96
97 static void cdDM_getEdgeArray(DerivedMesh *dm, MEdge *edge_r)
98 {
99         memcpy(edge_r, CDDM_get_edges(dm), sizeof(*edge_r) * dm->getNumEdges(dm));
100 }
101
102 static void cdDM_getFaceArray(DerivedMesh *dm, MFace *face_r)
103 {
104         memcpy(face_r, CDDM_get_faces(dm), sizeof(*face_r) * dm->getNumFaces(dm));
105 }
106
107 static void cdDM_foreachMappedVert(
108                            DerivedMesh *dm,
109                            void (*func)(void *userData, int index, float *co,
110                                         float *no_f, short *no_s),
111                            void *userData)
112 {
113         int i;
114         int maxVerts = dm->getNumVerts(dm);
115         MVert *mv = CDDM_get_verts(dm);
116         int *index = DM_get_vert_data_layer(dm, LAYERTYPE_ORIGINDEX);
117
118         for(i = 0; i < maxVerts; i++, mv++, index++) {
119                 if(*index == ORIGINDEX_NONE) continue;
120
121                 func(userData, *index, mv->co, NULL, mv->no);
122         }
123 }
124
125 static void cdDM_foreachMappedEdge(
126                            DerivedMesh *dm,
127                            void (*func)(void *userData, int index,
128                                         float *v0co, float *v1co),
129                            void *userData)
130 {
131         int i;
132         int maxEdges = dm->getNumEdges(dm);
133         MEdge *med = CDDM_get_edges(dm);
134         MVert *mv = CDDM_get_verts(dm);
135         int *index = DM_get_edge_data_layer(dm, LAYERTYPE_ORIGINDEX);
136
137         for(i = 0; i < maxEdges; i++, med++, index++) {
138                 if(*index == ORIGINDEX_NONE) continue;
139
140                 func(userData, *index, mv[med->v1].co, mv[med->v2].co);
141         }
142 }
143
144 static void cdDM_foreachMappedFaceCenter(
145                            DerivedMesh *dm,
146                            void (*func)(void *userData, int index,
147                                         float *cent, float *no),
148                            void *userData)
149 {
150         int i;
151         int maxFaces = dm->getNumFaces(dm);
152         MFace *mf = CDDM_get_faces(dm);
153         MVert *mv = CDDM_get_verts(dm);
154         int *index = DM_get_face_data_layer(dm, LAYERTYPE_ORIGINDEX);
155
156         for(i = 0; i < maxFaces; i++, mf++, index++) {
157                 float cent[3];
158                 float no[3];
159
160                 if(*index == ORIGINDEX_NONE) continue;
161
162                 VECCOPY(cent, mv[mf->v1].co);
163                 VecAddf(cent, cent, mv[mf->v2].co);
164                 VecAddf(cent, cent, mv[mf->v3].co);
165
166                 if (mf->v4) {
167                         CalcNormFloat4(mv[mf->v1].co, mv[mf->v2].co,
168                                        mv[mf->v3].co, mv[mf->v4].co, no);
169                         VecAddf(cent, cent, mv[mf->v4].co);
170                         VecMulf(cent, 0.25f);
171                 } else {
172                         CalcNormFloat(mv[mf->v1].co, mv[mf->v2].co,
173                                       mv[mf->v3].co, no);
174                         VecMulf(cent, 0.33333333333f);
175                 }
176
177                 func(userData, *index, cent, no);
178         }
179 }
180
181 static DispListMesh *cdDM_convertToDispListMesh(DerivedMesh *dm,
182                                                 int allowShared)
183 {
184         DispListMesh *dlm = MEM_callocN(sizeof(*dlm),
185                                         "cdDM_convertToDispListMesh dlm");
186
187         dlm->totvert = dm->vertData.numElems;
188         dlm->totedge = dm->edgeData.numElems;
189         dlm->totface = dm->faceData.numElems;
190         dlm->mvert = dm->dupVertArray(dm);
191         dlm->medge = dm->dupEdgeArray(dm);
192         dlm->mface = dm->dupFaceArray(dm);
193
194         dlm->tface = dm->getFaceDataArray(dm, LAYERTYPE_TFACE);
195         if(dlm->tface)
196                 dlm->tface = MEM_dupallocN(dlm->tface);
197
198         dlm->mcol = dm->getFaceDataArray(dm, LAYERTYPE_MCOL);
199         if(dlm->mcol)
200                 dlm->mcol = MEM_dupallocN(dlm->mcol);
201
202         dlm->nors = NULL;
203         dlm->dontFreeVerts = dlm->dontFreeOther = dlm->dontFreeNors = 0;
204
205         return dlm;
206 }
207
208 static void cdDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
209 {
210         int i;
211
212         for(i = 0; i < dm->vertData.numElems; i++) {
213                 DO_MINMAX(CDDM_get_vert(dm, i)->co, min_r, max_r);
214         }
215 }
216
217 static void cdDM_getVertCo(DerivedMesh *dm, int index, float co_r[3])
218 {
219         VECCOPY(co_r, CDDM_get_vert(dm, index)->co);
220 }
221
222 static void cdDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
223 {
224         int i;
225         MVert *mv = CDDM_get_verts(dm);
226
227         for(i = 0; i < dm->vertData.numElems; i++, mv++)
228                 VECCOPY(cos_r[i], mv->co);
229 }
230
231 static void cdDM_getVertNo(DerivedMesh *dm, int index, float no_r[3])
232 {
233         short *no = CDDM_get_vert(dm, index)->no;
234
235         no_r[0] = no[0] / 32767.f;
236         no_r[1] = no[1] / 32767.f;
237         no_r[2] = no[2] / 32767.f;
238 }
239
240 static void cdDM_drawVerts(DerivedMesh *dm)
241 {
242         int i;
243         MVert *mv = CDDM_get_verts(dm);
244
245         glBegin(GL_POINTS);
246         for(i = 0; i < dm->vertData.numElems; i++, mv++)
247                 glVertex3fv(mv->co);
248         glEnd();
249 }
250
251 static void cdDM_drawUVEdges(DerivedMesh *dm)
252 {
253         int i;
254         TFace *tf = DM_get_face_data_layer(dm, LAYERTYPE_TFACE);
255         MFace *mf = CDDM_get_faces(dm);
256
257         if(tf) {
258                 glBegin(GL_LINES);
259                 for(i = 0; i < dm->faceData.numElems; i++, tf++, mf++) {
260                         if(!(tf->flag&TF_HIDE)) {
261                                 glVertex2fv(tf->uv[0]);
262                                 glVertex2fv(tf->uv[1]);
263
264                                 glVertex2fv(tf->uv[1]);
265                                 glVertex2fv(tf->uv[2]);
266
267                                 if(!mf->v4) {
268                                         glVertex2fv(tf->uv[2]);
269                                         glVertex2fv(tf->uv[0]);
270                                 } else {
271                                         glVertex2fv(tf->uv[2]);
272                                         glVertex2fv(tf->uv[3]);
273
274                                         glVertex2fv(tf->uv[3]);
275                                         glVertex2fv(tf->uv[0]);
276                                 }
277                         }
278                 }
279                 glEnd();
280         }
281 }
282
283 static void cdDM_drawEdges(DerivedMesh *dm, int drawLooseEdges)
284 {
285         int i;
286         MEdge *medge = CDDM_get_edges(dm);
287         MVert *mvert = CDDM_get_verts(dm);
288                 
289         glBegin(GL_LINES);
290         for(i = 0; i < dm->edgeData.numElems; i++, medge++) {
291                 if((medge->flag&ME_EDGEDRAW)
292                    && (drawLooseEdges || !(medge->flag&ME_LOOSEEDGE))) {
293                         glVertex3fv(mvert[medge->v1].co);
294                         glVertex3fv(mvert[medge->v2].co);
295                 }
296         }
297         glEnd();
298 }
299
300 static void cdDM_drawLooseEdges(DerivedMesh *dm)
301 {
302         MEdge *medge = CDDM_get_edges(dm);
303         MVert *mvert = CDDM_get_verts(dm);
304         int i;
305
306         glBegin(GL_LINES);
307         for(i = 0; i < dm->edgeData.numElems; i++, medge++) {
308                 if(medge->flag&ME_LOOSEEDGE) {
309                         glVertex3fv(mvert[medge->v1].co);
310                         glVertex3fv(mvert[medge->v2].co);
311                 }
312         }
313         glEnd();
314 }
315
316 static void cdDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int))
317 {
318         int a;
319         int glmode = -1, shademodel = -1, matnr = -1, drawCurrentMat = 1;
320         MFace *mface = CDDM_get_faces(dm);
321         MVert *mvert = CDDM_get_verts(dm);
322
323 #define PASSVERT(index) {                                               \
324         if(shademodel == GL_SMOOTH) {                           \
325                 short *no = mvert[index].no;                    \
326                 glNormal3sv(no);                                                \
327         }                                                                                       \
328         glVertex3fv(mvert[index].co);   \
329 }
330
331         glBegin(glmode = GL_QUADS);
332         for(a = 0; a < dm->faceData.numElems; a++, mface++) {
333                 int new_glmode, new_matnr, new_shademodel;
334
335                 new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
336                 new_matnr = mface->mat_nr + 1;
337                 new_shademodel = (mface->flag & ME_SMOOTH)?GL_SMOOTH:GL_FLAT;
338                 
339                 if(new_glmode != glmode || new_matnr != matnr
340                    || new_shademodel != shademodel) {
341                         glEnd();
342
343                         drawCurrentMat = setMaterial(matnr = new_matnr);
344
345                         glShadeModel(shademodel = new_shademodel);
346                         glBegin(glmode = new_glmode);
347                 } 
348                 
349                 if(drawCurrentMat) {
350                         /* TODO make this better (cache facenormals as layer?) */
351                         if(shademodel == GL_FLAT) {
352                                 float nor[3];
353                                 if(mface->v4) {
354                                         CalcNormFloat4(mvert[mface->v1].co, mvert[mface->v2].co,
355                                                        mvert[mface->v3].co, mvert[mface->v4].co,
356                                                        nor);
357                                 } else {
358                                         CalcNormFloat(mvert[mface->v1].co, mvert[mface->v2].co,
359                                                       mvert[mface->v3].co, nor);
360                                 }
361                                 glNormal3fv(nor);
362                         }
363
364                         PASSVERT(mface->v1);
365                         PASSVERT(mface->v2);
366                         PASSVERT(mface->v3);
367                         if(mface->v4) {
368                                 PASSVERT(mface->v4);
369                         }
370                 }
371         }
372         glEnd();
373
374         glShadeModel(GL_FLAT);
375 #undef PASSVERT
376 }
377
378 static void cdDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2)
379 {
380         int a, glmode;
381         unsigned char *cp1, *cp2;
382         MFace *mface = CDDM_get_faces(dm);
383         MVert *mvert = CDDM_get_verts(dm);
384
385         cp1 = col1;
386         if(col2) {
387                 cp2 = col2;
388         } else {
389                 cp2 = NULL;
390                 useTwoSided = 0;
391         }
392
393         /* there's a conflict here... twosided colors versus culling...? */
394         /* defined by history, only texture faces have culling option */
395         /* we need that as mesh option builtin, next to double sided lighting */
396         if(col1 && col2)
397                 glEnable(GL_CULL_FACE);
398         
399         glShadeModel(GL_SMOOTH);
400         glBegin(glmode = GL_QUADS);
401         for(a = 0; a < dm->faceData.numElems; a++, mface++, cp1 += 16) {
402                 int new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
403
404                 if(new_glmode != glmode) {
405                         glEnd();
406                         glBegin(glmode = new_glmode);
407                 }
408                         
409                 glColor3ub(cp1[3], cp1[2], cp1[1]);
410                 glVertex3fv(mvert[mface->v1].co);
411                 glColor3ub(cp1[7], cp1[6], cp1[5]);
412                 glVertex3fv(mvert[mface->v2].co);
413                 glColor3ub(cp1[11], cp1[10], cp1[9]);
414                 glVertex3fv(mvert[mface->v3].co);
415                 if(mface->v4) {
416                         glColor3ub(cp1[15], cp1[14], cp1[13]);
417                         glVertex3fv(mvert[mface->v4].co);
418                 }
419                         
420                 if(useTwoSided) {
421                         glColor3ub(cp2[11], cp2[10], cp2[9]);
422                         glVertex3fv(mvert[mface->v3].co );
423                         glColor3ub(cp2[7], cp2[6], cp2[5]);
424                         glVertex3fv(mvert[mface->v2].co );
425                         glColor3ub(cp2[3], cp2[2], cp2[1]);
426                         glVertex3fv(mvert[mface->v1].co );
427                         if(mface->v4) {
428                                 glColor3ub(cp2[15], cp2[14], cp2[13]);
429                                 glVertex3fv(mvert[mface->v4].co );
430                         }
431                 }
432                 if(col2) cp2 += 16;
433         }
434         glEnd();
435
436         glShadeModel(GL_FLAT);
437         glDisable(GL_CULL_FACE);
438 }
439
440 static void cdDM_drawFacesTex_common(DerivedMesh *dm,
441                int (*drawParams)(TFace *tface, int matnr),
442                int (*drawParamsMapped)(void *userData, int index),
443                void *userData) 
444 {
445         int i;
446         MFace *mf = CDDM_get_faces(dm);
447         TFace *tf = DM_get_face_data_layer(dm, LAYERTYPE_TFACE);
448         MVert *mv = CDDM_get_verts(dm);
449         int *index = DM_get_face_data_layer(dm, LAYERTYPE_ORIGINDEX);
450
451         for(i = 0; i < dm->faceData.numElems; i++, mf++, index++) {
452                 MVert *mvert;
453                 int flag;
454                 unsigned char *cp = NULL;
455
456                 if(drawParams)
457                         if(tf) flag = drawParams(&tf[i], mf->mat_nr);
458                         else flag = drawParams(NULL, mf->mat_nr);
459                 else if(*index != ORIGINDEX_NONE)
460                         flag = drawParamsMapped(userData, *index);
461                 else
462                         flag = 0;
463
464                 if(flag == 0) {
465                         continue;
466                 } else if(flag == 1) {
467                         if(tf) {
468                                 cp = (unsigned char *)tf[i].col;
469                         } else {
470                                 cp = DM_get_face_data(dm, i, LAYERTYPE_MCOL);
471                         }
472                 }
473
474                 /* TODO make this better (cache facenormals as layer?) */
475                 if(!(mf->flag&ME_SMOOTH)) {
476                         float nor[3];
477                         if(mf->v4) {
478                                 CalcNormFloat4(mv[mf->v1].co, mv[mf->v2].co,
479                                                            mv[mf->v3].co, mv[mf->v4].co, nor);
480                         } else {
481                                 CalcNormFloat(mv[mf->v1].co, mv[mf->v2].co,
482                                                           mv[mf->v3].co, nor);
483                         }
484                         glNormal3fv(nor);
485                 }
486
487                 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
488                 if(tf) glTexCoord2fv(tf[i].uv[0]);
489                 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
490                 mvert = &mv[mf->v1];
491                 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
492                 glVertex3fv(mvert->co);
493                         
494                 if(tf) glTexCoord2fv(tf[i].uv[1]);
495                 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
496                 mvert = &mv[mf->v2];
497                 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
498                 glVertex3fv(mvert->co);
499
500                 if(tf) glTexCoord2fv(tf[i].uv[2]);
501                 if(cp) glColor3ub(cp[11], cp[10], cp[9]);
502                 mvert = &mv[mf->v3];
503                 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
504                 glVertex3fv(mvert->co);
505
506                 if(mf->v4) {
507                         if(tf) glTexCoord2fv(tf[i].uv[3]);
508                         if(cp) glColor3ub(cp[15], cp[14], cp[13]);
509                         mvert = &mv[mf->v4];
510                         if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
511                         glVertex3fv(mvert->co);
512                 }
513                 glEnd();
514         }
515 }
516
517 static void cdDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(TFace *tface, int matnr))
518 {
519         cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
520 }
521
522 static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors)
523 {
524         int i;
525         MFace *mf = CDDM_get_faces(dm);
526         MVert *mv = CDDM_get_verts(dm);
527         int *index = DM_get_face_data_layer(dm, LAYERTYPE_ORIGINDEX);
528         TFace *tf = DM_get_face_data_layer(dm, LAYERTYPE_TFACE);
529         MCol *mc = DM_get_face_data_layer(dm, LAYERTYPE_MCOL);
530
531         for(i = 0; i < dm->faceData.numElems; i++, mf++, index++) {
532                 int drawSmooth = (mf->flag & ME_SMOOTH);
533
534                 if(setDrawOptions && *index == ORIGINDEX_NONE) continue;
535
536                 if(!setDrawOptions || setDrawOptions(userData, *index, &drawSmooth)) {
537                         unsigned char *cp = NULL;
538
539                         if(useColors) {
540                                 if(tf) {
541                                         cp = (unsigned char *)tf[i].col;
542                                 } else if(mc) {
543                                         cp = (unsigned char *)&mc[i * 4];
544                                 }
545                         }
546
547                         glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
548                         glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
549
550                         if(!drawSmooth) {
551                                 /* TODO make this better (cache facenormals as layer?) */
552                                 float nor[3];
553                                 if(mf->v4) {
554                                         CalcNormFloat4(mv[mf->v1].co, mv[mf->v2].co,
555                                                                    mv[mf->v3].co, mv[mf->v4].co, nor);
556                                 } else {
557                                         CalcNormFloat(mv[mf->v1].co, mv[mf->v2].co,
558                                                                   mv[mf->v3].co, nor);
559                                 }
560                                 glNormal3fv(nor);
561
562                                 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
563                                 glVertex3fv(mv[mf->v1].co);
564                                 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
565                                 glVertex3fv(mv[mf->v2].co);
566                                 if(cp) glColor3ub(cp[11], cp[10], cp[9]);
567                                 glVertex3fv(mv[mf->v3].co);
568                                 if(mf->v4) {
569                                         if(cp) glColor3ub(cp[15], cp[14], cp[13]);
570                                         glVertex3fv(mv[mf->v4].co);
571                                 }
572                         } else {
573                                 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
574                                 glNormal3sv(mv[mf->v1].no);
575                                 glVertex3fv(mv[mf->v1].co);
576                                 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
577                                 glNormal3sv(mv[mf->v2].no);
578                                 glVertex3fv(mv[mf->v2].co);
579                                 if(cp) glColor3ub(cp[11], cp[10], cp[9]);
580                                 glNormal3sv(mv[mf->v3].no);
581                                 glVertex3fv(mv[mf->v3].co);
582                                 if(mf->v4) {
583                                         if(cp) glColor3ub(cp[15], cp[14], cp[13]);
584                                         glNormal3sv(mv[mf->v4].no);
585                                         glVertex3fv(mv[mf->v4].co);
586                                 }
587                         }
588
589                         glEnd();
590                 }
591         }
592 }
593
594 static void cdDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
595 {
596         cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
597 }
598
599 static void cdDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
600 {
601         int i;
602         int *index = DM_get_edge_data_layer(dm, LAYERTYPE_ORIGINDEX);
603         MEdge *edge = CDDM_get_edges(dm);
604         MVert *vert = CDDM_get_verts(dm);
605
606         glBegin(GL_LINES);
607         for(i = 0; i < dm->edgeData.numElems; i++, edge++, index++) {
608
609                 if(setDrawOptions && *index == ORIGINDEX_NONE) continue;
610
611                 if(!setDrawOptions || setDrawOptions(userData, *index)) {
612                         glVertex3fv(vert[edge->v1].co);
613                         glVertex3fv(vert[edge->v2].co);
614                 }
615         }
616         glEnd();
617 }
618
619 static void cdDM_release(DerivedMesh *dm)
620 {
621         CustomData_free(&dm->vertData);
622         CustomData_free(&dm->edgeData);
623         CustomData_free(&dm->faceData);
624
625         MEM_freeN(dm);
626 }
627
628
629 /**************** CDDM interface functions ****************/
630 static DerivedMesh *cdDM_create(const char *desc)
631 {
632         DerivedMesh *dm;
633
634         dm = MEM_callocN(sizeof(*dm), desc);
635
636         dm->getMinMax = cdDM_getMinMax;
637
638         dm->convertToDispListMesh = cdDM_convertToDispListMesh;
639
640         dm->getNumVerts = cdDM_getNumVerts;
641         dm->getNumFaces = cdDM_getNumFaces;
642         dm->getNumEdges = cdDM_getNumEdges;
643
644         dm->getVert = cdDM_getVert;
645         dm->getEdge = cdDM_getEdge;
646         dm->getFace = cdDM_getFace;
647         dm->getVertArray = cdDM_getVertArray;
648         dm->getEdgeArray = cdDM_getEdgeArray;
649         dm->getFaceArray = cdDM_getFaceArray;
650         dm->getVertData = DM_get_vert_data;
651         dm->getEdgeData = DM_get_edge_data;
652         dm->getFaceData = DM_get_face_data;
653         dm->getVertDataArray = DM_get_vert_data_layer;
654         dm->getEdgeDataArray = DM_get_edge_data_layer;
655         dm->getFaceDataArray = DM_get_face_data_layer;
656
657         dm->getVertCos = cdDM_getVertCos;
658         dm->getVertCo = cdDM_getVertCo;
659         dm->getVertNo = cdDM_getVertNo;
660
661         dm->drawVerts = cdDM_drawVerts;
662
663         dm->drawUVEdges = cdDM_drawUVEdges;
664         dm->drawEdges = cdDM_drawEdges;
665         dm->drawLooseEdges = cdDM_drawLooseEdges;
666         dm->drawMappedEdges = cdDM_drawMappedEdges;
667
668         dm->drawFacesSolid = cdDM_drawFacesSolid;
669         dm->drawFacesColored = cdDM_drawFacesColored;
670         dm->drawFacesTex = cdDM_drawFacesTex;
671         dm->drawMappedFaces = cdDM_drawMappedFaces;
672         dm->drawMappedFacesTex = cdDM_drawMappedFacesTex;
673
674         dm->foreachMappedVert = cdDM_foreachMappedVert;
675         dm->foreachMappedEdge = cdDM_foreachMappedEdge;
676         dm->foreachMappedFaceCenter = cdDM_foreachMappedFaceCenter;
677
678         dm->release = cdDM_release;
679
680         return dm;
681 }
682
683 DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces)
684 {
685         DerivedMesh *dm = cdDM_create("CDDM_new dm");
686         DM_init(dm, numVerts, numEdges, numFaces);
687
688         CustomData_add_layer(&dm->vertData, LAYERTYPE_MVERT, LAYERFLAG_NOCOPY,
689                              NULL);
690         CustomData_add_layer(&dm->edgeData, LAYERTYPE_MEDGE, LAYERFLAG_NOCOPY,
691                              NULL);
692         CustomData_add_layer(&dm->faceData, LAYERTYPE_MFACE, LAYERFLAG_NOCOPY,
693                              NULL);
694
695         return dm;
696 }
697
698 DerivedMesh *CDDM_from_mesh(Mesh *mesh)
699 {
700         DerivedMesh *dm = CDDM_new(mesh->totvert, mesh->totedge, mesh->totface);
701         int i;
702
703         if(mesh->msticky)
704                 CustomData_add_layer(&dm->vertData, LAYERTYPE_MSTICKY, 0, NULL);
705         if(mesh->dvert)
706                 CustomData_add_layer(&dm->vertData, LAYERTYPE_MDEFORMVERT, 0, NULL);
707
708         if(mesh->tface)
709                 CustomData_add_layer(&dm->faceData, LAYERTYPE_TFACE, 0, NULL);
710         if(mesh->mcol)
711                 CustomData_add_layer(&dm->faceData, LAYERTYPE_MCOL, 0, NULL);
712
713         for(i = 0; i < mesh->totvert; ++i) {
714                 DM_set_vert_data(dm, i, LAYERTYPE_MVERT, &mesh->mvert[i]);
715                 if(mesh->msticky)
716                         DM_set_vert_data(dm, i, LAYERTYPE_MSTICKY, &mesh->msticky[i]);
717                 if(mesh->dvert)
718                         DM_set_vert_data(dm, i, LAYERTYPE_MDEFORMVERT, &mesh->dvert[i]);
719
720                 DM_set_vert_data(dm, i, LAYERTYPE_ORIGINDEX, &i);
721         }
722
723         for(i = 0; i < mesh->totedge; ++i) {
724                 DM_set_edge_data(dm, i, LAYERTYPE_MEDGE, &mesh->medge[i]);
725
726                 DM_set_edge_data(dm, i, LAYERTYPE_ORIGINDEX, &i);
727         }
728
729         for(i = 0; i < mesh->totface; ++i) {
730                 DM_set_face_data(dm, i, LAYERTYPE_MFACE, &mesh->mface[i]);
731                 if(mesh->tface)
732                         DM_set_face_data(dm, i, LAYERTYPE_TFACE, &mesh->tface[i]);
733                 if(mesh->mcol)
734                         DM_set_face_data(dm, i, LAYERTYPE_MCOL, &mesh->mcol[i * 4]);
735
736                 DM_set_face_data(dm, i, LAYERTYPE_ORIGINDEX, &i);
737         }
738
739         return dm;
740 }
741
742 DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *me)
743 {
744         DerivedMesh *dm = CDDM_new(BLI_countlist(&em->verts),
745                                    BLI_countlist(&em->edges),
746                                    BLI_countlist(&em->faces));
747         EditVert *eve;
748         EditEdge *eed;
749         EditFace *efa;
750         MVert *mvert = CDDM_get_verts(dm);
751         MEdge *medge = CDDM_get_edges(dm);
752         MFace *mface = CDDM_get_faces(dm);
753         int i, hassticky = 0, hasdvert = 0, hastface = 0, hasmcol = 0;
754         int *index;
755
756         /* set eve->hash to vert index */
757         for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i)
758                 eve->tmp.l = i;
759
760         /* check for availability of layers */
761         if(CustomData_has_layer(&em->vdata, LAYERTYPE_MSTICKY))
762                 hassticky= CustomData_add_layer(&dm->vertData, LAYERTYPE_MSTICKY, 0, NULL);
763         if(CustomData_has_layer(&em->vdata, LAYERTYPE_MDEFORMVERT))
764                 hasdvert= CustomData_add_layer(&dm->vertData, LAYERTYPE_MDEFORMVERT, 0, NULL);
765         if(CustomData_has_layer(&em->vdata, LAYERTYPE_TFACE))
766                 hastface= CustomData_add_layer(&dm->vertData, LAYERTYPE_TFACE, 0, NULL);
767         if(CustomData_has_layer(&em->vdata, LAYERTYPE_MCOL))
768                 hasmcol= CustomData_add_layer(&dm->vertData, LAYERTYPE_MCOL, 0, NULL);
769
770         /* Need to be able to mark loose edges */
771         for(eed = em->edges.first; eed; eed = eed->next) {
772                 eed->f2 = 0;
773         }
774         for(efa = em->faces.first; efa; efa = efa->next) {
775                 efa->e1->f2 = 1;
776                 efa->e2->f2 = 1;
777                 efa->e3->f2 = 1;
778                 if(efa->e4) efa->e4->f2 = 1;
779         }
780
781         index = dm->getVertDataArray(dm, LAYERTYPE_ORIGINDEX);
782         for(i = 0, eve = em->verts.first; i < dm->vertData.numElems;
783             i++, eve = eve->next, index++) {
784                 MVert *mv = &mvert[i];
785
786                 VECCOPY(mv->co, eve->co);
787
788                 mv->no[0] = eve->no[0] * 32767.0;
789                 mv->no[1] = eve->no[1] * 32767.0;
790                 mv->no[2] = eve->no[2] * 32767.0;
791
792                 mv->mat_nr = 0;
793                 mv->flag = 0;
794
795                 *index = i;
796
797                 if(hassticky)
798                         DM_set_vert_data(dm, i, LAYERTYPE_MSTICKY,
799                                 CustomData_em_get(&em->vdata, eve->data, LAYERTYPE_MSTICKY));
800                 if(hasdvert)
801                         DM_set_vert_data(dm, i, LAYERTYPE_MDEFORMVERT,
802                                 CustomData_em_get(&em->vdata, eve->data, LAYERTYPE_MDEFORMVERT));
803         }
804
805         index = dm->getEdgeDataArray(dm, LAYERTYPE_ORIGINDEX);
806         for(i = 0, eed = em->edges.first; i < dm->edgeData.numElems;
807             i++, eed = eed->next, index++) {
808                 MEdge *med = &medge[i];
809
810                 med->v1 = eed->v1->tmp.l;
811                 med->v2 = eed->v2->tmp.l;
812                 med->crease = (unsigned char) (eed->crease * 255.0f);
813                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
814                 
815                 if(eed->seam) med->flag |= ME_SEAM;
816                 if(eed->sharp) med->flag |= ME_SHARP;
817                 if(!eed->f2) med->flag |= ME_LOOSEEDGE;
818
819                 *index = i;
820         }
821
822         index = dm->getFaceDataArray(dm, LAYERTYPE_ORIGINDEX);
823         for(i = 0, efa = em->faces.first; i < dm->faceData.numElems;
824             i++, efa = efa->next, index++) {
825                 MFace *mf = &mface[i];
826
827                 mf->v1 = efa->v1->tmp.l;
828                 mf->v2 = efa->v2->tmp.l;
829                 mf->v3 = efa->v3->tmp.l;
830                 mf->v4 = efa->v4 ? efa->v4->tmp.l : 0;
831                 mf->mat_nr = efa->mat_nr;
832                 mf->flag = efa->flag;
833                 test_index_face(mf, NULL, NULL, efa->v4?4:3);
834
835                 *index = i;
836
837                 if(hastface)
838                         DM_set_face_data(dm, i, LAYERTYPE_TFACE,
839                                 CustomData_em_get(&em->fdata, efa->data, LAYERTYPE_TFACE));
840                 if(hasmcol)
841                         DM_set_face_data(dm, i, LAYERTYPE_MCOL,
842                                 CustomData_em_get(&em->fdata, efa->data, LAYERTYPE_MCOL));
843         }
844
845         return dm;
846 }
847
848 DerivedMesh *CDDM_copy(DerivedMesh *source)
849 {
850         DerivedMesh *dest = CDDM_from_template(source,
851                                                source->vertData.numElems,
852                                                source->edgeData.numElems,
853                                                source->faceData.numElems);
854
855         CustomData_copy_data(&source->vertData, &dest->vertData, 0, 0,
856                              source->vertData.numElems);
857         CustomData_copy_data(&source->edgeData, &dest->edgeData, 0, 0,
858                              source->edgeData.numElems);
859         CustomData_copy_data(&source->faceData, &dest->faceData, 0, 0,
860                              source->faceData.numElems);
861
862         /* copy vert/face/edge data from source */
863         source->getVertArray(source, CDDM_get_verts(dest));
864         source->getEdgeArray(source, CDDM_get_edges(dest));
865         source->getFaceArray(source, CDDM_get_faces(dest));
866
867         return dest;
868 }
869
870 DerivedMesh *CDDM_from_template(DerivedMesh *source,
871                                 int numVerts, int numEdges, int numFaces)
872 {
873         DerivedMesh *dest = cdDM_create("CDDM_from_template dest");
874         DM_from_template(dest, source, numVerts, numEdges, numFaces);
875
876         /* if no vert/face/edge layers in custom data, add them */
877         if(!CDDM_get_verts(dest))
878                 CustomData_add_layer(&dest->vertData, LAYERTYPE_MVERT,
879                                      LAYERFLAG_NOCOPY, NULL);
880         if(!CDDM_get_edges(dest))
881                 CustomData_add_layer(&dest->edgeData, LAYERTYPE_MEDGE,
882                                      LAYERFLAG_NOCOPY, NULL);
883         if(!CDDM_get_faces(dest))
884                 CustomData_add_layer(&dest->faceData, LAYERTYPE_MFACE,
885                                      LAYERFLAG_NOCOPY, NULL);
886
887         return dest;
888 }
889
890 void CDDM_apply_vert_coords(DerivedMesh *dm, float (*vertCoords)[3])
891 {
892         int i;
893         MVert *vert = CDDM_get_verts(dm);
894
895         for(i = 0; i < dm->vertData.numElems; ++i, ++vert)
896                 VECCOPY(vert->co, vertCoords[i]);
897 }
898
899 /* adapted from mesh_calc_normals */
900 void CDDM_calc_normals(DerivedMesh *dm)
901 {
902         float (*temp_nors)[3];
903         float (*face_nors)[3];
904         int i;
905         int numVerts = dm->getNumVerts(dm);
906         int numFaces = dm->getNumFaces(dm);
907         MFace *mf;
908         MVert *mv = CDDM_get_verts(dm);
909
910         if(!mv) return;
911
912         temp_nors = MEM_callocN(numVerts * sizeof(*temp_nors),
913                                 "CDDM_calc_normals temp_nors");
914         face_nors = MEM_mallocN(numFaces * sizeof(*face_nors),
915                                 "CDDM_calc_normals face_nors");
916
917         mf = CDDM_get_faces(dm);
918         for(i = 0; i < numFaces; i++, mf++) {
919                 float *f_no = face_nors[i];
920
921                 if(mf->v4)
922                         CalcNormFloat4(mv[mf->v1].co, mv[mf->v2].co,
923                                        mv[mf->v3].co, mv[mf->v4].co, f_no);
924                 else
925                         CalcNormFloat(mv[mf->v1].co, mv[mf->v2].co,
926                                       mv[mf->v3].co, f_no);
927                 
928                 VecAddf(temp_nors[mf->v1], temp_nors[mf->v1], f_no);
929                 VecAddf(temp_nors[mf->v2], temp_nors[mf->v2], f_no);
930                 VecAddf(temp_nors[mf->v3], temp_nors[mf->v3], f_no);
931                 if(mf->v4)
932                         VecAddf(temp_nors[mf->v4], temp_nors[mf->v4], f_no);
933         }
934
935         for(i = 0; i < numVerts; i++, mv++) {
936                 float *no = temp_nors[i];
937                 
938                 if (Normalise(no) == 0.0) {
939                         VECCOPY(no, mv->co);
940                         Normalise(no);
941                 }
942
943                 mv->no[0] = (short)(no[0] * 32767.0);
944                 mv->no[1] = (short)(no[1] * 32767.0);
945                 mv->no[2] = (short)(no[2] * 32767.0);
946         }
947         
948         MEM_freeN(temp_nors);
949
950         /* TODO maybe cache face normals here? */
951         MEM_freeN(face_nors);
952 }
953
954 void CDDM_calc_edges(DerivedMesh *dm)
955 {
956         CustomData edgeData;
957         EdgeHash *eh = BLI_edgehash_new();
958         EdgeHashIterator *ehi;
959         int i;
960         int maxFaces = dm->getNumFaces(dm);
961         MFace *mf = CDDM_get_faces(dm);
962         MEdge *med;
963
964         for (i = 0; i < maxFaces; i++, mf++) {
965                 if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
966                         BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
967                 if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
968                         BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);
969                 
970                 if (mf->v4) {
971                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
972                                 BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
973                         if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
974                                 BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
975                 } else {
976                         if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
977                                 BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
978                 }
979         }
980
981         CustomData_from_template(&dm->edgeData, &edgeData, 0, BLI_edgehash_size(eh));
982
983         if(!CustomData_get_layer(&edgeData, LAYERTYPE_MEDGE))
984                 CustomData_add_layer(&edgeData, LAYERTYPE_MEDGE,
985                                      LAYERFLAG_NOCOPY, NULL);
986
987         ehi = BLI_edgehashIterator_new(eh);
988         med = CustomData_get_layer(&edgeData, LAYERTYPE_MEDGE);
989         for(i = 0; !BLI_edgehashIterator_isDone(ehi);
990             BLI_edgehashIterator_step(ehi), ++i, ++med) {
991                 BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
992
993                 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
994         }
995         BLI_edgehashIterator_free(ehi);
996
997         CustomData_free(&dm->edgeData);
998         dm->edgeData = edgeData;
999
1000         BLI_edgehash_free(eh, NULL);
1001 }
1002
1003 void CDDM_set_num_verts(DerivedMesh *dm, int numVerts)
1004 {
1005         CustomData_set_num_elems(&dm->vertData, numVerts);
1006 }
1007
1008 void CDDM_set_num_edges(DerivedMesh *dm, int numEdges)
1009 {
1010         CustomData_set_num_elems(&dm->edgeData, numEdges);
1011 }
1012
1013 void CDDM_set_num_faces(DerivedMesh *dm, int numFaces)
1014 {
1015         CustomData_set_num_elems(&dm->faceData, numFaces);
1016 }
1017
1018 MVert *CDDM_get_vert(DerivedMesh *dm, int index)
1019 {
1020         return CustomData_get(&dm->vertData, index, LAYERTYPE_MVERT);
1021 }
1022
1023 MEdge *CDDM_get_edge(DerivedMesh *dm, int index)
1024 {
1025         return CustomData_get(&dm->edgeData, index, LAYERTYPE_MEDGE);
1026 }
1027
1028 MFace *CDDM_get_face(DerivedMesh *dm, int index)
1029 {
1030         return CustomData_get(&dm->faceData, index, LAYERTYPE_MFACE);
1031 }
1032
1033 MVert *CDDM_get_verts(DerivedMesh *dm)
1034 {
1035         return CustomData_get_layer(&dm->vertData, LAYERTYPE_MVERT);
1036 }
1037
1038 MEdge *CDDM_get_edges(DerivedMesh *dm)
1039 {
1040         return CustomData_get_layer(&dm->edgeData, LAYERTYPE_MEDGE);
1041 }
1042
1043 MFace *CDDM_get_faces(DerivedMesh *dm)
1044 {
1045         return CustomData_get_layer(&dm->faceData, LAYERTYPE_MFACE);
1046 }
1047