Geometry: Skip recomputing bounds after translation #106159

Merged
Hans Goudey merged 1 commits from HooglyBoogly/blender:geometry-bounds-skip-translate into main 2023-03-27 20:51:14 +02:00
3 changed files with 62 additions and 21 deletions

View File

@ -1037,6 +1037,15 @@ void CurvesGeometry::calculate_bezier_auto_handles()
void CurvesGeometry::translate(const float3 &translation)
{
if (math::is_zero(translation)) {
return;
}
std::optional<Bounds<float3>> bounds;
if (this->runtime->bounds_cache.is_cached()) {
bounds = this->runtime->bounds_cache.data();
}
translate_positions(this->positions_for_write(), translation);
if (!this->handle_positions_left().is_empty()) {
translate_positions(this->handle_positions_left_for_write(), translation);
@ -1045,6 +1054,12 @@ void CurvesGeometry::translate(const float3 &translation)
translate_positions(this->handle_positions_right_for_write(), translation);
}
this->tag_positions_changed();
if (bounds) {
bounds->min += translation;
bounds->max += translation;
this->runtime->bounds_cache.ensure([&](blender::Bounds<float3> &r_data) { r_data = *bounds; });
}
}
void CurvesGeometry::transform(const float4x4 &matrix)

View File

@ -1582,23 +1582,42 @@ void BKE_mesh_transform(Mesh *me, const float mat[4][4], bool do_keys)
BKE_mesh_tag_positions_changed(me);
}
void BKE_mesh_translate(Mesh *me, const float offset[3], const bool do_keys)
static void translate_positions(MutableSpan<float3> positions, const float3 &translation)
{
MutableSpan<float3> positions = me->vert_positions_for_write();
for (float3 &position : positions) {
position += offset;
using namespace blender;
threading::parallel_for(positions.index_range(), 2048, [&](const IndexRange range) {
for (float3 &position : positions.slice(range)) {
position += translation;
}
});
}
void BKE_mesh_translate(Mesh *mesh, const float offset[3], const bool do_keys)
{
using namespace blender;
if (math::is_zero(float3(offset))) {
return;
}
int i;
if (do_keys && me->key) {
LISTBASE_FOREACH (KeyBlock *, kb, &me->key->block) {
float *fp = (float *)kb->data;
for (i = kb->totelem; i--; fp += 3) {
add_v3_v3(fp, offset);
}
std::optional<Bounds<float3>> bounds;
if (mesh->runtime->bounds_cache.is_cached()) {
bounds = mesh->runtime->bounds_cache.data();
}
translate_positions(mesh->vert_positions_for_write(), offset);
if (do_keys && mesh->key) {
LISTBASE_FOREACH (KeyBlock *, kb, &mesh->key->block) {
translate_positions({static_cast<float3 *>(kb->data), kb->totelem}, offset);
}
}
BKE_mesh_tag_positions_changed_uniformly(me);
BKE_mesh_tag_positions_changed_uniformly(mesh);
if (bounds) {
bounds->min += offset;
bounds->max += offset;
mesh->bounds_set_eager(*bounds);
}
}
void BKE_mesh_tessface_clear(Mesh *mesh)

View File

@ -54,14 +54,6 @@ static void transform_positions(MutableSpan<float3> positions, const float4x4 &m
});
}
static void translate_mesh(Mesh &mesh, const float3 translation)
{
if (!math::is_zero(translation)) {
translate_positions(mesh.vert_positions_for_write(), translation);
BKE_mesh_tag_positions_changed_uniformly(&mesh);
}
}
static void transform_mesh(Mesh &mesh, const float4x4 &transform)
{
transform_positions(mesh.vert_positions_for_write(), transform);
@ -70,11 +62,26 @@ static void transform_mesh(Mesh &mesh, const float4x4 &transform)
static void translate_pointcloud(PointCloud &pointcloud, const float3 translation)
{
if (math::is_zero(translation)) {
return;
}
std::optional<Bounds<float3>> bounds;
if (pointcloud.runtime->bounds_cache.is_cached()) {
bounds = pointcloud.runtime->bounds_cache.data();
}
MutableAttributeAccessor attributes = pointcloud.attributes_for_write();
SpanAttributeWriter position = attributes.lookup_or_add_for_write_span<float3>(
"position", ATTR_DOMAIN_POINT);
translate_positions(position.span, translation);
position.finish();
if (bounds) {
bounds->min += translation;
bounds->max += translation;
pointcloud.runtime->bounds_cache.ensure([&](Bounds<float3> &r_data) { r_data = *bounds; });
}
}
static void transform_pointcloud(PointCloud &pointcloud, const float4x4 &transform)
@ -199,7 +206,7 @@ static void translate_geometry_set(GeoNodeExecParams &params,
curves->geometry.wrap().translate(translation);
}
if (Mesh *mesh = geometry.get_mesh_for_write()) {
translate_mesh(*mesh, translation);
BKE_mesh_translate(mesh, translation, false);
}
if (PointCloud *pointcloud = geometry.get_pointcloud_for_write()) {
translate_pointcloud(*pointcloud, translation);