[Bf-blender-cvs] [32479d2] temp_hair_flow: First step toward hair directional flow solving: Calculate divergence from "source" (emitter) meshes.

Lukas Tönne noreply at git.blender.org
Wed Jan 7 19:37:43 CET 2015


Commit: 32479d290adcb3df70558129ec7966666cc456b4
Author: Lukas Tönne
Date:   Wed Jan 7 19:31:14 2015 +0100
Branches: temp_hair_flow
https://developer.blender.org/rB32479d290adcb3df70558129ec7966666cc456b4

First step toward hair directional flow solving: Calculate divergence
from "source" (emitter) meshes.

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

M	source/blender/editors/hair/hair_flow.c
M	source/blender/physics/BPH_strands.h
M	source/blender/physics/intern/eigen_utils.h
M	source/blender/physics/intern/grid.cpp
M	source/blender/physics/intern/grid.h
M	source/blender/physics/intern/hair_flow.cpp

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

diff --git a/source/blender/editors/hair/hair_flow.c b/source/blender/editors/hair/hair_flow.c
index 40d4ea5..17a4322 100644
--- a/source/blender/editors/hair/hair_flow.c
+++ b/source/blender/editors/hair/hair_flow.c
@@ -69,7 +69,7 @@ static int hair_solve_flow_exec(bContext *C, wmOperator *op)
 	int segments = RNA_int_get(op->ptr, "segments");
 	int res = RNA_int_get(op->ptr, "resolution");
 	
