Cycles: introduce an ownership system to protect nodes from unwanted deletions.

Problem: the Blender synchronization process creates and tags nodes for usage. It does
this by directly adding and removing nodes from the scene data. If some node is not tagged
as used at the end of a synchronization, it then deletes the node from the scene. This poses
a problem when it comes to supporting procedural nodes who can create other nodes not known
by the Blender synchonization system, which will remove them.

Nodes now have a NodeOwner, which is set after creation. Those owners for now are the Scene
for scene level nodes and ShaderGraph for shader nodes. Instead of creating and deleting
nodes using `new` and `delete` explicitely, we now use `create_node` and `delete_node` methods
found on the owners. `delete_node` will assert that the owner is the right one.

Whenever a scene level node is created or deleted, the appropriate node manager is tagged for
an update, freeing this responsability from BlenderSync or other software exporters.

Concerning BlenderSync, the `id_maps` do not explicitely manipulate scene data anymore, they
only keep track of which nodes are used, employing the scene to create and delete them. To
achieve this, the ParticleSystem is now a Node, although it does not have any sockets.

This is part of T79131.

Reviewed By: #cycles, brecht

Maniphest Tasks: T79131

Differential Revision: https://developer.blender.org/D8540
This commit is contained in:
Kévin Dietrich 2020-08-30 23:20:51 +02:00
parent 19363880a6
commit 429afe0c62
20 changed files with 461 additions and 232 deletions

View File

@ -83,13 +83,13 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
if (geom == NULL) {
/* Add new geometry if it did not exist yet. */
if (geom_type == Geometry::HAIR) {
geom = new Hair();
geom = scene->create_node<Hair>();
}
else if (geom_type == Geometry::VOLUME) {
geom = new Volume();
geom = scene->create_node<Volume>();
}
else {
geom = new Mesh();
geom = scene->create_node<Mesh>();
}
geometry_map.add(key, geom);
}

View File

