|
Blender
V2.59
|
00001 /* 00002 * $Id: MOD_array.c 36276 2011-04-21 15:53:30Z 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 /* Array modifier: duplicates the object multiple times along an axis */ 00039 00040 #include "MEM_guardedalloc.h" 00041 00042 #include "BLI_math.h" 00043 #include "BLI_utildefines.h" 00044 #include "BLI_ghash.h" 00045 #include "BLI_edgehash.h" 00046 00047 #include "DNA_curve_types.h" 00048 #include "DNA_meshdata_types.h" 00049 #include "DNA_object_types.h" 00050 00051 #include "BKE_cdderivedmesh.h" 00052 #include "BKE_displist.h" 00053 #include "BKE_mesh.h" 00054 #include "BKE_modifier.h" 00055 #include "BKE_object.h" 00056 00057 #include "depsgraph_private.h" 00058 00059 #include "MOD_util.h" 00060 00061 static void initData(ModifierData *md) 00062 { 00063 ArrayModifierData *amd = (ArrayModifierData*) md; 00064 00065 /* default to 2 duplicates distributed along the x-axis by an 00066 offset of 1 object-width 00067 */ 00068 amd->start_cap = amd->end_cap = amd->curve_ob = amd->offset_ob = NULL; 00069 amd->count = 2; 00070 amd->offset[0] = amd->offset[1] = amd->offset[2] = 0; 00071 amd->scale[0] = 1; 00072 amd->scale[1] = amd->scale[2] = 0; 00073 amd->length = 0; 00074 amd->merge_dist = 0.01; 00075 amd->fit_type = MOD_ARR_FIXEDCOUNT; 00076 amd->offset_type = MOD_ARR_OFF_RELATIVE; 00077 amd->flags = 0; 00078 } 00079 00080 static void copyData(ModifierData *md, ModifierData *target) 00081 { 00082 ArrayModifierData *amd = (ArrayModifierData*) md; 00083 ArrayModifierData *tamd = (ArrayModifierData*) target; 00084 00085 tamd->start_cap = amd->start_cap; 00086 tamd->end_cap = amd->end_cap; 00087 tamd->curve_ob = amd->curve_ob; 00088 tamd->offset_ob = amd->offset_ob; 00089 tamd->count = amd->count; 00090 copy_v3_v3(tamd->offset, amd->offset); 00091 copy_v3_v3(tamd->scale, amd->scale); 00092 tamd->length = amd->length; 00093 tamd->merge_dist = amd->merge_dist; 00094 tamd->fit_type = amd->fit_type; 00095 tamd->offset_type = amd->offset_type; 00096 tamd->flags = amd->flags; 00097 } 00098 00099 static void foreachObjectLink( 00100 ModifierData *md, Object *ob, 00101 void (*walk)(void *userData, Object *ob, Object **obpoin), 00102 void *userData) 00103 { 00104 ArrayModifierData *amd = (ArrayModifierData*) md; 00105 00106 walk(userData, ob, &amd->start_cap); 00107 walk(userData, ob, &amd->end_cap); 00108 walk(userData, ob, &amd->curve_ob); 00109 walk(userData, ob, &amd->offset_ob); 00110 } 00111 00112 static void updateDepgraph(ModifierData *md, DagForest *forest, 00113 struct Scene *UNUSED(scene), Object *UNUSED(ob), DagNode *obNode) 00114 { 00115 ArrayModifierData *amd = (ArrayModifierData*) md; 00116 00117 if (amd->start_cap) { 00118 DagNode *curNode = dag_get_node(forest, amd->start_cap); 00119 00120 dag_add_relation(forest, curNode, obNode, 00121 DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier"); 00122 } 00123 if (amd->end_cap) { 00124 DagNode *curNode = dag_get_node(forest, amd->end_cap); 00125 00126 dag_add_relation(forest, curNode, obNode, 00127 DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier"); 00128 } 00129 if (amd->curve_ob) { 00130 DagNode *curNode = dag_get_node(forest, amd->curve_ob); 00131 00132 dag_add_relation(forest, curNode, obNode, 00133 DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier"); 00134 } 00135 if (amd->offset_ob) { 00136 DagNode *curNode = dag_get_node(forest, amd->offset_ob); 00137 00138 dag_add_relation(forest, curNode, obNode, 00139 DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier"); 00140 } 00141 } 00142 00143 static float vertarray_size(MVert *mvert, int numVerts, int axis) 00144 { 00145 int i; 00146 float min_co, max_co; 00147 00148 /* if there are no vertices, width is 0 */ 00149 if(numVerts == 0) return 0; 00150 00151 /* find the minimum and maximum coordinates on the desired axis */ 00152 min_co = max_co = mvert->co[axis]; 00153 ++mvert; 00154 for(i = 1; i < numVerts; ++i, ++mvert) { 00155 if(mvert->co[axis] < min_co) min_co = mvert->co[axis]; 00156 if(mvert->co[axis] > max_co) max_co = mvert->co[axis]; 00157 } 00158 00159 return max_co - min_co; 00160 } 00161 00162 /* XXX This function fixes bad merging code, in some cases removing vertices creates indices > maxvert */ 00163 00164 static int test_index_face_maxvert(MFace *mface, CustomData *fdata, int mfindex, int nr, int maxvert) 00165 { 00166 if(mface->v1 >= maxvert) { 00167 // printf("bad index in array\n"); 00168 mface->v1= maxvert - 1; 00169 } 00170 if(mface->v2 >= maxvert) { 00171 // printf("bad index in array\n"); 00172 mface->v2= maxvert - 1; 00173 } 00174 if(mface->v3 >= maxvert) { 00175 // printf("bad index in array\n"); 00176 mface->v3= maxvert - 1; 00177 } 00178 if(mface->v4 >= maxvert) { 00179 // printf("bad index in array\n"); 00180 mface->v4= maxvert - 1; 00181 } 00182 00183 return test_index_face(mface, fdata, mfindex, nr); 00184 } 00185 00186 typedef struct IndexMapEntry { 00187 /* the new vert index that this old vert index maps to */ 00188 int new; 00189 /* -1 if this vert isn't merged, otherwise the old vert index it 00190 * should be replaced with 00191 */ 00192 int merge; 00193 /* 1 if this vert's first copy is merged with the last copy of its 00194 * merge target, otherwise 0 00195 */ 00196 short merge_final; 00197 } IndexMapEntry; 00198 00199 /* indexMap - an array of IndexMap entries 00200 * oldIndex - the old index to map 00201 * copyNum - the copy number to map to (original = 0, first copy = 1, etc.) 00202 */ 00203 static int calc_mapping(IndexMapEntry *indexMap, int oldIndex, int copyNum) 00204 { 00205 if(indexMap[oldIndex].merge < 0) { 00206 /* vert wasn't merged, so use copy of this vert */ 00207 return indexMap[oldIndex].new + copyNum; 00208 } else if(indexMap[oldIndex].merge == oldIndex) { 00209 /* vert was merged with itself */ 00210 return indexMap[oldIndex].new; 00211 } else { 00212 /* vert was merged with another vert */ 00213 /* follow the chain of merges to the end, or until we've passed 00214 * a number of vertices equal to the copy number 00215 */ 00216 if(copyNum <= 0) 00217 return indexMap[oldIndex].new; 00218 else 00219 return calc_mapping(indexMap, indexMap[oldIndex].merge, 00220 copyNum - 1); 00221 } 00222 } 00223 00224 static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, 00225 struct Scene *scene, Object *ob, DerivedMesh *dm, 00226 int initFlags) 00227 { 00228 int i, j; 00229 /* offset matrix */ 00230 float offset[4][4]; 00231 float final_offset[4][4]; 00232 float tmp_mat[4][4]; 00233 float length = amd->length; 00234 int count = amd->count; 00235 int numVerts, numEdges, numFaces; 00236 int maxVerts, maxEdges, maxFaces; 00237 int finalVerts, finalEdges, finalFaces; 00238 DerivedMesh *result, *start_cap = NULL, *end_cap = NULL; 00239 MVert *mvert, *src_mvert; 00240 MEdge *medge; 00241 MFace *mface; 00242 00243 IndexMapEntry *indexMap; 00244 00245 EdgeHash *edges; 00246 00247 /* need to avoid infinite recursion here */ 00248 if(amd->start_cap && amd->start_cap != ob) 00249 start_cap = amd->start_cap->derivedFinal; 00250 if(amd->end_cap && amd->end_cap != ob) 00251 end_cap = amd->end_cap->derivedFinal; 00252 00253 unit_m4(offset); 00254 00255 indexMap = MEM_callocN(sizeof(*indexMap) * dm->getNumVerts(dm), 00256 "indexmap"); 00257 00258 src_mvert = dm->getVertArray(dm); 00259 00260 maxVerts = dm->getNumVerts(dm); 00261 00262 if(amd->offset_type & MOD_ARR_OFF_CONST) 00263 add_v3_v3(offset[3], amd->offset); 00264 if(amd->offset_type & MOD_ARR_OFF_RELATIVE) { 00265 for(j = 0; j < 3; j++) 00266 offset[3][j] += amd->scale[j] * vertarray_size(src_mvert, 00267 maxVerts, j); 00268 } 00269 00270 if((amd->offset_type & MOD_ARR_OFF_OBJ) && (amd->offset_ob)) { 00271 float obinv[4][4]; 00272 float result_mat[4][4]; 00273 00274 if(ob) 00275 invert_m4_m4(obinv, ob->obmat); 00276 else 00277 unit_m4(obinv); 00278 00279 mul_serie_m4(result_mat, offset, 00280 obinv, amd->offset_ob->obmat, 00281 NULL, NULL, NULL, NULL, NULL); 00282 copy_m4_m4(offset, result_mat); 00283 } 00284 00285 if(amd->fit_type == MOD_ARR_FITCURVE && amd->curve_ob) { 00286 Curve *cu = amd->curve_ob->data; 00287 if(cu) { 00288 float tmp_mat[3][3]; 00289 float scale; 00290 00291 object_to_mat3(amd->curve_ob, tmp_mat); 00292 scale = mat3_to_scale(tmp_mat); 00293 00294 if(!cu->path) { 00295 cu->flag |= CU_PATH; // needed for path & bevlist 00296 makeDispListCurveTypes(scene, amd->curve_ob, 0); 00297 } 00298 if(cu->path) 00299 length = scale*cu->path->totdist; 00300 } 00301 } 00302 00303 /* calculate the maximum number of copies which will fit within the 00304 prescribed length */ 00305 if(amd->fit_type == MOD_ARR_FITLENGTH 00306 || amd->fit_type == MOD_ARR_FITCURVE) { 00307 float dist = sqrt(dot_v3v3(offset[3], offset[3])); 00308 00309 if(dist > 1e-6f) 00310 /* this gives length = first copy start to last copy end 00311 add a tiny offset for floating point rounding errors */ 00312 count = (length + 1e-6f) / dist; 00313 else 00314 /* if the offset has no translation, just make one copy */ 00315 count = 1; 00316 } 00317 00318 if(count < 1) 00319 count = 1; 00320 00321 /* allocate memory for count duplicates (including original) plus 00322 * start and end caps 00323 */ 00324 finalVerts = dm->getNumVerts(dm) * count; 00325 finalEdges = dm->getNumEdges(dm) * count; 00326 finalFaces = dm->getNumFaces(dm) * count; 00327 if(start_cap) { 00328 finalVerts += start_cap->getNumVerts(start_cap); 00329 finalEdges += start_cap->getNumEdges(start_cap); 00330 finalFaces += start_cap->getNumFaces(start_cap); 00331 } 00332 if(end_cap) { 00333 finalVerts += end_cap->getNumVerts(end_cap); 00334 finalEdges += end_cap->getNumEdges(end_cap); 00335 finalFaces += end_cap->getNumFaces(end_cap); 00336 } 00337 result = CDDM_from_template(dm, finalVerts, finalEdges, finalFaces); 00338 00339 /* calculate the offset matrix of the final copy (for merging) */ 00340 unit_m4(final_offset); 00341 00342 for(j=0; j < count - 1; j++) { 00343 mul_m4_m4m4(tmp_mat, final_offset, offset); 00344 copy_m4_m4(final_offset, tmp_mat); 00345 } 00346 00347 numVerts = numEdges = numFaces = 0; 00348 mvert = CDDM_get_verts(result); 00349 00350 for (i = 0; i < maxVerts; i++) { 00351 indexMap[i].merge = -1; /* default to no merge */ 00352 indexMap[i].merge_final = 0; /* default to no merge */ 00353 } 00354 00355 for (i = 0; i < maxVerts; i++) { 00356 MVert *inMV; 00357 MVert *mv = &mvert[numVerts]; 00358 MVert *mv2; 00359 float co[3]; 00360 00361 inMV = &src_mvert[i]; 00362 00363 DM_copy_vert_data(dm, result, i, numVerts, 1); 00364 *mv = *inMV; 00365 numVerts++; 00366 00367 indexMap[i].new = numVerts - 1; 00368 00369 copy_v3_v3(co, mv->co); 00370 00371 /* Attempts to merge verts from one duplicate with verts from the 00372 * next duplicate which are closer than amd->merge_dist. 00373 * Only the first such vert pair is merged. 00374 * If verts are merged in the first duplicate pair, they are merged 00375 * in all pairs. 00376 */ 00377 if((count > 1) && (amd->flags & MOD_ARR_MERGE)) { 00378 float tmp_co[3]; 00379 mul_v3_m4v3(tmp_co, offset, mv->co); 00380 00381 for(j = 0; j < maxVerts; j++) { 00382 /* if vertex already merged, don't use it */ 00383 if( indexMap[j].merge != -1 ) continue; 00384 00385 inMV = &src_mvert[j]; 00386 /* if this vert is within merge limit, merge */ 00387 if(compare_len_v3v3(tmp_co, inMV->co, amd->merge_dist)) { 00388 indexMap[i].merge = j; 00389 00390 /* test for merging with final copy of merge target */ 00391 if(amd->flags & MOD_ARR_MERGEFINAL) { 00392 copy_v3_v3(tmp_co, inMV->co); 00393 inMV = &src_mvert[i]; 00394 mul_m4_v3(final_offset, tmp_co); 00395 if(compare_len_v3v3(tmp_co, inMV->co, amd->merge_dist)) 00396 indexMap[i].merge_final = 1; 00397 } 00398 break; 00399 } 00400 } 00401 } 00402 00403 /* if no merging, generate copies of this vert */ 00404 if(indexMap[i].merge < 0) { 00405 for(j=0; j < count - 1; j++) { 00406 mv2 = &mvert[numVerts]; 00407 00408 DM_copy_vert_data(result, result, numVerts - 1, numVerts, 1); 00409 *mv2 = *mv; 00410 numVerts++; 00411 00412 mul_m4_v3(offset, co); 00413 copy_v3_v3(mv2->co, co); 00414 } 00415 } else if(indexMap[i].merge != i && indexMap[i].merge_final) { 00416 /* if this vert is not merging with itself, and it is merging 00417 * with the final copy of its merge target, remove the first copy 00418 */ 00419 numVerts--; 00420 DM_free_vert_data(result, numVerts, 1); 00421 } 00422 } 00423 00424 /* make a hashtable so we can avoid duplicate edges from merging */ 00425 edges = BLI_edgehash_new(); 00426 00427 maxEdges = dm->getNumEdges(dm); 00428 medge = CDDM_get_edges(result); 00429 for(i = 0; i < maxEdges; i++) { 00430 MEdge inMED; 00431 MEdge med; 00432 MEdge *med2; 00433 int vert1, vert2; 00434 00435 dm->getEdge(dm, i, &inMED); 00436 00437 med = inMED; 00438 med.v1 = indexMap[inMED.v1].new; 00439 med.v2 = indexMap[inMED.v2].new; 00440 00441 /* if vertices are to be merged with the final copies of their 00442 * merge targets, calculate that final copy 00443 */ 00444 if(indexMap[inMED.v1].merge_final) { 00445 med.v1 = calc_mapping(indexMap, indexMap[inMED.v1].merge, 00446 count - 1); 00447 } 00448 if(indexMap[inMED.v2].merge_final) { 00449 med.v2 = calc_mapping(indexMap, indexMap[inMED.v2].merge, 00450 count - 1); 00451 } 00452 00453 if(med.v1 == med.v2) continue; 00454 00455 /* XXX Unfortunately the calc_mapping returns sometimes numVerts... leads to bad crashes */ 00456 if(med.v1 >= numVerts) 00457 med.v1= numVerts-1; 00458 if(med.v2 >= numVerts) 00459 med.v2= numVerts-1; 00460 00461 if (initFlags) { 00462 med.flag |= ME_EDGEDRAW | ME_EDGERENDER; 00463 } 00464 00465 if(!BLI_edgehash_haskey(edges, med.v1, med.v2)) { 00466 DM_copy_edge_data(dm, result, i, numEdges, 1); 00467 medge[numEdges] = med; 00468 numEdges++; 00469 00470 BLI_edgehash_insert(edges, med.v1, med.v2, NULL); 00471 } 00472 00473 for(j = 1; j < count; j++) 00474 { 00475 vert1 = calc_mapping(indexMap, inMED.v1, j); 00476 vert2 = calc_mapping(indexMap, inMED.v2, j); 00477 00478 /* edge could collapse to single point after mapping */ 00479 if(vert1 == vert2) continue; 00480 00481 /* XXX Unfortunately the calc_mapping returns sometimes numVerts... leads to bad crashes */ 00482 if(vert1 >= numVerts) 00483 vert1= numVerts-1; 00484 if(vert2 >= numVerts) 00485 vert2= numVerts-1; 00486 00487 /* avoid duplicate edges */ 00488 if(!BLI_edgehash_haskey(edges, vert1, vert2)) { 00489 med2 = &medge[numEdges]; 00490 00491 DM_copy_edge_data(dm, result, i, numEdges, 1); 00492 *med2 = med; 00493 numEdges++; 00494 00495 med2->v1 = vert1; 00496 med2->v2 = vert2; 00497 00498 BLI_edgehash_insert(edges, med2->v1, med2->v2, NULL); 00499 } 00500 } 00501 } 00502 00503 maxFaces = dm->getNumFaces(dm); 00504 mface = CDDM_get_faces(result); 00505 for (i=0; i < maxFaces; i++) { 00506 MFace inMF; 00507 MFace *mf = &mface[numFaces]; 00508 00509 dm->getFace(dm, i, &inMF); 00510 00511 DM_copy_face_data(dm, result, i, numFaces, 1); 00512 *mf = inMF; 00513 00514 mf->v1 = indexMap[inMF.v1].new; 00515 mf->v2 = indexMap[inMF.v2].new; 00516 mf->v3 = indexMap[inMF.v3].new; 00517 if(inMF.v4) 00518 mf->v4 = indexMap[inMF.v4].new; 00519 00520 /* if vertices are to be merged with the final copies of their 00521 * merge targets, calculate that final copy 00522 */ 00523 if(indexMap[inMF.v1].merge_final) 00524 mf->v1 = calc_mapping(indexMap, indexMap[inMF.v1].merge, count-1); 00525 if(indexMap[inMF.v2].merge_final) 00526 mf->v2 = calc_mapping(indexMap, indexMap[inMF.v2].merge, count-1); 00527 if(indexMap[inMF.v3].merge_final) 00528 mf->v3 = calc_mapping(indexMap, indexMap[inMF.v3].merge, count-1); 00529 if(inMF.v4 && indexMap[inMF.v4].merge_final) 00530 mf->v4 = calc_mapping(indexMap, indexMap[inMF.v4].merge, count-1); 00531 00532 if(test_index_face_maxvert(mf, &result->faceData, numFaces, inMF.v4?4:3, numVerts) < 3) 00533 continue; 00534 00535 numFaces++; 00536 00537 /* if the face has fewer than 3 vertices, don't create it */ 00538 if(mf->v3 == 0 || (mf->v1 && (mf->v1 == mf->v3 || mf->v1 == mf->v4))) { 00539 numFaces--; 00540 DM_free_face_data(result, numFaces, 1); 00541 } 00542 00543 for(j = 1; j < count; j++) 00544 { 00545 MFace *mf2 = &mface[numFaces]; 00546 00547 DM_copy_face_data(dm, result, i, numFaces, 1); 00548 *mf2 = *mf; 00549 00550 mf2->v1 = calc_mapping(indexMap, inMF.v1, j); 00551 mf2->v2 = calc_mapping(indexMap, inMF.v2, j); 00552 mf2->v3 = calc_mapping(indexMap, inMF.v3, j); 00553 if (inMF.v4) 00554 mf2->v4 = calc_mapping(indexMap, inMF.v4, j); 00555 00556 numFaces++; 00557 00558 /* if the face has fewer than 3 vertices, don't create it */ 00559 if(test_index_face_maxvert(mf2, &result->faceData, numFaces-1, inMF.v4?4:3, numVerts) < 3) { 00560 numFaces--; 00561 DM_free_face_data(result, numFaces, 1); 00562 } 00563 } 00564 } 00565 00566 /* add start and end caps */ 00567 if(start_cap) { 00568 float startoffset[4][4]; 00569 MVert *cap_mvert; 00570 MEdge *cap_medge; 00571 MFace *cap_mface; 00572 int *origindex; 00573 int *vert_map; 00574 int capVerts, capEdges, capFaces; 00575 00576 capVerts = start_cap->getNumVerts(start_cap); 00577 capEdges = start_cap->getNumEdges(start_cap); 00578 capFaces = start_cap->getNumFaces(start_cap); 00579 cap_mvert = start_cap->getVertArray(start_cap); 00580 cap_medge = start_cap->getEdgeArray(start_cap); 00581 cap_mface = start_cap->getFaceArray(start_cap); 00582 00583 invert_m4_m4(startoffset, offset); 00584 00585 vert_map = MEM_callocN(sizeof(*vert_map) * capVerts, 00586 "arrayModifier_doArray vert_map"); 00587 00588 origindex = result->getVertDataArray(result, CD_ORIGINDEX); 00589 for(i = 0; i < capVerts; i++) { 00590 MVert *mv = &cap_mvert[i]; 00591 short merged = 0; 00592 00593 if(amd->flags & MOD_ARR_MERGE) { 00594 float tmp_co[3]; 00595 MVert *in_mv; 00596 int j; 00597 00598 copy_v3_v3(tmp_co, mv->co); 00599 mul_m4_v3(startoffset, tmp_co); 00600 00601 for(j = 0; j < maxVerts; j++) { 00602 in_mv = &src_mvert[j]; 00603 /* if this vert is within merge limit, merge */ 00604 if(compare_len_v3v3(tmp_co, in_mv->co, amd->merge_dist)) { 00605 vert_map[i] = calc_mapping(indexMap, j, 0); 00606 merged = 1; 00607 break; 00608 } 00609 } 00610 } 00611 00612 if(!merged) { 00613 DM_copy_vert_data(start_cap, result, i, numVerts, 1); 00614 mvert[numVerts] = *mv; 00615 mul_m4_v3(startoffset, mvert[numVerts].co); 00616 origindex[numVerts] = ORIGINDEX_NONE; 00617 00618 vert_map[i] = numVerts; 00619 00620 numVerts++; 00621 } 00622 } 00623 origindex = result->getEdgeDataArray(result, CD_ORIGINDEX); 00624 for(i = 0; i < capEdges; i++) { 00625 int v1, v2; 00626 00627 v1 = vert_map[cap_medge[i].v1]; 00628 v2 = vert_map[cap_medge[i].v2]; 00629 00630 if(!BLI_edgehash_haskey(edges, v1, v2)) { 00631 DM_copy_edge_data(start_cap, result, i, numEdges, 1); 00632 medge[numEdges] = cap_medge[i]; 00633 medge[numEdges].v1 = v1; 00634 medge[numEdges].v2 = v2; 00635 origindex[numEdges] = ORIGINDEX_NONE; 00636 00637 numEdges++; 00638 } 00639 } 00640 origindex = result->getFaceDataArray(result, CD_ORIGINDEX); 00641 for(i = 0; i < capFaces; i++) { 00642 DM_copy_face_data(start_cap, result, i, numFaces, 1); 00643 mface[numFaces] = cap_mface[i]; 00644 mface[numFaces].v1 = vert_map[mface[numFaces].v1]; 00645 mface[numFaces].v2 = vert_map[mface[numFaces].v2]; 00646 mface[numFaces].v3 = vert_map[mface[numFaces].v3]; 00647 if(mface[numFaces].v4) { 00648 mface[numFaces].v4 = vert_map[mface[numFaces].v4]; 00649 00650 test_index_face_maxvert(&mface[numFaces], &result->faceData, 00651 numFaces, 4, numVerts); 00652 } 00653 else 00654 { 00655 test_index_face(&mface[numFaces], &result->faceData, 00656 numFaces, 3); 00657 } 00658 00659 origindex[numFaces] = ORIGINDEX_NONE; 00660 00661 numFaces++; 00662 } 00663 00664 MEM_freeN(vert_map); 00665 start_cap->release(start_cap); 00666 } 00667 00668 if(end_cap) { 00669 float endoffset[4][4]; 00670 MVert *cap_mvert; 00671 MEdge *cap_medge; 00672 MFace *cap_mface; 00673 int *origindex; 00674 int *vert_map; 00675 int capVerts, capEdges, capFaces; 00676 00677 capVerts = end_cap->getNumVerts(end_cap); 00678 capEdges = end_cap->getNumEdges(end_cap); 00679 capFaces = end_cap->getNumFaces(end_cap); 00680 cap_mvert = end_cap->getVertArray(end_cap); 00681 cap_medge = end_cap->getEdgeArray(end_cap); 00682 cap_mface = end_cap->getFaceArray(end_cap); 00683 00684 mul_m4_m4m4(endoffset, final_offset, offset); 00685 00686 vert_map = MEM_callocN(sizeof(*vert_map) * capVerts, 00687 "arrayModifier_doArray vert_map"); 00688 00689 origindex = result->getVertDataArray(result, CD_ORIGINDEX); 00690 for(i = 0; i < capVerts; i++) { 00691 MVert *mv = &cap_mvert[i]; 00692 short merged = 0; 00693 00694 if(amd->flags & MOD_ARR_MERGE) { 00695 float tmp_co[3]; 00696 MVert *in_mv; 00697 int j; 00698 00699 copy_v3_v3(tmp_co, mv->co); 00700 mul_m4_v3(offset, tmp_co); 00701 00702 for(j = 0; j < maxVerts; j++) { 00703 in_mv = &src_mvert[j]; 00704 /* if this vert is within merge limit, merge */ 00705 if(compare_len_v3v3(tmp_co, in_mv->co, amd->merge_dist)) { 00706 vert_map[i] = calc_mapping(indexMap, j, count - 1); 00707 merged = 1; 00708 break; 00709 } 00710 } 00711 } 00712 00713 if(!merged) { 00714 DM_copy_vert_data(end_cap, result, i, numVerts, 1); 00715 mvert[numVerts] = *mv; 00716 mul_m4_v3(endoffset, mvert[numVerts].co); 00717 origindex[numVerts] = ORIGINDEX_NONE; 00718 00719 vert_map[i] = numVerts; 00720 00721 numVerts++; 00722 } 00723 } 00724 origindex = result->getEdgeDataArray(result, CD_ORIGINDEX); 00725 for(i = 0; i < capEdges; i++) { 00726 int v1, v2; 00727 00728 v1 = vert_map[cap_medge[i].v1]; 00729 v2 = vert_map[cap_medge[i].v2]; 00730 00731 if(!BLI_edgehash_haskey(edges, v1, v2)) { 00732 DM_copy_edge_data(end_cap, result, i, numEdges, 1); 00733 medge[numEdges] = cap_medge[i]; 00734 medge[numEdges].v1 = v1; 00735 medge[numEdges].v2 = v2; 00736 origindex[numEdges] = ORIGINDEX_NONE; 00737 00738 numEdges++; 00739 } 00740 } 00741 origindex = result->getFaceDataArray(result, CD_ORIGINDEX); 00742 for(i = 0; i < capFaces; i++) { 00743 DM_copy_face_data(end_cap, result, i, numFaces, 1); 00744 mface[numFaces] = cap_mface[i]; 00745 mface[numFaces].v1 = vert_map[mface[numFaces].v1]; 00746 mface[numFaces].v2 = vert_map[mface[numFaces].v2]; 00747 mface[numFaces].v3 = vert_map[mface[numFaces].v3]; 00748 if(mface[numFaces].v4) { 00749 mface[numFaces].v4 = vert_map[mface[numFaces].v4]; 00750 00751 test_index_face(&mface[numFaces], &result->faceData, 00752 numFaces, 4); 00753 } 00754 else 00755 { 00756 test_index_face(&mface[numFaces], &result->faceData, 00757 numFaces, 3); 00758 } 00759 origindex[numFaces] = ORIGINDEX_NONE; 00760 00761 numFaces++; 00762 } 00763 00764 MEM_freeN(vert_map); 00765 end_cap->release(end_cap); 00766 } 00767 00768 BLI_edgehash_free(edges, NULL); 00769 MEM_freeN(indexMap); 00770 00771 CDDM_lower_num_verts(result, numVerts); 00772 CDDM_lower_num_edges(result, numEdges); 00773 CDDM_lower_num_faces(result, numFaces); 00774 00775 return result; 00776 } 00777 00778 static DerivedMesh *applyModifier(ModifierData *md, Object *ob, 00779 DerivedMesh *dm, 00780 int UNUSED(useRenderParams), 00781 int UNUSED(isFinalCalc)) 00782 { 00783 DerivedMesh *result; 00784 ArrayModifierData *amd = (ArrayModifierData*) md; 00785 00786 result = arrayModifier_doArray(amd, md->scene, ob, dm, 0); 00787 00788 if(result != dm) 00789 CDDM_calc_normals(result); 00790 00791 return result; 00792 } 00793 00794 static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob, 00795 struct EditMesh *UNUSED(editData), 00796 DerivedMesh *dm) 00797 { 00798 return applyModifier(md, ob, dm, 0, 1); 00799 } 00800 00801 00802 ModifierTypeInfo modifierType_Array = { 00803 /* name */ "Array", 00804 /* structName */ "ArrayModifierData", 00805 /* structSize */ sizeof(ArrayModifierData), 00806 /* type */ eModifierTypeType_Constructive, 00807 /* flags */ eModifierTypeFlag_AcceptsMesh 00808 | eModifierTypeFlag_SupportsMapping 00809 | eModifierTypeFlag_SupportsEditmode 00810 | eModifierTypeFlag_EnableInEditmode 00811 | eModifierTypeFlag_AcceptsCVs, 00812 00813 /* copyData */ copyData, 00814 /* deformVerts */ NULL, 00815 /* deformMatrices */ NULL, 00816 /* deformVertsEM */ NULL, 00817 /* deformMatricesEM */ NULL, 00818 /* applyModifier */ applyModifier, 00819 /* applyModifierEM */ applyModifierEM, 00820 /* initData */ initData, 00821 /* requiredDataMask */ NULL, 00822 /* freeData */ NULL, 00823 /* isDisabled */ NULL, 00824 /* updateDepgraph */ updateDepgraph, 00825 /* dependsOnTime */ NULL, 00826 /* dependsOnNormals */ NULL, 00827 /* foreachObjectLink */ foreachObjectLink, 00828 /* foreachIDLink */ NULL, 00829 };