- remove calls to showkeypos from exit editmode functions, should be
[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 #include "DNA_object_force.h"
44
45 #include "BLI_blenlib.h"
46 #include "BLI_editVert.h"
47
48 #include "BKE_DerivedMesh.h"
49 #include "BKE_displist.h"
50 #include "BKE_effect.h"
51 #include "BKE_global.h"
52 #include "BKE_material.h"
53 #include "BKE_mesh.h"
54 #include "BKE_object.h"
55 #include "BKE_subsurf.h"
56
57 #include "BIF_gl.h"
58 #include "BIF_glutil.h"
59
60 ///////////////////////////////////
61 ///////////////////////////////////
62
63 typedef struct {
64         DerivedMesh dm;
65
66         Object *ob;
67         float *extverts, *nors;
68 } MeshDerivedMesh;
69
70 static float *meshDM__getVertCo(MeshDerivedMesh *mdm, int index)
71 {
72         if (mdm->extverts) {
73                 return mdm->extverts+3*index;
74         } else {
75                 return ((Mesh*) mdm->ob->data)->mvert[index].co;
76         }
77 }
78
79 static void meshDM_drawVerts(DerivedMesh *dm)
80 {
81         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
82         Mesh *me = mdm->ob->data;
83         int a, start=0, end=me->totvert;
84
85         set_buildvars(mdm->ob, &start, &end);
86
87         glBegin(GL_POINTS);
88         for(a= start; a<end; a++) {
89                 glVertex3fv(meshDM__getVertCo(mdm, a));
90         }
91         glEnd();
92 }
93 static void meshDM_drawEdges(DerivedMesh *dm)
94 {
95         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
96         Mesh *me= mdm->ob->data;
97         int a, start= 0, end= me->totface;
98         MFace *mface = me->mface;
99
100         set_buildvars(mdm->ob, &start, &end);
101         mface+= start;
102         
103                 // edges can't cope with buildvars, draw with
104                 // faces if build is in use.
105         if(me->medge && start==0 && end==me->totface) {
106                 MEdge *medge= me->medge;
107                 
108                 glBegin(GL_LINES);
109                 for(a=me->totedge; a>0; a--, medge++) {
110                         if(medge->flag & ME_EDGEDRAW) {
111                                 glVertex3fv(meshDM__getVertCo(mdm, medge->v1));
112                                 glVertex3fv(meshDM__getVertCo(mdm, medge->v2));
113                         }
114                 }
115                 glEnd();
116         }
117         else {
118                 glBegin(GL_LINES);
119                 for(a=start; a<end; a++, mface++) {
120                         int test= mface->edcode;
121                         
122                         if(test) {
123                                 if(test&ME_V1V2){
124                                         glVertex3fv(meshDM__getVertCo(mdm, mface->v1));
125                                         glVertex3fv(meshDM__getVertCo(mdm, mface->v2));
126                                 }
127
128                                 if(mface->v3) {
129                                         if(test&ME_V2V3){
130                                                 glVertex3fv(meshDM__getVertCo(mdm, mface->v2));
131                                                 glVertex3fv(meshDM__getVertCo(mdm, mface->v3));
132                                         }
133
134                                         if (mface->v4) {
135                                                 if(test&ME_V3V4){
136                                                         glVertex3fv(meshDM__getVertCo(mdm, mface->v3));
137                                                         glVertex3fv(meshDM__getVertCo(mdm, mface->v4));
138                                                 }
139                                                 if(test&ME_V4V1){
140                                                         glVertex3fv(meshDM__getVertCo(mdm, mface->v4));
141                                                         glVertex3fv(meshDM__getVertCo(mdm, mface->v1));
142                                                 }
143                                         } else {
144                                                 if(test&ME_V3V1){
145                                                         glVertex3fv(meshDM__getVertCo(mdm, mface->v3));
146                                                         glVertex3fv(meshDM__getVertCo(mdm, mface->v1));
147                                                 }
148                                         }
149                                 }
150                         }
151                 }
152                 glEnd();
153         }
154 }
155 static void meshDM_drawLooseEdges(DerivedMesh *dm)
156 {
157         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
158         Mesh *me = mdm->ob->data;
159         MFace *mface= me->mface;
160         int a, start=0, end=me->totface;
161
162         set_buildvars(mdm->ob, &start, &end);
163         mface+= start;
164                 
165         glBegin(GL_LINES);
166         for(a=start; a<end; a++, mface++) {
167                 if(!mface->v3) {
168                         glVertex3fv(meshDM__getVertCo(mdm, mface->v3));
169                         glVertex3fv(meshDM__getVertCo(mdm, mface->v4));
170                 } 
171         }
172         glEnd();
173 }
174 static void meshDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int))
175 {
176         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
177         Mesh *me = mdm->ob->data;
178         MVert *mvert= me->mvert;
179         MFace *mface= me->mface;
180         float *nors = mdm->nors;
181         int a, start=0, end=me->totface;
182         int glmode=-1, shademodel=-1, matnr=-1, drawCurrentMat=1;
183
184         set_buildvars(mdm->ob, &start, &end);
185         mface+= start;
186         
187 #define PASSVERT(index, punoBit) {                              \
188         if (shademodel==GL_SMOOTH) {                            \
189                 short *no = (mvert+index)->no;                  \
190                 if (mface->puno&punoBit) {                              \
191                         glNormal3s(-no[0], -no[1], -no[2]); \
192                 } else {                                                                \
193                         glNormal3sv(no);                                        \
194                 }                                                                               \
195         }                                                                                       \
196         glVertex3fv(meshDM__getVertCo(mdm,index));      \
197 }
198
199         glBegin(glmode=GL_QUADS);
200         for(a=start; a<end; a++, mface++, nors+=3) {
201                 if(mface->v3) {
202                         int new_glmode, new_matnr, new_shademodel;
203                                 
204                         new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
205                         new_matnr = mface->mat_nr+1;
206                         new_shademodel = (!(me->flag&ME_AUTOSMOOTH) && (mface->flag & ME_SMOOTH))?GL_SMOOTH:GL_FLAT;
207                         
208                         if (new_glmode!=glmode || new_matnr!=matnr || new_shademodel!=shademodel) {
209                                 glEnd();
210
211                                 drawCurrentMat = setMaterial(matnr=new_matnr);
212
213                                 glShadeModel(shademodel=new_shademodel);
214                                 glBegin(glmode=new_glmode);
215                         } 
216                         
217                         if (drawCurrentMat) {
218                                 if(shademodel==GL_FLAT) 
219                                         glNormal3fv(nors);
220
221                                 PASSVERT(mface->v1, ME_FLIPV1);
222                                 PASSVERT(mface->v2, ME_FLIPV2);
223                                 PASSVERT(mface->v3, ME_FLIPV3);
224                                 if (mface->v4) {
225                                         PASSVERT(mface->v4, ME_FLIPV4);
226                                 }
227                         }
228                 }
229         }
230         glEnd();
231
232         glShadeModel(GL_FLAT);
233 #undef PASSVERT
234 }
235
236 static void meshDM_drawFacesColored(DerivedMesh *dm, int useTwoSide, unsigned char *col1, unsigned char *col2)
237 {
238         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
239         Object *ob= mdm->ob;
240         Mesh *me= ob->data;
241         MFace *mface= me->mface;
242         int a, glmode, start=0, end=me->totface;
243         unsigned char *cp1, *cp2;
244
245         set_buildvars(ob, &start, &end);
246         mface+= start;
247         col1+= 4*start;
248         if(col2) col2+= 4*start;
249         
250         cp1= col1;
251         if(col2) {
252                 cp2= col2;
253         } else {
254                 cp2= NULL;
255                 useTwoSide= 0;
256         }
257
258         /* there's a conflict here... twosided colors versus culling...? */
259         /* defined by history, only texture faces have culling option */
260         /* we need that as mesh option builtin, next to double sided lighting */
261         if(col1 && col2)
262                 glEnable(GL_CULL_FACE);
263         
264         glShadeModel(GL_SMOOTH);
265         glBegin(glmode=GL_QUADS);
266         for(a=start; a<end; a++, mface++, cp1+= 16) {
267                 if(mface->v3) {
268                         int new_glmode= mface->v4?GL_QUADS:GL_TRIANGLES;
269
270                         if (new_glmode!=glmode) {
271                                 glEnd();
272                                 glBegin(glmode= new_glmode);
273                         }
274                                 
275                         glColor3ub(cp1[3], cp1[2], cp1[1]);
276                         glVertex3fv( meshDM__getVertCo(mdm,mface->v1) );
277                         glColor3ub(cp1[7], cp1[6], cp1[5]);
278                         glVertex3fv( meshDM__getVertCo(mdm,mface->v2) );
279                         glColor3ub(cp1[11], cp1[10], cp1[9]);
280                         glVertex3fv( meshDM__getVertCo(mdm,mface->v3) );
281                         if(mface->v4) {
282                                 glColor3ub(cp1[15], cp1[14], cp1[13]);
283                                 glVertex3fv( meshDM__getVertCo(mdm,mface->v4) );
284                         }
285                                 
286                         if(useTwoSide) {
287                                 glColor3ub(cp2[11], cp2[10], cp2[9]);
288                                 glVertex3fv( meshDM__getVertCo(mdm,mface->v3) );
289                                 glColor3ub(cp2[7], cp2[6], cp2[5]);
290                                 glVertex3fv( meshDM__getVertCo(mdm,mface->v2) );
291                                 glColor3ub(cp2[3], cp2[2], cp2[1]);
292                                 glVertex3fv( meshDM__getVertCo(mdm,mface->v1) );
293                                 if(mface->v4) {
294                                         glColor3ub(cp2[15], cp2[14], cp2[13]);
295                                         glVertex3fv( meshDM__getVertCo(mdm,mface->v4) );
296                                 }
297                         }
298                 }
299                 if(col2) cp2+= 16;
300         }
301         glEnd();
302
303         glShadeModel(GL_FLAT);
304         glDisable(GL_CULL_FACE);
305 }
306
307 static void meshDM_drawFacesTex(DerivedMesh *dm, int (*setDrawParams)(TFace *tf, int matnr)) 
308 {
309         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
310         Mesh *me = mdm->ob->data;
311         MVert *mvert= me->mvert;
312         MFace *mface= me->mface;
313         TFace *tface = me->tface;
314         float *nors = mdm->nors;
315         int a, start=0, end=me->totface;
316
317         set_buildvars(mdm->ob, &start, &end);
318         
319         for (a=start; a<end; a++) {
320                 MFace *mf= &mface[a];
321                 TFace *tf = tface?&tface[a]:NULL;
322                 unsigned char *cp= NULL;
323                 
324                 if(mf->v3==0) continue;
325                 if(tf && ((tf->flag&TF_HIDE) || (tf->mode&TF_INVISIBLE))) continue;
326
327                 if (setDrawParams(tf, mf->mat_nr)) {
328                         if (tf) {
329                                 cp= (unsigned char *) tf->col;
330                         } else if (me->mcol) {
331                                 cp= (unsigned char *) &me->mcol[a*4];
332                         }
333                 }
334
335                 if (!(mf->flag&ME_SMOOTH)) {
336                         glNormal3fv(&nors[a*3]);
337                 }
338
339                 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
340                 if (tf) glTexCoord2fv(tf->uv[0]);
341                 if (cp) glColor3ub(cp[3], cp[2], cp[1]);
342                 if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v1].no);
343                 glVertex3fv(meshDM__getVertCo(mdm, mf->v1));
344                         
345                 if (tf) glTexCoord2fv(tf->uv[1]);
346                 if (cp) glColor3ub(cp[7], cp[6], cp[5]);
347                 if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v2].no);
348                 glVertex3fv(meshDM__getVertCo(mdm, mf->v2));
349
350                 if (tf) glTexCoord2fv(tf->uv[2]);
351                 if (cp) glColor3ub(cp[11], cp[10], cp[9]);
352                 if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v3].no);
353                 glVertex3fv(meshDM__getVertCo(mdm, mf->v3));
354
355                 if(mf->v4) {
356                         if (tf) glTexCoord2fv(tf->uv[3]);
357                         if (cp) glColor3ub(cp[15], cp[14], cp[13]);
358                         if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v4].no);
359                         glVertex3fv(meshDM__getVertCo(mdm, mf->v4));
360                 }
361                 glEnd();
362         }
363 }
364 static int meshDM_getNumVerts(DerivedMesh *dm)
365 {
366         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
367         Mesh *me = mdm->ob->data;
368
369         return me->totvert;
370 }
371 static int meshDM_getNumFaces(DerivedMesh *dm)
372 {
373         MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
374         Mesh *me = mdm->ob->data;
375
376         return me->totface;
377 }
378
379 static DerivedMesh *getMeshDerivedMesh(Object *ob, float *extverts, float *nors)
380 {
381         MeshDerivedMesh *mdm = MEM_callocN(sizeof(*mdm), "dm");
382
383         mdm->dm.getNumVerts = meshDM_getNumVerts;
384         mdm->dm.getNumFaces = meshDM_getNumFaces;
385
386         mdm->dm.drawVerts = meshDM_drawVerts;
387
388         mdm->dm.drawEdges = meshDM_drawEdges;
389         mdm->dm.drawMappedEdges = meshDM_drawEdges;
390         mdm->dm.drawLooseEdges = meshDM_drawLooseEdges;
391
392         mdm->dm.drawFacesSolid = meshDM_drawFacesSolid;
393         mdm->dm.drawFacesColored = meshDM_drawFacesColored;
394         mdm->dm.drawFacesTex = meshDM_drawFacesTex;
395
396         mdm->dm.release = (void(*)(DerivedMesh*)) MEM_freeN;
397         
398         mdm->ob = ob;
399         mdm->extverts = extverts;
400         mdm->nors = nors;
401
402         return (DerivedMesh*) mdm;
403 }
404
405 ///
406
407 typedef struct {
408         DerivedMesh dm;
409
410         EditMesh *em;
411 } EditMeshDerivedMesh;
412
413 static void emDM_getMappedVertCoEM(DerivedMesh *dm, void *vert, float co_r[3])
414 {
415         EditVert *eve = vert;
416
417         co_r[0] = eve->co[0];
418         co_r[1] = eve->co[1];
419         co_r[2] = eve->co[2];
420 }
421 static void emDM_drawMappedVertsEM(DerivedMesh *dm, int (*setDrawOptions)(void *userData, EditVert *vert), void *userData)
422 {
423         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
424         EditVert *eve;
425
426         bglBegin(GL_POINTS);
427         for(eve= emdm->em->verts.first; eve; eve= eve->next) {
428                 if(!setDrawOptions || setDrawOptions(userData, eve))
429                         bglVertex3fv(eve->co);
430         }
431         bglEnd();               
432 }
433 static void emDM_drawMappedEdgeEM(DerivedMesh *dm, void *edge)
434 {
435         EditEdge *eed = edge;
436
437         glBegin(GL_LINES);
438         glVertex3fv(eed->v1->co);
439         glVertex3fv(eed->v2->co);
440         glEnd();
441 }
442 static void emDM_drawMappedEdgesEM(DerivedMesh *dm, int (*setDrawOptions)(void *userData, EditEdge *edge), void *userData) 
443 {
444         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
445         EditEdge *eed;
446
447         glBegin(GL_LINES);
448         for(eed= emdm->em->edges.first; eed; eed= eed->next) {
449                 if(!setDrawOptions || setDrawOptions(userData, eed)) {
450                         glVertex3fv(eed->v1->co);
451                         glVertex3fv(eed->v2->co);
452                 }
453         }
454         glEnd();
455 }
456 static void emDM_drawMappedEdgesInterpEM(DerivedMesh *dm, int (*setDrawOptions)(void *userData, EditEdge *edge), void (*setDrawInterpOptions)(void *userData, EditEdge *edge, float t), void *userData) 
457 {
458         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
459         EditEdge *eed;
460
461         glBegin(GL_LINES);
462         for(eed= emdm->em->edges.first; eed; eed= eed->next) {
463                 if(!setDrawOptions || setDrawOptions(userData, eed)) {
464                         setDrawInterpOptions(userData, eed, 0.0);
465                         glVertex3fv(eed->v1->co);
466                         setDrawInterpOptions(userData, eed, 1.0);
467                         glVertex3fv(eed->v2->co);
468                 }
469         }
470         glEnd();
471 }
472 static void emDM_drawMappedFacesEM(DerivedMesh *dm, int (*setDrawOptions)(void *userData, EditFace *face), void *userData)
473 {
474         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
475         EditFace *efa;
476
477         for (efa= emdm->em->faces.first; efa; efa= efa->next) {
478                 if(!setDrawOptions || setDrawOptions(userData, efa)) {
479                         glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
480                         glVertex3fv(efa->v1->co);
481                         glVertex3fv(efa->v2->co);
482                         glVertex3fv(efa->v3->co);
483                         if(efa->v4) glVertex3fv(efa->v4->co);
484                         glEnd();
485                 }
486         }
487 }
488 static void emDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int))
489 {
490         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
491         EditFace *efa;
492
493         for (efa= emdm->em->faces.first; efa; efa= efa->next) {
494                 if(efa->h==0) {
495                         if (setMaterial(efa->mat_nr+1)) {
496                                 glNormal3fv(efa->n);
497                                 glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
498                                 glVertex3fv(efa->v1->co);
499                                 glVertex3fv(efa->v2->co);
500                                 glVertex3fv(efa->v3->co);
501                                 if(efa->v4) glVertex3fv(efa->v4->co);
502                                 glEnd();
503                         }
504                 }
505         }
506 }
507
508 static int emDM_getNumVerts(DerivedMesh *dm)
509 {
510         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
511
512         return BLI_countlist(&emdm->em->verts);
513 }
514 static int emDM_getNumFaces(DerivedMesh *dm)
515 {
516         EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
517
518         return BLI_countlist(&emdm->em->faces);
519 }
520
521 static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em)
522 {
523         EditMeshDerivedMesh *emdm = MEM_callocN(sizeof(*emdm), "dm");
524
525         emdm->dm.getNumVerts = emDM_getNumVerts;
526         emdm->dm.getNumFaces = emDM_getNumFaces;
527         emdm->dm.getMappedVertCoEM = emDM_getMappedVertCoEM;
528
529         emdm->dm.drawMappedVertsEM = emDM_drawMappedVertsEM;
530
531         emdm->dm.drawMappedEdgeEM = emDM_drawMappedEdgeEM;
532         emdm->dm.drawMappedEdgesEM = emDM_drawMappedEdgesEM;
533         emdm->dm.drawMappedEdgesInterpEM = emDM_drawMappedEdgesInterpEM;
534         
535         emdm->dm.drawFacesSolid = emDM_drawFacesSolid;
536         emdm->dm.drawMappedFacesEM = emDM_drawMappedFacesEM;
537
538         emdm->dm.release = (void(*)(DerivedMesh*)) MEM_freeN;
539         
540         emdm->em = em;
541
542         return (DerivedMesh*) emdm;
543 }
544
545 ///
546
547 typedef struct {
548         DerivedMesh dm;
549
550         DispListMesh *dlm;
551 } SSDerivedMesh;
552
553 static void ssDM_drawMappedEdges(DerivedMesh *dm)
554 {
555         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
556         DispListMesh *dlm = ssdm->dlm;
557         MEdge *medge= dlm->medge;
558         MVert *mvert= dlm->mvert;
559         int a;
560         
561         glBegin(GL_LINES);
562         for (a=0; a<dlm->totedge; a++, medge++) {
563                 if (medge->flag&ME_EDGEDRAW) {
564                         glVertex3fv(mvert[medge->v1].co); 
565                         glVertex3fv(mvert[medge->v2].co);
566                 }
567         }
568         glEnd();
569 }
570
571 static void ssDM_drawLooseEdges(DerivedMesh *dm)
572 {
573         /* Can't implement currently */ 
574 }
575
576 static void ssDM_drawVerts(DerivedMesh *dm)
577 {
578         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
579         DispListMesh *dlm = ssdm->dlm;
580         MVert *mvert= dlm->mvert;
581         int i;
582
583         bglBegin(GL_POINTS);
584         for (i=0; i<dlm->totvert; i++) {
585                 bglVertex3fv(mvert[i].co);
586         }
587         bglEnd();
588 }
589 static void ssDM_drawEdges(DerivedMesh *dm) 
590 {
591         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
592         DispListMesh *dlm = ssdm->dlm;
593         MVert *mvert= dlm->mvert;
594         int i;
595
596         if (dlm->medge) {
597                 MEdge *medge= dlm->medge;
598         
599                 glBegin(GL_LINES);
600                 for (i=0; i<dlm->totedge; i++, medge++) {
601                         glVertex3fv(mvert[medge->v1].co); 
602                         glVertex3fv(mvert[medge->v2].co);
603                 }
604                 glEnd();
605         } else {
606                 MFace *mface= dlm->mface;
607
608                 glBegin(GL_LINES);
609                 for (i=0; i<dlm->totface; i++, mface++) {
610                         glVertex3fv(mvert[mface->v1].co);
611                         glVertex3fv(mvert[mface->v2].co);
612
613                         if (mface->v3) {
614                                 glVertex3fv(mvert[mface->v2].co);
615                                 glVertex3fv(mvert[mface->v3].co);
616
617                                 glVertex3fv(mvert[mface->v3].co);
618                                 if (mface->v4) {
619                                         glVertex3fv(mvert[mface->v4].co);
620
621                                         glVertex3fv(mvert[mface->v4].co);
622                                 }
623                                 glVertex3fv(mvert[mface->v1].co);
624                         }
625                 }
626                 glEnd();
627         }
628 }
629 static void ssDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int))
630 {
631         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
632         DispListMesh *dlm = ssdm->dlm;
633         float *nors = dlm->nors;
634         int glmode=-1, shademodel=-1, matnr=-1, drawCurrentMat=1;
635         int i;
636
637 #define PASSVERT(ind) {                                         \
638         if (shademodel==GL_SMOOTH)                              \
639                 glNormal3sv(dlm->mvert[(ind)].no);      \
640         glVertex3fv(dlm->mvert[(ind)].co);              \
641 }
642
643         glBegin(glmode=GL_QUADS);
644         for (i=0; i<dlm->totface; i++) {
645                 MFace *mf= &dlm->mface[i];
646                 
647                 if (mf->v3) {
648                         int new_glmode = mf->v4?GL_QUADS:GL_TRIANGLES;
649                         int new_shademodel = (mf->flag&ME_SMOOTH)?GL_SMOOTH:GL_FLAT;
650                         int new_matnr = mf->mat_nr+1;
651                         
652                         if(new_glmode!=glmode || new_shademodel!=shademodel || new_matnr!=matnr) {
653                                 glEnd();
654
655                                 drawCurrentMat = setMaterial(matnr=new_matnr);
656
657                                 glShadeModel(shademodel=new_shademodel);
658                                 glBegin(glmode=new_glmode);
659                         }
660                         
661                         if (drawCurrentMat) {
662                                 if (shademodel==GL_FLAT)
663                                         glNormal3fv(&nors[i*3]);
664                                         
665                                 PASSVERT(mf->v1);
666                                 PASSVERT(mf->v2);
667                                 PASSVERT(mf->v3);
668                                 if (mf->v4)
669                                         PASSVERT(mf->v4);
670                         }
671                 }
672         }
673         glEnd();
674         
675 #undef PASSVERT
676 }
677 static void ssDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *vcols1, unsigned char *vcols2)
678 {
679         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
680         DispListMesh *dlm = ssdm->dlm;
681         int i, lmode;
682         
683         glShadeModel(GL_SMOOTH);
684         if (vcols2) {
685                 glEnable(GL_CULL_FACE);
686         } else {
687                 useTwoSided = 0;
688         }
689                 
690 #define PASSVERT(vidx, fidx) {                                  \
691         unsigned char *col= &colbase[fidx*4];           \
692         glColor3ub(col[3], col[2], col[1]);                     \
693         glVertex3fv(dlm->mvert[(vidx)].co);                     \
694 }
695
696         glBegin(lmode= GL_QUADS);
697         for (i=0; i<dlm->totface; i++) {
698                 MFace *mf= &dlm->mface[i];
699                 
700                 if (mf->v3) {
701                         int nmode= mf->v4?GL_QUADS:GL_TRIANGLES;
702                         unsigned char *colbase= &vcols1[i*16];
703                         
704                         if (nmode!=lmode) {
705                                 glEnd();
706                                 glBegin(lmode= nmode);
707                         }
708                         
709                         PASSVERT(mf->v1, 0);
710                         PASSVERT(mf->v2, 1);
711                         PASSVERT(mf->v3, 2);
712                         if (mf->v4)
713                                 PASSVERT(mf->v4, 3);
714                         
715                         if (useTwoSided) {
716                                 unsigned char *colbase= &vcols2[i*16];
717
718                                 if (mf->v4)
719                                         PASSVERT(mf->v4, 3);
720                                 PASSVERT(mf->v3, 2);
721                                 PASSVERT(mf->v2, 1);
722                                 PASSVERT(mf->v1, 0);
723                         }
724                 }
725         }
726         glEnd();
727
728         if (vcols2)
729                 glDisable(GL_CULL_FACE);
730         
731 #undef PASSVERT
732 }
733 static void ssDM_drawFacesTex(DerivedMesh *dm, int (*setDrawParams)(TFace *tf, int matnr)) 
734 {
735         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
736         DispListMesh *dlm = ssdm->dlm;
737         MVert *mvert= dlm->mvert;
738         MFace *mface= dlm->mface;
739         TFace *tface = dlm->tface;
740         float *nors = dlm->nors;
741         int a;
742         
743         for (a=0; a<dlm->totface; a++) {
744                 MFace *mf= &mface[a];
745                 TFace *tf = tface?&tface[a]:NULL;
746                 unsigned char *cp= NULL;
747                 
748                 if(mf->v3==0) continue;
749                 if(tf && ((tf->flag&TF_HIDE) || (tf->mode&TF_INVISIBLE))) continue;
750
751                 if (setDrawParams(tf, mf->mat_nr)) {
752                         if (tf) {
753                                 cp= (unsigned char*) tf->col;
754                         } else if (dlm->mcol) {
755                                 cp= (unsigned char*) &dlm->mcol[a*4];
756                         }
757                 }
758
759                 if (!(mf->flag&ME_SMOOTH)) {
760                         glNormal3fv(&nors[a*3]);
761                 }
762
763                 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
764                 if (tf) glTexCoord2fv(tf->uv[0]);
765                 if (cp) glColor3ub(cp[3], cp[2], cp[1]);
766                 if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v1].no);
767                 glVertex3fv((mvert+mf->v1)->co);
768                         
769                 if (tf) glTexCoord2fv(tf->uv[1]);
770                 if (cp) glColor3ub(cp[7], cp[6], cp[5]);
771                 if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v2].no);
772                 glVertex3fv((mvert+mf->v2)->co);
773
774                 if (tf) glTexCoord2fv(tf->uv[2]);
775                 if (cp) glColor3ub(cp[11], cp[10], cp[9]);
776                 if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v3].no);
777                 glVertex3fv((mvert+mf->v3)->co);
778
779                 if(mf->v4) {
780                         if (tf) glTexCoord2fv(tf->uv[3]);
781                         if (cp) glColor3ub(cp[15], cp[14], cp[13]);
782                         if (mf->flag&ME_SMOOTH) glNormal3sv(mvert[mf->v4].no);
783                         glVertex3fv((mvert+mf->v4)->co);
784                 }
785                 glEnd();
786         }
787 }
788
789 static int ssDM_getNumVerts(DerivedMesh *dm)
790 {
791         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
792
793         return ssdm->dlm->totvert;
794 }
795 static int ssDM_getNumFaces(DerivedMesh *dm)
796 {
797         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
798
799         return ssdm->dlm->totface;
800 }
801
802 static DispListMesh *ssDM_convertToDispListMesh(DerivedMesh *dm)
803 {
804         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
805
806         return displistmesh_copy(ssdm->dlm);
807 }
808
809 static void ssDM_release(DerivedMesh *dm)
810 {
811         SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
812
813         displistmesh_free(ssdm->dlm);
814
815         MEM_freeN(dm);
816 }
817
818 DerivedMesh *derivedmesh_from_displistmesh(DispListMesh *dlm)
819 {
820         SSDerivedMesh *ssdm = MEM_callocN(sizeof(*ssdm), "dm");
821
822         ssdm->dm.getNumVerts = ssDM_getNumVerts;
823         ssdm->dm.getNumFaces = ssDM_getNumFaces;
824         ssdm->dm.convertToDispListMesh = ssDM_convertToDispListMesh;
825
826         ssdm->dm.drawVerts = ssDM_drawVerts;
827
828         ssdm->dm.drawEdges = ssDM_drawEdges;
829         ssdm->dm.drawMappedEdges = ssDM_drawMappedEdges;
830         ssdm->dm.drawLooseEdges = ssDM_drawLooseEdges;
831
832         ssdm->dm.drawFacesSolid = ssDM_drawFacesSolid;
833         ssdm->dm.drawFacesColored = ssDM_drawFacesColored;
834         ssdm->dm.drawFacesTex = ssDM_drawFacesTex;
835
836         ssdm->dm.release = ssDM_release;
837         
838         ssdm->dlm = dlm;
839
840         return (DerivedMesh*) ssdm;
841 }
842
843 ///
844
845 static void build_mesh_data(Object *ob, int inEditMode)
846 {
847         Mesh *me = ob->data;
848
849                 /* Inside edit mode mesh modifiers aren't calculated */
850         if(ob->disp.first==NULL && !inEditMode) { 
851                 if (    (ob->parent && (ob->partype==PARSKEL || ob->parent->type==OB_LATTICE)) ||
852                                 ob->hooks.first ||
853                                 (ob->softflag & OB_SB_ENABLE) ||
854                                 (ob->effect.first && ((Effect*) ob->effect.first)->type==EFF_WAVE))
855                         makeDispListMesh(ob);
856         }
857
858         if ((me->flag&ME_SUBSURF) && me->subdiv) {
859                 if(inEditMode && !G.editMesh->derived) {
860                         makeDispListMesh(ob);
861                 } else if (!inEditMode && !me->derived) {
862                         makeDispListMesh(ob);
863                 }
864         }
865
866         if(!me->disp.first || !((DispList*) me->disp.first)->nors) {
867                 addnormalsDispList(ob, &me->disp);
868         }
869 }
870
871 DerivedMesh *mesh_get_derived(Object *ob)
872 {
873         Mesh *me= ob->data;
874
875         if ((me->flag&ME_SUBSURF) && me->subdiv) {
876                 build_mesh_data(ob, G.obedit && me==G.obedit->data);
877
878                 if(G.obedit && me==G.obedit->data) {
879                         return G.editMesh->derived;
880                 } else {
881                         return me->derived;
882                 }
883         } 
884
885         return NULL;
886 }
887
888 DerivedMesh *mesh_get_derived_render(Object *ob, int *needsFree)
889 {
890         Mesh *me= ob->data;
891
892         if ((me->flag&ME_SUBSURF) && me->subdivr) {
893                 if (me->subdiv==me->subdivr) {
894                         *needsFree = 0;
895
896                                 // Don't reuse cache in editmode, we need to guarantee
897                                 // order of result and the incremental syncing messes
898                                 // with this (could be fixed). - zr
899                         if(!(G.obedit && me==G.obedit->data)) {
900                                 return me->derived;
901                         }
902                 } 
903
904                 *needsFree = 1;
905                 if(G.obedit && me==G.obedit->data) {
906                         return subsurf_make_derived_from_editmesh(G.editMesh, me->subdivr, me->subsurftype, NULL);
907                 } else {
908                         return subsurf_make_derived_from_mesh(me, me->subdivr);
909                 }
910         }
911
912         return NULL;
913 }
914
915 DerivedMesh *mesh_get_base_derived(Object *ob)
916 {
917         Mesh *me= ob->data;
918
919         build_mesh_data(ob, G.obedit && me==G.obedit->data);
920
921                 /* Build's extverts, nors */
922         if (G.obedit && me==G.obedit->data) {
923                 return getEditMeshDerivedMesh(G.editMesh);
924         } else {
925                 DispList *dl = find_displist(&ob->disp, DL_VERTS);
926                 DispList *meDL = me->disp.first;
927
928                 return getMeshDerivedMesh(ob, dl?dl->verts:NULL, meDL?meDL->nors:NULL);
929         }
930 }
931
932 DerivedMesh *mesh_get_cage_derived(struct Object *ob, int *needsFree)
933 {
934         Mesh *me= ob->data;
935         DerivedMesh *dm = NULL;
936
937         *needsFree = 0;
938
939         if (me->flag&ME_OPT_EDGES) {
940                 dm = mesh_get_derived(ob);
941         }
942         if (!dm) {
943                 *needsFree = 1;
944                 dm = mesh_get_base_derived(ob);
945         }
946
947         return dm;
948 }