[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [47616] trunk/blender: Particle Info node for Cycles.

Lukas Toenne lukas.toenne at googlemail.com
Fri Jun 8 18:17:58 CEST 2012


Revision: 47616
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=47616
Author:   lukastoenne
Date:     2012-06-08 16:17:57 +0000 (Fri, 08 Jun 2012)
Log Message:
-----------
Particle Info node for Cycles. This can be used to access particle information in material shaders for dupli objects. For now only the particle Age and individual Lifetime (in frames) are supported, more attributes can be added when needed.

The particle data is stored in a separate texture if any of the dupli objects uses particle info nodes in shaders. To map dupli objects onto particles the store an additional particle_index value, which is different from the simple dupli object index (only visible particles, also works for particle dupli groups mode).

Some simple use cases on the code.blender.org blog:
http://code.blender.org/index.php/2012/05/particle-info-node/

Modified Paths:
--------------
    trunk/blender/intern/cycles/blender/CMakeLists.txt
    trunk/blender/intern/cycles/blender/blender_object.cpp
    trunk/blender/intern/cycles/blender/blender_shader.cpp
    trunk/blender/intern/cycles/blender/blender_sync.h
    trunk/blender/intern/cycles/kernel/kernel_object.h
    trunk/blender/intern/cycles/kernel/kernel_textures.h
    trunk/blender/intern/cycles/kernel/kernel_types.h
    trunk/blender/intern/cycles/kernel/svm/svm.h
    trunk/blender/intern/cycles/kernel/svm/svm_geometry.h
    trunk/blender/intern/cycles/kernel/svm/svm_types.h
    trunk/blender/intern/cycles/render/nodes.cpp
    trunk/blender/intern/cycles/render/nodes.h
    trunk/blender/intern/cycles/render/object.cpp
    trunk/blender/intern/cycles/render/object.h
    trunk/blender/intern/cycles/render/scene.h
    trunk/blender/source/blender/blenkernel/BKE_node.h
    trunk/blender/source/blender/blenkernel/intern/anim.c
    trunk/blender/source/blender/blenkernel/intern/node.c
    trunk/blender/source/blender/makesdna/DNA_object_types.h
    trunk/blender/source/blender/makesrna/intern/rna_nodetree_types.h
    trunk/blender/source/blender/makesrna/intern/rna_object.c
    trunk/blender/source/blender/nodes/CMakeLists.txt
    trunk/blender/source/blender/nodes/NOD_shader.h

Added Paths:
-----------
    trunk/blender/intern/cycles/blender/blender_particles.cpp
    trunk/blender/source/blender/nodes/shader/nodes/node_shader_particle_info.c

Modified: trunk/blender/intern/cycles/blender/CMakeLists.txt
===================================================================
--- trunk/blender/intern/cycles/blender/CMakeLists.txt	2012-06-08 16:13:01 UTC (rev 47615)
+++ trunk/blender/intern/cycles/blender/CMakeLists.txt	2012-06-08 16:17:57 UTC (rev 47616)
@@ -22,6 +22,7 @@
 	blender_camera.cpp
 	blender_mesh.cpp
 	blender_object.cpp
+	blender_particles.cpp
 	blender_python.cpp
 	blender_session.cpp
 	blender_shader.cpp

Modified: trunk/blender/intern/cycles/blender/blender_object.cpp
===================================================================
--- trunk/blender/intern/cycles/blender/blender_object.cpp	2012-06-08 16:13:01 UTC (rev 47615)
+++ trunk/blender/intern/cycles/blender/blender_object.cpp	2012-06-08 16:17:57 UTC (rev 47616)
@@ -192,7 +192,7 @@
 
 /* Object */
 
-void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm, uint layer_flag, int motion)
+void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm, uint layer_flag, int motion, int particle_id)
 {
 	/* light is handled separately */
 	if(object_is_light(b_ob)) {
@@ -270,6 +270,12 @@
 			object->visibility &= ~PATH_RAY_CAMERA;
 		}
 
+		object->particle_id = particle_id;
+
+		/* particle sync */
+		if (object_use_particles(b_ob))
+			sync_particles(object, b_ob);
+	
 		object->tag_update(scene);
 	}
 }
@@ -292,54 +298,51 @@
 	/* object loop */
 	BL::Scene::objects_iterator b_ob;
 	BL::Scene b_sce = b_scene;
