I made a new texture type for this noise function now, so one can
easily use it in other places. Integrating into the cloud texture was
my first thought, due to the similarity to the static noise functions,
but adding it as another texture type is the cleaner solution.
Also found a couple of bugs that were fixed, so this is now quite usable.
Little test video demonstrating the rotation feature (no advection):
http://vimeo.com/9439250
(You may notice some kind of streak along the diagonal, this
regularity should not appear in a noise texture of course and must be
considered another bug)

>  One minor issue i had was that
>> apparently extrapolation modes for f-curves are not yet implemented
>> (confirm?), so that animating a continuously changing flow rotation is
>> a bit nasty.
>> Hope you like this and it can be included into svn.
>>
>> Regards
>> phonybone
>>
>
> This is not entirely true. There are extrapolation modes for the curves -
> constant (i.e. use values at endpoints), linear (i.e. linear interpolation
> of the segments of the curve near the endpoints).
>
> However, what you're probably referring to are the old "cyclic" options,
> which are now F-Modifiers. With the F-Curves selected in the Graph Editor,
> you can add F-Modifiers to those F-Curves. This currently cannot be done in
> the DopeSheet, but may be able to be supported in future (it's just a matter
> of adding another operator).

I am still not much further here. After a few svn updates i found that
now i don't even get f-curves for most animated values :(  Some still
work, like object transforms, but a lot of properties don't even show
up in the editor any more when animated. Maybe i am overlooking
something simple, but so far nobody could explain this to me.

Regards
phonybone
Index: release/scripts/ui/properties_texture.py
===================================================================
--- release/scripts/ui/properties_texture.py	(revision 26868)
+++ release/scripts/ui/properties_texture.py	(working copy)
@@ -956,6 +956,35 @@
         col.prop(pd, "turbulence_depth")
         col.prop(pd, "turbulence_strength")
 
+class TEXTURE_PT_flownoise(TextureTypePanel):
+    bl_label = "Flow Noise"
+    tex_type = 'FLOWNOISE'
+
+    def draw(self, context):
+        layout = self.layout
+
+        tex = context.texture
+        wide_ui = context.region.width > narrowui
+
+        layout.prop(tex, "stype", expand=True)
+        layout.label(text="Noise:")
+        layout.prop(tex, "noise_type", text="Type", expand=True)
+
+        split = layout.split()
+
+        col = split.column()
+        col.prop(tex, "noise_size", text="Size")
+        col.prop(tex, "noise_depth", text="Depth")
+        
+        col = split.column()
+        col.prop(tex, "flow_rotation", text="Rotation")
+        col.prop(tex, "flow_advection", text="Advection")
+
+        if wide_ui:
+            col = split.column()
+        col.prop(tex, "nabla", text="Nabla")
+
+
 bpy.types.register(TEXTURE_PT_context_texture)
 bpy.types.register(TEXTURE_PT_preview)
 
@@ -976,6 +1005,7 @@
 bpy.types.register(TEXTURE_PT_voxeldata)
 bpy.types.register(TEXTURE_PT_pointdensity)
 bpy.types.register(TEXTURE_PT_pointdensity_turbulence)
+bpy.types.register(TEXTURE_PT_flownoise)
 
 bpy.types.register(TEXTURE_PT_colors)
 bpy.types.register(TEXTURE_PT_mapping)
Index: release/scripts/ui/properties_physics_field.py
===================================================================
--- release/scripts/ui/properties_physics_field.py	(revision 26868)
+++ release/scripts/ui/properties_physics_field.py	(working copy)
@@ -113,6 +113,14 @@
             col.prop(field, "use_coordinates")
             col.prop(field, "root_coordinates")
             col.prop(field, "force_2d")
+        
+        elif field.type == 'TURBULENCE':
+            basic_force_field_settings_ui(self, context, field)
+
+            col = split.column()
+            col.prop(field, "flow_rotation")
+            col.prop(field, "flow_advection")
+
         else:
             basic_force_field_settings_ui(self, context, field)
 
Index: source/blender/render/intern/source/texture.c
===================================================================
--- source/blender/render/intern/source/texture.c	(revision 26868)
+++ source/blender/render/intern/source/texture.c	(working copy)
@@ -714,6 +714,39 @@
 
 }
 
