1 module grape.camera;
2 
3 import derelict.opengl3.gl3;
4 import std.math;
5 import std.stdio;
6 import grape.math;
7 import grape.window : WINDOW_WIDTH, WINDOW_HEIGHT;
8 
9 class Camera {
10   public :
11     /**
12      * 位置、姿勢の設定
13      *
14      * GLUTのgluLookAtと同じです。
15      * eye:    視点
16      * center: 注視点
17      * up:     上方向
18      */
19     void look_at(Vec3 eye, Vec3 center, Vec3 up) {
20       Vec3 f = Vec3(center.x-eye.x, center.y-eye.y, center.z-eye.z);
21 
22       f.normalize;
23       up.normalize;
24 
25       Vec3 s = f.cross(up);
26       Vec3 u = s.cross(f);
27 
28       _view = Mat4( s.x, u.x, -f.x, 0,
29                     s.y, u.y, -f.y, 0,
30                     s.z, u.z, -f.z, 0,
31                     0, 0, 0, 1 ).translate(-eye.x, -eye.y, -eye.z);
32     }
33 
34     @property {
35       /**
36        * view, projection行列を掛け合わせたMat4型を返す
37        *
38        * 基本的にこれをuniformのpvmMatrixに送ります。
39        */
40       Mat4 pvMat4() {
41         return _proj.multiply(_view);
42       }
43     }
44 
45   protected:
46     Mat4 _proj, _view;
47 }
48 
49 class PerspectiveCamera : Camera {
50   public:
51     this(in float fovy, in float aspect, in float near, in float far) {
52       perspective(fovy, aspect, near, far);
53     }
54 
55     /**
56      * 視界の設定
57      *
58      * GLUTのgluPerspectiveと同じです。
59      * fovy:    視野角
60      * aspect:  縦横比(通常は[画面幅/高さ]です)
61      * near:   一番近いz座標
62      * far:    一番遠いz座標
63      */
64     void perspective(in float fovy, in float aspect, in float near, in float far) {
65       // translate to grape.math
66       auto cot = delegate float(float x){ return 1 / tan(x); };
67       auto f = cot(fovy/2);
68 
69       _proj.set( f/aspect, 0, 0, 0,
70                  0, f, 0, 0,
71                  0, 0, (far+near)/(near-far), -1,
72                  0, 0, (2*far*near)/(near-far), 0 );
73     }
74 }
75 
76 class OrthographicCamera : Camera {
77   this(in float left, in float right, in float top, in float bottom, in float near, in float far) {
78     orthographic(left, right, top, bottom, near, far);
79   }
80 
81   void orthographic(in float left, in float right, in float top, in float bottom, in float near, in float far) {
82     auto a = 2 / (right - left);
83     auto b = 2 / (top - bottom);
84     auto c = -2 / (far - near);
85     auto tx = -(right + left) / (right - left);
86     auto ty = -(top + bottom) / (top - bottom);
87     auto tz = -(far + near) / (far - near);
88 
89     _proj.set( a, 0, 0, 0,
90                0, b, 0, 0,
91                0, 0, c, 0,
92                tx, ty, tz, 1 );
93   }
94 
95 }
96 
97 /*
98 class Camera {
99   public :
100     this() {
101       Vec3 eye = Vec3(0, 0, 1);
102       Vec3 center = Vec3(0, 0, 0);
103       Vec3 up = Vec3(0, 1, 0);
104 
105       perspective(45.0, cast(float)WINDOW_WIDTH/WINDOW_HEIGHT, 0.1, 100);
106       look_at(eye, center, up);
107     }
108 
109     this(in float near, in float far) {
110       Vec3 eye = Vec3(0, 0, 1);
111       Vec3 center = Vec3(0, 0, 0);
112       Vec3 up = Vec3(0, 1, 0);
113 
114       perspective(45.0, cast(float)WINDOW_WIDTH/WINDOW_HEIGHT, near, far); //TODO
115       look_at(eye, center, up);
116     }
117 
118 
119   private:
120     void set(Vec3 eye, Vec3 center, Vec3 up) {
121       //_manip = Manip(eye); // TODO 毎回作ってる
122       _center = center;
123       //_manip.add(up); // TODO Manipを毎回作ってないと危険
124     }
125 
126     Mat4 _proj, _view;
127     Vec3 _center;
128 }
129 */
130