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