GPv3: Initial Geometry Nodes support #112535

Merged
Falk David merged 61 commits from filedescriptor/blender:gpv3-geometry-nodes into main 2023-10-10 16:49:39 +02:00
4 changed files with 17 additions and 62 deletions
Showing only changes of commit 28a9ff0900 - Show all commits

View File

@ -119,8 +119,8 @@ class InstancesFieldContext : public fn::FieldContext {
};
/**
* A field context that can represent meshes, curves, point clouds, or instances,
* used for field inputs that can work for multiple geometry types.
* A field context that can represent meshes, curves, point clouds, instances or grease pencil
* layers, used for field inputs that can work for multiple geometry types.
*/
class GeometryFieldContext : public fn::FieldContext {
private:
@ -132,6 +132,8 @@ class GeometryFieldContext : public fn::FieldContext {
const void *geometry_;
const GeometryComponent::Type type_;
const eAttrDomain domain_;
/** Only used when the type is grease pencil and the domain is either points or curves
filedescriptor marked this conversation as resolved Outdated
  /** 
   * Only used when the type is grease pencil and the domain is either points or curves
   * (not layers).
   */
``` /** * Only used when the type is grease pencil and the domain is either points or curves * (not layers). */
* (not layers). */
int grease_pencil_layer_index_;
friend GeometryFieldInput;
@ -222,16 +224,6 @@ class PointCloudFieldInput : public fn::FieldInput {
const IndexMask &mask) const = 0;
};
class GreasePencilFieldInput : public fn::FieldInput {
public:
using fn::FieldInput::FieldInput;
GVArray get_varray_for_context(const fn::FieldContext &context,
const IndexMask &mask,
ResourceScope &scope) const override;
virtual GVArray get_varray_for_context(const GreasePencil &grease_pencil,
const IndexMask &mask) const = 0;
};
class InstancesFieldInput : public fn::FieldInput {
public:
using fn::FieldInput::FieldInput;

View File

@ -121,26 +121,14 @@ static ComponentAttributeProviders create_attribute_providers_for_grease_pencil(
return ComponentAttributeProviders({}, {&layer_custom_data});
}
static GVArray adapt_grease_pencil_attribute_domain(const GreasePencil &grease_pencil,
static GVArray adapt_grease_pencil_attribute_domain(const GreasePencil & /*grease_pencil*/,
const GVArray &varray,
const eAttrDomain from,
const eAttrDomain to)
{
if (!varray) {
return {};
}
if (varray.is_empty()) {
return {};
}
if (from == to) {
return varray;
}
if (varray.is_single()) {
BUFFER_FOR_CPP_TYPE_VALUE(varray.type(), value);
varray.get_internal_single(value);
return GVArray::ForSingle(varray.type(), grease_pencil.attributes().domain_size(to), value);
}
return {};
}
@ -211,4 +199,4 @@ std::optional<MutableAttributeAccessor> GreasePencilComponent::attributes_for_wr
return MutableAttributeAccessor(grease_pencil, get_grease_pencil_accessor_functions_ref());
}
} // namespace blender::bke
} // namespace blender::bke

View File

@ -321,25 +321,6 @@ GVArray PointCloudFieldInput::get_varray_for_context(const fn::FieldContext &con
return {};
}
GVArray GreasePencilFieldInput::get_varray_for_context(const fn::FieldContext &context,
const IndexMask &mask,
ResourceScope & /*scope*/) const
{
if (const GeometryFieldContext *geometry_context = dynamic_cast<const GeometryFieldContext *>(
&context))
{
if (const GreasePencil *grease_pencil = geometry_context->grease_pencil()) {
return this->get_varray_for_context(*grease_pencil, mask);
}
}
if (const GreasePencilLayerFieldContext *grease_pencil_context =
dynamic_cast<const GreasePencilLayerFieldContext *>(&context))
{
return this->get_varray_for_context(grease_pencil_context->grease_pencil(), mask);
}
return {};
}
GVArray InstancesFieldInput::get_varray_for_context(const fn::FieldContext &context,
const IndexMask &mask,
ResourceScope & /*scope*/) const
@ -375,6 +356,7 @@ GVArray AttributeFieldInput::get_varray_for_context(const GeometryFieldContext &
if (const GAttributeReader reader = curves_attributes.lookup(name_, domain, data_type)) {
return *reader;
}
/* Lookup attribute on the layer domain if it does not exist on points or curves. */
if (const GAttributeReader reader = layer_attributes.lookup(name_)) {
const CPPType &cpp_type = reader.varray.type();
BUFFER_FOR_CPP_TYPE_VALUE(cpp_type, value);
@ -689,6 +671,7 @@ bool try_capture_field_on_geometry(GeometryComponent &component,
if (component.type() == GeometryComponent::Type::GreasePencil &&
ELEM(domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE))
{
/* Capture the field on every layer individually. */
auto &grease_pencil_component = static_cast<GreasePencilComponent &>(component);
GreasePencil *grease_pencil = grease_pencil_component.get_for_write();
if (grease_pencil == nullptr) {

View File

@ -115,24 +115,15 @@ static void set_position_in_grease_pencil(GreasePencil &grease_pencil,
const Field<float3> &offset_field)
{
using namespace blender::bke::greasepencil;
const GrainSize grain_size{10000};
blender::Span<GreasePencilDrawingBase *> drawings = grease_pencil.drawings();
for (const int layer_index : grease_pencil.layers().index_range()) {
const Layer *layer = grease_pencil.layers()[layer_index];
int drawing_index = layer->drawing_index_at(grease_pencil.runtime->eval_frame);
if (drawing_index == -1) {
Drawing *drawing = bke::get_eval_grease_pencil_layer_drawing_for_write(grease_pencil,
layer_index);
if (drawing == nullptr) {
continue;
}
GreasePencilDrawingBase *drawing_base = drawings[drawing_index];
if (drawing_base->type != GP_DRAWING) {
continue;
}
Drawing &drawing = reinterpret_cast<GreasePencilDrawing *>(drawing_base)->wrap();
bke::GreasePencilLayerFieldContext field_context(
grease_pencil, ATTR_DOMAIN_POINT, layer_index);
fn::FieldEvaluator evaluator{field_context, drawing.strokes().points_num()};
fn::FieldEvaluator evaluator{field_context, drawing->strokes().points_num()};
evaluator.set_selection(selection_field);
evaluator.add(position_field);
evaluator.add(offset_field);
@ -146,12 +137,13 @@ static void set_position_in_grease_pencil(GreasePencil &grease_pencil,
const VArray<float3> positions_input = evaluator.get_evaluated<float3>(0);
const VArray<float3> offsets_input = evaluator.get_evaluated<float3>(1);
MutableSpan<float3> positions = drawing.strokes_for_write().positions_for_write();
MutableSpan<float3> positions = drawing->strokes_for_write().positions_for_write();
selection.foreach_index_optimized<int>(
grain_size, [&](const int i) { positions[i] = positions_input[i] + offsets_input[i]; });
selection.foreach_index_optimized<int>(GrainSize(4096), [&](const int i) {
positions[i] = positions_input[i] + offsets_input[i];
});
drawing.tag_positions_changed();
drawing->tag_positions_changed();
}
}