Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Tönne <lukas.toenne@gmail.com>2021-06-17 10:59:51 +0300
committerLukas Tönne <lukas.toenne@gmail.com>2021-06-17 10:59:51 +0300
commitbd5b2501706d78667f1f9c28465ede64ce04cf92 (patch)
treee39e00443d29fbd265411031929832429f6791eb
parentbdf792a42190402ed945007d80d65d3a01e0f41e (diff)
Move AttributeInterpolator util class to bke.
Moved the utility class to BKE_mesh_sample. Renamed it to MeshAttributeInterpolator to make clear that it works on mesh attributes only.
-rw-r--r--source/blender/blenkernel/BKE_mesh_sample.hh42
-rw-r--r--source/blender/blenkernel/intern/mesh_sample.cc123
-rw-r--r--source/blender/nodes/CMakeLists.txt2
-rw-r--r--source/blender/nodes/geometry/node_geometry_util_interp.cc157
-rw-r--r--source/blender/nodes/geometry/node_geometry_util_interp.hh63
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_attribute_transfer.cc8
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_raycast.cc13
7 files changed, 175 insertions, 233 deletions
diff --git a/source/blender/blenkernel/BKE_mesh_sample.hh b/source/blender/blenkernel/BKE_mesh_sample.hh
index f504650e349..c40d2e947e3 100644
--- a/source/blender/blenkernel/BKE_mesh_sample.hh
+++ b/source/blender/blenkernel/BKE_mesh_sample.hh
@@ -28,6 +28,11 @@
struct Mesh;
+namespace blender::bke {
+struct ReadAttributeLookup;
+class OutputAttribute;
+} // namespace blender::bke
+
namespace blender::bke::mesh_surface_sample {
using fn::CPPType;
@@ -35,6 +40,8 @@ using fn::GMutableSpan;
using fn::GSpan;
using fn::GVArray;
+Span<MLoopTri> get_mesh_looptris(const Mesh &mesh);
+
void sample_point_attribute(const Mesh &mesh,
Span<int> looptri_indices,
Span<float3> bary_coords,
@@ -52,4 +59,39 @@ void sample_face_attribute(const Mesh &mesh,
const GVArray &data_in,
GMutableSpan data_out);
+enum class eAttributeMapMode {
+ INTERPOLATED,
+ NEAREST,
+};
+
+/**
+ * A utility class that performs attribute interpolation from a source mesh.
+ *
+ * The interpolator is only valid as long as the mesh is valid.
+ * Barycentric weights are needed when interpolating point or corner domain attributes,
+ * these are computed lazily when needed and re-used.
+ */
+class MeshAttributeInterpolator {
+ private:
+ const Mesh *mesh_;
+ const Span<float3> positions_;
+ const Span<int> looptri_indices_;
+
+ Array<float3> bary_coords_;
+ Array<float3> nearest_weights_;
+
+ public:
+ MeshAttributeInterpolator(const Mesh *mesh,
+ const Span<float3> positions,
+ const Span<int> looptri_indices);
+
+ void sample_attribute(const ReadAttributeLookup &src_attribute,
+ OutputAttribute &dst_attribute,
+ eAttributeMapMode mode);
+
+ protected:
+ Span<float3> ensure_barycentric_coords();
+ Span<float3> ensure_nearest_weights();
+};
+
} // namespace blender::bke::mesh_surface_sample
diff --git a/source/blender/blenkernel/intern/mesh_sample.cc b/source/blender/blenkernel/intern/mesh_sample.cc
index 91c9951ae89..f52098e9b40 100644
--- a/source/blender/blenkernel/intern/mesh_sample.cc
+++ b/source/blender/blenkernel/intern/mesh_sample.cc
@@ -14,6 +14,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#include "BKE_attribute_access.hh"
#include "BKE_attribute_math.hh"
#include "BKE_mesh_runtime.h"
#include "BKE_mesh_sample.hh"
@@ -23,7 +24,7 @@
namespace blender::bke::mesh_surface_sample {
-static Span<MLoopTri> get_mesh_looptris(const Mesh &mesh)
+Span<MLoopTri> get_mesh_looptris(const Mesh &mesh)
{
/* This only updates a cache and can be considered to be logically const. */
const MLoopTri *looptris = BKE_mesh_runtime_looptri_ensure(const_cast<Mesh *>(&mesh));
@@ -155,4 +156,124 @@ void sample_face_attribute(const Mesh &mesh,
});
}
+MeshAttributeInterpolator::MeshAttributeInterpolator(const Mesh *mesh,
+ const Span<float3> positions,
+ const Span<int> looptri_indices)
+ : mesh_(mesh), positions_(positions), looptri_indices_(looptri_indices)
+{
+ BLI_assert(positions.size() == looptri_indices.size());
+}
+
+Span<float3> MeshAttributeInterpolator::ensure_barycentric_coords()
+{
+ if (!bary_coords_.is_empty()) {
+ BLI_assert(bary_coords_.size() == positions_.size());
+ return bary_coords_;
+ }
+ bary_coords_.reinitialize(positions_.size());
+
+ Span<MLoopTri> looptris = get_mesh_looptris(*mesh_);
+
+ for (const int i : bary_coords_.index_range()) {
+ const int looptri_index = looptri_indices_[i];
+ const MLoopTri &looptri = looptris[looptri_index];
+
+ const int v0_index = mesh_->mloop[looptri.tri[0]].v;
+ const int v1_index = mesh_->mloop[looptri.tri[1]].v;
+ const int v2_index = mesh_->mloop[looptri.tri[2]].v;
+
+ interp_weights_tri_v3(bary_coords_[i],
+ mesh_->mvert[v0_index].co,
+ mesh_->mvert[v1_index].co,
+ mesh_->mvert[v2_index].co,
+ positions_[i]);
+ }
+ return bary_coords_;
+}
+
+Span<float3> MeshAttributeInterpolator::ensure_nearest_weights()
+{
+ if (!nearest_weights_.is_empty()) {
+ BLI_assert(nearest_weights_.size() == positions_.size());
+ return nearest_weights_;
+ }
+ nearest_weights_.reinitialize(positions_.size());
+
+ Span<MLoopTri> looptris = get_mesh_looptris(*mesh_);
+
+ for (const int i : nearest_weights_.index_range()) {
+ const int looptri_index = looptri_indices_[i];
+ const MLoopTri &looptri = looptris[looptri_index];
+
+ const int v0_index = mesh_->mloop[looptri.tri[0]].v;
+ const int v1_index = mesh_->mloop[looptri.tri[1]].v;
+ const int v2_index = mesh_->mloop[looptri.tri[2]].v;
+
+ const float d0 = len_squared_v3v3(positions_[i], mesh_->mvert[v0_index].co);
+ const float d1 = len_squared_v3v3(positions_[i], mesh_->mvert[v1_index].co);
+ const float d2 = len_squared_v3v3(positions_[i], mesh_->mvert[v2_index].co);
+
+ nearest_weights_[i] = MIN3_PAIR(d0, d1, d2, float3(1, 0, 0), float3(0, 1, 0), float3(0, 0, 1));
+ }
+ return nearest_weights_;
+}
+
+void MeshAttributeInterpolator::sample_attribute(const ReadAttributeLookup &src_attribute,
+ OutputAttribute &dst_attribute,
+ eAttributeMapMode mode)
+{
+ if (looptri_indices_.is_empty()) {
+ return;
+ }
+
+ if (!src_attribute || !dst_attribute) {
+ return;
+ }
+ const GVArray &src_varray = *src_attribute.varray;
+ GMutableSpan dst_span = dst_attribute.as_span();
+ if (src_varray.is_empty() || dst_span.is_empty()) {
+ return;
+ }
+
+ /* Compute barycentric coordinates only when they are needed. */
+ Span<float3> weights;
+ if (ELEM(src_attribute.domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_CORNER)) {
+ switch (mode) {
+ case eAttributeMapMode::INTERPOLATED:
+ weights = ensure_barycentric_coords();
+ break;
+ case eAttributeMapMode::NEAREST:
+ weights = ensure_nearest_weights();
+ break;
+ }
+ }
+
+ /* Interpolate the source attributes on the surface. */
+ switch (src_attribute.domain) {
+ case ATTR_DOMAIN_POINT: {
+ sample_point_attribute(
+ *mesh_, looptri_indices_, weights, src_varray, dst_span);
+ break;
+ }
+ case ATTR_DOMAIN_FACE: {
+ sample_face_attribute(
+ *mesh_, looptri_indices_, src_varray, dst_span);
+ break;
+ }
+ case ATTR_DOMAIN_CORNER: {
+ sample_corner_attribute(
+ *mesh_, looptri_indices_, weights, src_varray, dst_span);
+ break;
+ }
+ case ATTR_DOMAIN_EDGE: {
+ /* Not yet supported. */
+ break;
+ }
+ default: {
+ BLI_assert_unreachable();
+ break;
+ }
+ }
+}
+
} // namespace blender::bke::mesh_surface_sample
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 0674ad767b6..bc2349e8834 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -204,7 +204,6 @@ set(SRC
geometry/node_geometry_exec.cc
geometry/node_geometry_tree.cc
geometry/node_geometry_util.cc
- geometry/node_geometry_util_interp.cc
shader/nodes/node_shader_add_shader.c
shader/nodes/node_shader_ambient_occlusion.c
@@ -341,7 +340,6 @@ set(SRC
function/node_function_util.hh
shader/node_shader_util.h
geometry/node_geometry_util.hh
- geometry/node_geometry_util_interp.hh
texture/node_texture_util.h
NOD_common.h
diff --git a/source/blender/nodes/geometry/node_geometry_util_interp.cc b/source/blender/nodes/geometry/node_geometry_util_interp.cc
deleted file mode 100644
index 879442afb7a..00000000000
--- a/source/blender/nodes/geometry/node_geometry_util_interp.cc
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "node_geometry_util_interp.hh"
-
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-
-#include "BKE_mesh_runtime.h"
-#include "BKE_mesh_sample.hh"
-
-#include "NOD_geometry_exec.hh"
-
-namespace blender::nodes {
-
-Span<MLoopTri> get_mesh_looptris(const Mesh &mesh)
-{
- /* This only updates a cache and can be considered to be logically const. */
- const MLoopTri *looptris = BKE_mesh_runtime_looptri_ensure(const_cast<Mesh *>(&mesh));
- const int looptris_len = BKE_mesh_runtime_looptri_len(&mesh);
- return {looptris, looptris_len};
-}
-
-AttributeInterpolator::AttributeInterpolator(const Mesh *mesh,
- const Span<float3> positions,
- const Span<int> looptri_indices)
- : mesh_(mesh), positions_(positions), looptri_indices_(looptri_indices)
-{
- BLI_assert(positions.size() == looptri_indices.size());
-}
-
-Span<float3> AttributeInterpolator::ensure_barycentric_coords()
-{
- if (!bary_coords_.is_empty()) {
- BLI_assert(bary_coords_.size() == positions_.size());
- return bary_coords_;
- }
- bary_coords_.reinitialize(positions_.size());
-
- Span<MLoopTri> looptris = get_mesh_looptris(*mesh_);
-
- for (const int i : bary_coords_.index_range()) {
- const int looptri_index = looptri_indices_[i];
- const MLoopTri &looptri = looptris[looptri_index];
-
- const int v0_index = mesh_->mloop[looptri.tri[0]].v;
- const int v1_index = mesh_->mloop[looptri.tri[1]].v;
- const int v2_index = mesh_->mloop[looptri.tri[2]].v;
-
- interp_weights_tri_v3(bary_coords_[i],
- mesh_->mvert[v0_index].co,
- mesh_->mvert[v1_index].co,
- mesh_->mvert[v2_index].co,
- positions_[i]);
- }
- return bary_coords_;
-}
-
-Span<float3> AttributeInterpolator::ensure_nearest_weights()
-{
- if (!nearest_weights_.is_empty()) {
- BLI_assert(nearest_weights_.size() == positions_.size());
- return nearest_weights_;
- }
- nearest_weights_.reinitialize(positions_.size());
-
- Span<MLoopTri> looptris = get_mesh_looptris(*mesh_);
-
- for (const int i : nearest_weights_.index_range()) {
- const int looptri_index = looptri_indices_[i];
- const MLoopTri &looptri = looptris[looptri_index];
-
- const int v0_index = mesh_->mloop[looptri.tri[0]].v;
- const int v1_index = mesh_->mloop[looptri.tri[1]].v;
- const int v2_index = mesh_->mloop[looptri.tri[2]].v;
-
- const float d0 = len_squared_v3v3(positions_[i], mesh_->mvert[v0_index].co);
- const float d1 = len_squared_v3v3(positions_[i], mesh_->mvert[v1_index].co);
- const float d2 = len_squared_v3v3(positions_[i], mesh_->mvert[v2_index].co);
-
- nearest_weights_[i] = MIN3_PAIR(d0, d1, d2, float3(1, 0, 0), float3(0, 1, 0), float3(0, 0, 1));
- }
- return nearest_weights_;
-}
-
-void AttributeInterpolator::sample_attribute(const ReadAttributeLookup &src_attribute,
- OutputAttribute &dst_attribute,
- eAttributeMapMode mode)
-{
- if (looptri_indices_.is_empty()) {
- return;
- }
-
- if (!src_attribute || !dst_attribute) {
- return;
- }
- const GVArray &src_varray = *src_attribute.varray;
- GMutableSpan dst_span = dst_attribute.as_span();
- if (src_varray.is_empty() || dst_span.is_empty()) {
- return;
- }
-
- /* Compute barycentric coordinates only when they are needed. */
- Span<float3> weights;
- if (ELEM(src_attribute.domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_CORNER)) {
- switch (mode) {
- case eAttributeMapMode::INTERPOLATED:
- weights = ensure_barycentric_coords();
- break;
- case eAttributeMapMode::NEAREST:
- weights = ensure_nearest_weights();
- break;
- }
- }
-
- /* Interpolate the source attributes on the surface. */
- switch (src_attribute.domain) {
- case ATTR_DOMAIN_POINT: {
- bke::mesh_surface_sample::sample_point_attribute(
- *mesh_, looptri_indices_, weights, src_varray, dst_span);
- break;
- }
- case ATTR_DOMAIN_FACE: {
- bke::mesh_surface_sample::sample_face_attribute(
- *mesh_, looptri_indices_, src_varray, dst_span);
- break;
- }
- case ATTR_DOMAIN_CORNER: {
- bke::mesh_surface_sample::sample_corner_attribute(
- *mesh_, looptri_indices_, weights, src_varray, dst_span);
- break;
- }
- case ATTR_DOMAIN_EDGE: {
- /* Not yet supported. */
- break;
- }
- default: {
- BLI_assert_unreachable();
- break;
- }
- }
-}
-
-} // namespace blender::nodes
diff --git a/source/blender/nodes/geometry/node_geometry_util_interp.hh b/source/blender/nodes/geometry/node_geometry_util_interp.hh
deleted file mode 100644
index f547a010906..00000000000
--- a/source/blender/nodes/geometry/node_geometry_util_interp.hh
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#pragma once
-
-#include "BKE_attribute_access.hh"
-
-struct Mesh;
-struct MLoopTri;
-
-namespace blender::nodes {
-
-Span<MLoopTri> get_mesh_looptris(const Mesh &mesh);
-
-enum class eAttributeMapMode {
- INTERPOLATED,
- NEAREST,
-};
-
-/**
- * A utility class that performs attribute interpolation from a source mesh.
- *
- * The interpolator is only valid as long as the mesh is valid.
- * Barycentric weights are needed when interpolating point or corner domain attributes,
- * these are computed lazily when needed and re-used.
- */
-class AttributeInterpolator {
- private:
- const Mesh *mesh_;
- const Span<float3> positions_;
- const Span<int> looptri_indices_;
-
- Array<float3> bary_coords_;
- Array<float3> nearest_weights_;
-
- public:
- AttributeInterpolator(const Mesh *mesh,
- const Span<float3> positions,
- const Span<int> looptri_indices);
-
- void sample_attribute(const blender::bke::ReadAttributeLookup &src_attribute,
- blender::bke::OutputAttribute &dst_attribute,
- eAttributeMapMode mode);
-
- protected:
- Span<float3> ensure_barycentric_coords();
- Span<float3> ensure_nearest_weights();
-};
-
-} // namespace blender::nodes
diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_transfer.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_transfer.cc
index 78fb3805cf0..d1114713672 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_attribute_transfer.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_transfer.cc
@@ -28,7 +28,6 @@
#include "UI_resources.h"
#include "node_geometry_util.hh"
-#include "node_geometry_util_interp.hh"
static bNodeSocketTemplate geo_node_attribute_transfer_in[] = {
{SOCK_GEOMETRY, N_("Geometry")},
@@ -205,7 +204,7 @@ static void get_closest_mesh_polygons(const Mesh &mesh,
Array<int> looptri_indices(positions.size());
get_closest_mesh_looptris(mesh, positions, looptri_indices, r_distances_sq, r_positions);
- Span<MLoopTri> looptris = get_mesh_looptris(mesh);
+ Span<MLoopTri> looptris = bke::mesh_surface_sample::get_mesh_looptris(mesh);
for (const int i : positions.index_range()) {
const MLoopTri &looptri = looptris[looptri_indices[i]];
r_poly_indices[i] = looptri.poly;
@@ -288,8 +287,9 @@ static void transfer_attribute_nearest_face_interpolated(const GeometrySet &src_
Array<float3> positions(tot_samples);
get_closest_mesh_looptris(*mesh, dst_positions, looptri_indices, {}, positions);
- AttributeInterpolator interp(mesh, positions, looptri_indices);
- interp.sample_attribute(src_attribute, dst_attribute, eAttributeMapMode::INTERPOLATED);
+ bke::mesh_surface_sample::MeshAttributeInterpolator interp(mesh, positions, looptri_indices);
+ interp.sample_attribute(
+ src_attribute, dst_attribute, bke::mesh_surface_sample::eAttributeMapMode::INTERPOLATED);
dst_attribute.save();
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_raycast.cc b/source/blender/nodes/geometry/nodes/node_geo_raycast.cc
index 5adf137067c..f41dd5a9ca3 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_raycast.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_raycast.cc
@@ -17,12 +17,12 @@
#include "DNA_mesh_types.h"
#include "BKE_bvhutils.h"
+#include "BKE_mesh_sample.hh"
#include "UI_interface.h"
#include "UI_resources.h"
#include "node_geometry_util.hh"
-#include "node_geometry_util_interp.hh"
static bNodeSocketTemplate geo_node_raycast_in[] = {
{SOCK_GEOMETRY, N_("Geometry")},
@@ -153,14 +153,14 @@ static void raycast_to_mesh(const Mesh *mesh,
}
}
-static eAttributeMapMode get_map_mode(GeometryNodeRaycastMapMode map_mode)
+static bke::mesh_surface_sample::eAttributeMapMode get_map_mode(GeometryNodeRaycastMapMode map_mode)
{
switch (map_mode) {
case GEO_NODE_RAYCAST_INTERPOLATED:
- return eAttributeMapMode::INTERPOLATED;
+ return bke::mesh_surface_sample::eAttributeMapMode::INTERPOLATED;
default:
case GEO_NODE_RAYCAST_NEAREST:
- return eAttributeMapMode::NEAREST;
+ return bke::mesh_surface_sample::eAttributeMapMode::NEAREST;
}
}
@@ -189,7 +189,8 @@ static void raycast_from_points(const GeoNodeExecParams &params,
}
const NodeGeometryRaycast &storage = *(const NodeGeometryRaycast *)params.node().storage;
- eAttributeMapMode map_mode = get_map_mode((GeometryNodeRaycastMapMode)storage.mapping);
+ bke::mesh_surface_sample::eAttributeMapMode map_mode = get_map_mode(
+ (GeometryNodeRaycastMapMode)storage.mapping);
const AttributeDomain result_domain = ATTR_DOMAIN_POINT;
GVArray_Typed<float3> ray_origins = dst_component.attribute_get_for_read<float3>(
@@ -246,7 +247,7 @@ static void raycast_from_points(const GeoNodeExecParams &params,
hit_distance_attribute.save();
/* Custom interpolated attributes */
- AttributeInterpolator interp(src_mesh, hit_positions, hit_indices);
+ bke::mesh_surface_sample::MeshAttributeInterpolator interp(src_mesh, hit_positions, hit_indices);
for (int i = 0; i < hit_attribute_names.size(); ++i) {
const std::optional<AttributeMetaData> meta_data = src_mesh_component->attribute_get_meta_data(
hit_attribute_names[i]);