Geometry Nodes: extract mesh surface sampling functions to separate file
This commit is contained in:
parent
d5309bf4cf
commit
1dd17726f2
|
@ -31,7 +31,7 @@ using fn::CPPType;
|
|||
* Utility function that simplifies calling a templated function based on a custom data type.
|
||||
*/
|
||||
template<typename Func>
|
||||
void convert_to_static_type(const CustomDataType data_type, const Func &func)
|
||||
inline void convert_to_static_type(const CustomDataType data_type, const Func &func)
|
||||
{
|
||||
switch (data_type) {
|
||||
case CD_PROP_FLOAT:
|
||||
|
@ -58,7 +58,8 @@ void convert_to_static_type(const CustomDataType data_type, const Func &func)
|
|||
}
|
||||
}
|
||||
|
||||
template<typename Func> void convert_to_static_type(const fn::CPPType &cpp_type, const Func &func)
|
||||
template<typename Func>
|
||||
inline void convert_to_static_type(const fn::CPPType &cpp_type, const Func &func)
|
||||
{
|
||||
if (cpp_type.is<float>()) {
|
||||
func(float());
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* 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
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#include "FN_generic_virtual_array.hh"
|
||||
|
||||
#include "BLI_float3.hh"
|
||||
|
||||
#include "BKE_attribute.h"
|
||||
|
||||
struct Mesh;
|
||||
|
||||
namespace blender::bke::mesh_surface_sample {
|
||||
|
||||
using fn::CPPType;
|
||||
using fn::GMutableSpan;
|
||||
using fn::GSpan;
|
||||
using fn::GVArray;
|
||||
|
||||
void sample_point_attribute(const Mesh &mesh,
|
||||
Span<int> looptri_indices,
|
||||
Span<float3> bary_coords,
|
||||
const GVArray &data_in,
|
||||
GMutableSpan data_out);
|
||||
|
||||
void sample_corner_attribute(const Mesh &mesh,
|
||||
Span<int> looptri_indices,
|
||||
Span<float3> bary_coords,
|
||||
const GVArray &data_in,
|
||||
GMutableSpan data_out);
|
||||
|
||||
void sample_face_attribute(const Mesh &mesh,
|
||||
Span<int> looptri_indices,
|
||||
const GVArray &data_in,
|
||||
GMutableSpan data_out);
|
||||
|
||||
} // namespace blender::bke::mesh_surface_sample
|
|
@ -190,6 +190,7 @@ set(SRC
|
|||
intern/mesh_remap.c
|
||||
intern/mesh_remesh_voxel.c
|
||||
intern/mesh_runtime.c
|
||||
intern/mesh_sample.cc
|
||||
intern/mesh_tangent.c
|
||||
intern/mesh_validate.c
|
||||
intern/mesh_validate.cc
|
||||
|
@ -379,6 +380,7 @@ set(SRC
|
|||
BKE_mesh_remap.h
|
||||
BKE_mesh_remesh_voxel.h
|
||||
BKE_mesh_runtime.h
|
||||
BKE_mesh_sample.hh
|
||||
BKE_mesh_tangent.h
|
||||
BKE_mesh_types.h
|
||||
BKE_mesh_wrapper.h
|
||||
|
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* 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 "BKE_attribute_math.hh"
|
||||
#include "BKE_mesh_runtime.h"
|
||||
#include "BKE_mesh_sample.hh"
|
||||
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
|
||||
namespace blender::bke::mesh_surface_sample {
|
||||
|
||||
static 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};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
BLI_NOINLINE static void sample_point_attribute(const Mesh &mesh,
|
||||
const Span<int> looptri_indices,
|
||||
const Span<float3> bary_coords,
|
||||
const VArray<T> &data_in,
|
||||
const MutableSpan<T> data_out)
|
||||
{
|
||||
const 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 float3 &bary_coord = bary_coords[i];
|
||||
|
||||
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 T v0 = data_in[v0_index];
|
||||
const T v1 = data_in[v1_index];
|
||||
const T v2 = data_in[v2_index];
|
||||
|
||||
const T interpolated_value = attribute_math::mix3(bary_coord, v0, v1, v2);
|
||||
data_out[i] = interpolated_value;
|
||||
}
|
||||
}
|
||||
|
||||
void sample_point_attribute(const Mesh &mesh,
|
||||
const Span<int> looptri_indices,
|
||||
const Span<float3> bary_coords,
|
||||
const GVArray &data_in,
|
||||
const GMutableSpan data_out)
|
||||
{
|
||||
BLI_assert(data_out.size() == looptri_indices.size());
|
||||
BLI_assert(data_out.size() == bary_coords.size());
|
||||
BLI_assert(data_in.size() == mesh.totvert);
|
||||
BLI_assert(data_in.type() == data_out.type());
|
||||
|
||||
const CPPType &type = data_in.type();
|
||||
attribute_math::convert_to_static_type(type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
sample_point_attribute<T>(
|
||||
mesh, looptri_indices, bary_coords, data_in.typed<T>(), data_out.typed<T>());
|
||||
});
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
BLI_NOINLINE static void sample_corner_attribute(const Mesh &mesh,
|
||||
const Span<int> looptri_indices,
|
||||
const Span<float3> bary_coords,
|
||||
const VArray<T> &data_in,
|
||||
const MutableSpan<T> data_out)
|
||||
{
|
||||
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 float3 &bary_coord = bary_coords[i];
|
||||
|
||||
const int loop_index_0 = looptri.tri[0];
|
||||
const int loop_index_1 = looptri.tri[1];
|
||||
const int loop_index_2 = looptri.tri[2];
|
||||
|
||||
const T v0 = data_in[loop_index_0];
|
||||
const T v1 = data_in[loop_index_1];
|
||||
const T v2 = data_in[loop_index_2];
|
||||
|
||||
const T interpolated_value = attribute_math::mix3(bary_coord, v0, v1, v2);
|
||||
data_out[i] = interpolated_value;
|
||||
}
|
||||
}
|
||||
|
||||
void sample_corner_attribute(const Mesh &mesh,
|
||||
const Span<int> looptri_indices,
|
||||
const Span<float3> bary_coords,
|
||||
const GVArray &data_in,
|
||||
const GMutableSpan data_out)
|
||||
{
|
||||
BLI_assert(data_out.size() == looptri_indices.size());
|
||||
BLI_assert(data_out.size() == bary_coords.size());
|
||||
BLI_assert(data_in.size() == mesh.totloop);
|
||||
BLI_assert(data_in.type() == data_out.type());
|
||||
|
||||
const CPPType &type = data_in.type();
|
||||
attribute_math::convert_to_static_type(type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
sample_corner_attribute<T>(
|
||||
mesh, looptri_indices, bary_coords, data_in.typed<T>(), data_out.typed<T>());
|
||||
});
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void sample_face_attribute(const Mesh &mesh,
|
||||
const Span<int> looptri_indices,
|
||||
const VArray<T> &data_in,
|
||||
const MutableSpan<T> data_out)
|
||||
{
|
||||
Span<MLoopTri> looptris = get_mesh_looptris(mesh);
|
||||
|
||||
for (const int i : data_out.index_range()) {
|
||||
const int looptri_index = looptri_indices[i];
|
||||
const MLoopTri &looptri = looptris[looptri_index];
|
||||
const int poly_index = looptri.poly;
|
||||
data_out[i] = data_in[poly_index];
|
||||
}
|
||||
}
|
||||
|
||||
void sample_face_attribute(const Mesh &mesh,
|
||||
const Span<int> looptri_indices,
|
||||
const GVArray &data_in,
|
||||
const GMutableSpan data_out)
|
||||
{
|
||||
BLI_assert(data_out.size() == looptri_indices.size());
|
||||
BLI_assert(data_in.size() == mesh.totpoly);
|
||||
BLI_assert(data_in.type() == data_out.type());
|
||||
|
||||
const CPPType &type = data_in.type();
|
||||
attribute_math::convert_to_static_type(type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
sample_face_attribute<T>(mesh, looptri_indices, data_in.typed<T>(), data_out.typed<T>());
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace blender::bke::mesh_surface_sample
|
|
@ -28,6 +28,7 @@
|
|||
#include "BKE_geometry_set_instances.hh"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_mesh_runtime.h"
|
||||
#include "BKE_mesh_sample.hh"
|
||||
#include "BKE_pointcloud.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
|
@ -249,99 +250,27 @@ BLI_NOINLINE static void eliminate_points_based_on_mask(Span<bool> elimination_m
|
|||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
BLI_NOINLINE static void interpolate_attribute_point(const Mesh &mesh,
|
||||
const Span<float3> bary_coords,
|
||||
const Span<int> looptri_indices,
|
||||
const Span<T> data_in,
|
||||
MutableSpan<T> data_out)
|
||||
{
|
||||
BLI_assert(data_in.size() == mesh.totvert);
|
||||
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 float3 &bary_coord = bary_coords[i];
|
||||
|
||||
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 T &v0 = data_in[v0_index];
|
||||
const T &v1 = data_in[v1_index];
|
||||
const T &v2 = data_in[v2_index];
|
||||
|
||||
const T interpolated_value = attribute_math::mix3(bary_coord, v0, v1, v2);
|
||||
data_out[i] = interpolated_value;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
BLI_NOINLINE static void interpolate_attribute_corner(const Mesh &mesh,
|
||||
const Span<float3> bary_coords,
|
||||
const Span<int> looptri_indices,
|
||||
const Span<T> data_in,
|
||||
MutableSpan<T> data_out)
|
||||
{
|
||||
BLI_assert(data_in.size() == mesh.totloop);
|
||||
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 float3 &bary_coord = bary_coords[i];
|
||||
|
||||
const int loop_index_0 = looptri.tri[0];
|
||||
const int loop_index_1 = looptri.tri[1];
|
||||
const int loop_index_2 = looptri.tri[2];
|
||||
|
||||
const T &v0 = data_in[loop_index_0];
|
||||
const T &v1 = data_in[loop_index_1];
|
||||
const T &v2 = data_in[loop_index_2];
|
||||
|
||||
const T interpolated_value = attribute_math::mix3(bary_coord, v0, v1, v2);
|
||||
data_out[i] = interpolated_value;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
BLI_NOINLINE static void interpolate_attribute_face(const Mesh &mesh,
|
||||
const Span<int> looptri_indices,
|
||||
const Span<T> data_in,
|
||||
MutableSpan<T> data_out)
|
||||
{
|
||||
BLI_assert(data_in.size() == mesh.totpoly);
|
||||
Span<MLoopTri> looptris = get_mesh_looptris(mesh);
|
||||
|
||||
for (const int i : data_out.index_range()) {
|
||||
const int looptri_index = looptri_indices[i];
|
||||
const MLoopTri &looptri = looptris[looptri_index];
|
||||
const int poly_index = looptri.poly;
|
||||
data_out[i] = data_in[poly_index];
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
BLI_NOINLINE static void interpolate_attribute(const Mesh &mesh,
|
||||
Span<float3> bary_coords,
|
||||
Span<int> looptri_indices,
|
||||
const AttributeDomain source_domain,
|
||||
Span<T> source_span,
|
||||
MutableSpan<T> output_span)
|
||||
const GVArray &source_data,
|
||||
GMutableSpan output_data)
|
||||
{
|
||||
switch (source_domain) {
|
||||
case ATTR_DOMAIN_POINT: {
|
||||
interpolate_attribute_point<T>(mesh, bary_coords, looptri_indices, source_span, output_span);
|
||||
bke::mesh_surface_sample::sample_point_attribute(
|
||||
mesh, looptri_indices, bary_coords, source_data, output_data);
|
||||
break;
|
||||
}
|
||||
case ATTR_DOMAIN_CORNER: {
|
||||
interpolate_attribute_corner<T>(
|
||||
mesh, bary_coords, looptri_indices, source_span, output_span);
|
||||
bke::mesh_surface_sample::sample_corner_attribute(
|
||||
mesh, looptri_indices, bary_coords, source_data, output_data);
|
||||
break;
|
||||
}
|
||||
case ATTR_DOMAIN_FACE: {
|
||||
interpolate_attribute_face<T>(mesh, looptri_indices, source_span, output_span);
|
||||
bke::mesh_surface_sample::sample_face_attribute(
|
||||
mesh, looptri_indices, source_data, output_data);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
@ -395,22 +324,22 @@ BLI_NOINLINE static void interpolate_existing_attributes(
|
|||
continue;
|
||||
}
|
||||
|
||||
for (const int UNUSED(i_set_instance) : set_group.transforms.index_range()) {
|
||||
const int offset = instance_start_offsets[i_instance];
|
||||
Span<float3> bary_coords = bary_coords_array[i_instance];
|
||||
Span<int> looptri_indices = looptri_indices_array[i_instance];
|
||||
|
||||
GMutableSpan instance_span = out_span.slice(offset, bary_coords.size());
|
||||
interpolate_attribute(
|
||||
mesh, bary_coords, looptri_indices, source_domain, *source_attribute, instance_span);
|
||||
|
||||
i_instance++;
|
||||
}
|
||||
|
||||
attribute_math::convert_to_static_type(output_data_type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
|
||||
GVArray_Span<T> source_span{*source_attribute};
|
||||
|
||||
for (const int UNUSED(i_set_instance) : set_group.transforms.index_range()) {
|
||||
const int offset = instance_start_offsets[i_instance];
|
||||
Span<float3> bary_coords = bary_coords_array[i_instance];
|
||||
Span<int> looptri_indices = looptri_indices_array[i_instance];
|
||||
|
||||
MutableSpan<T> instance_span = out_span.typed<T>().slice(offset, bary_coords.size());
|
||||
interpolate_attribute<T>(
|
||||
mesh, bary_coords, looptri_indices, source_domain, source_span, instance_span);
|
||||
|
||||
i_instance++;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue