Merging r47612 through r47623 from trunk into soc-2011-tomato
[blender.git] / intern / cycles / blender / blender_particles.cpp
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18
19 #include "object.h"
20
21 #include "mesh.h"
22 #include "blender_sync.h"
23 #include "blender_util.h"
24
25 #include "util_foreach.h"
26
27 CCL_NAMESPACE_BEGIN
28
29 /* Utilities */
30
31
32 /* Particles Sync */
33
34 bool BlenderSync::object_use_particles(BL::Object b_ob)
35 {
36         /* Particle data is only needed for
37          * a) Billboard render mode if object's own material uses particle info
38          * b) object/group render mode if any dupli object's material uses particle info
39          *
40          * Note: Meshes have to be synced at this point!
41          */
42         bool use_particles = false;
43         
44         BL::Object::particle_systems_iterator b_psys;
45         for (b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) {
46                 switch (b_psys->settings().render_type()) {
47                 /* XXX not implemented yet! 
48                  * billboards/strands would become part of the mesh data (?),
49                  * so the mesh attributes would store whether particle info is required.
50                  */
51                 #if 0
52                 case BL::ParticleSettings::render_type_BILLBOARD:
53                 case BL::ParticleSettings::render_type_PATH: {  /* for strand rendering */
54                         BL::ID key = (BKE_object_is_modified(b_ob))? b_ob: b_ob.data();
55                         Mesh *mesh = mesh_map.find(key);
56                         if (mesh) {
57                                 use_particles |= mesh->need_attribute(scene, ATTR_STD_PARTICLE);
58                         }
59                         break;
60                 }
61                 #endif
62                 
63                 case BL::ParticleSettings::render_type_OBJECT: {
64                         BL::Object b_dupli_ob = b_psys->settings().dupli_object();
65                         if (b_dupli_ob) {
66                                 BL::ID key = (BKE_object_is_modified(b_dupli_ob))? b_dupli_ob: b_dupli_ob.data();
67                                 Mesh *mesh = mesh_map.find(key);
68                                 if (mesh) {
69                                         use_particles |= mesh->need_attribute(scene, ATTR_STD_PARTICLE);
70                                 }
71                         }
72                         break;
73                 }
74                 
75                 case BL::ParticleSettings::render_type_GROUP: {
76                         BL::Group b_dupli_group = b_psys->settings().dupli_group();
77                         if (b_dupli_group) {
78                                 BL::Group::objects_iterator b_gob;
79                                 for (b_dupli_group.objects.begin(b_gob); b_gob != b_dupli_group.objects.end(); ++b_gob) {
80                                         BL::ID key = (BKE_object_is_modified(*b_gob))? *b_gob: b_gob->data();
81                                         Mesh *mesh = mesh_map.find(key);
82                                         if (mesh) {
83                                                 use_particles |= mesh->need_attribute(scene, ATTR_STD_PARTICLE);
84                                         }
85                                 }
86                         }
87                         break;
88                 }
89                 
90                 default:
91                         /* avoid compiler warning */
92                         break;
93                 }
94         }
95         
96         return use_particles;
97 }
98
99 static bool use_particle_system(BL::ParticleSystem b_psys)
100 {
101         /* only use duplicator particles? disabled particle info for
102          * halo and billboard to reduce particle count.
103          * Probably not necessary since particles don't contain a huge amount
104          * of data compared to other textures.
105          */
106         #if 0
107         int render_type = b_psys->settings().render_type();
108         return (render_type == BL::ParticleSettings::render_type_OBJECT
109                 || render_type == BL::ParticleSettings::render_type_GROUP);
110         #endif
111         
112         return true;
113 }
114
115 static bool use_particle(BL::Particle b_pa)
116 {
117         return b_pa.is_exist() && b_pa.is_visible() && b_pa.alive_state()==BL::Particle::alive_state_ALIVE;
118 }
119
120 int BlenderSync::object_count_particles(BL::Object b_ob)
121 {
122         int tot = 0;
123         BL::Object::particle_systems_iterator b_psys;
124         for(b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) {
125                 if (use_particle_system(*b_psys)) {
126                         BL::ParticleSystem::particles_iterator b_pa;
127                         for(b_psys->particles.begin(b_pa); b_pa != b_psys->particles.end(); ++b_pa) {
128                                 if(use_particle(*b_pa))
129                                         ++tot;
130                         }
131                 }
132         }
133         return tot;
134 }
135
136 void BlenderSync::sync_particles(Object *ob, BL::Object b_ob)
137 {
138         int tot = object_count_particles(b_ob);
139         
140         ob->particles.clear();
141         ob->particles.reserve(tot);
142         
143         int index;
144         BL::Object::particle_systems_iterator b_psys;
145         for(b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) {
146                 if (use_particle_system(*b_psys)) {
147                         BL::ParticleSystem::particles_iterator b_pa;
148                         for(b_psys->particles.begin(b_pa), index=0; b_pa != b_psys->particles.end(); ++b_pa, ++index) {
149                                 if(use_particle(*b_pa)) {
150                                         Particle pa;
151                                         
152                                         pa.age = b_scene.frame_current() - b_pa->birth_time();
153                                         pa.lifetime = b_pa->lifetime();
154                                         
155                                         ob->particles.push_back(pa);
156                                 }
157                         }
158                 }
159         }
160 }
161
162 CCL_NAMESPACE_END