41 #include "RNA_prototypes.h"
75 bool need_transform_dependency =
false;
92 need_transform_dependency =
true;
95 if (need_transform_dependency) {
102 return v[0] +
v[1] +
v[2];
133 for (i = i_begin; i < i_end; i++, sv++,
mv++) {
149 const int target_start,
150 const int target_verts_num,
151 const int source_start,
152 const int source_verts_num,
156 int i_source, i_target, i_target_low_bound, target_end, source_end;
158 SortVertsElem *sve_source, *sve_target, *sve_target_low_bound;
159 bool target_scan_completed;
161 target_end = target_start + target_verts_num;
162 source_end = source_start + source_verts_num;
169 svert_from_mvert(sorted_verts_target, mverts + target_start, target_start, target_end);
172 svert_from_mvert(sorted_verts_source, mverts + source_start, source_start, source_end);
178 sve_target_low_bound = sorted_verts_target;
179 i_target_low_bound = 0;
180 target_scan_completed =
false;
184 for (i_source = 0, sve_source = sorted_verts_source; i_source < source_verts_num;
185 i_source++, sve_source++) {
186 int best_target_vertex = -1;
187 float best_dist_sq = dist * dist;
188 float sve_source_sumco;
191 if (doubles_map[sve_source->
vertex_num] != -1) {
196 if (target_scan_completed) {
201 sve_source_sumco =
sum_v3(sve_source->
co);
205 while ((i_target_low_bound < target_verts_num) &&
206 (sve_target_low_bound->
sum_co < sve_source_sumco - dist3)) {
207 i_target_low_bound++;
208 sve_target_low_bound++;
211 if (i_target_low_bound >= target_verts_num) {
213 target_scan_completed =
true;
218 i_target = i_target_low_bound;
219 sve_target = sve_target_low_bound;
224 while ((i_target < target_verts_num) && (sve_target->
sum_co <= sve_source_sumco + dist3)) {
230 best_dist_sq = dist_sq;
238 while (best_target_vertex != -1 &&
239 !
ELEM(doubles_map[best_target_vertex], -1, best_target_vertex)) {
241 mverts[doubles_map[best_target_vertex]].
co,
243 best_target_vertex = doubles_map[best_target_vertex];
246 best_target_vertex = -1;
254 doubles_map[sve_source->
vertex_num] = best_target_vertex;
263 const float cap_offset[4][4],
264 uint cap_verts_index,
265 uint cap_edges_index,
274 const bool recalc_normals_later)
288 mv =
result->mvert + cap_verts_index;
290 for (i = 0; i < cap_nverts; i++,
mv++) {
293 mv->flag =
mv->bweight = 0;
297 if (!recalc_normals_later) {
299 for (i = 0; i < cap_nverts; i++) {
300 mul_mat3_m4_v3(cap_offset, dst_vert_normals[cap_verts_index + i]);
308 &
result->dvert[cap_verts_index], cap_nverts, remap, remap_len);
312 me =
result->medge + cap_edges_index;
313 for (i = 0; i < cap_nedges; i++, me++) {
314 me->
v1 += cap_verts_index;
315 me->
v2 += cap_verts_index;
319 mp =
result->mpoly + cap_polys_index;
320 for (i = 0; i < cap_npolys; i++, mp++) {
325 ml =
result->mloop + cap_loops_index;
326 for (i = 0; i < cap_nloops; i++, ml++) {
327 ml->
v += cap_verts_index;
328 ml->
e += cap_edges_index;
357 const MVert *src_mvert;
358 MVert *result_dm_verts;
368 bool offset_has_scale;
369 float current_offset[4][4];
370 float final_offset[4][4];
371 int *full_doubles_map =
NULL;
378 int start_cap_nverts = 0, start_cap_nedges = 0, start_cap_npolys = 0, start_cap_nloops = 0;
379 int end_cap_nverts = 0, end_cap_nedges = 0, end_cap_npolys = 0, end_cap_nloops = 0;
380 int result_nverts = 0, result_nedges = 0, result_npolys = 0, result_nloops = 0;
381 int chunk_nverts, chunk_nedges, chunk_nloops, chunk_npolys;
382 int first_chunk_start, first_chunk_nverts, last_chunk_start, last_chunk_nverts;
386 int *vgroup_start_cap_remap =
NULL;
387 int vgroup_start_cap_remap_len = 0;
388 int *vgroup_end_cap_remap =
NULL;
389 int vgroup_end_cap_remap_len = 0;
399 if (start_cap_ob && start_cap_ob != ctx->
object) {
402 start_cap_ob, ctx->
object, &vgroup_start_cap_remap_len);
406 if (start_cap_mesh) {
407 start_cap_nverts = start_cap_mesh->
totvert;
408 start_cap_nedges = start_cap_mesh->
totedge;
409 start_cap_nloops = start_cap_mesh->
totloop;
410 start_cap_npolys = start_cap_mesh->
totpoly;
414 if (end_cap_ob && end_cap_ob != ctx->
object) {
417 end_cap_ob, ctx->
object, &vgroup_end_cap_remap_len);
422 end_cap_nverts = end_cap_mesh->totvert;
423 end_cap_nedges = end_cap_mesh->totedge;
424 end_cap_nloops = end_cap_mesh->totloop;
425 end_cap_npolys = end_cap_mesh->totpoly;
443 for (src_mv = src_mvert, j = chunk_nverts; j--; src_mv++) {
454 float result_mat[4][4];
481 const size_t max_vertices_num = 1 << 26;
486 const float float_epsilon = 1e-6f;
487 bool offset_is_too_small =
false;
490 if (dist > float_epsilon) {
498 if (((
size_t)
count * (
size_t)chunk_nverts + (
size_t)start_cap_nverts +
499 (
size_t)end_cap_nverts) > max_vertices_num) {
501 offset_is_too_small =
true;
507 offset_is_too_small =
true;
510 if (offset_is_too_small) {
514 "The offset is too small, we cannot generate the amount of geometry it would require");
520 else if (((
size_t)
count * (
size_t)chunk_nverts + (
size_t)start_cap_nverts +
521 (
size_t)end_cap_nverts) > max_vertices_num) {
525 "The amount of copies is too high, we cannot generate the amount of "
526 "geometry it would require");
534 result_nverts = chunk_nverts *
count + start_cap_nverts + end_cap_nverts;
535 result_nedges = chunk_nedges *
count + start_cap_nedges + end_cap_nedges;
536 result_nloops = chunk_nloops *
count + start_cap_nloops + end_cap_nloops;
537 result_npolys = chunk_npolys *
count + start_cap_npolys + end_cap_npolys;
541 mesh, result_nverts, result_nedges, 0, result_nloops, result_npolys);
542 result_dm_verts =
result->mvert;
546 full_doubles_map =
MEM_malloc_arrayN(result_nverts,
sizeof(
int),
"mod array doubles map");
547 copy_vn_i(full_doubles_map, result_nverts, -1);
570 first_chunk_start = 0;
571 first_chunk_nverts = chunk_nverts;
574 const float(*src_vert_normals)[3] =
NULL;
576 if (!use_recalc_normals) {
589 const int vert_offset =
c * chunk_nverts;
595 for (i = 0; i < chunk_nverts; i++) {
596 const int i_dst = vert_offset + i;
597 mul_m4_v3(current_offset, result_dm_verts[i_dst].co);
600 if (!use_recalc_normals) {
601 copy_v3_v3(dst_vert_normals[i_dst], src_vert_normals[i]);
608 me =
result->medge +
c * chunk_nedges;
609 for (i = 0; i < chunk_nedges; i++, me++) {
610 me->
v1 +=
c * chunk_nverts;
611 me->
v2 +=
c * chunk_nverts;
614 mp =
result->mpoly +
c * chunk_npolys;
615 for (i = 0; i < chunk_npolys; i++, mp++) {
620 ml =
result->mloop +
c * chunk_nloops;
621 for (i = 0; i < chunk_nloops; i++, ml++) {
622 ml->
v +=
c * chunk_nverts;
623 ml->
e +=
c * chunk_nedges;
627 if (use_merge && (
c >= 1)) {
628 if (!offset_has_scale && (
c >= 2)) {
632 int this_chunk_index =
c * chunk_nverts;
633 int prev_chunk_index = (
c - 1) * chunk_nverts;
634 for (k = 0; k < chunk_nverts; k++, this_chunk_index++, prev_chunk_index++) {
635 int target = full_doubles_map[prev_chunk_index];
637 target += chunk_nverts;
638 while (target != -1 && !
ELEM(full_doubles_map[target], -1, target)) {
642 result_dm_verts[full_doubles_map[target]].co,
644 target = full_doubles_map[target];
651 full_doubles_map[this_chunk_index] = target;
657 (
c - 1) * chunk_nverts,
669 for (i = 0; i < totuv; i++) {
671 dmloopuv += chunk_nloops;
673 const float uv_offset[2] = {
677 int l_index = chunk_nloops;
678 for (; l_index-- != 0; dmloopuv++) {
679 dmloopuv->
uv[0] += uv_offset[0];
680 dmloopuv->
uv[1] += uv_offset[1];
686 last_chunk_start = (
count - 1) * chunk_nverts;
687 last_chunk_nverts = chunk_nverts;
703 if (start_cap_mesh) {
704 float start_offset[4][4];
705 int start_cap_start = result_nverts - start_cap_nverts - end_cap_nverts;
710 result_nverts - start_cap_nverts - end_cap_nverts,
711 result_nedges - start_cap_nedges - end_cap_nedges,
712 result_nloops - start_cap_nloops - end_cap_nloops,
713 result_npolys - start_cap_npolys - end_cap_npolys,
718 vgroup_start_cap_remap,
719 vgroup_start_cap_remap_len,
734 float end_offset[4][4];
735 int end_cap_start = result_nverts - end_cap_nverts;
740 result_nverts - end_cap_nverts,
741 result_nedges - end_cap_nedges,
742 result_nloops - end_cap_nloops,
743 result_npolys - end_cap_npolys,
748 vgroup_end_cap_remap,
749 vgroup_end_cap_remap_len,
767 for (i = 0; i < result_nverts; i++) {
768 int new_i = full_doubles_map[i];
773 while (!
ELEM(full_doubles_map[new_i], -1, new_i)) {
774 new_i = full_doubles_map[new_i];
777 full_doubles_map[i] = -1;
780 full_doubles_map[i] = new_i;
785 if (tot_doubles > 0) {
792 if (vgroup_start_cap_remap) {
795 if (vgroup_end_cap_remap) {
810 bool UNUSED(useRenderParams))
950 uiItemR(
col,
ptr,
"use_merge_vertices_cap", 0,
IFACE_(
"First and Last Copies"), ICON_NONE);
1006 "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.
float(* BKE_mesh_vertex_normals_for_write(struct Mesh *mesh))[3]
@ MESH_MERGE_VERTS_DUMP_IF_EQUAL
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)
const float(* BKE_mesh_vertex_normals_ensure(const struct Mesh *mesh))[3]
bool BKE_mesh_vertex_normals_are_dirty(const struct Mesh *mesh)
struct Mesh * BKE_mesh_merge_verts(struct Mesh *mesh, const int *vtargetmap, int tot_vtargetmap, int merge_mode)
void BKE_mesh_vertex_normals_clear_dirty(struct Mesh *mesh)
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, int flag)
struct Mesh * BKE_modifier_get_evaluated_mesh_from_evaluated_object(struct Object *ob_eval)
@ eModifierTypeType_Constructive
void BKE_modifier_set_error(const struct Object *ob, struct ModifierData *md, const char *format,...) ATTR_PRINTF_FORMAT(3
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])
void minmax_v3v3_v3(float min[3], float max[3], const float vec[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 copy_v3_v3(float r[3], const float a[3])
void copy_vn_i(int *array_tar, int size, int val)
MINLINE bool is_one_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
MINLINE bool is_zero_v2(const float a[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE bool compare_len_v3v3(const float a[3], const float b[3], float limit) ATTR_WARN_UNUSED_RESULT
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)
static void dm_mvert_map_doubles(int *doubles_map, const MVert *mverts, const int target_start, const int target_verts_num, const int source_start, const int source_verts_num, const float dist)
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 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)
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
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
void(* MEM_freeN)(void *vmemh)
T length(const vec_base< T, Size > &a)
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 DepsNodeHandle * node
struct CurveCache * curve_cache