+	int particle_offset = 0;
 
 	for(; b_sce; b_sce = b_sce.background_set()) {
 		for(b_sce.objects.begin(b_ob); b_ob != b_sce.objects.end(); ++b_ob) {
 			bool hide = (render_layer.use_viewport_visibility)? b_ob->hide(): b_ob->hide_render();
 			uint ob_layer = get_layer(b_ob->layers());
+			hide = hide || !(ob_layer & scene_layer);
 
-			if(!hide && (ob_layer & scene_layer)) {
+			if(!hide) {
+
+				int num_particles = object_count_particles(*b_ob);
+
 				if(b_ob->is_duplicator()) {
+					hide = true;	/* duplicators hidden by default */
+
 					/* dupli objects */
 					object_create_duplilist(*b_ob, b_scene);
 
 					BL::Object::dupli_list_iterator b_dup;
-					int b_index = 0;
-
 					for(b_ob->dupli_list.begin(b_dup); b_dup != b_ob->dupli_list.end(); ++b_dup) {
 						Transform tfm = get_transform(b_dup->matrix());
 						BL::Object b_dup_ob = b_dup->object();
 						bool dup_hide = (b_v3d)? b_dup_ob.hide(): b_dup_ob.hide_render();
 
-						if(!(b_dup->hide() || dup_hide))
-							sync_object(*b_ob, b_index, b_dup_ob, tfm, ob_layer, motion);
-
-						b_index++;
+						if(!(b_dup->hide() || dup_hide)) {
+							sync_object(*b_ob, b_dup->index(), b_dup_ob, tfm, ob_layer, motion, b_dup->particle_index() + particle_offset);
+						}
 					}
 
 					object_free_duplilist(*b_ob);
-
-					hide = true;
 				}
 
 				/* check if we should render or hide particle emitter */
 				BL::Object::particle_systems_iterator b_psys;
-				bool render_emitter = false;
-
-				for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) {
-					if(b_psys->settings().use_render_emitter()) {
+				for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys)
+					if(b_psys->settings().use_render_emitter())
 						hide = false;
-						render_emitter = true;
-					}
-					else if(!render_emitter)
-						hide = true;
-				}
 
 				if(!hide) {
 					/* object itself */
 					Transform tfm = get_transform(b_ob->matrix_world());
-					sync_object(*b_ob, 0, *b_ob, tfm, ob_layer, motion);
+					sync_object(*b_ob, 0, *b_ob, tfm, ob_layer, motion, 0);
 				}
+
+				particle_offset += num_particles;
 			}
 		}
 	}

