1 /+ 2 The MIT License (MIT) 3 4 Copyright (c) <2013> <Oleg Butko (deviator), Anton Akzhigitov (Akzwar)> 5 6 Permission is hereby granted, free of charge, to any person obtaining a copy 7 of this software and associated documentation files (the "Software"), to deal 8 in the Software without restriction, including without limitation the rights 9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 copies of the Software, and to permit persons to whom the Software is 11 furnished to do so, subject to the following conditions: 12 13 The above copyright notice and this permission notice shall be included in 14 all copies or substantial portions of the Software. 15 16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 THE SOFTWARE. 23 +/ 24 25 module des.space.camera; 26 27 public import des.space.node; 28 public import des.space.resolver; 29 30 import std.math; 31 32 /// 33 class Camera: SpaceNode 34 { 35 mixin SpaceNodeHelper!false; 36 37 /// 38 Resolver resolver; 39 40 /// 41 Transform projection, transform; 42 43 /// 44 this( SpaceNode par=null ) 45 { 46 spaceParent = par; 47 resolver = new Resolver; 48 } 49 50 const 51 { 52 /// 53 mat4 resolve( const(SpaceNode) obj ) { return resolver(obj, this); } 54 /// 55 mat4 matrix() @property { return getMatrix( transform ); } 56 } 57 } 58 59 /// 60 class LookAtTransform : Transform 61 { 62 /// 63 vec3 pos=vec3(0), target=vec3(0), up=vec3(0,0,1); 64 65 /// 66 @property mat4 matrix() const 67 { return calcLookAt( pos, target, up ); } 68 } 69 70 /// 71 class PerspectiveTransform : Transform 72 { 73 protected: 74 float _fov = 70; 75 float _ratio = 4.0f / 3.0f; 76 float _near = 1e-1; 77 float _far = 1e5; 78 79 mat4 self_mtr; 80 81 void recalc() { self_mtr = calcPerspective( _fov, _ratio, _near, _far ); } 82 83 public: 84 85 @property 86 { 87 /// 88 float fov() const { return _fov; } 89 /// 90 float fov( float v ) in { assert(v>0); } 91 body { _fov = v; recalc(); return _fov; } 92 93 /// 94 float ratio() const { return _ratio; } 95 /// 96 float ratio( float v ) in { assert(v>0); } 97 body { _ratio = v; recalc(); return _ratio; } 98 99 /// 100 float near() const { return _near; } 101 /// 102 float near( float v ) in { assert(v>0); } 103 body { _near = v; recalc(); return _near; } 104 105 /// 106 float far() const { return _far; } 107 /// 108 float far( float v ) in { assert(v>0); } 109 body { _far = v; recalc(); return _far; } 110 111 /// 112 mat4 matrix() const { return self_mtr; } 113 } 114 } 115 116 /++ simple lookAt perspective camera +/ 117 class SimpleCamera : Camera 118 { 119 protected: 120 LookAtTransform look_tr; 121 PerspectiveTransform perspective; 122 123 public: 124 125 /// 126 this( SpaceNode p=null ) 127 { 128 super(p); 129 look_tr = new LookAtTransform; 130 look_tr.up = vec3(0,0,1); 131 transform = look_tr; 132 perspective = new PerspectiveTransform; 133 projection = perspective; 134 } 135 136 @property 137 { 138 /// 139 void fov( float val ) { perspective.fov = val; } 140 /// 141 float fov() const { return perspective.fov; } 142 143 /// 144 void ratio( float val ) { perspective.ratio = val; } 145 /// 146 float ratio() const { return perspective.ratio; } 147 148 /// 149 void near( float val ) { perspective.near = val; } 150 /// 151 float near() const { return perspective.near; } 152 153 /// 154 void far( float val ) { perspective.far = val; } 155 /// 156 float far() const { return perspective.far; } 157 158 /// 159 void pos( in vec3 val ) { look_tr.pos = val; } 160 /// 161 vec3 pos() const { return look_tr.pos; } 162 163 /// 164 void up( in vec3 val ) { look_tr.up = val; } 165 /// 166 vec3 up() const { return look_tr.up; } 167 168 /// 169 void target( in vec3 val ) { look_tr.target = val; } 170 /// 171 vec3 target() const { return look_tr.target; } 172 } 173 } 174 175 private: 176 177 mat4 calcLookAt( in vec3 pos, in vec3 trg, in vec3 up ) 178 { 179 auto z = (pos-trg).e; 180 auto x = cross(up,z).e; 181 vec3 y; 182 if( x ) y = cross(z,x).e; 183 else 184 { 185 y = cross(z,vec3(1,0,0)).e; 186 x = cross(y,z).e; 187 } 188 return mat4( x.x, y.x, z.x, pos.x, 189 x.y, y.y, z.y, pos.y, 190 x.z, y.z, z.z, pos.z, 191 0, 0, 0, 1 ); 192 } 193 194 mat4 calcPerspective( float fov_degree, float ratio, float znear, float zfar ) 195 { 196 /+ fov conv to radians and div 2 +/ 197 float h = 1.0 / tan( fov_degree * PI / 360.0 ); 198 float w = h / ratio; 199 200 float depth = znear - zfar; 201 float q = ( znear + zfar ) / depth; 202 float n = ( 2.0f * znear * zfar ) / depth; 203 204 return mat4( w, 0, 0, 0, 205 0, h, 0, 0, 206 0, 0, q, n, 207 0, 0, -1, 0 ); 208 } 209 210 mat4 calcOrtho( float w, float h, float znear, float zfar ) 211 { 212 float x = znear - zfar; 213 return mat4( 2/w, 0, 0, 0, 214 0, 2/h, 0, 0, 215 0, 0, -1/x, 0, 216 0, 0, znear/x, 1 ); 217 }