Refactor: Cycles: Replace new/delete with unique_ptr also for nodes
Using new unique_ptr_vector utility class. Pull Request: https://projects.blender.org/blender/blender/pulls/132361
This commit is contained in:
@@ -357,8 +357,7 @@ static void xml_read_shader_graph(XMLReadState &state, Shader *shader, const xml
|
||||
continue;
|
||||
}
|
||||
|
||||
snode = (ShaderNode *)node_type->create(node_type);
|
||||
snode->set_owner(graph.get());
|
||||
snode = graph->create_node(node_type);
|
||||
}
|
||||
|
||||
xml_read_node(graph_reader, snode, node);
|
||||
@@ -373,11 +372,6 @@ static void xml_read_shader_graph(XMLReadState &state, Shader *shader, const xml
|
||||
const ustring filename(path_join(state.base, env->get_filename().string()));
|
||||
env->set_filename(filename);
|
||||
}
|
||||
|
||||
if (snode) {
|
||||
/* add to graph */
|
||||
graph->add(snode);
|
||||
}
|
||||
}
|
||||
|
||||
shader->set_graph(std::move(graph));
|
||||
@@ -386,9 +380,8 @@ static void xml_read_shader_graph(XMLReadState &state, Shader *shader, const xml
|
||||
|
||||
static void xml_read_shader(XMLReadState &state, const xml_node node)
|
||||
{
|
||||
Shader *shader = new Shader();
|
||||
Shader *shader = state.scene->create_node<Shader>();
|
||||
xml_read_shader_graph(state, shader, node);
|
||||
state.scene->shaders.push_back(shader);
|
||||
}
|
||||
|
||||
/* Background */
|
||||
@@ -415,14 +408,12 @@ static Mesh *xml_add_mesh(Scene *scene, const Transform &tfm, Object *object)
|
||||
}
|
||||
|
||||
/* Create mesh */
|
||||
Mesh *mesh = new Mesh();
|
||||
scene->geometry.push_back(mesh);
|
||||
Mesh *mesh = scene->create_node<Mesh>();
|
||||
|
||||
/* Create object. */
|
||||
object = new Object();
|
||||
object = scene->create_node<Object>();
|
||||
object->set_geometry(mesh);
|
||||
object->set_tfm(tfm);
|
||||
scene->objects.push_back(object);
|
||||
|
||||
return mesh;
|
||||
}
|
||||
@@ -649,12 +640,10 @@ static void xml_read_mesh(const XMLReadState &state, const xml_node node)
|
||||
|
||||
static void xml_read_light(XMLReadState &state, const xml_node node)
|
||||
{
|
||||
Light *light = new Light();
|
||||
Light *light = state.scene->create_node<Light>();
|
||||
|
||||
light->set_shader(state.shader);
|
||||
xml_read_node(state, light, node);
|
||||
|
||||
state.scene->lights.push_back(light);
|
||||
}
|
||||
|
||||
/* Transform */
|
||||
@@ -748,17 +737,14 @@ static void xml_read_object(XMLReadState &state, const xml_node node)
|
||||
Scene *scene = state.scene;
|
||||
|
||||
/* create mesh */
|
||||
Mesh *mesh = new Mesh();
|
||||
scene->geometry.push_back(mesh);
|
||||
Mesh *mesh = scene->create_node<Mesh>();
|
||||
|
||||
/* create object */
|
||||
Object *object = new Object();
|
||||
Object *object = scene->create_node<Object>();
|
||||
object->set_geometry(mesh);
|
||||
object->set_tfm(state.tfm);
|
||||
|
||||
xml_read_node(state, object, node);
|
||||
|
||||
scene->objects.push_back(object);
|
||||
}
|
||||
|
||||
/* Scene */
|
||||
|
||||
@@ -1124,7 +1124,6 @@ static ShaderNode *add_node(Scene *scene,
|
||||
|
||||
if (node) {
|
||||
node->name = b_node.name();
|
||||
graph->add(node);
|
||||
}
|
||||
|
||||
return node;
|
||||
@@ -1277,8 +1276,6 @@ static void add_nodes(Scene *scene,
|
||||
* input socket, so this needs to be a multimap. */
|
||||
input_map.emplace(b_link.from_socket().ptr.data, proxy->inputs[0]);
|
||||
output_map[b_link.to_socket().ptr.data] = proxy->outputs[0];
|
||||
|
||||
graph->add(proxy);
|
||||
}
|
||||
}
|
||||
else if (b_node.is_a(&RNA_ShaderNodeGroup) || b_node.is_a(&RNA_NodeCustomGroup) ||
|
||||
@@ -1310,7 +1307,6 @@ static void add_nodes(Scene *scene,
|
||||
}
|
||||
|
||||
ConvertNode *proxy = graph->create_node<ConvertNode>(input_type, input_type, true);
|
||||
graph->add(proxy);
|
||||
|
||||
/* register the proxy node for internal binding */
|
||||
group_proxy_input_map[b_input.identifier()] = proxy;
|
||||
@@ -1326,7 +1322,6 @@ static void add_nodes(Scene *scene,
|
||||
}
|
||||
|
||||
ConvertNode *proxy = graph->create_node<ConvertNode>(output_type, output_type, true);
|
||||
graph->add(proxy);
|
||||
|
||||
/* register the proxy node for internal binding */
|
||||
group_proxy_output_map[b_output.identifier()] = proxy;
|
||||
@@ -1590,7 +1585,6 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all)
|
||||
else {
|
||||
DiffuseBsdfNode *diffuse = graph->create_node<DiffuseBsdfNode>();
|
||||
diffuse->set_color(get_float3(b_mat.diffuse_color()));
|
||||
graph->add(diffuse);
|
||||
|
||||
ShaderNode *out = graph->output();
|
||||
graph->connect(diffuse->output("BSDF"), out->input("Surface"));
|
||||
@@ -1681,7 +1675,6 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
|
||||
else if (new_viewport_parameters.use_scene_world && b_world) {
|
||||
BackgroundNode *background = graph->create_node<BackgroundNode>();
|
||||
background->set_color(get_float3(b_world.color()));
|
||||
graph->add(background);
|
||||
|
||||
ShaderNode *out = graph->output();
|
||||
graph->connect(background->output("Background"), out->input("Surface"));
|
||||
@@ -1696,14 +1689,10 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
|
||||
}
|
||||
|
||||
BackgroundNode *background = graph->create_node<BackgroundNode>();
|
||||
graph->add(background);
|
||||
|
||||
LightPathNode *light_path = graph->create_node<LightPathNode>();
|
||||
graph->add(light_path);
|
||||
|
||||
MixNode *mix_scene_with_background = graph->create_node<MixNode>();
|
||||
mix_scene_with_background->set_color2(world_color);
|
||||
graph->add(mix_scene_with_background);
|
||||
|
||||
EnvironmentTextureNode *texture_environment = graph->create_node<EnvironmentTextureNode>();
|
||||
texture_environment->set_tex_mapping_type(TextureMapping::VECTOR);
|
||||
@@ -1711,7 +1700,6 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
|
||||
rotation_z[2] = new_viewport_parameters.studiolight_rotate_z;
|
||||
texture_environment->set_tex_mapping_rotation(rotation_z);
|
||||
texture_environment->set_filename(new_viewport_parameters.studiolight_path);
|
||||
graph->add(texture_environment);
|
||||
|
||||
MixNode *mix_intensity = graph->create_node<MixNode>();
|
||||
mix_intensity->set_mix_type(NODE_MIX_MUL);
|
||||
@@ -1719,16 +1707,13 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
|
||||
mix_intensity->set_color2(make_float3(new_viewport_parameters.studiolight_intensity,
|
||||
new_viewport_parameters.studiolight_intensity,
|
||||
new_viewport_parameters.studiolight_intensity));
|
||||
graph->add(mix_intensity);
|
||||
|
||||
TextureCoordinateNode *texture_coordinate = graph->create_node<TextureCoordinateNode>();
|
||||
graph->add(texture_coordinate);
|
||||
|
||||
MixNode *mix_background_with_environment = graph->create_node<MixNode>();
|
||||
mix_background_with_environment->set_fac(
|
||||
new_viewport_parameters.studiolight_background_alpha);
|
||||
mix_background_with_environment->set_color1(world_color);
|
||||
graph->add(mix_background_with_environment);
|
||||
|
||||
ShaderNode *out = graph->output();
|
||||
|
||||
@@ -1844,7 +1829,6 @@ void BlenderSync::sync_lights(BL::Depsgraph &b_depsgraph, bool update_all)
|
||||
EmissionNode *emission = graph->create_node<EmissionNode>();
|
||||
emission->set_color(one_float3());
|
||||
emission->set_strength(1.0f);
|
||||
graph->add(emission);
|
||||
|
||||
ShaderNode *out = graph->output();
|
||||
graph->connect(emission->output("Emission"), out->input("Surface"));
|
||||
|
||||
@@ -722,8 +722,8 @@ static Pass *pass_add(Scene *scene,
|
||||
void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_view_layer)
|
||||
{
|
||||
/* Delete all existing passes. */
|
||||
const set<Pass *> clear_passes(scene->passes.begin(), scene->passes.end());
|
||||
scene->delete_nodes(clear_passes);
|
||||
const vector<Pass *> &scene_passes = scene->passes;
|
||||
scene->delete_nodes(set<Pass *>(scene_passes.begin(), scene_passes.end()));
|
||||
|
||||
/* Always add combined pass. */
|
||||
pass_add(scene, PASS_COMBINED, "Combined");
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "util/array.h" // IWYU pragma: keep
|
||||
#include "util/map.h"
|
||||
#include "util/param.h"
|
||||
#include "util/unique_ptr.h"
|
||||
#include "util/vector.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
@@ -116,7 +117,7 @@ struct NodeType {
|
||||
const SocketType *find_input(ustring name) const;
|
||||
const SocketType *find_output(ustring name) const;
|
||||
|
||||
using CreateFunc = Node *(*)(const NodeType *);
|
||||
using CreateFunc = unique_ptr<Node> (*)(const NodeType *);
|
||||
|
||||
ustring name;
|
||||
Type type;
|
||||
@@ -141,14 +142,14 @@ struct NodeType {
|
||||
#define NODE_DECLARE \
|
||||
static const NodeType *get_node_type(); \
|
||||
template<typename T> static const NodeType *register_type(); \
|
||||
static Node *create(const NodeType *type); \
|
||||
static unique_ptr<Node> create(const NodeType *type); \
|
||||
static const NodeType *node_type;
|
||||
|
||||
#define NODE_DEFINE(structname) \
|
||||
const NodeType *structname::node_type = structname::register_type<structname>(); \
|
||||
Node *structname::create(const NodeType *) \
|
||||
unique_ptr<Node> structname::create(const NodeType *) \
|
||||
{ \
|
||||
return new structname(); \
|
||||
return make_unique<structname>(); \
|
||||
} \
|
||||
const NodeType *structname::get_node_type() \
|
||||
{ \
|
||||
|
||||
@@ -197,7 +197,6 @@ void HdCyclesLight::PopulateShaderGraph(HdSceneDelegate *sceneDelegate)
|
||||
BackgroundNode *bgNode = graph->create_node<BackgroundNode>();
|
||||
// Bake strength into shader graph, since only the shader is used for background lights
|
||||
bgNode->set_color(_light->get_strength());
|
||||
graph->add(bgNode);
|
||||
|
||||
graph->connect(bgNode->output("Background"), graph->output()->input("Surface"));
|
||||
|
||||
@@ -212,7 +211,6 @@ void HdCyclesLight::PopulateShaderGraph(HdSceneDelegate *sceneDelegate)
|
||||
if (strVal == "Constant" || strVal == "Linear" || strVal == "Quadratic") {
|
||||
LightFalloffNode *lfoNode = graph->create_node<LightFalloffNode>();
|
||||
lfoNode->set_strength(1.f);
|
||||
graph->add(lfoNode);
|
||||
graph->connect(lfoNode->output(strVal.c_str()), graph->output()->input("Surface"));
|
||||
outputNode = lfoNode;
|
||||
}
|
||||
@@ -223,7 +221,6 @@ void HdCyclesLight::PopulateShaderGraph(HdSceneDelegate *sceneDelegate)
|
||||
EmissionNode *emissionNode = graph->create_node<EmissionNode>();
|
||||
emissionNode->set_color(one_float3());
|
||||
emissionNode->set_strength(1.0f);
|
||||
graph->add(emissionNode);
|
||||
|
||||
graph->connect(emissionNode->output("Emission"), graph->output()->input("Surface"));
|
||||
|
||||
@@ -244,13 +241,11 @@ void HdCyclesLight::PopulateShaderGraph(HdSceneDelegate *sceneDelegate)
|
||||
if (value.IsHolding<float>()) {
|
||||
BlackbodyNode *blackbodyNode = graph->create_node<BlackbodyNode>();
|
||||
blackbodyNode->set_temperature(value.UncheckedGet<float>());
|
||||
graph->add(blackbodyNode);
|
||||
|
||||
if (_lightType == HdPrimTypeTokens->domeLight) {
|
||||
VectorMathNode *mathNode = graph->create_node<VectorMathNode>();
|
||||
mathNode->set_math_type(NODE_VECTOR_MATH_MULTIPLY);
|
||||
mathNode->set_vector2(_light->get_strength());
|
||||
graph->add(mathNode);
|
||||
|
||||
graph->connect(blackbodyNode->output("Color"), mathNode->input("Vector1"));
|
||||
graph->connect(mathNode->output("Vector"), outputNode->input("Color"));
|
||||
@@ -273,7 +268,6 @@ void HdCyclesLight::PopulateShaderGraph(HdSceneDelegate *sceneDelegate)
|
||||
TextureCoordinateNode *coordNode = graph->create_node<TextureCoordinateNode>();
|
||||
coordNode->set_ob_tfm(_light->get_tfm());
|
||||
coordNode->set_use_transform(true);
|
||||
graph->add(coordNode);
|
||||
|
||||
IESLightNode *iesNode = graph->create_node<IESLightNode>();
|
||||
iesNode->set_filename(ustring(filename));
|
||||
@@ -299,11 +293,9 @@ void HdCyclesLight::PopulateShaderGraph(HdSceneDelegate *sceneDelegate)
|
||||
TextureCoordinateNode *coordNode = graph->create_node<TextureCoordinateNode>();
|
||||
coordNode->set_ob_tfm(tfm);
|
||||
coordNode->set_use_transform(true);
|
||||
graph->add(coordNode);
|
||||
|
||||
textureNode = graph->create_node<EnvironmentTextureNode>();
|
||||
static_cast<EnvironmentTextureNode *>(textureNode)->set_filename(ustring(filename));
|
||||
graph->add(textureNode);
|
||||
|
||||
graph->connect(coordNode->output("Object"), textureNode->input("Vector"));
|
||||
|
||||
@@ -311,11 +303,9 @@ void HdCyclesLight::PopulateShaderGraph(HdSceneDelegate *sceneDelegate)
|
||||
}
|
||||
else {
|
||||
GeometryNode *coordNode = graph->create_node<GeometryNode>();
|
||||
graph->add(coordNode);
|
||||
|
||||
textureNode = graph->create_node<ImageTextureNode>();
|
||||
static_cast<ImageTextureNode *>(textureNode)->set_filename(ustring(filename));
|
||||
graph->add(textureNode);
|
||||
|
||||
graph->connect(coordNode->output("Parametric"), textureNode->input("Vector"));
|
||||
}
|
||||
@@ -323,7 +313,6 @@ void HdCyclesLight::PopulateShaderGraph(HdSceneDelegate *sceneDelegate)
|
||||
if (hasColorTemperature) {
|
||||
VectorMathNode *mathNode = graph->create_node<VectorMathNode>();
|
||||
mathNode->set_math_type(NODE_VECTOR_MATH_MULTIPLY);
|
||||
graph->add(mathNode);
|
||||
|
||||
graph->connect(textureNode->output("Color"), mathNode->input("Vector1"));
|
||||
ShaderInput *const outputNodeInput = outputNode->input("Color");
|
||||
@@ -335,7 +324,6 @@ void HdCyclesLight::PopulateShaderGraph(HdSceneDelegate *sceneDelegate)
|
||||
VectorMathNode *mathNode = graph->create_node<VectorMathNode>();
|
||||
mathNode->set_math_type(NODE_VECTOR_MATH_MULTIPLY);
|
||||
mathNode->set_vector2(_light->get_strength());
|
||||
graph->add(mathNode);
|
||||
|
||||
graph->connect(textureNode->output("Color"), mathNode->input("Vector1"));
|
||||
graph->connect(mathNode->output("Vector"), outputNode->input("Color"));
|
||||
|
||||
@@ -447,11 +447,7 @@ void HdCyclesMaterial::PopulateShaderGraph(const HdMaterialNetwork2 &networkMap)
|
||||
|
||||
// If it's a native Cycles' node-type, just do the lookup now.
|
||||
if (const NodeType *nodeType = NodeType::find(cyclesType)) {
|
||||
nodeDesc.node = static_cast<ShaderNode *>(nodeType->create(nodeType));
|
||||
nodeDesc.node->set_owner(graph.get());
|
||||
|
||||
graph->add(nodeDesc.node);
|
||||
|
||||
nodeDesc.node = graph->create_node(nodeType);
|
||||
_nodes.emplace(nodePath, nodeDesc);
|
||||
}
|
||||
else {
|
||||
@@ -547,11 +543,9 @@ void HdCyclesMaterial::PopulateShaderGraph(const HdMaterialNetwork2 &networkMap)
|
||||
|
||||
OutputAOVNode *aovNode = graph->create_node<OutputAOVNode>();
|
||||
aovNode->set_name(instanceId);
|
||||
graph->add(aovNode);
|
||||
|
||||
AttributeNode *instanceIdNode = graph->create_node<AttributeNode>();
|
||||
instanceIdNode->set_attribute(instanceId);
|
||||
graph->add(instanceIdNode);
|
||||
|
||||
graph->connect(instanceIdNode->output("Fac"), aovNode->input("Value"));
|
||||
}
|
||||
|
||||
@@ -51,7 +51,6 @@ HdCyclesSession::HdCyclesSession(const SessionParams ¶ms)
|
||||
|
||||
BackgroundNode *bgNode = graph->create_node<BackgroundNode>();
|
||||
bgNode->set_color(one_float3());
|
||||
graph->add(bgNode);
|
||||
|
||||
graph->connect(bgNode->output("Background"), graph->output()->input("Surface"));
|
||||
|
||||
@@ -64,10 +63,8 @@ HdCyclesSession::HdCyclesSession(const SessionParams ¶ms)
|
||||
unique_ptr<ShaderGraph> graph = make_unique<ShaderGraph>();
|
||||
|
||||
ObjectInfoNode *objectNode = graph->create_node<ObjectInfoNode>();
|
||||
graph->add(objectNode);
|
||||
|
||||
DiffuseBsdfNode *diffuseNode = graph->create_node<DiffuseBsdfNode>();
|
||||
graph->add(diffuseNode);
|
||||
|
||||
graph->connect(objectNode->output("Color"), diffuseNode->input("Color"));
|
||||
graph->connect(diffuseNode->output("BSDF"), graph->output()->input("Surface"));
|
||||
@@ -77,11 +74,9 @@ HdCyclesSession::HdCyclesSession(const SessionParams ¶ms)
|
||||
|
||||
OutputAOVNode *aovNode = graph->create_node<OutputAOVNode>();
|
||||
aovNode->set_name(instanceId);
|
||||
graph->add(aovNode);
|
||||
|
||||
AttributeNode *instanceIdNode = graph->create_node<AttributeNode>();
|
||||
instanceIdNode->set_attribute(instanceId);
|
||||
graph->add(instanceIdNode);
|
||||
|
||||
graph->connect(instanceIdNode->output("Fac"), aovNode->input("Value"));
|
||||
|
||||
@@ -138,7 +133,8 @@ void HdCyclesSession::SyncAovBindings(const HdRenderPassAovBindingVector &aovBin
|
||||
Scene *const scene = session->scene.get();
|
||||
|
||||
// Delete all existing passes
|
||||
scene->delete_nodes(set<Pass *>(scene->passes.begin(), scene->passes.end()));
|
||||
const vector<Pass *> &scene_passes = scene->passes;
|
||||
scene->delete_nodes(set<Pass *>(scene_passes.begin(), scene_passes.end()));
|
||||
|
||||
// Update passes with requested AOV bindings
|
||||
_aovBindings = aovBindings;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include "util/log.h"
|
||||
#include "util/progress.h"
|
||||
#include "util/set.h"
|
||||
#include "util/transform.h"
|
||||
#include "util/vector.h"
|
||||
|
||||
@@ -752,7 +753,7 @@ static void update_attributes(AttributeSet &attributes,
|
||||
continue;
|
||||
}
|
||||
|
||||
const ccl::array<char> &attr_data = result.get_data();
|
||||
const array<char> &attr_data = result.get_data();
|
||||
|
||||
/* weak way of detecting if the topology has changed
|
||||
* todo: reuse code from device_update patch */
|
||||
@@ -790,8 +791,6 @@ NODE_DEFINE(AlembicProcedural)
|
||||
SOCKET_FLOAT(default_radius, "Default Radius", 0.01f);
|
||||
SOCKET_FLOAT(scale, "Scale", 1.0f);
|
||||
|
||||
SOCKET_NODE_ARRAY(objects, "Objects", AlembicObject::get_node_type());
|
||||
|
||||
SOCKET_BOOLEAN(use_prefetch, "Use Prefetch", true);
|
||||
SOCKET_INT(prefetch_cache_size, "Prefetch Cache Size", 4096);
|
||||
|
||||
@@ -810,7 +809,7 @@ AlembicProcedural::~AlembicProcedural()
|
||||
ccl::set<Object *> objects_set;
|
||||
const ccl::set<AlembicObject *> abc_objects_set;
|
||||
|
||||
for (Node *node : objects) {
|
||||
for (Node *node : nodes) {
|
||||
AlembicObject *abc_object = static_cast<AlembicObject *>(node);
|
||||
|
||||
if (abc_object->get_object()) {
|
||||
@@ -842,13 +841,14 @@ void AlembicProcedural::generate(Scene *scene, Progress &progress)
|
||||
|
||||
if (frame < start_frame || frame > end_frame) {
|
||||
clear_modified();
|
||||
objects_modified = false;
|
||||
return;
|
||||
}
|
||||
|
||||
bool need_shader_updates = false;
|
||||
bool need_data_updates = false;
|
||||
|
||||
for (Node *object_node : objects) {
|
||||
for (Node *object_node : nodes) {
|
||||
AlembicObject *object = static_cast<AlembicObject *>(object_node);
|
||||
|
||||
if (object->is_modified()) {
|
||||
@@ -876,7 +876,7 @@ void AlembicProcedural::generate(Scene *scene, Progress &progress)
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_modified() && !need_shader_updates && !need_data_updates) {
|
||||
if (!(is_modified() || objects_modified) && !need_shader_updates && !need_data_updates) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -901,11 +901,12 @@ void AlembicProcedural::generate(Scene *scene, Progress &progress)
|
||||
filepath.clear();
|
||||
layers.clear();
|
||||
clear_modified();
|
||||
objects_modified = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!objects_loaded || objects_is_modified()) {
|
||||
if (!objects_loaded || objects_modified) {
|
||||
load_objects(progress);
|
||||
objects_loaded = true;
|
||||
}
|
||||
@@ -913,7 +914,7 @@ void AlembicProcedural::generate(Scene *scene, Progress &progress)
|
||||
const chrono_t frame_time = (chrono_t)((frame - frame_offset) / frame_rate);
|
||||
|
||||
/* Clear the subdivision caches as the data is stored differently. */
|
||||
for (Node *node : objects) {
|
||||
for (Node *node : nodes) {
|
||||
AlembicObject *object = static_cast<AlembicObject *>(node);
|
||||
|
||||
if (object->schema_type != AlembicObject::SUBD) {
|
||||
@@ -927,7 +928,7 @@ void AlembicProcedural::generate(Scene *scene, Progress &progress)
|
||||
|
||||
if (use_prefetch_is_modified()) {
|
||||
if (!use_prefetch) {
|
||||
for (Node *node : objects) {
|
||||
for (Node *node : nodes) {
|
||||
AlembicObject *object = static_cast<AlembicObject *>(node);
|
||||
object->clear_cache();
|
||||
}
|
||||
@@ -938,7 +939,7 @@ void AlembicProcedural::generate(Scene *scene, Progress &progress)
|
||||
/* Check whether the current memory usage fits in the new requested size,
|
||||
* abort the render if it is any higher. */
|
||||
size_t memory_used = 0ul;
|
||||
for (Node *node : objects) {
|
||||
for (Node *node : nodes) {
|
||||
AlembicObject *object = static_cast<AlembicObject *>(node);
|
||||
memory_used += object->get_cached_data().memory_used();
|
||||
}
|
||||
@@ -951,7 +952,7 @@ void AlembicProcedural::generate(Scene *scene, Progress &progress)
|
||||
|
||||
build_caches(progress);
|
||||
|
||||
for (Node *node : objects) {
|
||||
for (Node *node : nodes) {
|
||||
AlembicObject *object = static_cast<AlembicObject *>(node);
|
||||
|
||||
if (progress.get_cancel()) {
|
||||
@@ -983,12 +984,7 @@ void AlembicProcedural::generate(Scene *scene, Progress &progress)
|
||||
}
|
||||
|
||||
clear_modified();
|
||||
}
|
||||
|
||||
void AlembicProcedural::add_object(AlembicObject *object)
|
||||
{
|
||||
objects.push_back_slow(object);
|
||||
tag_objects_modified();
|
||||
objects_modified = false;
|
||||
}
|
||||
|
||||
void AlembicProcedural::tag_update(Scene *scene)
|
||||
@@ -998,7 +994,7 @@ void AlembicProcedural::tag_update(Scene *scene)
|
||||
|
||||
AlembicObject *AlembicProcedural::get_or_create_object(const ustring &path)
|
||||
{
|
||||
for (Node *node : objects) {
|
||||
for (Node *node : nodes) {
|
||||
AlembicObject *object = static_cast<AlembicObject *>(node);
|
||||
|
||||
if (object->get_path() == path) {
|
||||
@@ -1008,8 +1004,7 @@ AlembicObject *AlembicProcedural::get_or_create_object(const ustring &path)
|
||||
|
||||
AlembicObject *object = create_node<AlembicObject>();
|
||||
object->set_path(path);
|
||||
|
||||
add_object(object);
|
||||
objects_modified = true;
|
||||
|
||||
return object;
|
||||
}
|
||||
@@ -1018,7 +1013,7 @@ void AlembicProcedural::load_objects(Progress &progress)
|
||||
{
|
||||
unordered_map<string, AlembicObject *> object_map;
|
||||
|
||||
for (Node *node : objects) {
|
||||
for (Node *node : nodes) {
|
||||
AlembicObject *object = static_cast<AlembicObject *>(node);
|
||||
|
||||
/* only consider newly added objects */
|
||||
@@ -1071,7 +1066,7 @@ void AlembicProcedural::load_objects(Progress &progress)
|
||||
}
|
||||
|
||||
/* Share geometries between instances. */
|
||||
for (Node *node : objects) {
|
||||
for (Node *node : nodes) {
|
||||
AlembicObject *abc_object = static_cast<AlembicObject *>(node);
|
||||
|
||||
if (abc_object->instance_of) {
|
||||
@@ -1498,7 +1493,7 @@ void AlembicProcedural::build_caches(Progress &progress)
|
||||
{
|
||||
size_t memory_used = 0;
|
||||
|
||||
for (Node *node : objects) {
|
||||
for (Node *node : nodes) {
|
||||
AlembicObject *object = static_cast<AlembicObject *>(node);
|
||||
|
||||
if (progress.get_cancel()) {
|
||||
|
||||
@@ -461,8 +461,9 @@ class AlembicObject : public Node {
|
||||
*/
|
||||
class AlembicProcedural : public Procedural {
|
||||
Alembic::AbcGeom::IArchive archive;
|
||||
bool objects_loaded;
|
||||
Scene *scene_;
|
||||
bool objects_loaded = false;
|
||||
bool objects_modified = false;
|
||||
Scene *scene_ = nullptr;
|
||||
|
||||
public:
|
||||
NODE_DECLARE
|
||||
@@ -489,9 +490,6 @@ class AlembicProcedural : public Procedural {
|
||||
/* The frame rate used for rendering in units of frames per second. */
|
||||
NODE_SOCKET_API(float, frame_rate)
|
||||
|
||||
/* List of AlembicObjects to render. */
|
||||
NODE_SOCKET_API_ARRAY(array<Node *>, objects)
|
||||
|
||||
/* Set the default radius to use for curves when the Alembic Curves Schemas do not have radius
|
||||
* information. */
|
||||
NODE_SOCKET_API(float, default_radius)
|
||||
@@ -528,9 +526,6 @@ class AlembicProcedural : public Procedural {
|
||||
AlembicObject *get_or_create_object(const ustring &path);
|
||||
|
||||
private:
|
||||
/* Add an object to our list of objects, and tag the socket as modified. */
|
||||
void add_object(AlembicObject *object);
|
||||
|
||||
/* Load the data for all the objects whose data has not yet been loaded. */
|
||||
void load_objects(Progress &progress);
|
||||
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
#include "scene/stats.h"
|
||||
#include "scene/tables.h"
|
||||
|
||||
#include "util/algorithm.h"
|
||||
|
||||
#include "util/math.h"
|
||||
#include "util/math_cdf.h"
|
||||
#include "util/time.h"
|
||||
@@ -612,31 +610,29 @@ void Film::add_auto_pass(Scene *scene, PassType type, const char *name)
|
||||
|
||||
void Film::add_auto_pass(Scene *scene, PassType type, PassMode mode, const char *name)
|
||||
{
|
||||
Pass *pass = new Pass();
|
||||
unique_ptr<Pass> pass = make_unique<Pass>();
|
||||
pass->set_type(type);
|
||||
pass->set_mode(mode);
|
||||
pass->set_name(ustring((name) ? name : ""));
|
||||
pass->is_auto_ = true;
|
||||
|
||||
pass->set_owner(scene);
|
||||
scene->passes.push_back(pass);
|
||||
scene->passes.push_back(std::move(pass));
|
||||
}
|
||||
|
||||
void Film::remove_auto_passes(Scene *scene)
|
||||
{
|
||||
/* Remove all passes which were automatically created. */
|
||||
vector<Pass *> new_passes;
|
||||
unique_ptr_vector<Pass> new_passes;
|
||||
|
||||
for (Pass *pass : scene->passes) {
|
||||
for (size_t i = 0; i < scene->passes.size(); i++) {
|
||||
unique_ptr<Pass> pass = scene->passes.steal(i);
|
||||
if (!pass->is_auto_) {
|
||||
new_passes.push_back(pass);
|
||||
}
|
||||
else {
|
||||
delete pass;
|
||||
new_passes.push_back(std::move(pass));
|
||||
}
|
||||
}
|
||||
|
||||
scene->passes = new_passes;
|
||||
scene->passes = std::move(new_passes);
|
||||
}
|
||||
|
||||
static bool compare_pass_order(const Pass *a, const Pass *b)
|
||||
@@ -662,9 +658,11 @@ static bool compare_pass_order(const Pass *a, const Pass *b)
|
||||
void Film::finalize_passes(Scene *scene, const bool use_denoise)
|
||||
{
|
||||
/* Remove duplicate passes. */
|
||||
vector<Pass *> new_passes;
|
||||
unique_ptr_vector<Pass> new_passes;
|
||||
|
||||
for (size_t i = 0; i < scene->passes.size(); i++) {
|
||||
unique_ptr<Pass> pass = scene->passes.steal(i);
|
||||
|
||||
for (Pass *pass : scene->passes) {
|
||||
/* Disable denoising on passes if denoising is disabled, or if the
|
||||
* pass does not support it. */
|
||||
pass->set_mode((use_denoise && pass->get_info().support_denoise) ? pass->get_mode() :
|
||||
@@ -696,19 +694,16 @@ void Film::finalize_passes(Scene *scene, const bool use_denoise)
|
||||
}
|
||||
|
||||
if (!duplicate_found) {
|
||||
new_passes.push_back(pass);
|
||||
}
|
||||
else {
|
||||
delete pass;
|
||||
new_passes.push_back(std::move(pass));
|
||||
}
|
||||
}
|
||||
|
||||
/* Order from by components and type, This is required to for AOVs and cryptomatte passes,
|
||||
* which the kernel assumes to be in order. Note this must use stable sort so cryptomatte
|
||||
* passes remain in the right order. */
|
||||
stable_sort(new_passes.begin(), new_passes.end(), compare_pass_order);
|
||||
new_passes.stable_sort(compare_pass_order);
|
||||
|
||||
scene->passes = new_passes;
|
||||
scene->passes = std::move(new_passes);
|
||||
}
|
||||
|
||||
uint Film::get_kernel_features(const Scene *scene) const
|
||||
|
||||
@@ -5,12 +5,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "scene/pass.h"
|
||||
#include "util/string.h"
|
||||
|
||||
#include "kernel/types.h"
|
||||
|
||||
#include "graph/node.h"
|
||||
|
||||
#include "util/string.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
class Device;
|
||||
|
||||
@@ -1123,7 +1123,7 @@ bool GeometryManager::need_update() const
|
||||
|
||||
void GeometryManager::collect_statistics(const Scene *scene, RenderStats *stats)
|
||||
{
|
||||
for (Geometry *geometry : scene->geometry) {
|
||||
for (const Geometry *geometry : scene->geometry) {
|
||||
stats->mesh.geometry.add_entry(
|
||||
NamedSizeEntry(string(geometry->name.c_str()), geometry->get_total_size_in_bytes()));
|
||||
}
|
||||
|
||||
@@ -364,7 +364,7 @@ PassInfo Pass::get_info(const PassType type, const bool include_albedo, const bo
|
||||
return pass_info;
|
||||
}
|
||||
|
||||
bool Pass::contains(const vector<Pass *> &passes, PassType type)
|
||||
bool Pass::contains(const unique_ptr_vector<Pass> &passes, PassType type)
|
||||
{
|
||||
for (const Pass *pass : passes) {
|
||||
if (pass->get_type() != type) {
|
||||
@@ -377,7 +377,7 @@ bool Pass::contains(const vector<Pass *> &passes, PassType type)
|
||||
return false;
|
||||
}
|
||||
|
||||
const Pass *Pass::find(const vector<Pass *> &passes, const string &name)
|
||||
const Pass *Pass::find(const unique_ptr_vector<Pass> &passes, const string &name)
|
||||
{
|
||||
for (const Pass *pass : passes) {
|
||||
if (pass->get_name() == name) {
|
||||
@@ -388,7 +388,7 @@ const Pass *Pass::find(const vector<Pass *> &passes, const string &name)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const Pass *Pass::find(const vector<Pass *> &passes,
|
||||
const Pass *Pass::find(const unique_ptr_vector<Pass> &passes,
|
||||
PassType type,
|
||||
PassMode mode,
|
||||
const ustring &lightgroup)
|
||||
@@ -405,7 +405,7 @@ const Pass *Pass::find(const vector<Pass *> &passes,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int Pass::get_offset(const vector<Pass *> &passes, const Pass *pass)
|
||||
int Pass::get_offset(const unique_ptr_vector<Pass> &passes, const Pass *pass)
|
||||
{
|
||||
int pass_offset = 0;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <iosfwd>
|
||||
|
||||
#include "util/string.h"
|
||||
#include "util/vector.h"
|
||||
#include "util/unique_ptr_vector.h"
|
||||
|
||||
#include "kernel/types.h"
|
||||
|
||||
@@ -78,17 +78,17 @@ class Pass : public Node {
|
||||
const bool include_albedo = false,
|
||||
const bool is_lightgroup = false);
|
||||
|
||||
static bool contains(const vector<Pass *> &passes, PassType type);
|
||||
static bool contains(const unique_ptr_vector<Pass> &passes, PassType type);
|
||||
|
||||
/* Returns nullptr if there is no pass with the given name or type+mode. */
|
||||
static const Pass *find(const vector<Pass *> &passes, const string &name);
|
||||
static const Pass *find(const vector<Pass *> &passes,
|
||||
static const Pass *find(const unique_ptr_vector<Pass> &passes, const string &name);
|
||||
static const Pass *find(const unique_ptr_vector<Pass> &passes,
|
||||
PassType type,
|
||||
PassMode mode = PassMode::NOISY,
|
||||
const ustring &lightgroup = ustring());
|
||||
|
||||
/* Returns PASS_UNUSED if there is no corresponding pass. */
|
||||
static int get_offset(const vector<Pass *> &passes, const Pass *pass);
|
||||
static int get_offset(const unique_ptr_vector<Pass> &passes, const Pass *pass);
|
||||
|
||||
friend class Film;
|
||||
};
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
#include "graph/node.h"
|
||||
|
||||
#include "util/unique_ptr_vector.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
class Progress;
|
||||
@@ -31,17 +33,22 @@ class Procedural : public Node, public NodeOwner {
|
||||
/* Create a node and set this Procedural as the owner. */
|
||||
template<typename T> T *create_node()
|
||||
{
|
||||
T *node = new T();
|
||||
unique_ptr<T> node = make_unique<T>();
|
||||
T *node_ptr = node.get();
|
||||
node->set_owner(this);
|
||||
return node;
|
||||
nodes.push_back(std::move(node));
|
||||
return node_ptr;
|
||||
}
|
||||
|
||||
/* Delete a Node created and owned by this Procedural. */
|
||||
template<typename T> void delete_node(T *node)
|
||||
{
|
||||
assert(node->get_owner() == this);
|
||||
delete node;
|
||||
nodes.erase(node);
|
||||
}
|
||||
|
||||
protected:
|
||||
unique_ptr_vector<Node> nodes;
|
||||
};
|
||||
|
||||
class ProceduralManager {
|
||||
|
||||
@@ -96,30 +96,11 @@ void Scene::free_memory(bool final)
|
||||
* Similarly, we first delete all nodes and their associated device data, and
|
||||
* then the managers and their associated device data.
|
||||
*/
|
||||
for (Procedural *p : procedurals) {
|
||||
delete p;
|
||||
}
|
||||
for (Object *o : objects) {
|
||||
delete o;
|
||||
}
|
||||
for (Geometry *g : geometry) {
|
||||
delete g;
|
||||
}
|
||||
for (ParticleSystem *p : particle_systems) {
|
||||
delete p;
|
||||
}
|
||||
for (Light *l : lights) {
|
||||
delete l;
|
||||
}
|
||||
for (Pass *p : passes) {
|
||||
delete p;
|
||||
}
|
||||
|
||||
geometry.clear();
|
||||
procedurals.clear();
|
||||
objects.clear();
|
||||
geometry.clear();
|
||||
lights.clear();
|
||||
particle_systems.clear();
|
||||
procedurals.clear();
|
||||
passes.clear();
|
||||
|
||||
if (device) {
|
||||
@@ -130,19 +111,20 @@ void Scene::free_memory(bool final)
|
||||
}
|
||||
|
||||
if (final) {
|
||||
delete camera;
|
||||
delete dicing_camera;
|
||||
delete film;
|
||||
delete background;
|
||||
delete integrator;
|
||||
cameras.clear();
|
||||
integrators.clear();
|
||||
films.clear();
|
||||
backgrounds.clear();
|
||||
|
||||
camera = nullptr;
|
||||
dicing_camera = nullptr;
|
||||
integrator = nullptr;
|
||||
film = nullptr;
|
||||
background = nullptr;
|
||||
}
|
||||
|
||||
/* Delete Shaders after every other nodes to ensure that we do not try to
|
||||
* decrement the reference count on some dangling pointer. */
|
||||
for (Shader *s : shaders) {
|
||||
delete s;
|
||||
}
|
||||
|
||||
shaders.clear();
|
||||
|
||||
/* Now that all nodes have been deleted, we can safely delete managers and
|
||||
@@ -756,84 +738,93 @@ void Scene::tag_shadow_catcher_modified()
|
||||
|
||||
template<> Light *Scene::create_node<Light>()
|
||||
{
|
||||
Light *node = new Light();
|
||||
unique_ptr<Light> node = make_unique<Light>();
|
||||
Light *node_ptr = node.get();
|
||||
node->set_owner(this);
|
||||
lights.push_back(node);
|
||||
lights.push_back(std::move(node));
|
||||
light_manager->tag_update(this, LightManager::LIGHT_ADDED);
|
||||
return node;
|
||||
return node_ptr;
|
||||
}
|
||||
|
||||
template<> Mesh *Scene::create_node<Mesh>()
|
||||
{
|
||||
Mesh *node = new Mesh();
|
||||
unique_ptr<Mesh> node = make_unique<Mesh>();
|
||||
Mesh *node_ptr = node.get();
|
||||
node->set_owner(this);
|
||||
geometry.push_back(node);
|
||||
geometry.push_back(std::move(node));
|
||||
geometry_manager->tag_update(this, GeometryManager::MESH_ADDED);
|
||||
return node;
|
||||
return node_ptr;
|
||||
}
|
||||
|
||||
template<> Hair *Scene::create_node<Hair>()
|
||||
{
|
||||
Hair *node = new Hair();
|
||||
unique_ptr<Hair> node = make_unique<Hair>();
|
||||
Hair *node_ptr = node.get();
|
||||
node->set_owner(this);
|
||||
geometry.push_back(node);
|
||||
geometry.push_back(std::move(node));
|
||||
geometry_manager->tag_update(this, GeometryManager::HAIR_ADDED);
|
||||
return node;
|
||||
return node_ptr;
|
||||
}
|
||||
|
||||
template<> Volume *Scene::create_node<Volume>()
|
||||
{
|
||||
Volume *node = new Volume();
|
||||
unique_ptr<Volume> node = make_unique<Volume>();
|
||||
Volume *node_ptr = node.get();
|
||||
node->set_owner(this);
|
||||
geometry.push_back(node);
|
||||
geometry.push_back(std::move(node));
|
||||
geometry_manager->tag_update(this, GeometryManager::MESH_ADDED);
|
||||
return node;
|
||||
return node_ptr;
|
||||
}
|
||||
|
||||
template<> PointCloud *Scene::create_node<PointCloud>()
|
||||
{
|
||||
PointCloud *node = new PointCloud();
|
||||
unique_ptr<PointCloud> node = make_unique<PointCloud>();
|
||||
PointCloud *node_ptr = node.get();
|
||||
node->set_owner(this);
|
||||
geometry.push_back(node);
|
||||
geometry.push_back(std::move(node));
|
||||
geometry_manager->tag_update(this, GeometryManager::POINT_ADDED);
|
||||
return node;
|
||||
return node_ptr;
|
||||
}
|
||||
|
||||
template<> Object *Scene::create_node<Object>()
|
||||
{
|
||||
Object *node = new Object();
|
||||
unique_ptr<Object> node = make_unique<Object>();
|
||||
Object *node_ptr = node.get();
|
||||
node->set_owner(this);
|
||||
objects.push_back(node);
|
||||
objects.push_back(std::move(node));
|
||||
object_manager->tag_update(this, ObjectManager::OBJECT_ADDED);
|
||||
return node;
|
||||
return node_ptr;
|
||||
}
|
||||
|
||||
template<> ParticleSystem *Scene::create_node<ParticleSystem>()
|
||||
{
|
||||
ParticleSystem *node = new ParticleSystem();
|
||||
unique_ptr<ParticleSystem> node = make_unique<ParticleSystem>();
|
||||
ParticleSystem *node_ptr = node.get();
|
||||
node->set_owner(this);
|
||||
particle_systems.push_back(node);
|
||||
particle_systems.push_back(std::move(node));
|
||||
particle_system_manager->tag_update(this);
|
||||
return node;
|
||||
return node_ptr;
|
||||
}
|
||||
|
||||
template<> Shader *Scene::create_node<Shader>()
|
||||
{
|
||||
Shader *node = new Shader();
|
||||
unique_ptr<Shader> node = make_unique<Shader>();
|
||||
Shader *node_ptr = node.get();
|
||||
node->set_owner(this);
|
||||
shaders.push_back(node);
|
||||
shaders.push_back(std::move(node));
|
||||
shader_manager->tag_update(this, ShaderManager::SHADER_ADDED);
|
||||
return node;
|
||||
return node_ptr;
|
||||
}
|
||||
|
||||
template<> AlembicProcedural *Scene::create_node<AlembicProcedural>()
|
||||
{
|
||||
#ifdef WITH_ALEMBIC
|
||||
AlembicProcedural *node = new AlembicProcedural();
|
||||
unique_ptr<AlembicProcedural> node = make_unique<AlembicProcedural>();
|
||||
AlembicProcedural *node_ptr = node.get();
|
||||
node->set_owner(this);
|
||||
procedurals.push_back(node);
|
||||
procedurals.push_back(std::move(node));
|
||||
procedural_manager->tag_update();
|
||||
return node;
|
||||
return node_ptr;
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
@@ -841,59 +832,89 @@ template<> AlembicProcedural *Scene::create_node<AlembicProcedural>()
|
||||
|
||||
template<> Pass *Scene::create_node<Pass>()
|
||||
{
|
||||
Pass *node = new Pass();
|
||||
unique_ptr<Pass> node = make_unique<Pass>();
|
||||
Pass *node_ptr = node.get();
|
||||
node->set_owner(this);
|
||||
passes.push_back(node);
|
||||
passes.push_back(std::move(node));
|
||||
film->tag_modified();
|
||||
return node;
|
||||
return node_ptr;
|
||||
}
|
||||
|
||||
template<typename T> void delete_node_from_array(vector<T> &nodes, T node)
|
||||
template<> Camera *Scene::create_node<Camera>()
|
||||
{
|
||||
for (size_t i = 0; i < nodes.size(); ++i) {
|
||||
if (nodes[i] == node) {
|
||||
std::swap(nodes[i], nodes[nodes.size() - 1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nodes.resize(nodes.size() - 1);
|
||||
|
||||
delete node;
|
||||
unique_ptr<Camera> node = make_unique<Camera>();
|
||||
Camera *node_ptr = node.get();
|
||||
node->set_owner(this);
|
||||
cameras.push_back(std::move(node));
|
||||
return node_ptr;
|
||||
}
|
||||
|
||||
template<> void Scene::delete_node_impl(Light *node)
|
||||
template<> Integrator *Scene::create_node<Integrator>()
|
||||
{
|
||||
delete_node_from_array(lights, node);
|
||||
unique_ptr<Integrator> node = make_unique<Integrator>();
|
||||
Integrator *node_ptr = node.get();
|
||||
node->set_owner(this);
|
||||
integrators.push_back(std::move(node));
|
||||
return node_ptr;
|
||||
}
|
||||
|
||||
template<> Background *Scene::create_node<Background>()
|
||||
{
|
||||
unique_ptr<Background> node = make_unique<Background>();
|
||||
Background *node_ptr = node.get();
|
||||
node->set_owner(this);
|
||||
backgrounds.push_back(std::move(node));
|
||||
return node_ptr;
|
||||
}
|
||||
|
||||
template<> Film *Scene::create_node<Film>()
|
||||
{
|
||||
unique_ptr<Film> node = make_unique<Film>();
|
||||
Film *node_ptr = node.get();
|
||||
node->set_owner(this);
|
||||
films.push_back(std::move(node));
|
||||
return node_ptr;
|
||||
}
|
||||
|
||||
template<> void Scene::delete_node(Light *node)
|
||||
{
|
||||
assert(node->get_owner() == this);
|
||||
lights.erase_by_swap(node);
|
||||
light_manager->tag_update(this, LightManager::LIGHT_REMOVED);
|
||||
}
|
||||
|
||||
template<> void Scene::delete_node_impl(Mesh *node)
|
||||
template<> void Scene::delete_node(Mesh *node)
|
||||
{
|
||||
delete_node_from_array(geometry, static_cast<Geometry *>(node));
|
||||
assert(node->get_owner() == this);
|
||||
geometry.erase_by_swap(node);
|
||||
geometry_manager->tag_update(this, GeometryManager::MESH_REMOVED);
|
||||
}
|
||||
|
||||
template<> void Scene::delete_node_impl(Hair *node)
|
||||
template<> void Scene::delete_node(Hair *node)
|
||||
{
|
||||
delete_node_from_array(geometry, static_cast<Geometry *>(node));
|
||||
assert(node->get_owner() == this);
|
||||
geometry.erase_by_swap(node);
|
||||
geometry_manager->tag_update(this, GeometryManager::HAIR_REMOVED);
|
||||
}
|
||||
|
||||
template<> void Scene::delete_node_impl(Volume *node)
|
||||
template<> void Scene::delete_node(Volume *node)
|
||||
{
|
||||
delete_node_from_array(geometry, static_cast<Geometry *>(node));
|
||||
assert(node->get_owner() == this);
|
||||
geometry.erase_by_swap(node);
|
||||
geometry_manager->tag_update(this, GeometryManager::MESH_REMOVED);
|
||||
}
|
||||
|
||||
template<> void Scene::delete_node_impl(PointCloud *node)
|
||||
template<> void Scene::delete_node(PointCloud *node)
|
||||
{
|
||||
delete_node_from_array(geometry, static_cast<Geometry *>(node));
|
||||
assert(node->get_owner() == this);
|
||||
geometry.erase_by_swap(node);
|
||||
geometry_manager->tag_update(this, GeometryManager::POINT_REMOVED);
|
||||
}
|
||||
|
||||
template<> void Scene::delete_node_impl(Geometry *node)
|
||||
template<> void Scene::delete_node(Geometry *node)
|
||||
{
|
||||
assert(node->get_owner() == this);
|
||||
|
||||
uint flag;
|
||||
if (node->is_hair()) {
|
||||
flag = GeometryManager::HAIR_REMOVED;
|
||||
@@ -902,95 +923,91 @@ template<> void Scene::delete_node_impl(Geometry *node)
|
||||
flag = GeometryManager::MESH_REMOVED;
|
||||
}
|
||||
|
||||
delete_node_from_array(geometry, node);
|
||||
geometry.erase_by_swap(node);
|
||||
geometry_manager->tag_update(this, flag);
|
||||
}
|
||||
|
||||
template<> void Scene::delete_node_impl(Object *node)
|
||||
template<> void Scene::delete_node(Object *node)
|
||||
{
|
||||
delete_node_from_array(objects, node);
|
||||
assert(node->get_owner() == this);
|
||||
objects.erase_by_swap(node);
|
||||
object_manager->tag_update(this, ObjectManager::OBJECT_REMOVED);
|
||||
}
|
||||
|
||||
template<> void Scene::delete_node_impl(ParticleSystem *node)
|
||||
template<> void Scene::delete_node(ParticleSystem *node)
|
||||
{
|
||||
delete_node_from_array(particle_systems, node);
|
||||
assert(node->get_owner() == this);
|
||||
particle_systems.erase_by_swap(node);
|
||||
particle_system_manager->tag_update(this);
|
||||
}
|
||||
|
||||
template<> void Scene::delete_node_impl(Shader *node)
|
||||
template<> void Scene::delete_node(Shader *node)
|
||||
{
|
||||
assert(node->get_owner() == this);
|
||||
/* don't delete unused shaders, not supported */
|
||||
node->clear_reference_count();
|
||||
}
|
||||
|
||||
template<> void Scene::delete_node_impl(Procedural *node)
|
||||
template<> void Scene::delete_node(Procedural *node)
|
||||
{
|
||||
delete_node_from_array(procedurals, node);
|
||||
assert(node->get_owner() == this);
|
||||
procedurals.erase_by_swap(node);
|
||||
procedural_manager->tag_update();
|
||||
}
|
||||
|
||||
template<> void Scene::delete_node_impl(AlembicProcedural *node)
|
||||
template<> void Scene::delete_node(AlembicProcedural *node)
|
||||
{
|
||||
#ifdef WITH_ALEMBIC
|
||||
delete_node_impl(static_cast<Procedural *>(node));
|
||||
delete_node(static_cast<Procedural *>(node));
|
||||
#else
|
||||
(void)node;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<> void Scene::delete_node_impl(Pass *node)
|
||||
template<> void Scene::delete_node(Pass *node)
|
||||
{
|
||||
delete_node_from_array(passes, node);
|
||||
assert(node->get_owner() == this);
|
||||
passes.erase_by_swap(node);
|
||||
film->tag_modified();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void remove_nodes_in_set(const set<T *> &nodes_set,
|
||||
vector<T *> &nodes_array,
|
||||
const NodeOwner *owner)
|
||||
template<typename T> static void assert_same_owner(const set<T *> &nodes, const NodeOwner *owner)
|
||||
{
|
||||
size_t new_size = nodes_array.size();
|
||||
|
||||
for (size_t i = 0; i < new_size; ++i) {
|
||||
T *node = nodes_array[i];
|
||||
|
||||
if (nodes_set.find(node) != nodes_set.end()) {
|
||||
std::swap(nodes_array[i], nodes_array[new_size - 1]);
|
||||
|
||||
assert(node->get_owner() == owner);
|
||||
delete node;
|
||||
|
||||
i -= 1;
|
||||
new_size -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
nodes_array.resize(new_size);
|
||||
#ifdef NDEBUG
|
||||
(void)nodes;
|
||||
(void)owner;
|
||||
#else
|
||||
for (const T *node : nodes) {
|
||||
assert(node->get_owner() == owner);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template<> void Scene::delete_nodes(const set<Light *> &nodes, const NodeOwner *owner)
|
||||
{
|
||||
remove_nodes_in_set(nodes, lights, owner);
|
||||
assert_same_owner(nodes, owner);
|
||||
lights.erase_in_set(nodes);
|
||||
light_manager->tag_update(this, LightManager::LIGHT_REMOVED);
|
||||
}
|
||||
|
||||
template<> void Scene::delete_nodes(const set<Geometry *> &nodes, const NodeOwner *owner)
|
||||
{
|
||||
remove_nodes_in_set(nodes, geometry, owner);
|
||||
assert_same_owner(nodes, owner);
|
||||
geometry.erase_in_set(nodes);
|
||||
geometry_manager->tag_update(this, GeometryManager::GEOMETRY_REMOVED);
|
||||
}
|
||||
|
||||
template<> void Scene::delete_nodes(const set<Object *> &nodes, const NodeOwner *owner)
|
||||
{
|
||||
remove_nodes_in_set(nodes, objects, owner);
|
||||
assert_same_owner(nodes, owner);
|
||||
objects.erase_in_set(nodes);
|
||||
object_manager->tag_update(this, ObjectManager::OBJECT_REMOVED);
|
||||
}
|
||||
|
||||
template<> void Scene::delete_nodes(const set<ParticleSystem *> &nodes, const NodeOwner *owner)
|
||||
{
|
||||
remove_nodes_in_set(nodes, particle_systems, owner);
|
||||
assert_same_owner(nodes, owner);
|
||||
particle_systems.erase_in_set(nodes);
|
||||
particle_system_manager->tag_update(this);
|
||||
}
|
||||
|
||||
@@ -1004,13 +1021,15 @@ template<> void Scene::delete_nodes(const set<Shader *> &nodes, const NodeOwner
|
||||
|
||||
template<> void Scene::delete_nodes(const set<Procedural *> &nodes, const NodeOwner *owner)
|
||||
{
|
||||
remove_nodes_in_set(nodes, procedurals, owner);
|
||||
assert_same_owner(nodes, owner);
|
||||
procedurals.erase_in_set(nodes);
|
||||
procedural_manager->tag_update();
|
||||
}
|
||||
|
||||
template<> void Scene::delete_nodes(const set<Pass *> &nodes, const NodeOwner *owner)
|
||||
{
|
||||
remove_nodes_in_set(nodes, passes, owner);
|
||||
assert_same_owner(nodes, owner);
|
||||
passes.erase_in_set(nodes);
|
||||
film->tag_modified();
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#include "util/param.h"
|
||||
#include "util/string.h"
|
||||
#include "util/thread.h"
|
||||
#include "util/unique_ptr.h"
|
||||
#include "util/unique_ptr_vector.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
@@ -127,13 +129,17 @@ class Scene : public NodeOwner {
|
||||
Integrator *integrator;
|
||||
|
||||
/* data lists */
|
||||
vector<Object *> objects;
|
||||
vector<Geometry *> geometry;
|
||||
vector<Shader *> shaders;
|
||||
vector<Light *> lights;
|
||||
vector<ParticleSystem *> particle_systems;
|
||||
vector<Pass *> passes;
|
||||
vector<Procedural *> procedurals;
|
||||
unique_ptr_vector<Background> backgrounds;
|
||||
unique_ptr_vector<Film> films;
|
||||
unique_ptr_vector<Integrator> integrators;
|
||||
unique_ptr_vector<Camera> cameras;
|
||||
unique_ptr_vector<Shader> shaders;
|
||||
unique_ptr_vector<Pass> passes;
|
||||
unique_ptr_vector<ParticleSystem> particle_systems;
|
||||
unique_ptr_vector<Light> lights;
|
||||
unique_ptr_vector<Geometry> geometry;
|
||||
unique_ptr_vector<Object> objects;
|
||||
unique_ptr_vector<Procedural> procedurals;
|
||||
|
||||
/* data managers */
|
||||
unique_ptr<ImageManager> image_manager;
|
||||
@@ -199,12 +205,7 @@ class Scene : public NodeOwner {
|
||||
* node array (e.g. Scene::geometry for Geometry nodes) and tag the appropriate
|
||||
* manager for an update.
|
||||
*/
|
||||
template<typename T, typename... Args> T *create_node(Args &&...args)
|
||||
{
|
||||
T *node = new T(args...);
|
||||
node->set_owner(this);
|
||||
return node;
|
||||
}
|
||||
template<typename T, typename... Args> T *create_node(Args &&.../*args*/) = delete;
|
||||
|
||||
/* This function is used to delete a node from the scene instead of calling 'delete'
|
||||
* and manually removing the node from the data array. It also tags the
|
||||
@@ -212,20 +213,7 @@ class Scene : public NodeOwner {
|
||||
* the owner of the node. Calling this function on a node not owned by the scene
|
||||
* will likely cause a crash which we want in order to detect such cases.
|
||||
*/
|
||||
template<typename T> void delete_node(T *node)
|
||||
{
|
||||
assert(node->get_owner() == this);
|
||||
delete_node_impl(node);
|
||||
}
|
||||
|
||||
/* Same as above, but specify the actual owner.
|
||||
*/
|
||||
template<typename T> void delete_node(T *node, const NodeOwner *owner)
|
||||
{
|
||||
assert(node->get_owner() == owner);
|
||||
delete_node_impl(node);
|
||||
(void)owner;
|
||||
}
|
||||
template<typename T> void delete_node(T *node) = delete;
|
||||
|
||||
/* Remove all nodes in the set from the appropriate data arrays, and tag the
|
||||
* specific managers for an update. This assumes that the scene owns the nodes.
|
||||
@@ -263,69 +251,42 @@ class Scene : public NodeOwner {
|
||||
|
||||
/* Get size of a volume stack needed to render this scene. */
|
||||
int get_volume_stack_size() const;
|
||||
|
||||
template<typename T> void delete_node_impl(T *node)
|
||||
{
|
||||
delete node;
|
||||
}
|
||||
};
|
||||
|
||||
template<> Light *Scene::create_node<Light>();
|
||||
|
||||
template<> Mesh *Scene::create_node<Mesh>();
|
||||
|
||||
template<> Object *Scene::create_node<Object>();
|
||||
|
||||
template<> Hair *Scene::create_node<Hair>();
|
||||
|
||||
template<> Volume *Scene::create_node<Volume>();
|
||||
|
||||
template<> PointCloud *Scene::create_node<PointCloud>();
|
||||
|
||||
template<> ParticleSystem *Scene::create_node<ParticleSystem>();
|
||||
|
||||
template<> Shader *Scene::create_node<Shader>();
|
||||
|
||||
template<> AlembicProcedural *Scene::create_node<AlembicProcedural>();
|
||||
|
||||
template<> Pass *Scene::create_node<Pass>();
|
||||
template<> Camera *Scene::create_node<Camera>();
|
||||
template<> Background *Scene::create_node<Background>();
|
||||
template<> Film *Scene::create_node<Film>();
|
||||
template<> Integrator *Scene::create_node<Integrator>();
|
||||
|
||||
template<> void Scene::delete_node_impl(Light *node);
|
||||
|
||||
template<> void Scene::delete_node_impl(Mesh *node);
|
||||
|
||||
template<> void Scene::delete_node_impl(Volume *node);
|
||||
|
||||
template<> void Scene::delete_node_impl(PointCloud *node);
|
||||
|
||||
template<> void Scene::delete_node_impl(Hair *node);
|
||||
|
||||
template<> void Scene::delete_node_impl(Geometry *node);
|
||||
|
||||
template<> void Scene::delete_node_impl(Object *node);
|
||||
|
||||
template<> void Scene::delete_node_impl(ParticleSystem *node);
|
||||
|
||||
template<> void Scene::delete_node_impl(Shader *node);
|
||||
|
||||
template<> void Scene::delete_node_impl(Procedural *node);
|
||||
|
||||
template<> void Scene::delete_node_impl(AlembicProcedural *node);
|
||||
|
||||
template<> void Scene::delete_node_impl(Pass *node);
|
||||
template<> void Scene::delete_node(Light *node);
|
||||
template<> void Scene::delete_node(Mesh *node);
|
||||
template<> void Scene::delete_node(Volume *node);
|
||||
template<> void Scene::delete_node(PointCloud *node);
|
||||
template<> void Scene::delete_node(Hair *node);
|
||||
template<> void Scene::delete_node(Geometry *node);
|
||||
template<> void Scene::delete_node(Object *node);
|
||||
template<> void Scene::delete_node(ParticleSystem *node);
|
||||
template<> void Scene::delete_node(Shader *node);
|
||||
template<> void Scene::delete_node(Procedural *node);
|
||||
template<> void Scene::delete_node(AlembicProcedural *node);
|
||||
template<> void Scene::delete_node(Pass *node);
|
||||
|
||||
template<> void Scene::delete_nodes(const set<Light *> &nodes, const NodeOwner *owner);
|
||||
|
||||
template<> void Scene::delete_nodes(const set<Geometry *> &nodes, const NodeOwner *owner);
|
||||
|
||||
template<> void Scene::delete_nodes(const set<Object *> &nodes, const NodeOwner *owner);
|
||||
|
||||
template<> void Scene::delete_nodes(const set<ParticleSystem *> &nodes, const NodeOwner *owner);
|
||||
|
||||
template<> void Scene::delete_nodes(const set<Shader *> &nodes, const NodeOwner *owner);
|
||||
|
||||
template<> void Scene::delete_nodes(const set<Procedural *> &nodes, const NodeOwner *owner);
|
||||
|
||||
template<> void Scene::delete_nodes(const set<Pass *> &nodes, const NodeOwner *owner);
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
@@ -348,7 +348,6 @@ void Shader::tag_update(Scene *scene)
|
||||
for (const ShaderInput *in : node->inputs) {
|
||||
if (in->link) {
|
||||
TransparentBsdfNode *transparent = graph->create_node<TransparentBsdfNode>();
|
||||
graph->add(transparent);
|
||||
graph->connect(transparent->output("BSDF"), output->input("Surface"));
|
||||
has_surface = true;
|
||||
break;
|
||||
@@ -659,7 +658,6 @@ void ShaderManager::add_default(Scene *scene)
|
||||
|
||||
DiffuseBsdfNode *diffuse = graph->create_node<DiffuseBsdfNode>();
|
||||
diffuse->set_color(make_float3(0.8f, 0.8f, 0.8f));
|
||||
graph->add(diffuse);
|
||||
|
||||
graph->connect(diffuse->output("BSDF"), graph->output()->input("Surface"));
|
||||
|
||||
@@ -676,7 +674,6 @@ void ShaderManager::add_default(Scene *scene)
|
||||
unique_ptr<ShaderGraph> graph = make_unique<ShaderGraph>();
|
||||
|
||||
PrincipledVolumeNode *principled = graph->create_node<PrincipledVolumeNode>();
|
||||
graph->add(principled);
|
||||
|
||||
graph->connect(principled->output("Volume"), graph->output()->input("Volume"));
|
||||
|
||||
@@ -696,7 +693,6 @@ void ShaderManager::add_default(Scene *scene)
|
||||
EmissionNode *emission = graph->create_node<EmissionNode>();
|
||||
emission->set_color(make_float3(0.8f, 0.8f, 0.8f));
|
||||
emission->set_strength(0.0f);
|
||||
graph->add(emission);
|
||||
|
||||
graph->connect(emission->output("Emission"), graph->output()->input("Surface"));
|
||||
|
||||
|
||||
@@ -66,35 +66,27 @@ void ShaderOutput::disconnect()
|
||||
|
||||
ShaderNode::ShaderNode(const NodeType *type) : Node(type)
|
||||
{
|
||||
name = type->name;
|
||||
id = -1;
|
||||
bump = SHADER_BUMP_NONE;
|
||||
special_type = SHADER_SPECIAL_TYPE_NONE;
|
||||
|
||||
create_inputs_outputs(type);
|
||||
}
|
||||
|
||||
ShaderNode::~ShaderNode()
|
||||
ShaderNode::ShaderNode(const ShaderNode &other)
|
||||
: Node(other.type), bump(other.bump), special_type(other.special_type)
|
||||
{
|
||||
for (ShaderInput *socket : inputs) {
|
||||
delete socket;
|
||||
}
|
||||
|
||||
for (ShaderOutput *socket : outputs) {
|
||||
delete socket;
|
||||
}
|
||||
/* Inputs and outputs are recreated, no links to other nodes will remain. */
|
||||
name = other.name;
|
||||
create_inputs_outputs(type);
|
||||
}
|
||||
|
||||
void ShaderNode::create_inputs_outputs(const NodeType *type)
|
||||
{
|
||||
for (const SocketType &socket : type->inputs) {
|
||||
if (socket.flags & SocketType::LINKABLE) {
|
||||
inputs.push_back(new ShaderInput(socket, this));
|
||||
inputs.push_back(make_unique<ShaderInput>(socket, this));
|
||||
}
|
||||
}
|
||||
|
||||
for (const SocketType &socket : type->outputs) {
|
||||
outputs.push_back(new ShaderOutput(socket, this));
|
||||
outputs.push_back(make_unique<ShaderOutput>(socket, this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,8 +137,7 @@ ShaderOutput *ShaderNode::output(ustring name)
|
||||
void ShaderNode::remove_input(ShaderInput *input)
|
||||
{
|
||||
assert(input->link == nullptr);
|
||||
delete input;
|
||||
inputs.erase(remove(inputs.begin(), inputs.end(), input), inputs.end());
|
||||
inputs.erase(input);
|
||||
}
|
||||
|
||||
void ShaderNode::attributes(Shader *shader, AttributeRequestSet *attributes)
|
||||
@@ -221,7 +212,7 @@ ShaderGraph::ShaderGraph()
|
||||
finalized = false;
|
||||
simplified = false;
|
||||
num_node_ids = 0;
|
||||
add(create_node<OutputNode>());
|
||||
create_node<OutputNode>();
|
||||
}
|
||||
|
||||
ShaderGraph::~ShaderGraph()
|
||||
@@ -229,19 +220,19 @@ ShaderGraph::~ShaderGraph()
|
||||
clear_nodes();
|
||||
}
|
||||
|
||||
ShaderNode *ShaderGraph::add(ShaderNode *node)
|
||||
void ShaderGraph::add_node(unique_ptr<ShaderNode> &&node)
|
||||
{
|
||||
assert(!finalized);
|
||||
simplified = false;
|
||||
|
||||
node->set_owner(this);
|
||||
node->id = num_node_ids++;
|
||||
nodes.push_back(node);
|
||||
return node;
|
||||
nodes.push_back(std::move(node));
|
||||
}
|
||||
|
||||
OutputNode *ShaderGraph::output()
|
||||
{
|
||||
return (OutputNode *)nodes.front();
|
||||
return static_cast<OutputNode *>(nodes[0]);
|
||||
}
|
||||
|
||||
void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to)
|
||||
@@ -276,7 +267,7 @@ void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to)
|
||||
emission->from_auto_conversion = true;
|
||||
emission->set_color(one_float3());
|
||||
emission->set_strength(1.0f);
|
||||
convert = add(emission);
|
||||
convert = emission;
|
||||
/* Connect float inputs to Strength to save an additional Value->Color conversion. */
|
||||
if (from->type() == SocketType::FLOAT) {
|
||||
convert_in = convert->input("Strength");
|
||||
@@ -286,7 +277,7 @@ void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to)
|
||||
}
|
||||
}
|
||||
else {
|
||||
convert = add(create_node<ConvertNode>(from->type(), to->type(), true));
|
||||
convert = create_node<ConvertNode>(from->type(), to->type(), true);
|
||||
convert_in = convert->inputs[0];
|
||||
}
|
||||
|
||||
@@ -420,9 +411,6 @@ void ShaderGraph::find_dependencies(ShaderNodeSet &dependencies, ShaderInput *in
|
||||
|
||||
void ShaderGraph::clear_nodes()
|
||||
{
|
||||
for (ShaderNode *node : nodes) {
|
||||
delete_node(node);
|
||||
}
|
||||
nodes.clear();
|
||||
}
|
||||
|
||||
@@ -435,13 +423,6 @@ void ShaderGraph::copy_nodes(ShaderNodeSet &nodes, ShaderNodeMap &nnodemap)
|
||||
for (ShaderNode *node : nodes) {
|
||||
ShaderNode *nnode = node->clone(this);
|
||||
nnodemap[node] = nnode;
|
||||
|
||||
/* create new inputs and outputs to recreate links and ensure
|
||||
* that we still point to valid SocketType if the NodeType
|
||||
* changed in cloning, as it does for OSL nodes */
|
||||
nnode->inputs.clear();
|
||||
nnode->outputs.clear();
|
||||
nnode->create_inputs_outputs(nnode->type);
|
||||
}
|
||||
|
||||
/* recreate links */
|
||||
@@ -525,18 +506,16 @@ void ShaderGraph::remove_proxy_nodes()
|
||||
|
||||
/* remove nodes */
|
||||
if (any_node_removed) {
|
||||
list<ShaderNode *> newnodes;
|
||||
unique_ptr_vector<ShaderNode> newnodes;
|
||||
|
||||
for (ShaderNode *node : nodes) {
|
||||
for (size_t i = 0; i < nodes.size(); i++) {
|
||||
unique_ptr<ShaderNode> node = nodes.steal(i);
|
||||
if (!removed[node->id]) {
|
||||
newnodes.push_back(node);
|
||||
}
|
||||
else {
|
||||
delete_node(node);
|
||||
newnodes.push_back(std::move(node));
|
||||
}
|
||||
}
|
||||
|
||||
nodes = newnodes;
|
||||
nodes = std::move(newnodes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -596,7 +575,7 @@ void ShaderGraph::constant_fold(Scene *scene)
|
||||
* that happens to ensure there is still a valid graph for displacement.
|
||||
*/
|
||||
if (has_displacement && !output()->input("Displacement")->link) {
|
||||
ColorNode *value = (ColorNode *)add(create_node<ColorNode>());
|
||||
ColorNode *value = create_node<ColorNode>();
|
||||
value->set_value(output()->get_displacement());
|
||||
|
||||
connect(value->output("Color"), output()->input("Displacement"));
|
||||
@@ -828,24 +807,25 @@ void ShaderGraph::clean(Scene *scene)
|
||||
}
|
||||
|
||||
/* remove unused nodes */
|
||||
list<ShaderNode *> newnodes;
|
||||
unique_ptr_vector<ShaderNode> newnodes;
|
||||
|
||||
for (ShaderNode *node : nodes) {
|
||||
for (size_t i = 0; i < nodes.size(); i++) {
|
||||
unique_ptr<ShaderNode> node = nodes.steal(i);
|
||||
if (visited[node->id]) {
|
||||
newnodes.push_back(node);
|
||||
}
|
||||
else {
|
||||
delete_node(node);
|
||||
newnodes.push_back(std::move(node));
|
||||
}
|
||||
}
|
||||
|
||||
nodes = newnodes;
|
||||
nodes = std::move(newnodes);
|
||||
}
|
||||
|
||||
void ShaderGraph::expand()
|
||||
{
|
||||
/* Call expand on all nodes, to generate additional nodes. */
|
||||
for (ShaderNode *node : nodes) {
|
||||
/* Call expand on all nodes, to generate additional nodes.
|
||||
* No range based for loop because we modify the vector, and want to expand
|
||||
* newly generated nodes too. */
|
||||
for (size_t i = 0; i < nodes.size(); i++) {
|
||||
ShaderNode *node = nodes[i];
|
||||
node->expand(this);
|
||||
}
|
||||
}
|
||||
@@ -859,7 +839,9 @@ void ShaderGraph::default_inputs(bool do_osl)
|
||||
TextureCoordinateNode *texco = nullptr;
|
||||
VectorTransformNode *normal_transform = nullptr;
|
||||
|
||||
for (ShaderNode *node : nodes) {
|
||||
for (size_t i = 0; i < nodes.size(); i++) {
|
||||
ShaderNode *node = nodes[i];
|
||||
|
||||
for (ShaderInput *input : node->inputs) {
|
||||
if (!input->link && (!(input->flags() & SocketType::OSL_INTERNAL) || do_osl)) {
|
||||
if (input->flags() & SocketType::LINK_TEXTURE_GENERATED) {
|
||||
@@ -928,16 +910,6 @@ void ShaderGraph::default_inputs(bool do_osl)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (geom) {
|
||||
add(geom);
|
||||
}
|
||||
if (texco) {
|
||||
add(texco);
|
||||
}
|
||||
if (normal_transform) {
|
||||
add(normal_transform);
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderGraph::refine_bump_nodes()
|
||||
@@ -947,7 +919,10 @@ void ShaderGraph::refine_bump_nodes()
|
||||
* input to the inputs "center","dx" and "dy" What is in "bump" input is moved
|
||||
* to "center" input. */
|
||||
|
||||
for (ShaderNode *node : nodes) {
|
||||
/* No range based for loop because we modify the vector. */
|
||||
for (int i = 0; i < nodes.size(); i++) {
|
||||
ShaderNode *node = nodes[i];
|
||||
|
||||
if (node->special_type == SHADER_SPECIAL_TYPE_BUMP && node->input("Height")->link) {
|
||||
ShaderInput *bump_input = node->input("Height");
|
||||
ShaderNodeSet nodes_bump;
|
||||
@@ -981,14 +956,6 @@ void ShaderGraph::refine_bump_nodes()
|
||||
connect(out_dx, node->input("SampleX"));
|
||||
connect(out_dy, node->input("SampleY"));
|
||||
|
||||
/* Add generated nodes. */
|
||||
for (const NodePair &pair : nodes_dx) {
|
||||
add(pair.second);
|
||||
}
|
||||
for (const NodePair &pair : nodes_dy) {
|
||||
add(pair.second);
|
||||
}
|
||||
|
||||
/* Connect what is connected is bump to sample-center input. */
|
||||
connect(out, node->input("SampleCenter"));
|
||||
|
||||
@@ -1050,10 +1017,10 @@ void ShaderGraph::bump_from_displacement(bool use_object_space)
|
||||
* output, so it can finally set the shader normal, note we are only doing
|
||||
* this for bump from displacement, this will be the only bump allowed to
|
||||
* overwrite the shader normal */
|
||||
ShaderNode *set_normal = add(create_node<SetNormalNode>());
|
||||
ShaderNode *set_normal = create_node<SetNormalNode>();
|
||||
|
||||
/* add bump node and connect copied graphs to it */
|
||||
BumpNode *bump = (BumpNode *)add(create_node<BumpNode>());
|
||||
BumpNode *bump = create_node<BumpNode>();
|
||||
bump->set_use_object_space(use_object_space);
|
||||
bump->set_distance(1.0f);
|
||||
|
||||
@@ -1063,15 +1030,15 @@ void ShaderGraph::bump_from_displacement(bool use_object_space)
|
||||
ShaderOutput *out_dy = nodes_dy[out->parent]->output(out->name());
|
||||
|
||||
/* convert displacement vector to height */
|
||||
VectorMathNode *dot_center = (VectorMathNode *)add(create_node<VectorMathNode>());
|
||||
VectorMathNode *dot_dx = (VectorMathNode *)add(create_node<VectorMathNode>());
|
||||
VectorMathNode *dot_dy = (VectorMathNode *)add(create_node<VectorMathNode>());
|
||||
VectorMathNode *dot_center = create_node<VectorMathNode>();
|
||||
VectorMathNode *dot_dx = create_node<VectorMathNode>();
|
||||
VectorMathNode *dot_dy = create_node<VectorMathNode>();
|
||||
|
||||
dot_center->set_math_type(NODE_VECTOR_MATH_DOT_PRODUCT);
|
||||
dot_dx->set_math_type(NODE_VECTOR_MATH_DOT_PRODUCT);
|
||||
dot_dy->set_math_type(NODE_VECTOR_MATH_DOT_PRODUCT);
|
||||
|
||||
GeometryNode *geom = (GeometryNode *)add(create_node<GeometryNode>());
|
||||
GeometryNode *geom = create_node<GeometryNode>();
|
||||
connect(geom->output("Normal"), bump->input("Normal"));
|
||||
connect(geom->output("Normal"), dot_center->input("Vector2"));
|
||||
connect(geom->output("Normal"), dot_dx->input("Vector2"));
|
||||
@@ -1090,18 +1057,6 @@ void ShaderGraph::bump_from_displacement(bool use_object_space)
|
||||
|
||||
/* connect to output node */
|
||||
connect(set_normal->output("Normal"), output()->input("Normal"));
|
||||
|
||||
/* finally, add the copied nodes to the graph. we can't do this earlier
|
||||
* because we would create dependency cycles in the above loop */
|
||||
for (const NodePair &pair : nodes_center) {
|
||||
add(pair.second);
|
||||
}
|
||||
for (const NodePair &pair : nodes_dx) {
|
||||
add(pair.second);
|
||||
}
|
||||
for (const NodePair &pair : nodes_dy) {
|
||||
add(pair.second);
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight_out, bool volume)
|
||||
@@ -1121,7 +1076,6 @@ void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight
|
||||
if (fin) {
|
||||
/* mix closure: add node to mix closure weights */
|
||||
MixClosureWeightNode *mix_node = create_node<MixClosureWeightNode>();
|
||||
add(mix_node);
|
||||
ShaderInput *fac_in = mix_node->input("Fac");
|
||||
ShaderInput *weight_in = mix_node->input("Weight");
|
||||
|
||||
@@ -1164,7 +1118,6 @@ void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight
|
||||
const float weight_value = node->get_float(weight_in->socket_type);
|
||||
if (weight_in->link || weight_value != 0.0f) {
|
||||
MathNode *math_node = create_node<MathNode>();
|
||||
add(math_node);
|
||||
|
||||
if (weight_in->link) {
|
||||
connect(weight_in->link, math_node->input("Value1"));
|
||||
@@ -1214,8 +1167,8 @@ int ShaderGraph::get_num_closures()
|
||||
num_closures += 12;
|
||||
}
|
||||
else if (CLOSURE_IS_VOLUME(closure_type)) {
|
||||
/* TODO(sergey): Verify this is still needed, since we have special minimized volume storage
|
||||
* for the volume steps. */
|
||||
/* TODO(sergey): Verify this is still needed, since we have special minimized volume
|
||||
* storage for the volume steps. */
|
||||
num_closures += MAX_VOLUME_STACK_SIZE;
|
||||
}
|
||||
else if (closure_type == CLOSURE_BSDF_PHYSICAL_CONDUCTOR ||
|
||||
|
||||
@@ -9,12 +9,12 @@
|
||||
|
||||
#include "kernel/types.h"
|
||||
|
||||
#include "util/list.h"
|
||||
#include "util/map.h"
|
||||
#include "util/param.h"
|
||||
#include "util/set.h"
|
||||
#include "util/string.h"
|
||||
#include "util/types.h"
|
||||
#include "util/unique_ptr_vector.h"
|
||||
#include "util/vector.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
@@ -146,7 +146,7 @@ class ShaderOutput {
|
||||
class ShaderNode : public Node {
|
||||
public:
|
||||
explicit ShaderNode(const NodeType *type);
|
||||
~ShaderNode() override;
|
||||
ShaderNode(const ShaderNode &other);
|
||||
|
||||
void create_inputs_outputs(const NodeType *type);
|
||||
void remove_input(ShaderInput *input);
|
||||
@@ -205,13 +205,15 @@ class ShaderNode : public Node {
|
||||
{
|
||||
return false;
|
||||
}
|
||||
vector<ShaderInput *> inputs;
|
||||
vector<ShaderOutput *> outputs;
|
||||
unique_ptr_vector<ShaderInput> inputs;
|
||||
unique_ptr_vector<ShaderOutput> outputs;
|
||||
|
||||
int id; /* index in graph node array */
|
||||
ShaderBump bump; /* for bump mapping utility */
|
||||
|
||||
ShaderNodeSpecialType special_type; /* special node type */
|
||||
/* index in graph node array */
|
||||
int id = -1;
|
||||
/* for bump mapping utility */
|
||||
ShaderBump bump = SHADER_BUMP_NONE;
|
||||
/* special node type */
|
||||
ShaderNodeSpecialType special_type = SHADER_SPECIAL_TYPE_NONE;
|
||||
|
||||
/* ** Selective nodes compilation ** */
|
||||
|
||||
@@ -290,7 +292,7 @@ using ShaderNodeMap = map<ShaderNode *, ShaderNode *, ShaderNodeIDComparator>;
|
||||
|
||||
class ShaderGraph : public NodeOwner {
|
||||
public:
|
||||
list<ShaderNode *> nodes;
|
||||
unique_ptr_vector<ShaderNode> nodes;
|
||||
size_t num_node_ids;
|
||||
bool finalized;
|
||||
bool simplified;
|
||||
@@ -299,7 +301,6 @@ class ShaderGraph : public NodeOwner {
|
||||
ShaderGraph();
|
||||
~ShaderGraph() override;
|
||||
|
||||
ShaderNode *add(ShaderNode *node);
|
||||
OutputNode *output();
|
||||
|
||||
void connect(ShaderOutput *from, ShaderInput *to);
|
||||
@@ -318,26 +319,39 @@ class ShaderGraph : public NodeOwner {
|
||||
|
||||
void dump_graph(const char *filename);
|
||||
|
||||
/* This function is used to create a node of a specified type instead of
|
||||
* calling 'new', and sets the graph as the owner of the node.
|
||||
*/
|
||||
/* Create node from class and add it to the shader graph. */
|
||||
template<typename T, typename... Args> T *create_node(Args &&...args)
|
||||
{
|
||||
T *node = new T(args...);
|
||||
node->set_owner(this);
|
||||
return node;
|
||||
unique_ptr<T> node = make_unique<T>(args...);
|
||||
T *node_ptr = node.get();
|
||||
this->add_node(std::move(node));
|
||||
return node_ptr;
|
||||
}
|
||||
|
||||
/* This function is used to delete a node created and owned by the graph. */
|
||||
template<typename T> void delete_node(T *node)
|
||||
/* Create OSL node from class and add it to the shader graph. */
|
||||
template<typename T, typename... Args> T *create_osl_node(void *node_memory, Args &&...args)
|
||||
{
|
||||
assert(node->get_owner() == this);
|
||||
delete node;
|
||||
T *node_ptr = new (node_memory) T(args...);
|
||||
unique_ptr<T> node(node_ptr);
|
||||
this->add_node(std::move(node));
|
||||
return node_ptr;
|
||||
}
|
||||
|
||||
/* Create node from node type and add it to the shader graph. */
|
||||
ShaderNode *create_node(const NodeType *node_type)
|
||||
{
|
||||
unique_ptr<Node> node = node_type->create(node_type);
|
||||
unique_ptr<ShaderNode> shader_node(static_cast<ShaderNode *>(node.release()));
|
||||
ShaderNode *shader_node_ptr = shader_node.get();
|
||||
this->add_node(std::move(shader_node));
|
||||
return shader_node_ptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
using NodePair = pair<ShaderNode *const, ShaderNode *>;
|
||||
|
||||
void add_node(unique_ptr<ShaderNode> &&node);
|
||||
|
||||
void find_dependencies(ShaderNodeSet &dependencies, ShaderInput *input);
|
||||
void clear_nodes();
|
||||
void copy_nodes(ShaderNodeSet &nodes, ShaderNodeMap &nnodemap);
|
||||
|
||||
@@ -2147,9 +2147,9 @@ void RGBToBWNode::compile(OSLCompiler &compiler)
|
||||
const NodeType *ConvertNode::node_types[ConvertNode::MAX_TYPE][ConvertNode::MAX_TYPE];
|
||||
bool ConvertNode::initialized = ConvertNode::register_types();
|
||||
|
||||
Node *ConvertNode::create(const NodeType *type)
|
||||
unique_ptr<Node> ConvertNode::create(const NodeType *type)
|
||||
{
|
||||
return new ConvertNode(type->inputs[0].type, type->outputs[0].type);
|
||||
return make_unique<ConvertNode>(type->inputs[0].type, type->outputs[0].type);
|
||||
}
|
||||
|
||||
bool ConvertNode::register_types()
|
||||
@@ -4778,7 +4778,6 @@ void VolumeInfoNode::expand(ShaderGraph *graph)
|
||||
if (!color_out->links.empty()) {
|
||||
AttributeNode *attr = graph->create_node<AttributeNode>();
|
||||
attr->set_attribute(ustring("color"));
|
||||
graph->add(attr);
|
||||
graph->relink(color_out, attr->output("Color"));
|
||||
}
|
||||
|
||||
@@ -4786,7 +4785,6 @@ void VolumeInfoNode::expand(ShaderGraph *graph)
|
||||
if (!density_out->links.empty()) {
|
||||
AttributeNode *attr = graph->create_node<AttributeNode>();
|
||||
attr->set_attribute(ustring("density"));
|
||||
graph->add(attr);
|
||||
graph->relink(density_out, attr->output("Fac"));
|
||||
}
|
||||
|
||||
@@ -4794,7 +4792,6 @@ void VolumeInfoNode::expand(ShaderGraph *graph)
|
||||
if (!flame_out->links.empty()) {
|
||||
AttributeNode *attr = graph->create_node<AttributeNode>();
|
||||
attr->set_attribute(ustring("flame"));
|
||||
graph->add(attr);
|
||||
graph->relink(flame_out, attr->output("Fac"));
|
||||
}
|
||||
|
||||
@@ -4802,7 +4799,6 @@ void VolumeInfoNode::expand(ShaderGraph *graph)
|
||||
if (!temperature_out->links.empty()) {
|
||||
AttributeNode *attr = graph->create_node<AttributeNode>();
|
||||
attr->set_attribute(ustring("temperature"));
|
||||
graph->add(attr);
|
||||
graph->relink(temperature_out, attr->output("Fac"));
|
||||
}
|
||||
}
|
||||
@@ -6403,7 +6399,6 @@ void MapRangeNode::expand(ShaderGraph *graph)
|
||||
if (!result_out->links.empty()) {
|
||||
ClampNode *clamp_node = graph->create_node<ClampNode>();
|
||||
clamp_node->set_clamp_type(NODE_CLAMP_RANGE);
|
||||
graph->add(clamp_node);
|
||||
graph->relink(result_out, clamp_node->output("Result"));
|
||||
graph->connect(result_out, clamp_node->input("Value"));
|
||||
if (input("To Min")->link) {
|
||||
@@ -6706,7 +6701,6 @@ void MathNode::expand(ShaderGraph *graph)
|
||||
clamp_node->set_clamp_type(NODE_CLAMP_MINMAX);
|
||||
clamp_node->set_min(0.0f);
|
||||
clamp_node->set_max(1.0f);
|
||||
graph->add(clamp_node);
|
||||
graph->relink(result_out, clamp_node->output("Result"));
|
||||
graph->connect(result_out, clamp_node->input("Value"));
|
||||
}
|
||||
@@ -7033,7 +7027,6 @@ void BumpNode::constant_fold(const ConstantFolder &folder)
|
||||
if (height_in->link == nullptr) {
|
||||
if (normal_in->link == nullptr) {
|
||||
GeometryNode *geom = folder.graph->create_node<GeometryNode>();
|
||||
folder.graph->add(geom);
|
||||
folder.bypass(geom->output("Normal"));
|
||||
}
|
||||
else {
|
||||
@@ -7415,16 +7408,13 @@ OSLNode *OSLNode::create(ShaderGraph *graph, const size_t num_inputs, const OSLN
|
||||
memset(node_memory, 0, node_size + inputs_size);
|
||||
|
||||
if (!from) {
|
||||
OSLNode *node = new (node_memory) OSLNode();
|
||||
node->set_owner(graph);
|
||||
return node;
|
||||
return graph->create_osl_node<OSLNode>(node_memory);
|
||||
}
|
||||
/* copy input default values and node type for cloning */
|
||||
memcpy(node_memory + node_size, (char *)from + node_size, inputs_size);
|
||||
|
||||
OSLNode *node = new (node_memory) OSLNode(*from);
|
||||
OSLNode *node = graph->create_osl_node<OSLNode>(node_memory, *from);
|
||||
node->type = new NodeType(*(from->type));
|
||||
node->set_owner(from->owner);
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "util/array.h"
|
||||
#include "util/string.h"
|
||||
#include "util/unique_ptr.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
@@ -451,7 +452,7 @@ class ConvertNode : public ShaderNode {
|
||||
|
||||
static const int MAX_TYPE = 13;
|
||||
static bool register_types();
|
||||
static Node *create(const NodeType *type);
|
||||
static unique_ptr<Node> create(const NodeType *type);
|
||||
static const NodeType *node_types[MAX_TYPE][MAX_TYPE];
|
||||
static bool initialized;
|
||||
};
|
||||
|
||||
@@ -129,7 +129,7 @@ void BufferParams::update_passes()
|
||||
}
|
||||
}
|
||||
|
||||
void BufferParams::update_passes(const vector<Pass *> &scene_passes)
|
||||
void BufferParams::update_passes(const unique_ptr_vector<Pass> &scene_passes)
|
||||
{
|
||||
passes.clear();
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ class BufferParams : public Node {
|
||||
* The `update_passes()` without parameters updates offsets and strides which are stored outside
|
||||
* of the passes. */
|
||||
void update_passes();
|
||||
void update_passes(const vector<Pass *> &scene_passes);
|
||||
void update_passes(const unique_ptr_vector<Pass> &scene_passes);
|
||||
|
||||
/* Returns PASS_UNUSED if there is no such pass in the buffer. */
|
||||
int get_pass_offset(PassType type, PassMode mode = PassMode::NOISY) const;
|
||||
|
||||
@@ -194,13 +194,15 @@ bool DenoiseTask::load_input_pixels(const int layer)
|
||||
|
||||
/* Task stages */
|
||||
|
||||
static void add_pass(vector<Pass *> &passes, PassType type, PassMode mode = PassMode::NOISY)
|
||||
static void add_pass(unique_ptr_vector<Pass> &passes,
|
||||
PassType type,
|
||||
PassMode mode = PassMode::NOISY)
|
||||
{
|
||||
Pass *pass = new Pass();
|
||||
unique_ptr<Pass> pass = make_unique<Pass>();
|
||||
pass->set_type(type);
|
||||
pass->set_mode(mode);
|
||||
|
||||
passes.push_back(pass);
|
||||
passes.push_back(std::move(pass));
|
||||
}
|
||||
|
||||
bool DenoiseTask::load()
|
||||
@@ -227,7 +229,7 @@ bool DenoiseTask::load()
|
||||
denoiser->denoiser->set_params(params);
|
||||
|
||||
/* Allocate device buffer. */
|
||||
vector<Pass *> passes;
|
||||
unique_ptr_vector<Pass> passes;
|
||||
add_pass(passes, PassType::PASS_COMBINED);
|
||||
add_pass(passes, PassType::PASS_DENOISING_ALBEDO);
|
||||
add_pass(passes, PassType::PASS_DENOISING_NORMAL);
|
||||
@@ -244,9 +246,7 @@ bool DenoiseTask::load()
|
||||
buffer_params.full_height = image.height;
|
||||
buffer_params.update_passes(passes);
|
||||
|
||||
for (Pass *pass : passes) {
|
||||
delete pass;
|
||||
}
|
||||
passes.clear();
|
||||
|
||||
buffers.reset(buffer_params);
|
||||
|
||||
|
||||
@@ -85,7 +85,6 @@ class ShaderGraphBuilder {
|
||||
template<typename T> ShaderGraphBuilder &add_node(const T &node)
|
||||
{
|
||||
EXPECT_EQ(find_node(node.name()), (void *)nullptr);
|
||||
graph_->add(node.node());
|
||||
node_map_[node.name()] = node.node();
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -118,6 +118,7 @@ set(SRC_HEADERS
|
||||
types_uint4.h
|
||||
types_ushort4.h
|
||||
unique_ptr.h
|
||||
unique_ptr_vector.h
|
||||
vector.h
|
||||
version.h
|
||||
windows.h
|
||||
|
||||
176
intern/cycles/util/unique_ptr_vector.h
Normal file
176
intern/cycles/util/unique_ptr_vector.h
Normal file
@@ -0,0 +1,176 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "util/algorithm.h"
|
||||
#include "util/set.h"
|
||||
#include "util/unique_ptr.h"
|
||||
#include "util/vector.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* Convenient vector of unique_ptr.
|
||||
* - Indexing and iterators return the pointer value directly.
|
||||
* - Utility functions for erase by swapping elements, for nodes.
|
||||
*/
|
||||
template<typename T> class unique_ptr_vector {
|
||||
protected:
|
||||
vector<unique_ptr<T>> data;
|
||||
|
||||
public:
|
||||
T *operator[](const size_t i) const
|
||||
{
|
||||
return data[i].get();
|
||||
}
|
||||
|
||||
unique_ptr<T> steal(const size_t i)
|
||||
{
|
||||
unique_ptr<T> local;
|
||||
swap(data[i], local);
|
||||
return local;
|
||||
}
|
||||
|
||||
void push_back(unique_ptr<T> &&value)
|
||||
{
|
||||
data.push_back(std::move(value));
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return data.empty();
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
return data.size();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
data.clear();
|
||||
}
|
||||
|
||||
void free_memory()
|
||||
{
|
||||
data.free_memory();
|
||||
}
|
||||
|
||||
void erase(const T *value)
|
||||
{
|
||||
const int size = data.size();
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
if (data[i].get() == value) {
|
||||
data.erase(data.begin() + i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/* Slightly faster erase swapping with other element instead of moving many,
|
||||
* but will change element order. */
|
||||
void erase_by_swap(const T *value)
|
||||
{
|
||||
const int size = data.size();
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
if (data[i].get() == value) {
|
||||
swap(data[i], data[data.size() - 1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
data.resize(data.size() - 1);
|
||||
}
|
||||
|
||||
void erase_in_set(const set<T *> &values)
|
||||
{
|
||||
size_t new_size = data.size();
|
||||
|
||||
for (size_t i = 0; i < new_size; i++) {
|
||||
T *value = data[i].get();
|
||||
if (values.find(value) != values.end()) {
|
||||
swap(data[i], data[new_size - 1]);
|
||||
i -= 1;
|
||||
new_size -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
data.resize(new_size);
|
||||
}
|
||||
|
||||
/* Basic iterators for range based for loop. */
|
||||
struct ConstIterator {
|
||||
typename vector<unique_ptr<T>>::const_iterator it;
|
||||
|
||||
const T *operator*() const
|
||||
{
|
||||
return it->get();
|
||||
}
|
||||
bool operator!=(const ConstIterator &other) const
|
||||
{
|
||||
return it != other.it;
|
||||
}
|
||||
void operator++()
|
||||
{
|
||||
++it;
|
||||
}
|
||||
};
|
||||
|
||||
ConstIterator begin() const
|
||||
{
|
||||
return ConstIterator{data.begin()};
|
||||
}
|
||||
ConstIterator end() const
|
||||
{
|
||||
return ConstIterator{data.end()};
|
||||
}
|
||||
|
||||
struct Iterator {
|
||||
typename vector<unique_ptr<T>>::const_iterator it;
|
||||
|
||||
T *operator*() const
|
||||
{
|
||||
return it->get();
|
||||
}
|
||||
bool operator!=(const Iterator &other) const
|
||||
{
|
||||
return it != other.it;
|
||||
}
|
||||
void operator++()
|
||||
{
|
||||
++it;
|
||||
}
|
||||
};
|
||||
Iterator begin()
|
||||
{
|
||||
return Iterator{data.begin()};
|
||||
}
|
||||
Iterator end()
|
||||
{
|
||||
return Iterator{data.end()};
|
||||
}
|
||||
|
||||
/* Cast to read-only regular vector for easier interop.
|
||||
* Assumes unique_ptr is zero overhead. */
|
||||
operator const vector<T *> &()
|
||||
{
|
||||
static_assert(sizeof(unique_ptr<T>) == sizeof(T *));
|
||||
return reinterpret_cast<vector<T *> &>(*this);
|
||||
}
|
||||
|
||||
/* For sorting unique_ptr instead of pointer. */
|
||||
template<typename Compare> void stable_sort(Compare compare)
|
||||
{
|
||||
auto compare_unique_ptr = [compare](const unique_ptr<T> &a, const unique_ptr<T> &b) {
|
||||
return compare(a.get(), b.get());
|
||||
};
|
||||
|
||||
std::stable_sort(data.begin(), data.end(), compare_unique_ptr);
|
||||
}
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
Reference in New Issue
Block a user