GPv3: Add support for transform object origin.

Implements support for `transform only origins`.

Pull Request: https://projects.blender.org/blender/blender/pulls/126446
This commit is contained in:
casey bianco-davis
2024-09-13 17:06:43 +02:00
committed by Falk David
parent ffb5226944
commit 50770bd8f5
3 changed files with 190 additions and 0 deletions

View File

@@ -1045,6 +1045,34 @@ void BKE_grease_pencil_data_update(Depsgraph *depsgraph, Scene *scene, Object *o
void BKE_grease_pencil_duplicate_drawing_array(const GreasePencil *grease_pencil_src,
GreasePencil *grease_pencil_dst);
typedef struct GreasePencilPointCoordinates {
/* This is used when doing "move only origin" in object_data_transform.cc.
* radius is needs to be stored here as it is tied to object scale. */
float co[3];
float radius;
} GreasePencilPointCoordinates;
/**
* \note Used for "move only origins" in object_data_transform.cc.
*/
int BKE_grease_pencil_stroke_point_count(const GreasePencil &grease_pencil);
/**
* \note Used for "move only origins" in object_data_transform.cc.
*/
void BKE_grease_pencil_point_coords_get(const GreasePencil &grease_pencil,
GreasePencilPointCoordinates *elem_data);
/**
* \note Used for "move only origins" in object_data_transform.cc.
*/
void BKE_grease_pencil_point_coords_apply(GreasePencil &grease_pencil,
GreasePencilPointCoordinates *elem_data);
/**
* \note Used for "move only origins" in object_data_transform.cc.
*/
void BKE_grease_pencil_point_coords_apply_with_mat4(GreasePencil &grease_pencil,
GreasePencilPointCoordinates *elem_data,
const blender::float4x4 &mat);
int BKE_grease_pencil_object_material_index_get_by_name(Object *ob, const char *name);
Material *BKE_grease_pencil_object_material_new(Main *bmain,
Object *ob,

View File

@@ -1958,6 +1958,132 @@ void BKE_grease_pencil_duplicate_drawing_array(const GreasePencil *grease_pencil
/** \} */
/* ------------------------------------------------------------------- */
/** \name Grease Pencil origin functions
* \note Used for "move only origins" in object_data_transform.cc.
* \{ */
int BKE_grease_pencil_stroke_point_count(const GreasePencil &grease_pencil)
{
using namespace blender;
int total_points = 0;
for (const int layer_i : grease_pencil.layers().index_range()) {
const bke::greasepencil::Layer &layer = *grease_pencil.layer(layer_i);
const Map<bke::greasepencil::FramesMapKeyT, GreasePencilFrame> frames = layer.frames();
frames.foreach_item(
[&](const bke::greasepencil::FramesMapKeyT /*key*/, const GreasePencilFrame frame) {
const GreasePencilDrawingBase *base = grease_pencil.drawing(frame.drawing_index);
if (base->type != GP_DRAWING) {
return;
}
const bke::greasepencil::Drawing &drawing =
reinterpret_cast<const GreasePencilDrawing *>(base)->wrap();
const bke::CurvesGeometry &curves = drawing.strokes();
total_points += curves.points_num();
});
}
return total_points;
}
void BKE_grease_pencil_point_coords_get(const GreasePencil &grease_pencil,
GreasePencilPointCoordinates *elem_data)
{
using namespace blender;
for (const int layer_i : grease_pencil.layers().index_range()) {
const bke::greasepencil::Layer &layer = *grease_pencil.layer(layer_i);
const float4x4 layer_to_object = layer.local_transform();
const float4x4 object_to_layer = math::invert(layer_to_object);
const Map<bke::greasepencil::FramesMapKeyT, GreasePencilFrame> frames = layer.frames();
frames.foreach_item(
[&](const bke::greasepencil::FramesMapKeyT /*key*/, const GreasePencilFrame frame) {
const GreasePencilDrawingBase *base = grease_pencil.drawing(frame.drawing_index);
if (base->type != GP_DRAWING) {
return;
}
const bke::greasepencil::Drawing &drawing =
reinterpret_cast<const GreasePencilDrawing *>(base)->wrap();
const bke::CurvesGeometry &curves = drawing.strokes();
const Span<float3> positions = curves.positions();
const VArray<float> radii = drawing.radii();
for (const int i : curves.points_range()) {
copy_v3_v3(elem_data->co, math::transform_point(layer_to_object, positions[i]));
elem_data->radius = radii[i];
elem_data++;
}
});
}
}
void BKE_grease_pencil_point_coords_apply(GreasePencil &grease_pencil,
GreasePencilPointCoordinates *elem_data)
{
using namespace blender;
for (const int layer_i : grease_pencil.layers().index_range()) {
bke::greasepencil::Layer &layer = *grease_pencil.layer(layer_i);
const float4x4 layer_to_object = layer.local_transform();
const float4x4 object_to_layer = math::invert(layer_to_object);
const Map<bke::greasepencil::FramesMapKeyT, GreasePencilFrame> frames = layer.frames();
frames.foreach_item([&](bke::greasepencil::FramesMapKeyT /*key*/, GreasePencilFrame frame) {
GreasePencilDrawingBase *base = grease_pencil.drawing(frame.drawing_index);
if (base->type != GP_DRAWING) {
return;
}
bke::greasepencil::Drawing &drawing = reinterpret_cast<GreasePencilDrawing *>(base)->wrap();
bke::CurvesGeometry &curves = drawing.strokes_for_write();
MutableSpan<float3> positions = curves.positions_for_write();
MutableSpan<float> radii = drawing.radii_for_write();
for (const int i : curves.points_range()) {
positions[i] = math::transform_point(object_to_layer, float3(elem_data->co));
radii[i] = elem_data->radius;
elem_data++;
}
});
}
}
void BKE_grease_pencil_point_coords_apply_with_mat4(GreasePencil &grease_pencil,
GreasePencilPointCoordinates *elem_data,
const blender::float4x4 &mat)
{
using namespace blender;
const float scalef = mat4_to_scale(mat.ptr());
for (const int layer_i : grease_pencil.layers().index_range()) {
bke::greasepencil::Layer &layer = *grease_pencil.layer(layer_i);
const float4x4 layer_to_object = layer.local_transform();
const float4x4 object_to_layer = math::invert(layer_to_object);
const Map<bke::greasepencil::FramesMapKeyT, GreasePencilFrame> frames = layer.frames();
frames.foreach_item([&](bke::greasepencil::FramesMapKeyT /*key*/, GreasePencilFrame frame) {
GreasePencilDrawingBase *base = grease_pencil.drawing(frame.drawing_index);
if (base->type != GP_DRAWING) {
return;
}
bke::greasepencil::Drawing &drawing = reinterpret_cast<GreasePencilDrawing *>(base)->wrap();
bke::CurvesGeometry &curves = drawing.strokes_for_write();
MutableSpan<float3> positions = curves.positions_for_write();
MutableSpan<float> radii = drawing.radii_for_write();
for (const int i : curves.points_range()) {
positions[i] = math::transform_point(object_to_layer * mat, float3(elem_data->co));
radii[i] = elem_data->radius * scalef;
elem_data++;
}
});
}
}
/** \} */
/* ------------------------------------------------------------------- */
/** \name Grease Pencil material functions
* \{ */

View File

@@ -32,6 +32,7 @@
#include "BKE_curve.hh"
#include "BKE_editmesh.hh"
#include "BKE_gpencil_geom_legacy.h"
#include "BKE_grease_pencil.hh"
#include "BKE_key.hh"
#include "BKE_lattice.hh"
#include "BKE_mball.hh"
@@ -302,6 +303,11 @@ struct XFormObjectData_GPencil {
GPencilPointCoordinates elem_array[0];
};
struct XFormObjectData_GreasePencil {
struct XFormObjectData base;
struct GreasePencilPointCoordinates elem_array[0];
};
XFormObjectData *data_xform_create_ex(ID *id, bool is_edit_mode)
{
XFormObjectData *xod_base = nullptr;
@@ -474,6 +480,17 @@ XFormObjectData *data_xform_create_ex(ID *id, bool is_edit_mode)
xod_base = &xod->base;
break;
}
case ID_GP: {
GreasePencil *grease_pencil = (GreasePencil *)id;
const int elem_array_len = BKE_grease_pencil_stroke_point_count(*grease_pencil);
XFormObjectData_GreasePencil *xod = static_cast<XFormObjectData_GreasePencil *>(
MEM_mallocN(sizeof(*xod) + (sizeof(*xod->elem_array) * elem_array_len), __func__));
memset(xod, 0x0, sizeof(*xod));
BKE_grease_pencil_point_coords_get(*grease_pencil, xod->elem_array);
xod_base = &xod->base;
break;
}
default: {
break;
}
@@ -638,6 +655,13 @@ void data_xform_by_mat4(XFormObjectData *xod_base, const float mat[4][4])
BKE_gpencil_point_coords_apply_with_mat4(gpd, xod->elem_array, mat);
break;
}
case ID_GP: {
GreasePencil *grease_pencil = (GreasePencil *)xod_base->id;
XFormObjectData_GreasePencil *xod = (XFormObjectData_GreasePencil *)xod_base;
BKE_grease_pencil_point_coords_apply_with_mat4(
*grease_pencil, xod->elem_array, float4x4(mat));
break;
}
default: {
break;
}
@@ -739,6 +763,12 @@ void data_xform_restore(XFormObjectData *xod_base)
BKE_gpencil_point_coords_apply(gpd, xod->elem_array);
break;
}
case ID_GP: {
GreasePencil *grease_pencil = (GreasePencil *)xod_base->id;
XFormObjectData_GreasePencil *xod = (XFormObjectData_GreasePencil *)xod_base;
BKE_grease_pencil_point_coords_apply(*grease_pencil, xod->elem_array);
break;
}
default: {
break;
}
@@ -791,6 +821,12 @@ void data_xform_tag_update(XFormObjectData *xod_base)
DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_SYNC_TO_EVAL);
break;
}
case ID_GP: {
/* Generic update. */
GreasePencil *grease_pencil = (GreasePencil *)xod_base->id;
DEG_id_tag_update(&grease_pencil->id, ID_RECALC_GEOMETRY | ID_RECALC_SYNC_TO_EVAL);
break;
}
default: {
break;