- added Mesh->derived and Mesh->decimated DerivedMesh pointers
[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 #ifdef HAVE_CONFIG_H
34 #include <config.h>
35 #endif
36
37 #include "MEM_guardedalloc.h"
38
39 #include "DNA_effect_types.h"
40 #include "DNA_mesh_types.h"
41 #include "DNA_meshdata_types.h"
42 #include "DNA_object_types.h"
43
44 #include "BLI_blenlib.h"
45 #include "BLI_editVert.h"
46
47 #include "BKE_DerivedMesh.h"
48 #include "BKE_displist.h"
49 #include "BKE_effect.h"
50 #include "BKE_global.h"
51 #include "BKE_material.h"
52 #include "BKE_mesh.h"
53 #include "BKE_object.h"
54 #include "BKE_subsurf.h"
55
56 #include "BIF_gl.h"
57 #include "BIF_glutil.h"
58
59 ///////////////////////////////////
60 ///////////////////////////////////
61
62 typedef struct {
63         DerivedMesh dm;
64
65         Object *ob;
66         float *extverts, *nors;
67 } MeshDerivedMesh;
68
69 static float *meshDM__getVertCo(MeshDerivedMesh *mdm, int index)
70 {
71         if (mdm->extverts) {
72                 return mdm->extverts+3*index;
73         } else {
74                 return ((Mesh*) mdm->ob->data)->mvert[index].co;
75         }
76 }
77
78 static void meshDM_drawVerts(DerivedMesh *dm)
79 {
80         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
81         Mesh *me = mdm->ob->data;
82         int a, start=0, end=me->totvert;
83
84         set_buildvars(mdm->ob, &start, &end);
85
86         glBegin(GL_POINTS);
87         for(a= start; a<end; a++) {
88                 glVertex3fv(meshDM__getVertCo(mdm, a));
89         }
90         glEnd();
91 }
92 static void meshDM_drawEdges(DerivedMesh *dm)
93 {
94         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
95         Mesh *me= mdm->ob->data;
96         int a, start= 0, end= me->totface;
97         MFace *mface = me->mface;
98
99         set_buildvars(mdm->ob, &start, &end);
100         mface+= start;
101         
102                 // edges can't cope with buildvars, draw with
103                 // faces if build is in use.
104         if(me->medge && start==0 && end==me->totface) {
105                 MEdge *medge= me->medge;
106                 
107                 glBegin(GL_LINES);
108                 for(a=me->totedge; a>0; a--, medge++) {
109                         if(medge->flag & ME_EDGEDRAW) {
110                                 glVertex3fv(meshDM__getVertCo(mdm, medge->v1));
111                                 glVertex3fv(meshDM__getVertCo(mdm, medge->v2));
112                         }
113                 }
114                 glEnd();
115         }
116         else {
117                 glBegin(GL_LINES);
118                 for(a=start; a<end; a++, mface++) {
119                         int test= mface->edcode;
120                         
121                         if(test) {
122                                 if(test&ME_V1V2){
123                                         glVertex3fv(meshDM__getVertCo(mdm, mface->v1));
124                                         glVertex3fv(meshDM__getVertCo(mdm, mface->v2));
125                                 }
126
127                                 if(mface->v3) {
128                                         if(test&ME_V2V3){
129                                                 glVertex3fv(meshDM__getVertCo(mdm, mface->v2));
130                                                 glVertex3fv(meshDM__getVertCo(mdm, mface->v3));
131                                         }
132
133                                         if (mface->v4) {
134                                                 if(test&ME_V3V4){
135                                                         glVertex3fv(meshDM__getVertCo(mdm, mface->v3));
136                                                         glVertex3fv(meshDM__getVertCo(mdm, mface->v4));
137                                                 }
138                                                 if(test&ME_V4V1){
139                                                         glVertex3fv(meshDM__getVertCo(mdm, mface->v4));
140                                                         glVertex3fv(meshDM__getVertCo(mdm, mface->v1));
141                                                 }
142                                         } else {
143                                                 if(test&ME_V3V1){
144                                                         glVertex3fv(meshDM__getVertCo(mdm, mface->v3));
145                                                         glVertex3fv(meshDM__getVertCo(mdm, mface->v1));
146                                                 }
147                                         }
148                                 }
149                         }
150                 }
151                 glEnd();
152         }
153 }
154 static void meshDM_drawLooseEdges(DerivedMesh *dm)
155 {
156         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
157         Mesh *me = mdm->ob->data;
158         MFace *mface= me->mface;
159         int a, start=0, end=me->totface;
160
161         set_buildvars(mdm->ob, &start, &end);
162         mface+= start;
163                 
164         glBegin(GL_LINES);
165         for(a=start; a<end; a++, mface++) {
166                 if(!mface->v3) {
167                         glVertex3fv(meshDM__getVertCo(mdm, mface->v3));
168                         glVertex3fv(meshDM__getVertCo(mdm, mface->v4));
169                 } 
170         }
171         glEnd();
172 }
173 static void meshDM_drawFacesSolid(DerivedMesh *dm, void (*setMaterial)(int))
174 {
175         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
176         Mesh *me = mdm->ob->data;
177         MVert *mvert= me->mvert;
178         MFace *mface= me->mface;
179         float *nors = mdm->nors;
180         int a, start=0, end=me->totface;
181         int glmode=-1, shademodel=-1, matnr=-1;
182
183         set_buildvars(mdm->ob, &start, &end);
184         mface+= start;
185         
186 #define PASSVERT(index, punoBit) {                              \
187         if (shademodel==GL_SMOOTH) {                            \
188                 short *no = (mvert+index)->no;                  \
189                 if (mface->puno&punoBit) {                              \
190                         glNormal3s(-no[0], -no[1], -no[2]); \
191                 } else {                                                                \
192                         glNormal3sv(no);                                        \
193                 }                                                                               \
194         }                                                                                       \
195         glVertex3fv(meshDM__getVertCo(mdm,index));      \
196 }
197
198         glBegin(glmode=GL_QUADS);
199         for(a=start; a<end; a++, mface++, nors+=3) {
200                 if(mface->v3) {
201                         int new_glmode, new_matnr, new_shademodel;
202                                 
203                         new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
204                         new_matnr = mface->mat_nr+1;
205                         new_shademodel = (!(me->flag&ME_AUTOSMOOTH) && (mface->flag & ME_SMOOTH))?GL_SMOOTH:GL_FLAT;
206                         
207                         if (new_glmode!=glmode || new_matnr!=matnr || new_shademodel!=shademodel) {
208                                 glEnd();
209
210                                 setMaterial(matnr=new_matnr);
211
212                                 glShadeModel(shademodel=new_shademodel);
213                                 glBegin(glmode=new_glmode);
214                         }
215                                 
216                         if(shademodel==GL_FLAT) 
217                                 glNormal3fv(nors);
218
219                         PASSVERT(mface->v1, ME_FLIPV1);
220                         PASSVERT(mface->v2, ME_FLIPV2);
221                         PASSVERT(mface->v3, ME_FLIPV3);
222                         if (mface->v4) {
223                                 PASSVERT(mface->v4, ME_FLIPV4);
224                         }
225                 }
226         }
227         glEnd();
228
229         glShadeModel(GL_FLAT);
230 #undef PASSVERT
231 }
232
233 static void meshDM_drawFacesColored(DerivedMesh *dm, int useTwoSide, unsigned char *col1, unsigned char *col2)
234 {
235         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
236         Object *ob= mdm->ob;
237         Mesh *me= ob->data;
238         MFace *mface= me->mface;
239         int a, glmode, start=0, end=me->totface;
240         unsigned char *cp1, *cp2;
241
242         set_buildvars(ob, &start, &end);
243         mface+= start;
244         col1+= 4*start;
245         if(col2) col2+= 4*start;
246         
247         cp1= col1;
248         if(col2) {
249                 cp2= col2;
250         } else {
251                 cp2= NULL;
252                 useTwoSide= 0;
253         }
254
255         glEnable(GL_CULL_FACE);
256         glShadeModel(GL_SMOOTH);
257         glBegin(glmode=GL_QUADS);
258         for(a=start; a<end; a++, mface++, cp1+= 16) {
259                 if(mface->v3) {
260                         int new_glmode= mface->v4?GL_QUADS:GL_TRIANGLES;
261
262                         if (new_glmode!=glmode) {
263                                 glEnd();
264                                 glBegin(glmode= new_glmode);
265                         }
266                                 
267                         glColor3ub(cp1[3], cp1[2], cp1[1]);
268                         glVertex3fv( meshDM__getVertCo(mdm,mface->v1) );
269                         glColor3ub(cp1[7], cp1[6], cp1[5]);
270                         glVertex3fv( meshDM__getVertCo(mdm,mface->v2) );
271                         glColor3ub(cp1[11], cp1[10], cp1[9]);
272                         glVertex3fv( meshDM__getVertCo(mdm,mface->v3) );
273                         if(mface->v4) {
274                                 glColor3ub(cp1[15], cp1[14], cp1[13]);
275                                 glVertex3fv( meshDM__getVertCo(mdm,mface->v4) );
276                         }
277                                 
278                         if(useTwoSide) {
279                                 glColor3ub(cp2[11], cp2[10], cp2[9]);
280                                 glVertex3fv( meshDM__getVertCo(mdm,mface->v3) );
281                                 glColor3ub(cp2[7], cp2[6], cp2[5]);
282                                 glVertex3fv( meshDM__getVertCo(mdm,mface->v2) );
283                                 glColor3ub(cp2[3], cp2[2], cp2[1]);
284                                 glVertex3fv( meshDM__getVertCo(mdm,mface->v1) );
285                                 if(mface->v4) {
286                                         glColor3ub(cp2[15], cp2[14], cp2[13]);
287                                         glVertex3fv( meshDM__getVertCo(mdm,mface->v4) );
288                                 }
289                         }
290                 }
291                 if(col2) cp2+= 16;
292         }
293         glEnd();
294
295         glShadeModel(GL_FLAT);
296         glDisable(GL_CULL_FACE);
297 }
298
299 static void meshDM_drawFacesTex(DerivedMesh *dm, int (*setDrawParams)(TFace *tf, int matnr)) 
300 {
301         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
302         Mesh *me = mdm->ob->data;
303         MVert *mvert= me->mvert;
304         MFace *mface= me->mface;
305         TFace *tface = me->tface;
306         float *nors = mdm->nors;
307         int a, start=0, end=me->totface;
308
309         set_buildvars(mdm->ob, &start, &end);
310         
311         for (a=start; a<end; a++) {
312                 MFace *mf= &mface[a];
313                 unsigned char *cp= NULL;
314                 
315                 if(mf->v3==0) continue;
316                 if(tface && (tface->flag & (TF_HIDE|TF_INVISIBLE))) continue;
317
318                 if (setDrawParams(tface, mf->mat_nr)) {
319                         if (tface) {
320                                 cp= (unsigned char *) tface->col;
321                         } else if (me->mcol) {
322                                 cp= (unsigned char *) &me->mcol[a*4];
323                         }
324                 }
325
326                 if (!(mf->flag&ME_SMOOTH)) {
327                         glNormal3fv(&nors[a*3]);
328                 }
329
330                 glBegin(mface->v4?GL_QUADS:GL_TRIANGLES);
331                 if (tface) glTexCoord2fv(tface->uv[0]);
332                 if (cp) glColor3ub(cp[3], cp[2], cp[1]);
333                 if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v1].no);
334                 glVertex3fv(meshDM__getVertCo(mdm, mface->v1));
335                         
336                 if (tface) glTexCoord2fv(tface->uv[1]);
337                 if (cp) glColor3ub(cp[7], cp[6], cp[5]);
338                 if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v2].no);
339                 glVertex3fv(meshDM__getVertCo(mdm, mface->v2));
340
341                 if (tface) glTexCoord2fv(tface->uv[2]);
342                 if (cp) glColor3ub(cp[11], cp[10], cp[9]);
343                 if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v3].no);
344                 glVertex3fv(meshDM__getVertCo(mdm, mface->v3));
345
346                 if(mface->v4) {
347                         if (tface) glTexCoord2fv(tface->uv[3]);
348                         if (cp) glColor3ub(cp[15], cp[14], cp[13]);
349                         if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v4].no);
350                         glVertex3fv(meshDM__getVertCo(mdm, mface->v4));
351                 }
352                 glEnd();
353
354                 if (tface) tface++;
355         }
356 }
357 static int meshDM_getNumVerts(DerivedMesh *dm)
358 {
359         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
360         Mesh *me = mdm->ob->data;
361
362         return me->totvert;
363 }
364 static int meshDM_getNumFaces(DerivedMesh *dm)
365 {
366         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
367         Mesh *me = mdm->ob->data;
368
369         return me->totface;
370 }
371
372 static DispListMesh *meshDM_convertToDispListMesh(DerivedMesh *dm)
373 {
374         MeshDerivedMesh *mdm= (MeshDerivedMesh*) dm;
375
376         return displistmesh_from_mesh(mdm->ob->data, mdm->extverts);
377 }
378
379
380 static DerivedMesh *getMeshDerivedMesh(Object *ob, float *extverts, float *nors)
381 {
382         MeshDerivedMesh *mdm = MEM_mallocN(sizeof(*mdm), "dm");
383
384         mdm->dm.getNumVerts = meshDM_getNumVerts;
385         mdm->dm.getNumFaces = meshDM_getNumFaces;
386         mdm->dm.convertToDispListMesh = meshDM_convertToDispListMesh;
387
388         mdm->dm.drawVerts = meshDM_drawVerts;
389         mdm->dm.drawMappedVertEM = NULL;
390         mdm->dm.drawMappedVertsEM = NULL;
391         mdm->dm.drawMappedVertsEMSelect = NULL;
392
393         mdm->dm.drawEdges = meshDM_drawEdges;
394         mdm->dm.drawMappedEdges = meshDM_drawEdges;
395         mdm->dm.drawLooseEdges = meshDM_drawLooseEdges;
396         mdm->dm.drawMappedEdgeEM = NULL;
397         mdm->dm.drawMappedEdgesEM = NULL;
398         mdm->dm.drawMappedEdgesEMSelect = NULL;
399         mdm->dm.drawMappedFacesEMSelect = NULL;
400
401         mdm->dm.drawFacesSolid = meshDM_drawFacesSolid;
402         mdm->dm.drawFacesColored = meshDM_drawFacesColored;
403         mdm->dm.drawFacesTex = meshDM_drawFacesTex;
404         mdm->dm.drawFacesEM = NULL;
405
406         mdm->dm.release = MEM_freeN;
407         
408         mdm->ob = ob;
409         mdm->extverts = extverts;
410         mdm->nors = nors;
411
412         return (DerivedMesh*) mdm;
413 }
414
415 ///
416
417 typedef struct {
418         DerivedMesh dm;
419
420         EditMesh *em;
421 } EditMeshDerivedMesh;
422
423 static void emDM_getMappedVertCoEM(DerivedMesh *dm, void *vert, float co_r[3])
424 {
425         EditVert *eve = vert;
426
427         co_r[0] = eve->co[0];
428         co_r[1] = eve->co[1];
429         co_r[2] = eve->co[2];
430 }
431 static void emDM_drawMappedVertEM(DerivedMesh *dm, void *vert)
432 {
433         EditVert *eve = vert;
434
435         bglBegin(GL_POINTS);
436         bglVertex3fv(eve->co);
437         bglEnd();               
438 }
439 static void emDM_drawMappedVertsEM(DerivedMesh *dm, int sel)
440 {
441         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
442         EditVert *eve;
443
444         bglBegin(GL_POINTS);
445         for(eve= emdm->em->verts.first; eve; eve= eve->next) {
446                 if(eve->h==0 && (eve->f & SELECT)==sel ) 
447                         bglVertex3fv(eve->co);
448         }
449         bglEnd();               
450 }
451 static int emDM_drawMappedVertsEMSelect(DerivedMesh *dm, void (*setColor)(int index), int offset)
452 {
453         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
454         EditVert *eve;
455         int i = offset;
456
457         bglBegin(GL_POINTS);
458         for(eve= emdm->em->verts.first; eve; eve= eve->next, i++) {
459                 if(eve->h==0) {
460                         setColor(i);
461                         bglVertex3fv(eve->co);
462                 }
463         }
464         bglEnd();
465         
466         return i;
467 }
468 static void emDM_drawMappedEdgeEM(DerivedMesh *dm, void *edge)
469 {
470         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
471         EditEdge *eed = edge;
472
473         glBegin(GL_LINES);
474         glVertex3fv(eed->v1->co);
475         glVertex3fv(eed->v2->co);
476         glEnd();
477 }
478 static void emDM_drawMappedEdgesEM(DerivedMesh *dm, int useColor, char *baseCol, char *selCol, int onlySeams) 
479 {
480         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
481         EditEdge *eed;
482
483         glBegin(GL_LINES);
484         for(eed= emdm->em->edges.first; eed; eed= eed->next) {
485                 if(eed->h==0 && (!onlySeams || eed->seam)) {
486                         if (useColor==1) {
487                                 glColor4ubv((eed->f&SELECT)?selCol:baseCol);
488                         } else if (useColor==2) {
489                                 glColor4ubv((eed->v1->f&SELECT)?selCol:baseCol);
490                         }
491                         glVertex3fv(eed->v1->co);
492                         if (useColor==2) {
493                                 glColor4ubv((eed->v2->f&SELECT)?selCol:baseCol);
494                         }
495                         glVertex3fv(eed->v2->co);
496                 }
497         }
498         glEnd();
499 }
500 static int emDM_drawMappedEdgesEMSelect(DerivedMesh *dm, void (*setColor)(int index), int offset)
501 {
502         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
503         EditEdge *eed;
504         int i;
505
506         i = offset;
507         glBegin(GL_LINES);
508         for(eed= emdm->em->edges.first; eed; eed= eed->next, i++) {
509                 if (eed->h==0) {
510                         setColor(i);
511                         glVertex3fv(eed->v1->co);
512                         glVertex3fv(eed->v2->co);
513                 }
514         }
515         glEnd();
516
517         return i;
518 }
519 static void emDM_drawFacesEM(DerivedMesh *dm, int useColor, unsigned char *baseCol, unsigned char *selCol)
520 {
521         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
522         EditFace *efa;
523
524         for (efa= emdm->em->faces.first; efa; efa= efa->next) {
525                 if(efa->h==0) {
526                         if (useColor) {
527                                 glColor4ubv((efa->f & SELECT)?selCol:baseCol);
528                         }
529
530                         glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
531                         glVertex3fv(efa->v1->co);
532                         glVertex3fv(efa->v2->co);
533                         glVertex3fv(efa->v3->co);
534                         if(efa->v4) glVertex3fv(efa->v4->co);
535                         glEnd();
536                 }
537         }
538 }
539 static void emDM_drawFacesSolid(DerivedMesh *dm, void (*setMaterial)(int))
540 {
541         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
542         EditFace *efa;
543
544         for (efa= emdm->em->faces.first; efa; efa= efa->next) {
545                 if(efa->h==0) {
546                         setMaterial(efa->mat_nr+1);
547
548                         glNormal3fv(efa->n);
549                         glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
550                         glVertex3fv(efa->v1->co);
551                         glVertex3fv(efa->v2->co);
552                         glVertex3fv(efa->v3->co);
553                         if(efa->v4) glVertex3fv(efa->v4->co);
554                         glEnd();
555                 }
556         }
557 }
558 static int emDM_drawMappedFacesEMSelect(DerivedMesh *dm, void (*setColor)(int index), int offset)
559 {
560         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
561         EditFace *efa;
562         int i = offset;
563
564         for (efa= emdm->em->faces.first; efa; efa= efa->next, i++) {
565                 if (efa->h==0) {
566                         setColor(i);
567
568                         glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
569                         glVertex3fv(efa->v1->co);
570                         glVertex3fv(efa->v2->co);
571                         glVertex3fv(efa->v3->co);
572                         if(efa->v4) glVertex3fv(efa->v4->co);
573                         glEnd();
574                 }
575         }
576
577         return i;
578 }
579
580 static int emDM_getNumVerts(DerivedMesh *dm)
581 {
582         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
583
584         return BLI_countlist(&emdm->em->verts);
585 }
586 static int emDM_getNumFaces(DerivedMesh *dm)
587 {
588         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
589
590         return BLI_countlist(&emdm->em->faces);
591 }
592
593 static DispListMesh *emDM_convertToDispListMesh(DerivedMesh *dm)
594 {
595         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
596
597         return displistmesh_from_editmesh(emdm->em);
598 }
599
600 static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em)
601 {
602         EditMeshDerivedMesh *emdm = MEM_mallocN(sizeof(*emdm), "dm");
603
604         emdm->dm.getNumVerts = emDM_getNumVerts;
605         emdm->dm.getNumFaces = emDM_getNumFaces;
606         emdm->dm.getMappedVertCoEM = emDM_getMappedVertCoEM;
607         emdm->dm.convertToDispListMesh = emDM_convertToDispListMesh;
608
609         emdm->dm.drawVerts = NULL;
610         emdm->dm.drawMappedVertEM = emDM_drawMappedVertEM;
611         emdm->dm.drawMappedVertsEM = emDM_drawMappedVertsEM;
612         emdm->dm.drawMappedVertsEMSelect = emDM_drawMappedVertsEMSelect;
613
614         emdm->dm.drawEdges = NULL;
615         emdm->dm.drawMappedEdges = NULL;
616         emdm->dm.drawLooseEdges = NULL;
617         emdm->dm.drawMappedEdgeEM = emDM_drawMappedEdgeEM;
618         emdm->dm.drawMappedEdgesEM = emDM_drawMappedEdgesEM;
619         emdm->dm.drawMappedEdgesEMSelect = emDM_drawMappedEdgesEMSelect;
620         emdm->dm.drawMappedFacesEMSelect = emDM_drawMappedFacesEMSelect;
621
622         emdm->dm.drawFacesSolid = emDM_drawFacesSolid;
623         emdm->dm.drawFacesColored = NULL;
624         emdm->dm.drawFacesTex = NULL;
625         emdm->dm.drawFacesEM = emDM_drawFacesEM;
626
627         emdm->dm.release = MEM_freeN;
628         
629         emdm->em = em;
630
631         return (DerivedMesh*) emdm;
632 }
633
634 ///
635
636 typedef struct {
637         DerivedMesh dm;
638
639         DispListMesh *dlm;
640         EditMesh *em;
641
642         int needsFree;
643 } SSDerivedMesh;
644
645 static void ssDM_getMappedVertCoEM(DerivedMesh *dm, void *vert, float co_r[3])
646 {
647         EditVert *eve = vert;
648
649         co_r[0] = eve->ssco[0];
650         co_r[1] = eve->ssco[1];
651         co_r[2] = eve->ssco[2];
652 }
653 static void ssDM_drawMappedVertEM(DerivedMesh *dm, void *vert)
654 {
655         EditVert *eve = vert;
656
657         bglBegin(GL_POINTS);
658         bglVertex3fv(eve->ssco);
659         bglEnd();               
660 }
661 static void ssDM_drawMappedVertsEM(DerivedMesh *dm, int sel)
662 {
663         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
664         EditVert *eve;
665
666         bglBegin(GL_POINTS);
667         for (eve=ssdm->em->verts.first; eve; eve=eve->next) {
668                 if(eve->h==0 && (eve->f & SELECT)==sel && eve->ssco) 
669                         bglVertex3fv(eve->ssco);
670         }
671         bglEnd();
672 }
673 static int ssDM_drawMappedVertsEMSelect(DerivedMesh *dm, void (*setColor)(int index), int offset)
674 {
675         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
676         EditVert *eve;
677         int i = offset;
678
679         bglBegin(GL_POINTS);
680         for(eve= ssdm->em->verts.first; eve; eve= eve->next, i++) {
681                 if(eve->h==0 && eve->ssco) {
682                         setColor(i);
683                         bglVertex3fv(eve->ssco);
684                 }
685         }
686         bglEnd();
687         
688         return i;
689 }
690
691 static void ssDM_drawMappedEdges(DerivedMesh *dm)
692 {
693         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
694         DispListMesh *dlm = ssdm->dlm;
695         MEdge *medge= dlm->medge;
696         MVert *mvert= dlm->mvert;
697         int a;
698         
699         glBegin(GL_LINES);
700         for (a=0; a<dlm->totedge; a++, medge++) {
701                 if (medge->flag&ME_EDGEDRAW) {
702                         glVertex3fv(mvert[medge->v1].co); 
703                         glVertex3fv(mvert[medge->v2].co);
704                 }
705         }
706         glEnd();
707 }
708
709 static void ssDM_drawLooseEdges(DerivedMesh *dm)
710 {
711         /* Can't implement currently */ 
712 }
713
714 static void ssDM_drawMappedEdgeEM(DerivedMesh *dm, void *edge)
715 {
716         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
717         DispListMesh *dlm = ssdm->dlm;
718         MEdge *medge= dlm->medge;
719         MVert *mvert= dlm->mvert;
720         int a;
721
722         glBegin(GL_LINES);
723         for (a=0; a<dlm->totedge; a++, medge++) {
724                 if (medge->flag&ME_EDGEDRAW) {
725                         if (edge==dlm->editedge[a]) {
726                                 glVertex3fv(mvert[medge->v1].co); 
727                                 glVertex3fv(mvert[medge->v2].co);
728                         }
729                 }
730         }
731         glEnd();
732 }
733 static void ssDM_drawMappedEdgesEM(DerivedMesh *dm, int useColor, unsigned char *baseCol, unsigned char *selCol, int onlySeams) 
734 {
735         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
736         DispListMesh *dlm = ssdm->dlm;
737         MEdge *medge= dlm->medge;
738         MVert *mvert= dlm->mvert;
739         int a;
740         
741         glBegin(GL_LINES);
742         for (a=0; a<dlm->totedge; a++, medge++) {
743                 if (medge->flag&ME_EDGEDRAW) {
744                         EditEdge *eed = dlm->editedge[a];
745
746                         if (eed && eed->h==0 && (!onlySeams || eed->seam)) {
747                                 if (useColor) {
748                                         glColor4ubv((eed->f&SELECT)?selCol:baseCol);
749                                 }
750                                 glVertex3fv(mvert[medge->v1].co); 
751                                 glVertex3fv(mvert[medge->v2].co);
752                         }
753                 }
754         }
755         glEnd();
756 }
757 static int ssDM_drawMappedEdgesEMSelect(DerivedMesh *dm, void (*setColor)(int index), int offset)
758 {
759         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
760         DispListMesh *dlm = ssdm->dlm;
761         int i, endOffset;
762         MVert *mvert= dlm->mvert;
763         MEdge *medge= dlm->medge;
764         EditEdge *eed;
765
766         i = offset;
767         for(eed= ssdm->em->edges.first; eed; eed= eed->next)
768                 eed->vn= (EditVert*) i++;
769         endOffset = i;
770
771         glBegin(GL_LINES);
772         for (i=0; i<dlm->totedge; i++, medge++) {
773                 if(medge->flag & ME_EDGEDRAW) {
774                         EditEdge *eed= dlm->editedge[i];
775                         if(eed && eed->h==0) {
776                                 setColor((int) eed->vn);
777                                 glVertex3fv(mvert[medge->v1].co); 
778                                 glVertex3fv(mvert[medge->v2].co);
779                         }
780                 }
781         }
782         glEnd();
783
784         return endOffset;
785 }
786 static void ssDM_drawVerts(DerivedMesh *dm)
787 {
788         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
789         DispListMesh *dlm = ssdm->dlm;
790         MVert *mvert= dlm->mvert;
791         int i;
792
793         bglBegin(GL_POINTS);
794         for (i=0; i<dlm->totvert; i++) {
795                 bglVertex3fv(mvert[i].co);
796         }
797         bglEnd();
798 }
799 static void ssDM_drawEdges(DerivedMesh *dm) 
800 {
801         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
802         DispListMesh *dlm = ssdm->dlm;
803         MVert *mvert= dlm->mvert;
804         int i;
805
806         if (dlm->medge) {
807                 MEdge *medge= dlm->medge;
808         
809                 glBegin(GL_LINES);
810                 for (i=0; i<dlm->totedge; i++, medge++) {
811                         glVertex3fv(mvert[medge->v1].co); 
812                         glVertex3fv(mvert[medge->v2].co);
813                 }
814                 glEnd();
815         } else {
816                 MFace *mface= dlm->mface;
817
818                 glBegin(GL_LINES);
819                 for (i=0; i<dlm->totface; i++, mface++) {
820                         glVertex3fv(mvert[mface->v1].co);
821                         glVertex3fv(mvert[mface->v2].co);
822
823                         if (mface->v3) {
824                                 glVertex3fv(mvert[mface->v2].co);
825                                 glVertex3fv(mvert[mface->v3].co);
826
827                                 glVertex3fv(mvert[mface->v3].co);
828                                 if (mface->v4) {
829                                         glVertex3fv(mvert[mface->v4].co);
830
831                                         glVertex3fv(mvert[mface->v4].co);
832                                 }
833                                 glVertex3fv(mvert[mface->v1].co);
834                         }
835                 }
836                 glEnd();
837         }
838 }
839 static void ssDM_drawFacesSolid(DerivedMesh *dm, void (*setMaterial)(int))
840 {
841         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
842         DispListMesh *dlm = ssdm->dlm;
843         float *nors = dlm->nors;
844         int glmode=-1, shademodel=-1, matnr=-1;
845         int i;
846
847 #define PASSVERT(ind) {                                         \
848         if (shademodel==GL_SMOOTH)                              \
849                 glNormal3sv(dlm->mvert[(ind)].no);      \
850         glVertex3fv(dlm->mvert[(ind)].co);              \
851 }
852
853         glBegin(glmode=GL_QUADS);
854         for (i=0; i<dlm->totface; i++) {
855                 MFace *mf= &dlm->mface[i];
856                 
857                 if (mf->v3) {
858                         int new_glmode = mf->v4?GL_QUADS:GL_TRIANGLES;
859                         int new_shademodel = (mf->flag&ME_SMOOTH)?GL_SMOOTH:GL_FLAT;
860                         int new_matnr = mf->mat_nr+1;
861                         
862                         if(new_glmode!=glmode || new_shademodel!=shademodel || new_matnr!=matnr) {
863                                 glEnd();
864
865                                 setMaterial(matnr=new_matnr);
866
867                                 glShadeModel(shademodel=new_shademodel);
868                                 glBegin(glmode=new_glmode);
869                         }
870                         
871                         if (shademodel==GL_FLAT)
872                                 glNormal3fv(&nors[i*3]);
873                                 
874                         PASSVERT(mf->v1);
875                         PASSVERT(mf->v2);
876                         PASSVERT(mf->v3);
877                         if (mf->v4)
878                                 PASSVERT(mf->v4);
879                 }
880         }
881         glEnd();
882         
883 #undef PASSVERT
884 }
885 static void ssDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *vcols1, unsigned char *vcols2)
886 {
887         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
888         DispListMesh *dlm = ssdm->dlm;
889         int i, lmode;
890         
891         glShadeModel(GL_SMOOTH);
892         if (vcols2) {
893                 glEnable(GL_CULL_FACE);
894         } else {
895                 useTwoSided = 0;
896         }
897                 
898 #define PASSVERT(vidx, fidx) {                                  \
899         unsigned char *col= &colbase[fidx*4];           \
900         glColor3ub(col[3], col[2], col[1]);                     \
901         glVertex3fv(dlm->mvert[(vidx)].co);                     \
902 }
903
904         glBegin(lmode= GL_QUADS);
905         for (i=0; i<dlm->totface; i++) {
906                 MFace *mf= &dlm->mface[i];
907                 
908                 if (mf->v3) {
909                         int nmode= mf->v4?GL_QUADS:GL_TRIANGLES;
910                         unsigned char *colbase= &vcols1[i*16];
911                         
912                         if (nmode!=lmode) {
913                                 glEnd();
914                                 glBegin(lmode= nmode);
915                         }
916                         
917                         PASSVERT(mf->v1, 0);
918                         PASSVERT(mf->v2, 1);
919                         PASSVERT(mf->v3, 2);
920                         if (mf->v4)
921                                 PASSVERT(mf->v4, 3);
922                         
923                         if (useTwoSided) {
924                                 unsigned char *colbase= &vcols2[i*16];
925
926                                 if (mf->v4)
927                                         PASSVERT(mf->v4, 3);
928                                 PASSVERT(mf->v3, 2);
929                                 PASSVERT(mf->v2, 1);
930                                 PASSVERT(mf->v1, 0);
931                         }
932                 }
933         }
934         glEnd();
935
936         if (vcols2)
937                 glDisable(GL_CULL_FACE);
938         
939 #undef PASSVERT
940 }
941 static void ssDM_drawFacesEM(DerivedMesh *dm, int useColor, unsigned char *baseCol, unsigned char *selCol)
942 {
943         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
944         DispListMesh *dlm = ssdm->dlm;
945         MFace *mface= dlm->mface;
946         int a;
947
948         for(a=0; a<dlm->totface; a++, mface++) {
949                 if(mface->v3) {
950                         if (useColor) {
951                                 glColor4ubv((dlm->editface[a]->f & SELECT)?selCol:baseCol);
952                         }
953                         
954                         glBegin(mface->v4?GL_QUADS:GL_TRIANGLES);
955                         glVertex3fv(dlm->mvert[mface->v1].co);
956                         glVertex3fv(dlm->mvert[mface->v2].co);
957                         glVertex3fv(dlm->mvert[mface->v3].co);
958                         if (mface->v4) glVertex3fv(dlm->mvert[mface->v4].co);
959                         glEnd();
960                 }
961         }
962 }
963 static int ssDM_drawMappedFacesEMSelect(DerivedMesh *dm, void (*setColor)(int index), int offset)
964 {
965         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
966         DispListMesh *dlm = ssdm->dlm;
967         MFace *mface= dlm->mface;
968         int i, endOffset;
969         EditFace *prevefa, *efa;
970
971         for (i=offset, efa=ssdm->em->faces.first; efa; efa= efa->next, i++)
972                 efa->prev = (EditFace*) i;
973         endOffset = i;
974
975         for(i=0; i<dlm->totface; i++, mface++) {
976                 if(mface->v3 && dlm->editface[i]->h==0) {
977                         setColor((int) dlm->editface[i]->prev);
978                         
979                         glBegin(mface->v4?GL_QUADS:GL_TRIANGLES);
980                         glVertex3fv(dlm->mvert[mface->v1].co);
981                         glVertex3fv(dlm->mvert[mface->v2].co);
982                         glVertex3fv(dlm->mvert[mface->v3].co);
983                         if (mface->v4) glVertex3fv(dlm->mvert[mface->v4].co);
984                         glEnd();
985                 }
986         }
987
988         for (prevefa= NULL, efa= ssdm->em->faces.first; efa; prevefa= efa, efa= efa->next)
989                 efa->prev= prevefa;
990
991         return endOffset;
992 }
993
994 static void ssDM_drawFacesTex(DerivedMesh *dm, int (*setDrawParams)(TFace *tf, int matnr)) 
995 {
996         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
997         DispListMesh *dlm = ssdm->dlm;
998         MVert *mvert= dlm->mvert;
999         MFace *mface= dlm->mface;
1000         TFace *tface = dlm->tface;
1001         float *nors = dlm->nors;
1002         int a;
1003         
1004         for (a=0; a<dlm->totface; a++) {
1005                 MFace *mf= &mface[a];
1006                 unsigned char *cp= NULL;
1007                 
1008                 if(mf->v3==0) continue;
1009                 if(tface && (tface->flag & (TF_HIDE|TF_INVISIBLE))) continue;
1010
1011                 if (setDrawParams(tface, mf->mat_nr)) {
1012                         if (tface) {
1013                                 cp= (unsigned char*) tface->col;
1014                         } else if (dlm->mcol) {
1015                                 cp= (unsigned char*) &dlm->mcol[a*4];
1016                         }
1017                 }
1018
1019                 if (!(mf->flag&ME_SMOOTH)) {
1020                         glNormal3fv(&nors[a*3]);
1021                 }
1022
1023                 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
1024                 if (tface) glTexCoord2fv(tface->uv[0]);
1025                 if (cp) glColor3ub(cp[3], cp[2], cp[1]);
1026                 if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v1].no);
1027                 glVertex3fv((mvert+mf->v1)->co);
1028                         
1029                 if (tface) glTexCoord2fv(tface->uv[1]);
1030                 if (cp) glColor3ub(cp[7], cp[6], cp[5]);
1031                 if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v2].no);
1032                 glVertex3fv((mvert+mf->v2)->co);
1033
1034                 if (tface) glTexCoord2fv(tface->uv[2]);
1035                 if (cp) glColor3ub(cp[11], cp[10], cp[9]);
1036                 if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v3].no);
1037                 glVertex3fv((mvert+mf->v3)->co);
1038
1039                 if(mf->v4) {
1040                         if (tface) glTexCoord2fv(tface->uv[3]);
1041                         if (cp) glColor3ub(cp[15], cp[14], cp[13]);
1042                         if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v4].no);
1043                         glVertex3fv((mvert+mf->v4)->co);
1044                 }
1045                 glEnd();
1046
1047                 if (tface) tface++;
1048         }
1049 }
1050
1051 static int ssDM_getNumVerts(DerivedMesh *dm)
1052 {
1053         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1054
1055         return ssdm->dlm->totvert;
1056 }
1057 static int ssDM_getNumFaces(DerivedMesh *dm)
1058 {
1059         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1060
1061         return ssdm->dlm->totface;
1062 }
1063
1064 static DispListMesh *ssDM_convertToDispListMesh(DerivedMesh *dm)
1065 {
1066         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1067
1068         return displistmesh_copy(ssdm->dlm);
1069 }
1070
1071 static void ssDM_release(DerivedMesh *dm)
1072 {
1073         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
1074
1075         displistmesh_free(ssdm->dlm);
1076
1077         MEM_freeN(dm);
1078 }
1079
1080 DerivedMesh *derivedmesh_from_displistmesh(EditMesh *em, DispListMesh *dlm)
1081 {
1082         SSDerivedMesh *ssdm = MEM_mallocN(sizeof(*ssdm), "dm");
1083
1084         ssdm->dm.getNumVerts = ssDM_getNumVerts;
1085         ssdm->dm.getNumFaces = ssDM_getNumFaces;
1086         ssdm->dm.getMappedVertCoEM = ssDM_getMappedVertCoEM;
1087         ssdm->dm.convertToDispListMesh = ssDM_convertToDispListMesh;
1088
1089         ssdm->dm.drawVerts = ssDM_drawVerts;
1090         ssdm->dm.drawMappedVertEM = ssDM_drawMappedVertEM;
1091         ssdm->dm.drawMappedVertsEM = ssDM_drawMappedVertsEM;
1092         ssdm->dm.drawMappedVertsEMSelect = ssDM_drawMappedVertsEMSelect;
1093
1094         ssdm->dm.drawEdges = ssDM_drawEdges;
1095         ssdm->dm.drawMappedEdges = ssDM_drawMappedEdges;
1096         ssdm->dm.drawLooseEdges = ssDM_drawLooseEdges;
1097         ssdm->dm.drawMappedEdgeEM = ssDM_drawMappedEdgeEM;
1098         ssdm->dm.drawMappedEdgesEM = ssDM_drawMappedEdgesEM;
1099         ssdm->dm.drawMappedEdgesEMSelect = ssDM_drawMappedEdgesEMSelect;
1100         ssdm->dm.drawMappedFacesEMSelect = ssDM_drawMappedFacesEMSelect;
1101
1102         ssdm->dm.drawFacesSolid = ssDM_drawFacesSolid;
1103         ssdm->dm.drawFacesColored = ssDM_drawFacesColored;
1104         ssdm->dm.drawFacesTex = ssDM_drawFacesTex;
1105         ssdm->dm.drawFacesEM = ssDM_drawFacesEM;
1106
1107         ssdm->dm.release = ssDM_release;
1108         
1109         ssdm->dlm = dlm;
1110         ssdm->em = em;
1111
1112         return (DerivedMesh*) ssdm;
1113 }
1114
1115 ///
1116
1117 static void build_mesh_data(Object *ob)
1118 {
1119         Mesh *me = ob->data;
1120
1121         if(ob->disp.first==NULL) {
1122                 if(ob->parent && ob->partype==PARSKEL) makeDispList(ob);
1123                 else if(ob->parent && ob->parent->type==OB_LATTICE) makeDispList(ob);
1124                 else if(ob->hooks.first) makeDispList(ob);
1125                 else if(ob->softflag & 0x01) makeDispList(ob);
1126                 else if(ob->effect.first) {
1127                         Effect *eff= ob->effect.first;
1128                         if(eff->type==EFF_WAVE) makeDispList(ob);
1129                 }
1130         }
1131         if(me->disp.first==NULL && mesh_uses_displist(me)) {
1132                 makeDispList(ob);
1133         }
1134
1135         if(!me->disp.first || !((DispList*) me->disp.first)->nors) {
1136                 addnormalsDispList(ob, &me->disp);
1137         }
1138 }
1139
1140 DerivedMesh *mesh_get_derived(Object *ob)
1141 {
1142         Mesh *me= ob->data;
1143
1144         if (mesh_uses_displist(me)) {
1145                 build_mesh_data(ob);
1146
1147                 return me->derived;
1148         } 
1149
1150         return NULL;
1151 }
1152
1153 DerivedMesh *mesh_get_derived_render(Object *ob, int *needsFree)
1154 {
1155         Mesh *me= ob->data;
1156
1157         if (mesh_uses_displist(me)) {
1158                 if (me->subdiv==me->subdivr) {
1159                         *needsFree = 0;
1160                         return me->derived;
1161                 } else {
1162                         *needsFree = 1;
1163                         if(G.obedit && me==G.obedit->data) {
1164                                 return subsurf_make_derived_from_editmesh(G.editMesh, me->subdivr, me->flag, me->subsurftype);
1165                         } else {
1166                                 return subsurf_make_derived_from_mesh(me, me->subdivr, me->flag);
1167                         }
1168                 }
1169         }
1170
1171         return NULL;
1172 }
1173
1174 DerivedMesh *mesh_get_base_derived(Object *ob)
1175 {
1176         Mesh *me= ob->data;
1177
1178                 /* Build's extverts, nors */
1179         build_mesh_data(ob);
1180
1181         if (G.obedit && me==G.obedit->data) {
1182                 return getEditMeshDerivedMesh(G.editMesh);
1183         } else {
1184                 DispList *meDL = me->disp.first;
1185                 DispList *dl = find_displist(&ob->disp, DL_VERTS);
1186                 return getMeshDerivedMesh(ob, dl?dl->verts:NULL, meDL?meDL->nors:NULL);
1187         }
1188 }
1189
1190 DerivedMesh *mesh_get_cage_derived(struct Object *ob, int *needsFree)
1191 {
1192         Mesh *me= ob->data;
1193         DerivedMesh *dm = NULL;
1194
1195         *needsFree = 0;
1196
1197         if (me->flag&ME_OPT_EDGES) {
1198                 dm = mesh_get_derived(ob);
1199         }
1200         if (!dm) {
1201                 *needsFree = 1;
1202                 dm = mesh_get_base_derived(ob);
1203         }
1204
1205         return dm;
1206 }