[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [41060] trunk/blender: Particle dupliobject rotation changes:

Janne Karhu jhkarh at gmail.com
Sun Oct 16 18:14:38 CEST 2011


Revision: 41060
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=41060
Author:   jhk
Date:     2011-10-16 16:14:36 +0000 (Sun, 16 Oct 2011)
Log Message:
-----------
Particle dupliobject rotation changes:
There has been quite a bit of fuss about particle dupliobject rotation in 2.59, so here are some changes to make things work a bit more consistently and predictably in 2.60.

Much of the confusion has been about what the "Initial rotation" for particles actually means. Simply put it's just a vector that that the particles (and the dupliobjects) are aligned to and around which they can be rotated with the phase controls. I've now renamed these controls under a label "Rotation axis".

In 2.59 and previous versions the dupliobject's global x-axis was aligned to the particle rotation axis for non-hair particles. This meant that the object's own rotation (in addition to the particle rotation) could effect the dupliobjects' rotations. This old behavior can still be used with the "Rotation" option in the particle render panel when object/group is set as the visualization. This option is also activated automatically for old files to maintain backwards compatibility.

Now the default dupliobject rotations ignore the object's own rotation completely and align the object's tracking axis to the particle rotation axis. The tracking axis can be found under the Object tab -> Animation Hacks panel.

In 2.58 the way of calculating the rotation for hair didn't work as intended and enabled many non-functional combinations of options. For this reason I removed most of the rotation options for hair in 2.59. Now the options have been reimplemented better and the dupliobject's tracking axis is aligned to the hair direction by default (Rotation axis = Velocity / Hair). All the other axis options work too along with the phase controls.

Modified Paths:
--------------
    trunk/blender/release/scripts/startup/bl_ui/properties_particle.py
    trunk/blender/source/blender/blenkernel/intern/anim.c
    trunk/blender/source/blender/blenkernel/intern/particle.c
    trunk/blender/source/blender/blenloader/intern/readfile.c
    trunk/blender/source/blender/makesdna/DNA_particle_types.h
    trunk/blender/source/blender/makesrna/intern/rna_particle.c

Modified: trunk/blender/release/scripts/startup/bl_ui/properties_particle.py
===================================================================
--- trunk/blender/release/scripts/startup/bl_ui/properties_particle.py	2011-10-16 15:45:45 UTC (rev 41059)
+++ trunk/blender/release/scripts/startup/bl_ui/properties_particle.py	2011-10-16 16:14:36 UTC (rev 41060)
@@ -404,10 +404,13 @@
             part = context.space_data.pin_id
 
         layout.enabled = particle_panel_enabled(context, psys)
+        
+        layout.prop(part, "use_dynamic_rotation")
 
-        row = layout.row()
-        row.label(text="Initial Rotation:")
-        row.prop(part, "use_dynamic_rotation")
+        if part.use_dynamic_rotation:
+            layout.label(text="Initial Rotation Axis:")
+        else:
+            layout.label(text="Rotation Axis:")
 
         split = layout.split()
 
@@ -419,14 +422,20 @@
         col.prop(part, "phase_factor", slider=True)
         col.prop(part, "phase_factor_random", text="Random", slider=True)
 
-        col = layout.column()
-        col.label(text="Angular Velocity:")
-        col.row().prop(part, "angular_velocity_mode", expand=True)
+        if part.type != 'HAIR':
+            col = layout.column()
+            if part.use_dynamic_rotation:
+                col.label(text="Initial Angular Velocity:")
+            else:
+                col.label(text="Angular Velocity:")
+            sub = col.row(align=True)
+            sub.prop(part, "angular_velocity_mode", text="")
+            subsub = sub.column()
+            subsub.active = part.angular_velocity_mode != 'NONE'
+            subsub.prop(part, "angular_velocity_factor", text="")
+            
 
-        if part.angular_velocity_mode != 'NONE':
-            col.prop(part, "angular_velocity_factor", text="")
 
-
 class PARTICLE_PT_physics(ParticleButtonsPanel, Panel):
     bl_label = "Physics"
     COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -832,7 +841,9 @@
 
         elif part.render_type == 'OBJECT':
             col.prop(part, "dupli_object")
-            col.prop(part, "use_global_dupli")
+            sub = col.row()
+            sub.prop(part, "use_global_dupli")
+            sub.prop(part, "use_rotation_dupli")
         elif part.render_type == 'GROUP':
             col.prop(part, "dupli_group")
             split = layout.split()
@@ -841,13 +852,14 @@
             col.prop(part, "use_whole_group")
             sub = col.column()
             sub.active = (part.use_whole_group is False)
+            sub.prop(part, "use_group_pick_random")
             sub.prop(part, "use_group_count")
 
             col = split.column()
             sub = col.column()
             sub.active = (part.use_whole_group is False)
             sub.prop(part, "use_global_dupli")
-            sub.prop(part, "use_group_pick_random")
+            sub.prop(part, "use_rotation_dupli")
 
             if part.use_group_count and not part.use_whole_group:
                 row = layout.row()

Modified: trunk/blender/source/blender/blenkernel/intern/anim.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/anim.c	2011-10-16 15:45:45 UTC (rev 41059)
+++ trunk/blender/source/blender/blenkernel/intern/anim.c	2011-10-16 16:14:36 UTC (rev 41060)
@@ -1430,6 +1430,16 @@
 
 				VECCOPY(vec, obmat[3]);
 				obmat[3][0] = obmat[3][1] = obmat[3][2] = 0.0f;
+
+				/* particle rotation uses x-axis as the aligned axis, so pre-rotate the object accordingly */
+				if((part->draw & PART_DRAW_ROTATE_OB) == 0) {
+					float xvec[3], q[4];
+					xvec[0] = -1.f;
+					xvec[1] = xvec[2] = 0;
+					vec_to_quat(q, xvec, ob->trackflag, ob->upflag);
+					quat_to_mat4(obmat, q);
+					obmat[3][3]= 1.0f;
+				}
 				
 				/* Normal particles and cached hair live in global space so we need to
 				 * remove the real emitter's transformation before 2nd order duplication.
@@ -1448,7 +1458,7 @@
 					copy_m4_m4(mat, tmat);
 
 				if(part->draw & PART_DRAW_GLOBAL_OB)
-					VECADD(mat[3], mat[3], vec);
+					add_v3_v3v3(mat[3], mat[3], vec);
 
 				dob= new_dupli_object(lb, ob, mat, ob->lay, counter, GS(id->name) == ID_GR ? OB_DUPLIGROUP : OB_DUPLIPARTS, animated);
 				copy_m4_m4(dob->omat, oldobmat);

Modified: trunk/blender/source/blender/blenkernel/intern/particle.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/particle.c	2011-10-16 15:45:45 UTC (rev 41059)
+++ trunk/blender/source/blender/blenkernel/intern/particle.c	2011-10-16 16:14:36 UTC (rev 41060)
@@ -4384,34 +4384,51 @@
 		psys_particle_on_emitter(psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,nor,0,0,0,0);
 	else
 		psys_particle_on_emitter(psmd,PART_FROM_FACE,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,loc,nor,0,0,0,0);
-		
-	copy_m3_m4(nmat, ob->imat);
-	transpose_m3(nmat);
-	mul_m3_v3(nmat, nor);
-	normalize_v3(nor);
 
-	/* make sure that we get a proper side vector */
-	if(fabs(dot_v3v3(nor,vec))>0.999999) {
-		if(fabs(dot_v3v3(nor,xvec))>0.999999) {
-			nor[0] = 0.0f;
-			nor[1] = 1.0f;
-			nor[2] = 0.0f;
+	if(psys->part->rotmode == PART_ROT_VEL) {
+		copy_m3_m4(nmat, ob->imat);
+		transpose_m3(nmat);
+		mul_m3_v3(nmat, nor);
+		normalize_v3(nor);
+
+		/* make sure that we get a proper side vector */
+		if(fabs(dot_v3v3(nor,vec))>0.999999) {
+			if(fabs(dot_v3v3(nor,xvec))>0.999999) {
+				nor[0] = 0.0f;
+				nor[1] = 1.0f;
+				nor[2] = 0.0f;
+			}
+			else {
+				nor[0] = 1.0f;
+				nor[1] = 0.0f;
+				nor[2] = 0.0f;
+			}
 		}
-		else {
-			nor[0] = 1.0f;
-			nor[1] = 0.0f;
-			nor[2] = 0.0f;
+		cross_v3_v3v3(side, nor, vec);
+		normalize_v3(side);
+
+		/* rotate side vector around vec */
+		if(psys->part->phasefac != 0) {
+			float q_phase[4];
+			float phasefac = psys->part->phasefac;
+			if(psys->part->randphasefac != 0.0f)
+				phasefac += psys->part->randphasefac * PSYS_FRAND((pa-psys->particles) + 20);
+			axis_angle_to_quat( q_phase, vec, phasefac*(float)M_PI);
+
+			mul_qt_v3(q_phase, side);
 		}
+
+		cross_v3_v3v3(nor, vec, side);
+
+		unit_m4(mat);
+		VECCOPY(mat[0], vec);
+		VECCOPY(mat[1], side);
+		VECCOPY(mat[2], nor);
 	}
-	cross_v3_v3v3(side, nor, vec);
-	normalize_v3(side);
-	cross_v3_v3v3(nor, vec, side);
+	else {
+		quat_to_mat4(mat, pa->state.rot);
+	}
 
-	unit_m4(mat);
-	VECCOPY(mat[0], vec);
-	VECCOPY(mat[1], side);
-	VECCOPY(mat[2], nor);
-
 	*scale= len;
 }
 

Modified: trunk/blender/source/blender/blenloader/intern/readfile.c
===================================================================
--- trunk/blender/source/blender/blenloader/intern/readfile.c	2011-10-16 15:45:45 UTC (rev 41059)
+++ trunk/blender/source/blender/blenloader/intern/readfile.c	2011-10-16 16:14:36 UTC (rev 41060)
@@ -12176,6 +12176,20 @@
 			for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next)
 				do_versions_nodetree_image_default_alpha_output(ntree);
 		}
+
+		{
+			/* support old particle dupliobject rotation settings */
+			ParticleSettings *part;
+
+			for (part=main->particle.first; part; part=part->id.next) {
+				if(ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) {
+					part->draw |= PART_DRAW_ROTATE_OB;
+
+					if(part->rotmode == 0)
+						part->rotmode = PART_ROT_VEL;
+				}
+			}
+		}
 	}
 
 	/* WATCH IT!!!: pointers from libdata have not been converted yet here! */

