[Bf-blender-cvs] [6288a2d] hair_immediate_fixes: Hair volume calculation is now in its own file.

Lukas Tönne noreply at git.blender.org
Mon Sep 15 14:23:20 CEST 2014


Commit: 6288a2d9283cd751f5360a1f656957fa3c7541b6
Author: Lukas Tönne
Date:   Sun Sep 14 18:08:14 2014 +0200
Branches: hair_immediate_fixes
https://developer.blender.org/rB6288a2d9283cd751f5360a1f656957fa3c7541b6

Hair volume calculation is now in its own file.

Code is currently disabled until the other main forces are in place.

===================================================================

M	source/blender/physics/CMakeLists.txt
A	source/blender/physics/intern/hair_volume.c
M	source/blender/physics/intern/implicit_blender.c

===================================================================

diff --git a/source/blender/physics/CMakeLists.txt b/source/blender/physics/CMakeLists.txt
index b08cf17..5df32c2 100644
--- a/source/blender/physics/CMakeLists.txt
+++ b/source/blender/physics/CMakeLists.txt
@@ -41,6 +41,7 @@ set(INC_SYS
 set(SRC
 	intern/BPH_mass_spring.cpp
 	intern/ConstrainedConjugateGradient.h
+	intern/hair_volume.c
 	intern/implicit.h
 	intern/implicit_blender.c
 	intern/implicit_eigen.cpp
diff --git a/source/blender/physics/intern/hair_volume.c b/source/blender/physics/intern/hair_volume.c
new file mode 100644
index 0000000..5111eac
--- /dev/null
+++ b/source/blender/physics/intern/hair_volume.c
@@ -0,0 +1,483 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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.
+ *
+ * The Original Code is Copyright (C) Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Janne Karhu, Lukas Toenne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/hair_volume.c
+ *  \ingroup bph
+ */
+
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#if 0 // XXX TODO
+
+/* ================ Volumetric Hair Interaction ================
+ * adapted from
+ *      Volumetric Methods for Simulation and Rendering of Hair
+ *      by Lena Petrovic, Mark Henne and John Anderson
+ *      Pixar Technical Memo #06-08, Pixar Animation Studios
+ */
+
+/* Note about array indexing:
+ * Generally the arrays here are one-dimensional.
+ * The relation between 3D indices and the array offset is
+ *   offset = x + res_x * y + res_y * z
+ */
+
+/* TODO: This is an initial implementation and should be made much better in due time.
+ * What should at least be implemented is a grid size parameter and a smoothing kernel
+ * for bigger grids.
+ */
+
+/* 10x10x10 grid gives nice initial results */
+static const int hair_grid_res = 10;
+
+static int hair_grid_size(int res)
+{
+	return res * res * res;
+}
+
+BLI_INLINE void hair_grid_get_scale(int res, const float gmin[3], const float gmax[3], float scale[3])
+{
+	sub_v3_v3v3(scale, gmax, gmin);
+	mul_v3_fl(scale, 1.0f / (res-1));
+}
+
+typedef struct HairGridVert {
+	float velocity[3];
+	float density;
+} HairGridVert;
+
+#define HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, axis) ( min_ii( max_ii( (int)((vec[axis] - gmin[axis]) / scale[axis]), 0), res-2 ) )
+
+BLI_INLINE int hair_grid_offset(const float vec[3], int res, const float gmin[3], const float scale[3])
+{
+	int i, j, k;
+	i = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 0);
+	j = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 1);
+	k = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 2);
+	return i + (j + k*res)*res;
+}
+
+BLI_INLINE int hair_grid_interp_weights(int res, const float gmin[3], const float scale[3], const float vec[3], float uvw[3])
+{
+	int i, j, k, offset;
+	
+	i = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 0);
+	j = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 1);
+	k = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 2);
+	offset = i + (j + k*res)*res;
+	
+	uvw[0] = (vec[0] - gmin[0]) / scale[0] - (float)i;
+	uvw[1] = (vec[1] - gmin[1]) / scale[1] - (float)j;
+	uvw[2] = (vec[2] - gmin[2]) / scale[2] - (float)k;
+	
+	return offset;
+}
+
+BLI_INLINE void hair_grid_interpolate(const HairGridVert *grid, int res, const float gmin[3], const float scale[3], const float vec[3],
+                                      float *density, float velocity[3], float density_gradient[3])
+{
+	HairGridVert data[8];
+	float uvw[3], muvw[3];
+	int res2 = res * res;
+	int offset;
+	
+	offset = hair_grid_interp_weights(res, gmin, scale, vec, uvw);
+	muvw[0] = 1.0f - uvw[0];
+	muvw[1] = 1.0f - uvw[1];
+	muvw[2] = 1.0f - uvw[2];
+	
+	data[0] = grid[offset           ];
+	data[1] = grid[offset         +1];
+	data[2] = grid[offset     +res  ];
+	data[3] = grid[offset     +res+1];
+	data[4] = grid[offset+res2      ];
+	data[5] = grid[offset+res2    +1];
+	data[6] = grid[offset+res2+res  ];
+	data[7] = grid[offset+res2+res+1];
+	
+	if (density) {
+		*density = muvw[2]*( muvw[1]*( muvw[0]*data[0].density + uvw[0]*data[1].density )   +
+		                      uvw[1]*( muvw[0]*data[2].density + uvw[0]*data[3].density ) ) +
+		            uvw[2]*( muvw[1]*( muvw[0]*data[4].density + uvw[0]*data[5].density )   +
+		                      uvw[1]*( muvw[0]*data[6].density + uvw[0]*data[7].density ) );
+	}
+	if (velocity) {
+		int k;
+		for (k = 0; k < 3; ++k) {
+			velocity[k] = muvw[2]*( muvw[1]*( muvw[0]*data[0].velocity[k] + uvw[0]*data[1].velocity[k] )   +
+			                         uvw[1]*( muvw[0]*data[2].velocity[k] + uvw[0]*data[3].velocity[k] ) ) +
+			               uvw[2]*( muvw[1]*( muvw[0]*data[4].velocity[k] + uvw[0]*data[5].velocity[k] )   +
+			                         uvw[1]*( muvw[0]*data[6].velocity[k] + uvw[0]*data[7].velocity[k] ) );
+		}
+	}
+	if (density_gradient) {
+		density_gradient[0] = muvw[1] * muvw[2] * ( data[0].density - data[1].density ) +
+		                       uvw[1] * muvw[2] * ( data[2].density - data[3].density ) +
+		                      muvw[1] *  uvw[2] * ( data[4].density - data[5].density ) +
+		                       uvw[1] *  uvw[2] * ( data[6].density - data[7].density );
+		
+		density_gradient[1] = muvw[2] * muvw[0] * ( data[0].density - data[2].density ) +
+		                       uvw[2] * muvw[0] * ( data[4].density - data[6].density ) +
+		                      muvw[2] *  uvw[0] * ( data[1].density - data[3].density ) +
+		                       uvw[2] *  uvw[0] * ( data[5].density - data[7].density );
+		
+		density_gradient[2] = muvw[2] * muvw[0] * ( data[0].density - data[4].density ) +
+		                       uvw[2] * muvw[0] * ( data[1].density - data[5].density ) +
+		                      muvw[2] *  uvw[0] * ( data[2].density - data[6].density ) +
+		                       uvw[2] *  uvw[0] * ( data[3].density - data[7].density );
+	}
+}
+
+static void hair_velocity_smoothing(const HairGridVert *hairgrid, const float gmin[3], const float scale[3], float smoothfac,
+                                    lfVector *lF, lfVector *lX, lfVector *lV, unsigned int numverts)
+{
+	int v;
+	/* calculate forces */
+	for (v = 0; v < numverts; v++) {
+		float density, velocity[3];
+		
+		hair_grid_interpolate(hairgrid, hair_grid_res, gmin, scale, lX[v], &density, velocity, NULL);
+		
+		sub_v3_v3(velocity, lV[v]);
+		madd_v3_v3fl(lF[v], velocity, smoothfac);
+	}
+}
+
+static void hair_velocity_collision(const HairGridVert *collgrid, const float gmin[3], const float scale[3], float collfac,
+                                    lfVector *lF, lfVector *lX, lfVector *lV, unsigned int numverts)
+{
+	int v;
+	/* calculate forces */
+	for (v = 0; v < numverts; v++) {
+		int offset = hair_grid_offset(lX[v], hair_grid_res, gmin, scale);
+		
+		if (collgrid[offset].density > 0.0f) {
+			lF[v][0] += collfac * (collgrid[offset].velocity[0] - lV[v][0]);
+			lF[v][1] += collfac * (collgrid[offset].velocity[1] - lV[v][1]);
+			lF[v][2] += collfac * (collgrid[offset].velocity[2] - lV[v][2]);
+		}
+	}
+}
+
+static void hair_pressure_force(const HairGridVert *hairgrid, const float gmin[3], const float scale[3], float pressurefac, float minpressure,
+                                lfVector *lF, lfVector *lX, unsigned int numverts)
+{
+	int v;
+	
+	/* calculate forces */
+	for (v = 0; v < numverts; v++) {
+		float density, gradient[3], gradlen;
+		
+		hair_grid_interpolate(hairgrid, hair_grid_res, gmin, scale, lX[v], &density, NULL, gradient);
+		
+		gradlen = normalize_v3(gradient) - minpressure;
+		if (gradlen < 0.0f)
+			continue;
+		mul_v3_fl(gradient, gradlen);
+		
+		madd_v3_v3fl(lF[v], gradient, pressurefac);
+	}
+}
+
+static void hair_volume_get_boundbox(lfVector *lX, unsigned int numverts, float gmin[3], float gmax[3])
+{
+	int i;
+	
+	INIT_MINMAX(gmin, gmax);
+	for (i = 0; i < numverts; i++)
+		DO_MINMAX(lX[i], gmin, gmax);
+}
+
+BLI_INLINE bool hair_grid_point_valid(const float vec[3], float gmin[3], float gmax[3])
+{
+	return !(vec[0] < gmin[0] || vec[1] < gmin[1] || vec[2] < gmin[2] ||
+	         vec[0] > gmax[0] || vec[1] > gmax[1] || vec[2] > gmax[2]);
+}
+
+BLI_INLINE float dist_tent_v3f3(const float a[3], float x, float y, float z)
+{
+	float w = (1.0f - fabsf(a[0] - x)) * (1.0f - fabsf(a[1] - y)) * (1.0f - fabsf(a[2] - z));
+	return w;
+}
+
+/* returns the grid array offset as well to avoid redundant calculation */
+static int hair_grid_weights(int res, const float gmin[3], const float scale[3], const float vec[3], float weights[8])
+{
+	int i, j, k, offset;
+	float uvw[3];
+	
+	i = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 0);
+	j = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 1);
+	k = HAIR_GRID_INDEX_AXIS(vec, res, gmin, scale, 2);
+	offset = i + (j + k*res)*res;
+	
+	uvw[0] = (vec[0] - gmin[0]) / scale[0];
+	uvw[1] = (vec[1] - gmin[1]) / scale[1];
+	uvw[2] = (vec[2] - gmin[2]) / scale[2];
+	
+	weights[0] = dist_tent_v3f3(uvw, (float)i    , (float)j    , (float)k    );
+	weights[1] = dist_tent_v3f3(uvw, (float)(i+1), (float)j    , (float)k    );
+	weights[2] = dist_tent_v3f3(uvw, (float)i    , (float)(j+1), (float)k    );
+	weights[3] = dist_tent_v3f3(uvw, (float)(i+1), (float)(j+1), (float)k    );
+	weights[4] = dist_tent_v3f3(uvw, (float)i    , (float)j    , (float)(k+1));
+	weights[5] = dist_tent_v3f3(uvw, (float)(i+1), (float)j    , (float)(k+1));
+	weights[6] = dist_tent_v3f3(uvw, (float)i    , (float)(j+1), (float)(k+1));
+	weights[7] = dist_tent_v3f3(uvw, (float)(i+1), (float)(j+1), (float)(k+1));
+	
+	return offset;
+}
+
+stat

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list