GPv3: Re-evaluate on frame change

This makes it so the `GreasePencil` geometry gets updated on a time
change.
The frame at which the object gets evaluated is stored in runtime as
`eval_frame`. This is for example used to calculate the bounding box
of the geometry as well as invalidating the batch cache for different
frames.

Pull Request: https://projects.blender.org/blender/blender/pulls/111137
This commit is contained in:
Falk David
2023-08-15 17:31:11 +02:00
committed by Falk David
parent e955c94ed3
commit 969de5135a
5 changed files with 91 additions and 41 deletions

View File

@@ -570,6 +570,8 @@ class GreasePencilRuntime {
*/
void *batch_cache = nullptr;
bke::greasepencil::StrokeCache stroke_cache;
/* The frame on which the object was evaluated (only valid for evaluated object). */
int eval_frame;
public:
GreasePencilRuntime() {}

View File

@@ -1216,6 +1216,9 @@ void BKE_grease_pencil_data_update(Depsgraph *depsgraph, Scene *scene, Object *o
* would result in a copy when it's shared. So for now, we use a const_cast here. */
GreasePencil *grease_pencil_eval = const_cast<GreasePencil *>(geometry_set.get_grease_pencil());
/* Store the frame that this grease pencil data was evaluated on. */
grease_pencil_eval->runtime->eval_frame = int(DEG_get_ctime(depsgraph));
/* Assign evaluated object. */
BKE_object_eval_assign_data(object, &grease_pencil_eval->id, false);
object->runtime.geometry_set_eval = new GeometrySet(std::move(geometry_set));
@@ -1675,8 +1678,8 @@ enum ForeachDrawingMode {
static void foreach_drawing_ex(
GreasePencil &grease_pencil,
int frame,
ForeachDrawingMode mode,
const int frame,
const ForeachDrawingMode mode,
blender::FunctionRef<void(int, blender::bke::greasepencil::Drawing &)> function)
{
using namespace blender::bke::greasepencil;
@@ -1708,19 +1711,71 @@ static void foreach_drawing_ex(
function(index, drawing->wrap());
}
else if (drawing_base->type == GP_DRAWING_REFERENCE) {
/* TODO */
/* TODO: Drawing references are not implemented yet. */
BLI_assert_unreachable();
}
}
}
static void foreach_drawing_ex(
const GreasePencil &grease_pencil,
const int frame,
const ForeachDrawingMode mode,
blender::FunctionRef<void(int, const blender::bke::greasepencil::Drawing &)> function)
{
using namespace blender::bke::greasepencil;
blender::Span<GreasePencilDrawingBase *> drawings = grease_pencil.drawings();
for (const Layer *layer : grease_pencil.layers()) {
switch (mode) {
case VISIBLE: {
if (!layer->is_visible()) {
continue;
}
break;
}
case EDITABLE: {
if (!layer->is_editable()) {
continue;
}
break;
}
}
int index = layer->drawing_index_at(frame);
if (index == -1) {
continue;
}
const GreasePencilDrawingBase *drawing_base = drawings[index];
if (drawing_base->type == GP_DRAWING) {
const GreasePencilDrawing *drawing = reinterpret_cast<const GreasePencilDrawing *>(
drawing_base);
function(index, drawing->wrap());
}
else if (drawing_base->type == GP_DRAWING_REFERENCE) {
/* TODO: Drawing references are not implemented yet. */
BLI_assert_unreachable();
}
}
}
void GreasePencil::foreach_visible_drawing(
int frame, blender::FunctionRef<void(int, blender::bke::greasepencil::Drawing &)> function)
const int frame,
blender::FunctionRef<void(int, blender::bke::greasepencil::Drawing &)> function)
{
foreach_drawing_ex(*this, frame, VISIBLE, function);
}
void GreasePencil::foreach_visible_drawing(
const int frame,
blender::FunctionRef<void(int, const blender::bke::greasepencil::Drawing &)> function) const
{
foreach_drawing_ex(*this, frame, VISIBLE, function);
}
void GreasePencil::foreach_editable_drawing(
int frame, blender::FunctionRef<void(int, blender::bke::greasepencil::Drawing &)> function)
const int frame,
blender::FunctionRef<void(int, blender::bke::greasepencil::Drawing &)> function)
{
foreach_drawing_ex(*this, frame, EDITABLE, function);
}
@@ -1728,25 +1783,13 @@ void GreasePencil::foreach_editable_drawing(
std::optional<blender::Bounds<blender::float3>> GreasePencil::bounds_min_max() const
{
using namespace blender;
/* FIXME: this should somehow go through the visible drawings. We don't have access to the
* scene time here, so we probably need to cache the visible drawing for each layer somehow. */
std::optional<Bounds<float3>> bounds;
for (int i = 0; i < this->drawing_array_num; i++) {
GreasePencilDrawingBase *drawing_base = this->drawing_array[i];
switch (drawing_base->type) {
case GP_DRAWING: {
GreasePencilDrawing *drawing = reinterpret_cast<GreasePencilDrawing *>(drawing_base);
const bke::CurvesGeometry &curves = drawing->wrap().strokes();
this->foreach_visible_drawing(
this->runtime->eval_frame,
[&](int /*drawing_index*/, const bke::greasepencil::Drawing &drawing) {
const bke::CurvesGeometry &curves = drawing.strokes();
bounds = bounds::merge(bounds, curves.bounds_min_max());
break;
}
case GP_DRAWING_REFERENCE: {
/* TODO: Calculate the bounding box of the reference drawing. */
break;
}
}
}
});
return bounds;
}

View File

@@ -2691,8 +2691,12 @@ void DepsgraphRelationBuilder::build_object_data_geometry_datablock(ID *obdata)
}
break;
}
case ID_GP:
case ID_GP: {
TimeSourceKey time_key;
ComponentKey geometry_key(obdata, NodeType::GEOMETRY);
add_relation(time_key, geometry_key, "Grease Pencil Frame Change");
break;
}
default:
BLI_assert_msg(0, "Should not happen");
break;

