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 }