Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/camera.cc')
-rw-r--r--src/client/camera.cc129
1 files changed, 101 insertions, 28 deletions
diff --git a/src/client/camera.cc b/src/client/camera.cc
index 29310fc..21bf930 100644
--- a/src/client/camera.cc
+++ b/src/client/camera.cc
@@ -28,6 +28,7 @@ math::Vector3f target;
math::Vector3f eye;
math::Axis axis;
+const float MIN_DELTA = 10e-10;
// current camera mode
Mode mode;
@@ -86,10 +87,18 @@ void set_mode(Mode newmode) {
target_pitch = 0.0f;
distance = 0.4f;
+ axis.clear();
+
switch(newmode) {
case Track:
// switch camera to Track mode
mode = Track;
+ if (core::localcontrol()) {
+ if (core::localcontrol()->state())
+ axis.assign(core::localcontrol()->state()->axis());
+ else
+ axis.assign(core::localcontrol()->axis());
+ }
break;
case Free:
@@ -148,7 +157,7 @@ void next_mode()
void draw(float seconds)
{
math::Matrix4f matrix;
-
+ math::Axis target_axis;
float d = 0;
if (!core::localcontrol()) {
@@ -165,37 +174,102 @@ void draw(float seconds)
distance = 20.0f;
} else {
-
if (mode == Overview)
set_mode(Track);
if (core::localcontrol()->state()) {
target.assign(core::localcontrol()->state()->location());
- axis.assign(core::localcontrol()->state()->axis());
+ target_axis.assign(core::localcontrol()->state()->axis());
} else {
target.assign(core::localcontrol()->location());
- axis.assign(core::localcontrol()->axis());
+ target_axis.assign(core::localcontrol()->axis());
}
-
+
if (mode == Track) {
- if (core::localcontrol()->state() && core::localcontrol()->model()) {
- target -= (core::localcontrol()->model()->maxbbox().x + 0.15f) * core::localcontrol()->state()->axis().forward();
-
- target += (core::localcontrol()->model()->maxbbox().z + 0.3f ) *
- core::localcontrol()->state()->axis().up();
+ float cosangle;
+ float angle;
+ float side;
+ float u;
+ const float cam_speed = seconds * 4 ;
+
+ math::Vector3f n;
+ math::Vector3f p;
+
+ // camera axis: pitch
+
+ // project target_axis.up() into the plane with axis->left() normal
+ n = 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 = axis.forward().x * p.x +
+ axis.forward().y * p.y +
+ axis.forward().z * p.z;
+
+ if ((fabs(side) - MIN_DELTA > 0)) {
+
+ cosangle = math::dotproduct(p, axis.up());
+ if (fabs(cosangle) + MIN_DELTA < 1 ) {
+ angle = acos(cosangle) * 180.0f / M_PI;
+ angle = math::sgnf(side) * angle * cam_speed;
+ axis.change_pitch(-angle);
+ }
}
- // make the camera swing while turning
- target_direction = core::localcontrol()->target_direction;
- target_pitch = core::localcontrol()->target_pitch;
+ // camera axis: direction
+
+ // project target_axis.forward() into the plane with axis.up() normal
+ n = 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 = axis.left().x * p.x +
+ axis.left().y * p.y +
+ axis.left().z * p.z;
+
+ if ((fabs(side) - MIN_DELTA > 0)) {
+
+ cosangle = math::dotproduct(p, axis.forward());
+ if (fabs(cosangle) + MIN_DELTA < 1 ) {
+ angle = acos(cosangle) * 180.0f / M_PI;
+ angle = math::sgnf(side) * angle * cam_speed;
+ axis.change_direction(angle);
+ }
+ }
- yaw_target = - 30 * target_direction;
- pitch_target = - 30 * target_pitch;
- //pitch_target = pitch_track - 30 * target_pitch;
+ // camera axis: roll
+
+ // project target_axis.up() into the plane with axis.forward() normal
+ n = 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 = axis.left().x * p.x +
+ axis.left().y * p.y +
+ axis.left().z * p.z;
+
+ if ((fabs(side) - MIN_DELTA > 0)) {
+
+ cosangle = math::dotproduct(p, axis.up());
+ if (fabs(cosangle) + MIN_DELTA < 1 ) {
+ angle = acos(cosangle) * 180.0f / M_PI;
+ angle = math::sgnf(side) * angle * cam_speed;
+ axis.change_roll(angle);
+ }
+ }
distance = 0.0f;
+ if (core::localcontrol()->model()) {
+ target -= (core::localcontrol()->model()->maxbbox().x + 0.1f) * axis.forward();
+ target += (core::localcontrol()->model()->maxbbox().z + 0.1f ) * axis.up();
+ }
+
} else if (mode == Free) {
+ axis.assign(target_axis);
yaw_target = yaw_current - 90 * target_direction;
pitch_target = pitch_current - 90 * target_pitch;
@@ -205,26 +279,25 @@ void draw(float seconds)
} else {
distance = 1.0f;
}
-
- } else if (mode == Cockpit) {
- if (core::localcontrol()->state() && core::localcontrol()->model())
- target += (core::localcontrol()->model()->maxbbox().x+0.05) *
- core::localcontrol()->state()->axis().forward();
-
- distance = 0.0f;
- }
-
- if (mode != Cockpit) {
// adjust direction
d = degrees180f(yaw_current - yaw_target);
yaw_current = degrees360f( yaw_current - d * seconds);
axis.change_direction(yaw_current);
- // adjust pitch target
+ // adjust pitch
d = degrees180f(pitch_current - pitch_target);
- pitch_current = degrees360f(pitch_current - d *seconds);
+ pitch_current = degrees360f(pitch_current - d * seconds);
axis.change_pitch(pitch_current);
+
+ } else if (mode == Cockpit) {
+ axis.assign(target_axis);
+
+ if (core::localcontrol()->state() && core::localcontrol()->model())
+ target += (core::localcontrol()->model()->maxbbox().x+0.05) *
+ core::localcontrol()->state()->axis().forward();
+
+ distance = 0.0f;
}
}