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