source: golgotha/src/golg/camera.cc

Last change on this file was 80, checked in by Sam Hocevar, 12 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 24.5 KB
Line 
1/********************************************************************** <BR>
2  This file is part of Crack dot Com's free source code release of
3  Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
4  information about compiling & licensing issues visit this URL</a>
5  <PRE> If that doesn't help, contact Jonathan Clark at
6  golgotha_source@usa.net (Subject should have "GOLG" in it)
7***********************************************************************/
8
9#include "camera.hh"
10#include "global_id.hh"
11#include "g1_render.hh"
12#include "math/angle.hh"
13#include "input.hh"
14#include "player.hh"
15#include "objs/stank.hh"
16#include "math/trig.hh"
17#include "resources.hh"
18#include "map_man.hh"
19#include "map.hh"
20#include "m_flow.hh"
21#include "cwin_man.hh"
22#include "lisp/lisp.hh"
23#include "controller.hh"
24#include "objs/field_camera.hh"
25#include "objs/map_piece.hh"
26#include "saver.hh"
27#include "time/profile.hh"
28#include "lisp/lisp.hh"
29#include "sound/sfx_id.hh"
30#include "demo.hh"
31#include "lisp/li_init.hh"
32
33i4_profile_class   pf_suggest_camera_event("suggest_camera_event");
34
35enum {
36  G1_PAN_LEFT           =(1<<0),
37  G1_PAN_RIGHT          =(1<<1),
38  G1_PAN_FORWARD        =(1<<2),
39  G1_PAN_BACKWARD       =(1<<3),
40  G1_PAN_UP             =(1<<4),
41  G1_PAN_DOWN           =(1<<5),
42  G1_ROTATE_LEFT        =(1<<6),
43  G1_ROTATE_RIGHT       =(1<<7),
44  G1_ROTATE_UP          =(1<<8),
45  G1_ROTATE_DOWN        =(1<<9),
46 
47  G1_MOVE_LEFT          =(1<<10),
48  G1_MOVE_RIGHT         =(1<<11),
49  G1_MOVE_FORWARD       =(1<<12),
50  G1_MOVE_BACKWARD      =(1<<13)
51};
52
53
54char *cmd_names[]={"Pan Left",
55                   "Pan Right",
56                   "Pan Forward",
57                   "Pan Backward",
58                   "Pan Up",
59                   "Pan Down",
60                   "Rotate Left",
61                   "Rotate Right",
62                   "Rotate Up",
63                   "Rotate Down",
64                   "Move Left",
65                   "Move Right",
66                   "Move Forward",
67                   "Move Backward",
68                   0};
69
70
71
72w32 g1_scroll_bits=0;
73
74
75li_object *g1_camera_key_press(li_object *o, li_environment *env)
76{
77  w32 flag=li_get_int(li_eval(env->current_function()),env);
78  g1_scroll_bits|=flag; 
79  return 0;
80}
81
82li_object *g1_camera_key_depress(li_object *o, li_environment *env)
83{
84  w32 flag=li_get_int(li_eval(env->current_function()),env);
85  g1_scroll_bits&=~flag; 
86  return 0;
87}
88
89li_object *g1_toggle_follow_mode(li_object *_o, li_environment *env)
90{
91  g1_object_class *o=g1_player_man.get_local()->get_commander();
92  if (g1_current_controller.get() && o)
93    if (g1_current_controller->view.view_mode==G1_FOLLOW_MODE)
94      g1_current_controller->view.suggest_camera_mode(G1_ACTION_MODE, o->global_id);
95    else
96      g1_current_controller->view.suggest_camera_mode(G1_FOLLOW_MODE, o->global_id);
97
98  return 0;
99}
100
101
102class g1_add_camera_funs_initer : public i4_init_class
103{
104public:
105  void init()
106  {
107    char **cmd;
108    int f=1;
109    for (cmd=cmd_names; *cmd; cmd++)
110    {
111      li_set_value(*cmd, new li_int(f));
112      li_add_function(*cmd, g1_camera_key_press);
113
114      char end_cmd[200];   
115      sprintf(end_cmd, "-%s", *cmd);     
116      li_add_function(end_cmd, g1_camera_key_depress);
117      li_set_value(end_cmd, new li_int(f));
118           
119      f=f<<1;
120    }
121  }
122} g1_add_camera_funs_instance;
123
124
125
126li_object *g1_action_mode(li_object *o, li_environment *env)
127{
128  if (g1_current_view_state())
129    g1_current_view_state()->suggest_camera_mode(G1_ACTION_MODE);
130  return 0;
131}
132
133li_object *g1_strategy_mode(li_object *o, li_environment *env)
134{
135  if (g1_current_view_state())
136    g1_current_view_state()->suggest_camera_mode(G1_STRATEGY_MODE);
137  return 0;
138}
139
140li_object *g1_follow_mode(li_object *o, li_environment *env)
141{
142  g1_player_piece_class *com=g1_player_man.get_local()->get_commander();
143  if (g1_current_view_state() && com)
144    g1_current_view_state()->suggest_camera_mode(G1_FOLLOW_MODE, com->global_id);
145  return 0;
146}
147
148li_object *g1_camera_mode(li_object *o, li_environment *env)
149{
150  if (g1_current_view_state())
151    g1_current_view_state()->suggest_camera_mode(G1_WATCH_MODE);
152  return 0;
153}
154
155li_object *g1_set_current_camera(li_object *o, li_environment *env)
156{
157  if (g1_current_view_state() && g1_current_controller.get())
158  {
159    g1_object_class *c=g1_find_named_camera(li_get_string(li_eval(li_car(o,env),env),env));
160    if (c)
161    {
162      g1_camera_event evt;
163      evt.camera_at=c;
164      evt.type=G1_WATCH_FORCE;
165
166      g1_current_controller->view.suggest_camera_event(evt);
167    }
168  }
169  return 0;
170}
171
172
173li_object *g1_set_camera_position(li_object *o, li_environment *env)
174{
175  if (g1_current_view_state())
176  {
177    float x=li_get_float(li_eval(li_first(o,env), env),env);
178    float y=li_get_float(li_eval(li_second(o,env), env),env);
179    g1_current_view_state()->set_camera_position(x,y);
180  }
181 
182  return 0;
183}
184
185
186void g1_camera_info_struct::defaults()
187{
188  gx=gy=1;
189  gz=10;
190
191  horizon_rotate=i4_pi()/2;
192  ground_rotate=i4_pi()/2;
193  roll=0;
194}
195
196
197void g1_camera_info_struct::load(g1_loader_class *fp)
198{
199  fp->read_format("ffffff", &gx, &gy, &gz, &ground_rotate, &horizon_rotate, &roll); 
200}
201
202void g1_camera_info_struct::save(g1_saver_class *fp)
203{
204  fp->write_format("ffffff", &gx, &gy, &gz, &ground_rotate, &horizon_rotate, &roll); 
205}
206
207
208g1_camera_event::g1_camera_event()
209{
210  follow_object=0;
211  camera_at=0;
212  type=G1_WATCH_INVALID;
213  min_time=10, max_time=50;   // min/max times to sustain camera shot (in ticks)
214  time_elapsed=0;           // time that we've spent on this shot already (in ticks)
215
216 
217};
218
219
220void g1_view_state_class::save(g1_saver_class *fp)
221{
222  fp->start_version(1);
223
224  start.save(fp);
225  end.save(fp);
226 
227  fp->write_format("ff",
228                   &start_end_interpolate_fraction,
229                   &start_end_interpolate_fraction_step);
230  fp->write_8(view_mode);
231 
232  fp->write_global_id(follow_object_id);
233 
234  fp->end_version();
235}
236
237void g1_view_state_class::defaults()
238{
239  move_offset=i4_3d_vector(0,0,0);
240  watch_type=G1_WATCH_IDLE;   
241  follow_object_id=g1_global_id.invalid_id();
242  view_mode=G1_STRATEGY_MODE;
243  start_end_interpolate_fraction_step=0.0;
244  start_end_interpolate_fraction=1.0;
245  start_invalid=i4_T;
246  start.defaults();
247 
248  end.defaults();
249  current.defaults();
250}
251
252
253void g1_camera_event::object_ids_changed()   // call after level is reloaded
254{
255  camera_at=0;
256  follow_object=0;
257}
258
259void g1_view_state_class::load(g1_loader_class *fp)
260{
261  if (fp && fp->check_version(1))
262  {
263    start.load(fp);
264    end.load(fp);
265   
266    fp->read_format("ff",
267                     &start_end_interpolate_fraction,
268                     &start_end_interpolate_fraction_step);
269   
270    view_mode=(g1_view_mode_type)fp->read_8();
271    follow_object_id=fp->read_global_id();
272  }
273  else
274    follow_object_id=g1_global_id.invalid_id();
275
276  current_cam.object_ids_changed();
277  next_cam.object_ids_changed();
278}
279
280
281
282
283g1_view_state_class::g1_view_state_class()
284{
285  defaults();
286}
287
288
289// calculates current and returns a pointer to it
290g1_camera_info_struct *g1_view_state_class::get_camera()
291{
292  float fr=g1_render.frame_ratio;
293  if (fr>1.0) fr=1.0;
294  if (fr<0.0) fr=0.0;
295 
296  float i=start_end_interpolate_fraction + start_end_interpolate_fraction_step * fr;
297 
298  current.gx = i4_interpolate(start.gx, end.gx, i);
299  current.gy = i4_interpolate(start.gy, end.gy, i);
300  current.gz = i4_interpolate(start.gz, end.gz, i);
301   
302  current.ground_rotate = i4_interpolate_angle(start.ground_rotate, end.ground_rotate, i);
303  current.horizon_rotate = i4_interpolate_angle(start.horizon_rotate, end.horizon_rotate, i);
304  current.roll = i4_interpolate_angle(start.roll, end.roll, i);
305  current.ground_x_rotate = i4_interpolate_angle(start.ground_x_rotate, end.ground_x_rotate, i);
306  current.ground_y_rotate = i4_interpolate_angle(start.ground_y_rotate, end.ground_y_rotate, i);
307
308  return &current;
309}
310
311void g1_view_state_class::update_follow_mode()
312{
313  start=end;
314 
315  g1_object_class *follow = g1_global_id.check_id(follow_object_id) ?
316  g1_global_id.get(follow_object_id) : 0;
317  if (follow)
318  {
319    g1_player_piece_class *stank=g1_player_man.get_local()->get_commander();
320       
321    i4_float fr = g1_render.frame_ratio;
322 
323    i4_float itheta = follow==stank ? stank->base_angle  : follow->theta;   
324       
325    i4_float idist   = g1_resources.follow_camera_dist;
326    i4_float iheight = g1_resources.follow_camera_height;
327
328    i4_float ix = follow->x;
329    i4_float iy = follow->y;
330    i4_float ih = follow->h+ 0.1;
331     
332    end.ground_rotate = g1_resources.follow_camera_rotation + itheta;
333
334    end.gx = ix - cos(end.ground_rotate) * idist;
335    end.gy = iy - sin(end.ground_rotate) * idist;
336
337    float th = ih + iheight;
338    float gh = g1_get_map()->terrain_height(end.gx, end.gy)+0.01;
339
340    if (th < gh)
341    {
342      g1_resources.follow_camera_height = gh - ih;
343      th = gh;
344    }
345
346    end.gz = th;
347     
348    float xy_dist = sqrt((ix - end.gx) * (ix - end.gx) +
349                         (iy - end.gy) * (iy - end.gy));
350
351    end.horizon_rotate = i4_atan2(end.gz - ih, xy_dist);
352     
353    end.roll=0;
354    end.ground_x_rotate=0;
355    end.ground_y_rotate=0;
356
357    start_end_interpolate_fraction=0.0;
358    start_end_interpolate_fraction_step=1.0;
359  }
360  else
361  {
362    view_mode=G1_WATCH_MODE;
363    update();
364  }
365
366}
367
368void g1_view_state_class::update_action_mode()
369{
370  g1_player_piece_class *stank=g1_player_man.get_local()->get_commander();
371  if (!stank)
372  {
373    view_mode=G1_WATCH_MODE;
374    update();
375  }
376  else
377  {
378    stank->calc_action_cam(start,0);
379    stank->calc_action_cam(end,1);
380    start_end_interpolate_fraction=0.0;
381    start_end_interpolate_fraction_step=1.0;
382  }     
383}
384
385li_symbol_ref watch_camera_turn_speed("watch_camera_turn_speed"),
386              watch_camera_max_speed("watch_camera_max_speed"),
387              watch_camera_accel("watch_camera_accel");
388
389void g1_check_position(float &x, float &y)
390{
391  if (x<0) x=0;
392  if (y<0) y=0;
393  if (x+1>=g1_get_map()->width()) x=g1_get_map()->width()-1;
394  if (x+1>=g1_get_map()->height()) x=g1_get_map()->height()-1;
395}
396
397void g1_view_state_class::use_next_cam()
398{
399  if (next_cam.camera_at.get()==current_cam.camera_at.get())   // don't snap if same camera position
400    next_cam.time_elapsed=1;
401 
402  current_cam=next_cam;
403  next_cam.type=G1_WATCH_INVALID;
404  if (current_cam.type!=G1_WATCH_INVALID)
405  {
406    g1_object_class *watch_obj=current_cam.follow_object.get();
407    if (watch_obj)
408    {
409      i4_3d_vector pos=i4_3d_vector(watch_obj->x, watch_obj->y, watch_obj->h);       
410      g1_object_class *cam_object=g1_find_closest_field_camera(pos);
411      if (cam_object)
412       current_cam.camera_at=cam_object;
413    }
414    else if (next_cam.camera_at.get())
415    {
416      i4_transform_class t;
417
418      g1_object_class *cam=next_cam.camera_at.get();
419      cam->world_transform=&t;
420      cam->calc_world_transform(0, &t);
421
422      i4_3d_vector startp,endp;
423      t.transform(i4_3d_vector(0,0,0), startp);
424      t.transform(i4_3d_vector(1,0,0), endp);
425     
426
427      float xy_theta=i4_atan2(endp.y - startp.y, endp.x - startp.x);
428      float xy_dist=sqrt((endp.y - startp.y) * (endp.y - startp.y) +
429                         (endp.x - startp.x) * (endp.x - startp.x));
430
431      float z_theta=i4_atan2(endp.z - startp.z, xy_dist);
432   
433      end.gx=startp.x;
434      end.gy=startp.y;
435      end.gz=startp.z;
436
437      end.ground_x_rotate=0;
438      end.ground_y_rotate=0;
439
440      end.ground_rotate=xy_theta;
441      end.horizon_rotate=-z_theta;
442   
443      end.roll = 0;
444
445      start=end;
446    }
447  } 
448}
449
450void g1_view_state_class::update_watch_mode()
451{
452  start=end;
453
454  i4_bool next=i4_F;
455 
456 
457  // see if the next camera has higher priority
458  if ((next_cam.type>current_cam.type && current_cam.time_elapsed>current_cam.min_time) ||
459      (next_cam.type!=G1_WATCH_INVALID && current_cam.time_elapsed>current_cam.max_time))
460    next=i4_T;
461 
462 
463  if (!current_cam.follow_object.get()) // object following is gone   
464    next=i4_T;
465
466  if (current_cam.type==G1_WATCH_INVALID)
467    next=i4_T;
468 
469  if (next)
470    use_next_cam();
471           
472  if (current_cam.type==G1_WATCH_INVALID)
473    return ;
474
475 
476  g1_object_class *obj_to_watch=current_cam.follow_object.get();
477  g1_object_class *camera_at=current_cam.camera_at.get();
478
479  if (camera_at)
480  {
481    end.gx=camera_at->x;
482    end.gy=camera_at->y;
483    end.gz=camera_at->h;   
484  }
485
486 
487  if (obj_to_watch)
488  {
489    i4_3d_vector watch=i4_3d_vector(obj_to_watch->x, obj_to_watch->y, obj_to_watch->h);
490   
491    float xy_theta=i4_atan2(watch.y - end.gy, watch.x - end.gx);
492    float xy_dist=sqrt((watch.y - end.gy) * (watch.y - end.gy) +
493                       (watch.x - end.gx) * (watch.x - end.gx));
494
495    float z_theta=i4_atan2(watch.z - end.gz, xy_dist);
496   
497
498    float turn_speed=li_get_float(li_get_value(watch_camera_turn_speed.get()),0);
499
500    if (current_cam.time_elapsed==0)  // ifrst tick it's ok to snap
501    {
502      end.ground_rotate=xy_theta;
503      end.horizon_rotate=-z_theta;
504    }
505    else
506    {
507      i4_rotate_to(end.ground_rotate, xy_theta, turn_speed);                       
508      i4_rotate_to(end.horizon_rotate, -z_theta, turn_speed);
509    }
510   
511    end.roll = 0;
512   
513  }
514
515  current_cam.time_elapsed++;
516
517 
518  start_end_interpolate_fraction=0.0;
519  start_end_interpolate_fraction_step=1.0;
520}
521
522void g1_view_state_class::update_circle_mode()
523{
524  start=end;
525
526  i4_3d_vector watch=circle.looking_at;
527
528  // camera vel
529  // x = angle of ration about object being watched
530  // y = distance in from object in xy plane
531  // z = height above object
532
533
534  if (end.gz-watch.z<3)
535  {
536    end.gz+=circle.zvel;
537    circle.zvel+=0.0005;
538    if (circle.zvel>0.1)
539      circle.zvel=0.1;
540  }
541
542
543  circle.dist+=circle.dist_vel;
544  circle.dist_vel-=0.01;
545  if (circle.dist_vel<0)
546    circle.dist_vel=0;
547
548 
549  circle.theta+=circle.theta_vel;
550
551
552  end.gx=watch.x + cos(circle.theta)*circle.dist;
553  end.gy=watch.y + sin(circle.theta)*circle.dist; 
554
555   
556  float xy_theta=i4_atan2(watch.y - end.gy, watch.x - end.gx);
557  float xy_dist=sqrt((watch.y - end.gy) * (watch.y - end.gy) +
558                     (watch.x - end.gx) * (watch.x - end.gx));
559
560  float z_theta=i4_atan2(watch.z - end.gz, xy_dist);   
561
562  end.ground_rotate=xy_theta;
563  end.horizon_rotate=-z_theta;   
564  end.roll = 0;
565  end.ground_x_rotate=end.ground_y_rotate=0;
566
567  start_end_interpolate_fraction=0.0;
568  start_end_interpolate_fraction_step=1.0;
569}
570
571
572void g1_view_state_class::update_strategy_mode()
573{
574  i4_angle a=end.ground_rotate, move_speed=1.0;
575  start=end;
576
577
578  end.ground_x_rotate=end.ground_y_rotate=0;
579  end.ground_rotate=i4_pi()/2;
580  end.horizon_rotate=i4_pi()/2 - i4_pi()/8;
581  end.roll=0;
582     
583     
584  if (g1_scroll_bits & G1_MOVE_LEFT)
585    g1_current_controller->pan(-sin(a)*move_speed, cos(a)*move_speed, 0);
586
587  if (g1_scroll_bits & G1_MOVE_RIGHT)
588    g1_current_controller->pan(sin(a)*move_speed, -cos(a)*move_speed, 0);
589
590  if (g1_scroll_bits & G1_MOVE_FORWARD)
591    g1_current_controller->pan(cos(a)*move_speed, sin(a)*move_speed, 0);
592
593  if (g1_scroll_bits & G1_MOVE_BACKWARD)
594    g1_current_controller->pan(-cos(a)*move_speed, -sin(a)*move_speed, 0);
595
596  end.gx+=move_offset.x;
597  end.gy+=move_offset.y;
598  move_offset=i4_3d_vector(0,0,0);
599 
600  if (end.gx<2.0) end.gx = 2.0;
601  else if (end.gx>g1_map_width-2.0) end.gx = g1_map_width-2.0;
602  if (end.gy<2.0) end.gy = 2.0;
603  else if (end.gy>g1_map_height-2.0) end.gy = g1_map_height-2.0;
604 
605  end.gz=g1_get_map()->terrain_height(end.gx, end.gy) + g1_resources.startegy_camera_dist;
606
607  start_end_interpolate_fraction=0.0;
608  start_end_interpolate_fraction_step=1.0;
609}   
610
611
612static float g1_pan_speed=0, g1_rotate_speed=0;
613static li_symbol_ref editor_pan_accel("editor_pan_accel");
614static li_symbol_ref editor_rotate_accel("editor_rotate_accel");
615
616void g1_view_state_class::update_edit_mode()
617{
618  start_end_interpolate_fraction=1.0;
619  start_end_interpolate_fraction_step=0;
620 
621  i4_angle a=end.ground_rotate; 
622
623  end.gx+=move_offset.x;
624  end.gy+=move_offset.y;
625  move_offset=i4_3d_vector(0,0,0);
626
627     
628  if (g1_scroll_bits & (G1_ROTATE_DOWN | G1_ROTATE_UP | G1_ROTATE_RIGHT | G1_ROTATE_LEFT))
629    g1_rotate_speed+=li_get_float(li_get_value(editor_rotate_accel.get()),0);
630  else
631    g1_rotate_speed=0;
632 
633  if (g1_scroll_bits & (G1_PAN_DOWN | G1_PAN_UP | G1_PAN_RIGHT | G1_PAN_LEFT |
634                         G1_PAN_FORWARD | G1_PAN_BACKWARD))
635  {
636    g1_pan_speed+=li_get_float(li_get_value(editor_pan_accel.get()),0);
637    if (g1_pan_speed>4)
638      g1_pan_speed=4;
639  }
640  else
641    g1_pan_speed=0;
642
643
644
645  if (g1_scroll_bits & G1_ROTATE_LEFT)
646    g1_current_controller->rotate(g1_rotate_speed, 0);
647 
648  if (g1_scroll_bits & G1_ROTATE_RIGHT)
649    g1_current_controller->rotate(-g1_rotate_speed, 0);
650
651  if (g1_scroll_bits & G1_ROTATE_UP)
652    g1_current_controller->rotate(0, -g1_rotate_speed);
653
654 
655  if (g1_scroll_bits & G1_ROTATE_DOWN)
656    g1_current_controller->rotate(0, g1_rotate_speed);
657 
658 
659  if (g1_scroll_bits & G1_PAN_DOWN)
660    g1_current_controller->pan(0,0,-g1_pan_speed);
661 
662  if (g1_scroll_bits & G1_PAN_UP)
663    g1_current_controller->pan(0,0,g1_pan_speed);
664
665  if (g1_scroll_bits & G1_PAN_LEFT)
666    g1_current_controller->pan(-sin(a)*g1_pan_speed, cos(a)*g1_pan_speed,0);
667
668  if (g1_scroll_bits & G1_PAN_RIGHT)
669    g1_current_controller->pan(sin(a)*g1_pan_speed, -cos(a)*g1_pan_speed,0);
670
671  if (g1_scroll_bits & G1_PAN_FORWARD)
672    g1_current_controller->pan(cos(a)*g1_pan_speed, sin(a)*g1_pan_speed,0);
673
674  if (g1_scroll_bits & G1_PAN_BACKWARD)
675    g1_current_controller->pan(-cos(a)*g1_pan_speed, -sin(a)*g1_pan_speed,0);
676}
677
678void g1_view_state_class::update_camera_mode()
679{
680  g1_movie_flow_class *m=g1_get_map()->current_movie;
681  g1_cut_scene_class *cut=m ? m->current() : 0;
682  if (cut)
683  {
684    i4_float cx, cy, cz, tx, ty, tz, xy_theta, z_theta, xy_dist;
685
686    cut->paths[g1_cut_scene_class::CAMERA].get_point(m->get_frame(), cx,cy,cz);
687    cut->paths[g1_cut_scene_class::TARGET].get_point(m->get_frame(), tx,ty,tz);
688
689    xy_theta=i4_atan2(ty-cy, tx-cx);
690    xy_dist=sqrt((ty-cy)*(ty-cy) + (tx-cx)*(tx-cx));
691     
692    z_theta=i4_atan2(tz-cz, xy_dist);
693
694    end.gx=cx; end.gy=cy; end.gz=cz;
695
696    end.ground_rotate=xy_theta;
697    end.horizon_rotate=-z_theta;
698    end.roll = 0;
699  }
700  else
701  {
702    view_mode=G1_WATCH_MODE;
703    update();
704    return;
705  }
706}
707
708// should be called after every tick, updates end camera pos
709void g1_view_state_class::update()
710{
711  if (&g1_current_controller->view==this)
712    g1_change_key_context(view_mode);
713     
714  if (start_end_interpolate_fraction>=1.0)
715  {
716    start=end;
717    start_end_interpolate_fraction_step=1.0;
718    start_end_interpolate_fraction=0;
719  }
720  else
721    start_end_interpolate_fraction+=start_end_interpolate_fraction_step;
722 
723 
724  switch (view_mode)
725  {
726    case G1_EDIT_MODE :
727      update_edit_mode();
728      break;
729     
730    case G1_STRATEGY_MODE :
731      update_strategy_mode();
732      break;
733     
734    case G1_ACTION_MODE :
735      update_action_mode();
736      break;
737
738
739    case G1_FOLLOW_MODE :
740      update_follow_mode();     
741      break;
742   
743    case G1_CAMERA_MODE :
744      update_camera_mode();
745      break;
746
747    case G1_WATCH_MODE :
748      update_watch_mode();
749      break;
750
751    case G1_CIRCLE_WAIT :
752      update_circle_mode();
753      break;
754  }
755 
756}
757 
758
759void g1_view_state_class::calc_transform(i4_transform_class &transform)
760{
761  g1_camera_info_struct *c=get_camera();
762
763    // now calculate our actual transform
764  i4_transform_class tmp; 
765  transform.identity();
766 
767  tmp.rotate_y(i4_pi());
768  transform.multiply(tmp);
769
770  tmp.rotate_x(i4_pi()/2);
771  transform.multiply(tmp);
772     
773  tmp.rotate_z(-i4_pi()/2);
774  transform.multiply(tmp);                                           
775 
776  tmp.rotate_x(-c->roll);
777  transform.multiply(tmp);
778 
779  tmp.rotate_y(-c->horizon_rotate);
780  transform.multiply(tmp);
781
782  tmp.rotate_z(-c->ground_rotate);
783  transform.multiply(tmp); 
784 
785  //action mode is the only mode that specifies these
786  tmp.rotate_y(-c->ground_y_rotate);
787  transform.multiply(tmp);
788 
789  tmp.rotate_x(-c->ground_x_rotate);
790  transform.multiply(tmp);
791 
792  tmp.translate(-c->gx, -c->gy, -c->gz);
793  transform.multiply(tmp);
794 
795  s1_set_camera_pos(transform); 
796}
797
798
799
800void g1_view_state_class::suggest_camera_mode(g1_view_mode_type mode,
801                                              w32 follow_object_global_id)
802{
803  if (mode==G1_CIRCLE_WAIT)
804  {
805    g1_object_class *o=g1_global_id.checked_get(follow_object_global_id);
806    if (o)
807    {
808      circle.zvel=circle.theta=0;
809      circle.theta_vel=0.05;
810      circle.dist=1;
811      circle.dist_vel=0.2;
812      circle.looking_at=i4_3d_vector(o->x, o->y, o->h);
813      end.gz=o->h+0.1;
814    }
815    else return ;
816  }
817
818
819  view_mode=mode;
820  follow_object_id=follow_object_global_id;
821
822
823  switch (mode)
824  {
825    case G1_STRATEGY_MODE :
826      g1_demo_script_add("(strategy_mode)");
827      break;
828
829    case G1_ACTION_MODE :
830      g1_demo_script_add("(action_mode)");
831      break;
832
833    case G1_FOLLOW_MODE :
834      g1_demo_script_add("(follow_mode)");
835      break;
836  }
837
838}
839
840
841void g1_view_state_class::set_camera_position(float game_x, float game_y)
842{
843  move_offset.x=game_x-end.gx;
844  move_offset.y=game_y-end.gy;   
845
846  char cmd[50];
847  sprintf(cmd, "(set_camera_pos %0.2f %0.2f)", game_x, game_y);
848  g1_demo_script_add(cmd);
849}
850
851void g1_view_state_class::suggest_camera_event(g1_camera_event &event)
852{
853  pf_suggest_camera_event.start();
854
855  if (event.type==G1_WATCH_FORCE)
856  {
857    next_cam=event;
858    suggest_camera_mode(G1_WATCH_MODE, event.follow_object.get() ?
859                        event.follow_object->global_id : 0 );
860  }
861 
862#if 0
863  if (event.type>next_cam.type)
864  {
865    next_cam=event;
866    if (event.type==G1_WATCH_FORCE)
867      suggest_camera_mode(G1_WATCH_MODE, event.follow_object.get() ?
868                          event.follow_object->global_id : 0 );
869  }
870
871  // see if next is same type & at the caera location
872  else
873  {
874    i4_bool current_dead=i4_F;
875    // object we are watching is dead
876    g1_map_piece_class *mp;
877    mp=g1_map_piece_class::cast(current_cam.follow_object.get());
878    if (mp && mp->health<=0)
879      current_dead=i4_T;
880   
881    if ((current_dead || event.type==next_cam.type) &&
882        next_cam.camera_at.get()!=current_cam.camera_at.get())
883    {
884      g1_object_class *watch_obj=next_cam.follow_object.get();
885      if (watch_obj)
886      {
887        i4_3d_vector pos=i4_3d_vector(watch_obj->x, watch_obj->y, watch_obj->h);       
888        g1_object_class *cam_object=g1_find_closest_field_camera(pos);     
889        if (cam_object && cam_object==current_cam.camera_at.get())
890          current_cam.camera_at=cam_object;
891      }
892    }
893  }
894#endif
895 
896  pf_suggest_camera_event.stop();
897}
898
899
900void g1_view_state_class::get_camera_pos(i4_3d_vector &v)
901{
902  v.x=current.gx;
903  v.y=current.gy;
904  v.z=current.gz;
905}
906
907float g1_view_state_class::dist_sqrd(const i4_3d_vector &v)
908{
909  float d=(end.gx-v.x)*(end.gx-v.x) +
910          (end.gy-v.y)*(end.gy-v.y) +
911          (end.gz-v.z)*(end.gz-v.z);
912  return d;
913}
914
915
916void g1_view_state_class::zoom(float dist)
917{
918  float xy_contribute=fabs(cos(end.horizon_rotate));
919
920  i4_3d_vector move_vector(cos(end.ground_rotate) * xy_contribute,
921                           sin(end.ground_rotate) * xy_contribute,
922                           -sin(end.horizon_rotate));
923 
924  end.gx+=move_vector.x * dist;
925  end.gy+=move_vector.y * dist;
926  end.gz+=move_vector.z * dist;
927}
928
929void g1_view_state_class::pan(i4_float x, i4_float y, i4_float z)
930{
931  end.gx+=x;
932  end.gy+=y;
933  end.gz+=z;
934}
935
936void g1_view_state_class::rotate(i4_float about_game_z, i4_float up_down)
937{
938  end.horizon_rotate+=up_down;
939  end.ground_rotate+=about_game_z;
940}
941
942g1_view_state_class *g1_current_view_state()
943{
944  if (!g1_current_controller.get())
945    return 0;
946  else
947    return &g1_current_controller->view;
948}
949
950li_automatic_add_function(g1_action_mode, "action_mode"); 
951li_automatic_add_function(g1_strategy_mode, "strategy_mode"); 
952li_automatic_add_function(g1_follow_mode, "follow_mode"); 
953li_automatic_add_function(g1_set_camera_position, "set_camera_pos"); 
954
955li_automatic_add_function(g1_camera_mode, "camera_mode");
956li_automatic_add_function(g1_set_current_camera, "set_current_camera"); 
957li_automatic_add_function(g1_toggle_follow_mode, "toggle_follow_mode");
Note: See TracBrowser for help on using the repository browser.