Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/render/scene.cpp')
-rw-r--r--intern/cycles/render/scene.cpp959
1 files changed, 0 insertions, 959 deletions
diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp
deleted file mode 100644
index 6d79536061e..00000000000
--- a/intern/cycles/render/scene.cpp
+++ /dev/null
@@ -1,959 +0,0 @@
-/*
- * Copyright 2011-2013 Blender Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdlib.h>
-
-#include "bvh/bvh.h"
-#include "device/device.h"
-#include "render/alembic.h"
-#include "render/background.h"
-#include "render/bake.h"
-#include "render/camera.h"
-#include "render/curves.h"
-#include "render/film.h"
-#include "render/integrator.h"
-#include "render/light.h"
-#include "render/mesh.h"
-#include "render/object.h"
-#include "render/osl.h"
-#include "render/particles.h"
-#include "render/procedural.h"
-#include "render/scene.h"
-#include "render/session.h"
-#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"
-#include "util/util_logging.h"
-#include "util/util_progress.h"
-
-CCL_NAMESPACE_BEGIN
-
-DeviceScene::DeviceScene(Device *device)
- : bvh_nodes(device, "__bvh_nodes", MEM_GLOBAL),
- bvh_leaf_nodes(device, "__bvh_leaf_nodes", MEM_GLOBAL),
- object_node(device, "__object_node", MEM_GLOBAL),
- prim_type(device, "__prim_type", MEM_GLOBAL),
- prim_visibility(device, "__prim_visibility", MEM_GLOBAL),
- prim_index(device, "__prim_index", MEM_GLOBAL),
- prim_object(device, "__prim_object", MEM_GLOBAL),
- prim_time(device, "__prim_time", MEM_GLOBAL),
- tri_verts(device, "__tri_verts", MEM_GLOBAL),
- tri_shader(device, "__tri_shader", MEM_GLOBAL),
- tri_vnormal(device, "__tri_vnormal", MEM_GLOBAL),
- tri_vindex(device, "__tri_vindex", MEM_GLOBAL),
- tri_patch(device, "__tri_patch", MEM_GLOBAL),
- tri_patch_uv(device, "__tri_patch_uv", MEM_GLOBAL),
- curves(device, "__curves", MEM_GLOBAL),
- curve_keys(device, "__curve_keys", MEM_GLOBAL),
- curve_segments(device, "__curve_segments", MEM_GLOBAL),
- patches(device, "__patches", MEM_GLOBAL),
- objects(device, "__objects", MEM_GLOBAL),
- object_motion_pass(device, "__object_motion_pass", MEM_GLOBAL),
- object_motion(device, "__object_motion", MEM_GLOBAL),
- object_flag(device, "__object_flag", MEM_GLOBAL),
- object_volume_step(device, "__object_volume_step", MEM_GLOBAL),
- camera_motion(device, "__camera_motion", MEM_GLOBAL),
- attributes_map(device, "__attributes_map", MEM_GLOBAL),
- attributes_float(device, "__attributes_float", MEM_GLOBAL),
- attributes_float2(device, "__attributes_float2", MEM_GLOBAL),
- attributes_float3(device, "__attributes_float3", MEM_GLOBAL),
- attributes_uchar4(device, "__attributes_uchar4", MEM_GLOBAL),
- light_distribution(device, "__light_distribution", MEM_GLOBAL),
- lights(device, "__lights", MEM_GLOBAL),
- light_background_marginal_cdf(device, "__light_background_marginal_cdf", MEM_GLOBAL),
- light_background_conditional_cdf(device, "__light_background_conditional_cdf", MEM_GLOBAL),
- particles(device, "__particles", MEM_GLOBAL),
- svm_nodes(device, "__svm_nodes", MEM_GLOBAL),
- shaders(device, "__shaders", MEM_GLOBAL),
- lookup_table(device, "__lookup_table", MEM_GLOBAL),
- sample_pattern_lut(device, "__sample_pattern_lut", MEM_GLOBAL),
- ies_lights(device, "__ies", MEM_GLOBAL)
-{
- memset((void *)&data, 0, sizeof(data));
-}
-
-Scene::Scene(const SceneParams &params_, Device *device)
- : name("Scene"),
- bvh(NULL),
- default_surface(NULL),
- default_volume(NULL),
- default_light(NULL),
- default_background(NULL),
- default_empty(NULL),
- device(device),
- dscene(device),
- params(params_),
- update_stats(NULL),
- kernels_loaded(false),
- /* TODO(sergey): Check if it's indeed optimal value for the split kernel. */
- max_closure_global(1)
-{
- memset((void *)&dscene.data, 0, sizeof(dscene.data));
-
- /* OSL only works on the CPU */
- if (device->info.has_osl)
- shader_manager = ShaderManager::create(params.shadingsystem);
- else
- shader_manager = ShaderManager::create(SHADINGSYSTEM_SVM);
-
- light_manager = new LightManager();
- geometry_manager = new GeometryManager();
- object_manager = new ObjectManager();
- image_manager = new ImageManager(device->info);
- particle_system_manager = new ParticleSystemManager();
- bake_manager = new BakeManager();
- procedural_manager = new ProceduralManager();
-
- /* Create nodes after managers, since create_node() can tag the managers. */
- camera = create_node<Camera>();
- dicing_camera = create_node<Camera>();
- lookup_tables = new LookupTables();
- film = create_node<Film>();
- background = create_node<Background>();
- integrator = create_node<Integrator>();
-
- film->add_default(this);
- shader_manager->add_default(this);
-}
-
-Scene::~Scene()
-{
- free_memory(true);
-}
-
-void Scene::free_memory(bool final)
-{
- delete bvh;
- bvh = NULL;
-
- /* The order of deletion is important to make sure data is freed based on possible dependencies
- * as the Nodes' reference counts are decremented in the destructors:
- *
- * - Procedurals can create and hold pointers to any other types.
- * - Objects can hold pointers to Geometries and ParticleSystems
- * - Lights and Geometries can hold pointers to Shaders.
- *
- * Similarly, we first delete all nodes and their associated device data, and then the managers
- * and their associated device data.
- */
- foreach (Procedural *p, procedurals)
- delete p;
- foreach (Object *o, objects)
- delete o;
- foreach (Geometry *g, geometry)
- delete g;
- foreach (ParticleSystem *p, particle_systems)
- delete p;
- foreach (Light *l, lights)
- delete l;
- foreach (Pass *p, passes)
- delete p;
-
- geometry.clear();
- objects.clear();
- lights.clear();
- particle_systems.clear();
- procedurals.clear();
- passes.clear();
-
- if (device) {
- camera->device_free(device, &dscene, this);
- film->device_free(device, &dscene, this);
- background->device_free(device, &dscene);
- integrator->device_free(device, &dscene, true);
- }
-
- if (final) {
- delete camera;
- delete dicing_camera;
- delete film;
- delete background;
- delete integrator;
- }
-
- /* Delete Shaders after every other nodes to ensure that we do not try to decrement the reference
- * count on some dangling pointer. */
- foreach (Shader *s, shaders)
- delete s;
-
- shaders.clear();
-
- /* Now that all nodes have been deleted, we can safely delete managers and device data. */
- if (device) {
- object_manager->device_free(device, &dscene, true);
- geometry_manager->device_free(device, &dscene, true);
- shader_manager->device_free(device, &dscene, this);
- light_manager->device_free(device, &dscene);
-
- particle_system_manager->device_free(device, &dscene);
-
- bake_manager->device_free(device, &dscene);
-
- if (final)
- image_manager->device_free(device);
- else
- image_manager->device_free_builtin(device);
-
- lookup_tables->device_free(device, &dscene);
- }
-
- if (final) {
- delete lookup_tables;
- delete object_manager;
- delete geometry_manager;
- delete shader_manager;
- delete light_manager;
- delete particle_system_manager;
- delete image_manager;
- delete bake_manager;
- delete update_stats;
- delete procedural_manager;
- }
-}
-
-void Scene::host_update(Progress &progress)
-{
- if (update_stats) {
- update_stats->clear();
- }
-
- scoped_callback_timer timer([this](double time) {
- if (update_stats) {
- update_stats->scene.times.add_entry({"host_update", time});
- }
- });
-
- progress.set_status("Updating Shaders");
- shader_manager->host_update(this, progress);
-}
-
-void Scene::device_update(Device *device_, Progress &progress)
-{
- if (!device)
- device = device_;
-
- bool print_stats = need_data_update();
-
- scoped_callback_timer timer([this, print_stats](double time) {
- if (update_stats) {
- update_stats->scene.times.add_entry({"device_update", time});
-
- if (print_stats) {
- printf("Update statistics:\n%s\n", update_stats->full_report().c_str());
- }
- }
- });
-
- /* The order of updates is important, because there's dependencies between
- * the different managers, using data computed by previous managers.
- *
- * - Image manager uploads images used by shaders.
- * - Camera may be used for adaptive subdivision.
- * - Displacement shader must have all shader data available.
- * - Light manager needs lookup tables and final mesh data to compute emission CDF.
- * - Lookup tables are done a second time to handle film tables
- */
-
- progress.set_status("Updating Shaders");
- shader_manager->device_update(device, &dscene, this, progress);
-
- if (progress.get_cancel() || device->have_error())
- return;
-
- procedural_manager->update(this, progress);
-
- if (progress.get_cancel())
- return;
-
- progress.set_status("Updating Background");
- background->device_update(device, &dscene, this);
-
- if (progress.get_cancel() || device->have_error())
- return;
-
- progress.set_status("Updating Camera");
- camera->device_update(device, &dscene, this);
-
- if (progress.get_cancel() || device->have_error())
- return;
-
- geometry_manager->device_update_preprocess(device, this, progress);
-
- if (progress.get_cancel() || device->have_error())
- return;
-
- progress.set_status("Updating Objects");
- object_manager->device_update(device, &dscene, this, progress);
-
- if (progress.get_cancel() || device->have_error())
- return;
-
- progress.set_status("Updating Particle Systems");
- particle_system_manager->device_update(device, &dscene, this, progress);
-
- if (progress.get_cancel() || device->have_error())
- return;
-
- progress.set_status("Updating Meshes");
- geometry_manager->device_update(device, &dscene, this, progress);
-
- if (progress.get_cancel() || device->have_error())
- return;
-
- progress.set_status("Updating Objects Flags");
- object_manager->device_update_flags(device, &dscene, this, progress);
-
- if (progress.get_cancel() || device->have_error())
- return;
-
- progress.set_status("Updating Images");
- image_manager->device_update(device, this, progress);
-
- if (progress.get_cancel() || device->have_error())
- return;
-
- progress.set_status("Updating Camera Volume");
- camera->device_update_volume(device, &dscene, this);
-
- if (progress.get_cancel() || device->have_error())
- return;
-
- progress.set_status("Updating Lookup Tables");
- lookup_tables->device_update(device, &dscene, this);
-
- if (progress.get_cancel() || device->have_error())
- return;
-
- progress.set_status("Updating Lights");
- light_manager->device_update(device, &dscene, this, progress);
-
- if (progress.get_cancel() || device->have_error())
- return;
-
- progress.set_status("Updating Integrator");
- integrator->device_update(device, &dscene, this);
-
- if (progress.get_cancel() || device->have_error())
- return;
-
- progress.set_status("Updating Film");
- film->device_update(device, &dscene, this);
-
- if (progress.get_cancel() || device->have_error())
- return;
-
- progress.set_status("Updating Lookup Tables");
- lookup_tables->device_update(device, &dscene, this);
-
- if (progress.get_cancel() || device->have_error())
- return;
-
- progress.set_status("Updating Baking");
- bake_manager->device_update(device, &dscene, this, progress);
-
- if (progress.get_cancel() || device->have_error())
- return;
-
- if (device->have_error() == false) {
- progress.set_status("Updating Device", "Writing constant memory");
- device->const_copy_to("__data", &dscene.data, sizeof(dscene.data));
- }
-
- if (print_stats) {
- size_t mem_used = util_guarded_get_mem_used();
- size_t mem_peak = util_guarded_get_mem_peak();
-
- VLOG(1) << "System memory statistics after full device sync:\n"
- << " Usage: " << string_human_readable_number(mem_used) << " ("
- << string_human_readable_size(mem_used) << ")\n"
- << " Peak: " << string_human_readable_number(mem_peak) << " ("
- << string_human_readable_size(mem_peak) << ")";
- }
-}
-
-Scene::MotionType Scene::need_motion()
-{
- if (integrator->get_motion_blur())
- return MOTION_BLUR;
- else if (Pass::contains(passes, PASS_MOTION))
- return MOTION_PASS;
- else
- return MOTION_NONE;
-}
-
-float Scene::motion_shutter_time()
-{
- if (need_motion() == Scene::MOTION_PASS)
- return 2.0f;
- else
- return camera->get_shuttertime();
-}
-
-bool Scene::need_global_attribute(AttributeStandard std)
-{
- if (std == ATTR_STD_UV)
- return Pass::contains(passes, PASS_UV);
- else if (std == ATTR_STD_MOTION_VERTEX_POSITION)
- return need_motion() != MOTION_NONE;
- else if (std == ATTR_STD_MOTION_VERTEX_NORMAL)
- return need_motion() == MOTION_BLUR;
-
- return false;
-}
-
-void Scene::need_global_attributes(AttributeRequestSet &attributes)
-{
- for (int std = ATTR_STD_NONE; std < ATTR_STD_NUM; std++)
- if (need_global_attribute((AttributeStandard)std))
- attributes.add((AttributeStandard)std);
-}
-
-bool Scene::need_update()
-{
- return (need_reset() || film->is_modified());
-}
-
-bool Scene::need_data_update()
-{
- return (background->is_modified() || image_manager->need_update() ||
- object_manager->need_update() || geometry_manager->need_update() ||
- light_manager->need_update() || lookup_tables->need_update() ||
- integrator->is_modified() || shader_manager->need_update() ||
- particle_system_manager->need_update() || bake_manager->need_update() ||
- film->is_modified() || procedural_manager->need_update());
-}
-
-bool Scene::need_reset()
-{
- return need_data_update() || camera->is_modified();
-}
-
-void Scene::reset()
-{
- shader_manager->reset(this);
- shader_manager->add_default(this);
-
- /* ensure all objects are updated */
- camera->tag_modified();
- dicing_camera->tag_modified();
- film->tag_modified();
- background->tag_modified();
-
- background->tag_update(this);
- integrator->tag_update(this, Integrator::UPDATE_ALL);
- object_manager->tag_update(this, ObjectManager::UPDATE_ALL);
- geometry_manager->tag_update(this, GeometryManager::UPDATE_ALL);
- light_manager->tag_update(this, LightManager::UPDATE_ALL);
- particle_system_manager->tag_update(this);
- procedural_manager->tag_update();
-}
-
-void Scene::device_free()
-{
- free_memory(false);
-}
-
-void Scene::collect_statistics(RenderStats *stats)
-{
- geometry_manager->collect_statistics(this, stats);
- image_manager->collect_statistics(stats);
-}
-
-void Scene::enable_update_stats()
-{
- if (!update_stats) {
- update_stats = new SceneUpdateStats();
- }
-}
-
-void Scene::update_kernel_features()
-{
- if (!need_update()) {
- return;
- }
-
- /* These features are not being tweaked as often as shaders,
- * so could be done selective magic for the viewport as well. */
- uint kernel_features = shader_manager->get_kernel_features(this);
-
- bool use_motion = need_motion() == Scene::MotionType::MOTION_BLUR;
- kernel_features |= KERNEL_FEATURE_PATH_TRACING;
- if (params.hair_shape == CURVE_THICK) {
- kernel_features |= KERNEL_FEATURE_HAIR_THICK;
- }
- if (use_motion && camera->use_motion()) {
- kernel_features |= KERNEL_FEATURE_CAMERA_MOTION;
- }
- foreach (Object *object, objects) {
- Geometry *geom = object->get_geometry();
- if (use_motion) {
- if (object->use_motion() || geom->get_use_motion_blur()) {
- kernel_features |= KERNEL_FEATURE_OBJECT_MOTION;
- }
- if (geom->get_use_motion_blur()) {
- kernel_features |= KERNEL_FEATURE_CAMERA_MOTION;
- }
- }
- if (object->get_is_shadow_catcher()) {
- kernel_features |= KERNEL_FEATURE_SHADOW_CATCHER;
- }
- if (geom->is_mesh()) {
- Mesh *mesh = static_cast<Mesh *>(geom);
-#ifdef WITH_OPENSUBDIV
- if (mesh->get_subdivision_type() != Mesh::SUBDIVISION_NONE) {
- kernel_features |= KERNEL_FEATURE_PATCH_EVALUATION;
- }
-#endif
- }
- else if (geom->is_hair()) {
- kernel_features |= KERNEL_FEATURE_HAIR;
- }
- }
-
- if (bake_manager->get_baking()) {
- kernel_features |= KERNEL_FEATURE_BAKING;
- }
-
- kernel_features |= film->get_kernel_features(this);
-
- dscene.data.kernel_features = kernel_features;
-
- /* Currently viewport render is faster with higher max_closures, needs investigating. */
- const uint max_closures = (params.background) ? get_max_closure_count() : MAX_CLOSURE;
- dscene.data.max_closures = max_closures;
- dscene.data.max_shaders = shaders.size();
-
- dscene.data.volume_stack_size = get_volume_stack_size();
-}
-
-bool Scene::update(Progress &progress)
-{
- if (!need_update()) {
- return false;
- }
-
- /* Update scene data on the host side.
- * Only updates which do not depend on the kernel (including kernel features). */
- progress.set_status("Updating Scene");
- MEM_GUARDED_CALL(&progress, host_update, progress);
-
- /* Load render kernels. After host scene update so that the required kernel features are known.
- */
- load_kernels(progress, false);
-
- /* Upload scene data to the device. */
- progress.set_status("Updating Scene Device");
- MEM_GUARDED_CALL(&progress, device_update, device, progress);
-
- return true;
-}
-
-static void log_kernel_features(const uint features)
-{
- VLOG(2) << "Requested features:\n";
- VLOG(2) << "Use BSDF " << string_from_bool(features & KERNEL_FEATURE_NODE_BSDF) << "\n";
- VLOG(2) << "Use Principled BSDF " << string_from_bool(features & KERNEL_FEATURE_PRINCIPLED)
- << "\n";
- VLOG(2) << "Use Emission " << string_from_bool(features & KERNEL_FEATURE_NODE_EMISSION) << "\n";
- VLOG(2) << "Use Volume " << string_from_bool(features & KERNEL_FEATURE_NODE_VOLUME) << "\n";
- VLOG(2) << "Use Hair " << string_from_bool(features & KERNEL_FEATURE_NODE_HAIR) << "\n";
- VLOG(2) << "Use Bump " << string_from_bool(features & KERNEL_FEATURE_NODE_BUMP) << "\n";
- VLOG(2) << "Use Voronoi " << string_from_bool(features & KERNEL_FEATURE_NODE_VORONOI_EXTRA)
- << "\n";
- VLOG(2) << "Use Shader Raytrace " << string_from_bool(features & KERNEL_FEATURE_NODE_RAYTRACE)
- << "\n";
- VLOG(2) << "Use Transparent " << string_from_bool(features & KERNEL_FEATURE_TRANSPARENT) << "\n";
- VLOG(2) << "Use Denoising " << string_from_bool(features & KERNEL_FEATURE_DENOISING) << "\n";
- VLOG(2) << "Use Path Tracing " << string_from_bool(features & KERNEL_FEATURE_PATH_TRACING)
- << "\n";
- VLOG(2) << "Use Hair " << string_from_bool(features & KERNEL_FEATURE_HAIR) << "\n";
- VLOG(2) << "Use Object Motion " << string_from_bool(features & KERNEL_FEATURE_OBJECT_MOTION)
- << "\n";
- VLOG(2) << "Use Camera Motion " << string_from_bool(features & KERNEL_FEATURE_CAMERA_MOTION)
- << "\n";
- VLOG(2) << "Use Baking " << string_from_bool(features & KERNEL_FEATURE_BAKING) << "\n";
- VLOG(2) << "Use Subsurface " << string_from_bool(features & KERNEL_FEATURE_SUBSURFACE) << "\n";
- VLOG(2) << "Use Volume " << string_from_bool(features & KERNEL_FEATURE_VOLUME) << "\n";
- VLOG(2) << "Use Patch Evaluation "
- << string_from_bool(features & KERNEL_FEATURE_PATCH_EVALUATION) << "\n";
- VLOG(2) << "Use Shadow Catcher " << string_from_bool(features & KERNEL_FEATURE_SHADOW_CATCHER)
- << "\n";
-}
-
-bool Scene::load_kernels(Progress &progress, bool lock_scene)
-{
- thread_scoped_lock scene_lock;
- if (lock_scene) {
- scene_lock = thread_scoped_lock(mutex);
- }
-
- const uint kernel_features = dscene.data.kernel_features;
-
- if (!kernels_loaded || loaded_kernel_features != kernel_features) {
- progress.set_status("Loading render kernels (may take a few minutes the first time)");
-
- scoped_timer timer;
-
- log_kernel_features(kernel_features);
- if (!device->load_kernels(kernel_features)) {
- string message = device->error_message();
- if (message.empty())
- message = "Failed loading render kernel, see console for errors";
-
- progress.set_error(message);
- progress.set_status(message);
- progress.set_update();
- return false;
- }
-
- kernels_loaded = true;
- loaded_kernel_features = kernel_features;
- return true;
- }
- return false;
-}
-
-int Scene::get_max_closure_count()
-{
- if (shader_manager->use_osl()) {
- /* OSL always needs the maximum as we can't predict the
- * number of closures a shader might generate. */
- return MAX_CLOSURE;
- }
-
- int max_closures = 0;
- for (int i = 0; i < shaders.size(); i++) {
- Shader *shader = shaders[i];
- if (shader->reference_count()) {
- int num_closures = shader->graph->get_num_closures();
- max_closures = max(max_closures, num_closures);
- }
- }
- max_closure_global = max(max_closure_global, max_closures);
-
- if (max_closure_global > MAX_CLOSURE) {
- /* This is usually harmless as more complex shader tend to get many
- * closures discarded due to mixing or low weights. We need to limit
- * to MAX_CLOSURE as this is hardcoded in CPU/mega kernels, and it
- * avoids excessive memory usage for split kernels. */
- VLOG(2) << "Maximum number of closures exceeded: " << max_closure_global << " > "
- << MAX_CLOSURE;
-
- max_closure_global = MAX_CLOSURE;
- }
-
- return max_closure_global;
-}
-
-int Scene::get_volume_stack_size() const
-{
- int volume_stack_size = 0;
-
- /* Space for background volume and terminator.
- * Don't do optional here because camera ray initialization expects that there is space for
- * at least those elements (avoiding extra condition to check if there is actual volume or not).
- */
- volume_stack_size += 2;
-
- /* Quick non-expensive check. Can over-estimate maximum possible nested level, but does not
- * require expensive calculation during pre-processing. */
- for (const Object *object : objects) {
- if (object->check_is_volume()) {
- ++volume_stack_size;
- }
-
- if (volume_stack_size == MAX_VOLUME_STACK_SIZE) {
- break;
- }
- }
-
- volume_stack_size = min(volume_stack_size, MAX_VOLUME_STACK_SIZE);
-
- return volume_stack_size;
-}
-
-bool Scene::has_shadow_catcher()
-{
- if (shadow_catcher_modified_) {
- has_shadow_catcher_ = false;
- for (Object *object : objects) {
- if (object->get_is_shadow_catcher()) {
- has_shadow_catcher_ = true;
- break;
- }
- }
-
- shadow_catcher_modified_ = false;
- }
-
- return has_shadow_catcher_;
-}
-
-void Scene::tag_shadow_catcher_modified()
-{
- shadow_catcher_modified_ = true;
-}
-
-template<> Light *Scene::create_node<Light>()
-{
- Light *node = new Light();
- node->set_owner(this);
- lights.push_back(node);
- light_manager->tag_update(this, LightManager::LIGHT_ADDED);
- 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, GeometryManager::MESH_ADDED);
- 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, GeometryManager::HAIR_ADDED);
- 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, GeometryManager::MESH_ADDED);
- 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, ObjectManager::OBJECT_ADDED);
- 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->tag_update(this, ShaderManager::SHADER_ADDED);
- return node;
-}
-
-template<> AlembicProcedural *Scene::create_node<AlembicProcedural>()
-{
-#ifdef WITH_ALEMBIC
- AlembicProcedural *node = new AlembicProcedural();
- node->set_owner(this);
- procedurals.push_back(node);
- procedural_manager->tag_update();
- return node;
-#else
- return nullptr;
-#endif
-}
-
-template<> Pass *Scene::create_node<Pass>()
-{
- Pass *node = new Pass();
- node->set_owner(this);
- passes.push_back(node);
- film->tag_modified();
- 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, LightManager::LIGHT_REMOVED);
-}
-
-template<> void Scene::delete_node_impl(Mesh *node)
-{
- delete_node_from_array(geometry, static_cast<Geometry *>(node));
- geometry_manager->tag_update(this, GeometryManager::MESH_REMOVED);
-}
-
-template<> void Scene::delete_node_impl(Hair *node)
-{
- delete_node_from_array(geometry, static_cast<Geometry *>(node));
- geometry_manager->tag_update(this, GeometryManager::HAIR_REMOVED);
-}
-
-template<> void Scene::delete_node_impl(Volume *node)
-{
- delete_node_from_array(geometry, static_cast<Geometry *>(node));
- geometry_manager->tag_update(this, GeometryManager::MESH_REMOVED);
-}
-
-template<> void Scene::delete_node_impl(Geometry *node)
-{
- uint flag;
- if (node->is_hair()) {
- flag = GeometryManager::HAIR_REMOVED;
- }
- else {
- flag = GeometryManager::MESH_REMOVED;
- }
-
- delete_node_from_array(geometry, node);
- geometry_manager->tag_update(this, flag);
-}
-
-template<> void Scene::delete_node_impl(Object *node)
-{
- delete_node_from_array(objects, node);
- object_manager->tag_update(this, ObjectManager::OBJECT_REMOVED);
-}
-
-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 *shader)
-{
- /* don't delete unused shaders, not supported */
- shader->clear_reference_count();
-}
-
-template<> void Scene::delete_node_impl(Procedural *node)
-{
- delete_node_from_array(procedurals, node);
- procedural_manager->tag_update();
-}
-
-template<> void Scene::delete_node_impl(AlembicProcedural *node)
-{
-#ifdef WITH_ALEMBIC
- delete_node_impl(static_cast<Procedural *>(node));
-#else
- (void)node;
-#endif
-}
-
-template<> void Scene::delete_node_impl(Pass *node)
-{
- delete_node_from_array(passes, 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)
-{
- 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);
- (void)owner;
-}
-
-template<> void Scene::delete_nodes(const set<Light *> &nodes, const NodeOwner *owner)
-{
- remove_nodes_in_set(nodes, lights, owner);
- 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);
- 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);
- 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);
- particle_system_manager->tag_update(this);
-}
-
-template<> void Scene::delete_nodes(const set<Shader *> &nodes, const NodeOwner * /*owner*/)
-{
- /* don't delete unused shaders, not supported */
- for (Shader *shader : nodes) {
- shader->clear_reference_count();
- }
-}
-
-template<> void Scene::delete_nodes(const set<Procedural *> &nodes, const NodeOwner *owner)
-{
- remove_nodes_in_set(nodes, procedurals, owner);
- procedural_manager->tag_update();
-}
-
-template<> void Scene::delete_nodes(const set<Pass *> &nodes, const NodeOwner *owner)
-{
- remove_nodes_in_set(nodes, passes, owner);
- film->tag_modified();
-}
-
-CCL_NAMESPACE_END