[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