-	struct HairFlowData *data = BPH_strands_solve_hair_flow(scene, ob, max_length, res);
+	struct HairFlowData *data = BPH_strands_solve_hair_flow(scene, ob, max_length, res, edit->debug_data);
 	if (data) {
 		/* remove existing hair strands */
 		BM_mesh_clear(edit->bm);
diff --git a/source/blender/physics/BPH_strands.h b/source/blender/physics/BPH_strands.h
index f2b1b16..3d1965d 100644
--- a/source/blender/physics/BPH_strands.h
+++ b/source/blender/physics/BPH_strands.h
@@ -35,6 +35,7 @@ extern "C" {
 struct Object;
 struct Scene;
 struct BMEditStrands;
+struct SimDebugData;
 
 void BPH_strands_solve_constraints(struct Object *ob, struct BMEditStrands *es, float (*orig)[3]);
 
@@ -42,7 +43,7 @@ void BPH_strands_solve_constraints(struct Object *ob, struct BMEditStrands *es,
 
 struct HairFlowData;
 
-struct HairFlowData *BPH_strands_solve_hair_flow(struct Scene *scene, struct Object *ob, float max_length, int max_res);
+struct HairFlowData *BPH_strands_solve_hair_flow(struct Scene *scene, struct Object *ob, float max_length, int max_res, struct SimDebugData *debug_data);
 void BPH_strands_free_hair_flow(struct HairFlowData *data);
 
 void BPH_strands_sample_hair_flow(struct Object *ob, struct BMEditStrands *edit, struct HairFlowData *data,
diff --git a/source/blender/physics/intern/eigen_utils.h b/source/blender/physics/intern/eigen_utils.h
index 79c73c4..6d8351a 100644
--- a/source/blender/physics/intern/eigen_utils.h
+++ b/source/blender/physics/intern/eigen_utils.h
@@ -145,6 +145,69 @@ public:
 	}
 };
 
+/* utility struct that can be converted to float* implicitly for BLI math */
+struct float3 {
+	float x, y, z;
+	
+	float3() {}
+	float3(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}
+	float3(float *data) : x(data[0]), y(data[1]), z(data[2]) {}
+	
+	inline float operator[](int i) const { return *(&x + i); }
+	inline float& operator[](int i) { return *(&x + i); }
+	
+	inline operator float*() { return &x; }
+	inline operator const float*() const { return &x; }
+};
+
+/* Extension of sparse Eigen vectors,
+ * providing 3-float block access for blenlib math functions
+ */
+class sVector3 : public Eigen::SparseVector<Scalar> {
+public:
+	typedef Eigen::SparseVector<Scalar> base_t;
+	
+	struct Iterator {
+		Iterator(const sVector3 &vec) :
+		    m_iter(vec),
+		    m_index(0)
+		{
+		}
+		
+		inline Iterator& operator++() { ++m_iter; ++m_iter; ++m_iter; ++m_index; return *this; }
+		
+		inline const float* value() const { return &const_cast<base_t::InnerIterator&>(m_iter).valueRef(); }
+		inline float* valueRef() { return &m_iter.valueRef(); }
+		
+		inline Index index() const { return m_index; }
+		
+		inline operator bool() const { return m_iter; }
+		
+	private:
+		typename base_t::InnerIterator m_iter;
+		int m_index;
+	};
+	
+	sVector3()
+	{
+	}
+	
+	template <typename T>
+	sVector3& operator = (T rhs)
+	{
+		base_t::operator=(rhs);
+		return *this;
+	}
+	
+	/* Warning: involves a binary search!
+	 * Use the Iterator type if possible.
+	 */
+	float* v3(int vertex)
+	{
+		return &coeffRef(3 * vertex);
+	}
+};
+
 typedef Eigen::Triplet<Scalar> Triplet;
 typedef std::vector<Triplet> TripletList;
 
diff --git a/source/blender/physics/intern/grid.cpp b/source/blender/physics/intern/grid.cpp
index 18223ab..51fddb8 100644
--- a/source/blender/physics/intern/grid.cpp
+++ b/source/blender/physics/intern/grid.cpp
@@ -32,7 +32,13 @@
 #include "MEM_guardedalloc.h"
 
 extern "C" {
+#include "BLI_kdopbvh.h"
 #include "BLI_math.h"
+
+#include "DNA_object_types.h"
+
+#include "BKE_bvhutils.h"
+#include "BKE_cdderivedmesh.h"
 }
 
 #include "grid.h"
@@ -54,14 +60,15 @@ Grid::~Grid()
 
 void Grid::resize(float _cellsize, const float _offset[3], const int _res[3])
 {
+	BLI_assert(_cellsize >= 0.0f);
 	cellsize = _cellsize;
 	inv_cellsize = 1.0f / _cellsize;
 	copy_v3_v3(offset, _offset);
 	copy_v3_v3_int(res, _res);
 	num_cells = _res[0] * _res[1] * _res[2];
 	
-	divergence = lVector(num_cells);
-	pressure = lVector(num_cells);
+	divergence.resize(num_cells);
+	pressure.resize(num_cells);
 }
 
 void Grid::init()
@@ -74,6 +81,149 @@ void Grid::clear()
 	pressure.setZero();
 }
 
+int Grid::set_inner_cells(GridHash<bool> &bounds, GridHash<float3> &normal, Object *ob) const
+{
+	DerivedMesh *ob_dm = ob->derivedFinal;
+	if (!ob_dm)
+		return 0;
+	
+	DerivedMesh *dm = NULL;
+	MVert *mvert;
+//	MFace *mface;
+	BVHTreeFromMesh treeData = {NULL};
+	int numverts, i;
+	float gridmat[4][4], mat[4][4];
+	
+	float surface_distance = 0.6;
+	int tot_inner = 0;
+	
+	/* grid->world space conversion */
+	zero_m4(gridmat);
+	gridmat[0][0] = cellsize;
+	gridmat[1][1] = cellsize;
+	gridmat[2][2] = cellsize;
+	gridmat[3][3] = 1.0f;
+	copy_v3_v3(gridmat[3], offset);
+	/* object->grid space conversion */
+	invert_m4_m4(mat, gridmat);
+	mul_m4_m4m4(mat, mat, ob->obmat);
+	
+	/* local copy of dm for storing grid space mesh */
+	dm = CDDM_copy(ob_dm);
+	CDDM_calc_normals(dm);
+	mvert = dm->getVertArray(dm);
+//	mface = dm->getTessFaceArray(dm);
+	numverts = dm->getNumVerts(dm);
+	
+	/* transform vertices to grid space for fast lookups */
+	for (i = 0; i < numverts; i++) {
+		float n[3];
+		
+		/* vert pos */
+		mul_m4_v3(mat, mvert[i].co);
+		
+		/* vert normal */
+		normal_short_to_float_v3(n, mvert[i].no);
+		mul_mat3_m4_v3(mat, n);
+		normalize_v3(n);
+		normal_float_to_short_v3(mvert[i].no, n);
+	}
+	
+	if (bvhtree_from_mesh_faces(&treeData, dm, 0.0f, 4, 6)) {
+		int xmax = res[0];
+		int ymax = res[1];
+		int zmax = res[2];
+//#pragma omp parallel for schedule(static)
+		for (int z = 0; z < zmax; z++) {
+			for (int x = 0; x < xmax; x++) {
+				for (int y = 0; y < ymax; y++) {
+					float ray_start[3] = {(float)x + 0.5f, (float)y + 0.5f, (float)z + 0.5f};
+					BVHTreeNearest nearest = {0};
+					nearest.index = -1;
+					nearest.dist_sq = surface_distance * surface_distance; /* find_nearest uses squared distance */
+					
+					/* find the nearest point on the mesh */
+					if (BLI_bvhtree_find_nearest(treeData.tree, ray_start, &nearest, treeData.nearest_callback, &treeData) != -1) {
+#if 0
+						float weights[4];
+						int v1, v2, v3, f_index = nearest.index;
+						
+						/* calculate barycentric weights for nearest point */
+						v1 = mface[f_index].v1;
+						v2 = (nearest.flags & BVH_ONQUAD) ? mface[f_index].v3 : mface[f_index].v2;
+						v3 = (nearest.flags & BVH_ONQUAD) ? mface[f_index].v4 : mface[f_index].v3;
+						interp_weights_face_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, NULL, nearest.co);
+#endif
+						
+						/* tag obstacle cells */
+						*bounds.get(x, y, z) = true;
+						copy_v3_v3(*normal.get(x, y, z), nearest.no);
+						++tot_inner;
+					}
+				}
+			}
+		}
+	}
+	
+	/* free bvh tree */
+	free_bvhtree_from_mesh(&treeData);
+	
+	/* free world space dm copy */
+	dm->release(dm);
+	
+	return tot_inner;
+}
+
+void Grid::calc_divergence(GridHash<float> &divergence, const GridHash<bool> &source, const GridHash<float3> &source_normal) const
+{
+	const float flowfac = cellsize;
+	
+	divergence.clear();
+	
+	int xmax = res[0];
+	int ymax = res[1];
+	int zmax = res[2];
+	for (int z = 0; z < zmax; z++) {
+		for (int x = 0; x < xmax; x++) {
+			for (int y = 0; y < ymax; y++) {
+				const bool *sl = source.get(x-1, y, z);
+				const bool *sr = source.get(x+1, y, z);
+				const bool *sb = source.get(x, y-1, z);
+				const bool *st = source.get(x, y+1, z);
+				const bool *sd = source.get(x, y, z-1);
+				const bool *su = source.get(x, y, z+1);
+				const bool is_margin = !(sl && sr && sb && st && sd && su);
+				if (is_margin)
+					continue;
+				
+				const float3 n = *source_normal.get(x, y, z);
+				const float3 *nl = sl && *sl ? source_normal.get(x-1, y, z) : NULL;
+				const float3 *nr = sr && *sr ? source_normal.get(x+1, y, z) : NULL;
+				const float3 *nb = sb && *sb ? source_normal.get(x, y-1, z) : NULL;
+				const float3 *nt = st && *st ? source_normal.get(x, y+1, z) : NULL;
+				const float3 *nd = sd && *sd ? source_normal.get(x, y, z-1) : NULL;
+				const float3 *nu = su && *su ? source_normal.get(x, y, z+1) : NULL;
+				
+				float dx = 0.0f, dy = 0.0f, dz = 0.0f;
+				if (nl)
+					dx += n[0] - (*nl)[0];
+				if (nr)
+					dx += (*nr)[0] - n[0];
+				if (nb)
+					dy += n[1] - (*nb)[1];
+				if (nt)
+					dy += (*nt)[1] - n[1];
+				if (nd)
+					dz += n[2] - (*nd)[2];
+				if (nu)
+					dz += (*nu)[2] - n[2];
+				
+				divergence.add(x, y, z) -= 0.5f * flowfac * (dx + dy + dz);
+			}
+		}
+	}
+}
+
 } /* namespace BPH */
 
 #include "implicit.h"
