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:
@@ -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() {}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user