[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [34152] trunk/blender: New hair child options:

Janne Karhu jhkarh at gmail.com
Fri Jan 7 12:24:36 CET 2011


Revision: 34152
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=34152
Author:   jhk
Date:     2011-01-07 11:24:34 +0000 (Fri, 07 Jan 2011)
Log Message:
-----------
New hair child options:
* Renamed children to "simple" and "interpolated" as this is
  easier to explain and more descriptive than "from particles"
  and "from faces".
* Also shuffled the child ui around a bit to make it clearer.
* Child seed parameter allows to change the seed for children
  independent of the main seed value.
* Long hair mode for interpolated children:
  - Making even haircuts was impossible before as the child
    strand lengths were even, but their root coordinates were
    not similar in relation to the parent strands.
  - The "long hair" option uses the tips of the parent strands
    to calculate the child strand tips.
* Hair parting options:
  - Hair parting can now be calculated dynamically on the fly
    when in 2.49 there was a cumbersome way of using emitter mesh
    seams to define parting lines.
  - For long hair parting can be created by a tip distance/root
    distance threshold. For example setting the minimum threshold
    to 2.0 creates partings between children belonging to parents
    with tip distance of three times the root distance
    ((1+2)*root distance).
  - For short hair the parting thresholds are used as angles
    between the root directions.
* New kink parameters:
  - Kink flatness calculates kink into a shape that would have
    been achieved with an actual curling iron.
  - Kink amplitude clump determines how much the main clump value
    effects the kink amplitude.
  - The beginning of kink is now smoothed to make the hair look
    more natural close to the roots.
* Some bugs fixed along the way too:
  - Child parent's were not determined correctly in some cases.
  - Children didn't always look correct in particle mode.
  - Changing child parameters caused actual particles to be
    recalculated.
* Also cleaned up some deprecated code.

All in all there should be no real changes to how old files look
(except perhaps a bit better!), but the new options should make
hair/fur creation a bit more enjoyable. I'll try to make a video
demonstrating the new stuff shortly.

Modified Paths:
--------------
    trunk/blender/release/scripts/ui/properties_particle.py
    trunk/blender/source/blender/blenkernel/intern/particle.c
    trunk/blender/source/blender/blenkernel/intern/particle_system.c
    trunk/blender/source/blender/blenkernel/intern/pointcache.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/ui/properties_particle.py
===================================================================
--- trunk/blender/release/scripts/ui/properties_particle.py	2011-01-07 11:08:47 UTC (rev 34151)
+++ trunk/blender/release/scripts/ui/properties_particle.py	2011-01-07 11:24:34 UTC (rev 34152)
@@ -739,7 +739,7 @@
             row = layout.row()
             col = row.column()
 
-            if part.type == 'HAIR' and part.use_strand_primitive == True and part.child_type == 'FACES':
+            if part.type == 'HAIR' and part.use_strand_primitive == True and part.child_type == 'INTERPOLATED':
                 layout.prop(part, "use_simplify")
                 if part.use_simplify == True:
                     row = layout.row()
@@ -925,60 +925,76 @@
         col.prop(part, "child_nbr", text="Display")
         col.prop(part, "rendered_child_count", text="Render")
 
-        col = row.column(align=True)
-
-        if part.child_type == 'FACES':
+        if part.child_type == 'INTERPOLATED':
+            col = row.column()
+            col.prop(psys, "child_seed", text="Seed")
             col.prop(part, "virtual_parents", slider=True)
+            col.prop(part, "create_long_hair_children")
         else:
-            col.prop(part, "child_radius", text="Radius")
-            col.prop(part, "child_roundness", text="Roundness", slider=True)
-
             col = row.column(align=True)
             col.prop(part, "child_size", text="Size")
             col.prop(part, "child_size_random", text="Random")
 
-        layout.row().label(text="Effects:")
+        split = layout.split()
 
-        row = layout.row()
+        col = split.column()
+        col.label(text="Effects:")
 
-        col = row.column(align=True)
-        col.prop(part, "clump_factor", slider=True)
-        col.prop(part, "clump_shape", slider=True)
+        sub = col.column(align=True)
+        sub.prop(part, "clump_factor", slider=True)
+        sub.prop(part, "clump_shape", slider=True)
+        
+        sub = col.column(align=True)
+        sub.prop(part, "child_length", slider=True)
+        sub.prop(part, "child_length_threshold", slider=True)
 
-        col = row.column(align=True)
-        col.prop(part, "roughness_endpoint")
-        col.prop(part, "roughness_end_shape")
+        if part.child_type == 'SIMPLE':
+            sub = col.column(align=True)
+            sub.prop(part, "child_radius", text="Radius")
+            sub.prop(part, "child_roundness", text="Roundness", slider=True)
+            sub.prop(psys, "child_seed", text="Seed")
+        elif part.virtual_parents > 0.0:
+            sub = col.column(align=True)
+            sub.label(text="Parting not")
+            sub.label(text="available with")
+            sub.label(text="virtual parents.")
+        else:
+            sub = col.column(align=True)
+            sub.prop(part, "child_parting_factor", text="Parting", slider=True)
+            sub.prop(part, "child_parting_min", text="Min")
+            sub.prop(part, "child_parting_max", text="Max")
 
-        row = layout.row()
+        col = split.column()
+        col.label(text="Roughness:")
 
-        col = row.column(align=True)
-        col.prop(part, "roughness_1")
-        col.prop(part, "roughness_1_size")
+        sub = col.column(align=True)
+        sub.prop(part, "roughness_1", text="Uniform")
+        sub.prop(part, "roughness_1_size", text="Size")
 
-        col = row.column(align=True)
-        col.prop(part, "roughness_2")
-        col.prop(part, "roughness_2_size")
-        col.prop(part, "roughness_2_threshold", slider=True)
+        sub = col.column(align=True)
+        sub.prop(part, "roughness_endpoint", "Endpoint")
+        sub.prop(part, "roughness_end_shape")
 
-        row = layout.row()
-        col = row.column(align=True)
-        col.prop(part, "child_length", slider=True)
-        col.prop(part, "child_length_threshold", slider=True)
+        sub = col.column(align=True)
+        sub.prop(part, "roughness_2", text="Random")
+        sub.prop(part, "roughness_2_size", text="Size")
+        sub.prop(part, "roughness_2_threshold", slider=True)
 
-        col = row.column(align=True)
-        col.label(text="Space reserved for")
-        col.label(text="hair parting controls")
-
         layout.row().label(text="Kink:")
         layout.row().prop(part, "kink", expand=True)
 
         split = layout.split()
+        split.active = part.kink != 'NO'
 
         col = split.column()
-        col.prop(part, "kink_amplitude")
-        col.prop(part, "kink_frequency")
+        sub = col.column(align=True)
+        sub.prop(part, "kink_amplitude")
+        sub.prop(part, "kink_amplitude_clump", text="Clump", slider=True)
+        col.prop(part, "kink_flat", slider=True)
         col = split.column()
-        col.prop(part, "kink_shape", slider=True)
+        sub = col.column(align=True)
+        sub.prop(part, "kink_frequency")
+        sub.prop(part, "kink_shape", slider=True)
 
 
 class PARTICLE_PT_field_weights(ParticleButtonsPanel, bpy.types.Panel):

Modified: trunk/blender/source/blender/blenkernel/intern/particle.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/particle.c	2011-01-07 11:08:47 UTC (rev 34151)
+++ trunk/blender/source/blender/blenkernel/intern/particle.c	2011-01-07 11:24:34 UTC (rev 34152)
@@ -1862,144 +1862,184 @@
 	return 0.0;
 }
 
