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