Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/object_dupli.cc
| Show All 24 Lines | |||||
| #include <cstddef> | #include <cstddef> | ||||
| #include <cstdlib> | #include <cstdlib> | ||||
| #include "MEM_guardedalloc.h" | #include "MEM_guardedalloc.h" | ||||
| #include "BLI_listbase.h" | #include "BLI_listbase.h" | ||||
| #include "BLI_string_utf8.h" | #include "BLI_string_utf8.h" | ||||
| #include "BLI_alloca.h" | #include "BLI_array.hh" | ||||
| #include "BLI_float3.hh" | |||||
| #include "BLI_float4x4.hh" | #include "BLI_float4x4.hh" | ||||
| #include "BLI_math.h" | #include "BLI_math.h" | ||||
| #include "BLI_rand.h" | #include "BLI_rand.h" | ||||
| #include "BLI_span.hh" | #include "BLI_span.hh" | ||||
| #include "DNA_anim_types.h" | #include "DNA_anim_types.h" | ||||
| #include "DNA_collection_types.h" | #include "DNA_collection_types.h" | ||||
| #include "DNA_mesh_types.h" | #include "DNA_mesh_types.h" | ||||
| Show All 21 Lines | |||||
| #include "BKE_scene.h" | #include "BKE_scene.h" | ||||
| #include "DEG_depsgraph.h" | #include "DEG_depsgraph.h" | ||||
| #include "DEG_depsgraph_query.h" | #include "DEG_depsgraph_query.h" | ||||
| #include "BLI_hash.h" | #include "BLI_hash.h" | ||||
| #include "BLI_strict_flags.h" | #include "BLI_strict_flags.h" | ||||
| using blender::Array; | |||||
| using blender::float3; | |||||
| using blender::float4x4; | using blender::float4x4; | ||||
| using blender::Span; | using blender::Span; | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Internal Duplicate Context | /** \name Internal Duplicate Context | ||||
| * \{ */ | * \{ */ | ||||
| struct DupliContext { | struct DupliContext { | ||||
| ▲ Show 20 Lines • Show All 828 Lines • ▼ Show 20 Lines | struct FaceDupliData_EditMesh { | ||||
| BMEditMesh *em; | BMEditMesh *em; | ||||
| bool has_orco, has_uvs; | bool has_orco, has_uvs; | ||||
| int cd_loop_uv_offset; | int cd_loop_uv_offset; | ||||
| /* Can be nullptr. */ | /* Can be nullptr. */ | ||||
| const float (*vert_coords)[3]; | const float (*vert_coords)[3]; | ||||
| }; | }; | ||||
| static void get_dupliface_transform_from_coords(const float coords[][3], | static void get_dupliface_transform_from_coords(Span<float3> coords, | ||||
| const int coords_len, | |||||
| const bool use_scale, | const bool use_scale, | ||||
| const float scale_fac, | const float scale_fac, | ||||
| float r_mat[4][4]) | float r_mat[4][4]) | ||||
| { | { | ||||
| float loc[3], quat[4], scale, size[3]; | |||||
| /* Location. */ | /* Location. */ | ||||
| { | float3 location(0); | ||||
| const float w = 1.0f / (float)coords_len; | for (const float3 &coord : coords) { | ||||
| zero_v3(loc); | location += coord; | ||||
| for (int i = 0; i < coords_len; i++) { | |||||
| madd_v3_v3fl(loc, coords[i], w); | |||||
| } | |||||
| } | } | ||||
| location *= 1.0f / (float)coords.size(); | |||||
| /* Rotation. */ | /* Rotation. */ | ||||
| { | float quat[4]; | ||||
| float f_no[3]; | |||||
| cross_poly_v3(f_no, coords, (uint)coords_len); | float3 f_no; | ||||
| normalize_v3(f_no); | cross_poly_v3(f_no, (const float(*)[3])coords.data(), (uint)coords.size()); | ||||
| f_no.normalize(); | |||||
| tri_to_quat_ex(quat, coords[0], coords[1], coords[2], f_no); | tri_to_quat_ex(quat, coords[0], coords[1], coords[2], f_no); | ||||
| } | |||||
| /* Scale. */ | /* Scale. */ | ||||
| float scale; | |||||
| if (use_scale) { | if (use_scale) { | ||||
| const float area = area_poly_v3(coords, (uint)coords_len); | const float area = area_poly_v3((const float(*)[3])coords.data(), (uint)coords.size()); | ||||
| scale = sqrtf(area) * scale_fac; | scale = sqrtf(area) * scale_fac; | ||||
| } | } | ||||
| else { | else { | ||||
| scale = 1.0f; | scale = 1.0f; | ||||
| } | } | ||||
| size[0] = size[1] = size[2] = scale; | |||||
| loc_quat_size_to_mat4(r_mat, loc, quat, size); | loc_quat_size_to_mat4(r_mat, location, quat, float3(scale)); | ||||
| } | } | ||||
| static DupliObject *face_dupli(const DupliContext *ctx, | static DupliObject *face_dupli(const DupliContext *ctx, | ||||
| Object *inst_ob, | Object *inst_ob, | ||||
| const float child_imat[4][4], | const float child_imat[4][4], | ||||
| const int index, | const int index, | ||||
| const bool use_scale, | const bool use_scale, | ||||
| const float scale_fac, | const float scale_fac, | ||||
| const float (*coords)[3], | Span<float3> coords) | ||||
| const int coords_len) | |||||
| { | { | ||||
| float obmat[4][4]; | float obmat[4][4]; | ||||
| float space_mat[4][4]; | float space_mat[4][4]; | ||||
| /* `obmat` is transform to face. */ | /* `obmat` is transform to face. */ | ||||
| get_dupliface_transform_from_coords(coords, coords_len, use_scale, scale_fac, obmat); | get_dupliface_transform_from_coords(coords, use_scale, scale_fac, obmat); | ||||
| /* Make offset relative to inst_ob using relative child transform. */ | /* Make offset relative to inst_ob using relative child transform. */ | ||||
| mul_mat3_m4_v3(child_imat, obmat[3]); | mul_mat3_m4_v3(child_imat, obmat[3]); | ||||
| /* XXX ugly hack to ensure same behavior as in master. | /* XXX ugly hack to ensure same behavior as in master. | ||||
| * This should not be needed, #Object.parentinv is not consistent outside of parenting. */ | * This should not be needed, #Object.parentinv is not consistent outside of parenting. */ | ||||
| { | { | ||||
| float imat[3][3]; | float imat[3][3]; | ||||
| Show All 11 Lines | static DupliObject *face_dupli(const DupliContext *ctx, | ||||
| DupliObject *dob = make_dupli(ctx, inst_ob, obmat, index); | DupliObject *dob = make_dupli(ctx, inst_ob, obmat, index); | ||||
| /* Recursion. */ | /* Recursion. */ | ||||
| make_recursive_duplis(ctx, inst_ob, space_mat, index); | make_recursive_duplis(ctx, inst_ob, space_mat, index); | ||||
| return dob; | return dob; | ||||
| } | } | ||||
| /** Wrap #face_dupli, needed since we can't #alloca in a loop. */ | |||||
| static DupliObject *face_dupli_from_mesh(const DupliContext *ctx, | static DupliObject *face_dupli_from_mesh(const DupliContext *ctx, | ||||
| Object *inst_ob, | Object *inst_ob, | ||||
| const float child_imat[4][4], | const float child_imat[4][4], | ||||
| const int index, | const int index, | ||||
| const bool use_scale, | const bool use_scale, | ||||
| const float scale_fac, | const float scale_fac, | ||||
| /* Mesh variables. */ | /* Mesh variables. */ | ||||
| const MPoly *mpoly, | const MPoly *mpoly, | ||||
| const MLoop *mloopstart, | const MLoop *mloopstart, | ||||
| const MVert *mvert) | const MVert *mvert) | ||||
| { | { | ||||
| const int coords_len = mpoly->totloop; | const int coords_len = mpoly->totloop; | ||||
| float(*coords)[3] = (float(*)[3])BLI_array_alloca(coords, (size_t)coords_len); | Array<float3, 64> coords(coords_len); | ||||
| const MLoop *ml = mloopstart; | const MLoop *ml = mloopstart; | ||||
| for (int i = 0; i < coords_len; i++, ml++) { | for (int i = 0; i < coords_len; i++, ml++) { | ||||
| copy_v3_v3(coords[i], mvert[ml->v].co); | coords[i] = float3(mvert[ml->v].co); | ||||
| } | } | ||||
| return face_dupli(ctx, inst_ob, child_imat, index, use_scale, scale_fac, coords, coords_len); | return face_dupli(ctx, inst_ob, child_imat, index, use_scale, scale_fac, coords); | ||||
| } | } | ||||
| /** Wrap #face_dupli, needed since we can't #alloca in a loop. */ | |||||
| static DupliObject *face_dupli_from_editmesh(const DupliContext *ctx, | static DupliObject *face_dupli_from_editmesh(const DupliContext *ctx, | ||||
| Object *inst_ob, | Object *inst_ob, | ||||
| const float child_imat[4][4], | const float child_imat[4][4], | ||||
| const int index, | const int index, | ||||
| const bool use_scale, | const bool use_scale, | ||||
| const float scale_fac, | const float scale_fac, | ||||
| /* Mesh variables. */ | /* Mesh variables. */ | ||||
| BMFace *f, | BMFace *f, | ||||
| const float (*vert_coords)[3]) | const float (*vert_coords)[3]) | ||||
| { | { | ||||
| const int coords_len = f->len; | const int coords_len = f->len; | ||||
| float(*coords)[3] = (float(*)[3])BLI_array_alloca(coords, (size_t)coords_len); | Array<float3, 64> coords(coords_len); | ||||
| BMLoop *l_first, *l_iter; | BMLoop *l_first, *l_iter; | ||||
| int i = 0; | int i = 0; | ||||
| l_iter = l_first = BM_FACE_FIRST_LOOP(f); | l_iter = l_first = BM_FACE_FIRST_LOOP(f); | ||||
| if (vert_coords != nullptr) { | if (vert_coords != nullptr) { | ||||
| do { | do { | ||||
| copy_v3_v3(coords[i++], vert_coords[BM_elem_index_get(l_iter->v)]); | copy_v3_v3(coords[i++], vert_coords[BM_elem_index_get(l_iter->v)]); | ||||
| } while ((l_iter = l_iter->next) != l_first); | } while ((l_iter = l_iter->next) != l_first); | ||||
| } | } | ||||
| else { | else { | ||||
| do { | do { | ||||
| copy_v3_v3(coords[i++], l_iter->v->co); | copy_v3_v3(coords[i++], l_iter->v->co); | ||||
| } while ((l_iter = l_iter->next) != l_first); | } while ((l_iter = l_iter->next) != l_first); | ||||
| } | } | ||||
| return face_dupli(ctx, inst_ob, child_imat, index, use_scale, scale_fac, coords, coords_len); | return face_dupli(ctx, inst_ob, child_imat, index, use_scale, scale_fac, coords); | ||||
| } | } | ||||
| static void make_child_duplis_faces_from_mesh(const DupliContext *ctx, | static void make_child_duplis_faces_from_mesh(const DupliContext *ctx, | ||||
| void *userdata, | void *userdata, | ||||
| Object *inst_ob) | Object *inst_ob) | ||||
| { | { | ||||
| FaceDupliData_Mesh *fdd = (FaceDupliData_Mesh *)userdata; | FaceDupliData_Mesh *fdd = (FaceDupliData_Mesh *)userdata; | ||||
| const MPoly *mpoly = fdd->mpoly, *mp; | const MPoly *mpoly = fdd->mpoly, *mp; | ||||
| ▲ Show 20 Lines • Show All 556 Lines • Show Last 20 Lines | |||||