Geometry Nodes: extract mesh surface sampling functions to separate file

This commit is contained in:
Jacques Lucke 2021-04-21 17:02:19 +02:00
parent d5309bf4cf
commit 1dd17726f2
5 changed files with 239 additions and 94 deletions

View File

@ -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());

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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++;
}
});
}