diff options
author | Bastien Montagne <montagne29@wanadoo.fr> | 2017-02-17 22:03:55 +0300 |
---|---|---|
committer | Bastien Montagne <montagne29@wanadoo.fr> | 2017-02-17 22:03:55 +0300 |
commit | 322b1d3187fc5b3e82ebf8b13a675e3132059ef4 (patch) | |
tree | 50a7091fc310cd503e3878a9b9f7a4734f9fcdc7 /source | |
parent | cb36dbe606d9e5bef32a756a60b1d77a92dccfa8 (diff) | |
parent | 6f1493f68fe01a8e951cf6c4e50103e20b85d513 (diff) |
Merge branch 'master' into blender2.8
Conflicts:
source/blender/editors/animation/anim_draw.c
Diffstat (limited to 'source')
31 files changed, 655 insertions, 1168 deletions
diff --git a/source/blender/alembic/intern/abc_archive.cc b/source/blender/alembic/intern/abc_archive.cc index 0985a06d732..5f8fc1a3739 100644 --- a/source/blender/alembic/intern/abc_archive.cc +++ b/source/blender/alembic/intern/abc_archive.cc @@ -113,25 +113,25 @@ static OArchive create_archive(std::ostream *ostream, Alembic::Abc::MetaData &md, bool ogawa) { - md.set(Alembic::Abc::kApplicationNameKey, "Blender"); + md.set(Alembic::Abc::kApplicationNameKey, "Blender"); md.set(Alembic::Abc::kUserDescriptionKey, scene_name); - time_t raw_time; - time(&raw_time); - char buffer[128]; + time_t raw_time; + time(&raw_time); + char buffer[128]; #if defined _WIN32 || defined _WIN64 - ctime_s(buffer, 128, &raw_time); + ctime_s(buffer, 128, &raw_time); #else - ctime_r(&raw_time, buffer); + ctime_r(&raw_time, buffer); #endif - const std::size_t buffer_len = strlen(buffer); - if (buffer_len > 0 && buffer[buffer_len - 1] == '\n') { - buffer[buffer_len - 1] = '\0'; - } + const std::size_t buffer_len = strlen(buffer); + if (buffer_len > 0 && buffer[buffer_len - 1] == '\n') { + buffer[buffer_len - 1] = '\0'; + } - md.set(Alembic::Abc::kDateWrittenKey, buffer); + md.set(Alembic::Abc::kDateWrittenKey, buffer); ErrorHandler::Policy policy = ErrorHandler::kThrowPolicy; diff --git a/source/blender/alembic/intern/abc_curves.cc b/source/blender/alembic/intern/abc_curves.cc index 282777f3af0..0542255d84b 100644 --- a/source/blender/alembic/intern/abc_curves.cc +++ b/source/blender/alembic/intern/abc_curves.cc @@ -361,7 +361,7 @@ void read_curve_sample(Curve *cu, const ICurvesSchema &schema, const float time) * object directly and create a new DerivedMesh from that. Also we might need to * create new or delete existing NURBS in the curve. */ -DerivedMesh *AbcCurveReader::read_derivedmesh(DerivedMesh */*dm*/, const float time, int /*read_flag*/, const char **/*err_str*/) +DerivedMesh *AbcCurveReader::read_derivedmesh(DerivedMesh * /*dm*/, const float time, int /*read_flag*/, const char ** /*err_str*/) { ISampleSelector sample_sel(time); const ICurvesSchema::Sample sample = m_curves_schema.getValue(sample_sel); diff --git a/source/blender/alembic/intern/abc_exporter.cc b/source/blender/alembic/intern/abc_exporter.cc index 28d54672d20..45c31279b50 100644 --- a/source/blender/alembic/intern/abc_exporter.cc +++ b/source/blender/alembic/intern/abc_exporter.cc @@ -47,7 +47,7 @@ extern "C" { #ifdef WIN32 /* needed for MSCV because of snprintf from BLI_string */ -# include "BLI_winstuff.h" +# include "BLI_winstuff.h" #endif #include "BKE_anim.h" diff --git a/source/blender/alembic/intern/abc_points.cc b/source/blender/alembic/intern/abc_points.cc index 4c78f3e83c7..fc84759b1d9 100644 --- a/source/blender/alembic/intern/abc_points.cc +++ b/source/blender/alembic/intern/abc_points.cc @@ -200,7 +200,7 @@ void read_points_sample(const IPointsSchema &schema, read_mverts(config.mvert, positions, vnormals); } -DerivedMesh *AbcPointsReader::read_derivedmesh(DerivedMesh *dm, const float time, int /*read_flag*/, const char **/*err_str*/) +DerivedMesh *AbcPointsReader::read_derivedmesh(DerivedMesh *dm, const float time, int /*read_flag*/, const char ** /*err_str*/) { ISampleSelector sample_sel(time); const IPointsSchema::Sample sample = m_schema.getValue(sample_sel); diff --git a/source/blender/alembic/intern/abc_transform.cc b/source/blender/alembic/intern/abc_transform.cc index e2fc7674c4e..2c6ef09326c 100644 --- a/source/blender/alembic/intern/abc_transform.cc +++ b/source/blender/alembic/intern/abc_transform.cc @@ -122,7 +122,7 @@ Imath::Box3d AbcTransformWriter::bounds() return Imath::transform(bounds, m_matrix); } -bool AbcTransformWriter::hasAnimation(Object */*ob*/) const +bool AbcTransformWriter::hasAnimation(Object * /*ob*/) const { /* TODO(kevin): implement this. */ return true; @@ -146,6 +146,6 @@ bool AbcEmptyReader::valid() const void AbcEmptyReader::readObjectData(Main *bmain, float /*time*/) { - m_object = BKE_object_add_only_object(bmain, OB_EMPTY, m_object_name.c_str()); + m_object = BKE_object_add_only_object(bmain, OB_EMPTY, m_data_name.c_str()); m_object->data = NULL; } diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h index bf45a27e51c..cb72f0859d5 100644 --- a/source/blender/blenkernel/BKE_bvhutils.h +++ b/source/blender/blenkernel/BKE_bvhutils.h @@ -54,7 +54,6 @@ typedef struct BVHTreeFromEditMesh { /* default callbacks to bvh nearest and raycast */ BVHTree_NearestPointCallback nearest_callback; BVHTree_RayCastCallback raycast_callback; - BVHTree_NearestToRayCallback nearest_to_ray_callback; struct BMEditMesh *em; @@ -75,7 +74,6 @@ typedef struct BVHTreeFromMesh { /* default callbacks to bvh nearest and raycast */ BVHTree_NearestPointCallback nearest_callback; BVHTree_RayCastCallback raycast_callback; - BVHTree_NearestToRayCallback nearest_to_ray_callback; /* Vertex array, so that callbacks have instante access to data */ const struct MVert *vert; @@ -104,7 +102,7 @@ typedef struct BVHTreeFromMesh { * The tree is build in mesh space coordinates, this means special care must be made on queries * so that the coordinates and rays are first translated on the mesh local coordinates. * Reason for this is that bvh_from_mesh_* can use a cache in some cases and so it becomes possible to reuse a BVHTree. - * + * * free_bvhtree_from_mesh should be called when the tree is no longer needed. */ BVHTree *bvhtree_from_editmesh_verts( @@ -118,7 +116,7 @@ BVHTree *bvhtree_from_editmesh_verts_ex( BVHTree *bvhtree_from_mesh_verts( struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis); BVHTree *bvhtree_from_mesh_verts_ex( - struct BVHTreeFromMesh *data, struct MVert *vert, const int numVerts, + struct BVHTreeFromMesh *data, const struct MVert *vert, const int numVerts, const bool vert_allocated, const BLI_bitmap *mask, int verts_num_active, float epsilon, int tree_type, int axis); @@ -135,8 +133,8 @@ BVHTree *bvhtree_from_mesh_edges( float epsilon, int tree_type, int axis); BVHTree *bvhtree_from_mesh_edges_ex( struct BVHTreeFromMesh *data, - struct MVert *vert, const bool vert_allocated, - struct MEdge *edge, const int edges_num, const bool edge_allocated, + const struct MVert *vert, const bool vert_allocated, + const struct MEdge *edge, const int edges_num, const bool edge_allocated, const BLI_bitmap *edges_mask, int edges_num_active, float epsilon, int tree_type, int axis); @@ -145,8 +143,8 @@ BVHTree *bvhtree_from_mesh_faces( int tree_type, int axis); BVHTree *bvhtree_from_mesh_faces_ex( struct BVHTreeFromMesh *data, - struct MVert *vert, const bool vert_allocated, - struct MFace *face, const int numFaces, const bool face_allocated, + const struct MVert *vert, const bool vert_allocated, + const struct MFace *face, const int numFaces, const bool face_allocated, const BLI_bitmap *mask, int numFaces_active, float epsilon, int tree_type, int axis); diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index c1655d3e9c6..b3b67d0924a 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -140,8 +140,6 @@ void BKE_boundbox_init_from_minmax(struct BoundBox *bb, const float min[3], cons void BKE_boundbox_calc_center_aabb(const struct BoundBox *bb, float r_cent[3]); void BKE_boundbox_calc_size_aabb(const struct BoundBox *bb, float r_size[3]); void BKE_boundbox_minmax(const struct BoundBox *bb, float obmat[4][4], float r_min[3], float r_max[3]); -struct BoundBox *BKE_boundbox_ensure_minimum_dimensions( - struct BoundBox *bb, struct BoundBox *bb_temp, const float epsilon); struct BoundBox *BKE_object_boundbox_get(struct Object *ob); void BKE_object_dimensions_get(struct Object *ob, float vec[3]); diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index b1dcc40279f..9236a1b5853 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -121,7 +121,7 @@ static bool test_path(char *targetpath, const char *path_base, const char *path_ if (path_sep) BLI_join_dirfile(tmppath, sizeof(tmppath), path_base, path_sep); else BLI_strncpy(tmppath, path_base, sizeof(tmppath)); - /* rare cases folder_name is omitted (when looking for ~/.blender/2.xx dir only) */ + /* rare cases folder_name is omitted (when looking for ~/.config/blender/2.xx dir only) */ if (folder_name) BLI_make_file_string("/", targetpath, tmppath, folder_name); else diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c index d0e0c82e3be..c0e4ef37a93 100644 --- a/source/blender/blenkernel/intern/bvhutils.c +++ b/source/blender/blenkernel/intern/bvhutils.c @@ -376,45 +376,6 @@ static void mesh_edges_spherecast(void *userdata, int index, const BVHTreeRay *r } } -#define V3_MUL_ELEM(a, b) \ - (a)[0] * (b)[0], \ - (a)[1] * (b)[1], \ - (a)[2] * (b)[2] - -/* Callback to bvh tree nearest edge to ray. - * The tree must have been built using bvhtree_from_mesh_edges. - * userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */ -static void mesh_edges_nearest_to_ray( - void *userdata, const float ray_co[3], const float ray_dir[3], - const float scale[3], int index, BVHTreeNearest *nearest) -{ - struct BVHTreeFromMesh *data = userdata; - const MVert *vert = data->vert; - const MEdge *e = &data->edge[index]; - - const float t0[3] = {V3_MUL_ELEM(vert[e->v1].co, scale)}; - const float t1[3] = {V3_MUL_ELEM(vert[e->v2].co, scale)}; - const float origin_sc[3] = {V3_MUL_ELEM(ray_co, scale)}; - const float dir_sc[3] = {V3_MUL_ELEM(ray_dir, scale)}; - - float depth, point[3]; - const float dist_sq = dist_squared_ray_to_seg_v3(origin_sc, dir_sc, t0, t1, point, &depth); - - if (dist_sq < nearest->dist_sq) { - nearest->dist_sq = dist_sq; - nearest->index = index; - - point[0] /= scale[0]; - point[1] /= scale[1]; - point[2] /= scale[2]; - - copy_v3_v3(nearest->co, point); - sub_v3_v3v3(nearest->no, t0, t1); - } -} - -#undef V3_MUL_ELEM - /** \} */ /* @@ -459,7 +420,7 @@ static BVHTree *bvhtree_from_editmesh_verts_create_tree( static BVHTree *bvhtree_from_mesh_verts_create_tree( float epsilon, int tree_type, int axis, - MVert *vert, const int verts_num, + const MVert *vert, const int verts_num, const BLI_bitmap *verts_mask, int verts_num_active) { BLI_assert(vert != NULL); @@ -488,31 +449,23 @@ static BVHTree *bvhtree_from_mesh_verts_create_tree( static void bvhtree_from_mesh_verts_setup_data( BVHTreeFromMesh *data, BVHTree *tree, const bool is_cached, float epsilon, - MVert *vert, const bool vert_allocated) + const MVert *vert, const bool vert_allocated) { memset(data, 0, sizeof(*data)); - if (tree) { - data->tree = tree; - data->cached = is_cached; + data->tree = tree; + data->cached = is_cached; - /* a NULL nearest callback works fine - * remember the min distance to point is the same as the min distance to BV of point */ - data->nearest_callback = NULL; - data->raycast_callback = mesh_verts_spherecast; - data->nearest_to_ray_callback = NULL; + /* a NULL nearest callback works fine + * remember the min distance to point is the same as the min distance to BV of point */ + data->nearest_callback = NULL; + data->raycast_callback = mesh_verts_spherecast; - data->vert = vert; - data->vert_allocated = vert_allocated; - //data->face = DM_get_tessface_array(dm, &data->face_allocated); /* XXX WHY???? */ + data->vert = vert; + data->vert_allocated = vert_allocated; + //data->face = DM_get_tessface_array(dm, &data->face_allocated); /* XXX WHY???? */ - data->sphere_radius = epsilon; - } - else { - if (vert_allocated) { - MEM_freeN(vert); - } - } + data->sphere_radius = epsilon; } /* Builds a bvh tree where nodes are the vertices of the given em */ @@ -531,7 +484,6 @@ BVHTree *bvhtree_from_editmesh_verts_ex( data->em = em; data->nearest_callback = NULL; data->raycast_callback = editmesh_verts_spherecast; - data->nearest_to_ray_callback = NULL; } return tree; @@ -588,11 +540,18 @@ BVHTree *bvhtree_from_mesh_verts( /* printf("BVHTree is already build, using cached tree\n"); */ } - /* Setup BVHTreeFromMesh */ - bvhtree_from_mesh_verts_setup_data( - data, tree, true, epsilon, vert, vert_allocated); - - return data->tree; + if (tree) { + /* Setup BVHTreeFromMesh */ + bvhtree_from_mesh_verts_setup_data( + data, tree, true, epsilon, vert, vert_allocated); + } + else { + if (vert_allocated) { + MEM_freeN(vert); + } + memset(data, 0, sizeof(*data)); + } + return tree; } /** @@ -602,7 +561,7 @@ BVHTree *bvhtree_from_mesh_verts( * \param verts_num_active if >= 0, number of active verts to add to BVH tree (else will be computed from mask). */ BVHTree *bvhtree_from_mesh_verts_ex( - BVHTreeFromMesh *data, MVert *vert, const int verts_num, const bool vert_allocated, + BVHTreeFromMesh *data, const MVert *vert, const int verts_num, const bool vert_allocated, const BLI_bitmap *verts_mask, int verts_num_active, float epsilon, int tree_type, int axis) { @@ -613,7 +572,7 @@ BVHTree *bvhtree_from_mesh_verts_ex( bvhtree_from_mesh_verts_setup_data( data, tree, false, epsilon, vert, vert_allocated); - return data->tree; + return tree; } /** \} */ @@ -661,7 +620,7 @@ static BVHTree *bvhtree_from_editmesh_edges_create_tree( } static BVHTree *bvhtree_from_mesh_edges_create_tree( - MVert *vert, MEdge *edge, const int edge_num, + const MVert *vert, const MEdge *edge, const int edge_num, const BLI_bitmap *edges_mask, int edges_num_active, float epsilon, int tree_type, int axis) { @@ -694,34 +653,26 @@ static BVHTree *bvhtree_from_mesh_edges_create_tree( } static void bvhtree_from_mesh_edges_setup_data( - BVHTreeFromMesh *data, BVHTree *tree, const bool is_cached, float epsilon, - MVert *vert, const bool vert_allocated, MEdge *edge, const bool edge_allocated) + BVHTreeFromMesh *data, BVHTree *tree, + const bool is_cached, float epsilon, + const MVert *vert, const bool vert_allocated, + const MEdge *edge, const bool edge_allocated) { memset(data, 0, sizeof(*data)); + data->tree = tree; - if (data->tree) { - data->cached = is_cached; + data->cached = is_cached; - data->nearest_callback = mesh_edges_nearest_point; - data->raycast_callback = mesh_edges_spherecast; - data->nearest_to_ray_callback = mesh_edges_nearest_to_ray; + data->nearest_callback = mesh_edges_nearest_point; + data->raycast_callback = mesh_edges_spherecast; - data->vert = vert; - data->vert_allocated = vert_allocated; - data->edge = edge; - data->edge_allocated = edge_allocated; + data->vert = vert; + data->vert_allocated = vert_allocated; + data->edge = edge; + data->edge_allocated = edge_allocated; - data->sphere_radius = epsilon; - } - else { - if (vert_allocated) { - MEM_freeN(vert); - } - if (edge_allocated) { - MEM_freeN(edge); - } - } + data->sphere_radius = epsilon; } /* Builds a bvh tree where nodes are the edges of the given em */ @@ -742,8 +693,6 @@ BVHTree *bvhtree_from_editmesh_edges_ex( data->em = em; data->nearest_callback = NULL; /* TODO */ data->raycast_callback = NULL; /* TODO */ - /* TODO: not urgent however since users currently define own callbacks */ - data->nearest_to_ray_callback = NULL; } return tree; @@ -795,11 +744,21 @@ BVHTree *bvhtree_from_mesh_edges( /* printf("BVHTree is already build, using cached tree\n"); */ } - /* Setup BVHTreeFromMesh */ - bvhtree_from_mesh_edges_setup_data( - data, tree, true, epsilon, vert, vert_allocated, edge, edge_allocated); - - return data->tree; + if (tree) { + /* Setup BVHTreeFromMesh */ + bvhtree_from_mesh_edges_setup_data( + data, tree, true, epsilon, vert, vert_allocated, edge, edge_allocated); + } + else { + if (vert_allocated) { + MEM_freeN(vert); + } + if (edge_allocated) { + MEM_freeN(edge); + } + memset(data, 0, sizeof(*data)); + } + return tree; } /** @@ -810,8 +769,8 @@ BVHTree *bvhtree_from_mesh_edges( */ BVHTree *bvhtree_from_mesh_edges_ex( BVHTreeFromMesh *data, - MVert *vert, const bool vert_allocated, - MEdge *edge, const int edges_num, const bool edge_allocated, + const MVert *vert, const bool vert_allocated, + const MEdge *edge, const int edges_num, const bool edge_allocated, const BLI_bitmap *edges_mask, int edges_num_active, float epsilon, int tree_type, int axis) { @@ -823,7 +782,7 @@ BVHTree *bvhtree_from_mesh_edges_ex( bvhtree_from_mesh_edges_setup_data( data, tree, false, epsilon, vert, vert_allocated, edge, edge_allocated); - return data->tree; + return tree; } /** \} */ @@ -836,7 +795,7 @@ BVHTree *bvhtree_from_mesh_edges_ex( static BVHTree *bvhtree_from_mesh_faces_create_tree( float epsilon, int tree_type, int axis, - MVert *vert, MFace *face, const int faces_num, + const MVert *vert, const MFace *face, const int faces_num, const BLI_bitmap *faces_mask, int faces_num_active) { BVHTree *tree = NULL; @@ -880,34 +839,23 @@ static BVHTree *bvhtree_from_mesh_faces_create_tree( static void bvhtree_from_mesh_faces_setup_data( BVHTreeFromMesh *data, BVHTree *tree, const bool is_cached, float epsilon, - MVert *vert, const bool vert_allocated, - MFace *face, const bool face_allocated) + const MVert *vert, const bool vert_allocated, + const MFace *face, const bool face_allocated) { memset(data, 0, sizeof(*data)); - if (tree) { - data->tree = tree; - data->cached = is_cached; + data->tree = tree; + data->cached = is_cached; - data->nearest_callback = mesh_faces_nearest_point; - data->raycast_callback = mesh_faces_spherecast; - data->nearest_to_ray_callback = NULL; + data->nearest_callback = mesh_faces_nearest_point; + data->raycast_callback = mesh_faces_spherecast; - data->vert = vert; - data->vert_allocated = vert_allocated; - data->face = face; - data->face_allocated = face_allocated; + data->vert = vert; + data->vert_allocated = vert_allocated; + data->face = face; + data->face_allocated = face_allocated; - data->sphere_radius = epsilon; - } - else { - if (vert_allocated) { - MEM_freeN(vert); - } - if (face_allocated) { - MEM_freeN(face); - } - } + data->sphere_radius = epsilon; } /* Builds a bvh tree where nodes are the tesselated faces of the given dm */ @@ -950,10 +898,21 @@ BVHTree *bvhtree_from_mesh_faces( /* printf("BVHTree is already build, using cached tree\n"); */ } - /* Setup BVHTreeFromMesh */ - bvhtree_from_mesh_faces_setup_data(data, tree, true, epsilon, vert, vert_allocated, face, face_allocated); - - return data->tree; + if (tree) { + /* Setup BVHTreeFromMesh */ + bvhtree_from_mesh_faces_setup_data( + data, tree, true, epsilon, vert, vert_allocated, face, face_allocated); + } + else { + if (vert_allocated) { + MEM_freeN(vert); + } + if (face_allocated) { + MEM_freeN(face); + } + memset(data, 0, sizeof(*data)); + } + return tree; } /** @@ -964,8 +923,8 @@ BVHTree *bvhtree_from_mesh_faces( * \param numFaces_active if >= 0, number of active faces to add to BVH tree (else will be computed from mask). */ BVHTree *bvhtree_from_mesh_faces_ex( - BVHTreeFromMesh *data, MVert *vert, const bool vert_allocated, - MFace *face, const int numFaces, const bool face_allocated, + BVHTreeFromMesh *data, const MVert *vert, const bool vert_allocated, + const MFace *face, const int numFaces, const bool face_allocated, const BLI_bitmap *faces_mask, int faces_num_active, float epsilon, int tree_type, int axis) { @@ -975,9 +934,10 @@ BVHTree *bvhtree_from_mesh_faces_ex( faces_mask, faces_num_active); /* Setup BVHTreeFromMesh */ - bvhtree_from_mesh_faces_setup_data(data, tree, false, epsilon, vert, vert_allocated, face, face_allocated); + bvhtree_from_mesh_faces_setup_data( + data, tree, false, epsilon, vert, vert_allocated, face, face_allocated); - return data->tree; + return tree; } /** \} */ @@ -1088,34 +1048,20 @@ static void bvhtree_from_mesh_looptri_setup_data( { memset(data, 0, sizeof(*data)); - if (tree) { - data->tree = tree; - data->cached = is_cached; + data->tree = tree; + data->cached = is_cached; - data->nearest_callback = mesh_looptri_nearest_point; - data->raycast_callback = mesh_looptri_spherecast; - data->nearest_to_ray_callback = NULL; + data->nearest_callback = mesh_looptri_nearest_point; + data->raycast_callback = mesh_looptri_spherecast; - data->vert = vert; - data->vert_allocated = vert_allocated; - data->loop = mloop; - data->loop_allocated = loop_allocated; - data->looptri = looptri; - data->looptri_allocated = looptri_allocated; + data->vert = vert; + data->vert_allocated = vert_allocated; + data->loop = mloop; + data->loop_allocated = loop_allocated; + data->looptri = looptri; + data->looptri_allocated = looptri_allocated; - data->sphere_radius = epsilon; - } - else { - if (vert_allocated) { - MEM_freeN((void *)vert); - } - if (loop_allocated) { - MEM_freeN((void *)mloop); - } - if (looptri_allocated) { - MEM_freeN((void *)looptri); - } - } + data->sphere_radius = epsilon; } /** @@ -1160,7 +1106,6 @@ BVHTree *bvhtree_from_editmesh_looptri_ex( data->tree = tree; data->nearest_callback = editmesh_looptri_nearest_point; data->raycast_callback = editmesh_looptri_spherecast; - data->nearest_to_ray_callback = NULL; data->sphere_radius = 0.0f; data->em = em; data->cached = bvhCache != NULL; @@ -1242,14 +1187,28 @@ BVHTree *bvhtree_from_mesh_looptri( /* printf("BVHTree is already build, using cached tree\n"); */ } - /* Setup BVHTreeFromMesh */ - bvhtree_from_mesh_looptri_setup_data( - data, tree, true, epsilon, - mvert, vert_allocated, - mloop, loop_allocated, - looptri, looptri_allocated); + if (tree) { + /* Setup BVHTreeFromMesh */ + bvhtree_from_mesh_looptri_setup_data( + data, tree, true, epsilon, + mvert, vert_allocated, + mloop, loop_allocated, + looptri, looptri_allocated); + } + else { + if (vert_allocated) { + MEM_freeN(mvert); + } + if (loop_allocated) { + MEM_freeN(mloop); + } + if (looptri_allocated) { + MEM_freeN((void *)looptri); + } + memset(data, 0, sizeof(*data)); + } - return data->tree; + return tree; } BVHTree *bvhtree_from_mesh_looptri_ex( @@ -1272,7 +1231,7 @@ BVHTree *bvhtree_from_mesh_looptri_ex( mloop, loop_allocated, looptri, looptri_allocated); - return data->tree; + return tree; } /** \} */ @@ -1292,29 +1251,27 @@ void free_bvhtree_from_editmesh(struct BVHTreeFromEditMesh *data) /* Frees data allocated by a call to bvhtree_from_mesh_*. */ void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data) { - if (data->tree) { - if (!data->cached) { - BLI_bvhtree_free(data->tree); - } - - if (data->vert_allocated) { - MEM_freeN((void *)data->vert); - } - if (data->edge_allocated) { - MEM_freeN((void *)data->edge); - } - if (data->face_allocated) { - MEM_freeN((void *)data->face); - } - if (data->loop_allocated) { - MEM_freeN((void *)data->loop); - } - if (data->looptri_allocated) { - MEM_freeN((void *)data->looptri); - } + if (data->tree && !data->cached) { + BLI_bvhtree_free(data->tree); + } - memset(data, 0, sizeof(*data)); + if (data->vert_allocated) { + MEM_freeN((void *)data->vert); + } + if (data->edge_allocated) { + MEM_freeN((void *)data->edge); + } + if (data->face_allocated) { + MEM_freeN((void *)data->face); } + if (data->loop_allocated) { + MEM_freeN((void *)data->loop); + } + if (data->looptri_allocated) { + MEM_freeN((void *)data->looptri); + } + + memset(data, 0, sizeof(*data)); } diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 483fa977aff..7042b46330b 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -2428,8 +2428,12 @@ static DerivedMesh *cddm_copy_ex(DerivedMesh *source, dm->cd_flag = source->cd_flag; dm->dirty = source->dirty; - /* Tessellation data is never copied, so tag it here. */ - dm->dirty |= DM_DIRTY_TESS_CDLAYERS; + /* Tessellation data is never copied, so tag it here. + * Only tag dirty layers if we really ignored tessellation faces. + */ + if (!copy_tessface_data) { + dm->dirty |= DM_DIRTY_TESS_CDLAYERS; + } CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts); CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges); diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index a2d94ccc478..318f6480aaf 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -3159,7 +3159,7 @@ static ImBuf *load_sequence_single(Image *ima, ImageUser *iuser, int frame, cons struct ImBuf *ibuf; char name[FILE_MAX]; int flag; - ImageUser iuser_t; + ImageUser iuser_t = {0}; /* XXX temp stuff? */ if (ima->lastframe != frame) @@ -3167,8 +3167,12 @@ static ImBuf *load_sequence_single(Image *ima, ImageUser *iuser, int frame, cons ima->lastframe = frame; - if (iuser) + if (iuser) { iuser_t = *iuser; + } + else { + /* TODO(sergey): Do we need to initialize something here? */ + } iuser_t.view = view_id; BKE_image_user_file_path(&iuser_t, ima, name); diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 134173580ae..d93e66c6171 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -67,6 +67,11 @@ #include "DEG_depsgraph.h" +/* Define for cases when you want extra validation of mesh + * after certain modifications. + */ +// #undef VALIDATE_MESH + enum { MESHCMP_DVERT_WEIGHTMISMATCH = 1, MESHCMP_DVERT_GROUPMISMATCH, @@ -2094,104 +2099,296 @@ void BKE_mesh_calc_normals_split(Mesh *mesh) } } -/* Spli faces based on the edge angle. - * Matches behavior of face splitting in render engines. +/* Split faces helper functions. */ + +enum { + /* Vertex is adjacent to some loop which normal is different, + * hence split of this vertex is required. + */ + SPLIT_VERT_NEED_SPLIT = (1 << 0), + /* Original vertex was already re-used by split logic. */ + SPLIT_VERT_REUSED = (1 << 1), +}; +enum { + /* Edge is adjacent to any of vertex tagged for split. + */ + SPLIT_EDGE_NEED_SPLIT = (1 << 0), + /* Original edge was already re-used by split logic. */ + SPLIT_EDGE_REUSED = (1 << 1), +}; + +/* Tag vertices which normals are not equal to any adjacent loop + * and hence split on that vertex is required. + * + * Returns truth if any of vertex needs to be split. */ -void BKE_mesh_split_faces(Mesh *mesh) +static bool split_faces_tag_verts(const Mesh *mesh, uchar *vert_flags) +{ + const int num_polys = mesh->totpoly; + const MVert *mvert = mesh->mvert; + const MLoop *mloop = mesh->mloop; + const MPoly *mpoly = mesh->mpoly; + float (*lnors)[3] = CustomData_get_layer(&mesh->ldata, CD_NORMAL); + bool has_split_verts = false; + for (int poly = 0; poly < num_polys; poly++) { + const MPoly *mp = &mpoly[poly]; + for (int loop = 0; loop < mp->totloop; loop++) { + const MLoop *ml = &mloop[mp->loopstart + loop]; + const MVert *mv = &mvert[ml->v]; + float vn[3]; + normal_short_to_float_v3(vn, mv->no); + if (len_squared_v3v3(vn, lnors[mp->loopstart + loop]) > FLT_EPSILON) { + vert_flags[ml->v] |= SPLIT_VERT_NEED_SPLIT; + has_split_verts = true; + } + } + } + return has_split_verts; +} + +/* Count number of new vertices to be added. + * + * Note that one of the loop where split is required will re-use + * it's vertex in order to avoid creation of loose vertices. + */ +static int split_faces_count_new_verts(const Mesh *mesh, uchar *vert_flags) +{ + const int num_polys = mesh->totpoly; + const MLoop *mloop = mesh->mloop; + const MPoly *mpoly = mesh->mpoly; + int num_new_verts = 0; + for (int poly = 0; poly < num_polys; poly++) { + const MPoly *mp = &mpoly[poly]; + for (int loop = 0; loop < mp->totloop; loop++) { + const MLoop *ml = &mloop[mp->loopstart + loop]; + if (vert_flags[ml->v] & SPLIT_VERT_NEED_SPLIT) { + if (vert_flags[ml->v] & SPLIT_VERT_REUSED) { + ++num_new_verts; + } + else { + vert_flags[ml->v] |= SPLIT_VERT_REUSED; + } + } + } + } + return num_new_verts; +} + +/* Tag edges which are adjacent to at least one vertex tagged for split. */ +static void split_faces_tag_edges(Mesh *mesh, + const uchar *vert_flags, + uchar *edge_flags) +{ + const int num_polys = mesh->totpoly; + const MLoop *mloop = mesh->mloop; + const MPoly *mpoly = mesh->mpoly; + for (int poly = 0; poly < num_polys; poly++) { + const MPoly *mp = &mpoly[poly]; + int loop_prev = mp->totloop - 1; + for (int loop = 0; loop < mp->totloop; loop++) { + const int poly_loop_prev = mp->loopstart + loop_prev; + const MLoop *ml = &mloop[mp->loopstart + loop]; + const MLoop *ml_prev = &mloop[poly_loop_prev]; + const int mv_flag = vert_flags[ml->v]; + const int mv_prev_flag = vert_flags[ml_prev->v]; + bool need_split = false; + if (mv_flag & SPLIT_VERT_NEED_SPLIT) { + if (mv_prev_flag & SPLIT_VERT_NEED_SPLIT) { + /* Create new edge between twp split vertices. */ + need_split = true; + } + else { + /* Create new edge from existing vertex to a split one. */ + need_split = true; + } + } + else if (mv_prev_flag & SPLIT_VERT_NEED_SPLIT) { + /* Create new edge from split vertex to existing one. */ + need_split = true; + } + if (need_split) { + edge_flags[ml_prev->e] |= SPLIT_EDGE_NEED_SPLIT; + } + loop_prev = loop; + } + } +} + +/* Count number of new edges to be added. + * + * Note that one of the loop where split is required will re-use + * it's edge in order to avoid creation of loose edges. + */ +static int split_faces_count_new_edges(const Mesh *mesh, uchar *edge_flags) { - const int num_verts = mesh->totvert; - const int num_edges = mesh->totedge; + const int num_polys = mesh->totpoly; + const MLoop *mloop = mesh->mloop; + const MPoly *mpoly = mesh->mpoly; + int num_new_edges = 0; + for (int poly = 0; poly < num_polys; poly++) { + const MPoly *mp = &mpoly[poly]; + for (int loop = 0; loop < mp->totloop; loop++) { + const MLoop *ml = &mloop[mp->loopstart + loop]; + if (edge_flags[ml->e] & SPLIT_EDGE_NEED_SPLIT) { + if (edge_flags[ml->e] & SPLIT_EDGE_REUSED) { + ++num_new_edges; + } + else { + edge_flags[ml->e] |= SPLIT_EDGE_REUSED; + } + } + } + } + return num_new_edges; +} + +/* Perform actual split of vertices. + * + * NOTE: Will leave edges in inconsistent state. + */ +static void split_faces_split_verts(Mesh *mesh, + const int num_new_verts, + uchar *vert_flags) +{ + const int num_verts = mesh->totvert - num_new_verts; const int num_polys = mesh->totpoly; MVert *mvert = mesh->mvert; + MLoop *mloop = mesh->mloop; + MPoly *mpoly = mesh->mpoly; + const float (*lnors)[3] = CustomData_get_layer(&mesh->ldata, CD_NORMAL); + int num_added_verts = 0; + /* Clear reused flag, we need it again. */ + for (int i = 0; i < num_verts; ++i) { + vert_flags[i] &= ~SPLIT_VERT_REUSED; + } + for (int poly = 0; poly < num_polys; poly++) { + MPoly *mp = &mpoly[poly]; + /* First we split all vertices to get proper flag whether they are + * split or not for all of them before handling edges. + */ + for (int loop = 0; loop < mp->totloop; loop++) { + int poly_loop = mp->loopstart + loop; + MLoop *ml = &mloop[poly_loop]; + if (vert_flags[ml->v] & SPLIT_VERT_NEED_SPLIT) { + if ((vert_flags[ml->v] & SPLIT_VERT_REUSED) == 0) { + /* Ignore first split on vertex, re-use it instead. */ + vert_flags[ml->v] |= SPLIT_VERT_REUSED; + continue; + } + /* Create new vertex. */ + int new_vert = num_verts + num_added_verts; + CustomData_copy_data(&mesh->vdata, &mesh->vdata, + ml->v, new_vert, 1); + normal_float_to_short_v3(mvert[new_vert].no, + lnors[poly_loop]); + ml->v = new_vert; + num_added_verts++; + } + } + } +} + +/* Perform actual split of edges. + * + * NOTE: Will correct all edges. + */ +static void split_faces_split_edges(Mesh *mesh, + const int num_new_edges, + uchar *edge_flags) +{ + const int num_edges = mesh->totedge - num_new_edges; + const int num_polys = mesh->totpoly; MEdge *medge = mesh->medge; MLoop *mloop = mesh->mloop; MPoly *mpoly = mesh->mpoly; - float (*lnors)[3]; - int poly, num_new_verts = 0; + int num_added_edges = 0; + /* Clear reused flag, we need it again. */ + for (int i = 0; i < num_edges; ++i) { + edge_flags[i] &= ~SPLIT_EDGE_REUSED; + } + for (int poly = 0; poly < num_polys; poly++) { + MPoly *mp = &mpoly[poly]; + for (int loop = 0, loop_prev = mp->totloop - 1; loop < mp->totloop; loop++) { + const int poly_loop_prev = mp->loopstart + loop_prev; + const MLoop *ml = &mloop[mp->loopstart + loop]; + MLoop *ml_prev = &mloop[poly_loop_prev]; + MEdge *me_prev = &medge[ml_prev->e]; + if (edge_flags[ml_prev->e] & SPLIT_EDGE_NEED_SPLIT) { + if ((edge_flags[ml_prev->e] & SPLIT_EDGE_REUSED) == 0) { + edge_flags[ml_prev->e] |= SPLIT_EDGE_REUSED; + me_prev->v1 = ml_prev->v; + me_prev->v2 = ml->v; + } + else { + const int index = num_edges + num_added_edges; + CustomData_copy_data(&mesh->edata, &mesh->edata, + ml_prev->e, index, 1); + MEdge *me_new = &medge[index]; + me_new->v1 = ml_prev->v; + me_new->v2 = ml->v; + ml_prev->e = index; + num_added_edges++; + } + } + loop_prev = loop; + } + } +} + +/* Split faces based on the edge angle. + * Matches behavior of face splitting in render engines. + */ +void BKE_mesh_split_faces(Mesh *mesh) +{ + const int num_verts = mesh->totvert; + const int num_edges = mesh->totedge; + const int num_polys = mesh->totpoly; if ((mesh->flag & ME_AUTOSMOOTH) == 0) { return; } + if (num_polys == 0) { + return; + } BKE_mesh_tessface_clear(mesh); /* Compute loop normals if needed. */ if (!CustomData_has_layer(&mesh->ldata, CD_NORMAL)) { BKE_mesh_calc_normals_split(mesh); } - lnors = CustomData_get_layer(&mesh->ldata, CD_NORMAL); - /* Count number of vertices to be split. */ - for (poly = 0; poly < num_polys; poly++) { - MPoly *mp = &mpoly[poly]; - int loop; - for (loop = 0; loop < mp->totloop; loop++) { - MLoop *ml = &mloop[mp->loopstart + loop]; - MVert *mv = &mvert[ml->v]; - float vn[3]; - normal_short_to_float_v3(vn, mv->no); - if (!equals_v3v3(vn, lnors[mp->loopstart + loop])) { - num_new_verts++; - } - } - } - if (num_new_verts == 0) { - /* No new vertices are to be added, can do early exit. */ + /* Runtime flags. */ + uchar *vert_flags = MEM_callocN(sizeof(*vert_flags) * num_verts, + "split faces vert flags"); + /* Tag vertces and check whether anything is tagged. */ + if (!split_faces_tag_verts(mesh, vert_flags)) { + /* No new vertices to be split added, can do early exit. */ + MEM_freeN(vert_flags); return; } + /* Flush vertex flags to edges. */ + uchar *edge_flags = MEM_callocN(sizeof(*edge_flags) * num_edges, + "split faces edge flags"); + split_faces_tag_edges(mesh, vert_flags, edge_flags); + /* Count amount of new geometry. */ + int num_new_verts = split_faces_count_new_verts(mesh, vert_flags); + int num_new_edges = split_faces_count_new_edges(mesh, edge_flags); /* Reallocate all vert and edge related data. */ mesh->totvert += num_new_verts; - mesh->totedge += 2 * num_new_verts; + mesh->totedge += num_new_edges; CustomData_realloc(&mesh->vdata, mesh->totvert); CustomData_realloc(&mesh->edata, mesh->totedge); /* Update pointers to a newly allocated memory. */ BKE_mesh_update_customdata_pointers(mesh, false); - mvert = mesh->mvert; - medge = mesh->medge; - /* Perform actual vertex split. */ - num_new_verts = 0; - for (poly = 0; poly < num_polys; poly++) { - MPoly *mp = &mpoly[poly]; - int loop; - for (loop = 0; loop < mp->totloop; loop++) { - int poly_loop = mp->loopstart + loop; - MLoop *ml = &mloop[poly_loop]; - MVert *mv = &mvert[ml->v]; - float vn[3]; - normal_short_to_float_v3(vn, mv->no); - if (!equals_v3v3(vn, lnors[mp->loopstart + loop])) { - int poly_loop_prev = mp->loopstart + (loop + mp->totloop - 1) % mp->totloop; - MLoop *ml_prev = &mloop[poly_loop_prev]; - int new_edge_prev, new_edge; - /* Cretae new vertex. */ - int new_vert = num_verts + num_new_verts; - CustomData_copy_data(&mesh->vdata, &mesh->vdata, - ml->v, new_vert, 1); - normal_float_to_short_v3(mvert[new_vert].no, - lnors[poly_loop]); - /* Create new edges. */ - new_edge_prev = num_edges + 2 * num_new_verts; - new_edge = num_edges + 2 * num_new_verts + 1; - CustomData_copy_data(&mesh->edata, &mesh->edata, - ml_prev->e, new_edge_prev, 1); - CustomData_copy_data(&mesh->edata, &mesh->edata, - ml->e, new_edge, 1); - if (medge[new_edge_prev].v1 == ml->v) { - medge[new_edge_prev].v1 = new_vert; - } - else { - medge[new_edge_prev].v2 = new_vert; - } - if (medge[new_edge].v1 == ml->v) { - medge[new_edge].v1 = new_vert; - } - else { - medge[new_edge].v2 = new_vert; - } - - ml->v = new_vert; - ml_prev->e = new_edge_prev; - ml->e = new_edge; - num_new_verts++; - } - } - } + /* Perform actual split of vertices and adjacent edges. */ + split_faces_split_verts(mesh, num_new_verts, vert_flags); + split_faces_split_edges(mesh, num_new_edges, edge_flags); + /* CD_NORMAL is expected to be temporary only, and it's invalid at + * this point anyway. + */ + CustomData_free_layers(&mesh->ldata, CD_NORMAL, mesh->totloop); + MEM_freeN(vert_flags); + MEM_freeN(edge_flags); +#ifdef VALIDATE_MESH + BKE_mesh_validate(mesh, true, true); +#endif } /* settings: 1 - preview, 2 - render */ diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 7b3869b3a94..ad0ce3fef9b 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -2241,66 +2241,6 @@ void BKE_boundbox_minmax(const BoundBox *bb, float obmat[4][4], float r_min[3], } } -/** - * Returns a BBox which each dimensions are at least epsilon. - * \note In case a given dimension needs to be enlarged, its final value will be in [epsilon, 3 * epsilon] range. - * - * \param bb the input bbox to check. - * \param bb_temp the temp bbox to modify (\a bb content is never changed). - * \param epsilon the minimum dimension to ensure. - * \return either bb (if nothing needed to be changed) or bb_temp. - */ -BoundBox *BKE_boundbox_ensure_minimum_dimensions(BoundBox *bb, BoundBox *bb_temp, const float epsilon) -{ - if (fabsf(bb->vec[0][0] - bb->vec[4][0]) < epsilon) { - /* Flat along X axis... */ - *bb_temp = *bb; - bb = bb_temp; - bb->vec[0][0] -= epsilon; - bb->vec[1][0] -= epsilon; - bb->vec[2][0] -= epsilon; - bb->vec[3][0] -= epsilon; - bb->vec[4][0] += epsilon; - bb->vec[5][0] += epsilon; - bb->vec[6][0] += epsilon; - bb->vec[7][0] += epsilon; - } - - if (fabsf(bb->vec[0][1] - bb->vec[3][1]) < epsilon) { - /* Flat along Y axis... */ - if (bb != bb_temp) { - *bb_temp = *bb; - bb = bb_temp; - } - bb->vec[0][1] -= epsilon; - bb->vec[1][1] -= epsilon; - bb->vec[4][1] -= epsilon; - bb->vec[5][1] -= epsilon; - bb->vec[2][1] += epsilon; - bb->vec[3][1] += epsilon; - bb->vec[6][1] += epsilon; - bb->vec[7][1] += epsilon; - } - - if (fabsf(bb->vec[0][2] - bb->vec[1][2]) < epsilon) { - /* Flat along Z axis... */ - if (bb != bb_temp) { - *bb_temp = *bb; - bb = bb_temp; - } - bb->vec[0][2] -= epsilon; - bb->vec[3][2] -= epsilon; - bb->vec[4][2] -= epsilon; - bb->vec[7][2] -= epsilon; - bb->vec[1][2] += epsilon; - bb->vec[2][2] += epsilon; - bb->vec[5][2] += epsilon; - bb->vec[6][2] += epsilon; - } - - return bb; -} - BoundBox *BKE_object_boundbox_get(Object *ob) { BoundBox *bb = NULL; diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h index 91d39801645..ba565fca522 100644 --- a/source/blender/blenlib/BLI_kdopbvh.h +++ b/source/blender/blenlib/BLI_kdopbvh.h @@ -95,10 +95,6 @@ typedef void (*BVHTree_NearestPointCallback)(void *userdata, int index, const fl /* callback must update hit in case it finds a nearest successful hit */ typedef void (*BVHTree_RayCastCallback)(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit); -/* callback must update nearest in case it finds a nearest result */ -typedef void (*BVHTree_NearestToRayCallback)(void *userdata, const float ray_co[3], const float ray_dir[3], - const float scale[3], int index, BVHTreeNearest *nearest); - /* callback to check if 2 nodes overlap (use thread if intersection results need to be stored) */ typedef bool (*BVHTree_OverlapCallback)(void *userdata, int index_a, int index_b, int thread); @@ -143,18 +139,6 @@ int BLI_bvhtree_find_nearest( BVHTree *tree, const float co[3], BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata); -int BLI_bvhtree_find_nearest_to_ray_angle( - BVHTree *tree, const float co[3], const float dir[3], - const bool ray_is_normalized, const float scale[3], - BVHTreeNearest *nearest, - BVHTree_NearestToRayCallback callback, void *userdata); - -int BLI_bvhtree_find_nearest_to_ray( - BVHTree *tree, const float co[3], const float dir[3], - const bool ray_is_normalized, const float scale[3], - BVHTreeNearest *nearest, - BVHTree_NearestToRayCallback callback, void *userdata); - int BLI_bvhtree_ray_cast_ex( BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata, diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index 4a85e859c16..f1d9c9571f2 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -298,23 +298,6 @@ bool isect_ray_aabb_v3_simple( const float bb_min[3], const float bb_max[3], float *tmin, float *tmax); -struct NearestRayToAABB_Precalc { - float ray_origin[3]; - float ray_direction[3]; - float ray_inv_dir[3]; - float cdot_axis[3]; - float idiag_sq[3]; - bool sign[3]; -}; - -void dist_squared_ray_to_aabb_v3_precalc( - struct NearestRayToAABB_Precalc *data, - const float ray_origin[3], const float ray_direction[3]); -float dist_squared_ray_to_aabb_v3( - const struct NearestRayToAABB_Precalc *data, - const float bb_min[3], const float bb_max[3], - bool r_axis_closest[3]); - /* other */ bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const float radius, const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float ipoint[3]); diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index b14007a88cb..19d9711922e 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -159,29 +159,6 @@ typedef struct BVHRayCastData { BVHTreeRayHit hit; } BVHRayCastData; -typedef struct BVHNearestRayData { - BVHTree *tree; - BVHTree_NearestToRayCallback callback; - void *userdata; - - struct { - bool sign[3]; - float origin[3]; - float direction[3]; - - float direction_scaled_square[3]; - float inv_dir[3]; - - float cdot_axis[3]; - } ray; - - bool pick_smallest[3]; - - BVHTreeNearest nearest; - - float scale[3]; -} BVHNearestRayData; - /** \} */ @@ -1900,453 +1877,6 @@ void BLI_bvhtree_ray_cast_all( /* -------------------------------------------------------------------- */ -/** \name BLI_bvhtree_find_nearest_to_ray functions - * - * \{ */ - -static void dist_squared_ray_to_aabb_scaled_v3_precalc( - BVHNearestRayData *data, - const float ray_origin[3], const float ray_direction[3], - const bool ray_is_normalized, const float scale[3]) -{ - if (scale) { - copy_v3_v3(data->scale, scale); - } - else { - copy_v3_fl(data->scale, 1.0f); - } - /* un-normalize ray */ - if (ray_is_normalized && scale && - (data->scale[0] != 1.0f || data->scale[1] != 1.0f || data->scale[2] != 1.0f)) - { - data->ray.direction[0] = ray_direction[0] * data->scale[0]; - data->ray.direction[1] = ray_direction[1] * data->scale[1]; - data->ray.direction[2] = ray_direction[2] * data->scale[2]; - - mul_v3_v3fl(data->ray.direction, ray_direction, 1 / len_v3(data->ray.direction)); - } - else { - copy_v3_v3(data->ray.direction, ray_direction); - } - - float dir_sq[3]; - - for (int i = 0; i < 3; i++) { - data->ray.origin[i] = ray_origin[i]; - data->ray.inv_dir[i] = (data->ray.direction[i] != 0.0f) ? - (1.0f / data->ray.direction[i]) : FLT_MAX; - /* It has to be in function of `ray.inv_dir`, - * since the division of 1 by 0.0f, can be -inf or +inf */ - data->ray.sign[i] = (data->ray.inv_dir[i] < 0.0f); - - data->ray.direction_scaled_square[i] = data->ray.direction[i] * data->scale[i]; - - dir_sq[i] = SQUARE(data->ray.direction_scaled_square[i]); - - data->ray.direction_scaled_square[i] *= data->scale[i]; - } - - /* `diag_sq` Length square of each face diagonal */ - float diag_sq[3] = { - dir_sq[1] + dir_sq[2], - dir_sq[0] + dir_sq[2], - dir_sq[0] + dir_sq[1], - }; - - data->ray.cdot_axis[0] = (diag_sq[0] != 0.0f) ? data->ray.direction[0] / diag_sq[0] : FLT_MAX; - data->ray.cdot_axis[1] = (diag_sq[1] != 0.0f) ? data->ray.direction[1] / diag_sq[1] : FLT_MAX; - data->ray.cdot_axis[2] = (diag_sq[2] != 0.0f) ? data->ray.direction[2] / diag_sq[2] : FLT_MAX; -} - -/** - * Returns the squared distance from a ray to a bound-box `AABB`. - * It is based on `fast_ray_nearest_hit` solution to obtain - * the coordinates of the nearest edge of Bound Box to the ray - */ -MINLINE float dist_squared_ray_to_aabb_scaled_v3__impl( - const BVHNearestRayData *data, - const float bv[6], float *r_depth_sq, bool r_axis_closest[3]) -{ - - /* `tmin` is a vector that has the smaller distances to each of the - * infinite planes of the `AABB` faces (hit in nearest face X plane, - * nearest face Y plane and nearest face Z plane) */ - float local_bvmin[3], local_bvmax[3]; - - if (data->ray.sign[0]) { - local_bvmin[0] = bv[1]; - local_bvmax[0] = bv[0]; - } - else { - local_bvmin[0] = bv[0]; - local_bvmax[0] = bv[1]; - } - - if (data->ray.sign[1]) { - local_bvmin[1] = bv[3]; - local_bvmax[1] = bv[2]; - } - else { - local_bvmin[1] = bv[2]; - local_bvmax[1] = bv[3]; - } - - if (data->ray.sign[2]) { - local_bvmin[2] = bv[5]; - local_bvmax[2] = bv[4]; - } - else { - local_bvmin[2] = bv[4]; - local_bvmax[2] = bv[5]; - } - - sub_v3_v3(local_bvmin, data->ray.origin); - sub_v3_v3(local_bvmax, data->ray.origin); - - const float tmin[3] = { - local_bvmin[0] * data->ray.inv_dir[0], - local_bvmin[1] * data->ray.inv_dir[1], - local_bvmin[2] * data->ray.inv_dir[2], - }; - - /* `tmax` is a vector that has the longer distances to each of the - * infinite planes of the `AABB` faces (hit in farthest face X plane, - * farthest face Y plane and farthest face Z plane) */ - const float tmax[3] = { - local_bvmax[0] * data->ray.inv_dir[0], - local_bvmax[1] * data->ray.inv_dir[1], - local_bvmax[2] * data->ray.inv_dir[2], - }; - /* `v1` and `v3` is be the coordinates of the nearest `AABB` edge to the ray*/ - float v1[3], v2[3]; - /* `rtmin` is the highest value of the smaller distances. == max_axis_v3(tmin) - * `rtmax` is the lowest value of longer distances. == min_axis_v3(tmax)*/ - float rtmin, rtmax, mul; - /* `main_axis` is the axis equivalent to edge close to the ray */ - int main_axis; - - r_axis_closest[0] = false; - r_axis_closest[1] = false; - r_axis_closest[2] = false; - - /* *** min_axis_v3(tmax) *** */ - if ((tmax[0] <= tmax[1]) && (tmax[0] <= tmax[2])) { - // printf("# Hit in X %s\n", data->sign[0] ? "min", "max"); - rtmax = tmax[0]; - v1[0] = v2[0] = local_bvmax[0]; - mul = local_bvmax[0] * data->ray.direction_scaled_square[0]; - main_axis = 3; - r_axis_closest[0] = data->ray.sign[0]; - } - else if ((tmax[1] <= tmax[0]) && (tmax[1] <= tmax[2])) { - // printf("# Hit in Y %s\n", data->sign[1] ? "min", "max"); - rtmax = tmax[1]; - v1[1] = v2[1] = local_bvmax[1]; - mul = local_bvmax[1] * data->ray.direction_scaled_square[1]; - main_axis = 2; - r_axis_closest[1] = data->ray.sign[1]; - } - else { - // printf("# Hit in Z %s\n", data->sign[2] ? "min", "max"); - rtmax = tmax[2]; - v1[2] = v2[2] = local_bvmax[2]; - mul = local_bvmax[2] * data->ray.direction_scaled_square[2]; - main_axis = 1; - r_axis_closest[2] = data->ray.sign[2]; - } - - /* *** max_axis_v3(tmin) *** */ - if ((tmin[0] >= tmin[1]) && (tmin[0] >= tmin[2])) { - // printf("# To X %s\n", data->sign[0] ? "max", "min"); - rtmin = tmin[0]; - v1[0] = v2[0] = local_bvmin[0]; - mul += local_bvmin[0] * data->ray.direction_scaled_square[0]; - main_axis -= 3; - r_axis_closest[0] = !data->ray.sign[0]; - } - else if ((tmin[1] >= tmin[0]) && (tmin[1] >= tmin[2])) { - // printf("# To Y %s\n", data->sign[1] ? "max", "min"); - rtmin = tmin[1]; - v1[1] = v2[1] = local_bvmin[1]; - mul += local_bvmin[1] * data->ray.direction_scaled_square[1]; - main_axis -= 1; - r_axis_closest[1] = !data->ray.sign[1]; - } - else { - // printf("# To Z %s\n", data->sign[2] ? "max", "min"); - rtmin = tmin[2]; - v1[2] = v2[2] = local_bvmin[2]; - mul += local_bvmin[2] * data->ray.direction_scaled_square[2]; - main_axis -= 2; - r_axis_closest[2] = !data->ray.sign[2]; - } - /* *** end min/max axis *** */ - - if (main_axis < 0) - main_axis += 3; - - /* if rtmin < rtmax, ray intersect `AABB` */ - if (rtmin <= rtmax) { -#ifdef IGNORE_BEHIND_RAY - /* `if rtmax < depth_min`, the whole `AABB` is behind us */ - if (rtmax < min_depth) { - return fallback; - } -#endif - const float proj = rtmin * data->ray.direction[main_axis]; - - if (data->ray.sign[main_axis]) - r_axis_closest[main_axis] = (proj - local_bvmax[main_axis]) < (local_bvmin[main_axis] - proj); - else - r_axis_closest[main_axis] = (proj - local_bvmin[main_axis]) < (local_bvmax[main_axis] - proj); - - //if (r_depth_sq) - // *r_depth_sq = SQUARE(rtmin); - - return 0.0f; - } -#ifdef IGNORE_BEHIND_RAY - /* `if rtmin < depth_min`, the whole `AABB` is behing us */ - else if (rtmin < min_depth) { - return fallback; - } -#endif - - if (data->ray.sign[main_axis]) { - v1[main_axis] = local_bvmax[main_axis]; - v2[main_axis] = local_bvmin[main_axis]; - } - else { - v1[main_axis] = local_bvmin[main_axis]; - v2[main_axis] = local_bvmax[main_axis]; - } - { - /* `proj` equals to nearest point on the ray closest to the edge `v1 v2` of the `AABB`. */ - const float proj = mul * data->ray.cdot_axis[main_axis]; - float depth_sq, r_point[3]; - if (v1[main_axis] > proj) { /* the nearest point to the ray is the point v1 */ - r_axis_closest[main_axis] = true; - /* `depth` is equivalent the distance of the the projection of v1 on the ray */ - depth_sq = mul + data->ray.direction_scaled_square[main_axis] * v1[main_axis]; - - copy_v3_v3(r_point, v1); - } - else if (v2[main_axis] < proj) { /* the nearest point of the ray is the point v2 */ - r_axis_closest[main_axis] = false; - - depth_sq = mul + data->ray.direction_scaled_square[main_axis] * v2[main_axis]; - - copy_v3_v3(r_point, v2); - } - else { /* the nearest point of the ray is on the edge of the `AABB`. */ - r_axis_closest[main_axis] = (proj - v1[main_axis]) < (v2[main_axis] - proj); - - depth_sq = mul + data->ray.direction_scaled_square[main_axis] * proj; -#if 0 - r_point[0] = main_axis == 0 ? proj : v2[0]; - r_point[1] = main_axis == 1 ? proj : v2[1]; - r_point[2] = main_axis == 2 ? proj : v2[2]; -#else - v2[main_axis] = proj; - copy_v3_v3(r_point, v2); -#endif - } - depth_sq *= depth_sq; - - if (r_depth_sq) - *r_depth_sq = depth_sq; - - /* TODO: scale can be optional */ - r_point[0] *= data->scale[0]; - r_point[1] *= data->scale[1]; - r_point[2] *= data->scale[2]; - - return len_squared_v3(r_point) - depth_sq; - } -} - -/** - * <pre> - * + r_point - * | - * | dist - * | - * +----depth----+orig <-- dir - * - * tangent = dist/depth - * </pre> - */ -static float calc_tangent_sq(BVHNearestRayData *data, BVHNode *node) -{ - float depth_sq; - const float dist_sq = dist_squared_ray_to_aabb_scaled_v3__impl( - data, node->bv, &depth_sq, data->pick_smallest); - - return (dist_sq != 0.0f) ? (dist_sq / depth_sq) : 0.0f; -} - -static float calc_dist_sq_to_ray(BVHNearestRayData *data, BVHNode *node) -{ - return dist_squared_ray_to_aabb_scaled_v3__impl( - data, node->bv, NULL, - data->pick_smallest); -} - -static void dfs_find_lowest_tangent_dfs(BVHNearestRayData *data, BVHNode *node) -{ - if (node->totnode == 0) { - if (data->callback) { - data->callback(data->userdata, data->ray.origin, data->ray.direction, - data->scale, node->index, &data->nearest); - } - else { - data->nearest.index = node->index; - data->nearest.dist_sq = calc_tangent_sq(data, node); - /* TODO: return a value to the data->nearest.co - * not urgent however since users currently define own callbacks */ - } - } - else { - int i; - /* First pick the closest node to dive on */ - if (data->pick_smallest[node->main_axis]) { - for (i = 0; i != node->totnode; i++) { - if (calc_tangent_sq(data, node->children[i]) < data->nearest.dist_sq) { - dfs_find_lowest_tangent_dfs(data, node->children[i]); - } - } - } - else { - for (i = node->totnode - 1; i >= 0; i--) { - if (calc_tangent_sq(data, node->children[i]) < data->nearest.dist_sq) { - dfs_find_lowest_tangent_dfs(data, node->children[i]); - } - } - } - } -} - -static void dfs_find_nearest_to_ray_dfs(BVHNearestRayData *data, BVHNode *node) -{ - if (node->totnode == 0) { - if (data->callback) { - data->callback(data->userdata, data->ray.origin, data->ray.direction, - data->scale, node->index, &data->nearest); - } - else { - data->nearest.index = node->index; - data->nearest.dist_sq = calc_dist_sq_to_ray(data, node); - /* TODO: return a value to the data->nearest.co - * not urgent however since users currently define own callbacks */ - } - } - else { - int i; - /* First pick the closest node to dive on */ - if (data->pick_smallest[node->main_axis]) { - for (i = 0; i != node->totnode; i++) { - if (calc_dist_sq_to_ray(data, node->children[i]) < data->nearest.dist_sq) { - dfs_find_nearest_to_ray_dfs(data, node->children[i]); - } - } - } - else { - for (i = node->totnode - 1; i >= 0; i--) { - if (calc_dist_sq_to_ray(data, node->children[i]) < data->nearest.dist_sq) { - dfs_find_nearest_to_ray_dfs(data, node->children[i]); - } - } - } - } -} - -/** - * Returns the point whose tangent defined by the angle between the point and ray is the lowest - * nearest.dist_sq returns the angle's tangent - */ -int BLI_bvhtree_find_nearest_to_ray_angle( - BVHTree *tree, const float co[3], const float dir[3], - const bool ray_is_normalized, const float scale[3], - BVHTreeNearest *nearest, - BVHTree_NearestToRayCallback callback, void *userdata) -{ - BVHNearestRayData data; - BVHNode *root = tree->nodes[tree->totleaf]; - - data.tree = tree; - - data.callback = callback; - data.userdata = userdata; - - dist_squared_ray_to_aabb_scaled_v3_precalc(&data, co, dir, ray_is_normalized, scale); - - if (nearest) { - memcpy(&data.nearest, nearest, sizeof(*nearest)); - } - else { - data.nearest.index = -1; - data.nearest.dist_sq = FLT_MAX; - } - - /* dfs search */ - if (root) { - if (calc_tangent_sq(&data, root) < data.nearest.dist_sq) - dfs_find_lowest_tangent_dfs(&data, root); - } - - /* copy back results */ - if (nearest) { - memcpy(nearest, &data.nearest, sizeof(*nearest)); - } - - return data.nearest.index; -} - -/* return the nearest point to ray */ -int BLI_bvhtree_find_nearest_to_ray( - BVHTree *tree, const float co[3], const float dir[3], - const bool ray_is_normalized, const float scale[3], - BVHTreeNearest *nearest, - BVHTree_NearestToRayCallback callback, void *userdata) -{ - BVHNearestRayData data; - BVHNode *root = tree->nodes[tree->totleaf]; - - data.tree = tree; - - data.callback = callback; - data.userdata = userdata; - - dist_squared_ray_to_aabb_scaled_v3_precalc(&data, co, dir, ray_is_normalized, scale); - - if (nearest) { - memcpy(&data.nearest, nearest, sizeof(*nearest)); - } - else { - data.nearest.index = -1; - data.nearest.dist_sq = FLT_MAX; - } - - /* dfs search */ - if (root) { - if (calc_dist_sq_to_ray(&data, root) < data.nearest.dist_sq) { - dfs_find_nearest_to_ray_dfs(&data, root); - } - } - - /* copy back results */ - if (nearest) { - memcpy(nearest, &data.nearest, sizeof(*nearest)); - } - - return data.nearest.index; -} - -/** \} */ - - -/* -------------------------------------------------------------------- */ - /** \name BLI_bvhtree_range_query * * Allocs and fills an array with the indexs of node that are on the given spherical range (center, radius). diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index aeb6a550cd9..3cf26ccf904 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -2337,224 +2337,6 @@ bool isect_ray_aabb_v3_simple( } } -void dist_squared_ray_to_aabb_v3_precalc( - struct NearestRayToAABB_Precalc *data, - const float ray_origin[3], const float ray_direction[3]) -{ - float dir_sq[3]; - - for (int i = 0; i < 3; i++) { - data->ray_origin[i] = ray_origin[i]; - data->ray_direction[i] = ray_direction[i]; - data->ray_inv_dir[i] = (data->ray_direction[i] != 0.0f) ? (1.0f / data->ray_direction[i]) : FLT_MAX; - /* It has to be a function of `ray_inv_dir`, - * since the division of 1 by 0.0f, can be -inf or +inf */ - data->sign[i] = (data->ray_inv_dir[i] < 0.0f); - - dir_sq[i] = SQUARE(data->ray_direction[i]); - } - - /* `diag_sq` Length square of each face diagonal */ - float diag_sq[3] = { - dir_sq[1] + dir_sq[2], - dir_sq[0] + dir_sq[2], - dir_sq[0] + dir_sq[1], - }; - data->idiag_sq[0] = (diag_sq[0] > FLT_EPSILON) ? (1.0f / diag_sq[0]) : FLT_MAX; - data->idiag_sq[1] = (diag_sq[1] > FLT_EPSILON) ? (1.0f / diag_sq[1]) : FLT_MAX; - data->idiag_sq[2] = (diag_sq[2] > FLT_EPSILON) ? (1.0f / diag_sq[2]) : FLT_MAX; - - data->cdot_axis[0] = data->ray_direction[0] * data->idiag_sq[0]; - data->cdot_axis[1] = data->ray_direction[1] * data->idiag_sq[1]; - data->cdot_axis[2] = data->ray_direction[2] * data->idiag_sq[2]; -} - -/** - * Returns the squared distance from a ray to a bound-box `AABB`. - * It is based on `fast_ray_nearest_hit` solution to obtain - * the coordinates of the nearest edge of Bound Box to the ray - */ -float dist_squared_ray_to_aabb_v3( - const struct NearestRayToAABB_Precalc *data, - const float bb_min[3], const float bb_max[3], - bool r_axis_closest[3]) -{ - /* `tmin` is a vector that has the smaller distances to each of the - * infinite planes of the `AABB` faces (hit in nearest face X plane, - * nearest face Y plane and nearest face Z plane) */ - float local_bvmin[3], local_bvmax[3]; - - if (data->sign[0] == 0) { - local_bvmin[0] = bb_min[0] - data->ray_origin[0]; - local_bvmax[0] = bb_max[0] - data->ray_origin[0]; - } - else { - local_bvmin[0] = bb_max[0] - data->ray_origin[0]; - local_bvmax[0] = bb_min[0] - data->ray_origin[0]; - } - - if (data->sign[1] == 0) { - local_bvmin[1] = bb_min[1] - data->ray_origin[1]; - local_bvmax[1] = bb_max[1] - data->ray_origin[1]; - } - else { - local_bvmin[1] = bb_max[1] - data->ray_origin[1]; - local_bvmax[1] = bb_min[1] - data->ray_origin[1]; - } - - if (data->sign[2] == 0) { - local_bvmin[2] = bb_min[2] - data->ray_origin[2]; - local_bvmax[2] = bb_max[2] - data->ray_origin[2]; - } - else { - local_bvmin[2] = bb_max[2] - data->ray_origin[2]; - local_bvmax[2] = bb_min[2] - data->ray_origin[2]; - } - - const float tmin[3] = { - local_bvmin[0] * data->ray_inv_dir[0], - local_bvmin[1] * data->ray_inv_dir[1], - local_bvmin[2] * data->ray_inv_dir[2], - }; - - /* `tmax` is a vector that has the longer distances to each of the - * infinite planes of the `AABB` faces (hit in farthest face X plane, - * farthest face Y plane and farthest face Z plane) */ - const float tmax[3] = { - local_bvmax[0] * data->ray_inv_dir[0], - local_bvmax[1] * data->ray_inv_dir[1], - local_bvmax[2] * data->ray_inv_dir[2], - }; - /* `v1` and `v3` is be the coordinates of the nearest `AABB` edge to the ray*/ - float v1[3], v2[3]; - /* `rtmin` is the highest value of the smaller distances. == max_axis_v3(tmin) - * `rtmax` is the lowest value of longer distances. == min_axis_v3(tmax)*/ - float rtmin, rtmax, mul, rdist; - /* `main_axis` is the axis equivalent to edge close to the ray */ - int main_axis; - - r_axis_closest[0] = false; - r_axis_closest[1] = false; - r_axis_closest[2] = false; - - /* *** min_axis_v3(tmax) *** */ - if ((tmax[0] <= tmax[1]) && (tmax[0] <= tmax[2])) { - // printf("# Hit in X %s\n", data->sign[0] ? "min", "max"); - rtmax = tmax[0]; - v1[0] = v2[0] = local_bvmax[0]; - mul = local_bvmax[0] * data->ray_direction[0]; - main_axis = 3; - r_axis_closest[0] = data->sign[0]; - } - else if ((tmax[1] <= tmax[0]) && (tmax[1] <= tmax[2])) { - // printf("# Hit in Y %s\n", data->sign[1] ? "min", "max"); - rtmax = tmax[1]; - v1[1] = v2[1] = local_bvmax[1]; - mul = local_bvmax[1] * data->ray_direction[1]; - main_axis = 2; - r_axis_closest[1] = data->sign[1]; - } - else { - // printf("# Hit in Z %s\n", data->sign[2] ? "min", "max"); - rtmax = tmax[2]; - v1[2] = v2[2] = local_bvmax[2]; - mul = local_bvmax[2] * data->ray_direction[2]; - main_axis = 1; - r_axis_closest[2] = data->sign[2]; - } - - /* *** max_axis_v3(tmin) *** */ - if ((tmin[0] >= tmin[1]) && (tmin[0] >= tmin[2])) { - // printf("# To X %s\n", data->sign[0] ? "max", "min"); - rtmin = tmin[0]; - v1[0] = v2[0] = local_bvmin[0]; - mul += local_bvmin[0] * data->ray_direction[0]; - main_axis -= 3; - r_axis_closest[0] = !data->sign[0]; - } - else if ((tmin[1] >= tmin[0]) && (tmin[1] >= tmin[2])) { - // printf("# To Y %s\n", data->sign[1] ? "max", "min"); - rtmin = tmin[1]; - v1[1] = v2[1] = local_bvmin[1]; - mul += local_bvmin[1] * data->ray_direction[1]; - main_axis -= 1; - r_axis_closest[1] = !data->sign[1]; - } - else { - // printf("# To Z %s\n", data->sign[2] ? "max", "min"); - rtmin = tmin[2]; - v1[2] = v2[2] = local_bvmin[2]; - mul += local_bvmin[2] * data->ray_direction[2]; - main_axis -= 2; - r_axis_closest[2] = !data->sign[2]; - } - /* *** end min/max axis *** */ - - - /* `if rtmax < 0`, the whole `AABB` is behing us */ - if ((rtmax < 0.0f) && (rtmin < 0.0f)) { - return FLT_MAX; - } - - if (main_axis < 0) { - main_axis += 3; - } - - if (data->sign[main_axis] == 0) { - v1[main_axis] = local_bvmin[main_axis]; - v2[main_axis] = local_bvmax[main_axis]; - } - else { - v1[main_axis] = local_bvmax[main_axis]; - v2[main_axis] = local_bvmin[main_axis]; - } - - /* if rtmin < rtmax, ray intersect `AABB` */ - if (rtmin <= rtmax) { - const float proj = rtmin * data->ray_direction[main_axis]; - rdist = 0.0f; - r_axis_closest[main_axis] = (proj - v1[main_axis]) < (v2[main_axis] - proj); - } - else { - /* `proj` equals to nearest point on the ray closest to the edge `v1 v2` of the `AABB`. */ - const float proj = mul * data->cdot_axis[main_axis]; - float depth; - if (v1[main_axis] > proj) { /* the nearest point to the ray is the point v1 */ - /* `depth` is equivalent the distance from the origin to the point v1, - * Here's a faster way to calculate the dot product of v1 and ray - * (depth = dot_v3v3(v1, data->ray.direction))*/ - depth = mul + data->ray_direction[main_axis] * v1[main_axis]; - rdist = len_squared_v3(v1) - SQUARE(depth); - r_axis_closest[main_axis] = true; - } - else if (v2[main_axis] < proj) { /* the nearest point of the ray is the point v2 */ - depth = mul + data->ray_direction[main_axis] * v2[main_axis]; - rdist = len_squared_v3(v2) - SQUARE(depth); - r_axis_closest[main_axis] = false; - } - else { /* the nearest point of the ray is on the edge of the `AABB`. */ - float v[2]; - mul *= data->idiag_sq[main_axis]; - if (main_axis == 0) { - v[0] = (mul * data->ray_direction[1]) - v1[1]; - v[1] = (mul * data->ray_direction[2]) - v1[2]; - } - else if (main_axis == 1) { - v[0] = (mul * data->ray_direction[0]) - v1[0]; - v[1] = (mul * data->ray_direction[2]) - v1[2]; - } - else { - v[0] = (mul * data->ray_direction[0]) - v1[0]; - v[1] = (mul * data->ray_direction[1]) - v1[1]; - } - rdist = len_squared_v2(v); - r_axis_closest[main_axis] = (proj - v1[main_axis]) < (v2[main_axis] - proj); - } - } - - return rdist; -} - /* find closest point to p on line through (l1, l2) and return lambda, * where (0 <= lambda <= 1) when cp is in the line segment (l1, l2) */ diff --git a/source/blender/blenlib/intern/polyfill2d.c b/source/blender/blenlib/intern/polyfill2d.c index 8d9881e4539..2969b0eccf4 100644 --- a/source/blender/blenlib/intern/polyfill2d.c +++ b/source/blender/blenlib/intern/polyfill2d.c @@ -21,8 +21,15 @@ /** \file blender/blenlib/intern/polyfill2d.c * \ingroup bli * - * A simple implementation of the ear cutting algorithm - * to triangulate simple polygons without holes. + * An ear clipping algorithm to triangulate single boundary polygons. + * + * Details: + * + * - The algorithm guarantees all triangles are assigned (number of coords - 2) + * and that triangles will have non-overlapping indices (even for degenerate geometry). + * - Self-intersections are considered degenerate (resulting triangles will overlap). + * - While multiple polygons aren't supported, holes can still be defined using *key-holes* + * (where the polygon doubles back on its self with *exactly* matching coordinates). * * \note * @@ -74,6 +81,12 @@ typedef signed char eSign; #ifdef USE_KDTREE /** + * Spatial optimization for point-in-triangle intersection checks. + * The simple version of this algorithm is ``O(n^2)`` complexity + * (every point needing to check the triangle defined by every other point), + * Using a binary-tree reduces the complexity to ``O(n log n)`` + * plus some overhead of creating the tree. + * * This is a single purpose KDTree based on BLI_kdtree with some modifications * to better suit polyfill2d. * diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 61a93018f71..8a18533f730 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -10520,6 +10520,9 @@ static void read_libraries(FileData *basefd, ListBase *mainlist) else { mainptr->curlib->filedata = NULL; mainptr->curlib->id.tag |= LIB_TAG_MISSING; + /* Set lib version to current main one... Makes assert later happy. */ + mainptr->versionfile = mainptr->curlib->versionfile = mainl->versionfile; + mainptr->subversionfile = mainptr->curlib->subversionfile = mainl->subversionfile; } if (fd == NULL) { diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 57846f6c030..fda5b9501ee 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -78,7 +78,7 @@ * - write #TEST (#RenderInfo struct. 128x128 blend file preview is optional). * - write #GLOB (#FileGlobal struct) (some global vars). * - write #DNA1 (#SDNA struct) - * - write #USER (#UserDef struct) if filename is ``~/X.XX/config/startup.blend``. + * - write #USER (#UserDef struct) if filename is ``~/.config/blender/X.XX/config/startup.blend``. */ diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index 2b830657923..1d71ba8dc34 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -46,6 +46,8 @@ #include "BLI_dlrbTree.h" #include "BKE_context.h" +#include "BKE_curve.h" +#include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_nla.h" #include "BKE_mask.h" @@ -121,7 +123,8 @@ void ANIM_draw_cfra(const bContext *C, View2D *v2d, short flag) { Scene *scene = CTX_data_scene(C); - const float x = (float)(scene->r.cfra * scene->r.framelen); + const float time = scene->r.cfra + scene->r.subframe; + const float x = (float)(time * scene->r.framelen); glLineWidth((flag & DRAWCFRA_WIDE) ? 3.0 : 2.0); @@ -330,7 +333,8 @@ static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag, flo fcu->prev_norm_factor = 1.0f; if (fcu->bezt) { - BezTriple *bezt; + const bool use_preview_only = PRVRANGEON; + const BezTriple *bezt; int i; float max_coord = -FLT_MAX; float min_coord = FLT_MAX; @@ -340,28 +344,77 @@ static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag, flo return 1.0f; } - if (PRVRANGEON) { - for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { - if (IN_RANGE_INCL(bezt->vec[1][0], scene->r.psfra, scene->r.pefra)) { - max_coord = max_ff(max_coord, bezt->vec[0][1]); - max_coord = max_ff(max_coord, bezt->vec[1][1]); - max_coord = max_ff(max_coord, bezt->vec[2][1]); - - min_coord = min_ff(min_coord, bezt->vec[0][1]); - min_coord = min_ff(min_coord, bezt->vec[1][1]); - min_coord = min_ff(min_coord, bezt->vec[2][1]); - } + for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { + if (use_preview_only && !IN_RANGE_INCL(bezt->vec[1][0], + scene->r.psfra, + scene->r.pefra)) + { + continue; } - } - else { - for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { - max_coord = max_ff(max_coord, bezt->vec[0][1]); + + if (i == 0) { + /* We ignore extrapolation flags and handle here, and use the + * control point position only. so we normalize "interesting" + * part of the curve. + * + * Here we handle left extrapolation. + */ max_coord = max_ff(max_coord, bezt->vec[1][1]); - max_coord = max_ff(max_coord, bezt->vec[2][1]); - min_coord = min_ff(min_coord, bezt->vec[0][1]); min_coord = min_ff(min_coord, bezt->vec[1][1]); - min_coord = min_ff(min_coord, bezt->vec[2][1]); + } + else { + const BezTriple *prev_bezt = bezt - 1; + if (prev_bezt->ipo == BEZT_IPO_CONST) { + /* Constant interpolation: previous CV value is used up + * to the current keyframe. + */ + max_coord = max_ff(max_coord, bezt->vec[1][1]); + min_coord = min_ff(min_coord, bezt->vec[1][1]); + } + else if (prev_bezt->ipo == BEZT_IPO_LIN) { + /* Linear interpolation: min/max using both previous and + * and current CV. + */ + max_coord = max_ff(max_coord, bezt->vec[1][1]); + min_coord = min_ff(min_coord, bezt->vec[1][1]); + max_coord = max_ff(max_coord, prev_bezt->vec[1][1]); + min_coord = min_ff(min_coord, prev_bezt->vec[1][1]); + } + else if (prev_bezt->ipo == BEZT_IPO_BEZ) { + const int resol = fcu->driver + ? 32 + : min_ii((int)(5.0f * len_v2v2(bezt->vec[1], prev_bezt->vec[1])), 32); + if (resol < 2) { + max_coord = max_ff(max_coord, prev_bezt->vec[1][1]); + min_coord = min_ff(min_coord, prev_bezt->vec[1][1]); + } + else { + float data[120]; + float v1[2], v2[2], v3[2], v4[2]; + + v1[0] = prev_bezt->vec[1][0]; + v1[1] = prev_bezt->vec[1][1]; + v2[0] = prev_bezt->vec[2][0]; + v2[1] = prev_bezt->vec[2][1]; + + v3[0] = bezt->vec[0][0]; + v3[1] = bezt->vec[0][1]; + v4[0] = bezt->vec[1][0]; + v4[1] = bezt->vec[1][1]; + + correct_bezpart(v1, v2, v3, v4); + + BKE_curve_forward_diff_bezier(v1[0], v2[0], v3[0], v4[0], data, resol, sizeof(float) * 3); + BKE_curve_forward_diff_bezier(v1[1], v2[1], v3[1], v4[1], data + 1, resol, sizeof(float) * 3); + + for (int j = 0; j <= resol; ++j) { + const float *fp = &data[j * 3]; + max_coord = max_ff(max_coord, fp[1]); + min_coord = min_ff(min_coord, fp[1]); + } + } + } } } diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index c0d6963acbb..bb73cbf03b4 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -95,7 +95,7 @@ static void change_frame_apply(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - int frame = RNA_int_get(op->ptr, "frame"); + float frame = RNA_float_get(op->ptr, "frame"); bool do_snap = RNA_boolean_get(op->ptr, "snap"); if (do_snap && CTX_wm_space_seq(C)) { @@ -103,10 +103,15 @@ static void change_frame_apply(bContext *C, wmOperator *op) } /* set the new frame number */ - CFRA = frame; + CFRA = (int)frame; + if (scene->r.flag & SCER_SHOW_SUBFRAME) { + SUBFRA = frame - (int)frame; + } + else { + SUBFRA = 0.0f; + } FRAMENUMBER_MIN_CLAMP(CFRA); - SUBFRA = 0.0f; - + /* do updates */ BKE_sound_seek_scene(bmain, scene); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); @@ -125,18 +130,18 @@ static int change_frame_exec(bContext *C, wmOperator *op) /* ---- */ /* Get frame from mouse coordinates */ -static int frame_from_event(bContext *C, const wmEvent *event) +static float frame_from_event(bContext *C, const wmEvent *event) { ARegion *region = CTX_wm_region(C); Scene *scene = CTX_data_scene(C); float viewx; - int frame; + float frame; /* convert from region coordinates to View2D 'tot' space */ viewx = UI_view2d_region_to_view_x(®ion->v2d, event->mval[0]); /* round result to nearest int (frames are ints!) */ - frame = iroundf(viewx); + frame = viewx; if (scene->r.flag & SCER_LOCK_FRAME_SELECTION) { CLAMP(frame, PSFRA, PEFRA); @@ -187,7 +192,7 @@ static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event * as user could click on a single frame (jump to frame) as well as * click-dragging over a range (modal scrubbing). */ - RNA_int_set(op->ptr, "frame", frame_from_event(C, event)); + RNA_float_set(op->ptr, "frame", frame_from_event(C, event)); change_frame_seq_preview_begin(C, event); @@ -215,7 +220,7 @@ static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event) break; case MOUSEMOVE: - RNA_int_set(op->ptr, "frame", frame_from_event(C, event)); + RNA_float_set(op->ptr, "frame", frame_from_event(C, event)); change_frame_apply(C, op); break; @@ -268,7 +273,7 @@ static void ANIM_OT_change_frame(wmOperatorType *ot) ot->undo_group = "FRAME_CHANGE"; /* rna */ - ot->prop = RNA_def_int(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME); + ot->prop = RNA_def_float(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME); prop = RNA_def_boolean(ot->srna, "snap", false, "Snap", ""); RNA_def_property_flag(prop, PROP_SKIP_SAVE); } diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 6b5a5d81d32..276cfb373c2 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -1196,6 +1196,11 @@ void ED_curve_editnurb_load(Object *obedit) remap_hooks_and_vertex_parents(obedit); + /* We have to apply shapekeys *before* copying nurbs into newnurb, otherwise the reset to + * refkey/original curve data that has to be done when editing non-refkey shapekey would be useless, + * only affecting editnurb and not ob->data. */ + calc_shapeKeys(obedit); + for (nu = editnurb->first; nu; nu = nu->next) { newnu = BKE_nurb_duplicate(nu); BLI_addtail(&newnurb, newnu); @@ -1207,7 +1212,6 @@ void ED_curve_editnurb_load(Object *obedit) cu->nurb = newnurb; - calc_shapeKeys(obedit); ED_curve_updateAnimPaths(obedit->data); BKE_nurbList_free(&oldnurb); @@ -1228,7 +1232,6 @@ void ED_curve_editnurb_make(Object *obedit) if (actkey) { // XXX strcpy(G.editModeTitleExtra, "(Key) "); undo_editmode_clear(); - BKE_keyblock_convert_to_curve(actkey, cu, &cu->nurb); } if (editnurb) { @@ -1249,12 +1252,16 @@ void ED_curve_editnurb_make(Object *obedit) nu = nu->next; } - if (actkey) - editnurb->shapenr = obedit->shapenr; - /* animation could be added in editmode even if there was no animdata in * object mode hence we always need CVs index be created */ init_editNurb_keyIndex(editnurb, &cu->nurb); + + if (actkey) { + editnurb->shapenr = obedit->shapenr; + /* Apply shapekey to new nurbs of editnurb, not those of original curve (and *after* we generated keyIndex), + * else we do not have valid 'original' data to properly restore curve when leaving editmode. */ + BKE_keyblock_convert_to_curve(actkey, cu, &editnurb->nurbs); + } } } diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 5b011b679a6..e118e490f25 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -953,6 +953,9 @@ static int gp_dissolve_selected_points(bContext *C) /* skip strokes that are invalid for current view */ if (ED_gpencil_stroke_can_use(C, gps) == false) continue; + /* check if the color is editable */ + if (ED_gpencil_stroke_color_use(gpl, gps) == false) + continue; if (gps->flag & GP_STROKE_SELECT) { bGPDspoint *pt; @@ -1165,6 +1168,9 @@ static int gp_delete_selected_points(bContext *C) /* skip strokes that are invalid for current view */ if (ED_gpencil_stroke_can_use(C, gps) == false) continue; + /* check if the color is editable */ + if (ED_gpencil_stroke_color_use(gpl, gps) == false) + continue; if (gps->flag & GP_STROKE_SELECT) { @@ -1204,7 +1210,7 @@ static int gp_delete_exec(bContext *C, wmOperator *op) case GP_DELETEOP_POINTS: /* selected points (breaks the stroke into segments) */ result = gp_delete_selected_points(C); break; - + case GP_DELETEOP_FRAME: /* active frame */ result = gp_actframe_delete_exec(C, op); break; diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index 8579778ff79..8420591aa3e 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -653,9 +653,9 @@ DEF_ICON(IPO_BACK) DEF_ICON(IPO_EASE_IN) DEF_ICON(IPO_EASE_OUT) DEF_ICON(IPO_EASE_IN_OUT) +DEF_ICON(NORMALIZE_FCURVES) #ifndef DEF_ICON_BLANK_SKIP /* available */ - DEF_ICON(BLANK203) DEF_ICON(BLANK204) DEF_ICON(BLANK205) DEF_ICON(BLANK206) diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index e3bad758dd7..ab71ff53731 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1596,7 +1596,7 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB temp.xmin = temp.xmax - (BLI_rcti_size_y(rect) * 1.08f); if (extra_icon_type == UI_BUT_ICONEXTRA_CLEAR) { - widget_draw_icon(but, ICON_X, alpha, &temp, false); + widget_draw_icon(but, ICON_PANEL_CLOSE, alpha, &temp, false); } else if (extra_icon_type == UI_BUT_ICONEXTRA_EYEDROPPER) { widget_draw_icon(but, ICON_EYEDROPPER, alpha, &temp, false); diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index 9097432a251..55c07140216 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -887,13 +887,13 @@ static void write_result_func(TaskPool * __restrict pool, ReportList reports; BKE_reports_init(&reports, oglrender->reports->flag & ~RPT_PRINT); /* Do actual save logic here, depending on the file format. */ + Scene tmp_scene = *scene; + tmp_scene.r.cfra = cfra; if (is_movie) { /* We have to construct temporary scene with proper scene->r.cfra. * This is because underlying calls do not use r.cfra but use scene * for that. */ - Scene tmp_scene = *scene; - tmp_scene.r.cfra = cfra; ok = RE_WriteRenderViewsMovie(&reports, rr, &tmp_scene, @@ -917,8 +917,8 @@ static void write_result_func(TaskPool * __restrict pool, true, NULL); - BKE_render_result_stamp_info(scene, scene->camera, rr, false); - ok = RE_WriteRenderViewsImage(NULL, rr, scene, true, name); + BKE_render_result_stamp_info(&tmp_scene, tmp_scene.camera, rr, false); + ok = RE_WriteRenderViewsImage(NULL, rr, &tmp_scene, true, name); if (!ok) { BKE_reportf(&reports, RPT_ERROR, diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index a48208b55f7..5605a885584 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -1258,21 +1258,6 @@ static void space_view3d_listener(bScreen *UNUSED(sc), ScrArea *sa, struct wmNot } break; } - - /* removed since BKE_image_user_frame_calc is now called in view3d_draw_bgpic because screen_ops doesnt call the notifier. */ -#if 0 - if (wmn->category == NC_SCENE && wmn->data == ND_FRAME) { - View3D *v3d = area->spacedata.first; - BGpic *bgpic = v3d->bgpicbase.first; - - for (; bgpic; bgpic = bgpic->next) { - if (bgpic->ima) { - Scene *scene = wmn->reference; - BKE_image_user_frame_calc(&bgpic->iuser, scene->r.cfra, 0); - } - } - } -#endif } const char *view3d_context_dir[] = { diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 2e95b67d508..03e0b544657 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -1051,7 +1051,6 @@ static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt) static bool snapDerivedMesh( SnapObjectContext *sctx, SnapData *snapdata, Object *ob, DerivedMesh *dm, float obmat[4][4], const unsigned int ob_index, - bool do_bb, /* read/write args */ float *ray_depth, float *dist_px, /* return args */ @@ -1112,39 +1111,31 @@ static bool snapDerivedMesh( copy_v3_v3(ray_org_local, snapdata->ray_origin); mul_m4_v3(imat, ray_org_local); - if (do_bb) { - BoundBox *bb = BKE_object_boundbox_get(ob); - - if (bb) { - BoundBox bb_temp; - - /* We cannot afford a bounding box with some null dimension, which may happen in some cases... - * Threshold is rather high, but seems to be needed to get good behavior, see T46099. */ - bb = BKE_boundbox_ensure_minimum_dimensions(bb, &bb_temp, 1e-1f); - - /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see T46816. */ - if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) { - float dist_px_sq = dist_squared_to_projected_aabb_simple( - lpmat, snapdata->win_half, ray_min_dist, snapdata->mval, - ray_org_local, ray_normal_local, bb->vec[0], bb->vec[6]); - if (dist_px_sq > SQUARE(*dist_px)) - { - return retval; - } + /* Test BoundBox */ + BoundBox *bb = BKE_object_boundbox_get(ob); + if (bb) { + /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */ + if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) { + float dist_px_sq = dist_squared_to_projected_aabb_simple( + lpmat, snapdata->win_half, ray_min_dist, snapdata->mval, + ray_org_local, ray_normal_local, bb->vec[0], bb->vec[6]); + if (dist_px_sq > SQUARE(*dist_px)) + { + return retval; } - else { - /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */ - if (!isect_ray_aabb_v3_simple( - ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], NULL, NULL)) - { - return retval; - } + } + else { + /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */ + if (!isect_ray_aabb_v3_simple( + ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], NULL, NULL)) + { + return retval; } - /* was local_depth, see: T47838 */ - len_diff = dist_aabb_to_plane(bb->vec[0], bb->vec[6], ray_start_local, ray_normal_local); - if (len_diff < 0) len_diff = 0.0f; - need_ray_start_correction_init = false; } + /* was local_depth, see: T47838 */ + len_diff = dist_aabb_to_plane(bb->vec[0], bb->vec[6], ray_start_local, ray_normal_local); + if (len_diff < 0) len_diff = 0.0f; + need_ray_start_correction_init = false; } SnapObjectData_Mesh *sod = NULL; @@ -1295,10 +1286,17 @@ static bool snapDerivedMesh( } /* SCE_SNAP_MODE_VERTEX or SCE_SNAP_MODE_EDGE */ else { + + /* Warning: the depth_max is currently being used only in perspective view. + * It is not correct to limit the maximum depth for elements obtained with nearest + * since this limitation depends on the normal and the size of the occlusion face. + * And more... ray_depth is being confused with Z-depth here... (varies only the precision) */ + const float ray_depth_max_global = *ray_depth + snapdata->depth_range[0]; + Nearest2dUserData neasrest2d = { .dist_px_sq = SQUARE(*dist_px), .r_axis_closest = {1.0f, 1.0f, 1.0f}, - .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]}, + .depth_range = {snapdata->depth_range[0], ray_depth_max_global}, .userdata = treedata, .get_edge_verts = (Nearest2DGetEdgeVertsCallback)get_dm_edge_verts, .copy_vert_no = (Nearest2DCopyVertNoCallback)copy_dm_vert_no, @@ -1650,7 +1648,6 @@ static bool snapObject( } retval = snapDerivedMesh( sctx, snapdata, ob, dm, obmat, ob_index, - true, ray_depth, dist_px, r_loc, r_no, r_index, r_hit_list); diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 085bde11619..03958b004ed 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1765,6 +1765,7 @@ typedef struct Scene { #define SCER_LOCK_FRAME_SELECTION (1<<1) /* timeline/keyframe jumping - only selected items (on by default) */ #define SCE_KEYS_NO_SELONLY (1<<2) +#define SCER_SHOW_SUBFRAME (1<<3) /* mode (int now) */ #define R_OSA 0x0001 diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index ba542a457b2..211063fa03b 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -807,6 +807,21 @@ static void rna_Scene_frame_current_set(PointerRNA *ptr, int value) data->r.cfra = value; } +static float rna_Scene_frame_float_get(PointerRNA *ptr) +{ + Scene *data = (Scene *)ptr->data; + return (float)data->r.cfra + data->r.subframe; +} + +static void rna_Scene_frame_float_set(PointerRNA *ptr, float value) +{ + Scene *data = (Scene *)ptr->data; + /* if negative frames aren't allowed, then we can't use them */ + FRAMENUMBER_MIN_CLAMP(value); + data->r.cfra = (int)value; + data->r.subframe = value - data->r.cfra; +} + static float rna_Scene_frame_current_final_get(PointerRNA *ptr) { Scene *scene = (Scene *)ptr->data; @@ -887,6 +902,12 @@ static void rna_Scene_preview_range_end_frame_set(PointerRNA *ptr, int value) data->r.pefra = value; } +static void rna_Scene_show_subframe_update(Main *UNUSED(bmain), Scene *UNUSED(current_scene), PointerRNA *ptr) +{ + Scene *scene = (Scene *)ptr->id.data; + scene->r.subframe = 0.0f; +} + static void rna_Scene_frame_update(Main *bmain, Scene *UNUSED(current_scene), PointerRNA *ptr) { Scene *scene = (Scene *)ptr->id.data; @@ -8470,8 +8491,19 @@ void RNA_def_scene(BlenderRNA *brna) prop = RNA_def_property(srna, "frame_subframe", PROP_FLOAT, PROP_TIME); RNA_def_property_float_sdna(prop, NULL, "r.subframe"); RNA_def_property_ui_text(prop, "Current Sub-Frame", ""); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); - + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.01, 2); + RNA_def_property_update(prop, NC_SCENE | ND_FRAME, "rna_Scene_frame_update"); + + prop = RNA_def_property(srna, "frame_float", PROP_FLOAT, PROP_TIME); + RNA_def_property_ui_text(prop, "Current Sub-Frame", ""); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_range(prop, MINAFRAME, MAXFRAME); + RNA_def_property_ui_range(prop, MINAFRAME, MAXFRAME, 0.1, 2); + RNA_def_property_float_funcs(prop, "rna_Scene_frame_float_get", "rna_Scene_frame_float_set", NULL); + RNA_def_property_update(prop, NC_SCENE | ND_FRAME, "rna_Scene_frame_update"); + prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_TIME); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_int_sdna(prop, NULL, "r.sfra"); @@ -8536,7 +8568,15 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_int_funcs(prop, NULL, "rna_Scene_preview_range_end_frame_set", NULL); RNA_def_property_ui_text(prop, "Preview Range End Frame", "Alternative end frame for UI playback"); RNA_def_property_update(prop, NC_SCENE | ND_FRAME, NULL); - + + /* Subframe for moblur debug. */ + prop = RNA_def_property(srna, "show_subframe", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_boolean_sdna(prop, NULL, "r.flag", SCER_SHOW_SUBFRAME); + RNA_def_property_ui_text(prop, "Show Subframe", + "Show current scene subframe and allow set it using interface tools"); + RNA_def_property_update(prop, NC_SCENE | ND_FRAME, "rna_Scene_show_subframe_update"); + /* Timeline / Time Navigation settings */ prop = RNA_def_property(srna, "show_keys_from_selected_only", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SCE_KEYS_NO_SELONLY); |