diff options
author | Campbell Barton <ideasman42@gmail.com> | 2010-04-12 02:12:30 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2010-04-12 02:12:30 +0400 |
commit | 3fdaf5cecc9c7c521c4db514f916f083b17881a6 (patch) | |
tree | fabdb833cab9ba68321fe9687abb5a44fd303798 /source/blender/modifiers/intern/MOD_array.c | |
parent | 139a0e7cb8a9003baa3d50d6d99d7f437b1d1899 (diff) |
[#14437] Modifier Stack Refactor
patch by Ben Batt (artificer)
Updated patch for 6 or so modifiers added since the patch was written.
- tested with CMake and SCons
- fixed one error were flags were being added to the fluids type.
- remove BKE_simple_deform.h, simple_deform.c, move functions into MOD_simpledeform.c since there were problems with circular deps.
- moved some fluid and boolean functions used by modifiers too.
Diffstat (limited to 'source/blender/modifiers/intern/MOD_array.c')
-rw-r--r-- | source/blender/modifiers/intern/MOD_array.c | 813 |
1 files changed, 813 insertions, 0 deletions
diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c new file mode 100644 index 00000000000..1d28b424895 --- /dev/null +++ b/source/blender/modifiers/intern/MOD_array.c @@ -0,0 +1,813 @@ +/* +* $Id: +* +* ***** BEGIN GPL LICENSE BLOCK ***** +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software Foundation, +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +* The Original Code is Copyright (C) 2005 by the Blender Foundation. +* All rights reserved. +* +* Contributor(s): Daniel Dunbar +* Ton Roosendaal, +* Ben Batt, +* Brecht Van Lommel, +* Campbell Barton +* +* ***** END GPL LICENSE BLOCK ***** +* +*/ + +#include "stddef.h" +#include "string.h" +#include "stdarg.h" +#include "math.h" +#include "float.h" + +#include "BLI_kdtree.h" +#include "BLI_rand.h" +#include "BLI_uvproject.h" + +#include "MEM_guardedalloc.h" + +#include "DNA_armature_types.h" +#include "DNA_camera_types.h" +#include "DNA_curve_types.h" +#include "DNA_key_types.h" +#include "DNA_material_types.h" +#include "DNA_object_fluidsim.h" + + +#include "BKE_action.h" +#include "BKE_bmesh.h" +#include "BKE_booleanops.h" +#include "BKE_cloth.h" +#include "BKE_cdderivedmesh.h" +#include "BKE_displist.h" +#include "BKE_fluidsim.h" +#include "BKE_global.h" +#include "BKE_multires.h" +#include "BKE_key.h" +#include "BKE_lattice.h" +#include "BKE_material.h" +#include "BKE_mesh.h" +#include "BKE_modifier.h" +#include "BKE_object.h" +#include "BKE_paint.h" +#include "BKE_particle.h" +#include "BKE_pointcache.h" +#include "BKE_scene.h" +#include "BKE_smoke.h" +#include "BKE_softbody.h" +#include "BKE_subsurf.h" +#include "BKE_texture.h" + +#include "depsgraph_private.h" + +#include "MOD_modifiertypes.h" + +/* Array */ +/* Array modifier: duplicates the object multiple times along an axis +*/ + +static void initData(ModifierData *md) +{ + ArrayModifierData *amd = (ArrayModifierData*) md; + + /* default to 2 duplicates distributed along the x-axis by an + offset of 1 object-width + */ + amd->start_cap = amd->end_cap = amd->curve_ob = amd->offset_ob = NULL; + amd->count = 2; + amd->offset[0] = amd->offset[1] = amd->offset[2] = 0; + amd->scale[0] = 1; + amd->scale[1] = amd->scale[2] = 0; + amd->length = 0; + amd->merge_dist = 0.01; + amd->fit_type = MOD_ARR_FIXEDCOUNT; + amd->offset_type = MOD_ARR_OFF_RELATIVE; + amd->flags = 0; +} + +static void copyData(ModifierData *md, ModifierData *target) +{ + ArrayModifierData *amd = (ArrayModifierData*) md; + ArrayModifierData *tamd = (ArrayModifierData*) target; + + tamd->start_cap = amd->start_cap; + tamd->end_cap = amd->end_cap; + tamd->curve_ob = amd->curve_ob; + tamd->offset_ob = amd->offset_ob; + tamd->count = amd->count; + VECCOPY(tamd->offset, amd->offset); + VECCOPY(tamd->scale, amd->scale); + tamd->length = amd->length; + tamd->merge_dist = amd->merge_dist; + tamd->fit_type = amd->fit_type; + tamd->offset_type = amd->offset_type; + tamd->flags = amd->flags; +} + +static void foreachObjectLink( + ModifierData *md, Object *ob, + void (*walk)(void *userData, Object *ob, Object **obpoin), + void *userData) +{ + ArrayModifierData *amd = (ArrayModifierData*) md; + + walk(userData, ob, &amd->start_cap); + walk(userData, ob, &amd->end_cap); + walk(userData, ob, &amd->curve_ob); + walk(userData, ob, &amd->offset_ob); +} + +static void updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene, + Object *ob, DagNode *obNode) +{ + ArrayModifierData *amd = (ArrayModifierData*) md; + + if (amd->start_cap) { + DagNode *curNode = dag_get_node(forest, amd->start_cap); + + dag_add_relation(forest, curNode, obNode, + DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier"); + } + if (amd->end_cap) { + DagNode *curNode = dag_get_node(forest, amd->end_cap); + + dag_add_relation(forest, curNode, obNode, + DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier"); + } + if (amd->curve_ob) { + DagNode *curNode = dag_get_node(forest, amd->curve_ob); + + dag_add_relation(forest, curNode, obNode, + DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier"); + } + if (amd->offset_ob) { + DagNode *curNode = dag_get_node(forest, amd->offset_ob); + + dag_add_relation(forest, curNode, obNode, + DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier"); + } +} + +static float vertarray_size(MVert *mvert, int numVerts, int axis) +{ + int i; + float min_co, max_co; + + /* if there are no vertices, width is 0 */ + if(numVerts == 0) return 0; + + /* find the minimum and maximum coordinates on the desired axis */ + min_co = max_co = mvert->co[axis]; + ++mvert; + for(i = 1; i < numVerts; ++i, ++mvert) { + if(mvert->co[axis] < min_co) min_co = mvert->co[axis]; + if(mvert->co[axis] > max_co) max_co = mvert->co[axis]; + } + + return max_co - min_co; +} + +typedef struct IndexMapEntry { + /* the new vert index that this old vert index maps to */ + int new; + /* -1 if this vert isn't merged, otherwise the old vert index it + * should be replaced with + */ + int merge; + /* 1 if this vert's first copy is merged with the last copy of its + * merge target, otherwise 0 + */ + short merge_final; +} IndexMapEntry; + +/* indexMap - an array of IndexMap entries + * oldIndex - the old index to map + * copyNum - the copy number to map to (original = 0, first copy = 1, etc.) + */ +static int calc_mapping(IndexMapEntry *indexMap, int oldIndex, int copyNum) +{ + if(indexMap[oldIndex].merge < 0) { + /* vert wasn't merged, so use copy of this vert */ + return indexMap[oldIndex].new + copyNum; + } else if(indexMap[oldIndex].merge == oldIndex) { + /* vert was merged with itself */ + return indexMap[oldIndex].new; + } else { + /* vert was merged with another vert */ + /* follow the chain of merges to the end, or until we've passed + * a number of vertices equal to the copy number + */ + if(copyNum <= 0) + return indexMap[oldIndex].new; + else + return calc_mapping(indexMap, indexMap[oldIndex].merge, + copyNum - 1); + } +} + +static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, + Scene *scene, Object *ob, DerivedMesh *dm, + int initFlags) +{ + int i, j; + /* offset matrix */ + float offset[4][4]; + float final_offset[4][4]; + float tmp_mat[4][4]; + float length = amd->length; + int count = amd->count; + int numVerts, numEdges, numFaces; + int maxVerts, maxEdges, maxFaces; + int finalVerts, finalEdges, finalFaces; + DerivedMesh *result, *start_cap = NULL, *end_cap = NULL; + MVert *mvert, *src_mvert; + MEdge *medge; + MFace *mface; + + IndexMapEntry *indexMap; + + EdgeHash *edges; + + /* need to avoid infinite recursion here */ + if(amd->start_cap && amd->start_cap != ob) + start_cap = amd->start_cap->derivedFinal; + if(amd->end_cap && amd->end_cap != ob) + end_cap = amd->end_cap->derivedFinal; + + unit_m4(offset); + + indexMap = MEM_callocN(sizeof(*indexMap) * dm->getNumVerts(dm), + "indexmap"); + + src_mvert = dm->getVertArray(dm); + + maxVerts = dm->getNumVerts(dm); + + if(amd->offset_type & MOD_ARR_OFF_CONST) + add_v3_v3v3(offset[3], offset[3], amd->offset); + if(amd->offset_type & MOD_ARR_OFF_RELATIVE) { + for(j = 0; j < 3; j++) + offset[3][j] += amd->scale[j] * vertarray_size(src_mvert, + maxVerts, j); + } + + if((amd->offset_type & MOD_ARR_OFF_OBJ) && (amd->offset_ob)) { + float obinv[4][4]; + float result_mat[4][4]; + + if(ob) + invert_m4_m4(obinv, ob->obmat); + else + unit_m4(obinv); + + mul_serie_m4(result_mat, offset, + obinv, amd->offset_ob->obmat, + NULL, NULL, NULL, NULL, NULL); + copy_m4_m4(offset, result_mat); + } + + if(amd->fit_type == MOD_ARR_FITCURVE && amd->curve_ob) { + Curve *cu = amd->curve_ob->data; + if(cu) { + float tmp_mat[3][3]; + float scale; + + object_to_mat3(amd->curve_ob, tmp_mat); + scale = mat3_to_scale(tmp_mat); + + if(!cu->path) { + cu->flag |= CU_PATH; // needed for path & bevlist + makeDispListCurveTypes(scene, amd->curve_ob, 0); + } + if(cu->path) + length = scale*cu->path->totdist; + } + } + + /* calculate the maximum number of copies which will fit within the + prescribed length */ + if(amd->fit_type == MOD_ARR_FITLENGTH + || amd->fit_type == MOD_ARR_FITCURVE) { + float dist = sqrt(dot_v3v3(offset[3], offset[3])); + + if(dist > 1e-6f) + /* this gives length = first copy start to last copy end + add a tiny offset for floating point rounding errors */ + count = (length + 1e-6f) / dist; + else + /* if the offset has no translation, just make one copy */ + count = 1; + } + + if(count < 1) + count = 1; + + /* allocate memory for count duplicates (including original) plus + * start and end caps + */ + finalVerts = dm->getNumVerts(dm) * count; + finalEdges = dm->getNumEdges(dm) * count; + finalFaces = dm->getNumFaces(dm) * count; + if(start_cap) { + finalVerts += start_cap->getNumVerts(start_cap); + finalEdges += start_cap->getNumEdges(start_cap); + finalFaces += start_cap->getNumFaces(start_cap); + } + if(end_cap) { + finalVerts += end_cap->getNumVerts(end_cap); + finalEdges += end_cap->getNumEdges(end_cap); + finalFaces += end_cap->getNumFaces(end_cap); + } + result = CDDM_from_template(dm, finalVerts, finalEdges, finalFaces); + + /* calculate the offset matrix of the final copy (for merging) */ + unit_m4(final_offset); + + for(j=0; j < count - 1; j++) { + mul_m4_m4m4(tmp_mat, final_offset, offset); + copy_m4_m4(final_offset, tmp_mat); + } + + numVerts = numEdges = numFaces = 0; + mvert = CDDM_get_verts(result); + + for (i = 0; i < maxVerts; i++) { + indexMap[i].merge = -1; /* default to no merge */ + indexMap[i].merge_final = 0; /* default to no merge */ + } + + for (i = 0; i < maxVerts; i++) { + MVert *inMV; + MVert *mv = &mvert[numVerts]; + MVert *mv2; + float co[3]; + + inMV = &src_mvert[i]; + + DM_copy_vert_data(dm, result, i, numVerts, 1); + *mv = *inMV; + numVerts++; + + indexMap[i].new = numVerts - 1; + + VECCOPY(co, mv->co); + + /* Attempts to merge verts from one duplicate with verts from the + * next duplicate which are closer than amd->merge_dist. + * Only the first such vert pair is merged. + * If verts are merged in the first duplicate pair, they are merged + * in all pairs. + */ + if((count > 1) && (amd->flags & MOD_ARR_MERGE)) { + float tmp_co[3]; + VECCOPY(tmp_co, mv->co); + mul_m4_v3(offset, tmp_co); + + for(j = 0; j < maxVerts; j++) { + /* if vertex already merged, don't use it */ + if( indexMap[j].merge != -1 ) continue; + + inMV = &src_mvert[j]; + /* if this vert is within merge limit, merge */ + if(compare_len_v3v3(tmp_co, inMV->co, amd->merge_dist)) { + indexMap[i].merge = j; + + /* test for merging with final copy of merge target */ + if(amd->flags & MOD_ARR_MERGEFINAL) { + VECCOPY(tmp_co, inMV->co); + inMV = &src_mvert[i]; + mul_m4_v3(final_offset, tmp_co); + if(compare_len_v3v3(tmp_co, inMV->co, amd->merge_dist)) + indexMap[i].merge_final = 1; + } + break; + } + } + } + + /* if no merging, generate copies of this vert */ + if(indexMap[i].merge < 0) { + for(j=0; j < count - 1; j++) { + mv2 = &mvert[numVerts]; + + DM_copy_vert_data(result, result, numVerts - 1, numVerts, 1); + *mv2 = *mv; + numVerts++; + + mul_m4_v3(offset, co); + VECCOPY(mv2->co, co); + } + } else if(indexMap[i].merge != i && indexMap[i].merge_final) { + /* if this vert is not merging with itself, and it is merging + * with the final copy of its merge target, remove the first copy + */ + numVerts--; + DM_free_vert_data(result, numVerts, 1); + } + } + + /* make a hashtable so we can avoid duplicate edges from merging */ + edges = BLI_edgehash_new(); + + maxEdges = dm->getNumEdges(dm); + medge = CDDM_get_edges(result); + for(i = 0; i < maxEdges; i++) { + MEdge inMED; + MEdge med; + MEdge *med2; + int vert1, vert2; + + dm->getEdge(dm, i, &inMED); + + med = inMED; + med.v1 = indexMap[inMED.v1].new; + med.v2 = indexMap[inMED.v2].new; + + /* if vertices are to be merged with the final copies of their + * merge targets, calculate that final copy + */ + if(indexMap[inMED.v1].merge_final) { + med.v1 = calc_mapping(indexMap, indexMap[inMED.v1].merge, + count - 1); + } + if(indexMap[inMED.v2].merge_final) { + med.v2 = calc_mapping(indexMap, indexMap[inMED.v2].merge, + count - 1); + } + + if(med.v1 == med.v2) continue; + + if (initFlags) { + med.flag |= ME_EDGEDRAW | ME_EDGERENDER; + } + + if(!BLI_edgehash_haskey(edges, med.v1, med.v2)) { + DM_copy_edge_data(dm, result, i, numEdges, 1); + medge[numEdges] = med; + numEdges++; + + BLI_edgehash_insert(edges, med.v1, med.v2, NULL); + } + + for(j = 1; j < count; j++) + { + vert1 = calc_mapping(indexMap, inMED.v1, j); + vert2 = calc_mapping(indexMap, inMED.v2, j); + /* avoid duplicate edges */ + if(!BLI_edgehash_haskey(edges, vert1, vert2)) { + med2 = &medge[numEdges]; + + DM_copy_edge_data(dm, result, i, numEdges, 1); + *med2 = med; + numEdges++; + + med2->v1 = vert1; + med2->v2 = vert2; + + BLI_edgehash_insert(edges, med2->v1, med2->v2, NULL); + } + } + } + + maxFaces = dm->getNumFaces(dm); + mface = CDDM_get_faces(result); + for (i=0; i < maxFaces; i++) { + MFace inMF; + MFace *mf = &mface[numFaces]; + + dm->getFace(dm, i, &inMF); + + DM_copy_face_data(dm, result, i, numFaces, 1); + *mf = inMF; + + mf->v1 = indexMap[inMF.v1].new; + mf->v2 = indexMap[inMF.v2].new; + mf->v3 = indexMap[inMF.v3].new; + if(inMF.v4) + mf->v4 = indexMap[inMF.v4].new; + + /* if vertices are to be merged with the final copies of their + * merge targets, calculate that final copy + */ + if(indexMap[inMF.v1].merge_final) + mf->v1 = calc_mapping(indexMap, indexMap[inMF.v1].merge, count-1); + if(indexMap[inMF.v2].merge_final) + mf->v2 = calc_mapping(indexMap, indexMap[inMF.v2].merge, count-1); + if(indexMap[inMF.v3].merge_final) + mf->v3 = calc_mapping(indexMap, indexMap[inMF.v3].merge, count-1); + if(inMF.v4 && indexMap[inMF.v4].merge_final) + mf->v4 = calc_mapping(indexMap, indexMap[inMF.v4].merge, count-1); + + if(test_index_face(mf, &result->faceData, numFaces, inMF.v4?4:3) < 3) + continue; + + numFaces++; + + /* if the face has fewer than 3 vertices, don't create it */ + if(mf->v3 == 0 || (mf->v1 && (mf->v1 == mf->v3 || mf->v1 == mf->v4))) { + numFaces--; + DM_free_face_data(result, numFaces, 1); + } + + for(j = 1; j < count; j++) + { + MFace *mf2 = &mface[numFaces]; + + DM_copy_face_data(dm, result, i, numFaces, 1); + *mf2 = *mf; + + mf2->v1 = calc_mapping(indexMap, inMF.v1, j); + mf2->v2 = calc_mapping(indexMap, inMF.v2, j); + mf2->v3 = calc_mapping(indexMap, inMF.v3, j); + if (inMF.v4) + mf2->v4 = calc_mapping(indexMap, inMF.v4, j); + + test_index_face(mf2, &result->faceData, numFaces, inMF.v4?4:3); + numFaces++; + + /* if the face has fewer than 3 vertices, don't create it */ + if(mf2->v3 == 0 || (mf2->v1 && (mf2->v1 == mf2->v3 || mf2->v1 == + mf2->v4))) { + numFaces--; + DM_free_face_data(result, numFaces, 1); + } + } + } + + /* add start and end caps */ + if(start_cap) { + float startoffset[4][4]; + MVert *cap_mvert; + MEdge *cap_medge; + MFace *cap_mface; + int *origindex; + int *vert_map; + int capVerts, capEdges, capFaces; + + capVerts = start_cap->getNumVerts(start_cap); + capEdges = start_cap->getNumEdges(start_cap); + capFaces = start_cap->getNumFaces(start_cap); + cap_mvert = start_cap->getVertArray(start_cap); + cap_medge = start_cap->getEdgeArray(start_cap); + cap_mface = start_cap->getFaceArray(start_cap); + + invert_m4_m4(startoffset, offset); + + vert_map = MEM_callocN(sizeof(*vert_map) * capVerts, + "arrayModifier_doArray vert_map"); + + origindex = result->getVertDataArray(result, CD_ORIGINDEX); + for(i = 0; i < capVerts; i++) { + MVert *mv = &cap_mvert[i]; + short merged = 0; + + if(amd->flags & MOD_ARR_MERGE) { + float tmp_co[3]; + MVert *in_mv; + int j; + + VECCOPY(tmp_co, mv->co); + mul_m4_v3(startoffset, tmp_co); + + for(j = 0; j < maxVerts; j++) { + in_mv = &src_mvert[j]; + /* if this vert is within merge limit, merge */ + if(compare_len_v3v3(tmp_co, in_mv->co, amd->merge_dist)) { + vert_map[i] = calc_mapping(indexMap, j, 0); + merged = 1; + break; + } + } + } + + if(!merged) { + DM_copy_vert_data(start_cap, result, i, numVerts, 1); + mvert[numVerts] = *mv; + mul_m4_v3(startoffset, mvert[numVerts].co); + origindex[numVerts] = ORIGINDEX_NONE; + + vert_map[i] = numVerts; + + numVerts++; + } + } + origindex = result->getEdgeDataArray(result, CD_ORIGINDEX); + for(i = 0; i < capEdges; i++) { + int v1, v2; + + v1 = vert_map[cap_medge[i].v1]; + v2 = vert_map[cap_medge[i].v2]; + + if(!BLI_edgehash_haskey(edges, v1, v2)) { + DM_copy_edge_data(start_cap, result, i, numEdges, 1); + medge[numEdges] = cap_medge[i]; + medge[numEdges].v1 = v1; + medge[numEdges].v2 = v2; + origindex[numEdges] = ORIGINDEX_NONE; + + numEdges++; + } + } + origindex = result->getFaceDataArray(result, CD_ORIGINDEX); + for(i = 0; i < capFaces; i++) { + DM_copy_face_data(start_cap, result, i, numFaces, 1); + mface[numFaces] = cap_mface[i]; + mface[numFaces].v1 = vert_map[mface[numFaces].v1]; + mface[numFaces].v2 = vert_map[mface[numFaces].v2]; + mface[numFaces].v3 = vert_map[mface[numFaces].v3]; + if(mface[numFaces].v4) { + mface[numFaces].v4 = vert_map[mface[numFaces].v4]; + + test_index_face(&mface[numFaces], &result->faceData, + numFaces, 4); + } + else + { + test_index_face(&mface[numFaces], &result->faceData, + numFaces, 3); + } + + origindex[numFaces] = ORIGINDEX_NONE; + + numFaces++; + } + + MEM_freeN(vert_map); + start_cap->release(start_cap); + } + + if(end_cap) { + float endoffset[4][4]; + MVert *cap_mvert; + MEdge *cap_medge; + MFace *cap_mface; + int *origindex; + int *vert_map; + int capVerts, capEdges, capFaces; + + capVerts = end_cap->getNumVerts(end_cap); + capEdges = end_cap->getNumEdges(end_cap); + capFaces = end_cap->getNumFaces(end_cap); + cap_mvert = end_cap->getVertArray(end_cap); + cap_medge = end_cap->getEdgeArray(end_cap); + cap_mface = end_cap->getFaceArray(end_cap); + + mul_m4_m4m4(endoffset, final_offset, offset); + + vert_map = MEM_callocN(sizeof(*vert_map) * capVerts, + "arrayModifier_doArray vert_map"); + + origindex = result->getVertDataArray(result, CD_ORIGINDEX); + for(i = 0; i < capVerts; i++) { + MVert *mv = &cap_mvert[i]; + short merged = 0; + + if(amd->flags & MOD_ARR_MERGE) { + float tmp_co[3]; + MVert *in_mv; + int j; + + VECCOPY(tmp_co, mv->co); + mul_m4_v3(offset, tmp_co); + + for(j = 0; j < maxVerts; j++) { + in_mv = &src_mvert[j]; + /* if this vert is within merge limit, merge */ + if(compare_len_v3v3(tmp_co, in_mv->co, amd->merge_dist)) { + vert_map[i] = calc_mapping(indexMap, j, count - 1); + merged = 1; + break; + } + } + } + + if(!merged) { + DM_copy_vert_data(end_cap, result, i, numVerts, 1); + mvert[numVerts] = *mv; + mul_m4_v3(endoffset, mvert[numVerts].co); + origindex[numVerts] = ORIGINDEX_NONE; + + vert_map[i] = numVerts; + + numVerts++; + } + } + origindex = result->getEdgeDataArray(result, CD_ORIGINDEX); + for(i = 0; i < capEdges; i++) { + int v1, v2; + + v1 = vert_map[cap_medge[i].v1]; + v2 = vert_map[cap_medge[i].v2]; + + if(!BLI_edgehash_haskey(edges, v1, v2)) { + DM_copy_edge_data(end_cap, result, i, numEdges, 1); + medge[numEdges] = cap_medge[i]; + medge[numEdges].v1 = v1; + medge[numEdges].v2 = v2; + origindex[numEdges] = ORIGINDEX_NONE; + + numEdges++; + } + } + origindex = result->getFaceDataArray(result, CD_ORIGINDEX); + for(i = 0; i < capFaces; i++) { + DM_copy_face_data(end_cap, result, i, numFaces, 1); + mface[numFaces] = cap_mface[i]; + mface[numFaces].v1 = vert_map[mface[numFaces].v1]; + mface[numFaces].v2 = vert_map[mface[numFaces].v2]; + mface[numFaces].v3 = vert_map[mface[numFaces].v3]; + if(mface[numFaces].v4) { + mface[numFaces].v4 = vert_map[mface[numFaces].v4]; + + test_index_face(&mface[numFaces], &result->faceData, + numFaces, 4); + } + else + { + test_index_face(&mface[numFaces], &result->faceData, + numFaces, 3); + } + origindex[numFaces] = ORIGINDEX_NONE; + + numFaces++; + } + + MEM_freeN(vert_map); + end_cap->release(end_cap); + } + + BLI_edgehash_free(edges, NULL); + MEM_freeN(indexMap); + + CDDM_lower_num_verts(result, numVerts); + CDDM_lower_num_edges(result, numEdges); + CDDM_lower_num_faces(result, numFaces); + + return result; +} + +static DerivedMesh *applyModifier( + ModifierData *md, Object *ob, DerivedMesh *derivedData, + int useRenderParams, int isFinalCalc) +{ + DerivedMesh *result; + ArrayModifierData *amd = (ArrayModifierData*) md; + + result = arrayModifier_doArray(amd, md->scene, ob, derivedData, 0); + + if(result != derivedData) + CDDM_calc_normals(result); + + return result; +} + +static DerivedMesh *applyModifierEM( + ModifierData *md, Object *ob, EditMesh *editData, + DerivedMesh *derivedData) +{ + return applyModifier(md, ob, derivedData, 0, 1); +} + + +ModifierTypeInfo modifierType_Array = { + /* name */ "Array", + /* structName */ "ArrayModifierData", + /* structSize */ sizeof(ArrayModifierData), + /* type */ eModifierTypeType_Constructive, + /* flags */ eModifierTypeFlag_AcceptsMesh + | eModifierTypeFlag_SupportsMapping + | eModifierTypeFlag_SupportsEditmode + | eModifierTypeFlag_EnableInEditmode + | eModifierTypeFlag_AcceptsCVs, + + /* copyData */ copyData, + /* deformVerts */ 0, + /* deformVertsEM */ 0, + /* deformMatricesEM */ 0, + /* applyModifier */ applyModifier, + /* applyModifierEM */ applyModifierEM, + /* initData */ initData, + /* requiredDataMask */ 0, + /* freeData */ 0, + /* isDisabled */ 0, + /* updateDepgraph */ updateDepgraph, + /* dependsOnTime */ 0, + /* foreachObjectLink */ foreachObjectLink, + /* foreachIDLink */ 0, +}; |