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