+static int flownoisetex(Tex *tex, float *texvec, TexResult *texres)
+{
+	int rv = TEX_INT;
+	#define M_2PI 6.283185307
+
+	texres->tin = BLI_flowTurbulence(tex->noisesize, texvec[0], texvec[1], texvec[2], tex->flow_rotation*M_2PI, tex->flow_advection, tex->noisedepth, (tex->noisetype!=TEX_NOISESOFT));
+
+	if (texres->nor!=NULL) {
+		// calculate bumpnormal
+		texres->nor[0] = BLI_flowTurbulence(tex->noisesize, texvec[0] + tex->nabla, texvec[1], texvec[2], tex->flow_rotation*M_2PI, tex->flow_advection, tex->noisedepth,  (tex->noisetype!=TEX_NOISESOFT));
+		texres->nor[1] = BLI_flowTurbulence(tex->noisesize, texvec[0], texvec[1] + tex->nabla, texvec[2], tex->flow_rotation*M_2PI, tex->flow_advection, tex->noisedepth,  (tex->noisetype!=TEX_NOISESOFT));
+		texres->nor[2] = BLI_flowTurbulence(tex->noisesize, texvec[0], texvec[1], texvec[2] + tex->nabla, tex->flow_rotation*M_2PI, tex->flow_advection, tex->noisedepth,  (tex->noisetype!=TEX_NOISESOFT));
+		
+		tex_normal_derivate(tex, texres);
+		rv |= TEX_NOR;
+	}
+
+	if (tex->stype==TEX_COLOR) {
+		// in this case, int. value should really be computed from color,
+		// and bumpnormal from that, would be too slow, looks ok as is
+		texres->tr = texres->tin;
+		texres->tg = BLI_flowTurbulence(tex->noisesize, texvec[1], texvec[0], texvec[2], tex->flow_rotation*M_2PI, tex->flow_advection, tex->noisedepth, (tex->noisetype!=TEX_NOISESOFT));
+		texres->tb = BLI_flowTurbulence(tex->noisesize, texvec[1], texvec[2], texvec[0], tex->flow_rotation*M_2PI, tex->flow_advection, tex->noisedepth, (tex->noisetype!=TEX_NOISESOFT));
+		BRICONTRGB;
+		texres->ta = 1.0;
+		return (rv | TEX_RGB);
+	}
+
+	BRICONT;
+
+	return rv;
+}
+
 /* ------------------------------------------------------------------------- */
 
 static int evalnodes(Tex *tex, float *texvec, float *dxt, float *dyt, TexResult *texres, short thread, short which_output)
@@ -1271,6 +1304,9 @@
 	case TEX_VOXELDATA:
 		retval= voxeldatatex(tex, texvec, texres);  
 		break;
+	case TEX_FLOWNOISE:
+		retval= flownoisetex(tex, texvec, texres);
+		break;
 
 	}
 
Index: source/blender/blenkernel/intern/effect.c
===================================================================
--- source/blender/blenkernel/intern/effect.c	(revision 26868)
+++ source/blender/blenkernel/intern/effect.c	(working copy)
@@ -918,9 +918,10 @@
 			else {
 				VECADD(temp, efd->vec_to_point2, efd->nor2);
 			}
-			force[0] = -1.0f + 2.0f * BLI_gTurbulence(pd->f_size, temp[0], temp[1], temp[2], 2,0,2);
-			force[1] = -1.0f + 2.0f * BLI_gTurbulence(pd->f_size, temp[1], temp[2], temp[0], 2,0,2);
-			force[2] = -1.0f + 2.0f * BLI_gTurbulence(pd->f_size, temp[2], temp[0], temp[1], 2,0,2);
+			#define M_2PI 6.283185307
+			force[0] = -1.0f + 2.0f * BLI_flowTurbulence(pd->f_size, temp[0], temp[1], temp[2], pd->flow_rotation*M_2PI, pd->flow_advection, 2, 0);
+			force[1] = -1.0f + 2.0f * BLI_flowTurbulence(pd->f_size, temp[1], temp[2], temp[0], pd->flow_rotation*M_2PI, pd->flow_advection, 2, 0);
+			force[2] = -1.0f + 2.0f * BLI_flowTurbulence(pd->f_size, temp[2], temp[0], temp[1], pd->flow_rotation*M_2PI, pd->flow_advection, 2, 0);
 			mul_v3_fl(force, strength * efd->falloff);
 			break;
 		case PFIELD_DRAG:
Index: source/blender/makesdna/DNA_texture_types.h
===================================================================
--- source/blender/makesdna/DNA_texture_types.h	(revision 26868)
+++ source/blender/makesdna/DNA_texture_types.h	(working copy)
@@ -215,6 +215,9 @@
 	float vn_w4;
 	float vn_mexp;
 	short vn_distm, vn_coltype;
