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) 2005 by the Blender Foundation. 00019 * All rights reserved. 00020 * 00021 * Contributor(s): Daniel Dunbar 00022 * Ton Roosendaal, 00023 * Ben Batt, 00024 * Brecht Van Lommel, 00025 * Campbell Barton 00026 * 00027 * ***** END GPL LICENSE BLOCK ***** 00028 * 00029 */ 00030 00036 /* Screw modifier: revolves the edges about an axis */ 00037 00038 #include "DNA_meshdata_types.h" 00039 #include "DNA_object_types.h" 00040 00041 #include "BLI_math.h" 00042 #include "BLI_utildefines.h" 00043 00044 00045 #include "BKE_cdderivedmesh.h" 00046 00047 #include "depsgraph_private.h" 00048 #include "MOD_modifiertypes.h" 00049 #include "MEM_guardedalloc.h" 00050 00051 /* used for gathering edge connectivity */ 00052 typedef struct ScrewVertConnect { 00053 float dist; /* distance from the center axis */ 00054 float co[3]; /* loaction relative to the transformed axis */ 00055 float no[3]; /* calc normal of the vertex */ 00056 int v[2]; /* 2 verts on either side of this one */ 00057 MEdge *e[2]; /* edges on either side, a bit of a waste since each edge ref's 2 edges */ 00058 char flag; 00059 } ScrewVertConnect; 00060 00061 typedef struct ScrewVertIter { 00062 ScrewVertConnect * v_array; 00063 ScrewVertConnect * v_poin; 00064 int v; 00065 int v_other; 00066 MEdge *e; 00067 } ScrewVertIter; 00068 00069 00070 static void screwvert_iter_init(ScrewVertIter *iter, ScrewVertConnect *array, int v_init, int dir) 00071 { 00072 iter->v_array = array; 00073 iter->v = v_init; 00074 00075 if (v_init >= 0) { 00076 iter->v_poin = &array[v_init]; 00077 iter->v_other = iter->v_poin->v[dir]; 00078 iter->e = iter->v_poin->e[!dir]; 00079 } 00080 else { 00081 iter->v_poin= NULL; 00082 iter->e= NULL; 00083 } 00084 } 00085 00086 00087 static void screwvert_iter_step(ScrewVertIter *iter) 00088 { 00089 if (iter->v_poin->v[0] == iter->v_other) { 00090 iter->v_other= iter->v; 00091 iter->v= iter->v_poin->v[1]; 00092 } 00093 else if (iter->v_poin->v[1] == iter->v_other) { 00094 iter->v_other= iter->v; 00095 iter->v= iter->v_poin->v[0]; 00096 } 00097 if (iter->v >= 0) { 00098 iter->v_poin= &iter->v_array[iter->v]; 00099 iter->e= iter->v_poin->e[(iter->v_poin->e[0] == iter->e)]; 00100 } 00101 else { 00102 iter->e= NULL; 00103 iter->v_poin= NULL; 00104 } 00105 } 00106 00107 00108 static void initData(ModifierData *md) 00109 { 00110 ScrewModifierData *ltmd= (ScrewModifierData*) md; 00111 ltmd->ob_axis= NULL; 00112 ltmd->angle= M_PI * 2.0; 00113 ltmd->axis= 2; 00114 ltmd->flag= 0; 00115 ltmd->steps= 16; 00116 ltmd->render_steps= 16; 00117 ltmd->iter= 1; 00118 } 00119 00120 static void copyData(ModifierData *md, ModifierData *target) 00121 { 00122 ScrewModifierData *sltmd= (ScrewModifierData*) md; 00123 ScrewModifierData *tltmd= (ScrewModifierData*) target; 00124 00125 tltmd->ob_axis= sltmd->ob_axis; 00126 tltmd->angle= sltmd->angle; 00127 tltmd->axis= sltmd->axis; 00128 tltmd->flag= sltmd->flag; 00129 tltmd->steps= sltmd->steps; 00130 tltmd->render_steps= sltmd->render_steps; 00131 tltmd->screw_ofs= sltmd->screw_ofs; 00132 tltmd->iter= sltmd->iter; 00133 } 00134 00135 static DerivedMesh *applyModifier(ModifierData *md, Object *ob, 00136 DerivedMesh *derivedData, 00137 int useRenderParams, 00138 int UNUSED(isFinalCalc)) 00139 { 00140 DerivedMesh *dm= derivedData; 00141 DerivedMesh *result; 00142 ScrewModifierData *ltmd= (ScrewModifierData*) md; 00143 00144 int *origindex; 00145 int mface_index=0; 00146 int step; 00147 int i, j; 00148 unsigned int i1, i2; 00149 int step_tot= useRenderParams ? ltmd->render_steps : ltmd->steps; 00150 const int do_flip = ltmd->flag & MOD_SCREW_NORMAL_FLIP ? 1 : 0; 00151 int maxVerts=0, maxEdges=0, maxFaces=0; 00152 const unsigned int totvert= dm->getNumVerts(dm); 00153 const unsigned int totedge= dm->getNumEdges(dm); 00154 00155 char axis_char= 'X', close; 00156 float angle= ltmd->angle; 00157 float screw_ofs= ltmd->screw_ofs; 00158 float axis_vec[3]= {0.0f, 0.0f, 0.0f}; 00159 float tmp_vec1[3], tmp_vec2[3]; 00160 float mat3[3][3]; 00161 float mtx_tx[4][4]; /* transform the coords by an object relative to this objects transformation */ 00162 float mtx_tx_inv[4][4]; /* inverted */ 00163 float mtx_tmp_a[4][4]; 00164 00165 int vc_tot_linked= 0; 00166 short other_axis_1, other_axis_2; 00167 float *tmpf1, *tmpf2; 00168 00169 MFace *mface_new, *mf_new; 00170 MEdge *medge_orig, *med_orig, *med_new, *med_new_firstloop, *medge_new; 00171 MVert *mvert_new, *mvert_orig, *mv_orig, *mv_new, *mv_new_base; 00172 00173 ScrewVertConnect *vc, *vc_tmp, *vert_connect= NULL; 00174 00175 /* dont do anything? */ 00176 if (!totvert) 00177 return CDDM_from_template(dm, 0, 0, 0); 00178 00179 switch(ltmd->axis) { 00180 case 0: 00181 other_axis_1=1; 00182 other_axis_2=2; 00183 break; 00184 case 1: 00185 other_axis_1=0; 00186 other_axis_2=2; 00187 break; 00188 default: /* 2, use default to quiet warnings */ 00189 other_axis_1=0; 00190 other_axis_2=1; 00191 break; 00192 } 00193 00194 axis_vec[ltmd->axis]= 1.0f; 00195 00196 if (ltmd->ob_axis) { 00197 /* calc the matrix relative to the axis object */ 00198 invert_m4_m4(mtx_tmp_a, ob->obmat); 00199 copy_m4_m4(mtx_tx_inv, ltmd->ob_axis->obmat); 00200 mult_m4_m4m4(mtx_tx, mtx_tmp_a, mtx_tx_inv); 00201 00202 /* calc the axis vec */ 00203 mul_mat3_m4_v3(mtx_tx, axis_vec); /* only rotation component */ 00204 normalize_v3(axis_vec); 00205 00206 /* screw */ 00207 if(ltmd->flag & MOD_SCREW_OBJECT_OFFSET) { 00208 /* find the offset along this axis relative to this objects matrix */ 00209 float totlen = len_v3(mtx_tx[3]); 00210 00211 if(totlen != 0.0f) { 00212 float zero[3]={0.0f, 0.0f, 0.0f}; 00213 float cp[3]; 00214 screw_ofs= closest_to_line_v3(cp, mtx_tx[3], zero, axis_vec); 00215 } 00216 else { 00217 screw_ofs= 0.0f; 00218 } 00219 } 00220 00221 /* angle */ 00222 00223 #if 0 // cant incluide this, not predictable enough, though quite fun,. 00224 if(ltmd->flag & MOD_SCREW_OBJECT_ANGLE) { 00225 float mtx3_tx[3][3]; 00226 copy_m3_m4(mtx3_tx, mtx_tx); 00227 00228 float vec[3] = {0,1,0}; 00229 float cross1[3]; 00230 float cross2[3]; 00231 cross_v3_v3v3(cross1, vec, axis_vec); 00232 00233 mul_v3_m3v3(cross2, mtx3_tx, cross1); 00234 { 00235 float c1[3]; 00236 float c2[3]; 00237 float axis_tmp[3]; 00238 00239 cross_v3_v3v3(c1, cross2, axis_vec); 00240 cross_v3_v3v3(c2, axis_vec, c1); 00241 00242 00243 angle= angle_v3v3(cross1, c2); 00244 00245 cross_v3_v3v3(axis_tmp, cross1, c2); 00246 normalize_v3(axis_tmp); 00247 00248 if(len_v3v3(axis_tmp, axis_vec) > 1.0f) 00249 angle= -angle; 00250 00251 } 00252 } 00253 #endif 00254 } 00255 else { 00256 /* exis char is used by i_rotate*/ 00257 axis_char += ltmd->axis; /* 'X' + axis */ 00258 00259 /* useful to be able to use the axis vec in some cases still */ 00260 zero_v3(axis_vec); 00261 axis_vec[ltmd->axis]= 1.0f; 00262 } 00263 00264 /* apply the multiplier */ 00265 angle *= ltmd->iter; 00266 screw_ofs *= ltmd->iter; 00267 00268 /* multiplying the steps is a bit tricky, this works best */ 00269 step_tot = ((step_tot + 1) * ltmd->iter) - (ltmd->iter - 1); 00270 00271 /* will the screw be closed? 00272 * Note! smaller then FLT_EPSILON*100 gives problems with float precision so its never closed. */ 00273 if (fabsf(screw_ofs) <= (FLT_EPSILON*100.0f) && fabsf(fabsf(angle) - ((float)M_PI * 2.0f)) <= (FLT_EPSILON*100.0f)) { 00274 close= 1; 00275 step_tot--; 00276 if(step_tot < 3) step_tot= 3; 00277 00278 maxVerts = totvert * step_tot; /* -1 because we're joining back up */ 00279 maxEdges = (totvert * step_tot) + /* these are the edges between new verts */ 00280 (totedge * step_tot); /* -1 because vert edges join */ 00281 maxFaces = totedge * step_tot; 00282 00283 screw_ofs= 0.0f; 00284 } 00285 else { 00286 close= 0; 00287 if(step_tot < 3) step_tot= 3; 00288 00289 maxVerts = totvert * step_tot; /* -1 because we're joining back up */ 00290 maxEdges = (totvert * (step_tot-1)) + /* these are the edges between new verts */ 00291 (totedge * step_tot); /* -1 because vert edges join */ 00292 maxFaces = totedge * (step_tot-1); 00293 } 00294 00295 result= CDDM_from_template(dm, maxVerts, maxEdges, maxFaces); 00296 00297 /* copy verts from mesh */ 00298 mvert_orig = dm->getVertArray(dm); 00299 medge_orig = dm->getEdgeArray(dm); 00300 00301 mvert_new = result->getVertArray(result); 00302 mface_new = result->getFaceArray(result); 00303 medge_new = result->getEdgeArray(result); 00304 00305 origindex= result->getFaceDataArray(result, CD_ORIGINDEX); 00306 00307 DM_copy_vert_data(dm, result, 0, 0, totvert); /* copy first otherwise this overwrites our own vertex normals */ 00308 00309 /* Set the locations of the first set of verts */ 00310 00311 mv_new= mvert_new; 00312 mv_orig= mvert_orig; 00313 00314 /* Copy the first set of edges */ 00315 med_orig= medge_orig; 00316 med_new= medge_new; 00317 for (i=0; i < totedge; i++, med_orig++, med_new++) { 00318 med_new->v1= med_orig->v1; 00319 med_new->v2= med_orig->v2; 00320 med_new->crease= med_orig->crease; 00321 med_new->flag= med_orig->flag & ~ME_LOOSEEDGE; 00322 } 00323 00324 if(ltmd->flag & MOD_SCREW_NORMAL_CALC) { 00325 /* 00326 * Normal Calculation (for face flipping) 00327 * Sort edge verts for correct face flipping 00328 * NOT REALLY NEEDED but face flipping is nice. 00329 * 00330 * */ 00331 00332 00333 /* Notice! 00334 * 00335 * Since we are only ordering the edges here it can avoid mallocing the 00336 * extra space by abusing the vert array berfore its filled with new verts. 00337 * The new array for vert_connect must be at least sizeof(ScrewVertConnect) * totvert 00338 * and the size of our resulting meshes array is sizeof(MVert) * totvert * 3 00339 * so its safe to use the second 2 thrids of MVert the array for vert_connect, 00340 * just make sure ScrewVertConnect struct is no more then twice as big as MVert, 00341 * at the moment there is no chance of that being a problem, 00342 * unless MVert becomes half its current size. 00343 * 00344 * once the edges are ordered, vert_connect is not needed and it can be used for verts 00345 * 00346 * This makes the modifier faster with one less alloc. 00347 */ 00348 00349 vert_connect= MEM_mallocN(sizeof(ScrewVertConnect) * totvert, "ScrewVertConnect"); 00350 //vert_connect= (ScrewVertConnect *) &medge_new[totvert]; /* skip the first slice of verts */ 00351 vc= vert_connect; 00352 00353 /* Copy Vert Locations */ 00354 /* - We can do this in a later loop - only do here if no normal calc */ 00355 if (!totedge) { 00356 for (i=0; i < totvert; i++, mv_orig++, mv_new++) { 00357 copy_v3_v3(mv_new->co, mv_orig->co); 00358 normalize_v3_v3(vc->no, mv_new->co); /* no edges- this is really a dummy normal */ 00359 } 00360 } 00361 else { 00362 /*printf("\n\n\n\n\nStarting Modifier\n");*/ 00363 /* set edge users */ 00364 med_new= medge_new; 00365 mv_new= mvert_new; 00366 00367 if (ltmd->ob_axis) { 00368 /*mtx_tx is initialized early on */ 00369 for (i=0; i < totvert; i++, mv_new++, mv_orig++, vc++) { 00370 vc->co[0]= mv_new->co[0]= mv_orig->co[0]; 00371 vc->co[1]= mv_new->co[1]= mv_orig->co[1]; 00372 vc->co[2]= mv_new->co[2]= mv_orig->co[2]; 00373 00374 vc->flag= 0; 00375 vc->e[0]= vc->e[1]= NULL; 00376 vc->v[0]= vc->v[1]= -1; 00377 00378 mul_m4_v3(mtx_tx, vc->co); 00379 /* length in 2d, dont sqrt because this is only for comparison */ 00380 vc->dist = vc->co[other_axis_1]*vc->co[other_axis_1] + 00381 vc->co[other_axis_2]*vc->co[other_axis_2]; 00382 00383 /* printf("location %f %f %f -- %f\n", vc->co[0], vc->co[1], vc->co[2], vc->dist);*/ 00384 } 00385 } 00386 else { 00387 for (i=0; i < totvert; i++, mv_new++, mv_orig++, vc++) { 00388 vc->co[0]= mv_new->co[0]= mv_orig->co[0]; 00389 vc->co[1]= mv_new->co[1]= mv_orig->co[1]; 00390 vc->co[2]= mv_new->co[2]= mv_orig->co[2]; 00391 00392 vc->flag= 0; 00393 vc->e[0]= vc->e[1]= NULL; 00394 vc->v[0]= vc->v[1]= -1; 00395 00396 /* length in 2d, dont sqrt because this is only for comparison */ 00397 vc->dist = vc->co[other_axis_1]*vc->co[other_axis_1] + 00398 vc->co[other_axis_2]*vc->co[other_axis_2]; 00399 00400 /* printf("location %f %f %f -- %f\n", vc->co[0], vc->co[1], vc->co[2], vc->dist);*/ 00401 } 00402 } 00403 00404 /* this loop builds connectivity info for verts */ 00405 for (i=0; i<totedge; i++, med_new++) { 00406 vc= &vert_connect[med_new->v1]; 00407 00408 if (vc->v[0] == -1) { /* unused */ 00409 vc->v[0]= med_new->v2; 00410 vc->e[0]= med_new; 00411 } 00412 else if (vc->v[1] == -1) { 00413 vc->v[1]= med_new->v2; 00414 vc->e[1]= med_new; 00415 } 00416 else { 00417 vc->v[0]= vc->v[1]= -2; /* erro value - dont use, 3 edges on vert */ 00418 } 00419 00420 vc= &vert_connect[med_new->v2]; 00421 00422 /* same as above but swap v1/2 */ 00423 if (vc->v[0] == -1) { /* unused */ 00424 vc->v[0]= med_new->v1; 00425 vc->e[0]= med_new; 00426 } 00427 else if (vc->v[1] == -1) { 00428 vc->v[1]= med_new->v1; 00429 vc->e[1]= med_new; 00430 } 00431 else { 00432 vc->v[0]= vc->v[1]= -2; /* erro value - dont use, 3 edges on vert */ 00433 } 00434 } 00435 00436 /* find the first vert */ 00437 vc= vert_connect; 00438 for (i=0; i < totvert; i++, vc++) { 00439 /* Now do search for connected verts, order all edges and flip them 00440 * so resulting faces are flipped the right way */ 00441 vc_tot_linked= 0; /* count the number of linked verts for this loop */ 00442 if (vc->flag == 0) { 00443 int v_best=-1, ed_loop_closed=0; /* vert and vert new */ 00444 ScrewVertIter lt_iter; 00445 int ed_loop_flip= 0; /* compiler complains if not initialized, but it should be initialized below */ 00446 float fl= -1.0f; 00447 00448 /*printf("Loop on connected vert: %i\n", i);*/ 00449 00450 for(j=0; j<2; j++) { 00451 /*printf("\tSide: %i\n", j);*/ 00452 screwvert_iter_init(<_iter, vert_connect, i, j); 00453 if (j == 1) { 00454 screwvert_iter_step(<_iter); 00455 } 00456 while (lt_iter.v_poin) { 00457 /*printf("\t\tVERT: %i\n", lt_iter.v);*/ 00458 if (lt_iter.v_poin->flag) { 00459 /*printf("\t\t\tBreaking Found end\n");*/ 00460 //endpoints[0]= endpoints[1]= -1; 00461 ed_loop_closed= 1; /* circle */ 00462 break; 00463 } 00464 lt_iter.v_poin->flag= 1; 00465 vc_tot_linked++; 00466 /*printf("Testing 2 floats %f : %f\n", fl, lt_iter.v_poin->dist);*/ 00467 if (fl <= lt_iter.v_poin->dist) { 00468 fl= lt_iter.v_poin->dist; 00469 v_best= lt_iter.v; 00470 /*printf("\t\t\tVERT BEST: %i\n", v_best);*/ 00471 } 00472 screwvert_iter_step(<_iter); 00473 if (!lt_iter.v_poin) { 00474 /*printf("\t\t\tFound End Also Num %i\n", j);*/ 00475 /*endpoints[j]= lt_iter.v_other;*/ /* other is still valid */ 00476 break; 00477 } 00478 } 00479 } 00480 00481 /* now we have a collection of used edges. flip their edges the right way*/ 00482 /*if (v_best != -1) - */ 00483 00484 /*printf("Done Looking - vc_tot_linked: %i\n", vc_tot_linked);*/ 00485 00486 if (vc_tot_linked>1) { 00487 float vf_1, vf_2, vf_best; 00488 00489 vc_tmp= &vert_connect[v_best]; 00490 00491 tmpf1= vert_connect[vc_tmp->v[0]].co; 00492 tmpf2= vert_connect[vc_tmp->v[1]].co; 00493 00494 00495 /* edge connects on each side! */ 00496 if ((vc_tmp->v[0] > -1) && (vc_tmp->v[1] > -1)) { 00497 /*printf("Verts on each side (%i %i)\n", vc_tmp->v[0], vc_tmp->v[1]);*/ 00498 /* find out which is higher */ 00499 00500 vf_1= tmpf1[ltmd->axis]; 00501 vf_2= tmpf2[ltmd->axis]; 00502 vf_best= vc_tmp->co[ltmd->axis]; 00503 00504 if (vf_1 < vf_best && vf_best < vf_2) { 00505 ed_loop_flip= 0; 00506 } 00507 else if (vf_1 > vf_best && vf_best > vf_2) { 00508 ed_loop_flip= 1; 00509 } 00510 else { 00511 /* not so simple to work out which edge is higher */ 00512 sub_v3_v3v3(tmp_vec1, tmpf1, vc_tmp->co); 00513 sub_v3_v3v3(tmp_vec2, tmpf2, vc_tmp->co); 00514 normalize_v3(tmp_vec1); 00515 normalize_v3(tmp_vec2); 00516 00517 if (tmp_vec1[ltmd->axis] < tmp_vec2[ltmd->axis]) { 00518 ed_loop_flip= 1; 00519 } 00520 else { 00521 ed_loop_flip= 0; 00522 } 00523 } 00524 } 00525 else if (vc_tmp->v[0] >= 0) { /*vertex only connected on 1 side */ 00526 /*printf("Verts on ONE side (%i %i)\n", vc_tmp->v[0], vc_tmp->v[1]);*/ 00527 if (tmpf1[ltmd->axis] < vc_tmp->co[ltmd->axis]) { /* best is above */ 00528 ed_loop_flip= 1; 00529 } 00530 else { /* best is below or even... in even case we cant know whet to do. */ 00531 ed_loop_flip= 0; 00532 } 00533 00534 }/* else { 00535 printf("No Connected ___\n"); 00536 }*/ 00537 00538 /*printf("flip direction %i\n", ed_loop_flip);*/ 00539 00540 00541 /* switch the flip option if set 00542 * note: flip is now done at face level so copying vgroup slizes is easier */ 00543 /* 00544 if (do_flip) 00545 ed_loop_flip= !ed_loop_flip; 00546 */ 00547 00548 if (angle < 0.0f) 00549 ed_loop_flip= !ed_loop_flip; 00550 00551 /* if its closed, we only need 1 loop */ 00552 for(j=ed_loop_closed; j<2; j++) { 00553 /*printf("Ordering Side J %i\n", j);*/ 00554 00555 screwvert_iter_init(<_iter, vert_connect, v_best, j); 00556 /*printf("\n\nStarting - Loop\n");*/ 00557 lt_iter.v_poin->flag= 1; /* so a non loop will traverse the other side */ 00558 00559 00560 /* If this is the vert off the best vert and 00561 * the best vert has 2 edges connected too it 00562 * then swap the flip direction */ 00563 if (j == 1 && (vc_tmp->v[0] > -1) && (vc_tmp->v[1] > -1)) 00564 ed_loop_flip= !ed_loop_flip; 00565 00566 while (lt_iter.v_poin && lt_iter.v_poin->flag != 2) { 00567 /*printf("\tOrdering Vert V %i\n", lt_iter.v);*/ 00568 00569 lt_iter.v_poin->flag= 2; 00570 if (lt_iter.e) { 00571 if (lt_iter.v == lt_iter.e->v1) { 00572 if (ed_loop_flip == 0) { 00573 /*printf("\t\t\tFlipping 0\n");*/ 00574 SWAP(unsigned int, lt_iter.e->v1, lt_iter.e->v2); 00575 }/* else { 00576 printf("\t\t\tFlipping Not 0\n"); 00577 }*/ 00578 } 00579 else if (lt_iter.v == lt_iter.e->v2) { 00580 if (ed_loop_flip == 1) { 00581 /*printf("\t\t\tFlipping 1\n");*/ 00582 SWAP(unsigned int, lt_iter.e->v1, lt_iter.e->v2); 00583 }/* else { 00584 printf("\t\t\tFlipping Not 1\n"); 00585 }*/ 00586 }/* else { 00587 printf("\t\tIncorrect edge topology"); 00588 }*/ 00589 }/* else { 00590 printf("\t\tNo Edge at this point\n"); 00591 }*/ 00592 screwvert_iter_step(<_iter); 00593 } 00594 } 00595 } 00596 } 00597 00598 /* *VERTEX NORMALS* 00599 * we know the surrounding edges are ordered correctly now 00600 * so its safe to create vertex normals. 00601 * 00602 * calculate vertex normals that can be propodated on lathing 00603 * use edge connectivity work this out */ 00604 if (vc->v[0] >= 0) { 00605 if (vc->v[1] >= 0) { 00606 /* 2 edges connedted */ 00607 /* make 2 connecting vert locations relative to the middle vert */ 00608 sub_v3_v3v3(tmp_vec1, mvert_new[vc->v[0]].co, mvert_new[i].co); 00609 sub_v3_v3v3(tmp_vec2, mvert_new[vc->v[1]].co, mvert_new[i].co); 00610 /* normalize so both edges have the same influence, no matter their length */ 00611 normalize_v3(tmp_vec1); 00612 normalize_v3(tmp_vec2); 00613 00614 /* vc_no_tmp1 - this line is the average direction of both connecting edges 00615 * 00616 * Use the edge order to make the subtraction, flip the normal the right way 00617 * edge should be there but check just in case... */ 00618 if (vc->e && vc->e[0]->v1 == i) { 00619 sub_v3_v3(tmp_vec1, tmp_vec2); 00620 } 00621 else { 00622 sub_v3_v3v3(tmp_vec1, tmp_vec2, tmp_vec1); 00623 } 00624 } 00625 else { 00626 /* only 1 edge connected - same as above except 00627 * dont need to average edge direction */ 00628 if (vc->e && vc->e[0]->v2 == i) { 00629 sub_v3_v3v3(tmp_vec1, mvert_new[i].co, mvert_new[vc->v[0]].co); 00630 } 00631 else { 00632 sub_v3_v3v3(tmp_vec1, mvert_new[vc->v[0]].co, mvert_new[i].co); 00633 } 00634 } 00635 00636 /* vc_no_tmp2 - is a line 90d from the pivot to the vec 00637 * This is used so the resulting normal points directly away from the middle */ 00638 cross_v3_v3v3(tmp_vec2, axis_vec, vc->co); 00639 00640 /* edge average vector and right angle to the pivot make the normal */ 00641 cross_v3_v3v3(vc->no, tmp_vec1, tmp_vec2); 00642 00643 } 00644 else { 00645 copy_v3_v3(vc->no, vc->co); 00646 } 00647 00648 /* we wont be looping on this data again so copy normals here */ 00649 if (angle < 0.0f) 00650 negate_v3(vc->no); 00651 00652 normalize_v3(vc->no); 00653 normal_float_to_short_v3(mvert_new[i].no, vc->no); 00654 00655 /* Done with normals */ 00656 } 00657 } 00658 } 00659 else { 00660 mv_orig= mvert_orig; 00661 mv_new= mvert_new; 00662 00663 for (i=0; i < totvert; i++, mv_new++, mv_orig++) { 00664 copy_v3_v3(mv_new->co, mv_orig->co); 00665 } 00666 } 00667 /* done with edge connectivity based normal flipping */ 00668 00669 /* Add Faces */ 00670 for (step=1; step < step_tot; step++) { 00671 const int varray_stride= totvert * step; 00672 float step_angle; 00673 float nor_tx[3]; 00674 float mat[4][4]; 00675 /* Rotation Matrix */ 00676 step_angle= (angle / (step_tot - (!close))) * step; 00677 00678 if (ltmd->ob_axis) { 00679 axis_angle_to_mat3(mat3, axis_vec, step_angle); 00680 copy_m4_m3(mat, mat3); 00681 } 00682 else { 00683 unit_m4(mat); 00684 rotate_m4(mat, axis_char, step_angle); 00685 copy_m3_m4(mat3, mat); 00686 } 00687 00688 if(screw_ofs) 00689 madd_v3_v3fl(mat[3], axis_vec, screw_ofs * ((float)step / (float)(step_tot-1))); 00690 00691 /* copy a slice */ 00692 DM_copy_vert_data(dm, result, 0, varray_stride, totvert); 00693 00694 mv_new_base= mvert_new; 00695 mv_new= &mvert_new[varray_stride]; /* advance to the next slice */ 00696 00697 for (j=0; j<totvert; j++, mv_new_base++, mv_new++) { 00698 /* set normal */ 00699 if(vert_connect) { 00700 mul_v3_m3v3(nor_tx, mat3, vert_connect[j].no); 00701 00702 /* set the normal now its transformed */ 00703 normal_float_to_short_v3(mv_new->no, nor_tx); 00704 } 00705 00706 /* set location */ 00707 copy_v3_v3(mv_new->co, mv_new_base->co); 00708 00709 /* only need to set these if using non cleared memory */ 00710 /*mv_new->mat_nr= mv_new->flag= 0;*/ 00711 00712 if (ltmd->ob_axis) { 00713 sub_v3_v3(mv_new->co, mtx_tx[3]); 00714 00715 mul_m4_v3(mat, mv_new->co); 00716 00717 add_v3_v3(mv_new->co, mtx_tx[3]); 00718 } 00719 else { 00720 mul_m4_v3(mat, mv_new->co); 00721 } 00722 00723 /* add the new edge */ 00724 med_new->v1= varray_stride + j; 00725 med_new->v2= med_new->v1 - totvert; 00726 med_new->flag= ME_EDGEDRAW|ME_EDGERENDER; 00727 med_new++; 00728 } 00729 } 00730 00731 /* we can avoid if using vert alloc trick */ 00732 if(vert_connect) { 00733 MEM_freeN(vert_connect); 00734 vert_connect= NULL; 00735 } 00736 00737 if (close) { 00738 /* last loop of edges, previous loop dosnt account for the last set of edges */ 00739 const int varray_stride= (step_tot - 1) * totvert; 00740 00741 for (i=0; i<totvert; i++) { 00742 med_new->v1= i; 00743 med_new->v2= varray_stride + i; 00744 med_new->flag= ME_EDGEDRAW|ME_EDGERENDER; 00745 med_new++; 00746 } 00747 } 00748 00749 mf_new= mface_new; 00750 med_new_firstloop= medge_new; 00751 00752 for (i=0; i < totedge; i++, med_new_firstloop++) { 00753 /* for each edge, make a cylinder of quads */ 00754 i1= med_new_firstloop->v1; 00755 i2= med_new_firstloop->v2; 00756 00757 for (step=0; step < step_tot-1; step++) { 00758 00759 /* new face */ 00760 if(do_flip) { 00761 mf_new->v4= i1; 00762 mf_new->v3= i2; 00763 mf_new->v2= i2 + totvert; 00764 mf_new->v1= i1 + totvert; 00765 } 00766 else { 00767 mf_new->v1= i1; 00768 mf_new->v2= i2; 00769 mf_new->v3= i2 + totvert; 00770 mf_new->v4= i1 + totvert; 00771 } 00772 00773 if( !mf_new->v3 || !mf_new->v4 ) { 00774 SWAP(unsigned int, mf_new->v1, mf_new->v3); 00775 SWAP(unsigned int, mf_new->v2, mf_new->v4); 00776 } 00777 mf_new->flag= ME_SMOOTH; 00778 origindex[mface_index]= ORIGINDEX_NONE; 00779 mf_new++; 00780 mface_index++; 00781 00782 /* new vertical edge */ 00783 if (step) { /* The first set is already dome */ 00784 med_new->v1= i1; 00785 med_new->v2= i2; 00786 med_new->flag= med_new_firstloop->flag; 00787 med_new->crease= med_new_firstloop->crease; 00788 med_new++; 00789 } 00790 i1 += totvert; 00791 i2 += totvert; 00792 } 00793 00794 /* close the loop*/ 00795 if (close) { 00796 if(do_flip) { 00797 mf_new->v4= i1; 00798 mf_new->v3= i2; 00799 mf_new->v2= med_new_firstloop->v2; 00800 mf_new->v1= med_new_firstloop->v1; 00801 } 00802 else { 00803 mf_new->v1= i1; 00804 mf_new->v2= i2; 00805 mf_new->v3= med_new_firstloop->v2; 00806 mf_new->v4= med_new_firstloop->v1; 00807 } 00808 00809 if( !mf_new->v3 || !mf_new->v4 ) { 00810 SWAP(unsigned int, mf_new->v1, mf_new->v3); 00811 SWAP(unsigned int, mf_new->v2, mf_new->v4); 00812 } 00813 mf_new->flag= ME_SMOOTH; 00814 origindex[mface_index]= ORIGINDEX_NONE; 00815 mf_new++; 00816 mface_index++; 00817 } 00818 00819 /* new vertical edge */ 00820 med_new->v1= i1; 00821 med_new->v2= i2; 00822 med_new->flag= med_new_firstloop->flag & ~ME_LOOSEEDGE; 00823 med_new->crease= med_new_firstloop->crease; 00824 med_new++; 00825 } 00826 00827 if((ltmd->flag & MOD_SCREW_NORMAL_CALC) == 0) { 00828 CDDM_calc_normals(result); 00829 } 00830 00831 return result; 00832 } 00833 00834 00835 static void updateDepgraph(ModifierData *md, DagForest *forest, 00836 struct Scene *UNUSED(scene), 00837 Object *UNUSED(ob), 00838 DagNode *obNode) 00839 { 00840 ScrewModifierData *ltmd= (ScrewModifierData*) md; 00841 00842 if(ltmd->ob_axis) { 00843 DagNode *curNode= dag_get_node(forest, ltmd->ob_axis); 00844 00845 dag_add_relation(forest, curNode, obNode, 00846 DAG_RL_DATA_DATA | DAG_RL_OB_DATA, 00847 "Screw Modifier"); 00848 } 00849 } 00850 00851 static void foreachObjectLink( 00852 ModifierData *md, Object *ob, 00853 void (*walk)(void *userData, Object *ob, Object **obpoin), 00854 void *userData) 00855 { 00856 ScrewModifierData *ltmd= (ScrewModifierData*) md; 00857 00858 walk(userData, ob, <md->ob_axis); 00859 } 00860 00861 /* This dosnt work with material*/ 00862 static DerivedMesh *applyModifierEM( 00863 ModifierData *md, 00864 Object *ob, 00865 struct EditMesh *UNUSED(editData), 00866 DerivedMesh *derivedData) 00867 { 00868 return applyModifier(md, ob, derivedData, 0, 1); 00869 } 00870 00871 static int dependsOnTime(ModifierData *UNUSED(md)) 00872 { 00873 return 0; 00874 } 00875 00876 00877 ModifierTypeInfo modifierType_Screw = { 00878 /* name */ "Screw", 00879 /* structName */ "ScrewModifierData", 00880 /* structSize */ sizeof(ScrewModifierData), 00881 /* type */ eModifierTypeType_Constructive, 00882 00883 /* flags */ eModifierTypeFlag_AcceptsMesh 00884 | eModifierTypeFlag_AcceptsCVs 00885 | eModifierTypeFlag_SupportsEditmode 00886 | eModifierTypeFlag_EnableInEditmode, 00887 00888 /* copyData */ copyData, 00889 /* deformVerts */ NULL, 00890 /* deformMatrices */ NULL, 00891 /* deformVertsEM */ NULL, 00892 /* deformMatricesEM */ NULL, 00893 /* applyModifier */ applyModifier, 00894 /* applyModifierEM */ applyModifierEM, 00895 /* initData */ initData, 00896 /* requiredDataMask */ NULL, 00897 /* freeData */ NULL, 00898 /* isDisabled */ NULL, 00899 /* updateDepgraph */ updateDepgraph, 00900 /* dependsOnTime */ dependsOnTime, 00901 /* dependsOnNormals */ NULL, 00902 /* foreachObjectLink */ foreachObjectLink, 00903 /* foreachIDLink */ NULL, 00904 /* foreachTexLink */ NULL, 00905 };