[Bf-blender-cvs] [81a26cc] hair_system: Use the hair root normal for setting up the reference frames.
Lukas Tönne
noreply at git.blender.org
Thu Aug 7 15:23:06 CEST 2014
Commit: 81a26ccf91bfed4b3577a960878e53b75e9bc197
Author: Lukas Tönne
Date: Thu Aug 7 14:23:03 2014 +0200
Branches: hair_system
https://developer.blender.org/rB81a26ccf91bfed4b3577a960878e53b75e9bc197
Use the hair root normal for setting up the reference frames.
Currently the tangent is generated simply by projecting the Z-axis,
eventually we need to have a user-defined tangent space of some kind for
this.
===================================================================
M source/blender/blenkernel/intern/object.c
M source/blender/editors/physics/hair_ops.c
M source/blender/hair/intern/HAIR_curve.h
M source/blender/hair/intern/HAIR_math.cpp
M source/blender/hair/intern/HAIR_math.h
M source/blender/hair/intern/HAIR_scene.cpp
M source/blender/hair/intern/HAIR_smoothing.h
M source/blender/hair/intern/HAIR_solver.cpp
M source/blender/hair/intern/HAIR_types.h
M source/blender/makesdna/DNA_hair_types.h
===================================================================
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 70513cb..96612ff 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -3121,9 +3121,12 @@ void BKE_object_sim_tick(Scene *UNUSED(scene), Object *ob, float ctime, float ti
if (md->type == eModifierType_Hair) {
HairModifierData *hmd = (HairModifierData*) md;
-#if 0 /* debugging? */
+#if 0
HAIR_solver_step(hmd->solver, ctime, timestep);
#else
+ /* Debug Version
+ * WARNING: Debugging is not threadsafe atm, crashes with large hair numbers (>1024)!
+ */
float imat[4][4];
invert_m4_m4(imat, ob->obmat);
diff --git a/source/blender/editors/physics/hair_ops.c b/source/blender/editors/physics/hair_ops.c
index 6768340..4d07680 100644
--- a/source/blender/editors/physics/hair_ops.c
+++ b/source/blender/editors/physics/hair_ops.c
@@ -45,6 +45,7 @@
#include "BKE_context.h"
#include "BKE_DerivedMesh.h"
#include "BKE_hair.h"
+#include "BKE_mesh_sample.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_particle.h"
@@ -203,6 +204,7 @@ static void hair_copy_from_particles_psys(Object *ob, HairSystem *hsys, Particle
HairCurve *hair = hairs + i;
HairPoint *points;
int totpoints;
+ float loc[3], tan[3];
if (pa_cache->steps == 0)
continue;
@@ -211,6 +213,9 @@ static void hair_copy_from_particles_psys(Object *ob, HairSystem *hsys, Particle
points = BKE_hair_point_append_multi(hsys, hair, totpoints);
hair_copy_particle_emitter_location(ob, psys, root, dm, &hair->root);
+ BKE_mesh_sample_eval(dm, &hair->root, loc, hair->rest_nor);
+ tan[0] = 0.0f; tan[1] = 0.0f; tan[2] = 1.0f;
+ madd_v3_v3v3fl(hair->rest_tan, tan, hair->rest_nor, -dot_v3v3(tan, hair->rest_nor));
for (k = 0; k < totpoints; ++k) {
ParticleCacheKey *pa_key = pa_cache + k;
diff --git a/source/blender/hair/intern/HAIR_curve.h b/source/blender/hair/intern/HAIR_curve.h
index a954de9..ca75700 100644
--- a/source/blender/hair/intern/HAIR_curve.h
+++ b/source/blender/hair/intern/HAIR_curve.h
@@ -67,6 +67,7 @@ struct Point {
struct CurveRoot {
float3 co;
float3 nor;
+ float3 tan;
};
struct Curve {
@@ -77,7 +78,8 @@ struct Curve {
int totpoints;
float avg_rest_length;
- CurveRoot root0, root1;
+ CurveRoot root0, root1; /* root data at start and end of the time interval */
+ float3 rest_root_normal, rest_root_tangent;
HAIR_CXX_CLASS_ALLOC(Curve)
};
diff --git a/source/blender/hair/intern/HAIR_math.cpp b/source/blender/hair/intern/HAIR_math.cpp
index a89036b..3f7fe2d 100644
--- a/source/blender/hair/intern/HAIR_math.cpp
+++ b/source/blender/hair/intern/HAIR_math.cpp
@@ -24,7 +24,10 @@
* ***** END GPL LICENSE BLOCK *****
*/
+#include <stdlib.h>
#include <cstring>
+#include <limits>
+#include <cfloat>
extern "C" {
#include "BLI_utildefines.h"
@@ -34,6 +37,63 @@ extern "C" {
HAIR_NAMESPACE_BEGIN
+
+/**
+ * Generic function for implementing slerp
+ * (quaternions and spherical vector coords).
+ *
+ * \param t: factor in [0..1]
+ * \param cosom: dot product from normalized vectors/quats.
+ * \param r_w: calculated weights.
+ */
+static float2 interp_dot_slerp(float t, float cosom)
+{
+ const float eps = 1e-4f;
+
+ float2 w;
+
+ BLI_assert(IN_RANGE_INCL(cosom, -1.0001f, 1.0001f));
+
+ /* within [-1..1] range, avoid aligned axis */
+ if (LIKELY(fabsf(cosom) < (1.0f - eps))) {
+ float omega, sinom;
+
+ omega = acosf(cosom);
+ sinom = sinf(omega);
+ w[0] = sinf((1.0f - t) * omega) / sinom;
+ w[1] = sinf(t * omega) / sinom;
+ }
+ else {
+ /* fallback to lerp */
+ w[0] = 1.0f - t;
+ w[1] = t;
+ }
+
+ return w;
+}
+
+bool interp_v3v3_slerp(float3 &r, const float3 &a, const float3 &b, float t)
+{
+// BLI_ASSERT_UNIT_V3(a);
+// BLI_ASSERT_UNIT_V3(b);
+
+ float cosom = dot_v3v3(a, b);
+
+ /* direct opposites */
+ if (UNLIKELY(cosom < (-1.0f + FLT_EPSILON))) {
+ return false;
+ }
+
+ float2 w = interp_dot_slerp(t, cosom);
+
+ r = float3(w.x * a.x + w.y * b.x,
+ w.x * a.y + w.y * b.y,
+ w.x * a.z + w.y * b.z);
+
+ return true;
+}
+
+
static bool transform_matrix4_gj_inverse(float R[][4], float M[][4])
{
/* forward elimination */
diff --git a/source/blender/hair/intern/HAIR_math.h b/source/blender/hair/intern/HAIR_math.h
index ef4474c..b232b3e 100644
--- a/source/blender/hair/intern/HAIR_math.h
+++ b/source/blender/hair/intern/HAIR_math.h
@@ -157,6 +157,11 @@ __forceinline float normalize_v3_v3(float3 &r, const float3 &v)
return len;
}
+/**
+ * slerp, treat vectors as spherical coordinates
+ */
+bool interp_v3v3_slerp(float3 &r, const float3 &a, const float3 &b, float t);
+
/* quaternion functions */
__forceinline float3 mul_qt_v3(const float4 &q, const float3 &v)
diff --git a/source/blender/hair/intern/HAIR_scene.cpp b/source/blender/hair/intern/HAIR_scene.cpp
index d09761b..a00dc6b 100644
--- a/source/blender/hair/intern/HAIR_scene.cpp
+++ b/source/blender/hair/intern/HAIR_scene.cpp
@@ -88,8 +88,12 @@ SolverData *SceneConverter::build_solver_data(Scene *scene, Object *ob, DerivedM
*curve = Curve(hair->totpoints, point);
mesh_sample_eval(dm, mat, &hair->root, curve->root1.co, curve->root1.nor);
+ normalize_v3_v3(curve->root1.tan, float3(0,0,1) - dot_v3v3(float3(0,0,1), curve->root1.nor) * curve->root1.nor);
curve->root0 = curve->root1;
+ curve->rest_root_normal = float3(hair->rest_nor);
+ curve->rest_root_tangent = float3(hair->rest_tan);
+
for (int k = 0; k < hair->totpoints; ++k, ++point) {
HairPoint *hair_pt = hair->points + k;
diff --git a/source/blender/hair/intern/HAIR_smoothing.h b/source/blender/hair/intern/HAIR_smoothing.h
index 2443a64..feb4952 100644
--- a/source/blender/hair/intern/HAIR_smoothing.h
+++ b/source/blender/hair/intern/HAIR_smoothing.h
@@ -119,6 +119,7 @@ struct FrameIterator {
m_loc_iter(walker, rest_length, amount),
m_frame(initial_frame)
{
+ m_dir = initial_frame.normal;
}
int index() const { return m_loc_iter.index(); }
@@ -128,33 +129,25 @@ struct FrameIterator {
{
static const float epsilon = 1.0e-6;
- if (index() == 0) {
- float3 prev_co = m_loc_iter.get();
- m_loc_iter.next();
- float3 co = m_loc_iter.get();
- normalize_v3_v3(m_dir, co - prev_co);
- }
- else {
- float3 prev_dir = m_dir;
-
- float3 prev_co = m_loc_iter.get();
- m_loc_iter.next();
- float3 co = m_loc_iter.get();
- normalize_v3_v3(m_dir, co - prev_co);
-
- float3 C = cross_v3_v3(prev_dir, m_dir);
- float D = dot_v3v3(prev_dir, m_dir);
- if (D > epsilon && fabsf(D) < 1.0f - epsilon) {
- /* half angle sine, cosine */
- D = sqrtf((1.0f + D) * 0.5f);
- C = C / D * 0.5f;
- /* construct rotation from one segment to the next */
- float4 rot(C.x, C.y, C.z, D);
- /* apply the local rotation to the frame axes */
- m_frame.normal = mul_qt_v3(rot, m_frame.normal);
- m_frame.tangent = mul_qt_v3(rot, m_frame.tangent);
- m_frame.cotangent = mul_qt_v3(rot, m_frame.cotangent);
- }
+ float3 prev_dir = m_dir;
+
+ float3 prev_co = m_loc_iter.get();
+ m_loc_iter.next();
+ float3 co = m_loc_iter.get();
+ normalize_v3_v3(m_dir, co - prev_co);
+
+ float3 C = cross_v3_v3(prev_dir, m_dir);
+ float D = dot_v3v3(prev_dir, m_dir);
+ if (D > epsilon && fabsf(D) < 1.0f - epsilon) {
+ /* half angle sine, cosine */
+ D = sqrtf((1.0f + D) * 0.5f);
+ C = C / D * 0.5f;
+ /* construct rotation from one segment to the next */
+ float4 rot(C.x, C.y, C.z, D);
+ /* apply the local rotation to the frame axes */
+ m_frame.normal = mul_qt_v3(rot, m_frame.normal);
+ m_frame.tangent = mul_qt_v3(rot, m_frame.tangent);
+ m_frame.cotangent = mul_qt_v3(rot, m_frame.cotangent);
}
}
diff --git a/source/blender/hair/intern/HAIR_solver.cpp b/source/blender/hair/intern/HAIR_solver.cpp
index 830357e..174ba35 100644
--- a/source/blender/hair/intern/HAIR_solver.cpp
+++ b/source/blender/hair/intern/HAIR_solver.cpp
@@ -126,10 +126,8 @@ void SolverData::precompute_rest_bend(const HairParams ¶ms)
else if (curve->totpoints == 1)
pt->rest_bend = float3(0.0f, 0.0f, 0.0f);
else {
- /* XXX calculating a rest frame ad-hoc from identity here, should use the surface normal/tangent instead! */
- float3 normal, tangent;
- normalize_v3_v3(normal, next_pt->rest_co - pt->rest_co);
- normalize_v3_v3(tangent, float3(0,1,0) - dot_v3v3(float3(0,1,0), normal) * normal);
+
+ float3 normal = curve->rest_root_normal, tangent = curve->rest_root_tangent;
Frame rest_frame(normal, tangent, cross_v3_v3(normal, tangent));
FrameIterator<SolverDataRestLocWalker> iter(SolverDataRestLocWalker(curve), curve->avg_rest_length, params.bend_smoothing, rest_frame);
@@ -287,7 +285,7 @@ void Solver::free_data()
}
}
-static void calc_root_animation(float t0, float t1, float t, Curve *curve, float3 &co, float3 &vel)
+static void calc_root_animation(float t0, float t1, float t, Curve *curve, float3 &co, float3 &vel, float3 &normal, float3 &tangent)
{
const CurveRoot &root0 = curve->root0;
const CurveRoot &root1 = curve->root1;
@@ -298,10 +296,14 @@ static void calc_root_animation(float t0, float t1, float t, Curve *curve, float
co = root0.co * mx + root1.co * x;
vel = (root1.co - root0.co) / (t1 - t0);
+ interp_v3v3_slerp(normal, root0.nor, root1.nor, x);
+ interp_v3v3_slerp(tangent, root0.tan, root1.tan, x);
}
else {
co = root0.co;
vel = float3(0.0f, 0.0f, 0.0f);
+ normal = root0.nor;
+ tangent = root0.tan;
}
}
@@ -383,17 +385,9 @@ static void step(const HairParams ¶ms, const SolverForces &forces, float tim
/* note: roots are evaluated at the end of the timestep: time + timestep
* so the hair points align perfectly with them
*/
- calc_root_animation(t0, t1, time + timestep, curve, point->next.co, point->next.vel);
-
float3 normal, tangent;
- if (numpoints >= 2) {
- normalize_v3_v3(normal, (point+1)->cur.co - point->cur.co);
- normalize_v3_v3(tangent, float3(0,1,0) - dot_v3v3(float3(0,1,0), normal) * normal);
- }
- else {
- normal = float3(1,0,0);
- tangent = float3(0,1,0);
- }
+ calc_root_animation(t0, t1, time + timestep,
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list