1 /*
2 Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.com)
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version
7 3 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include "zoomcamera.h"
19
ZoomCamera()20 ZoomCamera::ZoomCamera() {
21 }
22
ZoomCamera(vec3 pos,vec3 target,float min_distance,float max_distance)23 ZoomCamera::ZoomCamera(vec3 pos, vec3 target, float min_distance, float max_distance) :
24 pos(pos), _pos(pos), target(target), _target(target), dest(pos), fov(90.0f) {
25
26 znear = 0.1;
27
28 up = vec3(0.0f, -1.0f, 0.0f);
29
30 setMinDistance(min_distance);
31 setMaxDistance(max_distance);
32
33 padding = 1.0;
34 speed = 1.0;
35 lockon = false;
36 lockon_time = 0.0;
37 reset();
38 }
39
reset()40 void ZoomCamera::reset() {
41 pos = _pos;
42 target = _target;
43 }
44
getMaxDistance()45 float ZoomCamera::getMaxDistance() { return max_distance; }
getMinDistance()46 float ZoomCamera::getMinDistance() { return min_distance; }
47
setPadding(float padding)48 void ZoomCamera::setPadding(float padding) {
49 this->padding = padding;
50 }
51
setMaxDistance(float max)52 void ZoomCamera::setMaxDistance(float max) {
53 max_distance = max;
54 zfar = max + 1.0;
55 }
56
setMinDistance(float min)57 void ZoomCamera::setMinDistance(float min) {
58 min_distance = min;
59 }
60
lockOn(bool lockon)61 void ZoomCamera::lockOn(bool lockon) {
62
63 if(lockon) {
64 lockon_time = 1.0;
65 }
66
67 this->lockon = lockon;
68 }
69
look()70 void ZoomCamera::look() {
71 lookAt(target);
72 }
73
lookAt(const vec3 & target)74 void ZoomCamera::lookAt(const vec3& target) {
75 gluLookAt( pos.x, pos.y, pos.z,
76 target.x, target.y, target.z,
77 up.x, up.y, up.z);
78 }
79
focus()80 void ZoomCamera::focus() {
81 display.mode3D(fov, znear, zfar);
82 look();
83 }
84
stop()85 void ZoomCamera::stop() {
86 this->dest = pos;
87 }
88
setSpeed(float speed)89 void ZoomCamera::setSpeed(float speed) {
90 this->speed = speed;
91 }
adjust(const Bounds2D & bounds)92 void ZoomCamera::adjust(const Bounds2D& bounds) {
93 adjust(bounds, true);
94 }
95
adjust(const Bounds2D & bounds,bool adjust_distance)96 void ZoomCamera::adjust(const Bounds2D& bounds, bool adjust_distance) {
97
98 //center camera on bounds
99
100 vec2 centre = bounds.centre();
101
102 //adjust by screen ratio
103 dest.x = centre.x;
104 dest.y = centre.y;
105
106 if(!adjust_distance) return;
107
108 //scale by 10% so we dont have stuff right on the edge of the screen
109 float width = bounds.width() * padding;
110 float height = bounds.height() * padding;
111
112 float aspect_ratio = display.width / (float) display.height;
113
114 if(aspect_ratio < 1.0) {
115 height /= aspect_ratio;
116 } else {
117 width /= aspect_ratio;
118 }
119
120 //calc visible width of the opposite wall at a distance of 1 this fov
121 float toa = tan( fov * 0.5f * DEGREES_TO_RADIANS ) * 2.0;
122
123 float distance;
124
125 //TOA = tan = opposite/adjacent (distance = adjacent)
126 //use the larger side of the box
127
128 //cropping: vertical, horizontal or none
129 if(gGourceSettings.crop_vertical) {
130
131 distance = width / toa;
132
133
134 } else if (gGourceSettings.crop_horizontal) {
135
136 distance = height / toa;
137
138 } else {
139
140 if(width >= height) {
141 distance = width / toa;
142 } else {
143 distance = height / toa;
144 }
145 }
146
147 //debugLog("toa %.2f, distance %.2f width %.2f height %.2f dratio %.2f\n", toa, distance, width, height, dratio);
148
149 //check bounds are valid
150 if(distance < min_distance) distance = min_distance;
151 if(distance > max_distance) distance = max_distance;
152
153 this->dest.z = -distance;
154 }
155
setDistance(float distance)156 void ZoomCamera::setDistance(float distance) {
157 dest.z = -distance;
158 }
159
setPos(const vec3 & pos,bool keep_angle)160 void ZoomCamera::setPos(const vec3& pos, bool keep_angle) {
161 if(keep_angle) {
162 vec3 dir = target - this->pos;
163 this->pos = pos;
164 this->target = pos + dir;
165 } else {
166 this->pos = pos;
167 }
168 }
169
logic(float dt)170 void ZoomCamera::logic(float dt) {
171 vec3 dp = (dest - pos);
172
173 vec3 dpt = dp * dt * speed;
174
175 if(lockon) {
176 dpt = dpt * lockon_time + dp * (1.0f-lockon_time);
177
178 if(lockon_time>0.0) {
179 lockon_time = std::max(0.0f, lockon_time-dt*0.5f);
180 }
181 }
182
183 if(glm::length2(dpt) > glm::length2(dp)) dpt = dp;
184
185 pos += dpt;
186
187 target = vec3(pos.x, pos.y, 0.0);
188 }
189