-static void do_prekink(ParticleKey *state, ParticleKey *par, float *par_rot, float time, float freq, float shape, float amplitude, short type, short axis, float obmat[][4])
+static void do_kink(ParticleKey *state, ParticleKey *par, float *par_rot, float time, float freq, float shape, float amplitude, float flat, short type, short axis, float obmat[][4], int smooth_start)
 {
-	float vec[3]={0.0,0.0,0.0}, q1[4]={1,0,0,0},q2[4];
-	float t;
+	float kink[3]={1.f,0.f,0.f}, par_vec[3], q1[4]={1.f,0.f,0.f,0.f};
+	float t, dt=1.f, result[3];
 
-	CLAMP(time,0.0,1.0);
+	if(par == NULL || type == PART_KINK_NO)
+		return;
 
+	CLAMP(time, 0.f, 1.f);
+
 	if(shape!=0.0f && type!=PART_KINK_BRAID) {
 		if(shape<0.0f)
-			time= (float)pow(time, 1.0+shape);
+			time= (float)pow(time, 1.f+shape);
 		else
-			time= (float)pow(time, 1.0/(1.0-shape));
+			time= (float)pow(time, 1.f/(1.f-shape));
 	}
 
-	t=time;
+	t = time * freq *(float)M_PI;
+	
+	if(smooth_start) {
+		dt = fabs(t);
+		/* smooth the beginning of kink */
+		CLAMP(dt, 0.f, (float)M_PI);
+		dt = sin(dt/2.f);
+	}
 
-	t*=(float)M_PI*freq;
+	if(type != PART_KINK_RADIAL) {
+		float temp[3];
 
-	if(par==0) return;
+		kink[axis]=1.f;
 
-	switch(type){
-		case PART_KINK_CURL:
-			vec[axis]=1.0;
-			if(par_rot)
-				QUATCOPY(q2,par_rot)
-			else
-				vec_to_quat( q2,par->vel,axis,(axis+1)%3);
-			mul_qt_v3(q2,vec);
-			mul_v3_fl(vec,amplitude);
-			VECADD(state->co,state->co,vec);
+		if(obmat)
+			mul_mat3_m4_v3(obmat, kink);
+		
+		if(par_rot)
+			mul_qt_v3(par_rot, kink);
 
-			VECSUB(vec,state->co,par->co);
+		/* make sure kink is normal to strand */
+		project_v3_v3v3(temp, kink, par->vel);
+		sub_v3_v3(kink, temp);
+		normalize_v3(kink);
+	}
 
-			if(t!=0.0)
-				axis_angle_to_quat(q1,par->vel,t);
-			
-			mul_qt_v3(q1,vec);
-			
-			VECADD(state->co,par->co,vec);
-			break;
-		case PART_KINK_RADIAL:
-			VECSUB(vec,state->co,par->co);
+	copy_v3_v3(result, state->co);
+	sub_v3_v3v3(par_vec, par->co, state->co);
 
-			normalize_v3(vec);
-			mul_v3_fl(vec,amplitude*(float)sin(t));
+	switch(type) {
+	case PART_KINK_CURL:
+	{
+		mul_v3_fl(par_vec, -1.f);
 
-			VECADD(state->co,state->co,vec);
-			break;
-		case PART_KINK_WAVE:
-			vec[axis]=1.0;
-			if(obmat)
-				mul_mat3_m4_v3(obmat,vec);
+		if(flat > 0.f) {
+			float proj[3];
+			project_v3_v3v3(proj, par_vec, par->vel);
+			madd_v3_v3fl(par_vec, proj, -flat);
 
-			if(par_rot)
-				mul_qt_v3(par_rot,vec);
+			project_v3_v3v3(proj, par_vec, kink);
+			madd_v3_v3fl(par_vec, proj, -flat);
+		}
 
-			project_v3_v3v3(q1,vec,par->vel);
-			
-			VECSUB(vec,vec,q1);
-			normalize_v3(vec);
+		axis_angle_to_quat(q1, kink, (float)M_PI/2.f);
 
-			mul_v3_fl(vec,amplitude*(float)sin(t));
+		mul_qt_v3(q1, par_vec);
 
-			VECADD(state->co,state->co,vec);
-			break;
-		case PART_KINK_BRAID:
-			if(par){
-				float y_vec[3]={0.0,1.0,0.0};
-				float z_vec[3]={0.0,0.0,1.0};
-				float vec_from_par[3], vec_one[3], radius, state_co[3];
-				float inp_y,inp_z,length;
-				
-				if(par_rot)
-					QUATCOPY(q2,par_rot)
-				else
-					vec_to_quat(q2,par->vel,axis,(axis+1)%3);
-				mul_qt_v3(q2,y_vec);
-				mul_qt_v3(q2,z_vec);
-				
-				VECSUB(vec_from_par,state->co,par->co);
-				radius= normalize_v3_v3(vec_one, vec_from_par);
+		madd_v3_v3fl(par_vec, kink, amplitude);
 
-				inp_y=dot_v3v3(y_vec,vec_one);
-				inp_z=dot_v3v3(z_vec,vec_one);
+		/* rotate kink vector around strand tangent */
+		if(t!=0.f) {
+			axis_angle_to_quat(q1, par->vel, t);
+			mul_qt_v3(q1, par_vec);
+		}
 
-				if(inp_y>0.5){
-					VECCOPY(state_co,y_vec);
+		add_v3_v3v3(result, par->co, par_vec);
+		break;
+	}
+	case PART_KINK_RADIAL:
+	{
+		if(flat > 0.f) {
+			float proj[3];
+			/* flatten along strand */
+			project_v3_v3v3(proj, par_vec, par->vel);
+			madd_v3_v3fl(result, proj, flat);
+		}
 
-					mul_v3_fl(y_vec,amplitude*(float)cos(t));
-					mul_v3_fl(z_vec,amplitude/2.0f*(float)sin(2.0f*t));
-				}
-				else if(inp_z>0.0){
-					VECCOPY(state_co,z_vec);
-					mul_v3_fl(state_co,(float)sin(M_PI/3.0f));
-					VECADDFAC(state_co,state_co,y_vec,-0.5f);
+		madd_v3_v3fl(result, par_vec, -amplitude*(float)sin(t));
+		break;
+	}
+	case PART_KINK_WAVE:
+	{
+		madd_v3_v3fl(result, kink, amplitude*(float)sin(t));
 
-					mul_v3_fl(y_vec,-amplitude*(float)cos(t + M_PI/3.0f));
-					mul_v3_fl(z_vec,amplitude/2.0f*(float)cos(2.0f*t + M_PI/6.0f));
-				}
-				else{
-					VECCOPY(state_co,z_vec);
-					mul_v3_fl(state_co,-(float)sin(M_PI/3.0f));
-					VECADDFAC(state_co,state_co,y_vec,-0.5f);
+		if(flat > 0.f) {
+			float proj[3];
+			/* flatten along wave */
+			project_v3_v3v3(proj, par_vec, kink);
+			madd_v3_v3fl(result, proj, flat);
 
-					mul_v3_fl(y_vec,amplitude*(float)-sin(t+M_PI/6.0f));
-					mul_v3_fl(z_vec,amplitude/2.0f*(float)-sin(2.0f*t+M_PI/3.0f));
-				}
+			/* flatten along strand */
+			project_v3_v3v3(proj, par_vec, par->vel);
+			madd_v3_v3fl(result, proj, flat);
+		}
+		break;
+	}
+	case PART_KINK_BRAID:
+	{
+		float y_vec[3]={0.f,1.f,0.f};
+		float z_vec[3]={0.f,0.f,1.f};
+		float vec_one[3], radius, state_co[3];
+		float inp_y, inp_z, length;
 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list