4 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * The Original Code is Copyright (C) 2006 Blender Foundation.
21 * All rights reserved.
23 * The Original Code is: all of this file.
25 * Contributor(s): Ben Batt <benbatt@gmail.com>
27 * ***** END GPL LICENSE BLOCK *****
29 * Implementation of CDDerivedMesh.
31 * BKE_cdderivedmesh.h contains the function prototypes for this file.
35 /** \file blender/blenkernel/intern/cdderivedmesh.c
40 /* TODO maybe BIF_gl.h should include string.h? */
44 #include "BLI_blenlib.h"
45 #include "BLI_edgehash.h"
46 #include "BLI_editVert.h"
49 #include "BLI_utildefines.h"
51 #include "BKE_cdderivedmesh.h"
52 #include "BKE_global.h"
54 #include "BKE_paint.h"
57 #include "DNA_meshdata_types.h"
58 #include "DNA_object_types.h"
59 #include "DNA_curve_types.h" /* for Curve */
61 #include "MEM_guardedalloc.h"
63 #include "GPU_buffers.h"
65 #include "GPU_extensions.h"
66 #include "GPU_material.h"
75 /* these point to data in the DerivedMesh custom data layers,
76 they are only here for efficiency and convenience **/
85 /* Mesh connectivity */
86 struct ListBase *fmap;
87 struct IndexNode *fmap_mem;
90 /**************** DerivedMesh interface functions ****************/
91 static int cdDM_getNumVerts(DerivedMesh *dm)
93 return dm->numVertData;
96 static int cdDM_getNumEdges(DerivedMesh *dm)
98 return dm->numEdgeData;
101 static int cdDM_getNumFaces(DerivedMesh *dm)
103 return dm->numFaceData;
106 static void cdDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
108 CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
109 *vert_r = cddm->mvert[index];
112 static void cdDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
114 CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
115 *edge_r = cddm->medge[index];
118 static void cdDM_getFace(DerivedMesh *dm, int index, MFace *face_r)
120 CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
121 *face_r = cddm->mface[index];
124 static void cdDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
126 CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
127 memcpy(vert_r, cddm->mvert, sizeof(*vert_r) * dm->numVertData);
130 static void cdDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
132 CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
133 memcpy(edge_r, cddm->medge, sizeof(*edge_r) * dm->numEdgeData);
136 static void cdDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
138 CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
139 memcpy(face_r, cddm->mface, sizeof(*face_r) * dm->numFaceData);
142 static void cdDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
144 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
147 if (dm->numVertData) {
148 for (i=0; i<dm->numVertData; i++) {
149 DO_MINMAX(cddm->mvert[i].co, min_r, max_r);
152 min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
156 static void cdDM_getVertCo(DerivedMesh *dm, int index, float co_r[3])
158 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
160 VECCOPY(co_r, cddm->mvert[index].co);
163 static void cdDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
165 MVert *mv = CDDM_get_verts(dm);
168 for(i = 0; i < dm->numVertData; i++, mv++)
169 VECCOPY(cos_r[i], mv->co);
172 static void cdDM_getVertNo(DerivedMesh *dm, int index, float no_r[3])
174 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
175 normal_short_to_float_v3(no_r, cddm->mvert[index].no);
178 static ListBase *cdDM_getFaceMap(Object *ob, DerivedMesh *dm)
180 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
182 if(!cddm->fmap && ob->type == OB_MESH) {
185 create_vert_face_map(&cddm->fmap, &cddm->fmap_mem, me->mface,
186 me->totvert, me->totface);
192 static int can_pbvh_draw(Object *ob, DerivedMesh *dm)
194 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
198 /* active modifiers means extra deformation, which can't be handled correct
199 on bith of PBVH and sculpt "layer" levels, so use PBVH only for internal brush
200 stuff and show final DerivedMesh so user would see actual object shape */
201 deformed|= ob->sculpt->modifiers_active;
203 /* as in case with modifiers, we can't synchronize deformation made against
204 PBVH and non-locked keyblock, so also use PBVH only for brushes and
205 final DM to give final result to user */
206 deformed|= ob->sculpt->kb && (ob->shapeflag&OB_SHAPE_LOCK) == 0;
211 return (cddm->mvert == me->mvert) || ob->sculpt->kb;
214 static struct PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm)
216 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
225 if(ob->sculpt->pbvh) {
226 cddm->pbvh= ob->sculpt->pbvh;
227 cddm->pbvh_draw = can_pbvh_draw(ob, dm);
230 /* always build pbvh from original mesh, and only use it for drawing if
231 this derivedmesh is just original mesh. it's the multires subsurf dm
232 that this is actually for, to support a pbvh on a modified mesh */
233 if(!cddm->pbvh && ob->type == OB_MESH) {
234 SculptSession *ss= ob->sculpt;
236 cddm->pbvh = BLI_pbvh_new();
237 cddm->pbvh_draw = can_pbvh_draw(ob, dm);
238 BLI_pbvh_build_mesh(cddm->pbvh, me->mface, me->mvert,
239 me->totface, me->totvert);
241 if(ss->modifiers_active && ob->derivedDeform) {
242 DerivedMesh *deformdm= ob->derivedDeform;
246 totvert= deformdm->getNumVerts(deformdm);
247 vertCos= MEM_callocN(3*totvert*sizeof(float), "cdDM_getPBVH vertCos");
248 deformdm->getVertCos(deformdm, vertCos);
249 BLI_pbvh_apply_vertCos(cddm->pbvh, vertCos);
257 /* update vertex normals so that drawing smooth faces works during sculpt
258 TODO: proper fix is to support the pbvh in all drawing modes */
259 static void cdDM_update_normals_from_pbvh(DerivedMesh *dm)
261 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
262 float (*face_nors)[3];
264 if(!cddm->pbvh || !cddm->pbvh_draw || !dm->numFaceData)
267 face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
269 BLI_pbvh_update(cddm->pbvh, PBVH_UpdateNormals, face_nors);
272 static void cdDM_drawSelectedVerts(DerivedMesh *dm)
274 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
275 MVert *mv = cddm->mvert;
277 if( GPU_buffer_legacy(dm) ) {
278 char prev_sel= 0; /* always invalid */;
281 for(i = 0; i < dm->numVertData; i++, mv++) {
282 if(!(mv->flag & ME_HIDE)) {
283 const char sel= mv->flag & 1;
284 if(prev_sel != sel) {
287 // TODO define selected color
289 glColor3f(1.0f, 1.0f, 0.0f);
291 glColor3f(0.0f, 0.0f, 0.0f);
300 else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
301 GPU_vertex_setup(dm);
302 if( !GPU_buffer_legacy(dm) ) {
303 if(dm->drawObject->tot_triangle_point) glDrawArrays(GL_POINTS,0, dm->drawObject->tot_triangle_point);
304 else glDrawArrays(GL_POINTS,0, dm->drawObject->tot_loose_point);
310 static void cdDM_drawVerts(DerivedMesh *dm)
312 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
313 MVert *mv = cddm->mvert;
316 if( GPU_buffer_legacy(dm) ) {
318 for(i = 0; i < dm->numVertData; i++, mv++)
322 else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
323 GPU_vertex_setup(dm);
324 if( !GPU_buffer_legacy(dm) ) {
325 if(dm->drawObject->tot_triangle_point)
326 glDrawArrays(GL_POINTS,0, dm->drawObject->tot_triangle_point);
328 glDrawArrays(GL_POINTS,0, dm->drawObject->tot_loose_point);
334 static void cdDM_drawUVEdges(DerivedMesh *dm)
336 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
337 MFace *mf = cddm->mface;
338 MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
342 if( GPU_buffer_legacy(dm) ) {
344 for(i = 0; i < dm->numFaceData; i++, mf++, tf++) {
345 if(!(mf->flag&ME_HIDE)) {
346 glVertex2fv(tf->uv[0]);
347 glVertex2fv(tf->uv[1]);
349 glVertex2fv(tf->uv[1]);
350 glVertex2fv(tf->uv[2]);
353 glVertex2fv(tf->uv[2]);
354 glVertex2fv(tf->uv[0]);
356 glVertex2fv(tf->uv[2]);
357 glVertex2fv(tf->uv[3]);
359 glVertex2fv(tf->uv[3]);
360 glVertex2fv(tf->uv[0]);
372 GPU_uvedge_setup(dm);
373 if( !GPU_buffer_legacy(dm) ) {
374 for(i = 0; i < dm->numFaceData; i++, mf++) {
375 if(!(mf->flag&ME_HIDE)) {
381 if( prevdraw != draw ) {
382 if( prevdraw > 0 && (curpos-prevstart) > 0) {
383 glDrawArrays(GL_LINES,prevstart,curpos-prevstart);
395 if( prevdraw > 0 && (curpos-prevstart) > 0 ) {
396 glDrawArrays(GL_LINES,prevstart,curpos-prevstart);
404 static void cdDM_drawEdges(DerivedMesh *dm, int drawLooseEdges, int drawAllEdges)
406 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
407 MVert *mvert = cddm->mvert;
408 MEdge *medge = cddm->medge;
411 if( GPU_buffer_legacy(dm) ) {
412 DEBUG_VBO( "Using legacy code. cdDM_drawEdges\n" );
414 for(i = 0; i < dm->numEdgeData; i++, medge++) {
415 if((drawAllEdges || (medge->flag&ME_EDGEDRAW))
416 && (drawLooseEdges || !(medge->flag&ME_LOOSEEDGE))) {
417 glVertex3fv(mvert[medge->v1].co);
418 glVertex3fv(mvert[medge->v2].co);
423 else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
429 if( !GPU_buffer_legacy(dm) ) {
430 for(i = 0; i < dm->numEdgeData; i++, medge++) {
431 if((drawAllEdges || (medge->flag&ME_EDGEDRAW))
432 && (drawLooseEdges || !(medge->flag&ME_LOOSEEDGE))) {
438 if( prevdraw != draw ) {
439 if( prevdraw > 0 && (i-prevstart) > 0 ) {
440 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2 );
446 if( prevdraw > 0 && (i-prevstart) > 0 ) {
447 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2 );
454 static void cdDM_drawLooseEdges(DerivedMesh *dm)
456 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
457 MVert *mvert = cddm->mvert;
458 MEdge *medge = cddm->medge;
461 if( GPU_buffer_legacy(dm) ) {
462 DEBUG_VBO( "Using legacy code. cdDM_drawLooseEdges\n" );
464 for(i = 0; i < dm->numEdgeData; i++, medge++) {
465 if(medge->flag&ME_LOOSEEDGE) {
466 glVertex3fv(mvert[medge->v1].co);
467 glVertex3fv(mvert[medge->v2].co);
472 else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
478 if( !GPU_buffer_legacy(dm) ) {
479 for(i = 0; i < dm->numEdgeData; i++, medge++) {
480 if(medge->flag&ME_LOOSEEDGE) {
486 if( prevdraw != draw ) {
487 if( prevdraw > 0 && (i-prevstart) > 0) {
488 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2 );
494 if( prevdraw > 0 && (i-prevstart) > 0 ) {
495 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2 );
502 static void cdDM_drawFacesSolid(DerivedMesh *dm,
503 float (*partial_redraw_planes)[4],
504 int UNUSED(fast), int (*setMaterial)(int, void *attribs))
506 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
507 MVert *mvert = cddm->mvert;
508 MFace *mface = cddm->mface;
509 float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
510 int a, glmode = -1, shademodel = -1, matnr = -1, drawCurrentMat = 1;
512 #define PASSVERT(index) { \
513 if(shademodel == GL_SMOOTH) { \
514 short *no = mvert[index].no; \
517 glVertex3fv(mvert[index].co); \
520 if(cddm->pbvh && cddm->pbvh_draw) {
521 if(dm->numFaceData) {
522 float (*face_nors)[3] = CustomData_get_layer(&dm->faceData, CD_NORMAL);
524 /* should be per face */
525 if(!setMaterial(mface->mat_nr+1, NULL))
528 glShadeModel((mface->flag & ME_SMOOTH)? GL_SMOOTH: GL_FLAT);
529 BLI_pbvh_draw(cddm->pbvh, partial_redraw_planes, face_nors, (mface->flag & ME_SMOOTH));
530 glShadeModel(GL_FLAT);
536 if( GPU_buffer_legacy(dm) ) {
537 DEBUG_VBO( "Using legacy code. cdDM_drawFacesSolid\n" );
538 glBegin(glmode = GL_QUADS);
539 for(a = 0; a < dm->numFaceData; a++, mface++) {
540 int new_glmode, new_matnr, new_shademodel;
542 new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
543 new_matnr = mface->mat_nr + 1;
544 new_shademodel = (mface->flag & ME_SMOOTH)?GL_SMOOTH:GL_FLAT;
546 if(new_glmode != glmode || new_matnr != matnr
547 || new_shademodel != shademodel) {
550 drawCurrentMat = setMaterial(matnr = new_matnr, NULL);
552 glShadeModel(shademodel = new_shademodel);
553 glBegin(glmode = new_glmode);
557 if(shademodel == GL_FLAT) {
562 /* TODO make this better (cache facenormals as layer?) */
565 normal_quad_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co);
567 normal_tri_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co);
585 else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
586 GPU_vertex_setup( dm );
587 GPU_normal_setup( dm );
588 if( !GPU_buffer_legacy(dm) ) {
589 glShadeModel(GL_SMOOTH);
590 for( a = 0; a < dm->drawObject->totmaterial; a++ ) {
591 if( setMaterial(dm->drawObject->materials[a].mat_nr+1, NULL) )
592 glDrawArrays(GL_TRIANGLES, dm->drawObject->materials[a].start,
593 dm->drawObject->materials[a].totpoint);
596 GPU_buffer_unbind( );
600 glShadeModel(GL_FLAT);
603 static void cdDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2)
605 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
607 unsigned char *cp1, *cp2;
608 MVert *mvert = cddm->mvert;
609 MFace *mface = cddm->mface;
619 /* there's a conflict here... twosided colors versus culling...? */
620 /* defined by history, only texture faces have culling option */
621 /* we need that as mesh option builtin, next to double sided lighting */
623 glEnable(GL_CULL_FACE);
626 cdDM_update_normals_from_pbvh(dm);
628 if( GPU_buffer_legacy(dm) ) {
629 DEBUG_VBO( "Using legacy code. cdDM_drawFacesColored\n" );
630 glShadeModel(GL_SMOOTH);
631 glBegin(glmode = GL_QUADS);
632 for(a = 0; a < dm->numFaceData; a++, mface++, cp1 += 16) {
633 int new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
635 if(new_glmode != glmode) {
637 glBegin(glmode = new_glmode);
641 glVertex3fv(mvert[mface->v1].co);
643 glVertex3fv(mvert[mface->v2].co);
645 glVertex3fv(mvert[mface->v3].co);
648 glVertex3fv(mvert[mface->v4].co);
653 glVertex3fv(mvert[mface->v3].co );
655 glVertex3fv(mvert[mface->v2].co );
657 glVertex3fv(mvert[mface->v1].co );
660 glVertex3fv(mvert[mface->v4].co );
667 else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
668 GPU_color4_upload(dm,cp1);
669 GPU_vertex_setup(dm);
671 if( !GPU_buffer_legacy(dm) ) {
672 glShadeModel(GL_SMOOTH);
673 glDrawArrays(GL_TRIANGLES, 0, dm->drawObject->tot_triangle_point);
676 GPU_color4_upload(dm,cp2);
678 glCullFace(GL_FRONT);
679 glDrawArrays(GL_TRIANGLES, 0, dm->drawObject->tot_triangle_point);
686 glShadeModel(GL_FLAT);
687 glDisable(GL_CULL_FACE);
690 static void cdDM_drawFacesTex_common(DerivedMesh *dm,
691 int (*drawParams)(MTFace *tface, MCol *mcol, int matnr),
692 int (*drawParamsMapped)(void *userData, int index),
695 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
696 MVert *mv = cddm->mvert;
697 MFace *mf = DM_get_face_data_layer(dm, CD_MFACE);
698 MCol *realcol = dm->getFaceDataArray(dm, CD_TEXTURE_MCOL);
699 float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
700 MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
701 int i, j, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
702 int startFace = 0, lastFlag = 0xdeadbeef;
703 MCol *mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL);
705 mcol = dm->getFaceDataArray(dm, CD_MCOL);
707 cdDM_update_normals_from_pbvh(dm);
709 if( GPU_buffer_legacy(dm) ) {
710 DEBUG_VBO( "Using legacy code. cdDM_drawFacesTex_common\n" );
711 for(i = 0; i < dm->numFaceData; i++, mf++) {
714 unsigned char *cp = NULL;
717 flag = drawParams(tf? &tf[i]: NULL, mcol? &mcol[i*4]: NULL, mf->mat_nr);
722 if(orig == ORIGINDEX_NONE) { if(nors) nors += 3; continue; }
723 if(drawParamsMapped) flag = drawParamsMapped(userData, orig);
724 else { if(nors) nors += 3; continue; }
727 if(drawParamsMapped) flag = drawParamsMapped(userData, i);
728 else { if(nors) nors += 3; continue; }
733 cp= (unsigned char*) &mcol[i*4];
735 if(!(mf->flag&ME_SMOOTH)) {
742 normal_quad_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
744 normal_tri_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
750 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
751 if(tf) glTexCoord2fv(tf[i].uv[0]);
752 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
754 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
755 glVertex3fv(mvert->co);
757 if(tf) glTexCoord2fv(tf[i].uv[1]);
758 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
760 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
761 glVertex3fv(mvert->co);
763 if(tf) glTexCoord2fv(tf[i].uv[2]);
764 if(cp) glColor3ub(cp[11], cp[10], cp[9]);
766 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
767 glVertex3fv(mvert->co);
770 if(tf) glTexCoord2fv(tf[i].uv[3]);
771 if(cp) glColor3ub(cp[15], cp[14], cp[13]);
773 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
774 glVertex3fv(mvert->co);
781 } else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
786 GPU_vertex_setup( dm );
787 GPU_normal_setup( dm );
790 /*if( realcol && dm->drawObject->colType == CD_TEXTURE_MCOL ) {
792 } else if( mcol && dm->drawObject->colType == CD_MCOL ) {
797 unsigned char *colors = MEM_mallocN(dm->getNumFaces(dm)*4*3*sizeof(unsigned char), "cdDM_drawFacesTex_common");
798 for( i=0; i < dm->getNumFaces(dm); i++ ) {
799 for( j=0; j < 4; j++ ) {
800 colors[i*12+j*3] = col[i*4+j].r;
801 colors[i*12+j*3+1] = col[i*4+j].g;
802 colors[i*12+j*3+2] = col[i*4+j].b;
805 GPU_color3_upload(dm,colors);
808 dm->drawObject->colType = CD_TEXTURE_MCOL;
810 dm->drawObject->colType = CD_MCOL;
812 GPU_color_setup( dm );
815 if( !GPU_buffer_legacy(dm) ) {
816 /* warning!, this logic is incorrect, see bug [#27175]
817 * firstly, there are no checks for changes in context, such as texface image.
818 * secondly, drawParams() sets the GL context, so checking if there is a change
819 * from lastFlag is too late once glDrawArrays() runs, since drawing the arrays
820 * will use the modified, OpenGL settings.
822 * However its tricky to fix this without duplicating the internal logic
823 * of drawParams(), perhaps we need an argument like...
824 * drawParams(..., keep_gl_state_but_return_when_changed) ?.
826 * We could also just disable VBO's here, since texface may be deprecated - campbell.
829 glShadeModel( GL_SMOOTH );
831 for(i = 0; i < dm->drawObject->tot_triangle_point/3; i++) {
832 int actualFace = dm->drawObject->triangle_to_mface[i];
836 flag = drawParams(tf? &tf[actualFace]: NULL, mcol? &mcol[actualFace*4]: NULL, mf[actualFace].mat_nr);
840 orig = index[actualFace];
841 if(orig == ORIGINDEX_NONE) continue;
843 flag = drawParamsMapped(userData, orig);
847 flag = drawParamsMapped(userData, actualFace);
849 if( flag != lastFlag ) {
850 if( startFace < i ) {
851 if( lastFlag != 0 ) { /* if the flag is 0 it means the face is hidden or invisible */
852 if (lastFlag==1 && col)
856 glDrawArrays(GL_TRIANGLES,startFace*3,(i-startFace)*3);
863 if( startFace < dm->drawObject->tot_triangle_point/3 ) {
864 if( lastFlag != 0 ) { /* if the flag is 0 it means the face is hidden or invisible */
865 if (lastFlag==1 && col)
869 glDrawArrays(GL_TRIANGLES, startFace*3, dm->drawObject->tot_triangle_point - startFace*3);
875 glShadeModel( GL_FLAT );
879 static void cdDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, MCol *mcol, int matnr))
881 cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
884 static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors, int (*setMaterial)(int, void *attribs),
885 int (*compareDrawOptions)(void *userData, int cur_index, int next_index))
887 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
888 MVert *mv = cddm->mvert;
889 MFace *mf = cddm->mface;
891 float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
892 int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
894 mc = DM_get_face_data_layer(dm, CD_ID_MCOL);
896 mc = DM_get_face_data_layer(dm, CD_WEIGHT_MCOL);
898 mc = DM_get_face_data_layer(dm, CD_MCOL);
900 cdDM_update_normals_from_pbvh(dm);
902 /* back-buffer always uses legacy since VBO's would need the
903 * color array temporarily overwritten for drawing, then reset. */
904 if( GPU_buffer_legacy(dm) || G.f & G_BACKBUFSEL) {
905 DEBUG_VBO( "Using legacy code. cdDM_drawMappedFaces\n" );
906 for(i = 0; i < dm->numFaceData; i++, mf++) {
907 int drawSmooth = (mf->flag & ME_SMOOTH);
910 orig= (index==NULL) ? i : *index++;
912 if(orig == ORIGINDEX_NONE)
913 draw= setMaterial(mf->mat_nr + 1, NULL);
914 else if (setDrawOptions != NULL)
915 draw= setDrawOptions(userData, orig, &drawSmooth);
918 unsigned char *cp = NULL;
921 cp = (unsigned char *)&mc[i * 4];
923 glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
924 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
933 normal_quad_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
935 normal_tri_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
940 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
941 glVertex3fv(mv[mf->v1].co);
942 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
943 glVertex3fv(mv[mf->v2].co);
944 if(cp) glColor3ub(cp[11], cp[10], cp[9]);
945 glVertex3fv(mv[mf->v3].co);
947 if(cp) glColor3ub(cp[15], cp[14], cp[13]);
948 glVertex3fv(mv[mf->v4].co);
951 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
952 glNormal3sv(mv[mf->v1].no);
953 glVertex3fv(mv[mf->v1].co);
954 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
955 glNormal3sv(mv[mf->v2].no);
956 glVertex3fv(mv[mf->v2].co);
957 if(cp) glColor3ub(cp[11], cp[10], cp[9]);
958 glNormal3sv(mv[mf->v3].no);
959 glVertex3fv(mv[mf->v3].co);
961 if(cp) glColor3ub(cp[15], cp[14], cp[13]);
962 glNormal3sv(mv[mf->v4].no);
963 glVertex3fv(mv[mf->v4].co);
973 else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
975 GPU_vertex_setup(dm);
976 GPU_normal_setup(dm);
977 if( useColors && mc )
979 if( !GPU_buffer_legacy(dm) ) {
980 int tottri = dm->drawObject->tot_triangle_point/3;
981 glShadeModel(GL_SMOOTH);
984 /* avoid buffer problems in following code */
986 if(setDrawOptions == NULL) {
987 /* just draw the entire face array */
988 glDrawArrays(GL_TRIANGLES, 0, (tottri-1) * 3);
991 /* we need to check if the next material changes */
992 int next_actualFace= dm->drawObject->triangle_to_mface[0];
994 for( i = 0; i < tottri; i++ ) {
995 //int actualFace = dm->drawObject->triangle_to_mface[i];
996 int actualFace = next_actualFace;
997 MFace *mface= mf + actualFace;
998 int drawSmooth= (mface->flag & ME_SMOOTH);
1003 next_actualFace= dm->drawObject->triangle_to_mface[i+1];
1005 orig= (index==NULL) ? actualFace : index[actualFace];
1007 if(orig == ORIGINDEX_NONE)
1008 draw= setMaterial(mface->mat_nr + 1, NULL);
1009 else if (setDrawOptions != NULL)
1010 draw= setDrawOptions(userData, orig, &drawSmooth);
1012 /* Goal is to draw as long of a contiguous triangle
1013 array as possible, so draw when we hit either an
1014 invisible triangle or at the end of the array */
1016 /* flush buffer if current triangle isn't drawable or it's last triangle... */
1017 flush= !draw || i == tottri - 1;
1019 /* ... or when material setting is dissferent */
1020 flush|= mf[actualFace].mat_nr != mf[next_actualFace].mat_nr;
1022 if(!flush && compareDrawOptions) {
1023 int next_orig= (index==NULL) ? next_actualFace : index[next_actualFace];
1025 /* also compare draw options and flush buffer if they're different
1026 need for face selection highlight in edit mode */
1027 flush|= compareDrawOptions(userData, orig, next_orig) == 0;
1031 int first= prevstart*3;
1032 int count= (i-prevstart+(draw ? 1 : 0))*3; /* Add one to the length if we're drawing at the end of the array */
1035 glDrawArrays(GL_TRIANGLES, first, count);
1042 glShadeModel(GL_FLAT);
1044 GPU_buffer_unbind();
1048 static void cdDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
1050 cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
1053 static void cddm_draw_attrib_vertex(DMVertexAttribs *attribs, MVert *mvert, int a, int index, int vert, int smoothnormal)
1057 /* orco texture coordinates */
1058 if(attribs->totorco) {
1059 if(attribs->orco.glTexco)
1060 glTexCoord3fv(attribs->orco.array[index]);
1062 glVertexAttrib3fvARB(attribs->orco.glIndex, attribs->orco.array[index]);
1065 /* uv texture coordinates */
1066 for(b = 0; b < attribs->tottface; b++) {
1067 MTFace *tf = &attribs->tface[b].array[a];
1069 if(attribs->tface[b].glTexco)
1070 glTexCoord2fv(tf->uv[vert]);
1072 glVertexAttrib2fvARB(attribs->tface[b].glIndex, tf->uv[vert]);
1076 for(b = 0; b < attribs->totmcol; b++) {
1077 MCol *cp = &attribs->mcol[b].array[a*4 + vert];
1079 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1080 glVertexAttrib4ubvARB(attribs->mcol[b].glIndex, col);
1083 /* tangent for normal mapping */
1084 if(attribs->tottang) {
1085 float *tang = attribs->tang.array[a*4 + vert];
1086 glVertexAttrib4fvARB(attribs->tang.glIndex, tang);
1091 glNormal3sv(mvert[index].no);
1093 /* vertex coordinate */
1094 glVertex3fv(mvert[index].co);
1097 static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData)
1099 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1100 GPUVertexAttribs gattribs;
1101 DMVertexAttribs attribs;
1102 MVert *mvert = cddm->mvert;
1103 MFace *mface = cddm->mface;
1104 MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE);
1105 float (*nors)[3] = dm->getFaceDataArray(dm, CD_NORMAL);
1106 int a, b, dodraw, matnr, new_matnr;
1107 int transp, new_transp, orig_transp;
1108 int orig, *index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
1110 cdDM_update_normals_from_pbvh(dm);
1114 transp = GPU_get_material_blend_mode();
1115 orig_transp = transp;
1117 glShadeModel(GL_SMOOTH);
1119 if( GPU_buffer_legacy(dm) || setDrawOptions != NULL ) {
1120 DEBUG_VBO( "Using legacy code. cdDM_drawMappedFacesGLSL\n" );
1121 memset(&attribs, 0, sizeof(attribs));
1125 for(a = 0; a < dm->numFaceData; a++, mface++) {
1126 const int smoothnormal = (mface->flag & ME_SMOOTH);
1127 new_matnr = mface->mat_nr + 1;
1129 if(new_matnr != matnr) {
1132 dodraw = setMaterial(matnr = new_matnr, &gattribs);
1134 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1142 else if(setDrawOptions) {
1143 orig = (index)? index[a]: a;
1145 if(orig == ORIGINDEX_NONE) {
1146 /* since the material is set by setMaterial(), faces with no
1147 * origin can be assumed to be generated by a modifier */
1151 else if(!setDrawOptions(userData, orig))
1156 new_transp = tf[a].transp;
1158 if(new_transp != transp) {
1161 if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
1162 GPU_set_material_blend_mode(orig_transp);
1164 GPU_set_material_blend_mode(new_transp);
1165 transp = new_transp;
1173 glNormal3fv(nors[a]);
1176 /* TODO ideally a normal layer should always be available */
1179 normal_quad_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co);
1181 normal_tri_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co);
1187 cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v1, 0, smoothnormal);
1188 cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v2, 1, smoothnormal);
1189 cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v3, 2, smoothnormal);
1192 cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v4, 3, smoothnormal);
1194 cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v3, 2, smoothnormal);
1199 GPUBuffer *buffer = NULL;
1200 char *varray = NULL;
1201 int numdata = 0, elementsize = 0, offset;
1202 int start = 0, numfaces = 0, prevdraw = 0, curface = 0;
1206 GPUAttrib datatypes[GPU_MAX_ATTRIB]; /* TODO, messing up when switching materials many times - [#21056]*/
1207 memset(&attribs, 0, sizeof(attribs));
1209 GPU_vertex_setup(dm);
1210 GPU_normal_setup(dm);
1212 if( !GPU_buffer_legacy(dm) ) {
1213 for( i = 0; i < dm->drawObject->tot_triangle_point/3; i++ ) {
1215 a = dm->drawObject->triangle_to_mface[i];
1218 new_matnr = mface->mat_nr + 1;
1220 if(new_matnr != matnr ) {
1221 numfaces = curface - start;
1222 if( numfaces > 0 ) {
1226 if( numdata != 0 ) {
1228 GPU_buffer_unlock(buffer);
1230 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1233 glDrawArrays(GL_TRIANGLES,start*3,numfaces*3);
1235 if( numdata != 0 ) {
1237 GPU_buffer_free(buffer);
1247 dodraw = setMaterial(matnr = new_matnr, &gattribs);
1249 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1251 if(attribs.totorco) {
1252 datatypes[numdata].index = attribs.orco.glIndex;
1253 datatypes[numdata].size = 3;
1254 datatypes[numdata].type = GL_FLOAT;
1257 for(b = 0; b < attribs.tottface; b++) {
1258 datatypes[numdata].index = attribs.tface[b].glIndex;
1259 datatypes[numdata].size = 2;
1260 datatypes[numdata].type = GL_FLOAT;
1263 for(b = 0; b < attribs.totmcol; b++) {
1264 datatypes[numdata].index = attribs.mcol[b].glIndex;
1265 datatypes[numdata].size = 4;
1266 datatypes[numdata].type = GL_UNSIGNED_BYTE;
1269 if(attribs.tottang) {
1270 datatypes[numdata].index = attribs.tang.glIndex;
1271 datatypes[numdata].size = 4;
1272 datatypes[numdata].type = GL_FLOAT;
1275 if( numdata != 0 ) {
1276 elementsize = GPU_attrib_element_size( datatypes, numdata );
1277 buffer = GPU_buffer_alloc( elementsize*dm->drawObject->tot_triangle_point);
1278 if( buffer == NULL ) {
1279 GPU_buffer_unbind();
1280 dm->drawObject->legacy = 1;
1283 varray = GPU_buffer_lock_stream(buffer);
1284 if( varray == NULL ) {
1285 GPU_buffer_unbind();
1286 GPU_buffer_free(buffer);
1287 dm->drawObject->legacy = 1;
1292 /* if the buffer was set, dont use it again.
1293 * prevdraw was assumed true but didnt run so set to false - [#21036] */
1304 new_transp = tf[a].transp;
1306 if(new_transp != transp) {
1307 numfaces = curface - start;
1308 if( numfaces > 0 ) {
1310 if( numdata != 0 ) {
1311 GPU_buffer_unlock(buffer);
1312 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1314 glDrawArrays(GL_TRIANGLES,start*3,(curface-start)*3);
1315 if( numdata != 0 ) {
1316 varray = GPU_buffer_lock_stream(buffer);
1322 if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
1323 GPU_set_material_blend_mode(orig_transp);
1325 GPU_set_material_blend_mode(new_transp);
1326 transp = new_transp;
1330 if( numdata != 0 ) {
1332 if(attribs.totorco) {
1333 VECCOPY((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v1]);
1334 VECCOPY((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v2]);
1335 VECCOPY((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v3]);
1336 offset += sizeof(float)*3;
1338 for(b = 0; b < attribs.tottface; b++) {
1339 MTFace *tf = &attribs.tface[b].array[a];
1340 VECCOPY2D((float *)&varray[elementsize*curface*3+offset],tf->uv[0]);
1341 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[1]);
1343 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[2]);
1344 offset += sizeof(float)*2;
1346 for(b = 0; b < attribs.totmcol; b++) {
1347 MCol *cp = &attribs.mcol[b].array[a*4 + 0];
1349 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1350 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset], col);
1351 cp = &attribs.mcol[b].array[a*4 + 1];
1352 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1353 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize], col);
1354 cp = &attribs.mcol[b].array[a*4 + 2];
1355 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1356 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize*2], col);
1357 offset += sizeof(unsigned char)*4;
1359 if(attribs.tottang) {
1360 float *tang = attribs.tang.array[a*4 + 0];
1361 QUATCOPY((float *)&varray[elementsize*curface*3+offset], tang);
1362 tang = attribs.tang.array[a*4 + 1];
1363 QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
1364 tang = attribs.tang.array[a*4 + 2];
1365 QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
1366 offset += sizeof(float)*4;
1372 if( numdata != 0 ) {
1374 if(attribs.totorco) {
1375 VECCOPY((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v3]);
1376 VECCOPY((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v4]);
1377 VECCOPY((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v1]);
1378 offset += sizeof(float)*3;
1380 for(b = 0; b < attribs.tottface; b++) {
1381 MTFace *tf = &attribs.tface[b].array[a];
1382 VECCOPY2D((float *)&varray[elementsize*curface*3+offset],tf->uv[2]);
1383 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[3]);
1384 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[0]);
1385 offset += sizeof(float)*2;
1387 for(b = 0; b < attribs.totmcol; b++) {
1388 MCol *cp = &attribs.mcol[b].array[a*4 + 2];
1390 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1391 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset], col);
1392 cp = &attribs.mcol[b].array[a*4 + 3];
1393 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1394 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize], col);
1395 cp = &attribs.mcol[b].array[a*4 + 0];
1396 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1397 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize*2], col);
1398 offset += sizeof(unsigned char)*4;
1400 if(attribs.tottang) {
1401 float *tang = attribs.tang.array[a*4 + 2];
1402 QUATCOPY((float *)&varray[elementsize*curface*3+offset], tang);
1403 tang = attribs.tang.array[a*4 + 3];
1404 QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
1405 tang = attribs.tang.array[a*4 + 0];
1406 QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
1407 offset += sizeof(float)*4;
1415 numfaces = curface - start;
1416 if( numfaces > 0 ) {
1418 if( numdata != 0 ) {
1419 GPU_buffer_unlock(buffer);
1420 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1422 glDrawArrays(GL_TRIANGLES,start*3,(curface-start)*3);
1425 GPU_buffer_unbind();
1427 GPU_buffer_free(buffer);
1430 glShadeModel(GL_FLAT);
1433 static void cdDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs))
1435 dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
1438 static void cdDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
1440 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1441 MVert *vert = cddm->mvert;
1442 MEdge *edge = cddm->medge;
1443 int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
1446 for(i = 0; i < dm->numEdgeData; i++, edge++) {
1449 if(setDrawOptions && orig == ORIGINDEX_NONE) continue;
1454 if(!setDrawOptions || setDrawOptions(userData, orig)) {
1455 glVertex3fv(vert[edge->v1].co);
1456 glVertex3fv(vert[edge->v2].co);
1462 static void cdDM_foreachMappedVert(
1464 void (*func)(void *userData, int index, float *co,
1465 float *no_f, short *no_s),
1468 MVert *mv = CDDM_get_verts(dm);
1469 int i, orig, *index = DM_get_vert_data_layer(dm, CD_ORIGINDEX);
1471 for(i = 0; i < dm->numVertData; i++, mv++) {
1474 if(orig == ORIGINDEX_NONE) continue;
1475 func(userData, orig, mv->co, NULL, mv->no);
1478 func(userData, i, mv->co, NULL, mv->no);
1482 static void cdDM_foreachMappedEdge(
1484 void (*func)(void *userData, int index,
1485 float *v0co, float *v1co),
1488 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1489 MVert *mv = cddm->mvert;
1490 MEdge *med = cddm->medge;
1491 int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
1493 for(i = 0; i < dm->numEdgeData; i++, med++) {
1496 if(orig == ORIGINDEX_NONE) continue;
1497 func(userData, orig, mv[med->v1].co, mv[med->v2].co);
1500 func(userData, i, mv[med->v1].co, mv[med->v2].co);
1504 static void cdDM_foreachMappedFaceCenter(
1506 void (*func)(void *userData, int index,
1507 float *cent, float *no),
1510 CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1511 MVert *mv = cddm->mvert;
1512 MFace *mf = cddm->mface;
1513 int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
1515 for(i = 0; i < dm->numFaceData; i++, mf++) {
1521 if(orig == ORIGINDEX_NONE) continue;
1526 VECCOPY(cent, mv[mf->v1].co);
1527 add_v3_v3(cent, mv[mf->v2].co);
1528 add_v3_v3(cent, mv[mf->v3].co);
1531 normal_quad_v3( no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
1532 add_v3_v3(cent, mv[mf->v4].co);
1533 mul_v3_fl(cent, 0.25f);
1535 normal_tri_v3( no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
1536 mul_v3_fl(cent, 0.33333333333f);
1539 func(userData, orig, cent, no);
1543 static void cdDM_free_internal(CDDerivedMesh *cddm)
1545 if(cddm->fmap) MEM_freeN(cddm->fmap);
1546 if(cddm->fmap_mem) MEM_freeN(cddm->fmap_mem);
1549 static void cdDM_release(DerivedMesh *dm)
1551 CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1553 if (DM_release(dm)) {
1554 cdDM_free_internal(cddm);
1559 /**************** CDDM interface functions ****************/
1560 static CDDerivedMesh *cdDM_create(const char *desc)
1562 CDDerivedMesh *cddm;
1565 cddm = MEM_callocN(sizeof(*cddm), desc);
1568 dm->getMinMax = cdDM_getMinMax;
1570 dm->getNumVerts = cdDM_getNumVerts;
1571 dm->getNumFaces = cdDM_getNumFaces;
1572 dm->getNumEdges = cdDM_getNumEdges;
1574 dm->getVert = cdDM_getVert;
1575 dm->getEdge = cdDM_getEdge;
1576 dm->getFace = cdDM_getFace;
1577 dm->copyVertArray = cdDM_copyVertArray;
1578 dm->copyEdgeArray = cdDM_copyEdgeArray;
1579 dm->copyFaceArray = cdDM_copyFaceArray;
1580 dm->getVertData = DM_get_vert_data;
1581 dm->getEdgeData = DM_get_edge_data;
1582 dm->getFaceData = DM_get_face_data;
1583 dm->getVertDataArray = DM_get_vert_data_layer;
1584 dm->getEdgeDataArray = DM_get_edge_data_layer;
1585 dm->getFaceDataArray = DM_get_face_data_layer;
1587 dm->getVertCos = cdDM_getVertCos;
1588 dm->getVertCo = cdDM_getVertCo;
1589 dm->getVertNo = cdDM_getVertNo;
1591 dm->getPBVH = cdDM_getPBVH;
1592 dm->getFaceMap = cdDM_getFaceMap;
1594 dm->drawVerts = cdDM_drawVerts;
1596 dm->drawSelectedVerts = cdDM_drawSelectedVerts;
1598 dm->drawUVEdges = cdDM_drawUVEdges;
1599 dm->drawEdges = cdDM_drawEdges;
1600 dm->drawLooseEdges = cdDM_drawLooseEdges;
1601 dm->drawMappedEdges = cdDM_drawMappedEdges;
1603 dm->drawFacesSolid = cdDM_drawFacesSolid;
1604 dm->drawFacesColored = cdDM_drawFacesColored;
1605 dm->drawFacesTex = cdDM_drawFacesTex;
1606 dm->drawFacesGLSL = cdDM_drawFacesGLSL;
1607 dm->drawMappedFaces = cdDM_drawMappedFaces;
1608 dm->drawMappedFacesTex = cdDM_drawMappedFacesTex;
1609 dm->drawMappedFacesGLSL = cdDM_drawMappedFacesGLSL;
1611 dm->foreachMappedVert = cdDM_foreachMappedVert;
1612 dm->foreachMappedEdge = cdDM_foreachMappedEdge;
1613 dm->foreachMappedFaceCenter = cdDM_foreachMappedFaceCenter;
1615 dm->release = cdDM_release;
1620 DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces)
1622 CDDerivedMesh *cddm = cdDM_create("CDDM_new dm");
1623 DerivedMesh *dm = &cddm->dm;
1625 DM_init(dm, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
1627 CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
1628 CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1629 CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
1631 CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
1632 CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1633 CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
1635 cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1636 cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1637 cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1642 DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob))
1644 CDDerivedMesh *cddm = cdDM_create("CDDM_from_mesh dm");
1645 DerivedMesh *dm = &cddm->dm;
1646 CustomDataMask mask = CD_MASK_MESH & (~CD_MASK_MDISPS);
1649 /* this does a referenced copy, with an exception for fluidsim */
1651 DM_init(dm, DM_TYPE_CDDM, mesh->totvert, mesh->totedge, mesh->totface);
1653 dm->deformedOnly = 1;
1655 alloctype= CD_REFERENCE;
1657 CustomData_merge(&mesh->vdata, &dm->vertData, mask, alloctype,
1659 CustomData_merge(&mesh->edata, &dm->edgeData, mask, alloctype,
1661 CustomData_merge(&mesh->fdata, &dm->faceData, mask, alloctype,
1664 cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1665 cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1666 cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1671 DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me))
1673 DerivedMesh *dm = CDDM_new(BLI_countlist(&em->verts),
1674 BLI_countlist(&em->edges),
1675 BLI_countlist(&em->faces));
1676 CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1680 MVert *mvert = cddm->mvert;
1681 MEdge *medge = cddm->medge;
1682 MFace *mface = cddm->mface;
1685 dm->deformedOnly = 1;
1687 CustomData_merge(&em->vdata, &dm->vertData, CD_MASK_DERIVEDMESH,
1688 CD_CALLOC, dm->numVertData);
1689 /* CustomData_merge(&em->edata, &dm->edgeData, CD_MASK_DERIVEDMESH,
1690 CD_CALLOC, dm->numEdgeData); */
1691 CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
1692 CD_CALLOC, dm->numFaceData);
1694 /* set eve->hash to vert index */
1695 for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i)
1698 /* Need to be able to mark loose edges */
1699 for(eed = em->edges.first; eed; eed = eed->next) {
1702 for(efa = em->faces.first; efa; efa = efa->next) {
1706 if(efa->e4) efa->e4->f2 = 1;
1709 index = dm->getVertDataArray(dm, CD_ORIGINDEX);
1710 for(i = 0, eve = em->verts.first; i < dm->numVertData;
1711 i++, eve = eve->next, index++) {
1712 MVert *mv = &mvert[i];
1714 VECCOPY(mv->co, eve->co);
1716 normal_float_to_short_v3(mv->no, eve->no);
1717 mv->bweight = (unsigned char) (eve->bweight * 255.0f);
1723 CustomData_from_em_block(&em->vdata, &dm->vertData, eve->data, i);
1726 index = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
1727 for(i = 0, eed = em->edges.first; i < dm->numEdgeData;
1728 i++, eed = eed->next, index++) {
1729 MEdge *med = &medge[i];
1731 med->v1 = eed->v1->tmp.l;
1732 med->v2 = eed->v2->tmp.l;
1733 med->crease = (unsigned char) (eed->crease * 255.0f);
1734 med->bweight = (unsigned char) (eed->bweight * 255.0f);
1735 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1737 if(eed->seam) med->flag |= ME_SEAM;
1738 if(eed->sharp) med->flag |= ME_SHARP;
1739 if(!eed->f2) med->flag |= ME_LOOSEEDGE;
1743 /* CustomData_from_em_block(&em->edata, &dm->edgeData, eed->data, i); */
1746 index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
1747 for(i = 0, efa = em->faces.first; i < dm->numFaceData;
1748 i++, efa = efa->next, index++) {
1749 MFace *mf = &mface[i];
1751 mf->v1 = efa->v1->tmp.l;
1752 mf->v2 = efa->v2->tmp.l;
1753 mf->v3 = efa->v3->tmp.l;
1754 mf->v4 = efa->v4 ? efa->v4->tmp.l : 0;
1755 mf->mat_nr = efa->mat_nr;
1756 mf->flag = efa->flag;
1760 CustomData_from_em_block(&em->fdata, &dm->faceData, efa->data, i);
1761 test_index_face(mf, &dm->faceData, i, efa->v4?4:3);
1767 DerivedMesh *CDDM_from_curve(Object *ob)
1769 return CDDM_from_curve_customDB(ob, &ob->disp);
1772 DerivedMesh *CDDM_from_curve_customDB(Object *ob, ListBase *dispbase)
1775 CDDerivedMesh *cddm;
1779 int totvert, totedge, totface;
1781 if (nurbs_to_mdata_customdb(ob, dispbase, &allvert, &totvert, &alledge,
1782 &totedge, &allface, &totface) != 0) {
1783 /* Error initializing mdata. This often happens when curve is empty */
1784 return CDDM_new(0, 0, 0);
1787 dm = CDDM_new(totvert, totedge, totface);
1788 dm->deformedOnly = 1;
1790 cddm = (CDDerivedMesh*)dm;
1792 memcpy(cddm->mvert, allvert, totvert*sizeof(MVert));
1793 memcpy(cddm->medge, alledge, totedge*sizeof(MEdge));
1794 memcpy(cddm->mface, allface, totface*sizeof(MFace));
1803 DerivedMesh *CDDM_copy(DerivedMesh *source)
1805 CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm");
1806 DerivedMesh *dm = &cddm->dm;
1807 int numVerts = source->numVertData;
1808 int numEdges = source->numEdgeData;
1809 int numFaces = source->numFaceData;
1811 /* ensure these are created if they are made on demand */
1812 source->getVertDataArray(source, CD_ORIGINDEX);
1813 source->getEdgeDataArray(source, CD_ORIGINDEX);
1814 source->getFaceDataArray(source, CD_ORIGINDEX);
1816 /* this initializes dm, and copies all non mvert/medge/mface layers */
1817 DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
1818 dm->deformedOnly = source->deformedOnly;
1820 CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts);
1821 CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges);
1822 CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numFaces);
1824 /* now add mvert/medge/mface layers */
1825 cddm->mvert = source->dupVertArray(source);
1826 cddm->medge = source->dupEdgeArray(source);
1827 cddm->mface = source->dupFaceArray(source);
1829 CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts);
1830 CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges);
1831 CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numFaces);
1836 /* note, the CD_ORIGINDEX layers are all 0, so if there is a direct
1837 * relationship betwen mesh data this needs to be set by the caller. */
1838 DerivedMesh *CDDM_from_template(DerivedMesh *source,
1839 int numVerts, int numEdges, int numFaces)
1841 CDDerivedMesh *cddm = cdDM_create("CDDM_from_template dest");
1842 DerivedMesh *dm = &cddm->dm;
1844 /* ensure these are created if they are made on demand */
1845 source->getVertDataArray(source, CD_ORIGINDEX);
1846 source->getEdgeDataArray(source, CD_ORIGINDEX);
1847 source->getFaceDataArray(source, CD_ORIGINDEX);
1849 /* this does a copy of all non mvert/medge/mface layers */
1850 DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
1852 /* now add mvert/medge/mface layers */
1853 CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
1854 CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1855 CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
1857 if(!CustomData_get_layer(&dm->vertData, CD_ORIGINDEX))
1858 CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
1859 if(!CustomData_get_layer(&dm->edgeData, CD_ORIGINDEX))
1860 CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1861 if(!CustomData_get_layer(&dm->faceData, CD_ORIGINDEX))
1862 CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
1864 cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1865 cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1866 cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1871 void CDDM_apply_vert_coords(DerivedMesh *dm, float (*vertCoords)[3])
1873 CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1877 /* this will just return the pointer if it wasn't a referenced layer */
1878 vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
1881 for(i = 0; i < dm->numVertData; ++i, ++vert)
1882 VECCOPY(vert->co, vertCoords[i]);
1885 void CDDM_apply_vert_normals(DerivedMesh *dm, short (*vertNormals)[3])
1887 CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1891 /* this will just return the pointer if it wasn't a referenced layer */
1892 vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
1895 for(i = 0; i < dm->numVertData; ++i, ++vert)
1896 copy_v3_v3_short(vert->no, vertNormals[i]);
1899 void CDDM_calc_normals(DerivedMesh *dm)
1901 CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1902 float (*face_nors)[3];
1904 if(dm->numVertData == 0) return;
1906 /* we don't want to overwrite any referenced layers */
1907 cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
1909 /* make a face normal layer if not present */
1910 face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
1912 face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC,
1913 NULL, dm->numFaceData);
1915 /* calculate face normals */
1916 mesh_calc_normals(cddm->mvert, dm->numVertData, CDDM_get_faces(dm), dm->numFaceData, face_nors);
1919 void CDDM_calc_edges(DerivedMesh *dm)
1921 CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1922 CustomData edgeData;
1923 EdgeHashIterator *ehi;
1924 MFace *mf = cddm->mface;
1926 EdgeHash *eh = BLI_edgehash_new();
1927 int i, *index, numEdges, maxFaces = dm->numFaceData;
1929 for (i = 0; i < maxFaces; i++, mf++) {
1930 if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
1931 BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
1932 if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
1933 BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);
1936 if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
1937 BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
1938 if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
1939 BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
1941 if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
1942 BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
1946 numEdges = BLI_edgehash_size(eh);
1948 /* write new edges into a temporary CustomData */
1949 memset(&edgeData, 0, sizeof(edgeData));
1950 CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1951 CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1953 ehi = BLI_edgehashIterator_new(eh);
1954 med = CustomData_get_layer(&edgeData, CD_MEDGE);
1955 index = CustomData_get_layer(&edgeData, CD_ORIGINDEX);
1956 for(i = 0; !BLI_edgehashIterator_isDone(ehi);
1957 BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) {
1958 BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
1960 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1961 *index = ORIGINDEX_NONE;
1963 BLI_edgehashIterator_free(ehi);
1965 /* free old CustomData and assign new one */
1966 CustomData_free(&dm->edgeData, dm->numEdgeData);
1967 dm->edgeData = edgeData;
1968 dm->numEdgeData = numEdges;
1970 cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1972 BLI_edgehash_free(eh, NULL);
1975 void CDDM_lower_num_verts(DerivedMesh *dm, int numVerts)
1977 if (numVerts < dm->numVertData)
1978 CustomData_free_elem(&dm->vertData, numVerts, dm->numVertData-numVerts);
1980 dm->numVertData = numVerts;
1983 void CDDM_lower_num_edges(DerivedMesh *dm, int numEdges)
1985 if (numEdges < dm->numEdgeData)
1986 CustomData_free_elem(&dm->edgeData, numEdges, dm->numEdgeData-numEdges);
1988 dm->numEdgeData = numEdges;
1991 void CDDM_lower_num_faces(DerivedMesh *dm, int numFaces)
1993 if (numFaces < dm->numFaceData)
1994 CustomData_free_elem(&dm->faceData, numFaces, dm->numFaceData-numFaces);
1996 dm->numFaceData = numFaces;
1999 MVert *CDDM_get_vert(DerivedMesh *dm, int index)
2001 return &((CDDerivedMesh*)dm)->mvert[index];
2004 MEdge *CDDM_get_edge(DerivedMesh *dm, int index)
2006 return &((CDDerivedMesh*)dm)->medge[index];
2009 MFace *CDDM_get_face(DerivedMesh *dm, int index)
2011 return &((CDDerivedMesh*)dm)->mface[index];
2014 MVert *CDDM_get_verts(DerivedMesh *dm)
2016 return ((CDDerivedMesh*)dm)->mvert;
2019 MEdge *CDDM_get_edges(DerivedMesh *dm)
2021 return ((CDDerivedMesh*)dm)->medge;
2024 MFace *CDDM_get_faces(DerivedMesh *dm)
2026 return ((CDDerivedMesh*)dm)->mface;