+	
+	/* flow noise rotation and advection */
+	float flow_rotation, flow_advection;
 
 	short noisedepth, noisetype;
 
@@ -290,6 +293,7 @@
 #define TEX_DISTNOISE	13
 #define TEX_POINTDENSITY	14
 #define TEX_VOXELDATA		15
+#define TEX_FLOWNOISE		16
 
 /* musgrave stype */
 #define TEX_MFRACTAL		0
Index: source/blender/makesdna/DNA_object_force.h
===================================================================
--- source/blender/makesdna/DNA_object_force.h	(revision 26868)
+++ source/blender/makesdna/DNA_object_force.h	(working copy)
@@ -108,6 +108,10 @@
 	struct RNG *rng;	/* random noise generator for e.g. wind */
 	float f_noise;		/* noise of force						*/
 	int seed;			/* noise random seed					*/
+	
+	/* flow noise parameters */
+	float flow_rotation;
+	float flow_advection;
 } PartDeflect;
 
 typedef struct EffectorWeights {
Index: source/blender/makesrna/intern/rna_texture.c
===================================================================
--- source/blender/makesrna/intern/rna_texture.c	(revision 26868)
+++ source/blender/makesrna/intern/rna_texture.c	(working copy)
@@ -57,6 +57,7 @@
 	{TEX_CLOUDS, "CLOUDS", ICON_TEXTURE, "Clouds", ""},
 	{TEX_DISTNOISE, "DISTORTED_NOISE", ICON_TEXTURE, "Distorted Noise", ""},
 	{TEX_ENVMAP, "ENVIRONMENT_MAP", ICON_IMAGE_DATA, "Environment Map", ""},
+	{TEX_FLOWNOISE, "FLOWNOISE", ICON_TEXTURE, "Flow noise", ""},
 	{TEX_IMAGE, "IMAGE", ICON_IMAGE_DATA, "Image or Movie", ""},
 	{TEX_MAGIC, "MAGIC", ICON_TEXTURE, "Magic", ""},
 	{TEX_MARBLE, "MARBLE", ICON_TEXTURE, "Marble", ""},
@@ -98,6 +99,8 @@
 			return &RNA_DistortedNoiseTexture;
 		case TEX_ENVMAP:
 			return &RNA_EnvironmentMapTexture;
+		case TEX_FLOWNOISE:
+			return &RNA_FlownoiseTexture;
 		case TEX_IMAGE:
 			return &RNA_ImageTexture;
 		case TEX_MAGIC:
@@ -770,6 +773,7 @@
 	{TEX_VORONOI_F2F1, "VORONOI_F2_F1", 0, "Voronoi F2-F1", ""},
 	{TEX_VORONOI_CRACKLE, "VORONOI_CRACKLE", 0, "Voronoi Crackle", ""},
 	{TEX_CELLNOISE, "CELL_NOISE", 0, "Cell Noise", ""},
+	{TEX_FLOWNOISE, "FLOW_NOISE", 0, "Flow Noise", ""},
 	{0, NULL, 0, NULL, NULL}};
 
 static EnumPropertyItem prop_noise_type[] = {
@@ -1817,6 +1821,63 @@
 	RNA_def_property_update(prop, 0, "rna_Texture_update");
 }
 
