[Bf-blender-cvs] [47fb3c6] hair_system: Partial fix for bending force issues: was missing vector normalization.
Lukas Tönne
noreply at git.blender.org
Thu Aug 21 11:56:24 CEST 2014
Commit: 47fb3c6c5f1255e6193bb3103651e446908bbb10
Author: Lukas Tönne
Date: Thu Aug 21 11:57:08 2014 +0200
Branches: hair_system
https://developer.blender.org/rB47fb3c6c5f1255e6193bb3103651e446908bbb10
Partial fix for bending force issues: was missing vector normalization.
===================================================================
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
===================================================================
diff --git a/source/blender/hair/intern/HAIR_math.cpp b/source/blender/hair/intern/HAIR_math.cpp
index 3f7fe2d..8255c31 100644
--- a/source/blender/hair/intern/HAIR_math.cpp
+++ b/source/blender/hair/intern/HAIR_math.cpp
@@ -29,10 +29,6 @@
#include <limits>
#include <cfloat>
-extern "C" {
-#include "BLI_utildefines.h"
-}
-
#include "HAIR_math.h"
HAIR_NAMESPACE_BEGIN
diff --git a/source/blender/hair/intern/HAIR_math.h b/source/blender/hair/intern/HAIR_math.h
index d503f21..6310e7d 100644
--- a/source/blender/hair/intern/HAIR_math.h
+++ b/source/blender/hair/intern/HAIR_math.h
@@ -33,6 +33,10 @@
#include <math.h>
+extern "C" {
+#include "BLI_utildefines.h"
+}
+
#include "HAIR_types.h"
HAIR_NAMESPACE_BEGIN
@@ -217,6 +221,27 @@ __forceinline float4 mul_qt_v4(const float4 &q, const float4 &v)
return r;
}
+__forceinline float4 rotation_between_vecs_to_quat(const float3 a, const float3 b)
+{
+ static const float epsilon = 1.0e-6;
+
+ float3 na, nb;
+ normalize_v3_v3(na, a);
+ normalize_v3_v3(nb, b);
+ float3 C = cross_v3_v3(na, nb);
+ float D = dot_v3v3(na, nb);
+
+ if (fabsf(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 quaternion */
+ return float4(C.x, C.y, C.z, D);
+ }
+ else
+ return unit_qt;
+}
+
/* matrix arithmetic */
__forceinline Transform operator + (const Transform &a, const Transform &b)
diff --git a/source/blender/hair/intern/HAIR_scene.cpp b/source/blender/hair/intern/HAIR_scene.cpp
index 1b394a2..f8729cd 100644
--- a/source/blender/hair/intern/HAIR_scene.cpp
+++ b/source/blender/hair/intern/HAIR_scene.cpp
@@ -47,7 +47,7 @@ extern "C" {
HAIR_NAMESPACE_BEGIN
-static bool mesh_sample_eval(DerivedMesh *dm, const Transform &tfm, MSurfaceSample *sample, float3 &loc, float3 &nor)
+static bool mesh_sample_eval_transformed(DerivedMesh *dm, const Transform &tfm, MSurfaceSample *sample, float3 &loc, float3 &nor)
{
float vloc[3], vnor[3];
@@ -88,13 +88,16 @@ SolverData *SceneConverter::build_solver_data(Scene *scene, Object *ob, DerivedM
Curve *curve = solver_curves + i;
*curve = Curve(hair->totpoints, point);
- mesh_sample_eval(dm, mat, &hair->root, curve->root1.co, curve->root1.nor);
+ mesh_sample_eval_transformed(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->avg_rest_length = hair->avg_rest_length;
curve->rest_root_normal = float3(hair->rest_nor);
curve->rest_root_tangent = float3(hair->rest_tan);
+// transform_direction(mat, curve->rest_root_normal);
+// transform_direction(mat, curve->rest_root_tangent);
for (int k = 0; k < hair->totpoints; ++k, ++point) {
HairPoint *hair_pt = hair->points + k;
@@ -130,7 +133,7 @@ void SceneConverter::update_solver_data_externals(SolverData *data, SolverForces
Curve *curve = solver_curves + i;
curve->root0 = curve->root1;
- mesh_sample_eval(dm, mat, &hcurve->root, curve->root1.co, curve->root1.nor);
+ mesh_sample_eval_transformed(dm, mat, &hcurve->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);
}
diff --git a/source/blender/hair/intern/HAIR_smoothing.h b/source/blender/hair/intern/HAIR_smoothing.h
index 30724eb..04b129f 100644
--- a/source/blender/hair/intern/HAIR_smoothing.h
+++ b/source/blender/hair/intern/HAIR_smoothing.h
@@ -132,7 +132,6 @@ 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(); }
@@ -140,27 +139,29 @@ struct FrameIterator {
void next()
{
- static const float epsilon = 1.0e-6;
-
- 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 (fabsf(D) > epsilon && fabsf(D) < 1.0f - epsilon) {
- /* half angle sine, cosine */
- D = sqrtf((1.0f + D) * 0.5f);
- C = C / D * 0.5f;
+ if (m_loc_iter.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);
+
/* construct rotation from one segment to the next */
- float4 rot(C.x, C.y, C.z, D);
+ float4 rot = rotation_between_vecs_to_quat(prev_dir, m_dir);
/* 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);
+ normalize_v3_v3(m_frame.normal, m_frame.normal);
+ normalize_v3_v3(m_frame.tangent, m_frame.tangent);
+ normalize_v3_v3(m_frame.cotangent, m_frame.cotangent);
}
}
diff --git a/source/blender/hair/intern/HAIR_solver.cpp b/source/blender/hair/intern/HAIR_solver.cpp
index 0adcb6f..ef52129 100644
--- a/source/blender/hair/intern/HAIR_solver.cpp
+++ b/source/blender/hair/intern/HAIR_solver.cpp
@@ -98,10 +98,14 @@ void SolverData::remove_from_world(rbDynamicsWorld *world)
RB_dworld_remove_ghost(world, &rb_ghost);
}
-static float3 calc_bend(const Frame &frame, const float3 &co0, const float3 &co1)
+static float3 world_to_frame_space(const Frame &frame, const float3 &vec)
{
- float3 edge = co1 - co0;
- return float3(dot_v3v3(edge, frame.normal), dot_v3v3(edge, frame.tangent), dot_v3v3(edge, frame.cotangent));
+ return float3(dot_v3v3(vec, frame.normal), dot_v3v3(vec, frame.tangent), dot_v3v3(vec, frame.cotangent));
+}
+
+static float3 frame_to_world_space(const Frame &frame, const float3 &vec)
+{
+ return frame.normal * vec.x + frame.tangent * vec.y + frame.cotangent * vec.z;
}
void SolverData::precompute_rest_bend(const HairParams ¶ms)
@@ -118,13 +122,12 @@ void SolverData::precompute_rest_bend(const HairParams ¶ms)
else if (curve->totpoints == 1)
pt->rest_bend = float3(0.0f, 0.0f, 0.0f);
else {
-
- float3 normal = curve->rest_root_normal, tangent = curve->rest_root_tangent;
- Frame rest_frame(normal, tangent, cross_v3_v3(normal, tangent));
+ float3 root_nor = curve->rest_root_normal, root_tan = curve->rest_root_tangent;
+ Frame rest_frame(root_nor, root_tan, cross_v3_v3(root_nor, root_tan));
FrameIterator<SolverDataRestLocWalker> iter(SolverDataRestLocWalker(curve), curve->avg_rest_length, params.bend_smoothing, rest_frame);
while (iter.index() < curve->totpoints - 1) {
- pt->rest_bend = calc_bend(iter.frame(), pt->rest_co, next_pt->rest_co);
+ pt->rest_bend = world_to_frame_space(iter.frame(), next_pt->rest_co - pt->rest_co);
iter.next();
++pt;
@@ -238,18 +241,9 @@ static float3 calc_stretch_damping(const HairParams ¶ms, const Point *point0
return params.stretch_damping * dot_v3v3(dvel, dir) * dir;
}
-static float3 bend_target(const Frame &frame, const Point *pt)
-{
- float3 rest_bend = pt->rest_bend;
- float3 target(frame.normal.x * rest_bend.x + frame.tangent.x * rest_bend.y + frame.cotangent.x * rest_bend.z,
- frame.normal.y * rest_bend.x + frame.tangent.y * rest_bend.y + frame.cotangent.y * rest_bend.z,
- frame.normal.z * rest_bend.x + frame.tangent.z * rest_bend.y + frame.cotangent.z * rest_bend.z);
- return target;
-}
-
static float3 calc_bend_force(const HairParams ¶ms, const Point *point0, const Point *point1, const Frame &frame, float time)
{
- float3 target = bend_target(frame, point0);
+ float3 target = frame_to_world_space(frame, point0->rest_bend);
float3 dir;
float3 edge = point1->cur.co - point0->cur.co;
@@ -358,10 +352,20 @@ static void calc_forces(const HairParams ¶ms, const SolverForces &forces, fl
}
Curve *curve = data.curves;
- int k_tot = 0;
+ int k_tot = data.startpoint;
for (int i = 0; i < data.totcurves; ++i, ++curve) {
int numpoints = curve->totpoints;
+ if (numpoints == 0)
+ continue;
+
+ float3 intern_force, intern_force_next, extern_force;
+ float3 acc_prev; /* reactio from previous point */
+
+ /* Root point animation */
+ Point *point = curve->points;
+ int k = 0;
+ Point *point_next = k < numpoints-1 ? point+1 : NULL;
/* note: roots are evaluated at the end of the timestep: time + timestep
* so the hair points align perfectly with them
@@ -369,29 +373,35 @@ static void calc_forces(const HairParams ¶ms, const SolverForces &forces, fl
float3 root_nor, root_tan;
get_root_frame(t0, t1, time + timestep, curve, root_nor, root_tan);
+ if (point_next) {
+ /* rest frame must be rotated according so the first segment is aligned with the rest direction */
+ float4 rot = rotation_between_vecs_to_quat(point_next->rest_co - point->rest_co, point_next->cur.co - point->cur.co);
+ root_nor = mul_qt_v3(rot, root_nor);
+ root_tan = mul_qt_v3(rot, root_tan);
+ normalize_v3_v3(root_nor, root_nor);
+ normalize_v3_v3(root_tan, root_tan);
+ }
+
Frame rest_frame(root_nor, root_tan, cross_v3_v3(root_nor, root_tan));
FrameIterator<SolverDataLocWalker> frame_iter(SolverDataLocWalker(curve), curve->avg_rest_length, params.bend_smoothing, rest_frame);
- float3 intern_force, intern_force_next, extern_force;
- float3 acc_prev; /* reactio from previous point */
+ accum_internal_forces(params, forces, time, timestep, point, point_next, frame_iter.frame(), intern_force, intern_force_next);
+ accum_external_forces(params, forces, time, timestep, point, point_next, frame_iter.frame(), extern_force);
- /* Root point animation */
- Point *point = curve->points;
- int k = 0;
- if (numpoints > 0) {
- Point *point_next = k < numpoints-1 ? point+1 : NULL;
- accum_internal_forces(params, forces, time, timestep, point, point_next, frame_iter.frame(), intern
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list