Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2006-11-19 02:07:32 +0300
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2006-11-19 02:07:32 +0300
commit2bb9d5471e1c43ebb1ec805648536edac9f78105 (patch)
treed240255e3763af312faa7dbe4c3ef7feb4d46df7 /source/blender/blenlib
parent904dfcc6a294aa4be904b026295f6f759a72df1b (diff)
Fix for bug #5250: inaccurate conversion between edit and pose mode bones.
Using acos(dot(u, v)) to find the angle between two vectors is quite inaccurate, and there's a better way to do it, as explained here: http://www.plunk.org/~hatch/rightway.php Also changed the use of atan for computing roll to atan2 in some places, the latter avoids accuracy and division by zero issues.
Diffstat (limited to 'source/blender/blenlib')
-rw-r--r--source/blender/blenlib/BLI_arithb.h9
-rw-r--r--source/blender/blenlib/intern/arithb.c31
2 files changed, 36 insertions, 4 deletions
diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h
index c2a81ebed65..c478262d500 100644
--- a/source/blender/blenlib/BLI_arithb.h
+++ b/source/blender/blenlib/BLI_arithb.h
@@ -537,6 +537,10 @@ saacos(
float fac
);
float
+saasin(
+ float fac
+);
+ float
sasqrt(
float fac
);
@@ -661,6 +665,11 @@ VecAngle2(
float *v1,
float *v2
);
+ float
+NormalizedVecAngle2(
+ float *v1,
+ float *v2
+);
void
i_lookat(
diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c
index 3fd65ca534c..51000b3b155 100644
--- a/source/blender/blenlib/intern/arithb.c
+++ b/source/blender/blenlib/intern/arithb.c
@@ -82,6 +82,13 @@ float saacos(float fac)
else return (float)acos(fac);
}
+float saasin(float fac)
+{
+ if(fac<= -1.0f) return (float)-M_PI/2.0f;
+ else if(fac>=1.0f) return (float)M_PI/2.0f;
+ else return (float)asin(fac);
+}
+
float sasqrt(float fac)
{
if(fac<=0.0) return 0.0;
@@ -2382,7 +2389,7 @@ void VecRotToQuat( float *vec, float phi, float *quat)
/* Return the angle in degrees between vecs 1-2 and 2-3 in degrees
If v1 is a shoulder, v2 is the elbow and v3 is the hand,
this would return the angle at the elbow */
-float VecAngle3( float *v1, float *v2, float *v3)
+float VecAngle3(float *v1, float *v2, float *v3)
{
float vec1[3], vec2[3];
@@ -2390,20 +2397,36 @@ float VecAngle3( float *v1, float *v2, float *v3)
VecSubf(vec2, v2, v3);
Normalise(vec1);
Normalise(vec2);
- return saacos(vec1[0]*vec2[0] + vec1[1]*vec2[1] + vec1[2]*vec2[2]) * 180.0/M_PI;
+
+ return NormalizedVecAngle2(vec1, vec2) * 180.0/M_PI;
}
/* Return the shortest angle in degrees between the 2 vectors */
-float VecAngle2( float *v1, float *v2)
+float VecAngle2(float *v1, float *v2)
{
float vec1[3], vec2[3];
+
VecCopyf(vec1, v1);
VecCopyf(vec2, v2);
Normalise(vec1);
Normalise(vec2);
- return saacos(vec1[0]*vec2[0] + vec1[1]*vec2[1] + vec1[2]*vec2[2]) * 180.0/M_PI;
+
+ return NormalizedVecAngle2(vec1, vec2)* 180.0/M_PI;
}
+float NormalizedVecAngle2(float *v1, float *v2)
+{
+ /* this is the same as acos(Inpf(v1, v2)), but more accurate */
+ if (Inpf(v1, v2) < 0.0f) {
+ v2[0]= -v2[0];
+ v2[1]= -v2[1];
+ v2[2]= -v2[2];
+
+ return (float)M_PI - 2.0f*saasin(VecLenf(v2, v1)/2.0f);
+ }
+ else
+ return 2.0f*saasin(VecLenf(v2, v1)/2.0);
+}
void euler_rot(float *beul, float ang, char axis)
{