Modified: trunk/blender/source/blender/makesdna/DNA_particle_types.h
===================================================================
--- trunk/blender/source/blender/makesdna/DNA_particle_types.h	2011-10-16 15:45:45 UTC (rev 41059)
+++ trunk/blender/source/blender/makesdna/DNA_particle_types.h	2011-10-16 16:14:36 UTC (rev 41060)
@@ -386,7 +386,8 @@
 #define PART_DRAW_HEALTH	16
 #define PART_ABS_PATH_TIME  32
 #define PART_DRAW_COUNT_GR	64
-#define PART_DRAW_BB_LOCK	128
+#define PART_DRAW_BB_LOCK	128	/* used with billboards */
+#define PART_DRAW_ROTATE_OB 128 /* used with dupliobjects/groups */
 #define PART_DRAW_PARENT	256
 #define PART_DRAW_NUM		512
 #define PART_DRAW_RAND_GR	1024

Modified: trunk/blender/source/blender/makesrna/intern/rna_particle.c
===================================================================
--- trunk/blender/source/blender/makesrna/intern/rna_particle.c	2011-10-16 15:45:45 UTC (rev 41059)
+++ trunk/blender/source/blender/makesrna/intern/rna_particle.c	2011-10-16 16:14:36 UTC (rev 41060)
@@ -1478,7 +1478,7 @@
 	static EnumPropertyItem rot_mode_items[] = {
 		{0, "NONE", 0, "None", ""},
 		{PART_ROT_NOR, "NOR", 0, "Normal", ""},
-		{PART_ROT_VEL, "VEL", 0, "Velocity", ""},
+		{PART_ROT_VEL, "VEL", 0, "Velocity / Hair", ""},
 		{PART_ROT_GLOB_X, "GLOB_X", 0, "Global X", ""},
 		{PART_ROT_GLOB_Y, "GLOB_Y", 0, "Global Y", ""},
 		{PART_ROT_GLOB_Z, "GLOB_Z", 0, "Global Z", ""},
@@ -1733,7 +1733,7 @@
 	RNA_def_property_enum_sdna(prop, NULL, "rotmode");
 	RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
 	RNA_def_property_enum_items(prop, rot_mode_items);
-	RNA_def_property_ui_text(prop, "Rotation", "Particles initial rotation");
+	RNA_def_property_ui_text(prop, "Rotation", "Particle rotation axis");
 	RNA_def_property_update(prop, 0, "rna_Particle_reset");
 
 	prop= RNA_def_property(srna, "angular_velocity_mode", PROP_ENUM, PROP_NONE);
@@ -1798,9 +1798,14 @@
 
 	prop= RNA_def_property(srna, "use_global_dupli", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_GLOBAL_OB);
-	RNA_def_property_ui_text(prop, "Use Global", "Use object's global coordinates for duplication");
+	RNA_def_property_ui_text(prop, "Global", "Use object's global coordinates for duplication");
 	RNA_def_property_update(prop, 0, "rna_Particle_redo");
 
+	prop= RNA_def_property(srna, "use_rotation_dupli", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_ROTATE_OB);
+	RNA_def_property_ui_text(prop, "Rotation", "Use object's rotation for duplication (global x-axis is aligned particle rotation axis)");
+	RNA_def_property_update(prop, 0, "rna_Particle_redo");
+
 	prop= RNA_def_property(srna, "use_render_adaptive", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_REN_ADAPT);
 	RNA_def_property_ui_text(prop, "Adaptive render", "Draw steps of the particle path");



More information about the Bf-blender-cvs mailing list