View File

@@ -96,16 +96,16 @@ static GPUVertFormat *grease_pencil_color_format()
/** \name Internal Utilities
* \{ */
static bool grease_pencil_batch_cache_valid(const GreasePencil &grease_pencil, int cfra)
static bool grease_pencil_batch_cache_valid(const GreasePencil &grease_pencil)
{
BLI_assert(grease_pencil.runtime != nullptr);
const GreasePencilBatchCache *cache = static_cast<GreasePencilBatchCache *>(
grease_pencil.runtime->batch_cache);
return (cache && cache->is_dirty == false && cache->cache_frame == cfra);
return (cache && cache->is_dirty == false &&
cache->cache_frame == grease_pencil.runtime->eval_frame);
}
static GreasePencilBatchCache *grease_pencil_batch_cache_init(GreasePencil &grease_pencil,
int cfra)
static GreasePencilBatchCache *grease_pencil_batch_cache_init(GreasePencil &grease_pencil)
{
BLI_assert(grease_pencil.runtime != nullptr);
GreasePencilBatchCache *cache = static_cast<GreasePencilBatchCache *>(
@@ -119,7 +119,7 @@ static GreasePencilBatchCache *grease_pencil_batch_cache_init(GreasePencil &grea
}
cache->is_dirty = false;
cache->cache_frame = cfra;
cache->cache_frame = grease_pencil.runtime->eval_frame;
return cache;
}
@@ -145,14 +145,14 @@ static void grease_pencil_batch_cache_clear(GreasePencil &grease_pencil)
cache->is_dirty = true;
}
static GreasePencilBatchCache *grease_pencil_batch_cache_get(GreasePencil &grease_pencil, int cfra)
static GreasePencilBatchCache *grease_pencil_batch_cache_get(GreasePencil &grease_pencil)
{
BLI_assert(grease_pencil.runtime != nullptr);
GreasePencilBatchCache *cache = static_cast<GreasePencilBatchCache *>(
grease_pencil.runtime->batch_cache);
if (!grease_pencil_batch_cache_valid(grease_pencil, cfra)) {
if (!grease_pencil_batch_cache_valid(grease_pencil)) {
grease_pencil_batch_cache_clear(grease_pencil);
return grease_pencil_batch_cache_init(grease_pencil, cfra);
return grease_pencil_batch_cache_init(grease_pencil);
}
return cache;
@@ -517,11 +517,9 @@ void DRW_grease_pencil_batch_cache_validate(GreasePencil *grease_pencil)
{
using namespace blender::draw;
BLI_assert(grease_pencil->runtime != nullptr);
/* TODO: pass correct frame here? */
if (!grease_pencil_batch_cache_valid(*grease_pencil, 0)) {
if (!grease_pencil_batch_cache_valid(*grease_pencil)) {
grease_pencil_batch_cache_clear(*grease_pencil);
/* TODO: pass correct frame here? */
grease_pencil_batch_cache_init(*grease_pencil, 0);
grease_pencil_batch_cache_init(*grease_pencil);
}
}
@@ -537,7 +535,7 @@ GPUBatch *DRW_cache_grease_pencil_get(Object *ob, int cfra)
{
using namespace blender::draw;
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob->data);
GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil, cfra);
GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil);
grease_pencil_geom_batch_ensure(grease_pencil, cfra);
return cache->geom_batch;
@@ -547,7 +545,7 @@ GPUBatch *DRW_cache_grease_pencil_edit_points_get(Object *ob, int cfra)
{
using namespace blender::draw;
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob->data);
GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil, cfra);
GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil);
grease_pencil_geom_batch_ensure(grease_pencil, cfra);
return cache->edit_points;
@@ -557,7 +555,7 @@ GPUVertBuf *DRW_cache_grease_pencil_position_buffer_get(Object *ob, int cfra)
{
using namespace blender::draw;
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob->data);
GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil, cfra);
GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil);
grease_pencil_geom_batch_ensure(grease_pencil, cfra);
return cache->vbo;
@@ -567,7 +565,7 @@ GPUVertBuf *DRW_cache_grease_pencil_color_buffer_get(Object *ob, int cfra)
{
using namespace blender::draw;
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob->data);
GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil, cfra);
GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil);
grease_pencil_geom_batch_ensure(grease_pencil, cfra);
return cache->vbo_col;

View File

@@ -525,9 +525,12 @@ typedef struct GreasePencil {
const blender::bke::greasepencil::Layer *layer, int frame_number) const;
void foreach_visible_drawing(
int frame, blender::FunctionRef<void(int, blender::bke::greasepencil::Drawing &)> function);
const int frame, blender::FunctionRef<void(int, blender::bke::greasepencil::Drawing &)> function);
void foreach_visible_drawing(
const int frame,
blender::FunctionRef<void(int, const blender::bke::greasepencil::Drawing &)> function) const;
void foreach_editable_drawing(
int frame, blender::FunctionRef<void(int, blender::bke::greasepencil::Drawing &)> function);
const int frame, blender::FunctionRef<void(int, blender::bke::greasepencil::Drawing &)> function);
std::optional<blender::Bounds<blender::float3>> bounds_min_max() const;