1 module sbylib.graphics.util.cameracontrol; 2 3 import sbylib.graphics.camera : Camera; 4 import sbylib.event; 5 import sbylib.math; 6 import sbylib.wrapper.glfw; 7 8 class CameraControl { 9 10 EventContext context; 11 alias context this; 12 13 private Window window; 14 private Camera camera; 15 private vec3 arrivalPos; 16 private quat arrivalRot; 17 18 float speed; 19 20 this(Window window, Camera camera) { 21 this.window = window; 22 this.camera = camera; 23 this.context = new EventContext; 24 this.arrivalPos = camera.pos; 25 this.arrivalRot = quat(0,0,0,1); 26 this.speed = 0.03; 27 28 with (context()) { 29 vec2 basePoint; 30 when(MouseButton.Button1.pressed.on(window)).then({basePoint = window.mousePos;}); 31 when(MouseButton.Button1.pressed.on(window)).then({ 32 if (window.cursorMode == CursorMode.Normal) { 33 window.cursorMode = CursorMode.Disabled; 34 } else { 35 window.cursorMode = CursorMode.Normal; 36 } 37 }); 38 39 alias accel = (vec3 v) { 40 if (KeyButton.LeftShift.isPressed.on(window)) { 41 this.arrivalPos += v * speed * 2; 42 } else { 43 this.arrivalPos += v * speed; 44 } 45 }; 46 when(KeyButton.KeyA.pressing.on(window)).then({ accel(-camera.rot.column[0]); }); 47 when(KeyButton.KeyD.pressing.on(window)).then({ accel(+camera.rot.column[0]); }); 48 when(KeyButton.KeyQ.pressing.on(window)).then({ accel(-camera.rot.column[1]); }); 49 when(KeyButton.KeyE.pressing.on(window)).then({ accel(+camera.rot.column[1]); }); 50 when(KeyButton.KeyW.pressing.on(window)).then({ accel(-camera.rot.column[2]); }); 51 when(KeyButton.KeyS.pressing.on(window)).then({ accel(+camera.rot.column[2]); }); 52 when((Ctrl + KeyButton.KeyD).pressed.on(window)).then({ window.shouldClose = true; }); 53 54 when(mouse.moved.on(window)).then({ 55 if (window.cursorMode == CursorMode.Normal) return; 56 auto dif = -(vec2(window.mousePos) - basePoint) * 0.003; 57 auto angle = dif.length.rad; 58 auto axis = safeNormalize(arrivalRot.toMatrix3 * vec3(dif.y, dif.x, 0)); 59 arrivalRot = quat.axisAngle(axis, angle) * arrivalRot; 60 auto forward = arrivalRot.baseZ; 61 auto side = normalize(cross(vec3(0,1,0), forward)); 62 auto up = normalize(cross(forward, side)); 63 arrivalRot = mat3(side, up, forward).toQuaternion; 64 basePoint = window.mousePos; 65 }); 66 67 when(Frame).then({ 68 camera.pos = mix(camera.pos, arrivalPos, 0.1); 69 camera.rot = slerp(camera.rot.toQuaternion, arrivalRot, 0.1).normalize.toMatrix3; 70 }); 71 72 when(context.unbound).then({ 73 window.cursorMode = CursorMode.Normal; 74 }); 75 } 76 } 77 78 ~this() { 79 context.destroy(); 80 window.cursorMode = CursorMode.Normal; 81 } 82 }