a84ca51f2749cfd4a84983f09ca9c93999b21ace
[blender-staging.git] / intern / cycles / render / particles.cpp
1 /*
2  * Copyright 2011-2013 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "device/device.h"
18 #include "render/particles.h"
19 #include "render/scene.h"
20
21 #include "util/util_foreach.h"
22 #include "util/util_logging.h"
23 #include "util/util_map.h"
24 #include "util/util_progress.h"
25 #include "util/util_vector.h"
26
27 CCL_NAMESPACE_BEGIN
28
29 /* Particle System */
30
31 ParticleSystem::ParticleSystem()
32 {
33 }
34
35 ParticleSystem::~ParticleSystem()
36 {
37 }
38
39 void ParticleSystem::tag_update(Scene *scene)
40 {
41         scene->particle_system_manager->need_update = true;
42 }
43
44 /* Particle System Manager */
45
46 ParticleSystemManager::ParticleSystemManager()
47 {
48         need_update = true;
49 }
50
51 ParticleSystemManager::~ParticleSystemManager()
52 {
53 }
54
55 void ParticleSystemManager::device_update_particles(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
56 {
57         /* count particles.
58          * adds one dummy particle at the beginning to avoid invalid lookups,
59          * in case a shader uses particle info without actual particle data. */
60         int num_particles = 1;
61         for(size_t j = 0; j < scene->particle_systems.size(); j++)
62                 num_particles += scene->particle_systems[j]->particles.size();
63         
64         float4 *particles = dscene->particles.resize(PARTICLE_SIZE*num_particles);
65         
66         /* dummy particle */
67         particles[0] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
68         particles[1] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
69         particles[2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
70         particles[3] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
71         particles[4] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
72         
73         int i = 1;
74         for(size_t j = 0; j < scene->particle_systems.size(); j++) {
75                 ParticleSystem *psys = scene->particle_systems[j];
76
77                 for(size_t k = 0; k < psys->particles.size(); k++) {
78                         /* pack in texture */
79                         Particle& pa = psys->particles[k];
80                         int offset = i*PARTICLE_SIZE;
81                         
82                         particles[offset] = make_float4(pa.index, pa.age, pa.lifetime, pa.size);
83                         particles[offset+1] = pa.rotation;
84                         particles[offset+2] = make_float4(pa.location.x, pa.location.y, pa.location.z, pa.velocity.x);
85                         particles[offset+3] = make_float4(pa.velocity.y, pa.velocity.z, pa.angular_velocity.x, pa.angular_velocity.y);
86                         particles[offset+4] = make_float4(pa.angular_velocity.z, 0.0f, 0.0f, 0.0f);
87                         
88                         i++;
89                         
90                         if(progress.get_cancel()) return;
91                 }
92         }
93         
94         device->tex_alloc(dscene->particles);
95 }
96
97 void ParticleSystemManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
98 {
99         if(!need_update)
100                 return;
101
102         VLOG(1) << "Total " << scene->particle_systems.size()
103                 << " particle systems.";
104
105         device_free(device, dscene);
106
107         progress.set_status("Updating Particle Systems", "Copying Particles to device");
108         device_update_particles(device, dscene, scene, progress);
109         
110         if(progress.get_cancel()) return;
111         
112         need_update = false;
113 }
114
115 void ParticleSystemManager::device_free(Device *device, DeviceScene *dscene)
116 {
117         device->tex_free(dscene->particles);
118         dscene->particles.clear();
119 }
120
121 void ParticleSystemManager::tag_update(Scene * /*scene*/)
122 {
123         need_update = true;
124 }
125
126 CCL_NAMESPACE_END
127