1 module armos.graphics.camera;
2 
3 import armos.graphics;
4 import armos.math;
5 import armos.events;
6 
7 /++
8 Cameraを表すinterfaceです.Cameraで写したい処理をbegin()とend()の間に記述します.
9 +/
10 interface Camera{
11     public{
12         /++
13             projectionMatrixを取得します.
14         +/
15         Matrix4f projectionMatrix();
16         
17         /++
18             viewMatrixを取得します.
19         +/
20         Matrix4f viewMatrix();
21 
22         /++
23             Cameraの位置を表します.
24         +/
25         Vector3f position();
26         
27         ///
28         Camera position(in Vector3f p);
29         
30         /++
31             Cameraが映す対象の位置を表します.
32         +/
33         Vector3f target();
34         
35         ///
36         Camera target(in Vector3f v);
37 
38         /++
39             Cameraの方向を表します.
40         +/
41         Vector3f up();
42         
43         ///
44         Camera up(in Vector3f v);
45 
46         /**
47           Cameraの視野角を表します.単位はdegreeです.
48          **/
49         double fov();
50         
51         ///
52         Camera fov(in double f);
53 
54         /++
55             描画を行う最短距離です.
56         +/
57         double nearDist();
58         
59         ///
60         Camera nearDist(in double n);
61         
62         /++
63             描画を行う最長距離です.
64         +/
65         double farDist();
66         
67         ///
68         Camera farDist(in double f);
69             
70         /++
71             Cameraで表示する処理を開始します.
72         +/
73         Camera begin();
74         
75         /++
76             Cameraで表示する処理を終了します.
77         +/
78         Camera end();
79     }//public
80 }//interface Camera
81 
82 ///
83 class DefaultCamera: Camera{
84     mixin CameraImpl;
85 }
86 
87 mixin template CameraImpl(){
88     import armos.math;
89     import armos.graphics;
90     import armos.app;
91     private alias T = typeof(this);
92     public{
93         /++
94             projectionMatrixを取得します.
95         +/
96         Matrix4f projectionMatrix()const{return _projectionMatrix;}
97 
98         ///
99         Matrix4f viewMatrix()const{return _viewMatrix;}
100         
101         /++
102             Cameraの位置を表します.
103         +/
104         Vector3f position()const{return _position;}
105         
106         ///
107         T position(in Vector3f p){_position = p; return this;}
108         
109 
110         /++
111             Cameraが映す対象の位置を表します.
112         +/
113         Vector3f target()const{return _target;}
114         
115         ///
116         T target(in Vector3f v){_target = v; return this;}
117 
118         /++
119             Cameraの方向を表します.
120         +/
121         Vector3f up()const{return _up;}
122         
123         ///
124         T up(in Vector3f v){_up = v; return this;}
125 
126         /**
127           Cameraの視野角を表します.単位はdegreeです.
128          **/
129         double fov()const{return _fov;}
130         
131         ///
132         T fov(in double f){_fov = f; return this;}
133 
134         /++
135             描画を行う最短距離です.
136         +/
137         double nearDist()const{return _nearDist;}
138         
139         ///
140         T nearDist(in double n){
141             _nearDist = n;
142             return this;
143         }
144 
145         /++
146             描画を行う最長距離です.
147         +/
148         double farDist()const{return _farDist;}
149         
150         ///
151         T farDist(in double f){
152             _farDist = f;
153             return this;
154         }
155 
156         /++
157             Cameraで表示する処理を開始します.
158         +/
159         T begin(){
160             _viewMatrix = lookAtViewMatrix(
161                     _position, 
162                     _target, 
163                     _up
164                     );
165 
166             _projectionMatrix = perspectiveMatrix(
167                     _fov,
168                     windowAspect,
169                     _nearDist,
170                     _farDist
171                     );
172 
173             pushViewMatrix;
174             loadViewMatrix(_viewMatrix);
175             pushProjectionMatrix;
176             loadProjectionMatrix(_projectionMatrix);
177             multProjectionMatrix(scalingMatrix!float(1f, -1f, 1f));
178             return this;
179         }
180 
181         /++
182             Cameraで表示する処理を終了します.
183         +/
184         T end(){
185             popViewMatrix;
186             popProjectionMatrix;
187             return this;
188         }
189     }
190 
191     private{
192         Matrix4f _projectionMatrix;
193         Matrix4f _viewMatrix;
194         
195         Vector3f _position = Vector3f.zero;
196         Vector3f _target   = Vector3f.zero;
197         Vector3f _up       = Vector3f(0, 1, 0);
198         
199         double   _fov      = 60.0;
200         double   _nearDist = 0.1;
201         double   _farDist  = 10000.0;
202     }
203 }
204 
205 import armos.app;
206 import armos.events;
207 
208 /++
209     Deprecated: WIP
210 +/
211 class EasyCam : Camera{
212     mixin CameraImpl;
213     
214     private{
215         alias N = float;
216         alias Q = Quaternion!(N);
217         alias V3 = Vector!(N, 3);
218         alias V4 = Vector!(N, 4);
219         alias M33 = Matrix!(N, 3, 3);
220         alias M44 = Matrix!(N, 4, 4);
221     }
222     
223     public{
224         this(){
225             addListener(currentEvents.mouseMoved, this, &this.mouseMoved);
226             addListener(currentEvents.mouseReleased, this, &this.mouseReleased);
227             addListener(currentEvents.mousePressed, this, &this.mousePressed);
228             addListener(currentEvents.update, this, &this.update);
229 
230             reset;
231         }
232 
233         void reset(){
234             _down = Q.unit;
235             _now = Q.unit;
236             _rotation = M44.identity;
237             _translation = M44.identity;
238             _translationDelta = M44.identity;
239             _isDrag = false;
240             _radiusTranslation = N(1);
241             _radius = N(1);
242 
243             _oldMousePosition = V3.zero;
244             _currentMousePosition = V3.zero;
245             _mouseMovingDirection = V3.zero;
246         }
247     }//public
248 
249     private{
250         Q _down;
251         Q _now;
252         M44 _rotation;
253         M44 _translation;
254         M44 _translationDelta;
255         bool _isDrag;
256         N _radiusTranslation;
257         N _radius;
258 
259         V3 _oldMousePosition;
260         V3 _currentMousePosition;
261         V3 _mouseMovingDirection;
262 
263         void mouseMoved(ref MouseMovedEventArg message){
264             _currentMousePosition = V3(message.x, message.y, 0);
265 
266         }
267 
268         void mouseReleased(ref MouseReleasedEventArg message){
269             _isDrag = false;
270         }
271 
272         void mousePressed(ref MousePressedEventArg message){
273             _isDrag = true;
274         }
275 
276         void update(ref EventArg arg){
277             _oldMousePosition = _currentMousePosition;
278             _mouseMovingDirection = _currentMousePosition - _oldMousePosition;
279         }
280     }//private
281 }//class EasyCam
282 
283 unittest{
284     assert(__traits(compiles, (){
285                 auto cam = new EasyCam;
286                 }));
287 }