Particle Info node for Cycles. This can be used to access particle information in...
[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         }
91         
92         return use_particles;
93 }
94
95 static bool use_particle_system(BL::ParticleSystem b_psys)
96 {
97         /* only use duplicator particles? disabled particle info for
98          * halo and billboard to reduce particle count.
99          * Probably not necessary since particles don't contain a huge amount
100          * of data compared to other textures.
101          */
102         #if 0
103         int render_type = b_psys->settings().render_type();
104         return (render_type == BL::ParticleSettings::render_type_OBJECT
105                 || render_type == BL::ParticleSettings::render_type_GROUP);
106         #endif
107         
108         return true;
109 }
110
111 static bool use_particle(BL::Particle b_pa)
112 {
113         return b_pa.is_exist() && b_pa.is_visible() && b_pa.alive_state()==BL::Particle::alive_state_ALIVE;
114 }
115
116 int BlenderSync::object_count_particles(BL::Object b_ob)
117 {
118         int tot = 0;
119         BL::Object::particle_systems_iterator b_psys;
120         for(b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) {
121                 if (use_particle_system(*b_psys)) {
122                         BL::ParticleSystem::particles_iterator b_pa;
123                         for(b_psys->particles.begin(b_pa); b_pa != b_psys->particles.end(); ++b_pa) {
124                                 if(use_particle(*b_pa))
125                                         ++tot;
126                         }
127                 }
128         }
129         return tot;
130 }
131
132 void BlenderSync::sync_particles(Object *ob, BL::Object b_ob)
133 {
134         int tot = object_count_particles(b_ob);
135         
136         ob->particles.clear();
137         ob->particles.reserve(tot);
138         
139         int index;
140         BL::Object::particle_systems_iterator b_psys;
141         for(b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) {
142                 if (use_particle_system(*b_psys)) {
143                         BL::ParticleSystem::particles_iterator b_pa;
144                         for(b_psys->particles.begin(b_pa), index=0; b_pa != b_psys->particles.end(); ++b_pa, ++index) {
145                                 if(use_particle(*b_pa)) {
146                                         Particle pa;
147                                         
148                                         pa.age = b_scene.frame_current() - b_pa->birth_time();
149                                         pa.lifetime = b_pa->lifetime();
150                                         
151                                         ob->particles.push_back(pa);
152                                 }
153                         }
154                 }
155         }
156 }
157
158 CCL_NAMESPACE_END