Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2006 Blender Foundation. 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): Ben Batt <benbatt@gmail.com> 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 * 00027 * Implementation of CDDerivedMesh. 00028 * 00029 * BKE_cdderivedmesh.h contains the function prototypes for this file. 00030 * 00031 */ 00032 00037 #include "GL/glew.h" 00038 00039 #include "BLI_blenlib.h" 00040 #include "BLI_edgehash.h" 00041 #include "BLI_editVert.h" 00042 #include "BLI_math.h" 00043 #include "BLI_pbvh.h" 00044 #include "BLI_utildefines.h" 00045 00046 #include "BKE_cdderivedmesh.h" 00047 #include "BKE_global.h" 00048 #include "BKE_mesh.h" 00049 #include "BKE_paint.h" 00050 00051 00052 #include "DNA_meshdata_types.h" 00053 #include "DNA_object_types.h" 00054 #include "DNA_curve_types.h" /* for Curve */ 00055 00056 #include "MEM_guardedalloc.h" 00057 00058 #include "GPU_buffers.h" 00059 #include "GPU_draw.h" 00060 #include "GPU_extensions.h" 00061 #include "GPU_material.h" 00062 00063 #include <string.h> 00064 #include <limits.h> 00065 #include <math.h> 00066 00067 typedef struct { 00068 DerivedMesh dm; 00069 00070 /* these point to data in the DerivedMesh custom data layers, 00071 they are only here for efficiency and convenience **/ 00072 MVert *mvert; 00073 MEdge *medge; 00074 MFace *mface; 00075 00076 /* Cached */ 00077 struct PBVH *pbvh; 00078 int pbvh_draw; 00079 00080 /* Mesh connectivity */ 00081 struct ListBase *fmap; 00082 struct IndexNode *fmap_mem; 00083 } CDDerivedMesh; 00084 00085 /**************** DerivedMesh interface functions ****************/ 00086 static int cdDM_getNumVerts(DerivedMesh *dm) 00087 { 00088 return dm->numVertData; 00089 } 00090 00091 static int cdDM_getNumEdges(DerivedMesh *dm) 00092 { 00093 return dm->numEdgeData; 00094 } 00095 00096 static int cdDM_getNumFaces(DerivedMesh *dm) 00097 { 00098 return dm->numFaceData; 00099 } 00100 00101 static void cdDM_getVert(DerivedMesh *dm, int index, MVert *vert_r) 00102 { 00103 CDDerivedMesh *cddm = (CDDerivedMesh *)dm; 00104 *vert_r = cddm->mvert[index]; 00105 } 00106 00107 static void cdDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r) 00108 { 00109 CDDerivedMesh *cddm = (CDDerivedMesh *)dm; 00110 *edge_r = cddm->medge[index]; 00111 } 00112 00113 static void cdDM_getFace(DerivedMesh *dm, int index, MFace *face_r) 00114 { 00115 CDDerivedMesh *cddm = (CDDerivedMesh *)dm; 00116 *face_r = cddm->mface[index]; 00117 } 00118 00119 static void cdDM_copyVertArray(DerivedMesh *dm, MVert *vert_r) 00120 { 00121 CDDerivedMesh *cddm = (CDDerivedMesh *)dm; 00122 memcpy(vert_r, cddm->mvert, sizeof(*vert_r) * dm->numVertData); 00123 } 00124 00125 static void cdDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r) 00126 { 00127 CDDerivedMesh *cddm = (CDDerivedMesh *)dm; 00128 memcpy(edge_r, cddm->medge, sizeof(*edge_r) * dm->numEdgeData); 00129 } 00130 00131 static void cdDM_copyFaceArray(DerivedMesh *dm, MFace *face_r) 00132 { 00133 CDDerivedMesh *cddm = (CDDerivedMesh *)dm; 00134 memcpy(face_r, cddm->mface, sizeof(*face_r) * dm->numFaceData); 00135 } 00136 00137 static void cdDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) 00138 { 00139 CDDerivedMesh *cddm = (CDDerivedMesh*) dm; 00140 int i; 00141 00142 if (dm->numVertData) { 00143 for (i=0; i<dm->numVertData; i++) { 00144 DO_MINMAX(cddm->mvert[i].co, min_r, max_r); 00145 } 00146 } else { 00147 min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0; 00148 } 00149 } 00150 00151 static void cdDM_getVertCo(DerivedMesh *dm, int index, float co_r[3]) 00152 { 00153 CDDerivedMesh *cddm = (CDDerivedMesh*) dm; 00154 00155 copy_v3_v3(co_r, cddm->mvert[index].co); 00156 } 00157 00158 static void cdDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3]) 00159 { 00160 MVert *mv = CDDM_get_verts(dm); 00161 int i; 00162 00163 for(i = 0; i < dm->numVertData; i++, mv++) 00164 copy_v3_v3(cos_r[i], mv->co); 00165 } 00166 00167 static void cdDM_getVertNo(DerivedMesh *dm, int index, float no_r[3]) 00168 { 00169 CDDerivedMesh *cddm = (CDDerivedMesh*) dm; 00170 normal_short_to_float_v3(no_r, cddm->mvert[index].no); 00171 } 00172 00173 static ListBase *cdDM_getFaceMap(Object *ob, DerivedMesh *dm) 00174 { 00175 CDDerivedMesh *cddm = (CDDerivedMesh*) dm; 00176 00177 if(!cddm->fmap && ob->type == OB_MESH) { 00178 Mesh *me= ob->data; 00179 00180 create_vert_face_map(&cddm->fmap, &cddm->fmap_mem, me->mface, 00181 me->totvert, me->totface); 00182 } 00183 00184 return cddm->fmap; 00185 } 00186 00187 static int can_pbvh_draw(Object *ob, DerivedMesh *dm) 00188 { 00189 CDDerivedMesh *cddm = (CDDerivedMesh*) dm; 00190 Mesh *me= ob->data; 00191 int deformed= 0; 00192 00193 /* active modifiers means extra deformation, which can't be handled correct 00194 on bith of PBVH and sculpt "layer" levels, so use PBVH only for internal brush 00195 stuff and show final DerivedMesh so user would see actual object shape */ 00196 deformed|= ob->sculpt->modifiers_active; 00197 00198 /* as in case with modifiers, we can't synchronize deformation made against 00199 PBVH and non-locked keyblock, so also use PBVH only for brushes and 00200 final DM to give final result to user */ 00201 deformed|= ob->sculpt->kb && (ob->shapeflag&OB_SHAPE_LOCK) == 0; 00202 00203 if(deformed) 00204 return 0; 00205 00206 return (cddm->mvert == me->mvert) || ob->sculpt->kb; 00207 } 00208 00209 static struct PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm) 00210 { 00211 CDDerivedMesh *cddm = (CDDerivedMesh*) dm; 00212 00213 if(!ob) { 00214 cddm->pbvh= NULL; 00215 return NULL; 00216 } 00217 00218 if(!ob->sculpt) 00219 return NULL; 00220 if(ob->sculpt->pbvh) { 00221 cddm->pbvh= ob->sculpt->pbvh; 00222 cddm->pbvh_draw = can_pbvh_draw(ob, dm); 00223 } 00224 00225 /* always build pbvh from original mesh, and only use it for drawing if 00226 this derivedmesh is just original mesh. it's the multires subsurf dm 00227 that this is actually for, to support a pbvh on a modified mesh */ 00228 if(!cddm->pbvh && ob->type == OB_MESH) { 00229 SculptSession *ss= ob->sculpt; 00230 Mesh *me= ob->data; 00231 cddm->pbvh = BLI_pbvh_new(); 00232 cddm->pbvh_draw = can_pbvh_draw(ob, dm); 00233 BLI_pbvh_build_mesh(cddm->pbvh, me->mface, me->mvert, 00234 me->totface, me->totvert); 00235 00236 if(ss->modifiers_active && ob->derivedDeform) { 00237 DerivedMesh *deformdm= ob->derivedDeform; 00238 float (*vertCos)[3]; 00239 int totvert; 00240 00241 totvert= deformdm->getNumVerts(deformdm); 00242 vertCos= MEM_callocN(3*totvert*sizeof(float), "cdDM_getPBVH vertCos"); 00243 deformdm->getVertCos(deformdm, vertCos); 00244 BLI_pbvh_apply_vertCos(cddm->pbvh, vertCos); 00245 MEM_freeN(vertCos); 00246 } 00247 } 00248 00249 return cddm->pbvh; 00250 } 00251 00252 /* update vertex normals so that drawing smooth faces works during sculpt 00253 TODO: proper fix is to support the pbvh in all drawing modes */ 00254 static void cdDM_update_normals_from_pbvh(DerivedMesh *dm) 00255 { 00256 CDDerivedMesh *cddm = (CDDerivedMesh*) dm; 00257 float (*face_nors)[3]; 00258 00259 if(!cddm->pbvh || !cddm->pbvh_draw || !dm->numFaceData) 00260 return; 00261 00262 face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL); 00263 00264 BLI_pbvh_update(cddm->pbvh, PBVH_UpdateNormals, face_nors); 00265 } 00266 00267 static void cdDM_drawVerts(DerivedMesh *dm) 00268 { 00269 CDDerivedMesh *cddm = (CDDerivedMesh*) dm; 00270 MVert *mv = cddm->mvert; 00271 int i; 00272 00273 if( GPU_buffer_legacy(dm) ) { 00274 glBegin(GL_POINTS); 00275 for(i = 0; i < dm->numVertData; i++, mv++) 00276 glVertex3fv(mv->co); 00277 glEnd(); 00278 } 00279 else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */ 00280 GPU_vertex_setup(dm); 00281 if( !GPU_buffer_legacy(dm) ) { 00282 if(dm->drawObject->tot_triangle_point) 00283 glDrawArrays(GL_POINTS,0, dm->drawObject->tot_triangle_point); 00284 else 00285 glDrawArrays(GL_POINTS,0, dm->drawObject->tot_loose_point); 00286 } 00287 GPU_buffer_unbind(); 00288 } 00289 } 00290 00291 static void cdDM_drawUVEdges(DerivedMesh *dm) 00292 { 00293 CDDerivedMesh *cddm = (CDDerivedMesh*) dm; 00294 MFace *mf = cddm->mface; 00295 MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE); 00296 int i; 00297 00298 if(mf) { 00299 if( GPU_buffer_legacy(dm) ) { 00300 glBegin(GL_LINES); 00301 for(i = 0; i < dm->numFaceData; i++, mf++, tf++) { 00302 if(!(mf->flag&ME_HIDE)) { 00303 glVertex2fv(tf->uv[0]); 00304 glVertex2fv(tf->uv[1]); 00305 00306 glVertex2fv(tf->uv[1]); 00307 glVertex2fv(tf->uv[2]); 00308 00309 if(!mf->v4) { 00310 glVertex2fv(tf->uv[2]); 00311 glVertex2fv(tf->uv[0]); 00312 } else { 00313 glVertex2fv(tf->uv[2]); 00314 glVertex2fv(tf->uv[3]); 00315 00316 glVertex2fv(tf->uv[3]); 00317 glVertex2fv(tf->uv[0]); 00318 } 00319 } 00320 } 00321 glEnd(); 00322 } 00323 else { 00324 int prevstart = 0; 00325 int prevdraw = 1; 00326 int draw = 1; 00327 int curpos = 0; 00328 00329 GPU_uvedge_setup(dm); 00330 if( !GPU_buffer_legacy(dm) ) { 00331 for(i = 0; i < dm->numFaceData; i++, mf++) { 00332 if(!(mf->flag&ME_HIDE)) { 00333 draw = 1; 00334 } 00335 else { 00336 draw = 0; 00337 } 00338 if( prevdraw != draw ) { 00339 if( prevdraw > 0 && (curpos-prevstart) > 0) { 00340 glDrawArrays(GL_LINES,prevstart,curpos-prevstart); 00341 } 00342 prevstart = curpos; 00343 } 00344 if( mf->v4 ) { 00345 curpos += 8; 00346 } 00347 else { 00348 curpos += 6; 00349 } 00350 prevdraw = draw; 00351 } 00352 if( prevdraw > 0 && (curpos-prevstart) > 0 ) { 00353 glDrawArrays(GL_LINES,prevstart,curpos-prevstart); 00354 } 00355 } 00356 GPU_buffer_unbind(); 00357 } 00358 } 00359 } 00360 00361 static void cdDM_drawEdges(DerivedMesh *dm, int drawLooseEdges, int drawAllEdges) 00362 { 00363 CDDerivedMesh *cddm = (CDDerivedMesh*) dm; 00364 MVert *mvert = cddm->mvert; 00365 MEdge *medge = cddm->medge; 00366 int i; 00367 00368 if( GPU_buffer_legacy(dm) ) { 00369 DEBUG_VBO( "Using legacy code. cdDM_drawEdges\n" ); 00370 glBegin(GL_LINES); 00371 for(i = 0; i < dm->numEdgeData; i++, medge++) { 00372 if((drawAllEdges || (medge->flag&ME_EDGEDRAW)) 00373 && (drawLooseEdges || !(medge->flag&ME_LOOSEEDGE))) { 00374 glVertex3fv(mvert[medge->v1].co); 00375 glVertex3fv(mvert[medge->v2].co); 00376 } 00377 } 00378 glEnd(); 00379 } 00380 else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */ 00381 int prevstart = 0; 00382 int prevdraw = 1; 00383 int draw = 1; 00384 00385 GPU_edge_setup(dm); 00386 if( !GPU_buffer_legacy(dm) ) { 00387 for(i = 0; i < dm->numEdgeData; i++, medge++) { 00388 if((drawAllEdges || (medge->flag&ME_EDGEDRAW)) 00389 && (drawLooseEdges || !(medge->flag&ME_LOOSEEDGE))) { 00390 draw = 1; 00391 } 00392 else { 00393 draw = 0; 00394 } 00395 if( prevdraw != draw ) { 00396 if( prevdraw > 0 && (i-prevstart) > 0 ) { 00397 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2 ); 00398 } 00399 prevstart = i; 00400 } 00401 prevdraw = draw; 00402 } 00403 if( prevdraw > 0 && (i-prevstart) > 0 ) { 00404 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2 ); 00405 } 00406 } 00407 GPU_buffer_unbind(); 00408 } 00409 } 00410 00411 static void cdDM_drawLooseEdges(DerivedMesh *dm) 00412 { 00413 CDDerivedMesh *cddm = (CDDerivedMesh*) dm; 00414 MVert *mvert = cddm->mvert; 00415 MEdge *medge = cddm->medge; 00416 int i; 00417 00418 if( GPU_buffer_legacy(dm) ) { 00419 DEBUG_VBO( "Using legacy code. cdDM_drawLooseEdges\n" ); 00420 glBegin(GL_LINES); 00421 for(i = 0; i < dm->numEdgeData; i++, medge++) { 00422 if(medge->flag&ME_LOOSEEDGE) { 00423 glVertex3fv(mvert[medge->v1].co); 00424 glVertex3fv(mvert[medge->v2].co); 00425 } 00426 } 00427 glEnd(); 00428 } 00429 else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */ 00430 int prevstart = 0; 00431 int prevdraw = 1; 00432 int draw = 1; 00433 00434 GPU_edge_setup(dm); 00435 if( !GPU_buffer_legacy(dm) ) { 00436 for(i = 0; i < dm->numEdgeData; i++, medge++) { 00437 if(medge->flag&ME_LOOSEEDGE) { 00438 draw = 1; 00439 } 00440 else { 00441 draw = 0; 00442 } 00443 if( prevdraw != draw ) { 00444 if( prevdraw > 0 && (i-prevstart) > 0) { 00445 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2 ); 00446 } 00447 prevstart = i; 00448 } 00449 prevdraw = draw; 00450 } 00451 if( prevdraw > 0 && (i-prevstart) > 0 ) { 00452 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2 ); 00453 } 00454 } 00455 GPU_buffer_unbind(); 00456 } 00457 } 00458 00459 static void cdDM_drawFacesSolid(DerivedMesh *dm, 00460 float (*partial_redraw_planes)[4], 00461 int UNUSED(fast), int (*setMaterial)(int, void *attribs)) 00462 { 00463 CDDerivedMesh *cddm = (CDDerivedMesh*) dm; 00464 MVert *mvert = cddm->mvert; 00465 MFace *mface = cddm->mface; 00466 float *nors= dm->getFaceDataArray(dm, CD_NORMAL); 00467 int a, glmode = -1, shademodel = -1, matnr = -1, drawCurrentMat = 1; 00468 00469 #define PASSVERT(index) { \ 00470 if(shademodel == GL_SMOOTH) { \ 00471 short *no = mvert[index].no; \ 00472 glNormal3sv(no); \ 00473 } \ 00474 glVertex3fv(mvert[index].co); \ 00475 } 00476 00477 if(cddm->pbvh && cddm->pbvh_draw) { 00478 if(dm->numFaceData) { 00479 float (*face_nors)[3] = CustomData_get_layer(&dm->faceData, CD_NORMAL); 00480 00481 /* should be per face */ 00482 if(!setMaterial(mface->mat_nr+1, NULL)) 00483 return; 00484 00485 glShadeModel((mface->flag & ME_SMOOTH)? GL_SMOOTH: GL_FLAT); 00486 BLI_pbvh_draw(cddm->pbvh, partial_redraw_planes, face_nors, (mface->flag & ME_SMOOTH)); 00487 glShadeModel(GL_FLAT); 00488 } 00489 00490 return; 00491 } 00492 00493 if( GPU_buffer_legacy(dm) ) { 00494 DEBUG_VBO( "Using legacy code. cdDM_drawFacesSolid\n" ); 00495 glBegin(glmode = GL_QUADS); 00496 for(a = 0; a < dm->numFaceData; a++, mface++) { 00497 int new_glmode, new_matnr, new_shademodel; 00498 00499 new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES; 00500 new_matnr = mface->mat_nr + 1; 00501 new_shademodel = (mface->flag & ME_SMOOTH)?GL_SMOOTH:GL_FLAT; 00502 00503 if(new_glmode != glmode || new_matnr != matnr 00504 || new_shademodel != shademodel) { 00505 glEnd(); 00506 00507 drawCurrentMat = setMaterial(matnr = new_matnr, NULL); 00508 00509 glShadeModel(shademodel = new_shademodel); 00510 glBegin(glmode = new_glmode); 00511 } 00512 00513 if(drawCurrentMat) { 00514 if(shademodel == GL_FLAT) { 00515 if (nors) { 00516 glNormal3fv(nors); 00517 } 00518 else { 00519 /* TODO make this better (cache facenormals as layer?) */ 00520 float nor[3]; 00521 if(mface->v4) { 00522 normal_quad_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co); 00523 } else { 00524 normal_tri_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co); 00525 } 00526 glNormal3fv(nor); 00527 } 00528 } 00529 00530 PASSVERT(mface->v1); 00531 PASSVERT(mface->v2); 00532 PASSVERT(mface->v3); 00533 if(mface->v4) { 00534 PASSVERT(mface->v4); 00535 } 00536 } 00537 00538 if(nors) nors += 3; 00539 } 00540 glEnd(); 00541 } 00542 else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */ 00543 GPU_vertex_setup( dm ); 00544 GPU_normal_setup( dm ); 00545 if( !GPU_buffer_legacy(dm) ) { 00546 glShadeModel(GL_SMOOTH); 00547 for( a = 0; a < dm->drawObject->totmaterial; a++ ) { 00548 if( setMaterial(dm->drawObject->materials[a].mat_nr+1, NULL) ) 00549 glDrawArrays(GL_TRIANGLES, dm->drawObject->materials[a].start, 00550 dm->drawObject->materials[a].totpoint); 00551 } 00552 } 00553 GPU_buffer_unbind( ); 00554 } 00555 00556 #undef PASSVERT 00557 glShadeModel(GL_FLAT); 00558 } 00559 00560 static void cdDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2) 00561 { 00562 CDDerivedMesh *cddm = (CDDerivedMesh*) dm; 00563 int a, glmode; 00564 unsigned char *cp1, *cp2; 00565 MVert *mvert = cddm->mvert; 00566 MFace *mface = cddm->mface; 00567 00568 cp1 = col1; 00569 if(col2) { 00570 cp2 = col2; 00571 } else { 00572 cp2 = NULL; 00573 useTwoSided = 0; 00574 } 00575 00576 /* there's a conflict here... twosided colors versus culling...? */ 00577 /* defined by history, only texture faces have culling option */ 00578 /* we need that as mesh option builtin, next to double sided lighting */ 00579 if(col2) { 00580 glEnable(GL_CULL_FACE); 00581 } 00582 00583 cdDM_update_normals_from_pbvh(dm); 00584 00585 if( GPU_buffer_legacy(dm) ) { 00586 DEBUG_VBO( "Using legacy code. cdDM_drawFacesColored\n" ); 00587 glShadeModel(GL_SMOOTH); 00588 glBegin(glmode = GL_QUADS); 00589 for(a = 0; a < dm->numFaceData; a++, mface++, cp1 += 16) { 00590 int new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES; 00591 00592 if(new_glmode != glmode) { 00593 glEnd(); 00594 glBegin(glmode = new_glmode); 00595 } 00596 00597 glColor3ubv(cp1+0); 00598 glVertex3fv(mvert[mface->v1].co); 00599 glColor3ubv(cp1+4); 00600 glVertex3fv(mvert[mface->v2].co); 00601 glColor3ubv(cp1+8); 00602 glVertex3fv(mvert[mface->v3].co); 00603 if(mface->v4) { 00604 glColor3ubv(cp1+12); 00605 glVertex3fv(mvert[mface->v4].co); 00606 } 00607 00608 if(useTwoSided) { 00609 glColor3ubv(cp2+8); 00610 glVertex3fv(mvert[mface->v3].co ); 00611 glColor3ubv(cp2+4); 00612 glVertex3fv(mvert[mface->v2].co ); 00613 glColor3ubv(cp2+0); 00614 glVertex3fv(mvert[mface->v1].co ); 00615 if(mface->v4) { 00616 glColor3ubv(cp2+12); 00617 glVertex3fv(mvert[mface->v4].co ); 00618 } 00619 } 00620 if(col2) cp2 += 16; 00621 } 00622 glEnd(); 00623 } 00624 else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */ 00625 GPU_color4_upload(dm,cp1); 00626 GPU_vertex_setup(dm); 00627 GPU_color_setup(dm); 00628 if( !GPU_buffer_legacy(dm) ) { 00629 glShadeModel(GL_SMOOTH); 00630 glDrawArrays(GL_TRIANGLES, 0, dm->drawObject->tot_triangle_point); 00631 00632 if( useTwoSided ) { 00633 GPU_color4_upload(dm,cp2); 00634 GPU_color_setup(dm); 00635 glCullFace(GL_FRONT); 00636 glDrawArrays(GL_TRIANGLES, 0, dm->drawObject->tot_triangle_point); 00637 glCullFace(GL_BACK); 00638 } 00639 } 00640 GPU_buffer_unbind(); 00641 } 00642 00643 glShadeModel(GL_FLAT); 00644 glDisable(GL_CULL_FACE); 00645 } 00646 00647 static void cdDM_drawFacesTex_common(DerivedMesh *dm, 00648 int (*drawParams)(MTFace *tface, int has_mcol, int matnr), 00649 int (*drawParamsMapped)(void *userData, int index), 00650 int (*compareDrawOptions)(void *userData, int cur_index, int next_index), 00651 void *userData) 00652 { 00653 CDDerivedMesh *cddm = (CDDerivedMesh*) dm; 00654 MVert *mv = cddm->mvert; 00655 MFace *mf = DM_get_face_data_layer(dm, CD_MFACE); 00656 MCol *realcol = dm->getFaceDataArray(dm, CD_TEXTURE_MCOL); 00657 float *nors= dm->getFaceDataArray(dm, CD_NORMAL); 00658 MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE); 00659 int i, j, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX); 00660 int startFace = 0 /*, lastFlag = 0xdeadbeef */ /* UNUSED */; 00661 MCol *mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL); 00662 if(!mcol) 00663 mcol = dm->getFaceDataArray(dm, CD_MCOL); 00664 00665 cdDM_update_normals_from_pbvh(dm); 00666 00667 if( GPU_buffer_legacy(dm) ) { 00668 DEBUG_VBO( "Using legacy code. cdDM_drawFacesTex_common\n" ); 00669 for(i = 0; i < dm->numFaceData; i++, mf++) { 00670 MVert *mvert; 00671 int flag; 00672 unsigned char *cp = NULL; 00673 00674 if(drawParams) { 00675 flag = drawParams(tf? &tf[i]: NULL, (mcol != NULL), mf->mat_nr); 00676 } 00677 else { 00678 if(index) { 00679 orig = *index++; 00680 if(orig == ORIGINDEX_NONE) { if(nors) nors += 3; continue; } 00681 if(drawParamsMapped) flag = drawParamsMapped(userData, orig); 00682 else { if(nors) nors += 3; continue; } 00683 } 00684 else 00685 if(drawParamsMapped) flag = drawParamsMapped(userData, i); 00686 else { if(nors) nors += 3; continue; } 00687 } 00688 00689 if(flag != 0) { 00690 if (flag==1 && mcol) 00691 cp= (unsigned char*) &mcol[i*4]; 00692 00693 if(!(mf->flag&ME_SMOOTH)) { 00694 if (nors) { 00695 glNormal3fv(nors); 00696 } 00697 else { 00698 float nor[3]; 00699 if(mf->v4) { 00700 normal_quad_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co); 00701 } else { 00702 normal_tri_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co); 00703 } 00704 glNormal3fv(nor); 00705 } 00706 } 00707 00708 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES); 00709 if(tf) glTexCoord2fv(tf[i].uv[0]); 00710 if(cp) glColor3ub(cp[3], cp[2], cp[1]); 00711 mvert = &mv[mf->v1]; 00712 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no); 00713 glVertex3fv(mvert->co); 00714 00715 if(tf) glTexCoord2fv(tf[i].uv[1]); 00716 if(cp) glColor3ub(cp[7], cp[6], cp[5]); 00717 mvert = &mv[mf->v2]; 00718 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no); 00719 glVertex3fv(mvert->co); 00720 00721 if(tf) glTexCoord2fv(tf[i].uv[2]); 00722 if(cp) glColor3ub(cp[11], cp[10], cp[9]); 00723 mvert = &mv[mf->v3]; 00724 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no); 00725 glVertex3fv(mvert->co); 00726 00727 if(mf->v4) { 00728 if(tf) glTexCoord2fv(tf[i].uv[3]); 00729 if(cp) glColor3ub(cp[15], cp[14], cp[13]); 00730 mvert = &mv[mf->v4]; 00731 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no); 00732 glVertex3fv(mvert->co); 00733 } 00734 glEnd(); 00735 } 00736 00737 if(nors) nors += 3; 00738 } 00739 } else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */ 00740 MCol *col = realcol; 00741 if(!col) 00742 col = mcol; 00743 00744 GPU_vertex_setup( dm ); 00745 GPU_normal_setup( dm ); 00746 GPU_uv_setup( dm ); 00747 if( col != NULL ) { 00748 /*if( realcol && dm->drawObject->colType == CD_TEXTURE_MCOL ) { 00749 col = 0; 00750 } else if( mcol && dm->drawObject->colType == CD_MCOL ) { 00751 col = 0; 00752 } 00753 00754 if( col != 0 ) {*/ 00755 unsigned char *colors = MEM_mallocN(dm->getNumFaces(dm)*4*3*sizeof(unsigned char), "cdDM_drawFacesTex_common"); 00756 for( i=0; i < dm->getNumFaces(dm); i++ ) { 00757 for( j=0; j < 4; j++ ) { 00758 /* bgr -> rgb is intentional (and stupid), but how its stored internally */ 00759 colors[i*12+j*3] = col[i*4+j].b; 00760 colors[i*12+j*3+1] = col[i*4+j].g; 00761 colors[i*12+j*3+2] = col[i*4+j].r; 00762 } 00763 } 00764 GPU_color3_upload(dm,colors); 00765 MEM_freeN(colors); 00766 if(realcol) 00767 dm->drawObject->colType = CD_TEXTURE_MCOL; 00768 else if(mcol) 00769 dm->drawObject->colType = CD_MCOL; 00770 //} 00771 GPU_color_setup( dm ); 00772 } 00773 00774 if( !GPU_buffer_legacy(dm) ) { 00775 int tottri = dm->drawObject->tot_triangle_point/3; 00776 int next_actualFace= dm->drawObject->triangle_to_mface[0]; 00777 00778 glShadeModel( GL_SMOOTH ); 00779 /* lastFlag = 0; */ /* UNUSED */ 00780 for(i = 0; i < tottri; i++) { 00781 int actualFace = next_actualFace; 00782 int flag = 1; 00783 int flush = 0; 00784 00785 if(i != tottri-1) 00786 next_actualFace= dm->drawObject->triangle_to_mface[i+1]; 00787 00788 if(drawParams) { 00789 flag = drawParams(tf? &tf[actualFace]: NULL, (mcol != NULL), mf[actualFace].mat_nr); 00790 } 00791 else { 00792 if(index) { 00793 orig = index[actualFace]; 00794 if(orig == ORIGINDEX_NONE) continue; 00795 if(drawParamsMapped) 00796 flag = drawParamsMapped(userData, orig); 00797 } 00798 else 00799 if(drawParamsMapped) 00800 flag = drawParamsMapped(userData, actualFace); 00801 } 00802 00803 /* flush buffer if current triangle isn't drawable or it's last triangle */ 00804 flush= !flag || i == tottri - 1; 00805 00806 if(!flush && compareDrawOptions) { 00807 /* also compare draw options and flush buffer if they're different 00808 need for face selection highlight in edit mode */ 00809 flush|= compareDrawOptions(userData, actualFace, next_actualFace) == 0; 00810 } 00811 00812 if(flush) { 00813 int first= startFace*3; 00814 int count= (i-startFace+(flag ? 1 : 0))*3; /* Add one to the length if we're drawing at the end of the array */ 00815 00816 if(count) { 00817 if (col) 00818 GPU_color_switch(1); 00819 else 00820 GPU_color_switch(0); 00821 00822 glDrawArrays(GL_TRIANGLES, first, count); 00823 } 00824 00825 startFace = i + 1; 00826 } 00827 } 00828 } 00829 00830 GPU_buffer_unbind(); 00831 glShadeModel( GL_FLAT ); 00832 } 00833 } 00834 00835 static void cdDM_drawFacesTex(DerivedMesh *dm, 00836 int (*setDrawOptions)(MTFace *tface, int has_mcol, int matnr), 00837 int (*compareDrawOptions)(void *userData, int cur_index, int next_index), 00838 void *userData) 00839 { 00840 cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData); 00841 } 00842 00843 static void cdDM_drawMappedFaces(DerivedMesh *dm, 00844 int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), 00845 int (*setMaterial)(int, void *attribs), 00846 int (*compareDrawOptions)(void *userData, int cur_index, int next_index), 00847 void *userData, int useColors) 00848 { 00849 CDDerivedMesh *cddm = (CDDerivedMesh*) dm; 00850 MVert *mv = cddm->mvert; 00851 MFace *mf = cddm->mface; 00852 MCol *mc; 00853 float *nors= dm->getFaceDataArray(dm, CD_NORMAL); 00854 int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX); 00855 00856 mc = DM_get_face_data_layer(dm, CD_ID_MCOL); 00857 if(!mc) 00858 mc = DM_get_face_data_layer(dm, CD_WEIGHT_MCOL); 00859 if(!mc) 00860 mc = DM_get_face_data_layer(dm, CD_MCOL); 00861 00862 cdDM_update_normals_from_pbvh(dm); 00863 00864 /* back-buffer always uses legacy since VBO's would need the 00865 * color array temporarily overwritten for drawing, then reset. */ 00866 if( GPU_buffer_legacy(dm) || G.f & G_BACKBUFSEL) { 00867 DEBUG_VBO( "Using legacy code. cdDM_drawMappedFaces\n" ); 00868 for(i = 0; i < dm->numFaceData; i++, mf++) { 00869 int drawSmooth = (mf->flag & ME_SMOOTH); 00870 int draw= 1; 00871 00872 orig= (index==NULL) ? i : *index++; 00873 00874 if(orig == ORIGINDEX_NONE) 00875 draw= setMaterial(mf->mat_nr + 1, NULL); 00876 else if (setDrawOptions != NULL) 00877 draw= setDrawOptions(userData, orig, &drawSmooth); 00878 00879 if(draw) { 00880 unsigned char *cp = NULL; 00881 00882 if(useColors && mc) 00883 cp = (unsigned char *)&mc[i * 4]; 00884 00885 /* no need to set shading mode to flat because 00886 * normals are already used to change shading */ 00887 glShadeModel(GL_SMOOTH); 00888 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES); 00889 00890 if (!drawSmooth) { 00891 if (nors) { 00892 glNormal3fv(nors); 00893 } 00894 else { 00895 float nor[3]; 00896 if(mf->v4) { 00897 normal_quad_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co); 00898 } else { 00899 normal_tri_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co); 00900 } 00901 glNormal3fv(nor); 00902 } 00903 00904 if(cp) glColor3ub(cp[3], cp[2], cp[1]); 00905 glVertex3fv(mv[mf->v1].co); 00906 if(cp) glColor3ub(cp[7], cp[6], cp[5]); 00907 glVertex3fv(mv[mf->v2].co); 00908 if(cp) glColor3ub(cp[11], cp[10], cp[9]); 00909 glVertex3fv(mv[mf->v3].co); 00910 if(mf->v4) { 00911 if(cp) glColor3ub(cp[15], cp[14], cp[13]); 00912 glVertex3fv(mv[mf->v4].co); 00913 } 00914 } else { 00915 if(cp) glColor3ub(cp[3], cp[2], cp[1]); 00916 glNormal3sv(mv[mf->v1].no); 00917 glVertex3fv(mv[mf->v1].co); 00918 if(cp) glColor3ub(cp[7], cp[6], cp[5]); 00919 glNormal3sv(mv[mf->v2].no); 00920 glVertex3fv(mv[mf->v2].co); 00921 if(cp) glColor3ub(cp[11], cp[10], cp[9]); 00922 glNormal3sv(mv[mf->v3].no); 00923 glVertex3fv(mv[mf->v3].co); 00924 if(mf->v4) { 00925 if(cp) glColor3ub(cp[15], cp[14], cp[13]); 00926 glNormal3sv(mv[mf->v4].no); 00927 glVertex3fv(mv[mf->v4].co); 00928 } 00929 } 00930 00931 glEnd(); 00932 } 00933 00934 if (nors) nors += 3; 00935 } 00936 } 00937 else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */ 00938 int prevstart = 0; 00939 GPU_vertex_setup(dm); 00940 GPU_normal_setup(dm); 00941 if( useColors && mc ) 00942 GPU_color_setup(dm); 00943 if( !GPU_buffer_legacy(dm) ) { 00944 int tottri = dm->drawObject->tot_triangle_point/3; 00945 glShadeModel(GL_SMOOTH); 00946 00947 if(tottri == 0) { 00948 /* avoid buffer problems in following code */ 00949 } 00950 if(setDrawOptions == NULL) { 00951 /* just draw the entire face array */ 00952 glDrawArrays(GL_TRIANGLES, 0, (tottri) * 3); 00953 } 00954 else { 00955 /* we need to check if the next material changes */ 00956 int next_actualFace= dm->drawObject->triangle_to_mface[0]; 00957 00958 for( i = 0; i < tottri; i++ ) { 00959 //int actualFace = dm->drawObject->triangle_to_mface[i]; 00960 int actualFace = next_actualFace; 00961 MFace *mface= mf + actualFace; 00962 int drawSmooth= (mface->flag & ME_SMOOTH); 00963 int draw = 1; 00964 int flush = 0; 00965 00966 if(i != tottri-1) 00967 next_actualFace= dm->drawObject->triangle_to_mface[i+1]; 00968 00969 orig= (index==NULL) ? actualFace : index[actualFace]; 00970 00971 if(orig == ORIGINDEX_NONE) 00972 draw= setMaterial(mface->mat_nr + 1, NULL); 00973 else if (setDrawOptions != NULL) 00974 draw= setDrawOptions(userData, orig, &drawSmooth); 00975 00976 /* Goal is to draw as long of a contiguous triangle 00977 array as possible, so draw when we hit either an 00978 invisible triangle or at the end of the array */ 00979 00980 /* flush buffer if current triangle isn't drawable or it's last triangle... */ 00981 flush= !draw || i == tottri - 1; 00982 00983 /* ... or when material setting is dissferent */ 00984 flush|= mf[actualFace].mat_nr != mf[next_actualFace].mat_nr; 00985 00986 if(!flush && compareDrawOptions) { 00987 flush|= compareDrawOptions(userData, actualFace, next_actualFace) == 0; 00988 } 00989 00990 if(flush) { 00991 int first= prevstart*3; 00992 int count= (i-prevstart+(draw ? 1 : 0))*3; /* Add one to the length if we're drawing at the end of the array */ 00993 00994 if(count) 00995 glDrawArrays(GL_TRIANGLES, first, count); 00996 00997 prevstart = i + 1; 00998 } 00999 } 01000 } 01001 01002 glShadeModel(GL_FLAT); 01003 } 01004 GPU_buffer_unbind(); 01005 } 01006 } 01007 01008 static void cdDM_drawMappedFacesTex(DerivedMesh *dm, 01009 int (*setDrawOptions)(void *userData, int index), 01010 int (*compareDrawOptions)(void *userData, int cur_index, int next_index), 01011 void *userData) 01012 { 01013 cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData); 01014 } 01015 01016 static void cddm_draw_attrib_vertex(DMVertexAttribs *attribs, MVert *mvert, int a, int index, int vert, int smoothnormal) 01017 { 01018 int b; 01019 01020 /* orco texture coordinates */ 01021 if(attribs->totorco) { 01022 if(attribs->orco.glTexco) 01023 glTexCoord3fv(attribs->orco.array[index]); 01024 else 01025 glVertexAttrib3fvARB(attribs->orco.glIndex, attribs->orco.array[index]); 01026 } 01027 01028 /* uv texture coordinates */ 01029 for(b = 0; b < attribs->tottface; b++) { 01030 MTFace *tf = &attribs->tface[b].array[a]; 01031 01032 if(attribs->tface[b].glTexco) 01033 glTexCoord2fv(tf->uv[vert]); 01034 else 01035 glVertexAttrib2fvARB(attribs->tface[b].glIndex, tf->uv[vert]); 01036 } 01037 01038 /* vertex colors */ 01039 for(b = 0; b < attribs->totmcol; b++) { 01040 MCol *cp = &attribs->mcol[b].array[a*4 + vert]; 01041 GLubyte col[4]; 01042 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; 01043 glVertexAttrib4ubvARB(attribs->mcol[b].glIndex, col); 01044 } 01045 01046 /* tangent for normal mapping */ 01047 if(attribs->tottang) { 01048 float *tang = attribs->tang.array[a*4 + vert]; 01049 glVertexAttrib4fvARB(attribs->tang.glIndex, tang); 01050 } 01051 01052 /* vertex normal */ 01053 if(smoothnormal) 01054 glNormal3sv(mvert[index].no); 01055 01056 /* vertex coordinate */ 01057 glVertex3fv(mvert[index].co); 01058 } 01059 01060 static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, 01061 int (*setMaterial)(int, void *attribs), 01062 int (*setDrawOptions)(void *userData, int index), 01063 void *userData) 01064 { 01065 CDDerivedMesh *cddm = (CDDerivedMesh*) dm; 01066 GPUVertexAttribs gattribs; 01067 DMVertexAttribs attribs; 01068 MVert *mvert = cddm->mvert; 01069 MFace *mface = cddm->mface; 01070 /* MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */ 01071 float (*nors)[3] = dm->getFaceDataArray(dm, CD_NORMAL); 01072 int a, b, dodraw, matnr, new_matnr; 01073 int orig, *index = dm->getFaceDataArray(dm, CD_ORIGINDEX); 01074 01075 cdDM_update_normals_from_pbvh(dm); 01076 01077 matnr = -1; 01078 dodraw = 0; 01079 01080 glShadeModel(GL_SMOOTH); 01081 01082 if( GPU_buffer_legacy(dm) || setDrawOptions != NULL ) { 01083 DEBUG_VBO( "Using legacy code. cdDM_drawMappedFacesGLSL\n" ); 01084 memset(&attribs, 0, sizeof(attribs)); 01085 01086 glBegin(GL_QUADS); 01087 01088 for(a = 0; a < dm->numFaceData; a++, mface++) { 01089 const int smoothnormal = (mface->flag & ME_SMOOTH); 01090 new_matnr = mface->mat_nr + 1; 01091 01092 if(new_matnr != matnr) { 01093 glEnd(); 01094 01095 dodraw = setMaterial(matnr = new_matnr, &gattribs); 01096 if(dodraw) 01097 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); 01098 01099 glBegin(GL_QUADS); 01100 } 01101 01102 if(!dodraw) { 01103 continue; 01104 } 01105 else if(setDrawOptions) { 01106 orig = (index)? index[a]: a; 01107 01108 if(orig == ORIGINDEX_NONE) { 01109 /* since the material is set by setMaterial(), faces with no 01110 * origin can be assumed to be generated by a modifier */ 01111 01112 /* continue */ 01113 } 01114 else if(!setDrawOptions(userData, orig)) 01115 continue; 01116 } 01117 01118 if(!smoothnormal) { 01119 if(nors) { 01120 glNormal3fv(nors[a]); 01121 } 01122 else { 01123 /* TODO ideally a normal layer should always be available */ 01124 float nor[3]; 01125 if(mface->v4) { 01126 normal_quad_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co); 01127 } else { 01128 normal_tri_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co); 01129 } 01130 glNormal3fv(nor); 01131 } 01132 } 01133 01134 cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v1, 0, smoothnormal); 01135 cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v2, 1, smoothnormal); 01136 cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v3, 2, smoothnormal); 01137 01138 if(mface->v4) 01139 cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v4, 3, smoothnormal); 01140 else 01141 cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v3, 2, smoothnormal); 01142 } 01143 glEnd(); 01144 } 01145 else { 01146 GPUBuffer *buffer = NULL; 01147 char *varray = NULL; 01148 int numdata = 0, elementsize = 0, offset; 01149 int start = 0, numfaces = 0 /* , prevdraw = 0 */ /* UNUSED */, curface = 0; 01150 int i; 01151 01152 MFace *mf = mface; 01153 GPUAttrib datatypes[GPU_MAX_ATTRIB]; /* TODO, messing up when switching materials many times - [#21056]*/ 01154 memset(&attribs, 0, sizeof(attribs)); 01155 01156 GPU_vertex_setup(dm); 01157 GPU_normal_setup(dm); 01158 01159 if( !GPU_buffer_legacy(dm) ) { 01160 for( i = 0; i < dm->drawObject->tot_triangle_point/3; i++ ) { 01161 01162 a = dm->drawObject->triangle_to_mface[i]; 01163 01164 mface = mf + a; 01165 new_matnr = mface->mat_nr + 1; 01166 01167 if(new_matnr != matnr ) { 01168 numfaces = curface - start; 01169 if( numfaces > 0 ) { 01170 01171 if( dodraw ) { 01172 01173 if( numdata != 0 ) { 01174 01175 GPU_buffer_unlock(buffer); 01176 01177 GPU_interleaved_attrib_setup(buffer,datatypes,numdata); 01178 } 01179 01180 glDrawArrays(GL_TRIANGLES,start*3,numfaces*3); 01181 01182 if( numdata != 0 ) { 01183 01184 GPU_buffer_free(buffer); 01185 01186 buffer = NULL; 01187 } 01188 01189 } 01190 } 01191 numdata = 0; 01192 start = curface; 01193 /* prevdraw = dodraw; */ /* UNUSED */ 01194 dodraw = setMaterial(matnr = new_matnr, &gattribs); 01195 if(dodraw) { 01196 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); 01197 01198 if(attribs.totorco) { 01199 datatypes[numdata].index = attribs.orco.glIndex; 01200 datatypes[numdata].size = 3; 01201 datatypes[numdata].type = GL_FLOAT; 01202 numdata++; 01203 } 01204 for(b = 0; b < attribs.tottface; b++) { 01205 datatypes[numdata].index = attribs.tface[b].glIndex; 01206 datatypes[numdata].size = 2; 01207 datatypes[numdata].type = GL_FLOAT; 01208 numdata++; 01209 } 01210 for(b = 0; b < attribs.totmcol; b++) { 01211 datatypes[numdata].index = attribs.mcol[b].glIndex; 01212 datatypes[numdata].size = 4; 01213 datatypes[numdata].type = GL_UNSIGNED_BYTE; 01214 numdata++; 01215 } 01216 if(attribs.tottang) { 01217 datatypes[numdata].index = attribs.tang.glIndex; 01218 datatypes[numdata].size = 4; 01219 datatypes[numdata].type = GL_FLOAT; 01220 numdata++; 01221 } 01222 if( numdata != 0 ) { 01223 elementsize = GPU_attrib_element_size( datatypes, numdata ); 01224 buffer = GPU_buffer_alloc( elementsize*dm->drawObject->tot_triangle_point); 01225 if( buffer == NULL ) { 01226 GPU_buffer_unbind(); 01227 dm->drawObject->legacy = 1; 01228 return; 01229 } 01230 varray = GPU_buffer_lock_stream(buffer); 01231 if( varray == NULL ) { 01232 GPU_buffer_unbind(); 01233 GPU_buffer_free(buffer); 01234 dm->drawObject->legacy = 1; 01235 return; 01236 } 01237 } 01238 else { 01239 /* if the buffer was set, dont use it again. 01240 * prevdraw was assumed true but didnt run so set to false - [#21036] */ 01241 /* prevdraw= 0; */ /* UNUSED */ 01242 buffer= NULL; 01243 } 01244 } 01245 } 01246 01247 if(dodraw && numdata != 0 ) { 01248 offset = 0; 01249 if(attribs.totorco) { 01250 copy_v3_v3((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v1]); 01251 copy_v3_v3((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v2]); 01252 copy_v3_v3((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v3]); 01253 offset += sizeof(float)*3; 01254 } 01255 for(b = 0; b < attribs.tottface; b++) { 01256 MTFace *tf = &attribs.tface[b].array[a]; 01257 copy_v2_v2((float *)&varray[elementsize*curface*3+offset],tf->uv[0]); 01258 copy_v2_v2((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[1]); 01259 01260 copy_v2_v2((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[2]); 01261 offset += sizeof(float)*2; 01262 } 01263 for(b = 0; b < attribs.totmcol; b++) { 01264 MCol *cp = &attribs.mcol[b].array[a*4 + 0]; 01265 GLubyte col[4]; 01266 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; 01267 copy_v4_v4_char((char *)&varray[elementsize*curface*3+offset], (char *)col); 01268 cp = &attribs.mcol[b].array[a*4 + 1]; 01269 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; 01270 copy_v4_v4_char((char *)&varray[elementsize*curface*3+offset+elementsize], (char *)col); 01271 cp = &attribs.mcol[b].array[a*4 + 2]; 01272 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; 01273 copy_v4_v4_char((char *)&varray[elementsize*curface*3+offset+elementsize*2], (char *)col); 01274 offset += sizeof(unsigned char)*4; 01275 } 01276 if(attribs.tottang) { 01277 float *tang = attribs.tang.array[a*4 + 0]; 01278 copy_v4_v4((float *)&varray[elementsize*curface*3+offset], tang); 01279 tang = attribs.tang.array[a*4 + 1]; 01280 copy_v4_v4((float *)&varray[elementsize*curface*3+offset+elementsize], tang); 01281 tang = attribs.tang.array[a*4 + 2]; 01282 copy_v4_v4((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang); 01283 offset += sizeof(float)*4; 01284 } 01285 (void)offset; 01286 } 01287 curface++; 01288 if(mface->v4) { 01289 if(dodraw && numdata != 0 ) { 01290 offset = 0; 01291 if(attribs.totorco) { 01292 copy_v3_v3((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v3]); 01293 copy_v3_v3((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v4]); 01294 copy_v3_v3((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v1]); 01295 offset += sizeof(float)*3; 01296 } 01297 for(b = 0; b < attribs.tottface; b++) { 01298 MTFace *tf = &attribs.tface[b].array[a]; 01299 copy_v2_v2((float *)&varray[elementsize*curface*3+offset],tf->uv[2]); 01300 copy_v2_v2((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[3]); 01301 copy_v2_v2((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[0]); 01302 offset += sizeof(float)*2; 01303 } 01304 for(b = 0; b < attribs.totmcol; b++) { 01305 MCol *cp = &attribs.mcol[b].array[a*4 + 2]; 01306 GLubyte col[4]; 01307 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; 01308 copy_v4_v4_char((char *)&varray[elementsize*curface*3+offset], (char *)col); 01309 cp = &attribs.mcol[b].array[a*4 + 3]; 01310 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; 01311 copy_v4_v4_char((char *)&varray[elementsize*curface*3+offset+elementsize], (char *)col); 01312 cp = &attribs.mcol[b].array[a*4 + 0]; 01313 col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; 01314 copy_v4_v4_char((char *)&varray[elementsize*curface*3+offset+elementsize*2], (char *)col); 01315 offset += sizeof(unsigned char)*4; 01316 } 01317 if(attribs.tottang) { 01318 float *tang = attribs.tang.array[a*4 + 2]; 01319 copy_v4_v4((float *)&varray[elementsize*curface*3+offset], tang); 01320 tang = attribs.tang.array[a*4 + 3]; 01321 copy_v4_v4((float *)&varray[elementsize*curface*3+offset+elementsize], tang); 01322 tang = attribs.tang.array[a*4 + 0]; 01323 copy_v4_v4((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang); 01324 offset += sizeof(float)*4; 01325 } 01326 (void)offset; 01327 } 01328 curface++; 01329 i++; 01330 } 01331 } 01332 numfaces = curface - start; 01333 if( numfaces > 0 ) { 01334 if( dodraw ) { 01335 if( numdata != 0 ) { 01336 GPU_buffer_unlock(buffer); 01337 GPU_interleaved_attrib_setup(buffer,datatypes,numdata); 01338 } 01339 glDrawArrays(GL_TRIANGLES,start*3,(curface-start)*3); 01340 } 01341 } 01342 GPU_buffer_unbind(); 01343 } 01344 GPU_buffer_free(buffer); 01345 } 01346 01347 glShadeModel(GL_FLAT); 01348 } 01349 01350 static void cdDM_drawFacesGLSL(DerivedMesh *dm,int (*setMaterial)(int, void *attribs)) 01351 { 01352 dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL); 01353 } 01354 01355 static void cdDM_drawMappedFacesMat(DerivedMesh *dm, 01356 void (*setMaterial)(void *userData, int, void *attribs), 01357 int (*setFace)(void *userData, int index), void *userData) 01358 { 01359 CDDerivedMesh *cddm = (CDDerivedMesh*) dm; 01360 GPUVertexAttribs gattribs; 01361 DMVertexAttribs attribs; 01362 MVert *mvert = cddm->mvert; 01363 MFace *mf = cddm->mface; 01364 float (*nors)[3] = dm->getFaceDataArray(dm, CD_NORMAL); 01365 int a, matnr, new_matnr; 01366 int orig, *index = dm->getFaceDataArray(dm, CD_ORIGINDEX); 01367 01368 cdDM_update_normals_from_pbvh(dm); 01369 01370 matnr = -1; 01371 01372 glShadeModel(GL_SMOOTH); 01373 01374 memset(&attribs, 0, sizeof(attribs)); 01375 01376 glBegin(GL_QUADS); 01377 01378 for(a = 0; a < dm->numFaceData; a++, mf++) { 01379 const int smoothnormal = (mf->flag & ME_SMOOTH); 01380 01381 /* material */ 01382 new_matnr = mf->mat_nr + 1; 01383 01384 if(new_matnr != matnr) { 01385 glEnd(); 01386 01387 setMaterial(userData, matnr = new_matnr, &gattribs); 01388 DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); 01389 01390 glBegin(GL_QUADS); 01391 } 01392 01393 /* skipping faces */ 01394 if(setFace) { 01395 orig = (index)? index[a]: a; 01396 01397 if(orig != ORIGINDEX_NONE && !setFace(userData, orig)) 01398 continue; 01399 } 01400 01401 /* smooth normal */ 01402 if(!smoothnormal) { 01403 if(nors) { 01404 glNormal3fv(nors[a]); 01405 } 01406 else { 01407 /* TODO ideally a normal layer should always be available */ 01408 float nor[3]; 01409 01410 if(mf->v4) 01411 normal_quad_v3( nor,mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co, mvert[mf->v4].co); 01412 else 01413 normal_tri_v3( nor,mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co); 01414 01415 glNormal3fv(nor); 01416 } 01417 } 01418 01419 /* vertices */ 01420 cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v1, 0, smoothnormal); 01421 cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v2, 1, smoothnormal); 01422 cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v3, 2, smoothnormal); 01423 01424 if(mf->v4) 01425 cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v4, 3, smoothnormal); 01426 else 01427 cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v3, 2, smoothnormal); 01428 } 01429 glEnd(); 01430 01431 glShadeModel(GL_FLAT); 01432 } 01433 01434 static void cdDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) 01435 { 01436 CDDerivedMesh *cddm = (CDDerivedMesh*) dm; 01437 MVert *vert = cddm->mvert; 01438 MEdge *edge = cddm->medge; 01439 int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX); 01440 01441 glBegin(GL_LINES); 01442 for(i = 0; i < dm->numEdgeData; i++, edge++) { 01443 if(index) { 01444 orig = *index++; 01445 if(setDrawOptions && orig == ORIGINDEX_NONE) continue; 01446 } 01447 else 01448 orig = i; 01449 01450 if(!setDrawOptions || setDrawOptions(userData, orig)) { 01451 glVertex3fv(vert[edge->v1].co); 01452 glVertex3fv(vert[edge->v2].co); 01453 } 01454 } 01455 glEnd(); 01456 } 01457 01458 static void cdDM_foreachMappedVert( 01459 DerivedMesh *dm, 01460 void (*func)(void *userData, int index, float *co, 01461 float *no_f, short *no_s), 01462 void *userData) 01463 { 01464 MVert *mv = CDDM_get_verts(dm); 01465 int i, orig, *index = DM_get_vert_data_layer(dm, CD_ORIGINDEX); 01466 01467 for(i = 0; i < dm->numVertData; i++, mv++) { 01468 if(index) { 01469 orig = *index++; 01470 if(orig == ORIGINDEX_NONE) continue; 01471 func(userData, orig, mv->co, NULL, mv->no); 01472 } 01473 else 01474 func(userData, i, mv->co, NULL, mv->no); 01475 } 01476 } 01477 01478 static void cdDM_foreachMappedEdge( 01479 DerivedMesh *dm, 01480 void (*func)(void *userData, int index, 01481 float *v0co, float *v1co), 01482 void *userData) 01483 { 01484 CDDerivedMesh *cddm = (CDDerivedMesh*) dm; 01485 MVert *mv = cddm->mvert; 01486 MEdge *med = cddm->medge; 01487 int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX); 01488 01489 for(i = 0; i < dm->numEdgeData; i++, med++) { 01490 if (index) { 01491 orig = *index++; 01492 if(orig == ORIGINDEX_NONE) continue; 01493 func(userData, orig, mv[med->v1].co, mv[med->v2].co); 01494 } 01495 else 01496 func(userData, i, mv[med->v1].co, mv[med->v2].co); 01497 } 01498 } 01499 01500 static void cdDM_foreachMappedFaceCenter( 01501 DerivedMesh *dm, 01502 void (*func)(void *userData, int index, 01503 float *cent, float *no), 01504 void *userData) 01505 { 01506 CDDerivedMesh *cddm = (CDDerivedMesh*)dm; 01507 MVert *mv = cddm->mvert; 01508 MFace *mf = cddm->mface; 01509 int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX); 01510 01511 for(i = 0; i < dm->numFaceData; i++, mf++) { 01512 float cent[3]; 01513 float no[3]; 01514 01515 if (index) { 01516 orig = *index++; 01517 if(orig == ORIGINDEX_NONE) continue; 01518 } 01519 else 01520 orig = i; 01521 01522 copy_v3_v3(cent, mv[mf->v1].co); 01523 add_v3_v3(cent, mv[mf->v2].co); 01524 add_v3_v3(cent, mv[mf->v3].co); 01525 01526 if (mf->v4) { 01527 normal_quad_v3( no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co); 01528 add_v3_v3(cent, mv[mf->v4].co); 01529 mul_v3_fl(cent, 0.25f); 01530 } else { 01531 normal_tri_v3( no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co); 01532 mul_v3_fl(cent, 0.33333333333f); 01533 } 01534 01535 func(userData, orig, cent, no); 01536 } 01537 } 01538 01539 static void cdDM_free_internal(CDDerivedMesh *cddm) 01540 { 01541 if(cddm->fmap) MEM_freeN(cddm->fmap); 01542 if(cddm->fmap_mem) MEM_freeN(cddm->fmap_mem); 01543 } 01544 01545 static void cdDM_release(DerivedMesh *dm) 01546 { 01547 CDDerivedMesh *cddm = (CDDerivedMesh*)dm; 01548 01549 if (DM_release(dm)) { 01550 cdDM_free_internal(cddm); 01551 MEM_freeN(cddm); 01552 } 01553 } 01554 01555 /**************** CDDM interface functions ****************/ 01556 static CDDerivedMesh *cdDM_create(const char *desc) 01557 { 01558 CDDerivedMesh *cddm; 01559 DerivedMesh *dm; 01560 01561 cddm = MEM_callocN(sizeof(*cddm), desc); 01562 dm = &cddm->dm; 01563 01564 dm->getMinMax = cdDM_getMinMax; 01565 01566 dm->getNumVerts = cdDM_getNumVerts; 01567 dm->getNumFaces = cdDM_getNumFaces; 01568 dm->getNumEdges = cdDM_getNumEdges; 01569 01570 dm->getVert = cdDM_getVert; 01571 dm->getEdge = cdDM_getEdge; 01572 dm->getFace = cdDM_getFace; 01573 dm->copyVertArray = cdDM_copyVertArray; 01574 dm->copyEdgeArray = cdDM_copyEdgeArray; 01575 dm->copyFaceArray = cdDM_copyFaceArray; 01576 dm->getVertData = DM_get_vert_data; 01577 dm->getEdgeData = DM_get_edge_data; 01578 dm->getFaceData = DM_get_face_data; 01579 dm->getVertDataArray = DM_get_vert_data_layer; 01580 dm->getEdgeDataArray = DM_get_edge_data_layer; 01581 dm->getFaceDataArray = DM_get_face_data_layer; 01582 01583 dm->getVertCos = cdDM_getVertCos; 01584 dm->getVertCo = cdDM_getVertCo; 01585 dm->getVertNo = cdDM_getVertNo; 01586 01587 dm->getPBVH = cdDM_getPBVH; 01588 dm->getFaceMap = cdDM_getFaceMap; 01589 01590 dm->drawVerts = cdDM_drawVerts; 01591 01592 dm->drawUVEdges = cdDM_drawUVEdges; 01593 dm->drawEdges = cdDM_drawEdges; 01594 dm->drawLooseEdges = cdDM_drawLooseEdges; 01595 dm->drawMappedEdges = cdDM_drawMappedEdges; 01596 01597 dm->drawFacesSolid = cdDM_drawFacesSolid; 01598 dm->drawFacesColored = cdDM_drawFacesColored; 01599 dm->drawFacesTex = cdDM_drawFacesTex; 01600 dm->drawFacesGLSL = cdDM_drawFacesGLSL; 01601 dm->drawMappedFaces = cdDM_drawMappedFaces; 01602 dm->drawMappedFacesTex = cdDM_drawMappedFacesTex; 01603 dm->drawMappedFacesGLSL = cdDM_drawMappedFacesGLSL; 01604 dm->drawMappedFacesMat = cdDM_drawMappedFacesMat; 01605 01606 dm->foreachMappedVert = cdDM_foreachMappedVert; 01607 dm->foreachMappedEdge = cdDM_foreachMappedEdge; 01608 dm->foreachMappedFaceCenter = cdDM_foreachMappedFaceCenter; 01609 01610 dm->release = cdDM_release; 01611 01612 return cddm; 01613 } 01614 01615 DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces) 01616 { 01617 CDDerivedMesh *cddm = cdDM_create("CDDM_new dm"); 01618 DerivedMesh *dm = &cddm->dm; 01619 01620 DM_init(dm, DM_TYPE_CDDM, numVerts, numEdges, numFaces); 01621 01622 CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts); 01623 CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges); 01624 CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces); 01625 01626 CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts); 01627 CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges); 01628 CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces); 01629 01630 cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT); 01631 cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE); 01632 cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE); 01633 01634 return dm; 01635 } 01636 01637 DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob)) 01638 { 01639 CDDerivedMesh *cddm = cdDM_create("CDDM_from_mesh dm"); 01640 DerivedMesh *dm = &cddm->dm; 01641 CustomDataMask mask = CD_MASK_MESH & (~CD_MASK_MDISPS); 01642 int alloctype; 01643 01644 /* this does a referenced copy, with an exception for fluidsim */ 01645 01646 DM_init(dm, DM_TYPE_CDDM, mesh->totvert, mesh->totedge, mesh->totface); 01647 01648 dm->deformedOnly = 1; 01649 01650 alloctype= CD_REFERENCE; 01651 01652 CustomData_merge(&mesh->vdata, &dm->vertData, mask, alloctype, 01653 mesh->totvert); 01654 CustomData_merge(&mesh->edata, &dm->edgeData, mask, alloctype, 01655 mesh->totedge); 01656 CustomData_merge(&mesh->fdata, &dm->faceData, mask, alloctype, 01657 mesh->totface); 01658 01659 cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT); 01660 cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE); 01661 cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE); 01662 01663 return dm; 01664 } 01665 01666 DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me)) 01667 { 01668 DerivedMesh *dm = CDDM_new(BLI_countlist(&em->verts), 01669 BLI_countlist(&em->edges), 01670 BLI_countlist(&em->faces)); 01671 CDDerivedMesh *cddm = (CDDerivedMesh*)dm; 01672 EditVert *eve; 01673 EditEdge *eed; 01674 EditFace *efa; 01675 MVert *mvert = cddm->mvert; 01676 MEdge *medge = cddm->medge; 01677 MFace *mface = cddm->mface; 01678 int i, *index; 01679 01680 dm->deformedOnly = 1; 01681 01682 CustomData_merge(&em->vdata, &dm->vertData, CD_MASK_DERIVEDMESH, 01683 CD_CALLOC, dm->numVertData); 01684 /* CustomData_merge(&em->edata, &dm->edgeData, CD_MASK_DERIVEDMESH, 01685 CD_CALLOC, dm->numEdgeData); */ 01686 CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH, 01687 CD_CALLOC, dm->numFaceData); 01688 01689 /* set eve->hash to vert index */ 01690 for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i) 01691 eve->tmp.l = i; 01692 01693 /* Need to be able to mark loose edges */ 01694 for(eed = em->edges.first; eed; eed = eed->next) { 01695 eed->f2 = 0; 01696 } 01697 for(efa = em->faces.first; efa; efa = efa->next) { 01698 efa->e1->f2 = 1; 01699 efa->e2->f2 = 1; 01700 efa->e3->f2 = 1; 01701 if(efa->e4) efa->e4->f2 = 1; 01702 } 01703 01704 index = dm->getVertDataArray(dm, CD_ORIGINDEX); 01705 for(i = 0, eve = em->verts.first; i < dm->numVertData; 01706 i++, eve = eve->next, index++) { 01707 MVert *mv = &mvert[i]; 01708 01709 copy_v3_v3(mv->co, eve->co); 01710 01711 normal_float_to_short_v3(mv->no, eve->no); 01712 mv->bweight = (unsigned char) (eve->bweight * 255.0f); 01713 01714 mv->flag = 0; 01715 01716 *index = i; 01717 01718 CustomData_from_em_block(&em->vdata, &dm->vertData, eve->data, i); 01719 } 01720 01721 index = dm->getEdgeDataArray(dm, CD_ORIGINDEX); 01722 for(i = 0, eed = em->edges.first; i < dm->numEdgeData; 01723 i++, eed = eed->next, index++) { 01724 MEdge *med = &medge[i]; 01725 01726 med->v1 = eed->v1->tmp.l; 01727 med->v2 = eed->v2->tmp.l; 01728 med->crease = (unsigned char) (eed->crease * 255.0f); 01729 med->bweight = (unsigned char) (eed->bweight * 255.0f); 01730 med->flag = ME_EDGEDRAW|ME_EDGERENDER; 01731 01732 if(eed->seam) med->flag |= ME_SEAM; 01733 if(eed->sharp) med->flag |= ME_SHARP; 01734 if(!eed->f2) med->flag |= ME_LOOSEEDGE; 01735 01736 *index = i; 01737 01738 /* CustomData_from_em_block(&em->edata, &dm->edgeData, eed->data, i); */ 01739 } 01740 01741 index = dm->getFaceDataArray(dm, CD_ORIGINDEX); 01742 for(i = 0, efa = em->faces.first; i < dm->numFaceData; 01743 i++, efa = efa->next, index++) { 01744 MFace *mf = &mface[i]; 01745 01746 mf->v1 = efa->v1->tmp.l; 01747 mf->v2 = efa->v2->tmp.l; 01748 mf->v3 = efa->v3->tmp.l; 01749 mf->v4 = efa->v4 ? efa->v4->tmp.l : 0; 01750 mf->mat_nr = efa->mat_nr; 01751 mf->flag = efa->flag; 01752 01753 *index = i; 01754 01755 CustomData_from_em_block(&em->fdata, &dm->faceData, efa->data, i); 01756 test_index_face(mf, &dm->faceData, i, efa->v4?4:3); 01757 } 01758 01759 return dm; 01760 } 01761 01762 DerivedMesh *CDDM_from_curve(Object *ob) 01763 { 01764 return CDDM_from_curve_customDB(ob, &ob->disp); 01765 } 01766 01767 DerivedMesh *CDDM_from_curve_customDB(Object *ob, ListBase *dispbase) 01768 { 01769 DerivedMesh *dm; 01770 CDDerivedMesh *cddm; 01771 MVert *allvert; 01772 MEdge *alledge; 01773 MFace *allface; 01774 int totvert, totedge, totface; 01775 01776 if (nurbs_to_mdata_customdb(ob, dispbase, &allvert, &totvert, &alledge, 01777 &totedge, &allface, &totface) != 0) { 01778 /* Error initializing mdata. This often happens when curve is empty */ 01779 return CDDM_new(0, 0, 0); 01780 } 01781 01782 dm = CDDM_new(totvert, totedge, totface); 01783 dm->deformedOnly = 1; 01784 01785 cddm = (CDDerivedMesh*)dm; 01786 01787 memcpy(cddm->mvert, allvert, totvert*sizeof(MVert)); 01788 memcpy(cddm->medge, alledge, totedge*sizeof(MEdge)); 01789 memcpy(cddm->mface, allface, totface*sizeof(MFace)); 01790 01791 MEM_freeN(allvert); 01792 MEM_freeN(alledge); 01793 MEM_freeN(allface); 01794 01795 return dm; 01796 } 01797 01798 DerivedMesh *CDDM_copy(DerivedMesh *source) 01799 { 01800 CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm"); 01801 DerivedMesh *dm = &cddm->dm; 01802 int numVerts = source->numVertData; 01803 int numEdges = source->numEdgeData; 01804 int numFaces = source->numFaceData; 01805 01806 /* ensure these are created if they are made on demand */ 01807 source->getVertDataArray(source, CD_ORIGINDEX); 01808 source->getEdgeDataArray(source, CD_ORIGINDEX); 01809 source->getFaceDataArray(source, CD_ORIGINDEX); 01810 01811 /* this initializes dm, and copies all non mvert/medge/mface layers */ 01812 DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces); 01813 dm->deformedOnly = source->deformedOnly; 01814 01815 CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts); 01816 CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges); 01817 CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numFaces); 01818 01819 /* now add mvert/medge/mface layers */ 01820 cddm->mvert = source->dupVertArray(source); 01821 cddm->medge = source->dupEdgeArray(source); 01822 cddm->mface = source->dupFaceArray(source); 01823 01824 CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts); 01825 CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges); 01826 CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numFaces); 01827 01828 return dm; 01829 } 01830 01831 /* note, the CD_ORIGINDEX layers are all 0, so if there is a direct 01832 * relationship betwen mesh data this needs to be set by the caller. */ 01833 DerivedMesh *CDDM_from_template(DerivedMesh *source, 01834 int numVerts, int numEdges, int numFaces) 01835 { 01836 CDDerivedMesh *cddm = cdDM_create("CDDM_from_template dest"); 01837 DerivedMesh *dm = &cddm->dm; 01838 01839 /* ensure these are created if they are made on demand */ 01840 source->getVertDataArray(source, CD_ORIGINDEX); 01841 source->getEdgeDataArray(source, CD_ORIGINDEX); 01842 source->getFaceDataArray(source, CD_ORIGINDEX); 01843 01844 /* this does a copy of all non mvert/medge/mface layers */ 01845 DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces); 01846 01847 /* now add mvert/medge/mface layers */ 01848 CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts); 01849 CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges); 01850 CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces); 01851 01852 if(!CustomData_get_layer(&dm->vertData, CD_ORIGINDEX)) 01853 CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts); 01854 if(!CustomData_get_layer(&dm->edgeData, CD_ORIGINDEX)) 01855 CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges); 01856 if(!CustomData_get_layer(&dm->faceData, CD_ORIGINDEX)) 01857 CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces); 01858 01859 cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT); 01860 cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE); 01861 cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE); 01862 01863 return dm; 01864 } 01865 01866 void CDDM_apply_vert_coords(DerivedMesh *dm, float (*vertCoords)[3]) 01867 { 01868 CDDerivedMesh *cddm = (CDDerivedMesh*)dm; 01869 MVert *vert; 01870 int i; 01871 01872 /* this will just return the pointer if it wasn't a referenced layer */ 01873 vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, dm->numVertData); 01874 cddm->mvert = vert; 01875 01876 for(i = 0; i < dm->numVertData; ++i, ++vert) 01877 copy_v3_v3(vert->co, vertCoords[i]); 01878 } 01879 01880 void CDDM_apply_vert_normals(DerivedMesh *dm, short (*vertNormals)[3]) 01881 { 01882 CDDerivedMesh *cddm = (CDDerivedMesh*)dm; 01883 MVert *vert; 01884 int i; 01885 01886 /* this will just return the pointer if it wasn't a referenced layer */ 01887 vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, dm->numVertData); 01888 cddm->mvert = vert; 01889 01890 for(i = 0; i < dm->numVertData; ++i, ++vert) 01891 copy_v3_v3_short(vert->no, vertNormals[i]); 01892 } 01893 01894 void CDDM_calc_normals(DerivedMesh *dm) 01895 { 01896 CDDerivedMesh *cddm = (CDDerivedMesh*)dm; 01897 float (*face_nors)[3]; 01898 01899 if(dm->numVertData == 0) return; 01900 01901 /* we don't want to overwrite any referenced layers */ 01902 cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, dm->numVertData); 01903 01904 /* make a face normal layer if not present */ 01905 face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL); 01906 if(!face_nors) 01907 face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC, 01908 NULL, dm->numFaceData); 01909 01910 /* calculate face normals */ 01911 mesh_calc_normals(cddm->mvert, dm->numVertData, CDDM_get_faces(dm), dm->numFaceData, face_nors); 01912 } 01913 01914 void CDDM_calc_edges(DerivedMesh *dm) 01915 { 01916 CDDerivedMesh *cddm = (CDDerivedMesh*)dm; 01917 CustomData edgeData; 01918 EdgeHashIterator *ehi; 01919 MFace *mf = cddm->mface; 01920 MEdge *med; 01921 EdgeHash *eh = BLI_edgehash_new(); 01922 int i, *index, numEdges, maxFaces = dm->numFaceData; 01923 01924 for (i = 0; i < maxFaces; i++, mf++) { 01925 if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2)) 01926 BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL); 01927 if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3)) 01928 BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL); 01929 01930 if (mf->v4) { 01931 if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4)) 01932 BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL); 01933 if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1)) 01934 BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL); 01935 } else { 01936 if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1)) 01937 BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL); 01938 } 01939 } 01940 01941 numEdges = BLI_edgehash_size(eh); 01942 01943 /* write new edges into a temporary CustomData */ 01944 memset(&edgeData, 0, sizeof(edgeData)); 01945 CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges); 01946 CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges); 01947 01948 ehi = BLI_edgehashIterator_new(eh); 01949 med = CustomData_get_layer(&edgeData, CD_MEDGE); 01950 index = CustomData_get_layer(&edgeData, CD_ORIGINDEX); 01951 for(i = 0; !BLI_edgehashIterator_isDone(ehi); 01952 BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) { 01953 BLI_edgehashIterator_getKey(ehi, &med->v1, &med->v2); 01954 01955 med->flag = ME_EDGEDRAW|ME_EDGERENDER; 01956 *index = ORIGINDEX_NONE; 01957 } 01958 BLI_edgehashIterator_free(ehi); 01959 01960 /* free old CustomData and assign new one */ 01961 CustomData_free(&dm->edgeData, dm->numEdgeData); 01962 dm->edgeData = edgeData; 01963 dm->numEdgeData = numEdges; 01964 01965 cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE); 01966 01967 BLI_edgehash_free(eh, NULL); 01968 } 01969 01970 void CDDM_lower_num_verts(DerivedMesh *dm, int numVerts) 01971 { 01972 if (numVerts < dm->numVertData) 01973 CustomData_free_elem(&dm->vertData, numVerts, dm->numVertData-numVerts); 01974 01975 dm->numVertData = numVerts; 01976 } 01977 01978 void CDDM_lower_num_edges(DerivedMesh *dm, int numEdges) 01979 { 01980 if (numEdges < dm->numEdgeData) 01981 CustomData_free_elem(&dm->edgeData, numEdges, dm->numEdgeData-numEdges); 01982 01983 dm->numEdgeData = numEdges; 01984 } 01985 01986 void CDDM_lower_num_faces(DerivedMesh *dm, int numFaces) 01987 { 01988 if (numFaces < dm->numFaceData) 01989 CustomData_free_elem(&dm->faceData, numFaces, dm->numFaceData-numFaces); 01990 01991 dm->numFaceData = numFaces; 01992 } 01993 01994 MVert *CDDM_get_vert(DerivedMesh *dm, int index) 01995 { 01996 return &((CDDerivedMesh*)dm)->mvert[index]; 01997 } 01998 01999 MEdge *CDDM_get_edge(DerivedMesh *dm, int index) 02000 { 02001 return &((CDDerivedMesh*)dm)->medge[index]; 02002 } 02003 02004 MFace *CDDM_get_face(DerivedMesh *dm, int index) 02005 { 02006 return &((CDDerivedMesh*)dm)->mface[index]; 02007 } 02008 02009 MVert *CDDM_get_verts(DerivedMesh *dm) 02010 { 02011 return ((CDDerivedMesh*)dm)->mvert; 02012 } 02013 02014 MEdge *CDDM_get_edges(DerivedMesh *dm) 02015 { 02016 return ((CDDerivedMesh*)dm)->medge; 02017 } 02018 02019 MFace *CDDM_get_faces(DerivedMesh *dm) 02020 { 02021 return ((CDDerivedMesh*)dm)->mface; 02022 } 02023