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))
886 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
887 MVert *mv = cddm->mvert;
888 MFace *mf = cddm->mface;
890 float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
891 int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
893 mc = DM_get_face_data_layer(dm, CD_ID_MCOL);
895 mc = DM_get_face_data_layer(dm, CD_WEIGHT_MCOL);
897 mc = DM_get_face_data_layer(dm, CD_MCOL);
899 cdDM_update_normals_from_pbvh(dm);
901 /* back-buffer always uses legacy since VBO's would need the
902 * color array temporarily overwritten for drawing, then reset. */
903 if( GPU_buffer_legacy(dm) || G.f & G_BACKBUFSEL) {
904 DEBUG_VBO( "Using legacy code. cdDM_drawMappedFaces\n" );
905 for(i = 0; i < dm->numFaceData; i++, mf++) {
906 int drawSmooth = (mf->flag & ME_SMOOTH);
909 orig= (index==NULL) ? i : *index++;
911 if(orig == ORIGINDEX_NONE)
912 draw= setMaterial(mf->mat_nr + 1, NULL);
913 else if (setDrawOptions != NULL)
914 draw= setDrawOptions(userData, orig, &drawSmooth);
917 unsigned char *cp = NULL;
920 cp = (unsigned char *)&mc[i * 4];
922 glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
923 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
932 normal_quad_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
934 normal_tri_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
939 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
940 glVertex3fv(mv[mf->v1].co);
941 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
942 glVertex3fv(mv[mf->v2].co);
943 if(cp) glColor3ub(cp[11], cp[10], cp[9]);
944 glVertex3fv(mv[mf->v3].co);
946 if(cp) glColor3ub(cp[15], cp[14], cp[13]);
947 glVertex3fv(mv[mf->v4].co);
950 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
951 glNormal3sv(mv[mf->v1].no);
952 glVertex3fv(mv[mf->v1].co);
953 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
954 glNormal3sv(mv[mf->v2].no);
955 glVertex3fv(mv[mf->v2].co);
956 if(cp) glColor3ub(cp[11], cp[10], cp[9]);
957 glNormal3sv(mv[mf->v3].no);
958 glVertex3fv(mv[mf->v3].co);
960 if(cp) glColor3ub(cp[15], cp[14], cp[13]);
961 glNormal3sv(mv[mf->v4].no);
962 glVertex3fv(mv[mf->v4].co);
972 else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
974 GPU_vertex_setup(dm);
975 GPU_normal_setup(dm);
976 if( useColors && mc )
978 if( !GPU_buffer_legacy(dm) ) {
979 int tottri = dm->drawObject->tot_triangle_point/3;
980 glShadeModel(GL_SMOOTH);
983 /* avoid buffer problems in following code */
985 if(setDrawOptions == NULL) {
986 /* just draw the entire face array */
987 glDrawArrays(GL_TRIANGLES, 0, (tottri-1) * 3);
990 /* we need to check if the next material changes */
991 int next_actualFace= dm->drawObject->triangle_to_mface[0];
993 for( i = 0; i < tottri; i++ ) {
994 //int actualFace = dm->drawObject->triangle_to_mface[i];
995 int actualFace = next_actualFace;
996 MFace *mface= mf + actualFace;
997 int drawSmooth= (mface->flag & ME_SMOOTH);
1001 next_actualFace= dm->drawObject->triangle_to_mface[i+1];
1003 orig= (index==NULL) ? actualFace : index[actualFace];
1005 if(orig == ORIGINDEX_NONE)
1006 draw= setMaterial(mface->mat_nr + 1, NULL);
1007 else if (setDrawOptions != NULL)
1008 draw= setDrawOptions(userData, orig, &drawSmooth);
1010 /* Goal is to draw as long of a contiguous triangle
1011 array as possible, so draw when we hit either an
1012 invisible triangle or at the end of the array */
1013 if(!draw || i == tottri - 1 || mf[actualFace].mat_nr != mf[next_actualFace].mat_nr) {
1015 /* Add one to the length (via `draw')
1016 if we're drawing at the end of the array */
1017 glDrawArrays(GL_TRIANGLES,prevstart*3, (i-prevstart+draw)*3);
1023 glShadeModel(GL_FLAT);
1025 GPU_buffer_unbind();
1029 static void cdDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
1031 cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
1034 static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData)
1036 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1037 GPUVertexAttribs gattribs;
1038 DMVertexAttribs attribs;
1039 MVert *mvert = cddm->mvert;
1040 MFace *mface = cddm->mface;
1041 MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE);
1042 float (*nors)[3] = dm->getFaceDataArray(dm, CD_NORMAL);
1043 int a, b, dodraw, matnr, new_matnr;
1044 int transp, new_transp, orig_transp;
1045 int orig, *index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
1047 cdDM_update_normals_from_pbvh(dm);
1051 transp = GPU_get_material_blend_mode();
1052 orig_transp = transp;
1054 glShadeModel(GL_SMOOTH);
1056 if( GPU_buffer_legacy(dm) || setDrawOptions != NULL ) {
1057 DEBUG_VBO( "Using legacy code. cdDM_drawMappedFacesGLSL\n" );
1058 memset(&attribs, 0, sizeof(attribs));
1062 for(a = 0; a < dm->numFaceData; a++, mface++) {
1063 const int smoothnormal = (mface->flag & ME_SMOOTH);
1064 new_matnr = mface->mat_nr + 1;
1066 if(new_matnr != matnr) {
1069 dodraw = setMaterial(matnr = new_matnr, &gattribs);
1071 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1079 else if(setDrawOptions) {
1080 orig = (index)? index[a]: a;
1082 if(orig == ORIGINDEX_NONE) {
1083 /* since the material is set by setMaterial(), faces with no
1084 * origin can be assumed to be generated by a modifier */
1088 else if(!setDrawOptions(userData, orig))
1093 new_transp = tf[a].transp;
1095 if(new_transp != transp) {
1098 if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
1099 GPU_set_material_blend_mode(orig_transp);
1101 GPU_set_material_blend_mode(new_transp);
1102 transp = new_transp;
1110 glNormal3fv(nors[a]);
1113 /* TODO ideally a normal layer should always be available */
1116 normal_quad_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co);
1118 normal_tri_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co);
1124 #define PASSVERT(index, vert) { \
1125 if(attribs.totorco) \
1126 glVertexAttrib3fvARB(attribs.orco.glIndex, attribs.orco.array[index]); \
1127 for(b = 0; b < attribs.tottface; b++) { \
1128 MTFace *tf = &attribs.tface[b].array[a]; \
1129 glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]); \
1131 for(b = 0; b < attribs.totmcol; b++) { \
1132 MCol *cp = &attribs.mcol[b].array[a*4 + vert]; \
1134 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; \
1135 glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col); \
1137 if(attribs.tottang) { \
1138 float *tang = attribs.tang.array[a*4 + vert]; \
1139 glVertexAttrib4fvARB(attribs.tang.glIndex, tang); \
1142 glNormal3sv(mvert[index].no); \
1143 glVertex3fv(mvert[index].co); \
1146 PASSVERT(mface->v1, 0);
1147 PASSVERT(mface->v2, 1);
1148 PASSVERT(mface->v3, 2);
1150 PASSVERT(mface->v4, 3)
1152 PASSVERT(mface->v3, 2)
1159 GPUBuffer *buffer = NULL;
1160 char *varray = NULL;
1161 int numdata = 0, elementsize = 0, offset;
1162 int start = 0, numfaces = 0, prevdraw = 0, curface = 0;
1166 GPUAttrib datatypes[GPU_MAX_ATTRIB]; /* TODO, messing up when switching materials many times - [#21056]*/
1167 memset(&attribs, 0, sizeof(attribs));
1169 GPU_vertex_setup(dm);
1170 GPU_normal_setup(dm);
1172 if( !GPU_buffer_legacy(dm) ) {
1173 for( i = 0; i < dm->drawObject->tot_triangle_point/3; i++ ) {
1175 a = dm->drawObject->triangle_to_mface[i];
1178 new_matnr = mface->mat_nr + 1;
1180 if(new_matnr != matnr ) {
1181 numfaces = curface - start;
1182 if( numfaces > 0 ) {
1186 if( numdata != 0 ) {
1188 GPU_buffer_unlock(buffer);
1190 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1193 glDrawArrays(GL_TRIANGLES,start*3,numfaces*3);
1195 if( numdata != 0 ) {
1197 GPU_buffer_free(buffer);
1207 dodraw = setMaterial(matnr = new_matnr, &gattribs);
1209 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
1211 if(attribs.totorco) {
1212 datatypes[numdata].index = attribs.orco.glIndex;
1213 datatypes[numdata].size = 3;
1214 datatypes[numdata].type = GL_FLOAT;
1217 for(b = 0; b < attribs.tottface; b++) {
1218 datatypes[numdata].index = attribs.tface[b].glIndex;
1219 datatypes[numdata].size = 2;
1220 datatypes[numdata].type = GL_FLOAT;
1223 for(b = 0; b < attribs.totmcol; b++) {
1224 datatypes[numdata].index = attribs.mcol[b].glIndex;
1225 datatypes[numdata].size = 4;
1226 datatypes[numdata].type = GL_UNSIGNED_BYTE;
1229 if(attribs.tottang) {
1230 datatypes[numdata].index = attribs.tang.glIndex;
1231 datatypes[numdata].size = 4;
1232 datatypes[numdata].type = GL_FLOAT;
1235 if( numdata != 0 ) {
1236 elementsize = GPU_attrib_element_size( datatypes, numdata );
1237 buffer = GPU_buffer_alloc( elementsize*dm->drawObject->tot_triangle_point);
1238 if( buffer == NULL ) {
1239 GPU_buffer_unbind();
1240 dm->drawObject->legacy = 1;
1243 varray = GPU_buffer_lock_stream(buffer);
1244 if( varray == NULL ) {
1245 GPU_buffer_unbind();
1246 GPU_buffer_free(buffer);
1247 dm->drawObject->legacy = 1;
1252 /* if the buffer was set, dont use it again.
1253 * prevdraw was assumed true but didnt run so set to false - [#21036] */
1264 new_transp = tf[a].transp;
1266 if(new_transp != transp) {
1267 numfaces = curface - start;
1268 if( numfaces > 0 ) {
1270 if( numdata != 0 ) {
1271 GPU_buffer_unlock(buffer);
1272 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1274 glDrawArrays(GL_TRIANGLES,start*3,(curface-start)*3);
1275 if( numdata != 0 ) {
1276 varray = GPU_buffer_lock_stream(buffer);
1282 if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID)
1283 GPU_set_material_blend_mode(orig_transp);
1285 GPU_set_material_blend_mode(new_transp);
1286 transp = new_transp;
1290 if( numdata != 0 ) {
1292 if(attribs.totorco) {
1293 VECCOPY((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v1]);
1294 VECCOPY((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v2]);
1295 VECCOPY((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v3]);
1296 offset += sizeof(float)*3;
1298 for(b = 0; b < attribs.tottface; b++) {
1299 MTFace *tf = &attribs.tface[b].array[a];
1300 VECCOPY2D((float *)&varray[elementsize*curface*3+offset],tf->uv[0]);
1301 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[1]);
1303 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[2]);
1304 offset += sizeof(float)*2;
1306 for(b = 0; b < attribs.totmcol; b++) {
1307 MCol *cp = &attribs.mcol[b].array[a*4 + 0];
1309 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1310 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset], col);
1311 cp = &attribs.mcol[b].array[a*4 + 1];
1312 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1313 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize], col);
1314 cp = &attribs.mcol[b].array[a*4 + 2];
1315 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1316 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize*2], col);
1317 offset += sizeof(unsigned char)*4;
1319 if(attribs.tottang) {
1320 float *tang = attribs.tang.array[a*4 + 0];
1321 QUATCOPY((float *)&varray[elementsize*curface*3+offset], tang);
1322 tang = attribs.tang.array[a*4 + 1];
1323 QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
1324 tang = attribs.tang.array[a*4 + 2];
1325 QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
1326 offset += sizeof(float)*4;
1332 if( numdata != 0 ) {
1334 if(attribs.totorco) {
1335 VECCOPY((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v3]);
1336 VECCOPY((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v4]);
1337 VECCOPY((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v1]);
1338 offset += sizeof(float)*3;
1340 for(b = 0; b < attribs.tottface; b++) {
1341 MTFace *tf = &attribs.tface[b].array[a];
1342 VECCOPY2D((float *)&varray[elementsize*curface*3+offset],tf->uv[2]);
1343 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[3]);
1344 VECCOPY2D((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[0]);
1345 offset += sizeof(float)*2;
1347 for(b = 0; b < attribs.totmcol; b++) {
1348 MCol *cp = &attribs.mcol[b].array[a*4 + 2];
1350 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1351 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset], col);
1352 cp = &attribs.mcol[b].array[a*4 + 3];
1353 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1354 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize], col);
1355 cp = &attribs.mcol[b].array[a*4 + 0];
1356 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
1357 QUATCOPY((unsigned char *)&varray[elementsize*curface*3+offset+elementsize*2], col);
1358 offset += sizeof(unsigned char)*4;
1360 if(attribs.tottang) {
1361 float *tang = attribs.tang.array[a*4 + 2];
1362 QUATCOPY((float *)&varray[elementsize*curface*3+offset], tang);
1363 tang = attribs.tang.array[a*4 + 3];
1364 QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
1365 tang = attribs.tang.array[a*4 + 0];
1366 QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
1367 offset += sizeof(float)*4;
1375 numfaces = curface - start;
1376 if( numfaces > 0 ) {
1378 if( numdata != 0 ) {
1379 GPU_buffer_unlock(buffer);
1380 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
1382 glDrawArrays(GL_TRIANGLES,start*3,(curface-start)*3);
1385 GPU_buffer_unbind();
1387 GPU_buffer_free(buffer);
1390 glShadeModel(GL_FLAT);
1393 static void cdDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs))
1395 dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
1398 static void cdDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
1400 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1401 MVert *vert = cddm->mvert;
1402 MEdge *edge = cddm->medge;
1403 int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
1406 for(i = 0; i < dm->numEdgeData; i++, edge++) {
1409 if(setDrawOptions && orig == ORIGINDEX_NONE) continue;
1414 if(!setDrawOptions || setDrawOptions(userData, orig)) {
1415 glVertex3fv(vert[edge->v1].co);
1416 glVertex3fv(vert[edge->v2].co);
1422 static void cdDM_foreachMappedVert(
1424 void (*func)(void *userData, int index, float *co,
1425 float *no_f, short *no_s),
1428 MVert *mv = CDDM_get_verts(dm);
1429 int i, orig, *index = DM_get_vert_data_layer(dm, CD_ORIGINDEX);
1431 for(i = 0; i < dm->numVertData; i++, mv++) {
1434 if(orig == ORIGINDEX_NONE) continue;
1435 func(userData, orig, mv->co, NULL, mv->no);
1438 func(userData, i, mv->co, NULL, mv->no);
1442 static void cdDM_foreachMappedEdge(
1444 void (*func)(void *userData, int index,
1445 float *v0co, float *v1co),
1448 CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
1449 MVert *mv = cddm->mvert;
1450 MEdge *med = cddm->medge;
1451 int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
1453 for(i = 0; i < dm->numEdgeData; i++, med++) {
1456 if(orig == ORIGINDEX_NONE) continue;
1457 func(userData, orig, mv[med->v1].co, mv[med->v2].co);
1460 func(userData, i, mv[med->v1].co, mv[med->v2].co);
1464 static void cdDM_foreachMappedFaceCenter(
1466 void (*func)(void *userData, int index,
1467 float *cent, float *no),
1470 CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1471 MVert *mv = cddm->mvert;
1472 MFace *mf = cddm->mface;
1473 int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
1475 for(i = 0; i < dm->numFaceData; i++, mf++) {
1481 if(orig == ORIGINDEX_NONE) continue;
1486 VECCOPY(cent, mv[mf->v1].co);
1487 add_v3_v3(cent, mv[mf->v2].co);
1488 add_v3_v3(cent, mv[mf->v3].co);
1491 normal_quad_v3( no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
1492 add_v3_v3(cent, mv[mf->v4].co);
1493 mul_v3_fl(cent, 0.25f);
1495 normal_tri_v3( no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
1496 mul_v3_fl(cent, 0.33333333333f);
1499 func(userData, orig, cent, no);
1503 static void cdDM_free_internal(CDDerivedMesh *cddm)
1505 if(cddm->fmap) MEM_freeN(cddm->fmap);
1506 if(cddm->fmap_mem) MEM_freeN(cddm->fmap_mem);
1509 static void cdDM_release(DerivedMesh *dm)
1511 CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1513 if (DM_release(dm)) {
1514 cdDM_free_internal(cddm);
1519 /**************** CDDM interface functions ****************/
1520 static CDDerivedMesh *cdDM_create(const char *desc)
1522 CDDerivedMesh *cddm;
1525 cddm = MEM_callocN(sizeof(*cddm), desc);
1528 dm->getMinMax = cdDM_getMinMax;
1530 dm->getNumVerts = cdDM_getNumVerts;
1531 dm->getNumFaces = cdDM_getNumFaces;
1532 dm->getNumEdges = cdDM_getNumEdges;
1534 dm->getVert = cdDM_getVert;
1535 dm->getEdge = cdDM_getEdge;
1536 dm->getFace = cdDM_getFace;
1537 dm->copyVertArray = cdDM_copyVertArray;
1538 dm->copyEdgeArray = cdDM_copyEdgeArray;
1539 dm->copyFaceArray = cdDM_copyFaceArray;
1540 dm->getVertData = DM_get_vert_data;
1541 dm->getEdgeData = DM_get_edge_data;
1542 dm->getFaceData = DM_get_face_data;
1543 dm->getVertDataArray = DM_get_vert_data_layer;
1544 dm->getEdgeDataArray = DM_get_edge_data_layer;
1545 dm->getFaceDataArray = DM_get_face_data_layer;
1547 dm->getVertCos = cdDM_getVertCos;
1548 dm->getVertCo = cdDM_getVertCo;
1549 dm->getVertNo = cdDM_getVertNo;
1551 dm->getPBVH = cdDM_getPBVH;
1552 dm->getFaceMap = cdDM_getFaceMap;
1554 dm->drawVerts = cdDM_drawVerts;
1556 dm->drawSelectedVerts = cdDM_drawSelectedVerts;
1558 dm->drawUVEdges = cdDM_drawUVEdges;
1559 dm->drawEdges = cdDM_drawEdges;
1560 dm->drawLooseEdges = cdDM_drawLooseEdges;
1561 dm->drawMappedEdges = cdDM_drawMappedEdges;
1563 dm->drawFacesSolid = cdDM_drawFacesSolid;
1564 dm->drawFacesColored = cdDM_drawFacesColored;
1565 dm->drawFacesTex = cdDM_drawFacesTex;
1566 dm->drawFacesGLSL = cdDM_drawFacesGLSL;
1567 dm->drawMappedFaces = cdDM_drawMappedFaces;
1568 dm->drawMappedFacesTex = cdDM_drawMappedFacesTex;
1569 dm->drawMappedFacesGLSL = cdDM_drawMappedFacesGLSL;
1571 dm->foreachMappedVert = cdDM_foreachMappedVert;
1572 dm->foreachMappedEdge = cdDM_foreachMappedEdge;
1573 dm->foreachMappedFaceCenter = cdDM_foreachMappedFaceCenter;
1575 dm->release = cdDM_release;
1580 DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces)
1582 CDDerivedMesh *cddm = cdDM_create("CDDM_new dm");
1583 DerivedMesh *dm = &cddm->dm;
1585 DM_init(dm, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
1587 CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
1588 CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1589 CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
1591 CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
1592 CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1593 CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
1595 cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1596 cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1597 cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1602 DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob))
1604 CDDerivedMesh *cddm = cdDM_create("CDDM_from_mesh dm");
1605 DerivedMesh *dm = &cddm->dm;
1606 CustomDataMask mask = CD_MASK_MESH & (~CD_MASK_MDISPS);
1609 /* this does a referenced copy, with an exception for fluidsim */
1611 DM_init(dm, DM_TYPE_CDDM, mesh->totvert, mesh->totedge, mesh->totface);
1613 dm->deformedOnly = 1;
1615 alloctype= CD_REFERENCE;
1617 CustomData_merge(&mesh->vdata, &dm->vertData, mask, alloctype,
1619 CustomData_merge(&mesh->edata, &dm->edgeData, mask, alloctype,
1621 CustomData_merge(&mesh->fdata, &dm->faceData, mask, alloctype,
1624 cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1625 cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1626 cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1631 DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me))
1633 DerivedMesh *dm = CDDM_new(BLI_countlist(&em->verts),
1634 BLI_countlist(&em->edges),
1635 BLI_countlist(&em->faces));
1636 CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1640 MVert *mvert = cddm->mvert;
1641 MEdge *medge = cddm->medge;
1642 MFace *mface = cddm->mface;
1645 dm->deformedOnly = 1;
1647 CustomData_merge(&em->vdata, &dm->vertData, CD_MASK_DERIVEDMESH,
1648 CD_CALLOC, dm->numVertData);
1649 /* CustomData_merge(&em->edata, &dm->edgeData, CD_MASK_DERIVEDMESH,
1650 CD_CALLOC, dm->numEdgeData); */
1651 CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
1652 CD_CALLOC, dm->numFaceData);
1654 /* set eve->hash to vert index */
1655 for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i)
1658 /* Need to be able to mark loose edges */
1659 for(eed = em->edges.first; eed; eed = eed->next) {
1662 for(efa = em->faces.first; efa; efa = efa->next) {
1666 if(efa->e4) efa->e4->f2 = 1;
1669 index = dm->getVertDataArray(dm, CD_ORIGINDEX);
1670 for(i = 0, eve = em->verts.first; i < dm->numVertData;
1671 i++, eve = eve->next, index++) {
1672 MVert *mv = &mvert[i];
1674 VECCOPY(mv->co, eve->co);
1676 normal_float_to_short_v3(mv->no, eve->no);
1677 mv->bweight = (unsigned char) (eve->bweight * 255.0f);
1683 CustomData_from_em_block(&em->vdata, &dm->vertData, eve->data, i);
1686 index = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
1687 for(i = 0, eed = em->edges.first; i < dm->numEdgeData;
1688 i++, eed = eed->next, index++) {
1689 MEdge *med = &medge[i];
1691 med->v1 = eed->v1->tmp.l;
1692 med->v2 = eed->v2->tmp.l;
1693 med->crease = (unsigned char) (eed->crease * 255.0f);
1694 med->bweight = (unsigned char) (eed->bweight * 255.0f);
1695 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1697 if(eed->seam) med->flag |= ME_SEAM;
1698 if(eed->sharp) med->flag |= ME_SHARP;
1699 if(!eed->f2) med->flag |= ME_LOOSEEDGE;
1703 /* CustomData_from_em_block(&em->edata, &dm->edgeData, eed->data, i); */
1706 index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
1707 for(i = 0, efa = em->faces.first; i < dm->numFaceData;
1708 i++, efa = efa->next, index++) {
1709 MFace *mf = &mface[i];
1711 mf->v1 = efa->v1->tmp.l;
1712 mf->v2 = efa->v2->tmp.l;
1713 mf->v3 = efa->v3->tmp.l;
1714 mf->v4 = efa->v4 ? efa->v4->tmp.l : 0;
1715 mf->mat_nr = efa->mat_nr;
1716 mf->flag = efa->flag;
1720 CustomData_from_em_block(&em->fdata, &dm->faceData, efa->data, i);
1721 test_index_face(mf, &dm->faceData, i, efa->v4?4:3);
1727 DerivedMesh *CDDM_from_curve(Object *ob)
1729 return CDDM_from_curve_customDB(ob, &ob->disp);
1732 DerivedMesh *CDDM_from_curve_customDB(Object *ob, ListBase *dispbase)
1735 CDDerivedMesh *cddm;
1739 int totvert, totedge, totface;
1741 if (nurbs_to_mdata_customdb(ob, dispbase, &allvert, &totvert, &alledge,
1742 &totedge, &allface, &totface) != 0) {
1743 /* Error initializing mdata. This often happens when curve is empty */
1744 return CDDM_new(0, 0, 0);
1747 dm = CDDM_new(totvert, totedge, totface);
1748 dm->deformedOnly = 1;
1750 cddm = (CDDerivedMesh*)dm;
1752 memcpy(cddm->mvert, allvert, totvert*sizeof(MVert));
1753 memcpy(cddm->medge, alledge, totedge*sizeof(MEdge));
1754 memcpy(cddm->mface, allface, totface*sizeof(MFace));
1763 DerivedMesh *CDDM_copy(DerivedMesh *source)
1765 CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm");
1766 DerivedMesh *dm = &cddm->dm;
1767 int numVerts = source->numVertData;
1768 int numEdges = source->numEdgeData;
1769 int numFaces = source->numFaceData;
1771 /* ensure these are created if they are made on demand */
1772 source->getVertDataArray(source, CD_ORIGINDEX);
1773 source->getEdgeDataArray(source, CD_ORIGINDEX);
1774 source->getFaceDataArray(source, CD_ORIGINDEX);
1776 /* this initializes dm, and copies all non mvert/medge/mface layers */
1777 DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
1778 dm->deformedOnly = source->deformedOnly;
1780 CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts);
1781 CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges);
1782 CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numFaces);
1784 /* now add mvert/medge/mface layers */
1785 cddm->mvert = source->dupVertArray(source);
1786 cddm->medge = source->dupEdgeArray(source);
1787 cddm->mface = source->dupFaceArray(source);
1789 CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts);
1790 CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges);
1791 CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numFaces);
1796 /* note, the CD_ORIGINDEX layers are all 0, so if there is a direct
1797 * relationship betwen mesh data this needs to be set by the caller. */
1798 DerivedMesh *CDDM_from_template(DerivedMesh *source,
1799 int numVerts, int numEdges, int numFaces)
1801 CDDerivedMesh *cddm = cdDM_create("CDDM_from_template dest");
1802 DerivedMesh *dm = &cddm->dm;
1804 /* ensure these are created if they are made on demand */
1805 source->getVertDataArray(source, CD_ORIGINDEX);
1806 source->getEdgeDataArray(source, CD_ORIGINDEX);
1807 source->getFaceDataArray(source, CD_ORIGINDEX);
1809 /* this does a copy of all non mvert/medge/mface layers */
1810 DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
1812 /* now add mvert/medge/mface layers */
1813 CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
1814 CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1815 CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
1817 if(!CustomData_get_layer(&dm->vertData, CD_ORIGINDEX))
1818 CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
1819 if(!CustomData_get_layer(&dm->edgeData, CD_ORIGINDEX))
1820 CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1821 if(!CustomData_get_layer(&dm->faceData, CD_ORIGINDEX))
1822 CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
1824 cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
1825 cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1826 cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
1831 void CDDM_apply_vert_coords(DerivedMesh *dm, float (*vertCoords)[3])
1833 CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1837 /* this will just return the pointer if it wasn't a referenced layer */
1838 vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
1841 for(i = 0; i < dm->numVertData; ++i, ++vert)
1842 VECCOPY(vert->co, vertCoords[i]);
1845 void CDDM_apply_vert_normals(DerivedMesh *dm, short (*vertNormals)[3])
1847 CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1851 /* this will just return the pointer if it wasn't a referenced layer */
1852 vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
1855 for(i = 0; i < dm->numVertData; ++i, ++vert)
1856 VECCOPY(vert->no, vertNormals[i]);
1859 void CDDM_calc_normals(DerivedMesh *dm)
1861 CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1862 float (*face_nors)[3];
1864 if(dm->numVertData == 0) return;
1866 /* we don't want to overwrite any referenced layers */
1867 cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
1869 /* make a face normal layer if not present */
1870 face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
1872 face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC,
1873 NULL, dm->numFaceData);
1875 /* calculate face normals */
1876 mesh_calc_normals(cddm->mvert, dm->numVertData, CDDM_get_faces(dm), dm->numFaceData, face_nors);
1879 void CDDM_calc_edges(DerivedMesh *dm)
1881 CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
1882 CustomData edgeData;
1883 EdgeHashIterator *ehi;
1884 MFace *mf = cddm->mface;
1886 EdgeHash *eh = BLI_edgehash_new();
1887 int i, *index, numEdges, maxFaces = dm->numFaceData;
1889 for (i = 0; i < maxFaces; i++, mf++) {
1890 if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
1891 BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
1892 if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
1893 BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);
1896 if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
1897 BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
1898 if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
1899 BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
1901 if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
1902 BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
1906 numEdges = BLI_edgehash_size(eh);
1908 /* write new edges into a temporary CustomData */
1909 memset(&edgeData, 0, sizeof(edgeData));
1910 CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
1911 CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
1913 ehi = BLI_edgehashIterator_new(eh);
1914 med = CustomData_get_layer(&edgeData, CD_MEDGE);
1915 index = CustomData_get_layer(&edgeData, CD_ORIGINDEX);
1916 for(i = 0; !BLI_edgehashIterator_isDone(ehi);
1917 BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) {
1918 BLI_edgehashIterator_getKey(ehi, (int*)&med->v1, (int*)&med->v2);
1920 med->flag = ME_EDGEDRAW|ME_EDGERENDER;
1921 *index = ORIGINDEX_NONE;
1923 BLI_edgehashIterator_free(ehi);
1925 /* free old CustomData and assign new one */
1926 CustomData_free(&dm->edgeData, dm->numEdgeData);
1927 dm->edgeData = edgeData;
1928 dm->numEdgeData = numEdges;
1930 cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
1932 BLI_edgehash_free(eh, NULL);
1935 void CDDM_lower_num_verts(DerivedMesh *dm, int numVerts)
1937 if (numVerts < dm->numVertData)
1938 CustomData_free_elem(&dm->vertData, numVerts, dm->numVertData-numVerts);
1940 dm->numVertData = numVerts;
1943 void CDDM_lower_num_edges(DerivedMesh *dm, int numEdges)
1945 if (numEdges < dm->numEdgeData)
1946 CustomData_free_elem(&dm->edgeData, numEdges, dm->numEdgeData-numEdges);
1948 dm->numEdgeData = numEdges;
1951 void CDDM_lower_num_faces(DerivedMesh *dm, int numFaces)
1953 if (numFaces < dm->numFaceData)
1954 CustomData_free_elem(&dm->faceData, numFaces, dm->numFaceData-numFaces);
1956 dm->numFaceData = numFaces;
1959 MVert *CDDM_get_vert(DerivedMesh *dm, int index)
1961 return &((CDDerivedMesh*)dm)->mvert[index];
1964 MEdge *CDDM_get_edge(DerivedMesh *dm, int index)
1966 return &((CDDerivedMesh*)dm)->medge[index];
1969 MFace *CDDM_get_face(DerivedMesh *dm, int index)
1971 return &((CDDerivedMesh*)dm)->mface[index];
1974 MVert *CDDM_get_verts(DerivedMesh *dm)
1976 return ((CDDerivedMesh*)dm)->mvert;
1979 MEdge *CDDM_get_edges(DerivedMesh *dm)
1981 return ((CDDerivedMesh*)dm)->medge;
1984 MFace *CDDM_get_faces(DerivedMesh *dm)
1986 return ((CDDerivedMesh*)dm)->mface;