Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/math/axis.cc17
-rw-r--r--src/math/axis.h3
-rw-r--r--src/render/camera.cc86
3 files changed, 38 insertions, 68 deletions
diff --git a/src/math/axis.cc b/src/math/axis.cc
index 4d752bf..aa35d92 100644
--- a/src/math/axis.cc
+++ b/src/math/axis.cc
@@ -74,6 +74,23 @@ void Axis::change_roll(const float angle) {
axis_vector[1].assign(up);
}
+// perform a rotation about an arbitrary axis
+/* notes:
+ http://mathworld.wolfram.com/RotationFormula.html
+*/
+void Axis::rotate(Vector3f const &normal, float angle)
+{
+ float cosa = cosf(angle);
+ float sina = sinf(angle);
+
+ for (size_t i =0; i < 3; i++) {
+ axis_vector[i] =
+ axis_vector[i]*cosa +
+ normal * dotproduct(normal, axis_vector[i]) * (1 - cosa) +
+ crossproduct(axis_vector[i], normal)*sina;
+ }
+}
+
/*
Axis const Axis::transpose()
{
diff --git a/src/math/axis.h b/src/math/axis.h
index d011675..1422564 100644
--- a/src/math/axis.h
+++ b/src/math/axis.h
@@ -48,6 +48,9 @@ public:
/// change roll, rotate around forward vector (positive is left)
void change_roll(const float angle);
+ /// rotation about an arbitrary axis
+ void rotate(Vector3f const &normal, float angle);
+
private:
Vector3f axis_vector[3];
};
diff --git a/src/render/camera.cc b/src/render/camera.cc
index e37fd0d..c35cb3c 100644
--- a/src/render/camera.cc
+++ b/src/render/camera.cc
@@ -186,79 +186,29 @@ void Camera::frame(float seconds)
distance = core::localcontrol()->radius();
if (mode() == Track) {
- float cosangle;
- float angle;
- float side;
- float u;
- //const float camspeed = 90.0f * seconds; // 180 degrees per second
-
- math::Vector3f n;
- math::Vector3f p;
-
- // camera axis: pitch
-
- // project target_axis.up() into the plane with axis->left() normal
- n = camera_axis.left();
- p = target_axis.up();
- u = p[0]*n[0] + p[1]*n[1] + p[2]*n[2] / (-n[0]*n[0] - n[1]*n[1] - n[2] * n[2]);
- p = target_axis.up() + u * n;
-
- side = camera_axis.forward().x * p.x +
- camera_axis.forward().y * p.y +
- camera_axis.forward().z * p.z;
-
- if ((fabs(side) - MIN_DELTA > 0)) {
-
- cosangle = math::dotproduct(p, camera_axis.up());
- if (fabs(cosangle) + MIN_DELTA < 1 ) {
- angle = acos(cosangle) * 180.0f / M_PI;
- angle = math::sgnf(side) * angle * seconds;
- camera_axis.change_pitch(-angle);
- }
- }
- // camera axis: direction
-
- // project target_axis.forward() into the plane with axis.up() normal
- n = camera_axis.up();
- p = target_axis.forward();
- u = p[0]*n[0] + p[1]*n[1] + p[2]*n[2] / (-n[0]*n[0] - n[1]*n[1] - n[2] * n[2]);
- p = target_axis.forward() + u * n;
-
- side = camera_axis.left().x * p.x +
- camera_axis.left().y * p.y +
- camera_axis.left().z * p.z;
-
- if ((fabs(side) - MIN_DELTA > 0)) {
-
- cosangle = math::dotproduct(p, camera_axis.forward());
- if (fabs(cosangle) + MIN_DELTA < 1 ) {
- angle = acos(cosangle) * 180.0f / M_PI;
- angle = math::sgnf(side) * angle * seconds;
- camera_axis.change_direction(angle);
- }
+ float cosangle; // cosine of an angle
+ float angle; // angle in radians
+ math::Vector3f n; // normal of a plane
+
+ // camera axis: pitch & direction
+
+ n.assign(math::crossproduct(camera_axis.forward(), target_axis.forward()));
+ if (n.lengthsquared() > MIN_DELTA) {
+ n.normalize();
+ cosangle = math::dotproduct(camera_axis.forward(), target_axis.forward());
+ angle = acos(cosangle); // * 180.0f / M_PI;
+ camera_axis.rotate(n, -angle * seconds);
}
// camera axis: roll
- // project target_axis.up() into the plane with axis.forward() normal
- n = camera_axis.forward();
- p = target_axis.up();
- u = p[0]*n[0] + p[1]*n[1] + p[2]*n[2] / (-n[0]*n[0] - n[1]*n[1] - n[2] * n[2]);
- p = target_axis.up() + u * n;
-
- side = camera_axis.left().x * p.x +
- camera_axis.left().y * p.y +
- camera_axis.left().z * p.z;
-
- if ((fabs(side) - MIN_DELTA > 0)) {
-
- cosangle = math::dotproduct(p, camera_axis.up());
- if (fabs(cosangle) + MIN_DELTA < 1 ) {
- angle = acos(cosangle) * 180.0f / M_PI;
- angle = math::sgnf(side) * angle * seconds;
- camera_axis.change_roll(angle);
- }
+ n.assign(math::crossproduct(camera_axis.left(), target_axis.left()));
+ if (n.lengthsquared() > MIN_DELTA) {
+ n.normalize();
+ cosangle = math::dotproduct(camera_axis.left(), target_axis.left());
+ angle = acos(cosangle); // * 180.0f / M_PI;
+ camera_axis.rotate(n, -angle * seconds);
}
if (core::localcontrol()->model()) {