1 /** 2 Copyright: Copyright (c) 2014-2016 Andrey Penechko. 3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 4 Authors: Andrey Penechko. 5 */ 6 7 module voxelman.utils.fpscamera; 8 9 import std.experimental.logger; 10 11 import dlib.math.matrix; 12 import dlib.math.affine; 13 import dlib.math.vector; 14 import dlib.math.quaternion; 15 import dlib.math.utils; 16 17 struct FpsCamera 18 { 19 void move(Vector3f vec) 20 { 21 if (isUpdated == false) update(); 22 position += vec; 23 isUpdated = false; 24 } 25 26 void moveAxis(vec3 vec) 27 { 28 if (isUpdated == false) update(); 29 30 // Strafe 31 vec3 right = rotationQuatHor.rotate(vec3(1,0,0)); 32 position += right * vec.x; 33 34 // Move up/down 35 position.y += vec.y; 36 37 // Move forward 38 vec3 target = rotationQuatHor.rotate(vec3(0,0,-1)); 39 position += target * vec.z; 40 41 isUpdated = false; 42 } 43 44 void rotate(vec2 angles) 45 { 46 heading += angles * sensivity; 47 clampHeading(); 48 isUpdated = false; 49 } 50 51 void setHeading(vec2 heading) 52 { 53 this.heading = heading; 54 clampHeading(); 55 isUpdated = false; 56 } 57 58 void clampHeading() 59 { 60 heading.x %= 360; 61 heading.y = clamp!float(heading.y, ANGLE_VERT_MIN, ANGLE_VERT_MAX); 62 } 63 64 void update() 65 { 66 rotationQuatHor = rotationQuaternion!float(vec3(0,1,0), degtorad!float(heading.x)); 67 rotationQuatVert = rotationQuaternion!float(vec3(1,0,0), degtorad!float(heading.y)); 68 69 rotationQuat = rotationQuatHor * rotationQuatVert; 70 rotationQuat.normalize(); 71 calcVectors(); 72 73 Matrix4f rotation = rotationQuat.toMatrix4x4.inverse; 74 Matrix4f translation = translationMatrix(-position); 75 76 cameraToClipMatrix = rotation * translation; 77 isUpdated = true; 78 } 79 80 float* cameraMatrix() 81 { 82 if(!isUpdated) update(); 83 return &(cameraToClipMatrix.arrayof[0]); 84 } 85 86 void printVectors() 87 { 88 infof("camera pos\t%s\ttarget\t%s\tup\t%s\tright\t%s", 89 position, target, up, right); 90 } 91 92 private void calcVectors() 93 { 94 target = rotationQuat.rotate(vec3(0,0,-1)); 95 up = rotationQuat.rotate(vec3(0,1,0)); 96 right = rotationQuat.rotate(vec3(1,0,0)); 97 } 98 99 Matrix4f perspective() 100 { 101 return perspectiveMatrix(fov, aspect, near, far); 102 } 103 104 float sensivity = 1.0f; 105 float fov = 60; // field of view 106 float aspect = 1; // window width/height 107 float near = 0.01; 108 float far = 4000; 109 110 vec3 position = vec3(0, 0, 0); 111 vec2 heading = vec2(0, 0); // hor, vert 112 113 vec3 target = vec3(0, 0, -1); 114 vec3 up = vec3(0, 1, 0); 115 vec3 right = vec3(1, 0, 0); 116 117 enum ANGLE_VERT_MIN = -90.0f; //minimum pitch 118 enum ANGLE_VERT_MAX = 90.0f; //maximal pitch 119 120 Matrix4f cameraToClipMatrix; 121 122 Quaternionf rotationQuat; 123 Quaternionf rotationQuatHor; 124 Quaternionf rotationQuatVert; 125 126 bool isUpdated = false; 127 }