Core: Use VectorList for duplilists
Replace Listbase with a VectorList for duplist generation. Performing one heap allocation for each dupli becomes very costly on scenes with many instances. Using a VectorList can make playback up to 15% faster. Most scenes will have lower performance improvements, but none of the ones I tested were slower. VectorLists also have the advantage of being able to query the size of the duplilist. Pull Request: https://projects.blender.org/blender/blender/pulls/138947
This commit is contained in:
@@ -8,6 +8,8 @@
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#include "BLI_vector_list.hh"
|
||||
|
||||
#include "BKE_geometry_set.hh"
|
||||
#include "BKE_instances.hh"
|
||||
|
||||
@@ -23,42 +25,9 @@ struct ViewerPath;
|
||||
/* ---------------------------------------------------- */
|
||||
/* Dupli-Geometry */
|
||||
|
||||
/**
|
||||
* \return a #ListBase of #DupliObject.
|
||||
*/
|
||||
ListBase *object_duplilist(Depsgraph *depsgraph,
|
||||
Scene *sce,
|
||||
Object *ob,
|
||||
blender::Set<const Object *> *include_objects = nullptr);
|
||||
/**
|
||||
* \return a #ListBase of #DupliObject for the preview geometry referenced by the #ViewerPath.
|
||||
*/
|
||||
ListBase *object_duplilist_preview(Depsgraph *depsgraph,
|
||||
Scene *scene,
|
||||
Object *ob,
|
||||
const ViewerPath *viewer_path);
|
||||
void free_object_duplilist(ListBase *lb);
|
||||
|
||||
/**
|
||||
* Get the legacy instances of this object. That includes instances coming from these sources:
|
||||
* - Particles
|
||||
* - Dupli Verts
|
||||
* - Dupli Faces
|
||||
* - "Objects as Font"
|
||||
*
|
||||
* This does not include collection instances which are not considered legacy and should be treated
|
||||
* properly at a higher level.
|
||||
*
|
||||
* Also see #get_dupli_generator for the different existing dupli generators.
|
||||
*/
|
||||
blender::bke::Instances object_duplilist_legacy_instances(Depsgraph &depsgraph,
|
||||
Scene &scene,
|
||||
Object &ob);
|
||||
|
||||
constexpr int MAX_DUPLI_RECUR = 8;
|
||||
|
||||
struct DupliObject {
|
||||
DupliObject *next, *prev;
|
||||
/* Object whose geometry is instanced. */
|
||||
Object *ob;
|
||||
/* Data owned by the object above that is instanced. This might not be the same as `ob->data`. */
|
||||
@@ -97,6 +66,41 @@ struct DupliObject {
|
||||
unsigned int random_id;
|
||||
};
|
||||
|
||||
using DupliList = blender::VectorList<DupliObject>;
|
||||
|
||||
/**
|
||||
* Fill a Vector of #DupliObject.
|
||||
*/
|
||||
void object_duplilist(Depsgraph *depsgraph,
|
||||
Scene *sce,
|
||||
Object *ob,
|
||||
blender::Set<const Object *> *include_objects,
|
||||
DupliList &r_duplilist);
|
||||
/**
|
||||
* Fill a Vector of #DupliObject for the preview geometry referenced by the #ViewerPath.
|
||||
*/
|
||||
void object_duplilist_preview(Depsgraph *depsgraph,
|
||||
Scene *scene,
|
||||
Object *ob,
|
||||
const ViewerPath *viewer_path,
|
||||
DupliList &r_duplilist);
|
||||
|
||||
/**
|
||||
* Get the legacy instances of this object. That includes instances coming from these sources:
|
||||
* - Particles
|
||||
* - Dupli Verts
|
||||
* - Dupli Faces
|
||||
* - "Objects as Font"
|
||||
*
|
||||
* This does not include collection instances which are not considered legacy and should be treated
|
||||
* properly at a higher level.
|
||||
*
|
||||
* Also see #get_dupli_generator for the different existing dupli generators.
|
||||
*/
|
||||
blender::bke::Instances object_duplilist_legacy_instances(Depsgraph &depsgraph,
|
||||
Scene &scene,
|
||||
Object &ob);
|
||||
|
||||
/**
|
||||
* Look up the RGBA value of a uniform shader attribute.
|
||||
* \return true if the attribute was found; if not, r_value is also set to zero.
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
|
||||
#include "BLI_sys_types.h"
|
||||
|
||||
#include "BKE_duplilist.hh"
|
||||
|
||||
struct Base;
|
||||
struct Collection;
|
||||
struct Depsgraph;
|
||||
struct DupliObject;
|
||||
struct GHash;
|
||||
struct Main;
|
||||
struct ListBase;
|
||||
struct Object;
|
||||
struct RenderData;
|
||||
struct Scene;
|
||||
@@ -73,8 +73,9 @@ Object *BKE_scene_object_find_by_name(const Scene *scene, const char *name);
|
||||
* Define struct here, so no need to bother with alloc/free it.
|
||||
*/
|
||||
struct SceneBaseIter {
|
||||
ListBase *duplilist;
|
||||
DupliList duplilist;
|
||||
DupliObject *dupob;
|
||||
int dupob_index;
|
||||
float omat[4][4];
|
||||
Object *dupli_refob;
|
||||
int phase;
|
||||
|
||||
@@ -3809,28 +3809,28 @@ bool BKE_object_minmax_dupli(Depsgraph *depsgraph,
|
||||
return ok;
|
||||
}
|
||||
|
||||
ListBase *lb = object_duplilist(depsgraph, scene, ob);
|
||||
LISTBASE_FOREACH (DupliObject *, dob, lb) {
|
||||
if (((use_hidden == false) && (dob->no_draw != 0)) || dob->ob_data == nullptr) {
|
||||
DupliList duplilist;
|
||||
object_duplilist(depsgraph, scene, ob, nullptr, duplilist);
|
||||
for (DupliObject &dob : duplilist) {
|
||||
if (((use_hidden == false) && (dob.no_draw != 0)) || dob.ob_data == nullptr) {
|
||||
/* pass */
|
||||
}
|
||||
else {
|
||||
Object temp_ob = blender::dna::shallow_copy(*dob->ob);
|
||||
blender::bke::ObjectRuntime runtime = *dob->ob->runtime;
|
||||
Object temp_ob = blender::dna::shallow_copy(*dob.ob);
|
||||
blender::bke::ObjectRuntime runtime = *dob.ob->runtime;
|
||||
temp_ob.runtime = &runtime;
|
||||
|
||||
/* Do not modify the original bounding-box. */
|
||||
temp_ob.runtime->bounds_eval.reset();
|
||||
BKE_object_replace_data_on_shallow_copy(&temp_ob, dob->ob_data);
|
||||
BKE_object_replace_data_on_shallow_copy(&temp_ob, dob.ob_data);
|
||||
if (const std::optional<Bounds<float3>> bounds = BKE_object_boundbox_get(&temp_ob)) {
|
||||
BoundBox bb;
|
||||
BKE_boundbox_init_from_minmax(&bb, bounds->min, bounds->max);
|
||||
BKE_boundbox_minmax(bb, float4x4(dob->mat), r_min, r_max);
|
||||
BKE_boundbox_minmax(bb, float4x4(dob.mat), r_min, r_max);
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
free_object_duplilist(lb); /* does restore */
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include "BLI_set.hh"
|
||||
#include "BLI_span.hh"
|
||||
#include "BLI_string_ref.hh"
|
||||
#include "BLI_vector.hh"
|
||||
#include "BLI_vector_list.hh"
|
||||
|
||||
#include "DNA_collection_types.h"
|
||||
#include "DNA_curves_types.h"
|
||||
@@ -75,6 +75,7 @@ using blender::float4x4;
|
||||
using blender::Set;
|
||||
using blender::Span;
|
||||
using blender::Vector;
|
||||
using blender::VectorList;
|
||||
using blender::bke::GeometrySet;
|
||||
using blender::bke::InstanceReference;
|
||||
using blender::bke::Instances;
|
||||
@@ -137,7 +138,7 @@ struct DupliContext {
|
||||
const struct DupliGenerator *gen;
|
||||
|
||||
/** Result containers. */
|
||||
ListBase *duplilist; /* Legacy doubly-linked list. */
|
||||
DupliList *duplilist;
|
||||
};
|
||||
|
||||
struct DupliGenerator {
|
||||
@@ -158,7 +159,8 @@ static void init_context(DupliContext *r_ctx,
|
||||
const float space_mat[4][4],
|
||||
blender::Set<const Object *> *include_objects,
|
||||
Vector<Object *> &instance_stack,
|
||||
Vector<short> &dupli_gen_type_stack)
|
||||
Vector<short> &dupli_gen_type_stack,
|
||||
DupliList &duplilist)
|
||||
{
|
||||
r_ctx->depsgraph = depsgraph;
|
||||
r_ctx->scene = scene;
|
||||
@@ -169,6 +171,7 @@ static void init_context(DupliContext *r_ctx,
|
||||
r_ctx->obedit = OBEDIT_FROM_OBACT(ob);
|
||||
r_ctx->instance_stack = &instance_stack;
|
||||
r_ctx->dupli_gen_type_stack = &dupli_gen_type_stack;
|
||||
r_ctx->duplilist = &duplilist;
|
||||
if (space_mat) {
|
||||
copy_m4_m4(r_ctx->space_mat, space_mat);
|
||||
}
|
||||
@@ -182,7 +185,6 @@ static void init_context(DupliContext *r_ctx,
|
||||
r_ctx->dupli_gen_type_stack->append(r_ctx->gen->type);
|
||||
}
|
||||
|
||||
r_ctx->duplilist = nullptr;
|
||||
r_ctx->preview_instance_index = -1;
|
||||
r_ctx->preview_base_geometry = nullptr;
|
||||
|
||||
@@ -268,8 +270,8 @@ static DupliObject *make_dupli(const DupliContext *ctx,
|
||||
|
||||
/* Add a #DupliObject instance to the result container. */
|
||||
if (ctx->duplilist) {
|
||||
dob = MEM_callocN<DupliObject>("dupli object");
|
||||
BLI_addtail(ctx->duplilist, dob);
|
||||
ctx->duplilist->append({});
|
||||
dob = &ctx->duplilist->last();
|
||||
}
|
||||
else {
|
||||
return nullptr;
|
||||
@@ -1804,39 +1806,49 @@ static const DupliGenerator *get_dupli_generator(const DupliContext *ctx)
|
||||
/** \name Dupli-Container Implementation
|
||||
* \{ */
|
||||
|
||||
ListBase *object_duplilist(Depsgraph *depsgraph,
|
||||
Scene *sce,
|
||||
Object *ob,
|
||||
Set<const Object *> *include_objects)
|
||||
void object_duplilist(Depsgraph *depsgraph,
|
||||
Scene *sce,
|
||||
Object *ob,
|
||||
Set<const Object *> *include_objects,
|
||||
DupliList &r_duplilist)
|
||||
{
|
||||
ListBase *duplilist = MEM_callocN<ListBase>("duplilist");
|
||||
DupliContext ctx;
|
||||
Vector<Object *> instance_stack;
|
||||
Vector<short> dupli_gen_type_stack({0});
|
||||
instance_stack.append(ob);
|
||||
init_context(
|
||||
&ctx, depsgraph, sce, ob, nullptr, include_objects, instance_stack, dupli_gen_type_stack);
|
||||
init_context(&ctx,
|
||||
depsgraph,
|
||||
sce,
|
||||
ob,
|
||||
nullptr,
|
||||
include_objects,
|
||||
instance_stack,
|
||||
dupli_gen_type_stack,
|
||||
r_duplilist);
|
||||
if (ctx.gen) {
|
||||
ctx.duplilist = duplilist;
|
||||
ctx.gen->make_duplis(&ctx);
|
||||
}
|
||||
|
||||
return duplilist;
|
||||
}
|
||||
|
||||
ListBase *object_duplilist_preview(Depsgraph *depsgraph,
|
||||
Scene *sce,
|
||||
Object *ob_eval,
|
||||
const ViewerPath *viewer_path)
|
||||
void object_duplilist_preview(Depsgraph *depsgraph,
|
||||
Scene *sce,
|
||||
Object *ob_eval,
|
||||
const ViewerPath *viewer_path,
|
||||
DupliList &r_duplilist)
|
||||
{
|
||||
ListBase *duplilist = MEM_callocN<ListBase>("duplilist");
|
||||
DupliContext ctx;
|
||||
Vector<Object *> instance_stack;
|
||||
Vector<short> dupli_gen_type_stack({0});
|
||||
instance_stack.append(ob_eval);
|
||||
init_context(
|
||||
&ctx, depsgraph, sce, ob_eval, nullptr, nullptr, instance_stack, dupli_gen_type_stack);
|
||||
ctx.duplilist = duplilist;
|
||||
init_context(&ctx,
|
||||
depsgraph,
|
||||
sce,
|
||||
ob_eval,
|
||||
nullptr,
|
||||
nullptr,
|
||||
instance_stack,
|
||||
dupli_gen_type_stack,
|
||||
r_duplilist);
|
||||
|
||||
Object *ob_orig = DEG_get_original(ob_eval);
|
||||
|
||||
@@ -1859,7 +1871,6 @@ ListBase *object_duplilist_preview(Depsgraph *depsgraph,
|
||||
ob_eval->type == OB_CURVES);
|
||||
}
|
||||
}
|
||||
return duplilist;
|
||||
}
|
||||
|
||||
blender::bke::Instances object_duplilist_legacy_instances(Depsgraph &depsgraph,
|
||||
@@ -1868,19 +1879,25 @@ blender::bke::Instances object_duplilist_legacy_instances(Depsgraph &depsgraph,
|
||||
{
|
||||
using namespace blender;
|
||||
|
||||
ListBase *duplilist = MEM_callocN<ListBase>("duplilist");
|
||||
DupliContext ctx;
|
||||
DupliList duplilist;
|
||||
Vector<Object *> instance_stack({&ob});
|
||||
Vector<short> dupli_gen_type_stack({0});
|
||||
|
||||
init_context(
|
||||
&ctx, &depsgraph, &scene, &ob, nullptr, nullptr, instance_stack, dupli_gen_type_stack);
|
||||
init_context(&ctx,
|
||||
&depsgraph,
|
||||
&scene,
|
||||
&ob,
|
||||
nullptr,
|
||||
nullptr,
|
||||
instance_stack,
|
||||
dupli_gen_type_stack,
|
||||
duplilist);
|
||||
if (ctx.gen == &gen_dupli_geometry_set) {
|
||||
/* These are not legacy instances. */
|
||||
return {};
|
||||
}
|
||||
if (ctx.gen) {
|
||||
ctx.duplilist = duplilist;
|
||||
ctx.gen->make_duplis(&ctx);
|
||||
}
|
||||
const bool is_particle_duplis = ctx.gen == &gen_dupli_particles;
|
||||
@@ -1889,12 +1906,12 @@ blender::bke::Instances object_duplilist_legacy_instances(Depsgraph &depsgraph,
|
||||
const int level_to_use = is_particle_duplis ? 1 : 0;
|
||||
|
||||
Vector<DupliObject *> top_level_duplis;
|
||||
LISTBASE_FOREACH (DupliObject *, dob, duplilist) {
|
||||
BLI_assert(dob->ob != &ob);
|
||||
for (DupliObject &dob : duplilist) {
|
||||
BLI_assert(dob.ob != &ob);
|
||||
/* We only need the top level instances in the end, because when #Instances references an
|
||||
* object, it implicitly also references all instances of that object. */
|
||||
if (dob->level == level_to_use) {
|
||||
top_level_duplis.append(dob);
|
||||
if (dob.level == level_to_use) {
|
||||
top_level_duplis.append(&dob);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1933,16 +1950,9 @@ blender::bke::Instances object_duplilist_legacy_instances(Depsgraph &depsgraph,
|
||||
}
|
||||
instances_ids.finish();
|
||||
|
||||
free_object_duplilist(duplilist);
|
||||
return top_level_instances;
|
||||
}
|
||||
|
||||
void free_object_duplilist(ListBase *lb)
|
||||
{
|
||||
BLI_freelistN(lb);
|
||||
MEM_freeN(lb);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
@@ -2095,7 +2095,8 @@ int BKE_scene_base_iter_next(
|
||||
if (val == 0) {
|
||||
iter->phase = F_START;
|
||||
iter->dupob = nullptr;
|
||||
iter->duplilist = nullptr;
|
||||
iter->dupob_index = -1;
|
||||
iter->duplilist.clear();
|
||||
iter->dupli_refob = nullptr;
|
||||
}
|
||||
else {
|
||||
@@ -2164,13 +2165,14 @@ int BKE_scene_base_iter_next(
|
||||
* this enters eternal loop because of
|
||||
* makeDispListMBall getting called inside of collection_duplilist */
|
||||
if ((*base)->object->instance_collection == nullptr) {
|
||||
iter->duplilist = object_duplilist(depsgraph, (*scene), (*base)->object);
|
||||
object_duplilist(depsgraph, (*scene), (*base)->object, nullptr, iter->duplilist);
|
||||
|
||||
iter->dupob = static_cast<DupliObject *>(iter->duplilist->first);
|
||||
iter->dupob = iter->duplilist.is_empty() ? nullptr : &iter->duplilist.first();
|
||||
iter->dupob_index = 0;
|
||||
|
||||
if (!iter->dupob) {
|
||||
free_object_duplilist(iter->duplilist);
|
||||
iter->duplilist = nullptr;
|
||||
iter->duplilist.clear();
|
||||
iter->dupob_index = -1;
|
||||
}
|
||||
iter->dupli_refob = nullptr;
|
||||
}
|
||||
@@ -2193,7 +2195,13 @@ int BKE_scene_base_iter_next(
|
||||
}
|
||||
copy_m4_m4((*ob)->runtime->object_to_world.ptr(), iter->dupob->mat);
|
||||
|
||||
iter->dupob = iter->dupob->next;
|
||||
if (++iter->dupob_index < iter->duplilist.size()) {
|
||||
iter->dupob = &iter->duplilist[iter->dupob_index];
|
||||
}
|
||||
else {
|
||||
iter->dupob = nullptr;
|
||||
iter->dupob_index = -1;
|
||||
}
|
||||
}
|
||||
else if (iter->phase == F_DUPLI) {
|
||||
iter->phase = F_SCENE;
|
||||
@@ -2205,8 +2213,7 @@ int BKE_scene_base_iter_next(
|
||||
iter->dupli_refob = nullptr;
|
||||
}
|
||||
|
||||
free_object_duplilist(iter->duplilist);
|
||||
iter->duplilist = nullptr;
|
||||
iter->duplilist.clear();
|
||||
run_again = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
/* Needed for the instance iterator. */
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "BKE_duplilist.hh"
|
||||
#include "BKE_object_types.hh"
|
||||
|
||||
struct BLI_Iterator;
|
||||
@@ -265,9 +266,11 @@ struct DEGObjectIterData {
|
||||
/* Object which created the dupli-list. */
|
||||
Object *dupli_parent;
|
||||
/* List of duplicated objects. */
|
||||
ListBase *dupli_list;
|
||||
DupliList dupli_list;
|
||||
/* Next duplicated object to step into. */
|
||||
DupliObject *dupli_object_next;
|
||||
/* The dupli_list index of dupli_object_next. */
|
||||
int dupli_object_next_index;
|
||||
/* Corresponds to current object: current iterator object is evaluated from
|
||||
* this duplicated object. */
|
||||
DupliObject *dupli_object_current;
|
||||
@@ -279,7 +282,9 @@ struct DEGObjectIterData {
|
||||
/* **** Iteration over ID nodes **** */
|
||||
size_t id_node_index;
|
||||
size_t num_id_nodes;
|
||||
DEGObjectIterData &operator=(const DEGObjectIterData &other);
|
||||
|
||||
/* Copy the current/next data and move the DupliList. */
|
||||
void transfer_from(DEGObjectIterData &other);
|
||||
};
|
||||
|
||||
void DEG_iterator_objects_begin(BLI_Iterator *iter, DEGObjectIterData *data);
|
||||
|
||||
@@ -113,17 +113,17 @@ bool deg_object_hide_original(eEvaluationMode eval_mode, Object *ob, DupliObject
|
||||
return false;
|
||||
}
|
||||
|
||||
void deg_iterator_duplis_init(DEGObjectIterData *data, Object *object, ListBase *duplis)
|
||||
void deg_iterator_duplis_init(DEGObjectIterData *data, Object *object)
|
||||
{
|
||||
data->dupli_parent = object;
|
||||
data->dupli_list = duplis;
|
||||
data->dupli_object_next = static_cast<DupliObject *>(duplis->first);
|
||||
data->dupli_object_next = data->dupli_list.is_empty() ? nullptr : &data->dupli_list.first();
|
||||
data->dupli_object_next_index = data->dupli_object_next ? 0 : -1;
|
||||
}
|
||||
|
||||
/* Returns false when iterator is exhausted. */
|
||||
bool deg_iterator_duplis_step(DEGObjectIterData *data)
|
||||
{
|
||||
if (data->dupli_list == nullptr) {
|
||||
if (data->dupli_list.is_empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -131,7 +131,13 @@ bool deg_iterator_duplis_step(DEGObjectIterData *data)
|
||||
DupliObject *dob = data->dupli_object_next;
|
||||
Object *obd = dob->ob;
|
||||
|
||||
data->dupli_object_next = data->dupli_object_next->next;
|
||||
if (++data->dupli_object_next_index < data->dupli_list.size()) {
|
||||
data->dupli_object_next = &data->dupli_list[data->dupli_object_next_index];
|
||||
}
|
||||
else {
|
||||
data->dupli_object_next = nullptr;
|
||||
data->dupli_object_next_index = -1;
|
||||
}
|
||||
|
||||
if (dob->no_draw) {
|
||||
continue;
|
||||
@@ -196,10 +202,10 @@ bool deg_iterator_duplis_step(DEGObjectIterData *data)
|
||||
}
|
||||
|
||||
free_owned_memory(data);
|
||||
free_object_duplilist(data->dupli_list);
|
||||
data->dupli_list.clear();
|
||||
data->dupli_parent = nullptr;
|
||||
data->dupli_list = nullptr;
|
||||
data->dupli_object_next = nullptr;
|
||||
data->dupli_object_next_index = -1;
|
||||
data->dupli_object_current = nullptr;
|
||||
deg_invalidate_iterator_work_data(data);
|
||||
return false;
|
||||
@@ -265,9 +271,9 @@ bool deg_iterator_objects_step(DEGObjectIterData *data)
|
||||
|
||||
const bool use_preview = object_orig == data->object_orig_with_preview;
|
||||
if (use_preview) {
|
||||
ListBase *preview_duplis = object_duplilist_preview(
|
||||
data->graph, data->scene, object, data->settings->viewer_path);
|
||||
deg_iterator_duplis_init(data, object, preview_duplis);
|
||||
object_duplilist_preview(
|
||||
data->graph, data->scene, object, data->settings->viewer_path, data->dupli_list);
|
||||
deg_iterator_duplis_init(data, object);
|
||||
data->id_node_index++;
|
||||
return true;
|
||||
}
|
||||
@@ -286,9 +292,9 @@ bool deg_iterator_objects_step(DEGObjectIterData *data)
|
||||
((object->transflag & OB_DUPLI) || object->runtime->geometry_set_eval != nullptr))
|
||||
{
|
||||
BLI_assert(deg::deg_validate_eval_copy_datablock(&object->id));
|
||||
ListBase *duplis = object_duplilist(
|
||||
data->graph, data->scene, object, data->settings->included_objects);
|
||||
deg_iterator_duplis_init(data, object, duplis);
|
||||
object_duplilist(
|
||||
data->graph, data->scene, object, data->settings->included_objects, data->dupli_list);
|
||||
deg_iterator_duplis_init(data, object);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -304,27 +310,27 @@ bool deg_iterator_objects_step(DEGObjectIterData *data)
|
||||
|
||||
} // namespace
|
||||
|
||||
DEGObjectIterData &DEGObjectIterData::operator=(const DEGObjectIterData &other)
|
||||
void DEGObjectIterData::transfer_from(DEGObjectIterData &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
this->settings = other.settings;
|
||||
this->graph = other.graph;
|
||||
this->flag = other.flag;
|
||||
this->scene = other.scene;
|
||||
this->eval_mode = other.eval_mode;
|
||||
this->object_orig_with_preview = other.object_orig_with_preview;
|
||||
this->next_object = other.next_object;
|
||||
this->dupli_parent = other.dupli_parent;
|
||||
this->dupli_list = other.dupli_list;
|
||||
this->dupli_object_next = other.dupli_object_next;
|
||||
this->dupli_object_current = other.dupli_object_current;
|
||||
this->temp_dupli_object = blender::dna::shallow_copy(other.temp_dupli_object);
|
||||
this->temp_dupli_object_runtime = other.temp_dupli_object_runtime;
|
||||
this->temp_dupli_object.runtime = &temp_dupli_object_runtime;
|
||||
this->id_node_index = other.id_node_index;
|
||||
this->num_id_nodes = other.num_id_nodes;
|
||||
}
|
||||
return *this;
|
||||
BLI_assert(this != &other);
|
||||
|
||||
this->settings = other.settings;
|
||||
this->graph = other.graph;
|
||||
this->flag = other.flag;
|
||||
this->scene = other.scene;
|
||||
this->eval_mode = other.eval_mode;
|
||||
this->object_orig_with_preview = other.object_orig_with_preview;
|
||||
this->next_object = other.next_object;
|
||||
this->dupli_parent = other.dupli_parent;
|
||||
this->dupli_list = std::move(other.dupli_list);
|
||||
this->dupli_object_next = other.dupli_object_next;
|
||||
this->dupli_object_next_index = other.dupli_object_next_index;
|
||||
this->dupli_object_current = other.dupli_object_current;
|
||||
this->temp_dupli_object = blender::dna::shallow_copy(other.temp_dupli_object);
|
||||
this->temp_dupli_object_runtime = other.temp_dupli_object_runtime;
|
||||
this->temp_dupli_object.runtime = &temp_dupli_object_runtime;
|
||||
this->id_node_index = other.id_node_index;
|
||||
this->num_id_nodes = other.num_id_nodes;
|
||||
}
|
||||
|
||||
static Object *find_object_with_preview_geometry(const ViewerPath &viewer_path)
|
||||
@@ -374,8 +380,9 @@ void DEG_iterator_objects_begin(BLI_Iterator *iter, DEGObjectIterData *data)
|
||||
|
||||
data->next_object = nullptr;
|
||||
data->dupli_parent = nullptr;
|
||||
data->dupli_list = nullptr;
|
||||
data->dupli_list.clear();
|
||||
data->dupli_object_next = nullptr;
|
||||
data->dupli_object_next_index = -1;
|
||||
data->dupli_object_current = nullptr;
|
||||
data->scene = DEG_get_evaluated_scene(depsgraph);
|
||||
data->id_node_index = 0;
|
||||
|
||||
@@ -77,19 +77,21 @@ static Vector<Object *> get_bake_targets(bContext &C, Depsgraph &depsgraph, Scen
|
||||
Vector<Object *> bake_targets;
|
||||
Object *active_object = CTX_data_active_object(&C);
|
||||
|
||||
DupliList duplilist;
|
||||
|
||||
if (active_object->type == OB_GREASE_PENCIL) {
|
||||
bake_targets.append(active_object);
|
||||
}
|
||||
else if (active_object->type == OB_EMPTY) {
|
||||
ListBase *lb = object_duplilist(&depsgraph, &scene, active_object);
|
||||
LISTBASE_FOREACH (DupliObject *, duplicate_object, lb) {
|
||||
if (duplicate_object->ob->type != OB_GREASE_PENCIL) {
|
||||
object_duplilist(&depsgraph, &scene, active_object, nullptr, duplilist);
|
||||
for (DupliObject &duplicate_object : duplilist) {
|
||||
if (duplicate_object.ob->type != OB_GREASE_PENCIL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bake_targets.append(duplicate_object->ob);
|
||||
bake_targets.append(duplicate_object.ob);
|
||||
}
|
||||
free_object_duplilist(lb);
|
||||
duplilist.clear();
|
||||
}
|
||||
|
||||
CTX_DATA_BEGIN (&C, Object *, object, selected_objects) {
|
||||
@@ -101,15 +103,15 @@ static Vector<Object *> get_bake_targets(bContext &C, Depsgraph &depsgraph, Scen
|
||||
bake_targets.append(object);
|
||||
}
|
||||
else if (object->type == OB_EMPTY) {
|
||||
ListBase *lb = object_duplilist(&depsgraph, &scene, active_object);
|
||||
LISTBASE_FOREACH (DupliObject *, duplicate_object, lb) {
|
||||
if (duplicate_object->ob->type != OB_GREASE_PENCIL) {
|
||||
object_duplilist(&depsgraph, &scene, active_object, nullptr, duplilist);
|
||||
for (DupliObject &duplicate_object : duplilist) {
|
||||
if (duplicate_object.ob->type != OB_GREASE_PENCIL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bake_targets.append(duplicate_object->ob);
|
||||
bake_targets.append(duplicate_object.ob);
|
||||
}
|
||||
free_object_duplilist(lb);
|
||||
duplilist.clear();
|
||||
}
|
||||
}
|
||||
CTX_DATA_END;
|
||||
|
||||
@@ -2498,10 +2498,10 @@ static void make_object_duplilist_real(bContext *C,
|
||||
return;
|
||||
}
|
||||
|
||||
ListBase *lb_duplis = object_duplilist(depsgraph, scene, object_eval);
|
||||
DupliList duplilist;
|
||||
object_duplilist(depsgraph, scene, object_eval, nullptr, duplilist);
|
||||
|
||||
if (BLI_listbase_is_empty(lb_duplis)) {
|
||||
free_object_duplilist(lb_duplis);
|
||||
if (duplilist.is_empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2515,8 +2515,8 @@ static void make_object_duplilist_real(bContext *C,
|
||||
}
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (DupliObject *, dob, lb_duplis) {
|
||||
Object *ob_src = DEG_get_original(dob->ob);
|
||||
for (DupliObject &dob : duplilist) {
|
||||
Object *ob_src = DEG_get_original(dob.ob);
|
||||
Object *ob_dst = static_cast<Object *>(ID_NEW_SET(ob_src, BKE_id_copy(bmain, &ob_src->id)));
|
||||
id_us_min(&ob_dst->id);
|
||||
|
||||
@@ -2551,32 +2551,32 @@ static void make_object_duplilist_real(bContext *C,
|
||||
id_us_min((ID *)ob_dst->instance_collection);
|
||||
ob_dst->instance_collection = nullptr;
|
||||
|
||||
copy_m4_m4(ob_dst->runtime->object_to_world.ptr(), dob->mat);
|
||||
copy_m4_m4(ob_dst->runtime->object_to_world.ptr(), dob.mat);
|
||||
BKE_object_apply_mat4(ob_dst, ob_dst->object_to_world().ptr(), false, false);
|
||||
|
||||
dupli_map.add(dob, ob_dst);
|
||||
dupli_map.add(&dob, ob_dst);
|
||||
|
||||
if (parent_gh) {
|
||||
void **val;
|
||||
/* Due to nature of hash/comparison of this ghash, a lot of duplis may be considered as
|
||||
* 'the same', this avoids trying to insert same key several time and
|
||||
* raise asserts in debug builds... */
|
||||
if (!BLI_ghash_ensure_p(parent_gh, dob, &val)) {
|
||||
if (!BLI_ghash_ensure_p(parent_gh, &dob, &val)) {
|
||||
*val = ob_dst;
|
||||
}
|
||||
|
||||
if (is_dupli_instancer && instancer_gh) {
|
||||
/* Same as above, we may have several 'hits'. */
|
||||
if (!BLI_ghash_ensure_p(instancer_gh, dob, &val)) {
|
||||
if (!BLI_ghash_ensure_p(instancer_gh, &dob, &val)) {
|
||||
*val = ob_dst;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (DupliObject *, dob, lb_duplis) {
|
||||
Object *ob_src = dob->ob;
|
||||
Object *ob_dst = dupli_map.lookup(dob);
|
||||
for (DupliObject &dob : duplilist) {
|
||||
Object *ob_src = dob.ob;
|
||||
Object *ob_dst = dupli_map.lookup(&dob);
|
||||
|
||||
/* Remap new object to itself, and clear again newid pointer of orig object. */
|
||||
BKE_libblock_relink_to_newid(bmain, &ob_dst->id, 0);
|
||||
@@ -2594,14 +2594,14 @@ static void make_object_duplilist_real(bContext *C,
|
||||
* they won't be read, this is simply for a hash lookup. */
|
||||
DupliObject dob_key;
|
||||
dob_key.ob = ob_src_par;
|
||||
dob_key.type = dob->type;
|
||||
if (dob->type == OB_DUPLICOLLECTION) {
|
||||
dob_key.type = dob.type;
|
||||
if (dob.type == OB_DUPLICOLLECTION) {
|
||||
memcpy(&dob_key.persistent_id[1],
|
||||
&dob->persistent_id[1],
|
||||
sizeof(dob->persistent_id[1]) * (MAX_DUPLI_RECUR - 1));
|
||||
&dob.persistent_id[1],
|
||||
sizeof(dob.persistent_id[1]) * (MAX_DUPLI_RECUR - 1));
|
||||
}
|
||||
else {
|
||||
dob_key.persistent_id[0] = dob->persistent_id[0];
|
||||
dob_key.persistent_id[0] = dob.persistent_id[0];
|
||||
}
|
||||
ob_dst_par = static_cast<Object *>(BLI_ghash_lookup(parent_gh, &dob_key));
|
||||
}
|
||||
@@ -2630,7 +2630,7 @@ static void make_object_duplilist_real(bContext *C,
|
||||
* ignoring the first item.
|
||||
* We only check on persistent_id here, since we have no idea what object it might be. */
|
||||
memcpy(&dob_key.persistent_id[0],
|
||||
&dob->persistent_id[1],
|
||||
&dob.persistent_id[1],
|
||||
sizeof(dob_key.persistent_id[0]) * (MAX_DUPLI_RECUR - 1));
|
||||
ob_dst_par = static_cast<Object *>(BLI_ghash_lookup(instancer_gh, &dob_key));
|
||||
}
|
||||
@@ -2648,7 +2648,7 @@ static void make_object_duplilist_real(bContext *C,
|
||||
if (ob_dst->parent) {
|
||||
/* NOTE: this may be the parent of other objects, but it should
|
||||
* still work out ok */
|
||||
BKE_object_apply_mat4(ob_dst, dob->mat, false, true);
|
||||
BKE_object_apply_mat4(ob_dst, dob.mat, false, true);
|
||||
|
||||
/* to set ob_dst->orig and in case there's any other discrepancies */
|
||||
DEG_id_tag_update(&ob_dst->id, ID_RECALC_TRANSFORM);
|
||||
@@ -2669,8 +2669,6 @@ static void make_object_duplilist_real(bContext *C,
|
||||
BLI_ghash_free(instancer_gh, nullptr, nullptr);
|
||||
}
|
||||
|
||||
free_object_duplilist(lb_duplis);
|
||||
|
||||
BKE_main_id_newptr_and_tag_clear(bmain);
|
||||
|
||||
base->object->transflag &= ~OB_DUPLI;
|
||||
|
||||
@@ -472,6 +472,7 @@ static eSnapMode iter_snap_objects(SnapObjectContext *sctx, IterSnapObjsCallback
|
||||
BKE_view_layer_synced_ensure(scene, view_layer);
|
||||
Base *base_act = BKE_view_layer_active_base_get(view_layer);
|
||||
|
||||
DupliList duplilist;
|
||||
LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) {
|
||||
if (!snap_object_is_snappable(sctx, snap_target_select, base_act, base)) {
|
||||
continue;
|
||||
@@ -482,20 +483,20 @@ static eSnapMode iter_snap_objects(SnapObjectContext *sctx, IterSnapObjsCallback
|
||||
if (obj_eval->transflag & OB_DUPLI ||
|
||||
blender::bke::object_has_geometry_set_instances(*obj_eval))
|
||||
{
|
||||
ListBase *lb = object_duplilist(sctx->runtime.depsgraph, sctx->scene, obj_eval);
|
||||
LISTBASE_FOREACH (DupliObject *, dupli_ob, lb) {
|
||||
BLI_assert(DEG_is_evaluated(dupli_ob->ob));
|
||||
object_duplilist(sctx->runtime.depsgraph, sctx->scene, obj_eval, nullptr, duplilist);
|
||||
for (DupliObject &dupli_ob : duplilist) {
|
||||
BLI_assert(DEG_is_evaluated(dupli_ob.ob));
|
||||
if ((tmp = sob_callback(sctx,
|
||||
dupli_ob->ob,
|
||||
dupli_ob->ob_data,
|
||||
float4x4(dupli_ob->mat),
|
||||
dupli_ob.ob,
|
||||
dupli_ob.ob_data,
|
||||
float4x4(dupli_ob.mat),
|
||||
is_object_active,
|
||||
false)) != SCE_SNAP_TO_NONE)
|
||||
{
|
||||
ret = tmp;
|
||||
}
|
||||
}
|
||||
free_object_duplilist(lb);
|
||||
duplilist.clear();
|
||||
}
|
||||
|
||||
bool use_hide = false;
|
||||
|
||||
@@ -14,9 +14,6 @@
|
||||
|
||||
#include "BlenderStrokeRenderer.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace Freestyle;
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_collection_types.h"
|
||||
@@ -50,6 +47,9 @@ using namespace Freestyle;
|
||||
|
||||
#include "FRS_freestyle.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace Freestyle;
|
||||
|
||||
FreestyleGlobals g_freestyle;
|
||||
|
||||
// Freestyle configuration
|
||||
|
||||
@@ -287,6 +287,7 @@ void AbstractHierarchyIterator::export_graph_construct()
|
||||
deg_iter_settings.depsgraph = depsgraph_;
|
||||
deg_iter_settings.flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
|
||||
DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET;
|
||||
DupliList duplilist;
|
||||
DEG_OBJECT_ITER_BEGIN (°_iter_settings, object) {
|
||||
/* Non-instanced objects always have their object-parent as export-parent. */
|
||||
const bool weak_export = mark_as_weak_export(object);
|
||||
@@ -298,27 +299,27 @@ void AbstractHierarchyIterator::export_graph_construct()
|
||||
}
|
||||
|
||||
/* Export the duplicated objects instanced by this object. */
|
||||
ListBase *lb = object_duplilist(depsgraph_, scene, object);
|
||||
if (lb) {
|
||||
object_duplilist(depsgraph_, scene, object, nullptr, duplilist);
|
||||
if (!duplilist.is_empty()) {
|
||||
DupliParentFinder dupli_parent_finder;
|
||||
|
||||
LISTBASE_FOREACH (DupliObject *, dupli_object, lb) {
|
||||
PersistentID persistent_id(dupli_object);
|
||||
if (!should_visit_dupli_object(dupli_object)) {
|
||||
for (DupliObject &dupli_object : duplilist) {
|
||||
PersistentID persistent_id(&dupli_object);
|
||||
if (!should_visit_dupli_object(&dupli_object)) {
|
||||
continue;
|
||||
}
|
||||
dupli_parent_finder.insert(dupli_object);
|
||||
dupli_parent_finder.insert(&dupli_object);
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (DupliObject *, dupli_object, lb) {
|
||||
if (!should_visit_dupli_object(dupli_object)) {
|
||||
for (DupliObject &dupli_object : duplilist) {
|
||||
if (!should_visit_dupli_object(&dupli_object)) {
|
||||
continue;
|
||||
}
|
||||
visit_dupli_object(dupli_object, object, dupli_parent_finder);
|
||||
visit_dupli_object(&dupli_object, object, dupli_parent_finder);
|
||||
}
|
||||
}
|
||||
|
||||
free_object_duplilist(lb);
|
||||
duplilist.clear();
|
||||
}
|
||||
DEG_OBJECT_ITER_END;
|
||||
}
|
||||
|
||||
@@ -400,7 +400,7 @@ static void rna_Depsgraph_object_instances_next(CollectionPropertyIterator *iter
|
||||
|
||||
/* We need to copy current iterator status to next one being worked on. */
|
||||
di_it->iterators[(di_it->counter + 1) % 2].iter = di_it->iterators[di_it->counter % 2].iter;
|
||||
di_it->deg_data[(di_it->counter + 1) % 2] = di_it->deg_data[di_it->counter % 2];
|
||||
di_it->deg_data[(di_it->counter + 1) % 2].transfer_from(di_it->deg_data[di_it->counter % 2]);
|
||||
di_it->counter++;
|
||||
|
||||
di_it->iterators[di_it->counter % 2].iter.data = &di_it->deg_data[di_it->counter % 2];
|
||||
|
||||
Reference in New Issue
Block a user