1 module camera;
2 
3 import std.math;
4 
5 import des.space;
6 import des.app;
7 
8 class MCamera : SimpleCamera
9 {
10 protected:
11     vec3 orb;
12     vec2 rot;
13 
14     float rotate_coef = 80.0f;
15     float offset_coef = 50.0f;
16     float y_angle_limit = PI_2 - 0.01;
17 
18 public:
19     this()
20     {
21         super();
22         orb = vec3( 5, 1, 3 );
23         look_tr.target = vec3(0,0,0);
24         look_tr.up = vec3(0,0,1);
25         near = 0.001;
26         updatePos();
27     }
28 
29     void mouseReaction( in MouseEvent ev )
30     {
31         if( ev.type == MouseEvent.Type.WHEEL )
32             moveFront( -ev.whe.y * 0.1 );
33 
34         if( ev.type == ev.Type.MOTION )
35         {
36             if( ev.isPressed( ev.Button.LEFT ) )
37             {
38                 auto frel = vec2( ev.rel ) * vec2(-1,1);
39                 auto angle = frel / rotate_coef;
40                 addRotate( angle );
41             }
42             if( ev.isPressed( ev.Button.MIDDLE ) )
43             {
44                 auto frel = vec2( ev.rel ) * vec2(-1,1);
45                 auto offset = frel / offset_coef * sqrt( orb.len );
46                 moveCenter( offset );
47             }
48         }
49     }
50 
51 protected:
52     void moveFront( float dist )
53     {
54         orb += orb * dist;
55         if( orb.len2 < 1 ) orb = orb.e;
56         updatePos();
57     }
58 
59     void addRotate( in vec2 angle )
60     {
61         rot = normRotate( rot + angle );
62         orb = vec3( cos(rot.x) * cos(rot.y),
63                     sin(rot.x) * cos(rot.y),
64                     sin(rot.y) ) * orb.len;
65         updatePos();
66     }
67 
68     void moveCenter( in vec2 offset )
69     {
70         auto lo = (look_tr.matrix * vec4(offset,0,0)).xyz;
71         look_tr.target += lo;
72         updatePos();
73     }
74 
75     void updatePos() { pos = orb + look_tr.target; }
76 
77     vec2 normRotate( in vec2 r )
78     {
79         vec2 ret = r;
80         if( ret.y > y_angle_limit ) ret.y = y_angle_limit;
81         if( ret.y < -y_angle_limit ) ret.y = -y_angle_limit;
82         return ret;
83     }
84 }