diff options
Diffstat (limited to 'intern/cycles/scene/particles.cpp')
-rw-r--r-- | intern/cycles/scene/particles.cpp | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/intern/cycles/scene/particles.cpp b/intern/cycles/scene/particles.cpp new file mode 100644 index 00000000000..92381171082 --- /dev/null +++ b/intern/cycles/scene/particles.cpp @@ -0,0 +1,149 @@ +/* + * 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 "scene/particles.h" +#include "device/device.h" +#include "scene/scene.h" +#include "scene/stats.h" + +#include "util/foreach.h" +#include "util/hash.h" +#include "util/log.h" +#include "util/map.h" +#include "util/progress.h" +#include "util/vector.h" + +CCL_NAMESPACE_BEGIN + +/* Particle System */ + +NODE_DEFINE(ParticleSystem) +{ + NodeType *type = NodeType::add("particle_system", create); + return type; +} + +ParticleSystem::ParticleSystem() : Node(get_node_type()) +{ +} + +ParticleSystem::~ParticleSystem() +{ +} + +void ParticleSystem::tag_update(Scene *scene) +{ + scene->particle_system_manager->tag_update(scene); +} + +/* Particle System Manager */ + +ParticleSystemManager::ParticleSystemManager() +{ + need_update_ = true; +} + +ParticleSystemManager::~ParticleSystemManager() +{ +} + +void ParticleSystemManager::device_update_particles(Device *, + DeviceScene *dscene, + Scene *scene, + Progress &progress) +{ + /* count particles. + * adds one dummy particle at the beginning to avoid invalid lookups, + * in case a shader uses particle info without actual particle data. */ + int num_particles = 1; + for (size_t j = 0; j < scene->particle_systems.size(); j++) + num_particles += scene->particle_systems[j]->particles.size(); + + KernelParticle *kparticles = dscene->particles.alloc(num_particles); + + /* dummy particle */ + memset(kparticles, 0, sizeof(KernelParticle)); + + int i = 1; + for (size_t j = 0; j < scene->particle_systems.size(); j++) { + ParticleSystem *psys = scene->particle_systems[j]; + + for (size_t k = 0; k < psys->particles.size(); k++) { + /* pack in texture */ + Particle &pa = psys->particles[k]; + + kparticles[i].index = pa.index; + kparticles[i].age = pa.age; + kparticles[i].lifetime = pa.lifetime; + kparticles[i].size = pa.size; + kparticles[i].rotation = pa.rotation; + kparticles[i].location = float3_to_float4(pa.location); + kparticles[i].velocity = float3_to_float4(pa.velocity); + kparticles[i].angular_velocity = float3_to_float4(pa.angular_velocity); + + i++; + + if (progress.get_cancel()) + return; + } + } + + dscene->particles.copy_to_device(); +} + +void ParticleSystemManager::device_update(Device *device, + DeviceScene *dscene, + Scene *scene, + Progress &progress) +{ + if (!need_update()) + return; + + scoped_callback_timer timer([scene](double time) { + if (scene->update_stats) { + scene->update_stats->particles.times.add_entry({"device_update", time}); + } + }); + + VLOG(1) << "Total " << scene->particle_systems.size() << " particle systems."; + + device_free(device, dscene); + + progress.set_status("Updating Particle Systems", "Copying Particles to device"); + device_update_particles(device, dscene, scene, progress); + + if (progress.get_cancel()) + return; + + need_update_ = false; +} + +void ParticleSystemManager::device_free(Device *, DeviceScene *dscene) +{ + dscene->particles.free(); +} + +void ParticleSystemManager::tag_update(Scene * /*scene*/) +{ + need_update_ = true; +} + +bool ParticleSystemManager::need_update() const +{ + return need_update_; +} + +CCL_NAMESPACE_END |