90 bool need_transform_dependency =
false;
107 need_transform_dependency =
true;
110 if (need_transform_dependency) {
117 return v[0] +
v[1] +
v[2];
148 for (i = i_begin; i < i_end; i++, sv++,
mv++) {
164 const int target_start,
165 const int target_num_verts,
166 const int source_start,
167 const int source_num_verts,
171 int i_source, i_target, i_target_low_bound, target_end, source_end;
173 SortVertsElem *sve_source, *sve_target, *sve_target_low_bound;
174 bool target_scan_completed;
176 target_end = target_start + target_num_verts;
177 source_end = source_start + source_num_verts;
184 svert_from_mvert(sorted_verts_target, mverts + target_start, target_start, target_end);
187 svert_from_mvert(sorted_verts_source, mverts + source_start, source_start, source_end);
193 sve_target_low_bound = sorted_verts_target;
194 i_target_low_bound = 0;
195 target_scan_completed =
false;
199 for (i_source = 0, sve_source = sorted_verts_source; i_source < source_num_verts;
200 i_source++, sve_source++) {
201 int best_target_vertex = -1;
202 float best_dist_sq = dist * dist;
203 float sve_source_sumco;
206 if (doubles_map[sve_source->
vertex_num] != -1) {
211 if (target_scan_completed) {
216 sve_source_sumco =
sum_v3(sve_source->
co);
220 while ((i_target_low_bound < target_num_verts) &&
221 (sve_target_low_bound->
sum_co < sve_source_sumco - dist3)) {
222 i_target_low_bound++;
223 sve_target_low_bound++;
226 if (i_target_low_bound >= target_num_verts) {
228 target_scan_completed =
true;
233 i_target = i_target_low_bound;
234 sve_target = sve_target_low_bound;
239 while ((i_target < target_num_verts) && (sve_target->
sum_co <= sve_source_sumco + dist3)) {
245 best_dist_sq = dist_sq;
253 while (best_target_vertex != -1 &&
254 !
ELEM(doubles_map[best_target_vertex], -1, best_target_vertex)) {
256 mverts[doubles_map[best_target_vertex]].
co,
258 best_target_vertex = doubles_map[best_target_vertex];
261 best_target_vertex = -1;
269 doubles_map[sve_source->
vertex_num] = best_target_vertex;
278 const float cap_offset[4][4],
279 uint cap_verts_index,
280 uint cap_edges_index,
289 const bool recalc_normals_later)
303 mv =
result->mvert + cap_verts_index;
305 for (i = 0; i < cap_nverts; i++,
mv++) {
308 mv->flag =
mv->bweight = 0;
311 if (!recalc_normals_later) {
323 &
result->dvert[cap_verts_index], cap_nverts, remap, remap_len);
327 me =
result->medge + cap_edges_index;
328 for (i = 0; i < cap_nedges; i++, me++) {
329 me->
v1 += cap_verts_index;
330 me->
v2 += cap_verts_index;
334 mp =
result->mpoly + cap_polys_index;
335 for (i = 0; i < cap_npolys; i++, mp++) {
340 ml =
result->mloop + cap_loops_index;
341 for (i = 0; i < cap_nloops; i++, ml++) {
342 ml->
v += cap_verts_index;
343 ml->
e += cap_edges_index;
372 const MVert *src_mvert;
373 MVert *
mv, *mv_prev, *result_dm_verts;
383 bool offset_has_scale;
384 float current_offset[4][4];
385 float final_offset[4][4];
386 int *full_doubles_map =
NULL;
393 int start_cap_nverts = 0, start_cap_nedges = 0, start_cap_npolys = 0, start_cap_nloops = 0;
394 int end_cap_nverts = 0, end_cap_nedges = 0, end_cap_npolys = 0, end_cap_nloops = 0;
395 int result_nverts = 0, result_nedges = 0, result_npolys = 0, result_nloops = 0;
396 int chunk_nverts, chunk_nedges, chunk_nloops, chunk_npolys;
397 int first_chunk_start, first_chunk_nverts, last_chunk_start, last_chunk_nverts;
401 int *vgroup_start_cap_remap =
NULL;
402 int vgroup_start_cap_remap_len = 0;
403 int *vgroup_end_cap_remap =
NULL;
404 int vgroup_end_cap_remap_len = 0;
414 if (start_cap_ob && start_cap_ob != ctx->
object) {
416 start_cap_ob, ctx->
object, &vgroup_start_cap_remap_len);
419 if (start_cap_mesh) {
420 start_cap_nverts = start_cap_mesh->
totvert;
421 start_cap_nedges = start_cap_mesh->
totedge;
422 start_cap_nloops = start_cap_mesh->
totloop;
423 start_cap_npolys = start_cap_mesh->
totpoly;
427 if (end_cap_ob && end_cap_ob != ctx->
object) {
429 end_cap_ob, ctx->
object, &vgroup_end_cap_remap_len);
433 end_cap_nverts = end_cap_mesh->totvert;
434 end_cap_nedges = end_cap_mesh->totedge;
435 end_cap_nloops = end_cap_mesh->totloop;
436 end_cap_npolys = end_cap_mesh->totpoly;
454 for (src_mv = src_mvert, j = chunk_nverts; j--; src_mv++) {
465 float result_mat[4][4];
492 const size_t max_num_vertices = 1 << 26;
497 const float float_epsilon = 1e-6f;
498 bool offset_is_too_small =
false;
499 float dist =
len_v3(offset[3]);
501 if (dist > float_epsilon) {
509 if (((
size_t)
count * (
size_t)chunk_nverts + (
size_t)start_cap_nverts +
510 (
size_t)end_cap_nverts) > max_num_vertices) {
512 offset_is_too_small =
true;
518 offset_is_too_small =
true;
521 if (offset_is_too_small) {
525 "The offset is too small, we cannot generate the amount of geometry it would require");
531 else if (((
size_t)
count * (
size_t)chunk_nverts + (
size_t)start_cap_nverts +
532 (
size_t)end_cap_nverts) > max_num_vertices) {
536 "The amount of copies is too high, we cannot generate the amount of "
537 "geometry it would require");
545 result_nverts = chunk_nverts *
count + start_cap_nverts + end_cap_nverts;
546 result_nedges = chunk_nedges *
count + start_cap_nedges + end_cap_nedges;
547 result_nloops = chunk_nloops *
count + start_cap_nloops + end_cap_nloops;
548 result_npolys = chunk_npolys *
count + start_cap_npolys + end_cap_npolys;
552 mesh, result_nverts, result_nedges, 0, result_nloops, result_npolys);
553 result_dm_verts =
result->mvert;
557 full_doubles_map =
MEM_malloc_arrayN(result_nverts,
sizeof(
int),
"mod array doubles map");
558 copy_vn_i(full_doubles_map, result_nverts, -1);
581 first_chunk_start = 0;
582 first_chunk_nverts = chunk_nverts;
592 mv_prev = result_dm_verts;
593 mv = mv_prev +
c * chunk_nverts;
596 mul_m4_m4m4(current_offset, current_offset, offset);
599 for (i = 0; i < chunk_nverts; i++,
mv++, mv_prev++) {
603 if (!use_recalc_normals) {
613 me =
result->medge +
c * chunk_nedges;
614 for (i = 0; i < chunk_nedges; i++, me++) {
615 me->
v1 +=
c * chunk_nverts;
616 me->
v2 +=
c * chunk_nverts;
619 mp =
result->mpoly +
c * chunk_npolys;
620 for (i = 0; i < chunk_npolys; i++, mp++) {
625 ml =
result->mloop +
c * chunk_nloops;
626 for (i = 0; i < chunk_nloops; i++, ml++) {
627 ml->
v +=
c * chunk_nverts;
628 ml->
e +=
c * chunk_nedges;
632 if (use_merge && (
c >= 1)) {
633 if (!offset_has_scale && (
c >= 2)) {
637 int this_chunk_index =
c * chunk_nverts;
638 int prev_chunk_index = (
c - 1) * chunk_nverts;
639 for (k = 0; k < chunk_nverts; k++, this_chunk_index++, prev_chunk_index++) {
640 int target = full_doubles_map[prev_chunk_index];
642 target += chunk_nverts;
643 while (target != -1 && !
ELEM(full_doubles_map[target], -1, target)) {
647 result_dm_verts[full_doubles_map[target]].co,
649 target = full_doubles_map[target];
656 full_doubles_map[this_chunk_index] = target;
662 (
c - 1) * chunk_nverts,
674 for (i = 0; i < totuv; i++) {
676 dmloopuv += chunk_nloops;
678 const float uv_offset[2] = {
682 int l_index = chunk_nloops;
683 for (; l_index-- != 0; dmloopuv++) {
684 dmloopuv->
uv[0] += uv_offset[0];
685 dmloopuv->
uv[1] += uv_offset[1];
691 last_chunk_start = (
count - 1) * chunk_nverts;
692 last_chunk_nverts = chunk_nverts;
708 if (start_cap_mesh) {
709 float start_offset[4][4];
710 int start_cap_start = result_nverts - start_cap_nverts - end_cap_nverts;
715 result_nverts - start_cap_nverts - end_cap_nverts,
716 result_nedges - start_cap_nedges - end_cap_nedges,
717 result_nloops - start_cap_nloops - end_cap_nloops,
718 result_npolys - start_cap_npolys - end_cap_npolys,
723 vgroup_start_cap_remap,
724 vgroup_start_cap_remap_len,
739 float end_offset[4][4];
740 int end_cap_start = result_nverts - end_cap_nverts;
745 result_nverts - end_cap_nverts,
746 result_nedges - end_cap_nedges,
747 result_nloops - end_cap_nloops,
748 result_npolys - end_cap_npolys,
753 vgroup_end_cap_remap,
754 vgroup_end_cap_remap_len,
772 for (i = 0; i < result_nverts; i++) {
773 int new_i = full_doubles_map[i];
778 while (!
ELEM(full_doubles_map[new_i], -1, new_i)) {
779 new_i = full_doubles_map[new_i];
782 full_doubles_map[i] = -1;
785 full_doubles_map[i] = new_i;
790 if (tot_doubles > 0) {
800 if (use_recalc_normals) {
804 if (vgroup_start_cap_remap) {
807 if (vgroup_end_cap_remap) {
822 bool UNUSED(useRenderParams))
962 uiItemR(
col,
ptr,
"use_merge_vertices_cap", 0,
IFACE_(
"First and Last Copies"), ICON_NONE);
1018 "ArrayModifierData",
typedef float(TangentPoint)[2]
float BKE_anim_path_get_length(const struct CurveCache *curve_cache)
int CustomData_number_of_layers(const struct CustomData *data, int type)
bool CustomData_has_layer(const struct CustomData *data, int type)
void * CustomData_get_layer_n(const struct CustomData *data, int type, int n)
void * CustomData_get_layer(const struct CustomData *data, int type)
void CustomData_copy_data(const struct CustomData *source, struct CustomData *dest, int source_index, int dest_index, int count)
display list (or rather multi purpose list) stuff.
struct Mesh * BKE_mesh_new_nomain_from_template(const struct Mesh *me_src, int verts_len, int edges_len, int tessface_len, int loops_len, int polys_len)
@ MESH_MERGE_VERTS_DUMP_IF_EQUAL
struct Mesh * BKE_mesh_merge_verts(struct Mesh *mesh, const int *vtargetmap, const int tot_vtargetmap, const int merge_mode)
void(* IDWalkFunc)(void *userData, struct Object *ob, struct ID **idpoin, int cb_flag)
@ eModifierTypeFlag_AcceptsCVs
@ eModifierTypeFlag_SupportsMapping
@ eModifierTypeFlag_EnableInEditmode
@ eModifierTypeFlag_SupportsEditmode
@ eModifierTypeFlag_AcceptsMesh
void BKE_modifier_copydata_generic(const struct ModifierData *md, struct ModifierData *md_dst, const int flag)
@ eModifierTypeType_Constructive
void BKE_modifier_set_error(const struct Object *ob, struct ModifierData *md, const char *format,...) ATTR_PRINTF_FORMAT(3
struct Mesh * BKE_modifier_get_evaluated_mesh_from_evaluated_object(struct Object *ob_eval, const bool get_cage_mesh)
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void unit_m4(float m[4][4])
void mul_mat3_m4_v3(const float M[4][4], float r[3])
bool invert_m4_m4(float R[4][4], const float A[4][4])
void mul_m4_v3(const float M[4][4], float r[3])
#define mul_m4_series(...)
void copy_m4_m4(float m1[4][4], const float m2[4][4])
float mat4_to_scale(const float M[4][4])
void mat4_to_size(float size[3], const float M[4][4])
MINLINE bool compare_len_v3v3(const float a[3], const float b[3], const float limit) ATTR_WARN_UNUSED_RESULT
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
void copy_vn_i(int *array_tar, const int size, const int val)
MINLINE void normal_float_to_short_v3(short r[3], const float n[3])
MINLINE float normalize_v3(float r[3])
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void normal_short_to_float_v3(float r[3], const short n[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE bool is_one_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
MINLINE bool is_zero_v2(const float a[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
#define INIT_MINMAX(min, max)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
@ DAG_EVAL_NEED_CURVE_PATH
void DEG_add_object_relation(struct DepsNodeHandle *node_handle, struct Object *object, eDepsObjectComponentType component, const char *description)
void DEG_add_modifier_to_transform_relation(struct DepsNodeHandle *node_handle, const char *description)
void DEG_add_special_eval_flag(struct DepsNodeHandle *handle, struct ID *id, uint32_t flag)
#define DNA_struct_default_get(struct_name)
struct ArrayModifierData ArrayModifierData
Object is a sort of wrapper for general info.
@ UI_PANEL_DATA_EXPAND_ROOT
@ UI_SUBPANEL_DATA_EXPAND_1
Read Guarded memory(de)allocation.
static void uv_panel_draw(const bContext *UNUSED(C), Panel *panel)
static void constant_offset_draw(const bContext *UNUSED(C), Panel *panel)
static Mesh * modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
static void svert_from_mvert(SortVertsElem *sv, const MVert *mv, const int i_begin, const int i_end)
static void symmetry_panel_header_draw(const bContext *UNUSED(C), Panel *panel)
static void relative_offset_draw(const bContext *UNUSED(C), Panel *panel)
static int svert_sum_cmp(const void *e1, const void *e2)
static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
static void relative_offset_header_draw(const bContext *UNUSED(C), Panel *panel)
static bool isDisabled(const struct Scene *UNUSED(scene), ModifierData *md, bool UNUSED(useRenderParams))
ModifierTypeInfo modifierType_Array
static void constant_offset_header_draw(const bContext *UNUSED(C), Panel *panel)
static void object_offset_draw(const bContext *UNUSED(C), Panel *panel)
static void mesh_merge_transform(Mesh *result, Mesh *cap_mesh, const float cap_offset[4][4], uint cap_verts_index, uint cap_edges_index, int cap_loops_index, int cap_polys_index, int cap_nverts, int cap_nedges, int cap_nloops, int cap_npolys, int *remap, int remap_len, const bool recalc_normals_later)
static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
struct SortVertsElem SortVertsElem
static Mesh * arrayModifier_doArray(ArrayModifierData *amd, const ModifierEvalContext *ctx, Mesh *mesh)
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
BLI_INLINE float sum_v3(const float v[3])
static void initData(ModifierData *md)
static void panelRegister(ARegionType *region_type)
static void symmetry_panel_draw(const bContext *UNUSED(C), Panel *panel)
static void caps_panel_draw(const bContext *UNUSED(C), Panel *panel)
static void dm_mvert_map_doubles(int *doubles_map, const MVert *mverts, const int target_start, const int target_num_verts, const int source_start, const int source_num_verts, const float dist)
static void object_offset_header_draw(const bContext *UNUSED(C), Panel *panel)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
PanelType * modifier_subpanel_register(ARegionType *region_type, const char *name, const char *label, PanelDrawFn draw_header, PanelDrawFn draw, PanelType *parent)
StructRNA RNA_ArrayModifier
void uiLayoutSetActive(uiLayout *layout, bool active)
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE btScalar length(const btQuaternion &q)
Return the length of a quaternion.
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
void(* MEM_freeN)(void *vmemh)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
struct Object * start_cap
struct Object * offset_ob
const float * anim_path_accum_length
struct CustomData pdata ldata
struct DepsNodeHandle * node
struct CurveCache * curve_cache