@ -19,6 +19,8 @@
#include <string.h>
#include "render/scene.h"
#include "util/util_map.h"
#include "util/util_set.h"
#include "util/util_vector.h"
@ -32,9 +34,8 @@ CCL_NAMESPACE_BEGIN
template<typename K, typename T> class id_map {
public:
id_map(vector<T *> *scene_data_)
id_map()
{
scene_data = scene_data_;
}
T *find(const BL::ID &id)
@ -76,7 +77,6 @@ template<typename K, typename T> class id_map {
void add(const K &key, T *data)
{
assert(find(key) == NULL);
scene_data->push_back(data);
b_map[key] = data;
used(data);
}
@ -97,22 +97,23 @@ template<typename K, typename T> class id_map {
}
/* Combined add and update as needed. */
bool add_or_update(T **r_data, const BL::ID &id)
bool add_or_update(Scene *scene, T **r_data, const BL::ID &id)
{
return add_or_update(r_data, id, id, id.ptr.owner_id);
return add_or_update(scene, r_data, id, id, id.ptr.owner_id);
}
bool add_or_update(T **r_data, const BL::ID &id, const K &key)
bool add_or_update(Scene *scene, T **r_data, const BL::ID &id, const K &key)
{
return add_or_update(r_data, id, id, key);
return add_or_update(scene, r_data, id, id, key);
}
bool add_or_update(T **r_data, const BL::ID &id, const BL::ID &parent, const K &key)
bool add_or_update(
Scene *scene, T **r_data, const BL::ID &id, const BL::ID &parent, const K &key)
{
T *data = find(key);
bool recalc;
if (!data) {
/* Add data if it didn't exist yet. */
data = new T();
data = scene->create_node<T>();
add(key, data);
recalc = true;
}
@ -144,27 +145,8 @@ template<typename K, typename T> class id_map {
b_map[NULL] = data;
}
bool post_sync(bool do_delete = true)
void post_sync(Scene *scene, bool do_delete = true)
{
/* remove unused data */
vector<T *> new_scene_data;
typename vector<T *>::iterator it;
bool deleted = false;
for (it = scene_data->begin(); it != scene_data->end(); it++) {
T *data = *it;
if (do_delete && used_set.find(data) == used_set.end()) {
delete data;
deleted = true;
}
else
new_scene_data.push_back(data);
}
*scene_data = new_scene_data;
/* update mapping */
map<K, T *> new_map;
typedef pair<const K, T *> TMapPair;
typename map<K, T *>::iterator jt;
@ -172,15 +154,17 @@ template<typename K, typename T> class id_map {
for (jt = b_map.begin(); jt != b_map.end(); jt++) {
TMapPair &pair = *jt;
if (used_set.find(pair.second) != used_set.end())
if (do_delete && used_set.find(pair.second) == used_set.end()) {
scene->delete_node(pair.second);
}
else {
new_map[pair.first] = pair.second;
}
}
used_set.clear();
b_recalc.clear();
b_map = new_map;
return deleted;
}
const map<K, T *> &key_to_scene_data()
@ -189,7 +173,6 @@ template<typename K, typename T> class id_map {
}
protected:
vector<T *> *scene_data;
map<K, T *> b_map;
set<T *> used_set;
set<void *> b_recalc;

View File

@ -39,9 +39,9 @@ void BlenderSync::sync_light(BL::Object &b_parent,
BL::Light b_light(b_ob.data());
/* Update if either object or light data changed. */
if (!light_map.add_or_update(&light, b_ob, b_parent, key)) {
if (!light_map.add_or_update(scene, &light, b_ob, b_parent, key)) {
Shader *shader;
if (!shader_map.add_or_update(&shader, b_light)) {
if (!shader_map.add_or_update(scene, &shader, b_light)) {
if (light->is_portal)
*use_portal = true;
return;
@ -176,7 +176,7 @@ void BlenderSync::sync_background_light(BL::SpaceView3D &b_v3d, bool use_portal)
Light *light;
ObjectKey key(b_world, 0, b_world, false);
if (light_map.add_or_update(&light, b_world, b_world, key) || world_recalc ||
if (light_map.add_or_update(scene, &light, b_world, b_world, key) || world_recalc ||
b_world.ptr.data != world_map) {
light->type = LIGHT_BACKGROUND;
if (sampling_method == SAMPLING_MANUAL) {

View File

@ -207,7 +207,7 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
/* test if we need to sync */
bool object_updated = false;
if (object_map.add_or_update(&object, b_ob, b_parent, key))
if (object_map.add_or_update(scene, &object, b_ob, b_parent, key))
object_updated = true;
/* mesh sync */
@ -405,14 +405,10 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,
sync_background_light(b_v3d, use_portal);
/* handle removed data and modified pointers */
if (light_map.post_sync())
scene->light_manager->tag_update(scene);
if (geometry_map.post_sync())
scene->geometry_manager->tag_update(scene);
if (object_map.post_sync())
scene->object_manager->tag_update(scene);
if (particle_system_map.post_sync())
scene->particle_system_manager->tag_update(scene);
light_map.post_sync(scene);
geometry_map.post_sync(scene);
object_map.post_sync(scene);
particle_system_map.post_sync(scene);
}
if (motion)

View File

@ -53,7 +53,8 @@ bool BlenderSync::sync_dupli_particle(BL::Object &b_ob,
ParticleSystem *psys;
bool first_use = !particle_system_map.is_used(key);
bool need_update = particle_system_map.add_or_update(&psys, b_ob, b_instance.object(), key);
bool need_update = particle_system_map.add_or_update(
scene, &psys, b_ob, b_instance.object(), key);
/* no update needed? */
if (!need_update && !object->geometry->need_update && !scene->object_manager->need_update)

View File

@ -224,7 +224,7 @@ static ShaderNode *add_node(Scene *scene,
if (b_node.is_a(&RNA_ShaderNodeRGBCurve)) {
BL::ShaderNodeRGBCurve b_curve_node(b_node);
BL::CurveMapping mapping(b_curve_node.mapping());
RGBCurvesNode *curves = new RGBCurvesNode();
RGBCurvesNode *curves = graph->create_node<RGBCurvesNode>();
curvemapping_color_to_array(mapping, curves->curves, RAMP_TABLE_SIZE, true);
curvemapping_minmax(mapping, true, &curves->min_x, &curves->max_x);
node = curves;
@ -232,13 +232,13 @@ static ShaderNode *add_node(Scene *scene,
if (b_node.is_a(&RNA_ShaderNodeVectorCurve)) {
BL::ShaderNodeVectorCurve b_curve_node(b_node);
BL::CurveMapping mapping(b_curve_node.mapping());
VectorCurvesNode *curves = new VectorCurvesNode();
VectorCurvesNode *curves = graph->create_node<VectorCurvesNode>();
curvemapping_color_to_array(mapping, curves->curves, RAMP_TABLE_SIZE, false);
curvemapping_minmax(mapping, false, &curves->min_x, &curves->max_x);
node = curves;
}
else if (b_node.is_a(&RNA_ShaderNodeValToRGB)) {
RGBRampNode *ramp = new RGBRampNode();
RGBRampNode *ramp = graph->create_node<RGBRampNode>();
BL::ShaderNodeValToRGB b_ramp_node(b_node);
BL::ColorRamp b_color_ramp(b_ramp_node.color_ramp());
colorramp_to_array(b_color_ramp, ramp->ramp, ramp->ramp_alpha, RAMP_TABLE_SIZE);
@ -246,94 +246,94 @@ static ShaderNode *add_node(Scene *scene,
node = ramp;
}
else if (b_node.is_a(&RNA_ShaderNodeRGB)) {
ColorNode *color = new ColorNode();
ColorNode *color = graph->create_node<ColorNode>();
color->value = get_node_output_rgba(b_node, "Color");
node = color;
}
else if (b_node.is_a(&RNA_ShaderNodeValue)) {
ValueNode *value = new ValueNode();
ValueNode *value = graph->create_node<ValueNode>();
value->value = get_node_output_value(b_node, "Value");
node = value;
}
else if (b_node.is_a(&RNA_ShaderNodeCameraData)) {
node = new CameraNode();
node = graph->create_node<CameraNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeInvert)) {
node = new InvertNode();
node = graph->create_node<InvertNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeGamma)) {
node = new GammaNode();
node = graph->create_node<GammaNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeBrightContrast)) {
node = new BrightContrastNode();
node = graph->create_node<BrightContrastNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeMixRGB)) {
BL::ShaderNodeMixRGB b_mix_node(b_node);
MixNode *mix = new MixNode();
MixNode *mix = graph->create_node<MixNode>();
mix->type = (NodeMix)b_mix_node.blend_type();
mix->use_clamp = b_mix_node.use_clamp();
node = mix;
}
else if (b_node.is_a(&RNA_ShaderNodeSeparateRGB)) {
node = new SeparateRGBNode();
node = graph->create_node<SeparateRGBNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeCombineRGB)) {
node = new CombineRGBNode();
node = graph->create_node<CombineRGBNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeSeparateHSV)) {
node = new SeparateHSVNode();
node = graph->create_node<SeparateHSVNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeCombineHSV)) {
node = new CombineHSVNode();
node = graph->create_node<CombineHSVNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeSeparateXYZ)) {
node = new SeparateXYZNode();
node = graph->create_node<SeparateXYZNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeCombineXYZ)) {
node = new CombineXYZNode();
node = graph->create_node<CombineXYZNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeHueSaturation)) {
node = new HSVNode();
node = graph->create_node<HSVNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeRGBToBW)) {
node = new RGBToBWNode();
node = graph->create_node<RGBToBWNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeMapRange)) {
BL::ShaderNodeMapRange b_map_range_node(b_node);
MapRangeNode *map_range_node = new MapRangeNode();
MapRangeNode *map_range_node = graph->create_node<MapRangeNode>();
map_range_node->clamp = b_map_range_node.clamp();
map_range_node->type = (NodeMapRangeType)b_map_range_node.interpolation_type();
node = map_range_node;
}
else if (b_node.is_a(&RNA_ShaderNodeClamp)) {
BL::ShaderNodeClamp b_clamp_node(b_node);
ClampNode *clamp_node = new ClampNode();
ClampNode *clamp_node = graph->create_node<ClampNode>();
clamp_node->type = (NodeClampType)b_clamp_node.clamp_type();
node = clamp_node;
}
else if (b_node.is_a(&RNA_ShaderNodeMath)) {
BL::ShaderNodeMath b_math_node(b_node);
MathNode *math_node = new MathNode();
MathNode *math_node = graph->create_node<MathNode>();
math_node->type = (NodeMathType)b_math_node.operation();
math_node->use_clamp = b_math_node.use_clamp();
node = math_node;
}
else if (b_node.is_a(&RNA_ShaderNodeVectorMath)) {
BL::ShaderNodeVectorMath b_vector_math_node(b_node);
VectorMathNode *vector_math_node = new VectorMathNode();
VectorMathNode *vector_math_node = graph->create_node<VectorMathNode>();
vector_math_node->type = (NodeVectorMathType)b_vector_math_node.operation();
node = vector_math_node;
}
else if (b_node.is_a(&RNA_ShaderNodeVectorRotate)) {
BL::ShaderNodeVectorRotate b_vector_rotate_node(b_node);
VectorRotateNode *vector_rotate_node = new VectorRotateNode();
VectorRotateNode *vector_rotate_node = graph->create_node<VectorRotateNode>();
vector_rotate_node->type = (NodeVectorRotateType)b_vector_rotate_node.rotation_type();
vector_rotate_node->invert = b_vector_rotate_node.invert();
node = vector_rotate_node;
}
else if (b_node.is_a(&RNA_ShaderNodeVectorTransform)) {
BL::ShaderNodeVectorTransform b_vector_transform_node(b_node);
VectorTransformNode *vtransform = new VectorTransformNode();
VectorTransformNode *vtransform = graph->create_node<VectorTransformNode>();
vtransform->type = (NodeVectorTransformType)b_vector_transform_node.vector_type();
vtransform->convert_from = (NodeVectorTransformConvertSpace)
b_vector_transform_node.convert_from();
@ -344,43 +344,43 @@ static ShaderNode *add_node(Scene *scene,
BL::Node::outputs_iterator out_it;
b_node.outputs.begin(out_it);
NormalNode *norm = new NormalNode();
NormalNode *norm = graph->create_node<NormalNode>();
norm->direction = get_node_output_vector(b_node, "Normal");
node = norm;
}
else if (b_node.is_a(&RNA_ShaderNodeMapping)) {
BL::ShaderNodeMapping b_mapping_node(b_node);
MappingNode *mapping = new MappingNode();
MappingNode *mapping = graph->create_node<MappingNode>();
mapping->type = (NodeMappingType)b_mapping_node.vector_type();
node = mapping;
}
else if (b_node.is_a(&RNA_ShaderNodeFresnel)) {
node = new FresnelNode();
node = graph->create_node<FresnelNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeLayerWeight)) {
node = new LayerWeightNode();
node = graph->create_node<LayerWeightNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeAddShader)) {
node = new AddClosureNode();
node = graph->create_node<AddClosureNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeMixShader)) {
node = new MixClosureNode();
node = graph->create_node<MixClosureNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeAttribute)) {
BL::ShaderNodeAttribute b_attr_node(b_node);
AttributeNode *attr = new AttributeNode();
AttributeNode *attr = graph->create_node<AttributeNode>();
attr->attribute = b_attr_node.attribute_name();
node = attr;
}
else if (b_node.is_a(&RNA_ShaderNodeBackground)) {
node = new BackgroundNode();
node = graph->create_node<BackgroundNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeHoldout)) {
node = new HoldoutNode();
node = graph->create_node<HoldoutNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeBsdfAnisotropic)) {
BL::ShaderNodeBsdfAnisotropic b_aniso_node(b_node);
AnisotropicBsdfNode *aniso = new AnisotropicBsdfNode();
AnisotropicBsdfNode *aniso = graph->create_node<AnisotropicBsdfNode>();
switch (b_aniso_node.distribution()) {
case BL::ShaderNodeBsdfAnisotropic::distribution_BECKMANN:
@ -400,12 +400,12 @@ static ShaderNode *add_node(Scene *scene,
node = aniso;
}
else if (b_node.is_a(&RNA_ShaderNodeBsdfDiffuse)) {
node = new DiffuseBsdfNode();
node = graph->create_node<DiffuseBsdfNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeSubsurfaceScattering)) {
BL::ShaderNodeSubsurfaceScattering b_subsurface_node(b_node);
SubsurfaceScatteringNode *subsurface = new SubsurfaceScatteringNode();
SubsurfaceScatteringNode *subsurface = graph->create_node<SubsurfaceScatteringNode>();
switch (b_subsurface_node.falloff()) {
case BL::ShaderNodeSubsurfaceScattering::falloff_CUBIC:
@ -426,7 +426,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeBsdfGlossy)) {
BL::ShaderNodeBsdfGlossy b_glossy_node(b_node);
GlossyBsdfNode *glossy = new GlossyBsdfNode();
GlossyBsdfNode *glossy = graph->create_node<GlossyBsdfNode>();
switch (b_glossy_node.distribution()) {
case BL::ShaderNodeBsdfGlossy::distribution_SHARP:
@ -449,7 +449,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeBsdfGlass)) {
BL::ShaderNodeBsdfGlass b_glass_node(b_node);
GlassBsdfNode *glass = new GlassBsdfNode();
GlassBsdfNode *glass = graph->create_node<GlassBsdfNode>();
switch (b_glass_node.distribution()) {
case BL::ShaderNodeBsdfGlass::distribution_SHARP:
glass->distribution = CLOSURE_BSDF_SHARP_GLASS_ID;
@ -468,7 +468,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeBsdfRefraction)) {
BL::ShaderNodeBsdfRefraction b_refraction_node(b_node);
RefractionBsdfNode *refraction = new RefractionBsdfNode();
RefractionBsdfNode *refraction = graph->create_node<RefractionBsdfNode>();
switch (b_refraction_node.distribution()) {
case BL::ShaderNodeBsdfRefraction::distribution_SHARP:
refraction->distribution = CLOSURE_BSDF_REFRACTION_ID;
@ -484,7 +484,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeBsdfToon)) {
BL::ShaderNodeBsdfToon b_toon_node(b_node);
ToonBsdfNode *toon = new ToonBsdfNode();
ToonBsdfNode *toon = graph->create_node<ToonBsdfNode>();
switch (b_toon_node.component()) {
case BL::ShaderNodeBsdfToon::component_DIFFUSE:
toon->component = CLOSURE_BSDF_DIFFUSE_TOON_ID;
@ -497,7 +497,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeBsdfHair)) {
BL::ShaderNodeBsdfHair b_hair_node(b_node);
HairBsdfNode *hair = new HairBsdfNode();
HairBsdfNode *hair = graph->create_node<HairBsdfNode>();
switch (b_hair_node.component()) {
case BL::ShaderNodeBsdfHair::component_Reflection:
hair->component = CLOSURE_BSDF_HAIR_REFLECTION_ID;
@ -510,7 +510,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeBsdfHairPrincipled)) {
BL::ShaderNodeBsdfHairPrincipled b_principled_hair_node(b_node);
PrincipledHairBsdfNode *principled_hair = new PrincipledHairBsdfNode();
PrincipledHairBsdfNode *principled_hair = graph->create_node<PrincipledHairBsdfNode>();
principled_hair->parametrization = (NodePrincipledHairParametrization)get_enum(
b_principled_hair_node.ptr,
"parametrization",
@ -520,7 +520,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeBsdfPrincipled)) {
BL::ShaderNodeBsdfPrincipled b_principled_node(b_node);
PrincipledBsdfNode *principled = new PrincipledBsdfNode();
PrincipledBsdfNode *principled = graph->create_node<PrincipledBsdfNode>();
switch (b_principled_node.distribution()) {
case BL::ShaderNodeBsdfPrincipled::distribution_GGX:
principled->distribution = CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID;
@ -540,77 +540,77 @@ static ShaderNode *add_node(Scene *scene,
node = principled;
}
else if (b_node.is_a(&RNA_ShaderNodeBsdfTranslucent)) {
node = new TranslucentBsdfNode();
node = graph->create_node<TranslucentBsdfNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeBsdfTransparent)) {
node = new TransparentBsdfNode();
node = graph->create_node<TransparentBsdfNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeBsdfVelvet)) {
node = new VelvetBsdfNode();
node = graph->create_node<VelvetBsdfNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeEmission)) {
node = new EmissionNode();
node = graph->create_node<EmissionNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeAmbientOcclusion)) {
BL::ShaderNodeAmbientOcclusion b_ao_node(b_node);
AmbientOcclusionNode *ao = new AmbientOcclusionNode();
AmbientOcclusionNode *ao = graph->create_node<AmbientOcclusionNode>();
ao->samples = b_ao_node.samples();
ao->inside = b_ao_node.inside();
ao->only_local = b_ao_node.only_local();
node = ao;
}
else if (b_node.is_a(&RNA_ShaderNodeVolumeScatter)) {
node = new ScatterVolumeNode();
node = graph->create_node<ScatterVolumeNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeVolumeAbsorption)) {
node = new AbsorptionVolumeNode();
node = graph->create_node<AbsorptionVolumeNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeVolumePrincipled)) {
PrincipledVolumeNode *principled = new PrincipledVolumeNode();
PrincipledVolumeNode *principled = graph->create_node<PrincipledVolumeNode>();
node = principled;
}
else if (b_node.is_a(&RNA_ShaderNodeNewGeometry)) {
node = new GeometryNode();
node = graph->create_node<GeometryNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeWireframe)) {
BL::ShaderNodeWireframe b_wireframe_node(b_node);
WireframeNode *wire = new WireframeNode();
WireframeNode *wire = graph->create_node<WireframeNode>();
wire->use_pixel_size = b_wireframe_node.use_pixel_size();
node = wire;
}
else if (b_node.is_a(&RNA_ShaderNodeWavelength)) {
node = new WavelengthNode();
node = graph->create_node<WavelengthNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeBlackbody)) {
node = new BlackbodyNode();
node = graph->create_node<BlackbodyNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeLightPath)) {
node = new LightPathNode();
node = graph->create_node<LightPathNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeLightFalloff)) {
node = new LightFalloffNode();
node = graph->create_node<LightFalloffNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeObjectInfo)) {
node = new ObjectInfoNode();
node = graph->create_node<ObjectInfoNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeParticleInfo)) {
node = new ParticleInfoNode();
node = graph->create_node<ParticleInfoNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeHairInfo)) {
node = new HairInfoNode();
node = graph->create_node<HairInfoNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeVolumeInfo)) {
node = new VolumeInfoNode();
node = graph->create_node<VolumeInfoNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeVertexColor)) {
BL::ShaderNodeVertexColor b_vertex_color_node(b_node);
VertexColorNode *vertex_color_node = new VertexColorNode();
VertexColorNode *vertex_color_node = graph->create_node<VertexColorNode>();
vertex_color_node->layer_name = b_vertex_color_node.layer_name();
node = vertex_color_node;
}
else if (b_node.is_a(&RNA_ShaderNodeBump)) {
BL::ShaderNodeBump b_bump_node(b_node);
BumpNode *bump = new BumpNode();
BumpNode *bump = graph->create_node<BumpNode>();
bump->invert = b_bump_node.invert();
node = bump;
}
@ -624,12 +624,13 @@ static ShaderNode *add_node(Scene *scene,
string bytecode_hash = b_script_node.bytecode_hash();
if (!bytecode_hash.empty()) {
node = OSLShaderManager::osl_node(manager, "", bytecode_hash, b_script_node.bytecode());
node = OSLShaderManager::osl_node(
graph, manager, "", bytecode_hash, b_script_node.bytecode());
}
else {
string absolute_filepath = blender_absolute_path(
b_data, b_ntree, b_script_node.filepath());
node = OSLShaderManager::osl_node(manager, absolute_filepath, "");
node = OSLShaderManager::osl_node(graph, manager, absolute_filepath, "");
}
}
#else
@ -641,7 +642,7 @@ static ShaderNode *add_node(Scene *scene,
BL::ShaderNodeTexImage b_image_node(b_node);
BL::Image b_image(b_image_node.image());
BL::ImageUser b_image_user(b_image_node.image_user());
ImageTextureNode *image = new ImageTextureNode();
ImageTextureNode *image = graph->create_node<ImageTextureNode>();
image->interpolation = get_image_interpolation(b_image_node);
image->extension = get_image_extension(b_image_node);
@ -693,7 +694,7 @@ static ShaderNode *add_node(Scene *scene,
BL::ShaderNodeTexEnvironment b_env_node(b_node);
BL::Image b_image(b_env_node.image());
BL::ImageUser b_image_user(b_env_node.image_user());
EnvironmentTextureNode *env = new EnvironmentTextureNode();
EnvironmentTextureNode *env = graph->create_node<EnvironmentTextureNode>();
env->interpolation = get_image_interpolation(b_env_node);
env->projection = (NodeEnvironmentProjection)b_env_node.projection();
@ -726,7 +727,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeTexGradient)) {
BL::ShaderNodeTexGradient b_gradient_node(b_node);
GradientTextureNode *gradient = new GradientTextureNode();
GradientTextureNode *gradient = graph->create_node<GradientTextureNode>();
gradient->type = (NodeGradientType)b_gradient_node.gradient_type();
BL::TexMapping b_texture_mapping(b_gradient_node.texture_mapping());
get_tex_mapping(&gradient->tex_mapping, b_texture_mapping);
@ -734,7 +735,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeTexVoronoi)) {
BL::ShaderNodeTexVoronoi b_voronoi_node(b_node);
VoronoiTextureNode *voronoi = new VoronoiTextureNode();
VoronoiTextureNode *voronoi = graph->create_node<VoronoiTextureNode>();
voronoi->dimensions = b_voronoi_node.voronoi_dimensions();
voronoi->feature = (NodeVoronoiFeature)b_voronoi_node.feature();
voronoi->metric = (NodeVoronoiDistanceMetric)b_voronoi_node.distance();
@ -744,7 +745,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeTexMagic)) {
BL::ShaderNodeTexMagic b_magic_node(b_node);
MagicTextureNode *magic = new MagicTextureNode();
MagicTextureNode *magic = graph->create_node<MagicTextureNode>();
magic->depth = b_magic_node.turbulence_depth();
BL::TexMapping b_texture_mapping(b_magic_node.texture_mapping());
get_tex_mapping(&magic->tex_mapping, b_texture_mapping);
@ -752,7 +753,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeTexWave)) {
BL::ShaderNodeTexWave b_wave_node(b_node);
WaveTextureNode *wave = new WaveTextureNode();
WaveTextureNode *wave = graph->create_node<WaveTextureNode>();
wave->type = (NodeWaveType)b_wave_node.wave_type();
wave->bands_direction = (NodeWaveBandsDirection)b_wave_node.bands_direction();
wave->rings_direction = (NodeWaveRingsDirection)b_wave_node.rings_direction();
@ -763,14 +764,14 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeTexChecker)) {
BL::ShaderNodeTexChecker b_checker_node(b_node);
CheckerTextureNode *checker = new CheckerTextureNode();
CheckerTextureNode *checker = graph->create_node<CheckerTextureNode>();
BL::TexMapping b_texture_mapping(b_checker_node.texture_mapping());
get_tex_mapping(&checker->tex_mapping, b_texture_mapping);
node = checker;
}
else if (b_node.is_a(&RNA_ShaderNodeTexBrick)) {
BL::ShaderNodeTexBrick b_brick_node(b_node);
BrickTextureNode *brick = new BrickTextureNode();
BrickTextureNode *brick = graph->create_node<BrickTextureNode>();
brick->offset = b_brick_node.offset();
brick->offset_frequency = b_brick_node.offset_frequency();
brick->squash = b_brick_node.squash();
@ -781,7 +782,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeTexNoise)) {
BL::ShaderNodeTexNoise b_noise_node(b_node);
NoiseTextureNode *noise = new NoiseTextureNode();
NoiseTextureNode *noise = graph->create_node<NoiseTextureNode>();
noise->dimensions = b_noise_node.noise_dimensions();
BL::TexMapping b_texture_mapping(b_noise_node.texture_mapping());
get_tex_mapping(&noise->tex_mapping, b_texture_mapping);
@ -789,7 +790,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeTexMusgrave)) {
BL::ShaderNodeTexMusgrave b_musgrave_node(b_node);
MusgraveTextureNode *musgrave_node = new MusgraveTextureNode();
MusgraveTextureNode *musgrave_node = graph->create_node<MusgraveTextureNode>();
musgrave_node->type = (NodeMusgraveType)b_musgrave_node.musgrave_type();
musgrave_node->dimensions = b_musgrave_node.musgrave_dimensions();
BL::TexMapping b_texture_mapping(b_musgrave_node.texture_mapping());
@ -798,7 +799,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeTexCoord)) {
BL::ShaderNodeTexCoord b_tex_coord_node(b_node);
TextureCoordinateNode *tex_coord = new TextureCoordinateNode();
TextureCoordinateNode *tex_coord = graph->create_node<TextureCoordinateNode>();
tex_coord->from_dupli = b_tex_coord_node.from_instancer();
if (b_tex_coord_node.object()) {
tex_coord->use_transform = true;
@ -808,7 +809,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeTexSky)) {
BL::ShaderNodeTexSky b_sky_node(b_node);
SkyTextureNode *sky = new SkyTextureNode();
SkyTextureNode *sky = graph->create_node<SkyTextureNode>();
sky->type = (NodeSkyType)b_sky_node.sky_type();
sky->sun_direction = normalize(get_float3(b_sky_node.sun_direction()));
sky->turbidity = b_sky_node.turbidity();
@ -828,7 +829,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeTexIES)) {
BL::ShaderNodeTexIES b_ies_node(b_node);
IESLightNode *ies = new IESLightNode();
IESLightNode *ies = graph->create_node<IESLightNode>();
switch (b_ies_node.mode()) {
case BL::ShaderNodeTexIES::mode_EXTERNAL:
ies->filename = blender_absolute_path(b_data, b_ntree, b_ies_node.filepath());
@ -844,20 +845,20 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeTexWhiteNoise)) {
BL::ShaderNodeTexWhiteNoise b_tex_white_noise_node(b_node);
WhiteNoiseTextureNode *white_noise_node = new WhiteNoiseTextureNode();
WhiteNoiseTextureNode *white_noise_node = graph->create_node<WhiteNoiseTextureNode>();
white_noise_node->dimensions = b_tex_white_noise_node.noise_dimensions();
node = white_noise_node;
}
else if (b_node.is_a(&RNA_ShaderNodeNormalMap)) {
BL::ShaderNodeNormalMap b_normal_map_node(b_node);
NormalMapNode *nmap = new NormalMapNode();
NormalMapNode *nmap = graph->create_node<NormalMapNode>();
nmap->space = (NodeNormalMapSpace)b_normal_map_node.space();
nmap->attribute = b_normal_map_node.uv_map();
node = nmap;
}
else if (b_node.is_a(&RNA_ShaderNodeTangent)) {
BL::ShaderNodeTangent b_tangent_node(b_node);
TangentNode *tangent = new TangentNode();
TangentNode *tangent = graph->create_node<TangentNode>();
tangent->direction_type = (NodeTangentDirectionType)b_tangent_node.direction_type();
tangent->axis = (NodeTangentAxis)b_tangent_node.axis();
tangent->attribute = b_tangent_node.uv_map();
@ -865,14 +866,14 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeUVMap)) {
BL::ShaderNodeUVMap b_uvmap_node(b_node);
UVMapNode *uvm = new UVMapNode();
UVMapNode *uvm = graph->create_node<UVMapNode>();
uvm->attribute = b_uvmap_node.uv_map();
uvm->from_dupli = b_uvmap_node.from_instancer();
node = uvm;
}
else if (b_node.is_a(&RNA_ShaderNodeTexPointDensity)) {
BL::ShaderNodeTexPointDensity b_point_density_node(b_node);
PointDensityTextureNode *point_density = new PointDensityTextureNode();
PointDensityTextureNode *point_density = graph->create_node<PointDensityTextureNode>();
point_density->space = (NodeTexVoxelSpace)b_point_density_node.space();
point_density->interpolation = get_image_interpolation(b_point_density_node);
point_density->handle = scene->image_manager->add_image(
@ -897,26 +898,26 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeBevel)) {
BL::ShaderNodeBevel b_bevel_node(b_node);
BevelNode *bevel = new BevelNode();
BevelNode *bevel = graph->create_node<BevelNode>();
bevel->samples = b_bevel_node.samples();
node = bevel;
}
else if (b_node.is_a(&RNA_ShaderNodeDisplacement)) {
BL::ShaderNodeDisplacement b_disp_node(b_node);
DisplacementNode *disp = new DisplacementNode();
DisplacementNode *disp = graph->create_node<DisplacementNode>();
disp->space = (NodeNormalMapSpace)b_disp_node.space();
node = disp;
}
else if (b_node.is_a(&RNA_ShaderNodeVectorDisplacement)) {
BL::ShaderNodeVectorDisplacement b_disp_node(b_node);
VectorDisplacementNode *disp = new VectorDisplacementNode();
VectorDisplacementNode *disp = graph->create_node<VectorDisplacementNode>();
disp->space = (NodeNormalMapSpace)b_disp_node.space();
disp->attribute = "";
node = disp;
}
else if (b_node.is_a(&RNA_ShaderNodeOutputAOV)) {
BL::ShaderNodeOutputAOV b_aov_node(b_node);
OutputAOVNode *aov = new OutputAOVNode();
OutputAOVNode *aov = graph->create_node<OutputAOVNode>();
aov->name = b_aov_node.name();
node = aov;
}
@ -1038,7 +1039,7 @@ static void add_nodes(Scene *scene,
continue;
}
ConvertNode *proxy = new ConvertNode(to_socket_type, to_socket_type, true);
ConvertNode *proxy = graph->create_node<ConvertNode>(to_socket_type, to_socket_type, true);
input_map[b_link->from_socket().ptr.data] = proxy->inputs[0];
output_map[b_link->to_socket().ptr.data] = proxy->outputs[0];
@ -1069,7 +1070,7 @@ static void add_nodes(Scene *scene,
continue;
}
ConvertNode *proxy = new ConvertNode(input_type, input_type, true);
ConvertNode *proxy = graph->create_node<ConvertNode>(input_type, input_type, true);
graph->add(proxy);
/* register the proxy node for internal binding */
@ -1085,7 +1086,7 @@ static void add_nodes(Scene *scene,
continue;
}
ConvertNode *proxy = new ConvertNode(output_type, output_type, true);
ConvertNode *proxy = graph->create_node<ConvertNode>(output_type, output_type, true);
graph->add(proxy);
/* register the proxy node for internal binding */
@ -1240,7 +1241,7 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all)
Shader *shader;
/* test if we need to sync */
if (shader_map.add_or_update(&shader, b_mat) || update_all) {
if (shader_map.add_or_update(scene, &shader, b_mat) || update_all) {
ShaderGraph *graph = new ShaderGraph();
shader->name = b_mat.name().c_str();
@ -1253,7 +1254,7 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all)
add_nodes(scene, b_engine, b_data, b_depsgraph, b_scene, graph, b_ntree);
}
else {
DiffuseBsdfNode *diffuse = new DiffuseBsdfNode();
DiffuseBsdfNode *diffuse = graph->create_node<DiffuseBsdfNode>();
diffuse->color = get_float3(b_mat.diffuse_color());
graph->add(diffuse);
@ -1336,7 +1337,7 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
shader->volume_step_rate = get_float(cworld, "volume_step_size");
}
else if (new_viewport_parameters.use_scene_world && b_world) {
BackgroundNode *background = new BackgroundNode();
BackgroundNode *background = graph->create_node<BackgroundNode>();
background->color = get_float3(b_world.color());
graph->add(background);
@ -1352,23 +1353,23 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
world_color = make_float3(0.0f, 0.0f, 0.0f);
}
BackgroundNode *background = new BackgroundNode();
BackgroundNode *background = graph->create_node<BackgroundNode>();
graph->add(background);
LightPathNode *light_path = new LightPathNode();
LightPathNode *light_path = graph->create_node<LightPathNode>();
graph->add(light_path);
MixNode *mix_scene_with_background = new MixNode();
MixNode *mix_scene_with_background = graph->create_node<MixNode>();
mix_scene_with_background->color2 = world_color;
graph->add(mix_scene_with_background);
EnvironmentTextureNode *texture_environment = new EnvironmentTextureNode();
EnvironmentTextureNode *texture_environment = graph->create_node<EnvironmentTextureNode>();
texture_environment->tex_mapping.type = TextureMapping::VECTOR;
texture_environment->tex_mapping.rotation[2] = new_viewport_parameters.studiolight_rotate_z;
texture_environment->filename = new_viewport_parameters.studiolight_path;
graph->add(texture_environment);
MixNode *mix_intensity = new MixNode();
MixNode *mix_intensity = graph->create_node<MixNode>();
mix_intensity->type = NODE_MIX_MUL;
mix_intensity->fac = 1.0f;
mix_intensity->color2 = make_float3(new_viewport_parameters.studiolight_intensity,
@ -1376,10 +1377,10 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
new_viewport_parameters.studiolight_intensity);
graph->add(mix_intensity);
TextureCoordinateNode *texture_coordinate = new TextureCoordinateNode();
TextureCoordinateNode *texture_coordinate = graph->create_node<TextureCoordinateNode>();
graph->add(texture_coordinate);
MixNode *mix_background_with_environment = new MixNode();
MixNode *mix_background_with_environment = graph->create_node<MixNode>();
mix_background_with_environment->fac = new_viewport_parameters.studiolight_background_alpha;
mix_background_with_environment->color1 = world_color;
graph->add(mix_background_with_environment);
@ -1466,7 +1467,7 @@ void BlenderSync::sync_lights(BL::Depsgraph &b_depsgraph, bool update_all)
Shader *shader;
/* test if we need to sync */
if (shader_map.add_or_update(&shader, b_light) || update_all) {
if (shader_map.add_or_update(scene, &shader, b_light) || update_all) {
ShaderGraph *graph = new ShaderGraph();
/* create nodes */
@ -1478,7 +1479,7 @@ void BlenderSync::sync_lights(BL::Depsgraph &b_depsgraph, bool update_all)
add_nodes(scene, b_engine, b_data, b_depsgraph, b_scene, graph, b_ntree);
}
else {
EmissionNode *emission = new EmissionNode();
EmissionNode *emission = graph->create_node<EmissionNode>();
emission->color = make_float3(1.0f, 1.0f, 1.0f);
emission->strength = 1.0f;
graph->add(emission);

View File

@ -55,11 +55,11 @@ BlenderSync::BlenderSync(BL::RenderEngine &b_engine,
: b_engine(b_engine),
b_data(b_data),
b_scene(b_scene),
shader_map(&scene->shaders),
object_map(&scene->objects),
geometry_map(&scene->geometry),
light_map(&scene->lights),
particle_system_map(&scene->particle_systems),
shader_map(),
object_map(),
geometry_map(),
light_map(),
particle_system_map(),
world_map(NULL),
world_recalc(false),
scene(scene),
@ -239,7 +239,7 @@ void BlenderSync::sync_data(BL::RenderSettings &b_render,
/* Shader sync done at the end, since object sync uses it.
* false = don't delete unused shaders, not supported. */
shader_map.post_sync(false);
shader_map.post_sync(scene, false);
free_data_after_sync(b_depsgraph);
}

View File

@ -26,10 +26,16 @@ CCL_NAMESPACE_BEGIN
/* Node Type */
NodeOwner::~NodeOwner()
{
}
Node::Node(const NodeType *type_, ustring name_) : name(name_), type(type_)
{
assert(type);
owner = nullptr;
/* assign non-empty name, convenient for debugging */
if (name.empty()) {
name = type->name;
@ -679,4 +685,14 @@ bool Node::is_a(const NodeType *type_)
return false;
}
const NodeOwner *Node::get_owner() const
{
return owner;
}
void Node::set_owner(const NodeOwner *owner_)
{
owner_ = owner;
}
CCL_NAMESPACE_END

View File

@ -31,6 +31,10 @@ struct Transform;
/* Node */
struct NodeOwner {
virtual ~NodeOwner();
};
struct Node {
explicit Node(const NodeType *type, ustring name = ustring());
virtual ~Node() = 0;
@ -99,6 +103,12 @@ struct Node {
ustring name;
const NodeType *type;
const NodeOwner *get_owner() const;
void set_owner(const NodeOwner *owner_);
protected:
const NodeOwner *owner;
};
CCL_NAMESPACE_END

View File

@ -221,7 +221,7 @@ ShaderGraph::ShaderGraph()
finalized = false;
simplified = false;
num_node_ids = 0;
add(new OutputNode());
add(create_node<OutputNode>());
}
ShaderGraph::~ShaderGraph()
@ -272,7 +272,7 @@ void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to)
ShaderInput *convert_in;
if (to->type() == SocketType::CLOSURE) {
EmissionNode *emission = new EmissionNode();
EmissionNode *emission = create_node<EmissionNode>();
emission->color = make_float3(1.0f, 1.0f, 1.0f);
emission->strength = 1.0f;
convert = add(emission);
@ -285,7 +285,7 @@ void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to)
}
}
else {
convert = add(new ConvertNode(from->type(), to->type(), true));
convert = add(create_node<ConvertNode>(from->type(), to->type(), true));
convert_in = convert->inputs[0];
}
@ -416,7 +416,7 @@ void ShaderGraph::find_dependencies(ShaderNodeSet &dependencies, ShaderInput *in
void ShaderGraph::clear_nodes()
{
foreach (ShaderNode *node, nodes) {
delete node;
delete_node(node);
}
nodes.clear();
}
@ -428,7 +428,7 @@ void ShaderGraph::copy_nodes(ShaderNodeSet &nodes, ShaderNodeMap &nnodemap)
/* copy nodes */
foreach (ShaderNode *node, nodes) {
ShaderNode *nnode = node->clone();
ShaderNode *nnode = node->clone(this);
nnodemap[node] = nnode;
/* create new inputs and outputs to recreate links and ensure
@ -523,7 +523,7 @@ void ShaderGraph::remove_proxy_nodes()
if (!removed[node->id])
newnodes.push_back(node);
else
delete node;
delete_node(node);
}
nodes = newnodes;
@ -821,7 +821,7 @@ void ShaderGraph::clean(Scene *scene)
if (visited[node->id])
newnodes.push_back(node);
else
delete node;
delete_node(node);
}
nodes = newnodes;
@ -848,43 +848,43 @@ void ShaderGraph::default_inputs(bool do_osl)
if (!input->link && (!(input->flags() & SocketType::OSL_INTERNAL) || do_osl)) {
if (input->flags() & SocketType::LINK_TEXTURE_GENERATED) {
if (!texco)
texco = new TextureCoordinateNode();
texco = create_node<TextureCoordinateNode>();
connect(texco->output("Generated"), input);
}
if (input->flags() & SocketType::LINK_TEXTURE_NORMAL) {
if (!texco)
texco = new TextureCoordinateNode();
texco = create_node<TextureCoordinateNode>();
connect(texco->output("Normal"), input);
}
else if (input->flags() & SocketType::LINK_TEXTURE_UV) {
if (!texco)
texco = new TextureCoordinateNode();
texco = create_node<TextureCoordinateNode>();
connect(texco->output("UV"), input);
}
else if (input->flags() & SocketType::LINK_INCOMING) {
if (!geom)
geom = new GeometryNode();
geom = create_node<GeometryNode>();
connect(geom->output("Incoming"), input);
}
else if (input->flags() & SocketType::LINK_NORMAL) {
if (!geom)
geom = new GeometryNode();
geom = create_node<GeometryNode>();
connect(geom->output("Normal"), input);
}
else if (input->flags() & SocketType::LINK_POSITION) {
if (!geom)
geom = new GeometryNode();
geom = create_node<GeometryNode>();
connect(geom->output("Position"), input);
}
else if (input->flags() & SocketType::LINK_TANGENT) {
if (!geom)
geom = new GeometryNode();
geom = create_node<GeometryNode>();
connect(geom->output("Tangent"), input);
}
@ -1064,7 +1064,7 @@ void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight
if (fin) {
/* mix closure: add node to mix closure weights */
MixClosureWeightNode *mix_node = new MixClosureWeightNode();
MixClosureWeightNode *mix_node = create_node<MixClosureWeightNode>();
add(mix_node);
ShaderInput *fac_in = mix_node->input("Fac");
ShaderInput *weight_in = mix_node->input("Weight");
@ -1101,7 +1101,7 @@ void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight
/* already has a weight connected to it? add weights */
float weight_value = node->get_float(weight_in->socket_type);
if (weight_in->link || weight_value != 0.0f) {
MathNode *math_node = new MathNode();
MathNode *math_node = create_node<MathNode>();
add(math_node);
if (weight_in->link)

View File

@ -159,7 +159,7 @@ class ShaderNode : public Node {
ShaderInput *input(ustring name);
ShaderOutput *output(ustring name);
virtual ShaderNode *clone() const = 0;
virtual ShaderNode *clone(ShaderGraph *graph) const = 0;
virtual void attributes(Shader *shader, AttributeRequestSet *attributes);
virtual void compile(SVMCompiler &compiler) = 0;
virtual void compile(OSLCompiler &compiler) = 0;
@ -275,9 +275,9 @@ class ShaderNode : public Node {
#define SHADER_NODE_CLASS(type) \
NODE_DECLARE \
type(); \
virtual ShaderNode *clone() const \
virtual ShaderNode *clone(ShaderGraph *graph) const \
{ \
return new type(*this); \
return graph->create_node<type>(*this); \
} \
virtual void compile(SVMCompiler &compiler); \
virtual void compile(OSLCompiler &compiler);
@ -289,9 +289,9 @@ class ShaderNode : public Node {
virtual void compile(OSLCompiler &compiler);
#define SHADER_NODE_BASE_CLASS(type) \
virtual ShaderNode *clone() const \
virtual ShaderNode *clone(ShaderGraph *graph) const \
{ \
return new type(*this); \
return graph->create_node<type>(*this); \
} \
virtual void compile(SVMCompiler &compiler); \
virtual void compile(OSLCompiler &compiler);
@ -312,7 +312,7 @@ typedef map<ShaderNode *, ShaderNode *, ShaderNodeIDComparator> ShaderNodeMap;
* Shader graph of nodes. Also does graph manipulations for default inputs,
* bump mapping from displacement, and possibly other things in the future. */
class ShaderGraph {
class ShaderGraph : public NodeOwner {
public:
list<ShaderNode *> nodes;
size_t num_node_ids;
@ -345,6 +345,24 @@ class ShaderGraph {
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.
*/
template<typename T, typename... Args> T *create_node(Args &&... args)
{
T *node = new T(args...);
node->set_owner(this);
return node;
}
/* This function is used to delete a node created and owned by the graph.
*/
template<typename T> void delete_node(T *node)
{
assert(node->get_owner() == this);
delete node;
}
protected:
typedef pair<ShaderNode *const, ShaderNode *> NodePair;

View File

@ -262,9 +262,9 @@ ImageTextureNode::ImageTextureNode() : ImageSlotTextureNode(node_type)
tiles.push_back(1001);
}
ShaderNode *ImageTextureNode::clone() const
ShaderNode *ImageTextureNode::clone(ShaderGraph *graph) const
{
ImageTextureNode *node = new ImageTextureNode(*this);
ImageTextureNode *node = graph->create_node<ImageTextureNode>(*this);
node->handle = handle;
return node;
}
@ -525,9 +525,9 @@ EnvironmentTextureNode::EnvironmentTextureNode() : ImageSlotTextureNode(node_typ
animated = false;
}
ShaderNode *EnvironmentTextureNode::clone() const
ShaderNode *EnvironmentTextureNode::clone(ShaderGraph *graph) const
{
EnvironmentTextureNode *node = new EnvironmentTextureNode(*this);
EnvironmentTextureNode *node = graph->create_node<EnvironmentTextureNode>(*this);
node->handle = handle;
return node;
}
@ -1234,9 +1234,9 @@ IESLightNode::IESLightNode() : TextureNode(node_type)
slot = -1;
}
ShaderNode *IESLightNode::clone() const
ShaderNode *IESLightNode::clone(ShaderGraph *graph) const
{
IESLightNode *node = new IESLightNode(*this);
IESLightNode *node = graph->create_node<IESLightNode>(*this);
node->light_manager = NULL;
node->slot = -1;
@ -1782,12 +1782,12 @@ PointDensityTextureNode::~PointDensityTextureNode()
{
}
ShaderNode *PointDensityTextureNode::clone() const
ShaderNode *PointDensityTextureNode::clone(ShaderGraph *graph) const
{
/* Increase image user count for new node. We need to ensure to not call
* add_image again, to work around access of freed data on the Blender
* side. A better solution should be found to avoid this. */
PointDensityTextureNode *node = new PointDensityTextureNode(*this);
PointDensityTextureNode *node = graph->create_node<PointDensityTextureNode>(*this);
node->handle = handle; /* TODO: not needed? */
return node;
}
@ -2783,8 +2783,8 @@ void PrincipledBsdfNode::expand(ShaderGraph *graph)
ShaderInput *emission_in = input("Emission");
if (emission_in->link || emission != make_float3(0.0f, 0.0f, 0.0f)) {
/* Create add closure and emission. */
AddClosureNode *add = new AddClosureNode();
EmissionNode *emission_node = new EmissionNode();
AddClosureNode *add = graph->create_node<AddClosureNode>();
EmissionNode *emission_node = graph->create_node<EmissionNode>();
ShaderOutput *new_out = add->output("Closure");
graph->add(add);
@ -2802,8 +2802,8 @@ void PrincipledBsdfNode::expand(ShaderGraph *graph)
ShaderInput *alpha_in = input("Alpha");
if (alpha_in->link || alpha != 1.0f) {
/* Create mix and transparent BSDF for alpha transparency. */
MixClosureNode *mix = new MixClosureNode();
TransparentBsdfNode *transparent = new TransparentBsdfNode();
MixClosureNode *mix = graph->create_node<MixClosureNode>();
TransparentBsdfNode *transparent = graph->create_node<TransparentBsdfNode>();
graph->add(mix);
graph->add(transparent);
@ -4475,7 +4475,7 @@ void VolumeInfoNode::expand(ShaderGraph *graph)
{
ShaderOutput *color_out = output("Color");
if (!color_out->links.empty()) {
AttributeNode *attr = new AttributeNode();
AttributeNode *attr = graph->create_node<AttributeNode>();
attr->attribute = "color";
graph->add(attr);
graph->relink(color_out, attr->output("Color"));
@ -4483,7 +4483,7 @@ void VolumeInfoNode::expand(ShaderGraph *graph)
ShaderOutput *density_out = output("Density");
if (!density_out->links.empty()) {
AttributeNode *attr = new AttributeNode();
AttributeNode *attr = graph->create_node<AttributeNode>();
attr->attribute = "density";
graph->add(attr);
graph->relink(density_out, attr->output("Fac"));
@ -4491,7 +4491,7 @@ void VolumeInfoNode::expand(ShaderGraph *graph)
ShaderOutput *flame_out = output("Flame");
if (!flame_out->links.empty()) {
AttributeNode *attr = new AttributeNode();
AttributeNode *attr = graph->create_node<AttributeNode>();
attr->attribute = "flame";
graph->add(attr);
graph->relink(flame_out, attr->output("Fac"));
@ -4499,7 +4499,7 @@ void VolumeInfoNode::expand(ShaderGraph *graph)
ShaderOutput *temperature_out = output("Temperature");
if (!temperature_out->links.empty()) {
AttributeNode *attr = new AttributeNode();
AttributeNode *attr = graph->create_node<AttributeNode>();
attr->attribute = "temperature";
graph->add(attr);
graph->relink(temperature_out, attr->output("Fac"));
@ -5768,7 +5768,7 @@ void MapRangeNode::expand(ShaderGraph *graph)
if (clamp) {
ShaderOutput *result_out = output("Result");
if (!result_out->links.empty()) {
ClampNode *clamp_node = new ClampNode();
ClampNode *clamp_node = graph->create_node<ClampNode>();
clamp_node->type = NODE_CLAMP_RANGE;
graph->add(clamp_node);
graph->relink(result_out, clamp_node->output("Result"));
@ -6009,7 +6009,7 @@ void MathNode::expand(ShaderGraph *graph)
if (use_clamp) {
ShaderOutput *result_out = output("Value");
if (!result_out->links.empty()) {
ClampNode *clamp_node = new ClampNode();
ClampNode *clamp_node = graph->create_node<ClampNode>();
clamp_node->type = NODE_CLAMP_MINMAX;
clamp_node->min = 0.0f;
clamp_node->max = 1.0f;
@ -6337,7 +6337,7 @@ void BumpNode::constant_fold(const ConstantFolder &folder)
if (height_in->link == NULL) {
if (normal_in->link == NULL) {
GeometryNode *geom = new GeometryNode();
GeometryNode *geom = folder.graph->create_node<GeometryNode>();
folder.graph->add(geom);
folder.bypass(geom->output("Normal"));
}
@ -6620,12 +6620,12 @@ OSLNode::~OSLNode()
delete type;
}
ShaderNode *OSLNode::clone() const
ShaderNode *OSLNode::clone(ShaderGraph *graph) const
{
return OSLNode::create(this->inputs.size(), this);
return OSLNode::create(graph, this->inputs.size(), this);
}
OSLNode *OSLNode::create(size_t num_inputs, const OSLNode *from)
OSLNode *OSLNode::create(ShaderGraph *graph, size_t num_inputs, const OSLNode *from)
{
/* allocate space for the node itself and parameters, aligned to 16 bytes
* assuming that's the most parameter types need */
@ -6636,7 +6636,9 @@ OSLNode *OSLNode::create(size_t num_inputs, const OSLNode *from)
memset(node_memory, 0, node_size + inputs_size);
if (!from) {
return new (node_memory) OSLNode();
OSLNode *node = new (node_memory) OSLNode();
node->set_owner(graph);
return node;
}
else {
/* copy input default values and node type for cloning */
@ -6644,6 +6646,7 @@ OSLNode *OSLNode::create(size_t num_inputs, const OSLNode *from)
OSLNode *node = new (node_memory) OSLNode(*from);
node->type = new NodeType(*(from->type));
node->set_owner(from->owner);
return node;
}
}

View File

@ -92,7 +92,7 @@ class ImageSlotTextureNode : public TextureNode {
class ImageTextureNode : public ImageSlotTextureNode {
public:
SHADER_NODE_NO_CLONE_CLASS(ImageTextureNode)
ShaderNode *clone() const;
ShaderNode *clone(ShaderGraph *graph) const;
void attributes(Shader *shader, AttributeRequestSet *attributes);
bool has_attribute_dependency()
{
@ -126,7 +126,7 @@ class ImageTextureNode : public ImageSlotTextureNode {
class EnvironmentTextureNode : public ImageSlotTextureNode {
public:
SHADER_NODE_NO_CLONE_CLASS(EnvironmentTextureNode)
ShaderNode *clone() const;
ShaderNode *clone(ShaderGraph *graph) const;
void attributes(Shader *shader, AttributeRequestSet *attributes);
bool has_attribute_dependency()
{
@ -364,7 +364,7 @@ class PointDensityTextureNode : public ShaderNode {
}
~PointDensityTextureNode();
ShaderNode *clone() const;
ShaderNode *clone(ShaderGraph *graph) const;
void attributes(Shader *shader, AttributeRequestSet *attributes);
bool has_attribute_dependency()
{
@ -400,7 +400,7 @@ class IESLightNode : public TextureNode {
SHADER_NODE_NO_CLONE_CLASS(IESLightNode)
~IESLightNode();
ShaderNode *clone() const;
ShaderNode *clone(ShaderGraph *graph) const;
virtual int get_group()
{
return NODE_GROUP_LEVEL_2;
@ -1501,10 +1501,10 @@ class SetNormalNode : public ShaderNode {
class OSLNode : public ShaderNode {
public:
static OSLNode *create(size_t num_inputs, const OSLNode *from = NULL);
static OSLNode *create(ShaderGraph *graph, size_t num_inputs, const OSLNode *from = NULL);
~OSLNode();
ShaderNode *clone() const;
ShaderNode *clone(ShaderGraph *graph) const;
char *input_default_value();
void add_input(ustring name, SocketType::Type type);

View File

@ -439,7 +439,8 @@ const char *OSLShaderManager::shader_load_bytecode(const string &hash, const str
/* This is a static function to avoid RTTI link errors with only this
* file being compiled without RTTI to match OSL and LLVM libraries. */
OSLNode *OSLShaderManager::osl_node(ShaderManager *manager,
OSLNode *OSLShaderManager::osl_node(ShaderGraph *graph,
ShaderManager *manager,
const std::string &filepath,
const std::string &bytecode_hash,
const std::string &bytecode)
@ -482,7 +483,7 @@ OSLNode *OSLShaderManager::osl_node(ShaderManager *manager,
}
/* create node */
OSLNode *node = OSLNode::create(num_inputs);
OSLNode *node = OSLNode::create(graph, num_inputs);
/* add new sockets from parameters */
set<void *> used_sockets;

View File

@ -93,7 +93,8 @@ class OSLShaderManager : public ShaderManager {
OSLShaderInfo *shader_loaded_info(const string &hash);
/* create OSL node using OSLQuery */
static OSLNode *osl_node(ShaderManager *manager,
static OSLNode *osl_node(ShaderGraph *graph,
ShaderManager *manager,
const std::string &filepath,
const std::string &bytecode_hash = "",
const std::string &bytecode = "");

View File

@ -29,7 +29,13 @@ CCL_NAMESPACE_BEGIN
/* Particle System */
ParticleSystem::ParticleSystem()
NODE_DEFINE(ParticleSystem)
{
NodeType *type = NodeType::add("particle_system", create);
return type;
}
ParticleSystem::ParticleSystem() : Node(node_type)
{
}

View File

@ -20,6 +20,8 @@
#include "util/util_array.h"
#include "util/util_types.h"
#include "graph/node.h"
CCL_NAMESPACE_BEGIN
class Device;
@ -40,8 +42,10 @@ struct Particle {
float3 angular_velocity;
};
class ParticleSystem {
class ParticleSystem : public Node {
public:
NODE_DECLARE
ParticleSystem();
~ParticleSystem();

View File

@ -33,6 +33,7 @@
#include "render/shader.h"
#include "render/svm.h"
#include "render/tables.h"
#include "render/volume.h"
#include "util/util_foreach.h"
#include "util/util_guarded_allocator.h"
@ -98,15 +99,15 @@ Scene::Scene(const SceneParams &params_, Device *device)
{
memset((void *)&dscene.data, 0, sizeof(dscene.data));
camera = new Camera();
dicing_camera = new Camera();
camera = create_node<Camera>();
dicing_camera = create_node<Camera>();
lookup_tables = new LookupTables();
film = new Film();
background = new Background();
film = create_node<Film>();
background = create_node<Background>();
light_manager = new LightManager();
geometry_manager = new GeometryManager();
object_manager = new ObjectManager();
integrator = new Integrator();
integrator = create_node<Integrator>();
image_manager = new ImageManager(device->info);
particle_system_manager = new ParticleSystemManager();
bake_manager = new BakeManager();
@ -560,4 +561,127 @@ int Scene::get_max_closure_count()
return max_closure_global;
}
template<> Light *Scene::create_node<Light>()
{
Light *node = new Light();
node->set_owner(this);
lights.push_back(node);
light_manager->tag_update(this);
return node;
}
template<> Mesh *Scene::create_node<Mesh>()
{
Mesh *node = new Mesh();
node->set_owner(this);
geometry.push_back(node);
geometry_manager->tag_update(this);
return node;
}
template<> Hair *Scene::create_node<Hair>()
{
Hair *node = new Hair();
node->set_owner(this);
geometry.push_back(node);
geometry_manager->tag_update(this);
return node;
}
template<> Volume *Scene::create_node<Volume>()
{
Volume *node = new Volume();
node->set_owner(this);
geometry.push_back(node);
geometry_manager->tag_update(this);
return node;
}
template<> Object *Scene::create_node<Object>()
{
Object *node = new Object();
node->set_owner(this);
objects.push_back(node);
object_manager->tag_update(this);
return node;
}
template<> ParticleSystem *Scene::create_node<ParticleSystem>()
{
ParticleSystem *node = new ParticleSystem();
node->set_owner(this);
particle_systems.push_back(node);
particle_system_manager->tag_update(this);
return node;
}
template<> Shader *Scene::create_node<Shader>()
{
Shader *node = new Shader();
node->set_owner(this);
shaders.push_back(node);
shader_manager->need_update = true;
return node;
}
template<typename T> void delete_node_from_array(vector<T> &nodes, T node)
{
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;
}
template<> void Scene::delete_node_impl(Light *node)
{
delete_node_from_array(lights, node);
light_manager->tag_update(this);
}
template<> void Scene::delete_node_impl(Mesh *node)
{
delete_node_from_array(geometry, static_cast<Geometry *>(node));
geometry_manager->tag_update(this);
}
template<> void Scene::delete_node_impl(Hair *node)
{
delete_node_from_array(geometry, static_cast<Geometry *>(node));
geometry_manager->tag_update(this);
}
template<> void Scene::delete_node_impl(Volume *node)
{
delete_node_from_array(geometry, static_cast<Geometry *>(node));
geometry_manager->tag_update(this);
}
template<> void Scene::delete_node_impl(Geometry *node)
{
delete_node_from_array(geometry, node);
geometry_manager->tag_update(this);
}
template<> void Scene::delete_node_impl(Object *node)
{
delete_node_from_array(objects, node);
object_manager->tag_update(this);
}
template<> void Scene::delete_node_impl(ParticleSystem *node)
{
delete_node_from_array(particle_systems, node);
particle_system_manager->tag_update(this);
}
template<> void Scene::delete_node_impl(Shader * /*node*/)
{
/* don't delete unused shaders, not supported */
}
CCL_NAMESPACE_END

View File

@ -59,6 +59,7 @@ class Progress;
class BakeManager;
class BakeData;
class RenderStats;
class Volume;
/* Scene Device Data */
@ -212,7 +213,7 @@ class SceneParams {
/* Scene */
class Scene {
class Scene : public NodeOwner {
public:
/* Optional name. Is used for logging and reporting. */
string name;
@ -281,6 +282,40 @@ class Scene {
bool update(Progress &progress, bool &kernel_switch_needed);
/* This function is used to create a node of a specified type instead of
* calling 'new', and sets the scene as the owner of the node.
* The function has overloads that will also add the created node to the right
* 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;
}
/* 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
* appropriate manager for an update, if any, and checks that the scene is indeed
* 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;
}
protected:
/* Check if some heavy data worth logging was updated.
* Mainly used to suppress extra annoying logging.
@ -303,8 +338,43 @@ class Scene {
/* Get maximum number of closures to be used in kernel. */
int get_max_closure_count();
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<> ParticleSystem *Scene::create_node<ParticleSystem>();
template<> Shader *Scene::create_node<Shader>();
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(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);
CCL_NAMESPACE_END
#endif /* __SCENE_H__ */

View File

@ -624,16 +624,15 @@ void ShaderManager::add_default(Scene *scene)
{
ShaderGraph *graph = new ShaderGraph();
DiffuseBsdfNode *diffuse = new DiffuseBsdfNode();
DiffuseBsdfNode *diffuse = graph->create_node<DiffuseBsdfNode>();
diffuse->color = make_float3(0.8f, 0.8f, 0.8f);
graph->add(diffuse);
graph->connect(diffuse->output("BSDF"), graph->output()->input("Surface"));
Shader *shader = new Shader();
Shader *shader = scene->create_node<Shader>();
shader->name = "default_surface";
shader->set_graph(graph);
scene->shaders.push_back(shader);
scene->default_surface = shader;
shader->tag_update(scene);
}
@ -642,15 +641,14 @@ void ShaderManager::add_default(Scene *scene)
{
ShaderGraph *graph = new ShaderGraph();
PrincipledVolumeNode *principled = new PrincipledVolumeNode();
PrincipledVolumeNode *principled = graph->create_node<PrincipledVolumeNode>();
graph->add(principled);
graph->connect(principled->output("Volume"), graph->output()->input("Volume"));
Shader *shader = new Shader();
Shader *shader = scene->create_node<Shader>();
shader->name = "default_volume";
shader->set_graph(graph);
scene->shaders.push_back(shader);
scene->default_volume = shader;
shader->tag_update(scene);
}
@ -659,17 +657,16 @@ void ShaderManager::add_default(Scene *scene)
{
ShaderGraph *graph = new ShaderGraph();
EmissionNode *emission = new EmissionNode();
EmissionNode *emission = graph->create_node<EmissionNode>();
emission->color = make_float3(0.8f, 0.8f, 0.8f);
emission->strength = 0.0f;
graph->add(emission);
graph->connect(emission->output("Emission"), graph->output()->input("Surface"));
Shader *shader = new Shader();
Shader *shader = scene->create_node<Shader>();
shader->name = "default_light";
shader->set_graph(graph);
scene->shaders.push_back(shader);
scene->default_light = shader;
shader->tag_update(scene);
}
@ -678,10 +675,9 @@ void ShaderManager::add_default(Scene *scene)
{
ShaderGraph *graph = new ShaderGraph();
Shader *shader = new Shader();
Shader *shader = scene->create_node<Shader>();
shader->name = "default_background";
shader->set_graph(graph);
scene->shaders.push_back(shader);
scene->default_background = shader;
shader->tag_update(scene);
}
@ -690,10 +686,9 @@ void ShaderManager::add_default(Scene *scene)
{
ShaderGraph *graph = new ShaderGraph();
Shader *shader = new Shader();
Shader *shader = scene->create_node<Shader>();
shader->name = "default_empty";
shader->set_graph(graph);
scene->shaders.push_back(shader);
scene->default_empty = shader;
shader->tag_update(scene);
}