Added: trunk/blender/intern/cycles/blender/blender_particles.cpp
===================================================================
--- trunk/blender/intern/cycles/blender/blender_particles.cpp	                        (rev 0)
+++ trunk/blender/intern/cycles/blender/blender_particles.cpp	2012-06-08 16:17:57 UTC (rev 47616)
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "object.h"
+
+#include "mesh.h"
+#include "blender_sync.h"
+#include "blender_util.h"
+
+#include "util_foreach.h"
+
+CCL_NAMESPACE_BEGIN
+
+/* Utilities */
+
+
+/* Particles Sync */
+
+bool BlenderSync::object_use_particles(BL::Object b_ob)
+{
+	/* Particle data is only needed for
+	 * a) Billboard render mode if object's own material uses particle info
+	 * b) object/group render mode if any dupli object's material uses particle info
+	 *
+	 * Note: Meshes have to be synced at this point!
+	 */
+	bool use_particles = false;
+	
+	BL::Object::particle_systems_iterator b_psys;
+	for (b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) {
+		switch (b_psys->settings().render_type()) {
+		/* XXX not implemented yet! 
+		 * billboards/strands would become part of the mesh data (?),
+		 * so the mesh attributes would store whether particle info is required.
+		 */
+		#if 0
+		case BL::ParticleSettings::render_type_BILLBOARD:
+		case BL::ParticleSettings::render_type_PATH: {	/* for strand rendering */
+			BL::ID key = (BKE_object_is_modified(b_ob))? b_ob: b_ob.data();
+			Mesh *mesh = mesh_map.find(key);
+			if (mesh) {
+				use_particles |= mesh->need_attribute(scene, ATTR_STD_PARTICLE);
+			}
+			break;
+		}
+		#endif
+		
+		case BL::ParticleSettings::render_type_OBJECT: {
+			BL::Object b_dupli_ob = b_psys->settings().dupli_object();
+			if (b_dupli_ob) {
+				BL::ID key = (BKE_object_is_modified(b_dupli_ob))? b_dupli_ob: b_dupli_ob.data();
+				Mesh *mesh = mesh_map.find(key);
+				if (mesh) {
+					use_particles |= mesh->need_attribute(scene, ATTR_STD_PARTICLE);
+				}
+			}
+			break;
+		}
+		
+		case BL::ParticleSettings::render_type_GROUP: {
+			BL::Group b_dupli_group = b_psys->settings().dupli_group();
+			if (b_dupli_group) {
+				BL::Group::objects_iterator b_gob;
+				for (b_dupli_group.objects.begin(b_gob); b_gob != b_dupli_group.objects.end(); ++b_gob) {
+					BL::ID key = (BKE_object_is_modified(*b_gob))? *b_gob: b_gob->data();
+					Mesh *mesh = mesh_map.find(key);
+					if (mesh) {
+						use_particles |= mesh->need_attribute(scene, ATTR_STD_PARTICLE);
+					}
+				}
+			}
+			break;
+		}
+		}
+	}
+	
+	return use_particles;
+}
+
+static bool use_particle_system(BL::ParticleSystem b_psys)
+{
+	/* only use duplicator particles? disabled particle info for
+	 * halo and billboard to reduce particle count.
+	 * Probably not necessary since particles don't contain a huge amount
+	 * of data compared to other textures.
+	 */
+	#if 0
+	int render_type = b_psys->settings().render_type();
+	return (render_type == BL::ParticleSettings::render_type_OBJECT
+	        || render_type == BL::ParticleSettings::render_type_GROUP);
+	#endif
+	
+	return true;
+}
+
+static bool use_particle(BL::Particle b_pa)
+{
+	return b_pa.is_exist() && b_pa.is_visible() && b_pa.alive_state()==BL::Particle::alive_state_ALIVE;
+}
+
+int BlenderSync::object_count_particles(BL::Object b_ob)
+{
+	int tot = 0;
+	BL::Object::particle_systems_iterator b_psys;
+	for(b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) {
+		if (use_particle_system(*b_psys)) {
+			BL::ParticleSystem::particles_iterator b_pa;
+			for(b_psys->particles.begin(b_pa); b_pa != b_psys->particles.end(); ++b_pa) {
+				if(use_particle(*b_pa))
+					++tot;
+			}
+		}
+	}
+	return tot;
+}
+
+void BlenderSync::sync_particles(Object *ob, BL::Object b_ob)
+{
+	int tot = object_count_particles(b_ob);
+	
+	ob->particles.clear();
+	ob->particles.reserve(tot);
+	
+	int index;
+	BL::Object::particle_systems_iterator b_psys;
+	for(b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) {
+		if (use_particle_system(*b_psys)) {
+			BL::ParticleSystem::particles_iterator b_pa;
+			for(b_psys->particles.begin(b_pa), index=0; b_pa != b_psys->particles.end(); ++b_pa, ++index) {
+				if(use_particle(*b_pa)) {
+					Particle pa;
+					
+					pa.age = b_scene.frame_current() - b_pa->birth_time();
+					pa.lifetime = b_pa->lifetime();
+					
+					ob->particles.push_back(pa);
+				}
+			}
+		}
+	}
+}
+
+CCL_NAMESPACE_END

Modified: trunk/blender/intern/cycles/blender/blender_shader.cpp
===================================================================
--- trunk/blender/intern/cycles/blender/blender_shader.cpp	2012-06-08 16:13:01 UTC (rev 47615)
+++ trunk/blender/intern/cycles/blender/blender_shader.cpp	2012-06-08 16:17:57 UTC (rev 47616)
@@ -337,6 +337,10 @@
 			node = new ObjectInfoNode();
 			break;
 		}
+		case BL::ShaderNode::type_PARTICLE_INFO: {
+			node = new ParticleInfoNode();
+			break;
+		}
 		case BL::ShaderNode::type_TEX_IMAGE: {
 			BL::ShaderNodeTexImage b_image_node(b_node);
 			BL::Image b_image(b_image_node.image());

Modified: trunk/blender/intern/cycles/blender/blender_sync.h
===================================================================
--- trunk/blender/intern/cycles/blender/blender_sync.h	2012-06-08 16:13:01 UTC (rev 47615)
+++ trunk/blender/intern/cycles/blender/blender_sync.h	2012-06-08 16:17:57 UTC (rev 47616)
@@ -80,17 +80,20 @@
 
 	void sync_nodes(Shader *shader, BL::ShaderNodeTree b_ntree);
 	Mesh *sync_mesh(BL::Object b_ob, bool object_updated);
-	void sync_object(BL::Object b_parent, int b_index, BL::Object b_object, Transform& tfm, uint layer_flag, int motion);
+	void sync_object(BL::Object b_parent, int b_index, BL::Object b_object, Transform& tfm, uint layer_flag, int motion, int particle_id);
 	void sync_light(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm);
 	void sync_background_light();
 	void sync_mesh_motion(BL::Object b_ob, Mesh *mesh, int motion);
 	void sync_camera_motion(BL::Object b_ob, int motion);

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list