+static void rna_def_texture_flownoise(BlenderRNA *brna)
+{
+	StructRNA *srna;
+	PropertyRNA *prop;
+
+	static EnumPropertyItem prop_flownoise_stype[] = {
+	{TEX_DEFAULT, "GREYSCALE", 0, "Greyscale", ""},
+	{TEX_COLOR, "COLOR", 0, "Color", ""},
+	{0, NULL, 0, NULL, NULL}};
+
+	srna= RNA_def_struct(brna, "FlownoiseTexture", "Texture");
+	RNA_def_struct_ui_text(srna, "Flow noise Texture", "Procedural animatable noise texture");
+	RNA_def_struct_sdna(srna, "Tex");
+
+	prop= RNA_def_property(srna, "noise_size", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "noisesize");
+	RNA_def_property_range(prop, 0.0001, FLT_MAX);
+	RNA_def_property_ui_range(prop, 0.0001, 2, 10, 2);
+	RNA_def_property_ui_text(prop, "Noise Size", "Sets scaling for noise input");
+	RNA_def_property_update(prop, 0, "rna_Texture_update");
+
+	prop= RNA_def_property(srna, "noise_depth", PROP_INT, PROP_NONE);
+	RNA_def_property_int_sdna(prop, NULL, "noisedepth");
+	RNA_def_property_range(prop, 0, INT_MAX);
+	RNA_def_property_ui_range(prop, 0, 6, 0, 2);
+	RNA_def_property_ui_text(prop, "Noise Depth", "Sets the depth of the noise calculation");
+	RNA_def_property_update(prop, 0, "rna_Texture_nodes_update");
+
+	prop= RNA_def_property(srna, "noise_type", PROP_ENUM, PROP_NONE);
+	RNA_def_property_enum_sdna(prop, NULL, "noisetype");
+	RNA_def_property_enum_items(prop, prop_noise_type);
+	RNA_def_property_ui_text(prop, "Noise Type", "");
+	RNA_def_property_update(prop, 0, "rna_Texture_nodes_update");
+
+	prop= RNA_def_property(srna, "stype", PROP_ENUM, PROP_NONE);
+	RNA_def_property_enum_sdna(prop, NULL, "stype");
+	RNA_def_property_enum_items(prop, prop_flownoise_stype);
+	RNA_def_property_ui_text(prop, "Color", "");
+	RNA_def_property_update(prop, 0, "rna_Texture_nodes_update");
+
+	prop= RNA_def_property(srna, "nabla", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_range(prop, 0.001, 0.1);
+	RNA_def_property_ui_range(prop, 0.001, 0.1, 1, 2);
+	RNA_def_property_ui_text(prop, "Nabla", "Size of derivative offset used for calculating normal");
+	RNA_def_property_update(prop, 0, "rna_Texture_update");
+
+	prop= RNA_def_property(srna, "flow_rotation", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_range(prop, 0.0, 1.0);
+	RNA_def_property_ui_text(prop, "Rotation", "Rotation of flow noise");
+	RNA_def_property_update(prop, 0, "rna_Texture_update");
+
+	prop= RNA_def_property(srna, "flow_advection", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_range(prop, -2.0, 2.0);
+	RNA_def_property_ui_text(prop, "Advection", "Advection of flow noise");
+	RNA_def_property_update(prop, 0, "rna_Texture_update");
+}
+
 static void rna_def_texture(BlenderRNA *brna)
 {
 	StructRNA *srna;
@@ -1908,6 +1969,7 @@
 	rna_def_texture_distorted_noise(brna);
 	rna_def_texture_pointdensity(brna);
 	rna_def_texture_voxeldata(brna);
+	rna_def_texture_flownoise(brna);
 	/* XXX add more types here .. */
 }
 
Index: source/blender/makesrna/intern/rna_object_force.c
===================================================================
--- source/blender/makesrna/intern/rna_object_force.c	(revision 26868)
+++ source/blender/makesrna/intern/rna_object_force.c	(working copy)
@@ -1170,6 +1170,18 @@
 	RNA_def_property_ui_text(prop, "Noise", "Noise of the force");
 	RNA_def_property_update(prop, 0, "rna_FieldSettings_update");
 
+	prop= RNA_def_property(srna, "flow_rotation", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "flow_rotation");
+	RNA_def_property_range(prop, 0.0f, 1.0f);
+	RNA_def_property_ui_text(prop, "Rotation", "Rotation of flow noise");
+	RNA_def_property_update(prop, 0, "rna_FieldSettings_update");
+
+	prop= RNA_def_property(srna, "flow_advection", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "flow_advection");
+	RNA_def_property_range(prop, -2.0f, 2.0f);
+	RNA_def_property_ui_text(prop, "Advection", "Advection of flow noise");
+	RNA_def_property_update(prop, 0, "rna_FieldSettings_update");
+
 	prop= RNA_def_property(srna, "seed", PROP_INT, PROP_UNSIGNED);
 	RNA_def_property_range(prop, 1, 128);
 	RNA_def_property_ui_text(prop, "Seed", "Seed of the noise");
Index: source/blender/blenlib/BLI_noise.h
===================================================================
--- source/blender/blenlib/BLI_noise.h	(revision 26868)
+++ source/blender/blenlib/BLI_noise.h	(working copy)
@@ -56,6 +56,9 @@
 /* newnoise: cellNoise & cellNoiseV (for vector/point/color) */
 float cellNoise(float x, float y, float z);
 void cellNoiseV(float x, float y, float z, float *ca);
+/* flow noise */
+float BLI_flowNoise3(float x, float y, float z, float angle, float *dnoise_dx, float *dnoise_dy, float *dnoise_dz);
+float BLI_flowTurbulence(float noisesize, float x, float y, float z, float angle, float advection, int oct, int hard);
 
 
 #ifdef __cplusplus
Index: source/blender/blenlib/intern/noise.c
===================================================================
--- source/blender/blenlib/intern/noise.c	(revision 26868)
+++ source/blender/blenlib/intern/noise.c	(working copy)
@@ -215,7 +215,7 @@
 	return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);
 }
 
-/* instead of adding another permutation array, just use hash table defined above */
+/* instead of adding another hashutation array, just use hash table defined above */
 static float newPerlin(float x, float y, float z)
 {
 	int A, AA, AB, B, BA, BB;
@@ -1855,3 +1855,318 @@
 /****************/
 /* musgrave end */
 /****************/
+
+/* Flow noise
+ * This code was copied & modified from Stefan Gustavson's ([email protected])
+ * DSOnoises package, available under GNU GPL here: http://webstaff.itn.liu.se/~stegu/aqsis/DSOs/DSOnoises.html
+ */
+
+/*
+ * This is an implementation of Perlin "simplex noise" over two dimensions
+ * (x,y) and three dimensions (x,y,z). One extra parameter 't' rotates the
+ * underlying gradients of the grid, which gives a swirling, flow-like
+ * motion. The derivative is returned, to make it possible to do pseudo-
+ * advection and implement "flow noise", as presented by Ken Perlin and
+ * Fabrice Neyret at Siggraph 2001.
+ *
+ * When not animated and presented in one octave only, this noise
+ * looks exactly the same as the plain version of simplex noise.
+ * It's nothing magical by itself, although the extra animation
+ * parameter 't' is useful. Fun stuff starts to happen when you
+ * do fractal sums of several octaves, with different rotation speeds
+ * and an advection of smaller scales by larger scales (or even the
+ * other way around it you feel adventurous).
+ *
+ * The gradient rotations that can be performed by this noise function
+ * and the true analytic derivatives are required to do flow noise.
+ * You can't do it properly with regular Perlin noise.
+ *
+ */
+
+#define FLOW_NOISE_FASTFLOOR(x) ( ((x)>0) ? ((int)x) : (((int)x)-1) )
+
+/*
+ * Permutation table. This is just a random jumble of all numbers 0-255,
+ * repeated twice to avoid wrapping the index at 255 for each lookup.
+ */
+unsigned char perm[512] = {151,160,137,91,90,15,
+  131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
+  190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
+  88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
+  77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
+  102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
+  135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
+  5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
+  223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
+  129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
+  251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
+  49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
+  138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180,
+  151,160,137,91,90,15,
+  131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
+  190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
+  88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
+  77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
+  102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
+  135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
+  5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
+  223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
+  129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
+  251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
+  49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
+  138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180 
+};
+
+/*
+ * For 3D, we define two orthogonal vectors in the desired rotation plane.
+ * These vectors are based on the midpoints of the 12 edges of a cube,
+ * they all rotate in their own plane and are never coincident or collinear.
+ * A larger array of random vectors would also do the job, but these 12
+ * (including 4 repeats to make the array length a power of two) work better.
+ * They are not random, they are carefully chosen to represent a small
+ * isotropic set of directions for any rotation angle.
+ */
+
+/* a = sqrt(2)/sqrt(3) = 0.816496580 */
+#define a 0.81649658f
+
+static float grad3u[16][3] = {
+  { 1.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f }, // 12 cube edges
+  { -1.0f, 0.0f, 1.0f }, { 0.0f, -1.0f, 1.0f },
+  { 1.0f, 0.0f, -1.0f }, { 0.0f, 1.0f, -1.0f },
+  { -1.0f, 0.0f, -1.0f }, { 0.0f, -1.0f, -1.0f },
+  { a, a, a }, { -a, a, -a },
+  { -a, -a, a }, { a, -a, -a },
+  { -a, a, a }, { a, -a, a },
+  { a, -a, -a }, { -a, a, -a }
+};
+
+static float grad3v[16][3] = {
+  { -a, a, a }, { -a, -a, a },
+  { a, -a, a }, { a, a, a },
+  { -a, -a, -a }, { a, -a, -a },
+  { a, a, -a }, { -a, a, -a },
+  { 1.0f, -1.0f, 0.0f }, { 1.0f, 1.0f, 0.0f },
+  { -1.0f, 1.0f, 0.0f }, { -1.0f, -1.0f, 0.0f },
+  { 1.0f, 0.0f, 1.0f }, { -1.0f, 0.0f, 1.0f }, // 4 repeats to make 16
+  { 0.0f, 1.0f, -1.0f }, { 0.0f, -1.0f, -1.0f }
+};
+
+#undef a
+
+static void gradrot3( int hash, float sin_t, float cos_t, float *gx, float *gy, float *gz ) {
+    int h = hash & 15;
+    float gux = grad3u[h][0];
+    float guy = grad3u[h][1];
+    float guz = grad3u[h][2];
+    float gvx = grad3v[h][0];
+    float gvy = grad3v[h][1];
+    float gvz = grad3v[h][2];
+    *gx = cos_t * gux + sin_t * gvx;
+    *gy = cos_t * guy + sin_t * gvy;
+    *gz = cos_t * guz + sin_t * gvz;
+    return;
+}
+
+static float graddotp3( float gx, float gy, float gz, float x, float y, float z ) {
+  return gx * x + gy * y + gz * z;
+}
+
+/* Skewing factors for 3D simplex grid:
+ * F3 = 1/3
+ * G3 = 1/6 */
+#define FLOW_NOISE_F3 0.333333333f
+#define FLOW_NOISE_G3 0.166666667f
+
+float BLI_flowNoise3( float x, float y, float z, float angle,
+                 float *dnoise_dx, float *dnoise_dy, float *dnoise_dz )
+{
+	float n0, n1, n2, n3; /* Noise contributions from the four simplex corners */
+	float noise;          /* Return value */
+	float gx0, gy0, gz0, gx1, gy1, gz1; /* Gradients at simplex corners */
+	float gx2, gy2, gz2, gx3, gy3, gz3;
+	float sin_t = sin(angle), cos_t = cos(angle); /* Sine and cosine for the gradient rotation angle */
+
+	/* Skew the input space to determine which simplex cell we're in */
+	float s = (x+y+z)*FLOW_NOISE_F3; /* Very nice and simple skew factor for 3D */
+	float xs = x+s;
+	float ys = y+s;
+	float zs = z+s;
+	int i = FLOW_NOISE_FASTFLOOR(xs);
+	int j = FLOW_NOISE_FASTFLOOR(ys);
+	int k = FLOW_NOISE_FASTFLOOR(zs);
+
+	float t = (float)(i+j+k)*FLOW_NOISE_G3; 
+	float X0 = (float)i-t; /* Unskew the cell origin back to (x,y,z) space */
+	float Y0 = (float)j-t;
+	float Z0 = (float)k-t;
+	float x0 = x-X0; /* The x,y,z distances from the cell origin */
+	float y0 = y-Y0;
+	float z0 = z-Z0;
+
+	/* For the 3D case, the simplex shape is a slightly irregular tetrahedron.
+	 * Determine which simplex we are in. */
+	int i1, j1, k1; /* Offsets for second corner of simplex in (i,j,k) coords */
+	int i2, j2, k2; /* Offsets for third corner of simplex in (i,j,k) coords */
+	
+	float x1, y1, z1, x2, y2, z2, x3, y3, z3;
+	int ii, jj, kk;
+	float t0, t20, t40, t1, t21, t41, t2, t22, t42, t3, t23, t43;
+
+	if(x0>=y0) {
+		if(y0>=z0)
+		{ i1=1; j1=0; k1=0; i2=1; j2=1; k2=0; } /* X Y Z order */
+		else if(x0>=z0) { i1=1; j1=0; k1=0; i2=1; j2=0; k2=1; } /* X Z Y order */
+		else { i1=0; j1=0; k1=1; i2=1; j2=0; k2=1; } /* Z X Y order */
+		}
+	else { // x0<y0
+		if(y0<z0) { i1=0; j1=0; k1=1; i2=0; j2=1; k2=1; } /* Z Y X order */
+		else if(x0<z0) { i1=0; j1=1; k1=0; i2=0; j2=1; k2=1; } /* Y Z X order */
+		else { i1=0; j1=1; k1=0; i2=1; j2=1; k2=0; } /* Y X Z order */
+	}
+
+	/* A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z),
+	 * a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and
+	 * a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where
+	 * c = 1/6.   */
+
+	x1 = x0 - (float)i1 + FLOW_NOISE_G3; /* Offsets for second corner in (x,y,z) coords */
+	y1 = y0 - (float)j1 + FLOW_NOISE_G3;
+	z1 = z0 - (float)k1 + FLOW_NOISE_G3;
+	x2 = x0 - (float)i2 + 2.0f * FLOW_NOISE_G3; /* Offsets for third corner in (x,y,z) coords */
+	y2 = y0 - (float)j2 + 2.0f * FLOW_NOISE_G3;
+	z2 = z0 - (float)k2 + 2.0f * FLOW_NOISE_G3;
+	x3 = x0 - 1.0f + 3.0f * FLOW_NOISE_G3; /* Offsets for last corner in (x,y,z) coords */
+	y3 = y0 - 1.0f + 3.0f * FLOW_NOISE_G3;
+	z3 = z0 - 1.0f + 3.0f * FLOW_NOISE_G3;
+
+	/* Wrap the integer indices at 256, to avoid indexing perm[] out of bounds */
+	ii = (i > 0 ? i % 256 : 256 - ((-i) % 256));
+	jj = (j > 0 ? j % 256 : 256 - ((-j) % 256));
+	kk = (k > 0 ? k % 256 : 256 - ((-k) % 256));
+
+	/* Calculate the contribution from the four corners */
+	t0 = 0.6f - x0*x0 - y0*y0 - z0*z0;
+	if(t0 < 0.0f) n0 = t0 = t20 = t40 = gx0 = gy0 = gz0 = 0.0f;
+	else {
+		gradrot3( perm[ii + perm[jj + perm[kk]]], sin_t, cos_t, &gx0, &gy0, &gz0 );
+		t20 = t0 * t0;
+		t40 = t20 * t20;
+		n0 = t40 * graddotp3( gx0, gy0, gz0, x0, y0, z0 );
+	}
+
+	t1 = 0.6f - x1*x1 - y1*y1 - z1*z1;
+	if(t1 < 0.0f) n1 = t1 = t21 = t41 = gx1 = gy1 = gz1 = 0.0f;
+	else {
+		gradrot3( perm[ii + i1 + perm[jj + j1 + perm[kk + k1]]], sin_t, cos_t, &gx1, &gy1, &gz1 );
+		t21 = t1 * t1;
+		t41 = t21 * t21;
+		n1 = t41 * graddotp3( gx1, gy1, gz1, x1, y1, z1 );
+	}
+
+	t2 = 0.6f - x2*x2 - y2*y2 - z2*z2;
+	if(t2 < 0.0f) n2 = t2 = t22 = t42 = gx2 = gy2 = gz2 = 0.0f;
+	else {
+		gradrot3( perm[ii + i2 + perm[jj + j2 + perm[kk + k2]]], sin_t, cos_t, &gx2, &gy2, &gz2 );
+		t22 = t2 * t2;
+		t42 = t22 * t22;
+		n2 = t42 * graddotp3( gx2, gy2, gz2, x2, y2, z2 );
+	}
+
+	t3 = 0.6f - x3*x3 - y3*y3 - z3*z3;
+	if(t3 < 0.0f) n3 = t3 = t23 = t43 = gx3 = gy3 = gz3 = 0.0f;
+	else {
+		gradrot3( perm[ii + 1 + perm[jj + 1 + perm[kk + 1]]], sin_t, cos_t, &gx3, &gy3, &gz3 );
+		t23 = t3 * t3;
+		t43 = t23 * t23;
+		n3 = t43 * graddotp3( gx3, gy3, gz3, x3, y3, z3 );
+	}
+
+	/*  Add contributions from each corner to get the final noise value.
+		* The result is scaled to return values in the range [-1,1] */
+	noise = 28.0f * (n0 + n1 + n2 + n3);
+
+	/* Compute derivative, if requested by supplying non-null pointers
+		* for the last three arguments */
+	if( ( dnoise_dx != 0 ) && ( dnoise_dy != 0 ) && ( dnoise_dz != 0 ))
+	{
+		/*  A straight, unoptimised calculation would be like:
+		*     *dnoise_dx = -8.0f * t20 * t0 * x0 * graddotp3(gx0, gy0, gz0, x0, y0, z0) + t40 * gx0;
+		*    *dnoise_dy = -8.0f * t20 * t0 * y0 * graddotp3(gx0, gy0, gz0, x0, y0, z0) + t40 * gy0;
+		*    *dnoise_dz = -8.0f * t20 * t0 * z0 * graddotp3(gx0, gy0, gz0, x0, y0, z0) + t40 * gz0;
+		*    *dnoise_dx += -8.0f * t21 * t1 * x1 * graddotp3(gx1, gy1, gz1, x1, y1, z1) + t41 * gx1;
+		*    *dnoise_dy += -8.0f * t21 * t1 * y1 * graddotp3(gx1, gy1, gz1, x1, y1, z1) + t41 * gy1;
+		*    *dnoise_dz += -8.0f * t21 * t1 * z1 * graddotp3(gx1, gy1, gz1, x1, y1, z1) + t41 * gz1;
+		*    *dnoise_dx += -8.0f * t22 * t2 * x2 * graddotp3(gx2, gy2, gz2, x2, y2, z2) + t42 * gx2;
+		*    *dnoise_dy += -8.0f * t22 * t2 * y2 * graddotp3(gx2, gy2, gz2, x2, y2, z2) + t42 * gy2;
+		*    *dnoise_dz += -8.0f * t22 * t2 * z2 * graddotp3(gx2, gy2, gz2, x2, y2, z2) + t42 * gz2;
+		*    *dnoise_dx += -8.0f * t23 * t3 * x3 * graddotp3(gx3, gy3, gz3, x3, y3, z3) + t43 * gx3;
+		*    *dnoise_dy += -8.0f * t23 * t3 * y3 * graddotp3(gx3, gy3, gz3, x3, y3, z3) + t43 * gy3;
+		*    *dnoise_dz += -8.0f * t23 * t3 * z3 * graddotp3(gx3, gy3, gz3, x3, y3, z3) + t43 * gz3;
+		*/
+		float temp0, temp1, temp2, temp3;
+		temp0 = t20 * t0 * graddotp3( gx0, gy0, gz0, x0, y0, z0 );
+		*dnoise_dx = temp0 * x0;
+		*dnoise_dy = temp0 * y0;
+		*dnoise_dz = temp0 * z0;
+		temp1 = t21 * t1 * graddotp3( gx1, gy1, gz1, x1, y1, z1 );
+		*dnoise_dx += temp1 * x1;
+		*dnoise_dy += temp1 * y1;
+		*dnoise_dz += temp1 * z1;
+		temp2 = t22 * t2 * graddotp3( gx2, gy2, gz2, x2, y2, z2 );
+		*dnoise_dx += temp2 * x2;
+		*dnoise_dy += temp2 * y2;
+		*dnoise_dz += temp2 * z2;
+		temp3 = t23 * t3 * graddotp3( gx3, gy3, gz3, x3, y3, z3 );
+		*dnoise_dx += temp3 * x3;
+		*dnoise_dy += temp3 * y3;
+		*dnoise_dz += temp3 * z3;
+		*dnoise_dx *= -8.0f;
+		*dnoise_dy *= -8.0f;
+		*dnoise_dz *= -8.0f;
+		/* This corrects a bug in the original implementation */
+		*dnoise_dx += t40 * gx0 + t41 * gx1 + t42 * gx2 + t43 * gx3;
+		*dnoise_dy += t40 * gy0 + t41 * gy1 + t42 * gy2 + t43 * gy3;
+		*dnoise_dz += t40 * gz0 + t41 * gz1 + t42 * gz2 + t43 * gz3;
+		*dnoise_dx *= 28.0f; /* Scale derivative to match the noise scaling */
+		*dnoise_dy *= 28.0f;
+		*dnoise_dz *= 28.0f;
+	}
+	return noise;
+}
+
+float BLI_flowTurbulence(float noisesize, float x, float y, float z, float angle, float advection, int oct, int hard)
+{
+	float sum, t, amp=1, adv_amp=advection, fscale=1;
+	int i;
+	float dx, dy, dz, adv_x=0.0f, adv_y=0.0f, adv_z=0.0f;
+	
+	if (noisesize!=0.0) {
+		noisesize = 1.0/noisesize;
+		x *= noisesize;
+		y *= noisesize;
+		z *= noisesize;
+	}
+	
+	sum = 0.0f;
+	if (hard) {
+		for (i=0; i<=oct; i++, amp*=0.5, adv_amp*=0.5f, fscale*=2) {
+			t = fabs(BLI_flowNoise3(fscale*x + adv_x, fscale*y + adv_y, fscale*z + adv_z, angle, &dx, &dy, &dz));
+			adv_x -= dx*adv_amp; adv_y -= dy*adv_amp; adv_z -= dz*adv_amp;
+			sum += t * amp;
+		}
+	} else {
+		for (i=0; i<=oct; i++, amp*=0.5, adv_amp*=0.5f, fscale*=2) {
+			t = 0.5f*(1.0f + BLI_flowNoise3(fscale*x + adv_x, fscale*y + adv_y, fscale*z + adv_z, angle, &dx, &dy, &dz));
+			adv_x -= dx*adv_amp; adv_y -= dy*adv_amp; adv_z -= dz*adv_amp;
+			sum += t * amp;
+		}
+	}
+	
+	sum *= ((float)(1<<oct)/(float)((1<<(oct+1))-1));
+
+	return sum;
+}
+/*
+ * Flow noise end
+ */
_______________________________________________
Bf-committers mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-committers

Reply via email to