diff --git a/source/blender/physics/intern/grid.h b/source/blender/physics/intern/grid.h
index 829d944..fce336b 100644
--- a/source/blender/physics/intern/grid.h
+++ b/source/blender/physics/intern/grid.h
@@ -32,12 +32,85 @@
  *  \ingroup bph
  */
 
+#include "MEM_guardedalloc.h"
+
 #include "BLI_utildefines.h"
+#include "BLI_math.h"
 
 #include "eigen_utils.h"
 
 namespace BPH {
 
+template <typename T>
+struct GridHash {
+	GridHash() :
+	    m_data(NULL),
+	    m_size(0)
+	{
+		zero_v3_int(m_stride);
+		zero_v3_int(m_res);
+	}
+	
+	~GridHash()
+	{
+		if (m_data)
+			MEM_freeN(m_data);
+	}
+	
+	void resize(const int res[3])
+	{
+		if (m_data)
+			MEM_freeN(m_data);
+		
+		copy_v3_v3_int(m_res, res);
+		m_stride[0] = 1;
+		m_stride[1] = res[0];
+		m_stride[2] = res[0] * res[1];
+		m_size      = res[0] * res[1] * res[2];
+		
+		m_data = (T *)MEM_mallocN(sizeof(T) * m_size, "grid hash data");
+	}
+	
+	void clear()
+	{
+		memset(m_data, 0, sizeof(T) * m_size);
+	}
+	
+	inline T* get(int x, int y, int z)
+	{
+		if (x >= 0 && x < m_res[0] && y >= 0 && y < m_res[1] && z >= 0 && z < m_res[2])
+			return m_data + x + y * m_stride[1] + z * m_stride[2];
+		else
+			return NULL;
+	}
+	
+	inline const T* get(int x, int y, int z) const
+	{
+		if (x >= 0 && x < m_res[0] && y >= 0 && y < m_res[1] && z >= 0 && z < m

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list