00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "scenegraph/freeview.hpp"
00035 #include "math/quaternion.hpp"
00036
00037 namespace gsgl
00038 {
00039
00040 using namespace data;
00041 using namespace math;
00042
00043 namespace scenegraph
00044 {
00045
00046 BROKER_DEFINE_CREATOR(gsgl::scenegraph::freeview);
00047
00048
00049
00050
00051 freeview::freeview(const string & name, node *parent)
00052 : node(name, parent), cam(0), last_code(sg_event::NULL_EVENT), relative(false),
00053 transition_end_tick(0), transition_angular_velocity(0), transition_axis(vector::Z_AXIS), transition_linear_velocity(0), transition_path(vector::ZERO)
00054 {
00055 cam = new camera(this);
00056 }
00057
00058
00059 freeview::freeview(const data::config_record & obj_conf)
00060 : node(obj_conf), cam(0), last_code(sg_event::NULL_EVENT), relative(false),
00061 transition_end_tick(0), transition_angular_velocity(0), transition_axis(vector::Z_AXIS), transition_linear_velocity(0), transition_path(vector::ZERO)
00062 {
00063 cam = new camera(this);
00064
00065 if (!obj_conf[L"field_of_view"].is_empty())
00066 {
00067 cam->get_field_of_view() = static_cast<gsgl::real_t>(obj_conf[L"field_of_view"].to_double());
00068 }
00069 else
00070 {
00071 cam->get_field_of_view() = 60;
00072 }
00073 }
00074
00075
00076 freeview::~freeview()
00077 {
00078 }
00079
00080
00081 static config_variable<gsgl::real_t> ROTATION_STEP(L"scenegraph/freeview/rotation_step", 1.0f);
00082 static config_variable<gsgl::real_t> TRANSITION_TIME(L"scenegraph/freeview/transition_time", 0.5f);
00083
00084
00085 void freeview::reset(context *c)
00086 {
00087 assert(get_parent());
00088
00089 last_code = sg_event::NULL_EVENT;
00090 transition_end_tick = 0;
00091
00092 transition_angular_velocity = 0;
00093 transition_axis = vector::Z_AXIS;
00094
00095 transition_linear_velocity = 0;
00096 transition_path = vector::ZERO;
00097
00098 get_translation() = vector(0, -get_parent()->default_view_distance(), 0);
00099 get_orientation() = transform::IDENTITY;
00100
00101 if (get_translation().mag() > 0)
00102 relative = true;
00103 }
00104
00105
00106 void freeview::update(context *c)
00107 {
00108 if (c->cur_tick < transition_end_tick)
00109 {
00110 if (transition_angular_velocity)
00111 {
00112 quaternion rq(transition_axis, transition_angular_velocity * c->delta_tick / 1000.0f);
00113 transform rt(rq);
00114 get_orientation() = rt * get_orientation();
00115
00116 if (relative)
00117 get_translation() = rt * get_translation();
00118 }
00119 else if (transition_linear_velocity)
00120 {
00121 get_translation() += transition_path * (transition_linear_velocity * c->delta_tick / 1000.0f);
00122 }
00123 }
00124 }
00125
00126
00127 bool freeview::rot_absolute(sg_event::event_code code, context *c)
00128 {
00129 if (code != last_code)
00130 {
00131 vector axis;
00132 gsgl::real_t velocity = static_cast<gsgl::real_t>(ROTATION_STEP * math::DEG2RAD / TRANSITION_TIME);
00133
00134 switch (code)
00135 {
00136 case sg_event::VIEW_ROT_X_POS:
00137 axis = vector::X_AXIS;
00138 break;
00139 case sg_event::VIEW_ROT_X_NEG:
00140 axis = vector::X_AXIS;
00141 velocity *= -1;
00142 break;
00143 case sg_event::VIEW_ROT_Y_POS:
00144 axis = vector::Y_AXIS;
00145 break;
00146 case sg_event::VIEW_ROT_Y_NEG:
00147 axis = vector::Y_AXIS;
00148 velocity *= -1;
00149 break;
00150 case sg_event::VIEW_ROT_Z_POS:
00151 axis = vector::Z_AXIS;
00152 break;
00153 case sg_event::VIEW_ROT_Z_NEG:
00154 axis = vector::Z_AXIS;
00155 velocity *= -1;
00156 break;
00157 default:
00158 return false;
00159 }
00160
00161 last_code = code;
00162
00163 transition_axis = get_orientation() * axis;
00164 transition_angular_velocity = velocity;
00165 }
00166
00167 if (transition_angular_velocity != 0)
00168 {
00169 transition_end_tick = c->cur_tick + static_cast<unsigned long>(1000.0f * TRANSITION_TIME);
00170 }
00171
00172 return true;
00173 }
00174
00175
00176 bool freeview::rot_relative(sg_event::event_code code, context *c)
00177 {
00178 if (code != last_code)
00179 {
00180 vector axis;
00181 gsgl::real_t velocity = static_cast<gsgl::real_t>(ROTATION_STEP * math::DEG2RAD / TRANSITION_TIME);
00182
00183 switch (code)
00184 {
00185 case sg_event::VIEW_ROT_X_POS:
00186 axis = vector::X_AXIS;
00187 velocity *= -1;
00188 break;
00189 case sg_event::VIEW_ROT_X_NEG:
00190 axis = vector::X_AXIS;
00191 break;
00192 case sg_event::VIEW_ROT_Y_POS:
00193 axis = vector::Y_AXIS;
00194 break;
00195 case sg_event::VIEW_ROT_Y_NEG:
00196 axis = vector::Y_AXIS;
00197 velocity *= -1;
00198 break;
00199 case sg_event::VIEW_ROT_Z_POS:
00200 axis = vector::Z_AXIS;
00201 velocity *= -1;
00202 break;
00203 case sg_event::VIEW_ROT_Z_NEG:
00204 axis = vector::Z_AXIS;
00205 break;
00206 default:
00207 return false;
00208 }
00209
00210 last_code = code;
00211
00212 transition_axis = get_orientation() * axis;
00213 transition_angular_velocity = velocity;
00214 }
00215
00216 if (transition_angular_velocity != 0)
00217 {
00218 transition_end_tick = c->cur_tick + static_cast<unsigned long>(1000.0f * TRANSITION_TIME);
00219 }
00220
00221 return true;
00222 }
00223
00224
00225 bool freeview::handle_event(context *c, sg_event & e)
00226 {
00227 assert(c->view == this);
00228
00229 switch (e.get_code())
00230 {
00231 case sg_event::VIEW_ROT_X_POS:
00232 case sg_event::VIEW_ROT_X_NEG:
00233 case sg_event::VIEW_ROT_Y_POS:
00234 case sg_event::VIEW_ROT_Y_NEG:
00235 case sg_event::VIEW_ROT_Z_POS:
00236 case sg_event::VIEW_ROT_Z_NEG:
00237 if (relative)
00238 return rot_relative(e.get_code(), c);
00239 else
00240 return rot_absolute(e.get_code(), c);
00241
00242 case sg_event::VIEW_TOGGLE_ROT_MODE:
00243
00244 if (get_translation().mag2())
00245 {
00246 relative = !relative;
00247 last_code = sg_event::NULL_EVENT;
00248 }
00249 return true;
00250
00251 case sg_event::VIEW_ZOOM_IN:
00252 case sg_event::VIEW_ZOOM_OUT:
00253 if (relative)
00254 {
00255 transition_angular_velocity = 0;
00256
00257 if (transition_end_tick < c->cur_tick)
00258 {
00259 double dist = get_translation().mag();
00260 if (dist > 0)
00261 {
00262 double surf = get_parent()->minimum_view_distance();
00263 double alt = dist - surf;
00264 if (alt < 0.0)
00265 alt = 0.0;
00266 double new_alt = alt * (e.get_code() == sg_event::VIEW_ZOOM_IN ? 0.5 : 2.0);
00267 double new_dist = surf + new_alt;
00268 double ratio = new_dist / dist;
00269
00270 vector desired_position = get_translation() * static_cast<gsgl::real_t>(ratio);
00271 vector path = desired_position - get_translation();
00272
00273 transition_linear_velocity = path.mag() / TRANSITION_TIME;
00274 transition_path = path; transition_path.normalize();
00275
00276 transition_end_tick = c->cur_tick + static_cast<unsigned long>(1000.0f * TRANSITION_TIME);
00277 }
00278 }
00279 }
00280 return true;
00281
00282 case sg_event::VIEW_RESET:
00283 reset(c);
00284 return true;
00285
00286 default:
00287 break;
00288 }
00289
00290 return false;
00291 }
00292
00293
00294 }
00295
00296 }