<!DOCTYPE html>
< html lang = "en-US" >
< head >
< meta charset = "utf-8" >
< meta name = "viewport" content = "width=device-width,initial-scale=1" >
< title > A Better Camera | Learn Wgpu< / title >
< meta name = "description" content = "" >
< meta name = "generator" content = "VuePress 1.4.0" >
< meta property = "article:modified_time" content = "2020-11-25T23:51:22.000Z" > < meta property = "og:site_name" content = "Learn Wgpu" > < meta property = "og:title" content = "A Better Camera" > < meta property = "og:type" content = "website" > < meta property = "og:url" content = "/intermediate/tutorial12-camera/" > < meta name = "twitter:title" content = "A Better Camera" > < meta name = "twitter:url" content = "/intermediate/tutorial12-camera/" > < meta name = "twitter:card" content = "summary_large_image" > < meta name = "twitter:label1" content = "Written by" > < meta name = "twitter:data2" content = "Benjamin R Hansen" > < meta name = "twitter:creator" content = "https://twitter.com/sotrh760" >
< link rel = "preload" href = "/learn-wgpu/assets/css/0.styles.7acc6ef6.css" as = "style" > < link rel = "preload" href = "/learn-wgpu/assets/js/app.00a40aeb.js" as = "script" > < link rel = "preload" href = "/learn-wgpu/assets/js/2.da3fd46f.js" as = "script" > < link rel = "preload" href = "/learn-wgpu/assets/js/14.f852c057.js" as = "script" > < link rel = "preload" href = "/learn-wgpu/assets/js/22.2132e362.js" as = "script" > < link rel = "prefetch" href = "/learn-wgpu/assets/js/10.de8cadfb.js" > < link rel = "prefetch" href = "/learn-wgpu/assets/js/11.65c8dcc2.js" > < link rel = "prefetch" href = "/learn-wgpu/assets/js/12.26aabcb1.js" > < link rel = "prefetch" href = "/learn-wgpu/assets/js/13.78eedf26.js" > < link rel = "prefetch" href = "/learn-wgpu/assets/js/15.057386b5.js" > < link rel = "prefetch" href = "/learn-wgpu/assets/js/16.9abecf13.js" > < link rel = "prefetch" href = "/learn-wgpu/assets/js/17.f03fd0c9.js" > < link rel = "prefetch" href = "/learn-wgpu/assets/js/18.d3691f26.js" > < link rel = "prefetch" href = "/learn-wgpu/assets/js/19.e9350ae9.js" > < link rel = "prefetch" href = "/learn-wgpu/assets/js/20.70e640cc.js" > < link rel = "prefetch" href = "/learn-wgpu/assets/js/21.19d2890c.js" > < link rel = "prefetch" href = "/learn-wgpu/assets/js/23.1a88f225.js" > < link rel = "prefetch" href = "/learn-wgpu/assets/js/24.c0cbce8a.js" > < link rel = "prefetch" href = "/learn-wgpu/assets/js/25.2c8435d6.js" > < link rel = "prefetch" href = "/learn-wgpu/assets/js/26.5b0dad74.js" > < link rel = "prefetch" href = "/learn-wgpu/assets/js/27.04f788d9.js" > < link rel = "prefetch" href = "/learn-wgpu/assets/js/28.a3ac06e2.js" > < link rel = "prefetch" href = "/learn-wgpu/assets/js/29.281013fa.js" > < link rel = "prefetch" href = "/learn-wgpu/assets/js/3.2a393c66.js" > < link rel = "prefetch" href = "/learn-wgpu/assets/js/30.dc887be9.js" > < link rel = "prefetch" href = "/learn-wgpu/assets/js/4.6b1a77da.js" > < link rel = "prefetch" href = "/learn-wgpu/assets/js/5.5e4953de.js" > < link rel = "prefetch" href = "/learn-wgpu/assets/js/6.cc40d32a.js" > < link rel = "prefetch" href = "/learn-wgpu/assets/js/7.88810c81.js" > < link rel = "prefetch" href = "/learn-wgpu/assets/js/8.d5139107.js" > < link rel = "prefetch" href = "/learn-wgpu/assets/js/9.ecb6e79c.js" >
< link rel = "stylesheet" href = "/learn-wgpu/assets/css/0.styles.7acc6ef6.css" >
< / head >
< body >
< div id = "app" data-server-rendered = "true" > < div class = "theme-container" > < header class = "navbar" > < div class = "inner" > < div class = "sidebar-button" > < svg xmlns = "http://www.w3.org/2000/svg" aria-hidden = "true" role = "img" viewBox = "0 0 448 512" class = "icon" > < path fill = "currentColor" d = "M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z" > < / path > < / svg > < / div > < a href = "/learn-wgpu/" class = "home-link router-link-active" > <!-- --> < span class = "site-name" > Learn Wgpu< / span > < / a > < div class = "links" > <!-- --> < div class = "search-box" > < input aria-label = "Search" autocomplete = "off" spellcheck = "false" value = "" > <!-- --> < / div > < / div > < / div > < / header > < div class = "sidebar-mask" > < / div > < div class = "docs-layout" > < aside class = "sidebar" > <!-- --> < ul class = "sidebar-links" > < li > < a href = "/learn-wgpu/" class = "sidebar-link" > Introduction< / a > < / li > < li > < section class = "sidebar-group depth-0" > < p class = "sidebar-heading" > < span > Beginner< / span > <!-- --> < / p > < ul class = "sidebar-links sidebar-group-items" > < li > < a href = "/learn-wgpu/beginner/tutorial1-window/" class = "sidebar-link" > Dependencies and the window< / a > < / li > < li > < a href = "/learn-wgpu/beginner/tutorial2-swapchain/" class = "sidebar-link" > The Swapchain< / a > < / li > < li > < a href = "/learn-wgpu/beginner/tutorial3-pipeline/" class = "sidebar-link" > The Pipeline< / a > < / li > < li > < a href = "/learn-wgpu/beginner/tutorial4-buffer/" class = "sidebar-link" > Buffers and Indices< / a > < / li > < li > < a href = "/learn-wgpu/beginner/tutorial5-textures/" class = "sidebar-link" > Textures and bind groups< / a > < / li > < li > < a href = "/learn-wgpu/beginner/tutorial6-uniforms/" class = "sidebar-link" > Uniform buffers and a 3d camera< / a > < / li > < li > < a href = "/learn-wgpu/beginner/tutorial7-instancing/" class = "sidebar-link" > Instancing< / a > < / li > < li > < a href = "/learn-wgpu/beginner/tutorial8-depth/" class = "sidebar-link" > The Depth Buffer< / a > < / li > < li > < a href = "/learn-wgpu/beginner/tutorial9-models/" class = "sidebar-link" > Model Loading< / a > < / li > < / ul > < / section > < / li > < li > < section class = "sidebar-group depth-0" > < p class = "sidebar-heading open" > < span > Intermediate< / span > <!-- --> < / p > < ul class = "sidebar-links sidebar-group-items" > < li > < a href = "/learn-wgpu/intermediate/tutorial10-lighting/" class = "sidebar-link" > Working with Lights< / a > < / li > < li > < a href = "/learn-wgpu/intermediate/tutorial11-normals/" class = "sidebar-link" > Normal Mapping< / a > < / li > < li > < a href = "/learn-wgpu/intermediate/tutorial12-camera/" class = "active sidebar-link" > A Better Camera< / a > < ul class = "sidebar-sub-headers" > < li class = "sidebar-sub-header" > < a href = "/learn-wgpu/intermediate/tutorial12-camera/#the-camera" class = "sidebar-link" > The Camera< / a > < / li > < li class = "sidebar-sub-header" > < a href = "/learn-wgpu/intermediate/tutorial12-camera/#the-projection" class = "sidebar-link" > The Projection< / a > < / li > < li class = "sidebar-sub-header" > < a href = "/learn-wgpu/intermediate/tutorial12-camera/#cleaning-up-main-rs" class = "sidebar-link" > Cleaning up main.rs< / a > < / li > < / ul > < / li > < li > < a href = "/learn-wgpu/intermediate/tutorial13-threading/" class = "sidebar-link" > Multi-threading with Wgpu and Rayon< / a > < / li > < / ul > < / section > < / li > < li > < section class = "sidebar-group collapsable depth-0" > < p class = "sidebar-heading" > < span > Showcase< / span > < span class = "arrow right" > < / span > < / p > <!-- --> < / section > < / li > < li > < a href = "/learn-wgpu/news/" class = "sidebar-link" > News< / a > < / li > < / ul > < / aside > < main class = "page" > < div class = "theme-default-content content__default" > < h1 id = "a-better-camera" > < a href = "#a-better-camera" class = "header-anchor" > #< / a > A Better Camera< / h1 > < p > I've been putting this off for a while. Implementing a camera isn't specifically related to using WGPU properly, but it's been bugging me so let's do it.< / p > < p > < code > main.rs< / code > is getting a little crowded, so let's create a < code > camera.rs< / code > file to put our camera code. The first thing we're going to put in it in is some imports and our < code > OPENGL_TO_WGPU_MATRIX< /
< span class = "token keyword" > use< / span > < span class = "token namespace" > winit< span class = "token punctuation" > ::< / span > event< span class = "token punctuation" > ::< / span > < / span > < span class = "token operator" > *< / span > < span class = "token punctuation" > ;< / span >
< span class = "token keyword" > use< / span > < span class = "token namespace" > winit< span class = "token punctuation" > ::< / span > dpi< span class = "token punctuation" > ::< / span > < / span > < span class = "token class-name" > PhysicalPosition< / span > < span class = "token punctuation" > ;< / span >
< span class = "token keyword" > use< / span > < span class = "token namespace" > std< span class = "token punctuation" > ::< / span > time< span class = "token punctuation" > ::< / span > < / span > < span class = "token class-name" > Duration< / span > < span class = "token punctuation" > ;< / span >
< span class = "token keyword" > use< / span > < span class = "token namespace" > std< span class = "token punctuation" > ::< / span > < / span > < span class = "token keyword" > f32< / span > < span class = "token punctuation" > ::< / span > < span class = "token namespace" > consts< span class = "token punctuation" > ::< / span > < / span > < span class = "token constant" > FRAC_PI_2< / span > < span class = "token punctuation" > ;< / span >
< span class = "token attribute attr-name" > #[rustfmt::skip]< / span >
< span class = "token keyword" > pub< / span > < span class = "token keyword" > const< / span > < span class = "token constant" > OPENGL_TO_WGPU_MATRIX< / span > < span class = "token punctuation" > :< / span > < span class = "token namespace" > cgmath< span class = "token punctuation" > ::< / span > < / span > < span class = "token class-name" > Matrix4< / span > < span class = "token operator" > < < / span > < span class = "token keyword" > f32< / span > < span class = "token operator" > > < / span > < span class = "token operator" > =< / span > < span class = "token namespace" > cgmath< span class = "token punctuation" > ::< / span > < / span > < span class = "token class-name" > Matrix4< / span > < span class = "token punctuation" > ::< / span > < span class = "token function" > new< / span > < span class = "token punctuation" > (< / span >
< span class = "token number" > 1.0< / span > < span class = "token punctuation" > ,< / span > < span class = "token number" > 0.0< / span > < span class = "token punctuation" > ,< / span > < span class = "token number" > 0.0< / span > < span class = "token punctuation" > ,< / span > < span class = "token number" > 0.0< / span > < span class = "token punctuation" > ,< / span >
< span class = "token number" > 0.0< / span > < span class = "token punctuation" > ,< / span > < span class = "token number" > 1.0< / span > < span class = "token punctuation" > ,< / span > < span class = "token number" > 0.0< / span > < span class = "token punctuation" > ,< / span > < span class = "token number" > 0.0< / span > < span class = "token punctuation" > ,< / span >
< span class = "token number" > 0.0< / span > < span class = "token punctuation" > ,< / span > < span class = "token number" > 0.0< / span > < span class = "token punctuation" > ,< / span > < span class = "token number" > 0.5< / span > < span class = "token punctuation" > ,< / span > < span class = "token number" > 0.0< / span > < span class = "token punctuation" > ,< / span >
< span class = "token number" > 0.0< / span > < span class = "token punctuation" > ,< / span > < span class = "token number" > 0.0< / span > < span class = "token punctuation" > ,< / span > < span class = "token number" > 0.5< / span > < span class = "token punctuation" > ,< / span > < span class = "token number" > 1.0< / span > < span class = "token punctuation" > ,< / span >
< span class = "token punctuation" > )< / span > < span class = "token punctuation" > ;< / span >
< / code > < / pre > < / div > < h2 id = "the-camera" > < a href = "#the-camera" class = "header-anchor" > #< / a > The Camera< / h2 > < p > Next we need create a new < code > Camera< / code > struct. We're going to be using a FPS style camera, so we'll store the position and the yaw (horizontal rotation), and pitch (vertical rotation). We'll have a < code > calc_matrix< / code > method to create our view matrix.< / p > < div class = "language-rust extra-class" > < pre class = "language-rust" > < code > < span class = "token attribute attr-name" > #[derive(Debug)]< / span >
< span class = "token keyword" > pub< / span > < span class = "token keyword" > struct< / span > < span class = "token type-definition class-name" > Camera< / span > < span class = "token punctuation" > {< / span >
< span class = "token keyword" > pub< / span > position< span class = "token punctuation" > :< / span > < span class = "token class-name" > Point3< / span > < span class = "token operator" > < < / span > < span class = "token keyword" > f32< / span > < span class = "token operator" > > < / span > < span class = "token punctuation" > ,< / span >
yaw< span class = "token punctuation" > :< / span > < span class = "token class-name" > Rad< / span > < span class = "token operator" > < < / span > < span class = "token keyword" > f32< / span > < span class = "token operator" > > < / span > < span class = "token punctuation" > ,< / span >
pitch< span class = "token punctuation" > :< / span > < span class = "token class-name" > Rad< / span > < span class = "token operator" > < < / span > < span class = "token keyword" > f32< / span > < span class = "token operator" > > < / span > < span class = "token punctuation" > ,< / span >
< span class = "token punctuation" > }< / span >
< span class = "token keyword" > impl< / span > < span class = "token class-name" > Camera< / span > < span class = "token punctuation" > {< / span >
< span class = "token keyword" > pub< / span > < span class = "token keyword" > fn< / span > < span class = "token function-definition function" > new< / span > < span class = "token operator" > < < / span >
< span class = "token class-name" > V< / span > < span class = "token punctuation" > :< / span > < span class = "token class-name" > Into< / span > < span class = "token operator" > < < / span > < span class = "token class-name" > Point3< / span > < span class = "token operator" > < < / span > < span class = "token keyword" > f32< / span > < span class = "token operator" > > > < / span > < span class = "token punctuation" > ,< / span >
< span class = "token class-name" > Y< / span > < span class = "token punctuation" > :< / span > < span class = "token class-name" > Into< / span > < span class = "token operator" > < < / span > < span class = "token class-name" > Rad< / span > < span class = "token operator" > < < / span > < span class = "token keyword" > f32< / span > < span class = "token operator" > > > < / span > < span class = "token punctuation" > ,< / span >
< span class = "token class-name" > P< / span > < span class = "token punctuation" > :< / span > < span class = "token class-name" > Into< / span > < span class = "token operator" > < < / span > < span class = "token class-name" > Rad< / span > < span class = "token operator" > < < / span > < span class = "token keyword" > f32< / span > < span class = "token operator" > > > < / span > < span class = "token punctuation" > ,< / span >
< span class = "token operator" > > < / span > < span class = "token punctuation" > (< / span >
position< span class = "token punctuation" > :< / span > < span class = "token class-name" > V< / span > < span class = "token punctuation" > ,< / span >
yaw< span class = "token punctuation" > :< / span > < span class = "token class-name" > Y< / span > < span class = "token punctuation" > ,< / span >
pitch< span class = "token punctuation" > :< / span > < span class = "token class-name" > P< / span > < span class = "token punctuation" > ,< / span >
< span class = "token punctuation" > )< / span > < span class = "token punctuation" > -> < / span > < span class = "token keyword" > Self< / span > < span class = "token punctuation" > {< / span >
< span class = "token keyword" > Self< / span > < span class = "token punctuation" > {< / span >
position< span class = "token punctuation" > :< / span > position< span class = "token punctuation" > .< / span > < span class = "token function" > into< / span > < span class = "token punctuation" > (< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ,< / span >
yaw< span class = "token punctuation" > :< / span > yaw< span class = "token punctuation" > .< / span > < span class = "token function" > into< / span > < span class = "token punctuation" > (< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ,< / span >
pitch< span class = "token punctuation" > :< / span > pitch< span class = "token punctuation" > .< / span > < span class = "token function" > into< / span > < span class = "token punctuation" > (< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ,< / span >
< span class = "token punctuation" > }< / span >
< span class = "token punctuation" > }< / span >
< span class = "token keyword" > pub< / span > < span class = "token keyword" > fn< / span > < span class = "token function-definition function" > calc_matrix< / span > < span class = "token punctuation" > (< / span > < span class = "token operator" > & < / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > -> < / span > < span class = "token class-name" > Matrix4< / span > < span class = "token operator" > < < / span > < span class = "token keyword" > f32< / span > < span class = "token operator" > > < / span > < span class = "token punctuation" > {< / span >
< span class = "token class-name" > Matrix4< / span > < span class = "token punctuation" > ::< / span > < span class = "token function" > look_at_dir< / span > < span class = "token punctuation" > (< / span >
< span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > position< span class = "token punctuation" > ,< / span >
< span class = "token class-name" > Vector3< / span > < span class = "token punctuation" > ::< / span > < span class = "token function" > new< / span > < span class = "token punctuation" > (< / span >
< span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > yaw< span class = "token number" > .0< / span > < span class = "token punctuation" > .< / span > < span class = "token function" > cos< / span > < span class = "token punctuation" > (< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ,< / span >
< span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > pitch< span class = "token number" > .0< / span > < span class = "token punctuation" > .< / span > < span class = "token function" > sin< / span > < span class = "token punctuation" > (< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ,< / span >
< span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > yaw< span class = "token number" > .0< / span > < span class = "token punctuation" > .< / span > < span class = "token function" > sin< / span > < span class = "token punctuation" > (< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ,< / span >
< span class = "token punctuation" > )< / span > < span class = "token punctuation" > .< / span > < span class = "token function" > normalize< / span > < span class = "token punctuation" > (< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ,< / span >
< span class = "token class-name" > Vector3< / span > < span class = "token punctuation" > ::< / span > < span class = "token function" > unit_y< / span > < span class = "token punctuation" > (< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ,< / span >
< span class = "token punctuation" > )< / span >
< span class = "token punctuation" > }< / span >
< span class = "token punctuation" > }< / span >
< / code > < / pre > < / div > < h2 id = "the-projection" > < a href = "#the-projection" class = "header-anchor" > #< / a > The Projection< / h2 > < p > I've decided to split the projection from the camera. The projection only really needs to change if the window resizes, so let's create a < code > Projection< / code > struct.< / p > < div class = "language-rust extra-class" > < pre class = "language-rust" > < code > < span class = "token keyword" > pub< / span > < span class = "token keyword" > struct< / span > < span class = "token type-definition class-name" > Projection< / span > < span class = "token punctuation" > {< / span >
aspect< span class = "token punctuation" > :< / span > < span class = "token keyword" > f32< / span > < span class = "token punctuation" > ,< / span >
fovy< span class = "token punctuation" > :< / span > < span class = "token class-name" > Rad< / span > < span class = "token operator" > < < / span > < span class = "token keyword" > f32< / span > < span class = "token operator" > > < / span > < span class = "token punctuation" > ,< / span >
znear< span class = "token punctuation" > :< / span > < span class = "token keyword" > f32< / span > < span class = "token punctuation" > ,< / span >
zfar< span class = "token punctuation" > :< / span > < span class = "token keyword" > f32< / span > < span class = "token punctuation" > ,< / span >
< span class = "token punctuation" > }< / span >
< span class = "token keyword" > impl< / span > < span class = "token class-name" > Projection< / span > < span class = "token punctuation" > {< / span >
< span class = "token keyword" > pub< / span > < span class = "token keyword" > fn< / span > < span class = "token function-definition function" > new< / span > < span class = "token operator" > < < / span > < span class = "token class-name" > F< / span > < span class = "token punctuation" > :< / span > < span class = "token class-name" > Into< / span > < span class = "token operator" > < < / span > < span class = "token class-name" > Rad< / span > < span class = "token operator" > < < / span > < span class = "token keyword" > f32< / span > < span class = "token operator" > > > < / span > < span class = "token operator" > > < / span > < span class = "token punctuation" > (< / span >
width< span class = "token punctuation" > :< / span > < span class = "token keyword" > u32< / span > < span class = "token punctuation" > ,< / span >
height< span class = "token punctuation" > :< / span > < span class = "token keyword" > u32< / span > < span class = "token punctuation" > ,< / span >
fovy< span class = "token punctuation" > :< / span > < span class = "token class-name" > F< / span > < span class = "token punctuation" > ,< / span >
znear< span class = "token punctuation" > :< / span > < span class = "token keyword" > f32< / span > < span class = "token punctuation" > ,< / span >
zfar< span class = "token punctuation" > :< / span > < span class = "token keyword" > f32< / span > < span class = "token punctuation" > ,< / span >
< span class = "token punctuation" > )< / span > < span class = "token punctuation" > -> < / span > < span class = "token keyword" > Self< / span > < span class = "token punctuation" > {< / span >
< span class = "token keyword" > Self< / span > < span class = "token punctuation" > {< / span >
aspect< span class = "token punctuation" > :< / span > width < span class = "token keyword" > as< / span > < span class = "token keyword" > f32< / span > < span class = "token operator" > /< / span > height < span class = "token keyword" > as< / span > < span class = "token keyword" > f32< / span > < span class = "token punctuation" > ,< / span >
fovy< span class = "token punctuation" > :< / span > fovy< span class = "token punctuation" > .< / span > < span class = "token function" > into< / span > < span class = "token punctuation" > (< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ,< / span >
znear< span class = "token punctuation" > ,< / span >
zfar< span class = "token punctuation" > ,< / span >
< span class = "token punctuation" > }< / span >
< span class = "token punctuation" > }< / span >
< span class = "token keyword" > pub< / span > < span class = "token keyword" > fn< / span > < span class = "token function-definition function" > resize< / span > < span class = "token punctuation" > (< / span > < span class = "token operator" > & < / span > < span class = "token keyword" > mut< / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > ,< / span > width< span class = "token punctuation" > :< / span > < span class = "token keyword" > u32< / span > < span class = "token punctuation" > ,< / span > height< span class = "token punctuation" > :< / span > < span class = "token keyword" > u32< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > {< / span >
< span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > aspect < span class = "token operator" > =< / span > width < span class = "token keyword" > as< / span > < span class = "token keyword" > f32< / span > < span class = "token operator" > /< / span > height < span class = "token keyword" > as< / span > < span class = "token keyword" > f32< / span > < span class = "token punctuation" > ;< / span >
< span class = "token punctuation" > }< / span >
< span class = "token keyword" > pub< / span > < span class = "token keyword" > fn< / span > < span class = "token function-definition function" > calc_matrix< / span > < span class = "token punctuation" > (< / span > < span class = "token operator" > & < / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > -> < / span > < span class = "token class-name" > Matrix4< / span > < span class = "token operator" > < < / span > < span class = "token keyword" > f32< / span > < span class = "token operator" > > < / span > < span class = "token punctuation" > {< / span >
< span class = "token constant" > OPENGL_TO_WGPU_MATRIX< / span > < span class = "token operator" > *< / span > < span class = "token function" > perspective< / span > < span class = "token punctuation" > (< / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > fovy< span class = "token punctuation" > ,< / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > aspect< span class = "token punctuation" > ,< / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > znear< span class = "token punctuation" > ,< / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > zfar< span class = "token punctuation" > )< / span >
< span class = "token punctuation" > }< / span >
< span class = "token punctuation" > }< / span >
< / code > < / pre > < / div > < p > On thing to note: < code > cgmath< / code > currently returns a right-handed projection matrix from the < code > perspective< / code > function. This means that the z-axis points out of the screen. If you want the z-axis to be < em > into< / em > the screen (aka. a left-handed projection matrix), you'll have to code your own.< / p > < p > You can tell the difference between a right-handed coordinate system and a left-handed one by using your hands. Point your thumb to the right. This is the x-axis. Point your pointer finger up. This is the y-axis. Extend your middle finger. This is the z-axis. On your right hand your middle finger should be pointing towards you. On your left hand it should be pointing away.< / p > < p > < img src = "/learn-wgpu/assets/img/left_right_hand.ccabf5d0.gif" alt = "./left_right_hand.gif" > < / p > < h1 id = "the-camera-controller" > < a href = "#the-camera-controller" class = "header-anchor" > #< / a > The Camera Controller< / h1 > < p > As our camera is different, so we'll need a new camera controller. Add the following to < code > camera.rs< / code > .< / p > < div class = "language-rust extra-class" > < pre class = "language-rust" > < code > < span class = "token attribute attr-name" > #[derive(Debug)]< / span >
< span class = "token keyword" > pub< / span > < span class = "token keyword" > struct< / span > < span class = "token type-definition class-name" > CameraController< / span > < span class = "token punctuation" > {< / span >
amount_left< span class = "token punctuation" > :< / span > < span class = "token keyword" > f32< / span > < span class = "token punctuation" > ,< / span >
amount_right< span class = "token punctuation" > :< / span > < span class = "token keyword" > f32< / span > < span class = "token punctuation" > ,< / span >
amount_forward< span class = "token punctuation" > :< / span > < span class = "token keyword" > f32< / span > < span class = "token punctuation" > ,< / span >
amount_backward< span class = "token punctuation" > :< / span > < span class = "token keyword" > f32< / span > < span class = "token punctuation" > ,< / span >
amount_up< span class = "token punctuation" > :< / span > < span class = "token keyword" > f32< / span > < span class = "token punctuation" > ,< / span >
amount_down< span class = "token punctuation" > :< / span > < span class = "token keyword" > f32< / span > < span class = "token punctuation" > ,< / span >
rotate_horizontal< span class = "token punctuation" > :< / span > < span class = "token keyword" > f32< / span > < span class = "token punctuation" > ,< / span >
rotate_vertical< span class = "token punctuation" > :< / span > < span class = "token keyword" > f32< / span > < span class = "token punctuation" > ,< / span >
scroll< span class = "token punctuation" > :< / span > < span class = "token keyword" > f32< / span > < span class = "token punctuation" > ,< / span >
speed< span class = "token punctuation" > :< / span > < span class = "token keyword" > f32< / span > < span class = "token punctuation" > ,< / span >
sensitivity< span class = "token punctuation" > :< / span > < span class = "token keyword" > f32< / span > < span class = "token punctuation" > ,< / span >
< span class = "token punctuation" > }< / span >
< span class = "token keyword" > impl< / span > < span class = "token class-name" > CameraController< / span > < span class = "token punctuation" > {< / span >
< span class = "token keyword" > pub< / span > < span class = "token keyword" > fn< / span > < span class = "token function-definition function" > new< / span > < span class = "token punctuation" > (< / span > speed< span class = "token punctuation" > :< / span > < span class = "token keyword" > f32< / span > < span class = "token punctuation" > ,< / span > sensitivity< span class = "token punctuation" > :< / span > < span class = "token keyword" > f32< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > -> < / span > < span class = "token keyword" > Self< / span > < span class = "token punctuation" > {< / span >
< span class = "token keyword" > Self< / span > < span class = "token punctuation" > {< / span >
amount_left< span class = "token punctuation" > :< / span > < span class = "token number" > 0.0< / span > < span class = "token punctuation" > ,< / span >
amount_right< span class = "token punctuation" > :< / span > < span class = "token number" > 0.0< / span > < span class = "token punctuation" > ,< / span >
amount_forward< span class = "token punctuation" > :< / span > < span class = "token number" > 0.0< / span > < span class = "token punctuation" > ,< / span >
amount_backward< span class = "token punctuation" > :< / span > < span class = "token number" > 0.0< / span > < span class = "token punctuation" > ,< / span >
amount_up< span class = "token punctuation" > :< / span > < span class = "token number" > 0.0< / span > < span class = "token punctuation" > ,< / span >
amount_down< span class = "token punctuation" > :< / span > < span class = "token number" > 0.0< / span > < span class = "token punctuation" > ,< / span >
rotate_horizontal< span class = "token punctuation" > :< / span > < span class = "token number" > 0.0< / span > < span class = "token punctuation" > ,< / span >
rotate_vertical< span class = "token punctuation" > :< / span > < span class = "token number" > 0.0< / span > < span class = "token punctuation" > ,< / span >
scroll< span class = "token punctuation" > :< / span > < span class = "token number" > 0.0< / span > < span class = "token punctuation" > ,< / span >
speed< span class = "token punctuation" > ,< / span >
sensitivity< span class = "token punctuation" > ,< / span >
< span class = "token punctuation" > }< / span >
< span class = "token punctuation" > }< / span >
< span class = "token keyword" > pub< / span > < span class = "token keyword" > fn< / span > < span class = "token function-definition function" > process_keyboard< / span > < span class = "token punctuation" > (< / span > < span class = "token operator" > & < / span > < span class = "token keyword" > mut< / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > ,< / span > key< span class = "token punctuation" > :< / span > < span class = "token class-name" > VirtualKeyCode< / span > < span class = "token punctuation" > ,< / span > state< span class = "token punctuation" > :< / span > < span class = "token class-name" > ElementState< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > -> < / span > < span class = "token keyword" > bool< / span > < span class = "token punctuation" > {< / span >
< span class = "token keyword" > let< / span > amount < span class = "token operator" > =< / span > < span class = "token keyword" > if< / span > state < span class = "token operator" > ==< / span > < span class = "token class-name" > ElementState< / span > < span class = "token punctuation" > ::< / span > < span class = "token class-name" > Pressed< / span > < span class = "token punctuation" > {< / span > < span class = "token number" > 1.0< / span > < span class = "token punctuation" > }< / span > < span class = "token keyword" > else< / span > < span class = "token punctuation" > {< / span > < span class = "token number" > 0.0< / span > < span class = "token punctuation" > }< / span > < span class = "token punctuation" > ;< / span >
< span class = "token keyword" > match< / span > key < span class = "token punctuation" > {< / span >
< span class = "token class-name" > VirtualKeyCode< / span > < span class = "token punctuation" > ::< / span > < span class = "token class-name" > W< / span > < span class = "token operator" > |< / span > < span class = "token class-name" > VirtualKeyCode< / span > < span class = "token punctuation" > ::< / span > < span class = "token class-name" > Up< / span > < span class = "token operator" > => < / span > < span class = "token punctuation" > {< / span >
< span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > amount_forward < span class = "token operator" > =< / span > amount< span class = "token punctuation" > ;< / span >
< span class = "token boolean" > true< / span >
< span class = "token punctuation" > }< / span >
< span class = "token class-name" > VirtualKeyCode< / span > < span class = "token punctuation" > ::< / span > < span class = "token class-name" > S< / span > < span class = "token operator" > |< / span > < span class = "token class-name" > VirtualKeyCode< / span > < span class = "token punctuation" > ::< / span > < span class = "token class-name" > Down< / span > < span class = "token operator" > => < / span > < span class = "token punctuation" > {< / span >
< span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > amount_backward < span class = "token operator" > =< / span > amount< span class = "token punctuation" > ;< / span >
< span class = "token boolean" > true< / span >
< span class = "token punctuation" > }< / span >
< span class = "token class-name" > VirtualKeyCode< / span > < span class = "token punctuation" > ::< / span > < span class = "token class-name" > A< / span > < span class = "token operator" > |< / span > < span class = "token class-name" > VirtualKeyCode< / span > < span class = "token punctuation" > ::< / span > < span class = "token class-name" > Left< / span > < span class = "token operator" > => < / span > < span class = "token punctuation" > {< / span >
< span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > amount_left < span class = "token operator" > =< / span > amount< span class = "token punctuation" > ;< / span >
< span class = "token boolean" > true< / span >
< span class = "token punctuation" > }< / span >
< span class = "token class-name" > VirtualKeyCode< / span > < span class = "token punctuation" > ::< / span > < span class = "token class-name" > D< / span > < span class = "token operator" > |< / span > < span class = "token class-name" > VirtualKeyCode< / span > < span class = "token punctuation" > ::< / span > < span class = "token class-name" > Right< / span > < span class = "token operator" > => < / span > < span class = "token punctuation" > {< / span >
< span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > amount_right < span class = "token operator" > =< / span > amount< span class = "token punctuation" > ;< / span >
< span class = "token boolean" > true< / span >
< span class = "token punctuation" > }< / span >
< span class = "token class-name" > VirtualKeyCode< / span > < span class = "token punctuation" > ::< / span > < span class = "token class-name" > Space< / span > < span class = "token operator" > => < / span > < span class = "token punctuation" > {< / span >
< span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > amount_up < span class = "token operator" > =< / span > amount< span class = "token punctuation" > ;< / span >
< span class = "token boolean" > true< / span >
< span class = "token punctuation" > }< / span >
< span class = "token class-name" > VirtualKeyCode< / span > < span class = "token punctuation" > ::< / span > < span class = "token class-name" > LShift< / span > < span class = "token operator" > => < / span > < span class = "token punctuation" > {< / span >
< span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > amount_down < span class = "token operator" > =< / span > amount< span class = "token punctuation" > ;< / span >
< span class = "token boolean" > true< / span >
< span class = "token punctuation" > }< / span >
_ < span class = "token operator" > => < / span > < span class = "token boolean" > false< / span > < span class = "token punctuation" > ,< / span >
< span class = "token punctuation" > }< / span >
< span class = "token punctuation" > }< / span >
< span class = "token keyword" > pub< / span > < span class = "token keyword" > fn< / span > < span class = "token function-definition function" > process_mouse< / span > < span class = "token punctuation" > (< / span > < span class = "token operator" > & < / span > < span class = "token keyword" > mut< / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > ,< / span > mouse_dx< span class = "token punctuation" > :< / span > < span class = "token keyword" > f64< / span > < span class = "token punctuation" > ,< / span > mouse_dy< span class = "token punctuation" > :< / span > < span class = "token keyword" > f64< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > {< / span >
< span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > rotate_horizontal < span class = "token operator" > =< / span > mouse_dx < span class = "token keyword" > as< / span > < span class = "token keyword" > f32< / span > < span class = "token punctuation" > ;< / span >
< span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > rotate_vertical < span class = "token operator" > =< / span > mouse_dy < span class = "token keyword" > as< / span > < span class = "token keyword" > f32< / span > < span class = "token punctuation" > ;< / span >
< span class = "token punctuation" > }< / span >
< span class = "token keyword" > pub< / span > < span class = "token keyword" > fn< / span > < span class = "token function-definition function" > process_scroll< / span > < span class = "token punctuation" > (< / span > < span class = "token operator" > & < / span > < span class = "token keyword" > mut< / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > ,< / span > delta< span class = "token punctuation" > :< / span > < span class = "token operator" > & < / span > < span class = "token class-name" > MouseScrollDelta< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > {< / span >
< span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > scroll < span class = "token operator" > =< / span > < span class = "token operator" > -< / span > < span class = "token keyword" > match< / span > delta < span class = "token punctuation" > {< / span >
< span class = "token comment" > // I'm assuming a line is about 100 pixels< / span >
< span class = "token class-name" > MouseScrollDelta< / span > < span class = "token punctuation" > ::< / span > < span class = "token class-name" > LineDelta< / span > < span class = "token punctuation" > (< / span > _< span class = "token punctuation" > ,< / span > scroll< span class = "token punctuation" > )< / span > < span class = "token operator" > => < / span > scroll < span class = "token operator" > *< / span > < span class = "token number" > 100.0< / span > < span class = "token punctuation" > ,< / span >
< span class = "token class-name" > MouseScrollDelta< / span > < span class = "token punctuation" > ::< / span > < span class = "token class-name" > PixelDelta< / span > < span class = "token punctuation" > (< / span > < span class = "token class-name" > PhysicalPosition< / span > < span class = "token punctuation" > {< / span >
y< span class = "token punctuation" > :< / span > scroll< span class = "token punctuation" > ,< / span >
< span class = "token punctuation" > ..< / span >
< span class = "token punctuation" > }< / span > < span class = "token punctuation" > )< / span > < span class = "token operator" > => < / span > < span class = "token operator" > *< / span > scroll < span class = "token keyword" > as< / span > < span class = "token keyword" > f32< / span > < span class = "token punctuation" > ,< / span >
< span class = "token punctuation" > }< / span > < span class = "token punctuation" > ;< / span >
< span class = "token punctuation" > }< / span >
< span class = "token keyword" > pub< / span > < span class = "token keyword" > fn< / span > < span class = "token function-definition function" > update_camera< / span > < span class = "token punctuation" > (< / span > < span class = "token operator" > & < / span > < span class = "token keyword" > mut< / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > ,< / span > camera< span class = "token punctuation" > :< / span > < span class = "token operator" > & < / span > < span class = "token keyword" > mut< / span > < span class = "token class-name" > Camera< / span > < span class = "token punctuation" > ,< / span > dt< span class = "token punctuation" > :< / span > < span class = "token class-name" > Duration< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > {< / span >
< span class = "token keyword" > let< / span > dt < span class = "token operator" > =< / span > dt< span class = "token punctuation" > .< / span > < span class = "token function" > as_secs_f32< / span > < span class = "token punctuation" > (< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ;< / span >
< span class = "token comment" > // Move forward/backward and left/right< / span >
< span class = "token keyword" > let< / span > < span class = "token punctuation" > (< / span > yaw_sin< span class = "token punctuation" > ,< / span > yaw_cos< span class = "token punctuation" > )< / span > < span class = "token operator" > =< / span > camera< span class = "token punctuation" > .< / span > yaw< span class = "token number" > .0< / span > < span class = "token punctuation" > .< / span > < span class = "token function" > sin_cos< / span > < span class = "token punctuation" > (< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ;< / span >
< span class = "token keyword" > let< / span > forward < span class = "token operator" > =< / span > < span class = "token class-name" > Vector3< / span > < span class = "token punctuation" > ::< / span > < span class = "token function" > new< / span > < span class = "token punctuation" > (< / span > yaw_cos< span class = "token punctuation" > ,< / span > < span class = "token number" > 0.0< / span > < span class = "token punctuation" > ,< / span > yaw_sin< span class = "token punctuation" > )< / span > < span class = "token punctuation" > .< / span > < span class = "token function" > normalize< / span > < span class = "token punctuation" > (< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ;< / span >
< span class = "token keyword" > let< / span > right < span class = "token operator" > =< / span > < span class = "token class-name" > Vector3< / span > < span class = "token punctuation" > ::< / span > < span class = "token function" > new< / span > < span class = "token punctuation" > (< / span > < span class = "token operator" > -< / span > yaw_sin< span class = "token punctuation" > ,< / span > < span class = "token number" > 0.0< / span > < span class = "token punctuation" > ,< / span > yaw_cos< span class = "token punctuation" > )< / span > < span class = "token punctuation" > .< / span > < span class = "token function" > normalize< / span > < span class = "token punctuation" > (< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ;< / span >
camera< span class = "token punctuation" > .< / span > position < span class = "token operator" > +=< / span > forward < span class = "token operator" > *< / span > < span class = "token punctuation" > (< / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > amount_forward < span class = "token operator" > -< / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > amount_backward< span class = "token punctuation" > )< / span > < span class = "token operator" > *< / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > speed < span class = "token operator" > *< / span > dt< span class = "token punctuation" > ;< / span >
camera< span class = "token punctuation" > .< / span > position < span class = "token operator" > +=< / span > right < span class = "token operator" > *< / span > < span class = "token punctuation" > (< / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > amount_right < span class = "token operator" > -< / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > amount_left< span class = "token punctuation" > )< / span > < span class = "token operator" > *< / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > speed < span class = "token operator" > *< / span > dt< span class = "token punctuation" > ;< / span >
< span class = "token comment" > // Move in/out (aka. " zoom" )< / span >
< span class = "token comment" > // Note: this isn't an actual zoom. The camera's position< / span >
< span class = "token comment" > // changes when zooming. I've added this to make it easier< / span >
< span class = "token comment" > // to get closer to an object you want to focus on.< / span >
< span class = "token keyword" > let< / span > < span class = "token punctuation" > (< / span > pitch_sin< span class = "token punctuation" > ,< / span > pitch_cos< span class = "token punctuation" > )< / span > < span class = "token operator" > =< / span > camera< span class = "token punctuation" > .< / span > pitch< span class = "token number" > .0< / span > < span class = "token punctuation" > .< / span > < span class = "token function" > sin_cos< / span > < span class = "token punctuation" > (< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ;< / span >
< span class = "token keyword" > let< / span > scrollward < span class = "token operator" > =< / span > < span class = "token class-name" > Vector3< / span > < span class = "token punctuation" > ::< / span > < span class = "token function" > new< / span > < span class = "token punctuation" > (< / span > pitch_cos < span class = "token operator" > *< / span > yaw_cos< span class = "token punctuation" > ,< / span > pitch_sin< span class = "token punctuation" > ,< / span > pitch_cos < span class = "token operator" > *< / span > yaw_sin< span class = "token punctuation" > )< / span > < span class = "token punctuation" > .< / span > < span class = "token function" > normalize< / span > < span class = "token punctuation" > (< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ;< / span >
camera< span class = "token punctuation" > .< / span > position < span class = "token operator" > +=< / span > scrollward < span class = "token operator" > *< / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > scroll < span class = "token operator" > *< / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > speed < span class = "token operator" > *< / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > sensitivity < span class = "token operator" > *< / span > dt< span class = "token punctuation" > ;< / span >
< span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > scroll < span class = "token operator" > =< / span > < span class = "token number" > 0.0< / span > < span class = "token punctuation" > ;< / span >
< span class = "token comment" > // Move up/down. Since we don't use roll, we can just< / span >
< span class = "token comment" > // modify the y coordinate directly.< / span >
camera< span class = "token punctuation" > .< / span > position< span class = "token punctuation" > .< / span > y < span class = "token operator" > +=< / span > < span class = "token punctuation" > (< / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > amount_up < span class = "token operator" > -< / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > amount_down< span class = "token punctuation" > )< / span > < span class = "token operator" > *< / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > speed < span class = "token operator" > *< / span > dt< span class = "token punctuation" > ;< / span >
< span class = "token comment" > // Rotate< / span >
camera< span class = "token punctuation" > .< / span > yaw < span class = "token operator" > +=< / span > < span class = "token class-name" > Rad< / span > < span class = "token punctuation" > (< / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > rotate_horizontal< span class = "token punctuation" > )< / span > < span class = "token operator" > *< / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > sensitivity < span class = "token operator" > *< / span > dt< span class = "token punctuation" > ;< / span >
camera< span class = "token punctuation" > .< / span > pitch < span class = "token operator" > +=< / span > < span class = "token class-name" > Rad< / span > < span class = "token punctuation" > (< / span > < span class = "token operator" > -< / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > rotate_vertical< span class = "token punctuation" > )< / span > < span class = "token operator" > *< / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > sensitivity < span class = "token operator" > *< / span > dt< span class = "token punctuation" > ;< / span >
< span class = "token comment" > // If process_mouse isn't called every frame, these values< / span >
< span class = "token comment" > // will not get set to zero, and the camera will rotate< / span >
< span class = "token comment" > // when moving in a non cardinal direction.< / span >
< span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > rotate_horizontal < span class = "token operator" > =< / span > < span class = "token number" > 0.0< / span > < span class = "token punctuation" > ;< / span >
< span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > rotate_vertical < span class = "token operator" > =< / span > < span class = "token number" > 0.0< / span > < span class = "token punctuation" > ;< / span >
< span class = "token comment" > // Keep the camera's angle from going too high/low.< / span >
< span class = "token keyword" > if< / span > camera< span class = "token punctuation" > .< / span > pitch < span class = "token operator" > < < / span > < span class = "token operator" > -< / span > < span class = "token class-name" > Rad< / span > < span class = "token punctuation" > (< / span > < span class = "token constant" > FRAC_PI_2< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > {< / span >
camera< span class = "token punctuation" > .< / span > pitch < span class = "token operator" > =< / span > < span class = "token operator" > -< / span > < span class = "token class-name" > Rad< / span > < span class = "token punctuation" > (< / span > < span class = "token constant" > FRAC_PI_2< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ;< / span >
< span class = "token punctuation" > }< / span > < span class = "token keyword" > else< / span > < span class = "token keyword" > if< / span > camera< span class = "token punctuation" > .< / span > pitch < span class = "token operator" > > < / span > < span class = "token class-name" > Rad< / span > < span class = "token punctuation" > (< / span > < span class = "token constant" > FRAC_PI_2< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > {< / span >
camera< span class = "token punctuation" > .< / span > pitch < span class = "token operator" > =< / span > < span class = "token class-name" > Rad< / span > < span class = "token punctuation" > (< / span > < span class = "token constant" > FRAC_PI_2< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ;< / span >
< span class = "token punctuation" > }< / span >
< span class = "token punctuation" > }< / span >
< span class = "token punctuation" > }< / span >
< / code > < / pre > < / div > < h2 id = "cleaning-up-main-rs" > < a href = "#cleaning-up-main-rs" class = "header-anchor" > #< / a > Cleaning up < code > main.rs< / code > < / h2 > < p > First things first we need to delete < code > Camera< / code > and < code > CameraController< / code > as well as the extra < code > OPENGL_TO_WGPU_MATRIX< / code > from < code > main.rs< / code > . Once you've done that import < code > camera.rs< / code > .< / p > < div class = "language-rust extra-class" > < pre class = "language-rust" > < code > < span class = "token keyword" > mod< / span > < span class = "token module-declaration namespace" > model< / span > < span class = "token punctuation" > ;< / span >
< span class = "token keyword" > mod< / span > < span class = "token module-declaration namespace" > texture< / span > < span class = "token punctuation" > ;< / span >
< span class = "token keyword" > mod< / span > < span class = "token module-declaration namespace" > camera< / span > < span class = "token punctuation" > ;< / span > < span class = "token comment" > // NEW!< / span >
< / code > < / pre > < / div > < p > We need to update < code > update_view_proj< / code > to use our new < code > Camera< / code > and < code > Projection< / code > .< / p > < div class = "language-rust extra-class" > < pre class = "language-rust" > < code >
< span class = "token keyword" > impl< / span > < span class = "token class-name" > Uniforms< / span > < span class = "token punctuation" > {< / span >
< span class = "token comment" > // ...< / span >
< span class = "token comment" > // UPDATED!< / span >
< span class = "token keyword" > fn< / span > < span class = "token function-definition function" > update_view_proj< / span > < span class = "token punctuation" > (< / span > < span class = "token operator" > & < / span > < span class = "token keyword" > mut< / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > ,< / span > camera< span class = "token punctuation" > :< / span > < span class = "token operator" > & < / span > < span class = "token namespace" > camera< span class = "token punctuation" > ::< / span > < / span > < span class = "token class-name" > Camera< / span > < span class = "token punctuation" > ,< / span > projection< span class = "token punctuation" > :< / span > < span class = "token operator" > & < / span > < span class = "token namespace" > camera< span class = "token punctuation" > ::< / span > < / span > < span class = "token class-name" > Projection< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > {< / span >
< span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > view_position < span class = "token operator" > =< / span > camera< span class = "token punctuation" > .< / span > position< span class = "token punctuation" > .< / span > < span class = "token function" > to_homogeneous< / span > < span class = "token punctuation" > (< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ;< / span >
< span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > view_proj < span class = "token operator" > =< / span > projection< span class = "token punctuation" > .< / span > < span class = "token function" > calc_matrix< / span > < span class = "token punctuation" > (< / span > < span class = "token punctuation" > )< / span > < span class = "token operator" > *< / span > camera< span class = "token punctuation" > .< / span > < span class = "token function" > calc_matrix< / span > < span class = "token punctuation" > (< / span > < span class = "token punctuation" > )< / span >
< span class = "token punctuation" > }< / span >
< span class = "token punctuation" > }< / span >
< / code > < / pre > < / div > < p > We need to change our < code > State< / code > to use our < code > Camera< / code > , < code > CameraProjection< / code > and < code > Projection< / code > as well. We'll also add a < code > mouse_pressed< / code > field to store whether the mouse was pressed.< / p > < div class = "language-rust extra-class" > < pre class = "language-rust" > < code > < span class = "token keyword" > struct< / span > < span class = "token type-definition class-name" > State< / span > < span class = "token punctuation" > {< / span >
< span class = "token comment" > // ...< / span >
camera< span class = "token punctuation" > :< / span > < span class = "token namespace" > camera< span class = "token punctuation" > ::< / span > < / span > < span class = "token class-name" > Camera< / span > < span class = "token punctuation" > ,< / span > < span class = "token comment" > // UPDATED!< / span >
projection< span class = "token punctuation" > :< / span > < span class = "token namespace" > camera< span class = "token punctuation" > ::< / span > < / span > < span class = "token class-name" > Projection< / span > < span class = "token punctuation" > ,< / span > < span class = "token comment" > // NEW!< / span >
camera_controller< span class = "token punctuation" > :< / span > < span class = "token namespace" > camera< span class = "token punctuation" > ::< / span > < / span > < span class = "token class-name" > CameraController< / span > < span class = "token punctuation" > ,< / span > < span class = "token comment" > // UPDATED!< / span >
< span class = "token comment" > // ...< / span >
< span class = "token comment" > // NEW!< / span >
mouse_pressed< span class = "token punctuation" > :< / span > < span class = "token keyword" > bool< / span > < span class = "token punctuation" > ,< / span >
< span class = "token punctuation" > }< / span >
< / code > < / pre > < / div > < p > You'll need to import < code > winit::dpi::PhysicalPosition< / code > if you haven't already.< / p > < p > We need to update < code > new()< / code > as well.< / p > < div class = "language-rust extra-class" > < pre class = "language-rust" > < code > < span class = "token keyword" > impl< / span > < span class = "token class-name" > State< / span > < span class = "token punctuation" > {< / span >
< span class = "token keyword" > async< / span > < span class = "token keyword" > fn< / span > < span class = "token function-definition function" > new< / span > < span class = "token punctuation" > (< / span > window< span class = "token punctuation" > :< / span > < span class = "token operator" > & < / span > < span class = "token class-name" > Window< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > -> < / span > < span class = "token keyword" > Self< / span > < span class = "token punctuation" > {< / span >
< span class = "token comment" > // ...< / span >
< span class = "token comment" > // UPDATED!< / span >
< span class = "token keyword" > let< / span > camera < span class = "token operator" > =< / span > < span class = "token namespace" > camera< span class = "token punctuation" > ::< / span > < / span > < span class = "token class-name" > Camera< / span > < span class = "token punctuation" > ::< / span > < span class = "token function" > new< / span > < span class = "token punctuation" > (< / span > < span class = "token punctuation" > (< / span > < span class = "token number" > 0.0< / span > < span class = "token punctuation" > ,< / span > < span class = "token number" > 5.0< / span > < span class = "token punctuation" > ,< / span > < span class = "token number" > 10.0< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ,< / span > < span class = "token namespace" > cgmath< span class = "token punctuation" > ::< / span > < / span > < span class = "token class-name" > Deg< / span > < span class = "token punctuation" > (< / span > < span class = "token operator" > -< / span > < span class = "token number" > 90.0< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ,< / span > < span class = "token namespace" > cgmath< span class = "token punctuation" > ::< / span > < / span > < span class = "token class-name" > Deg< / span > < span class = "token punctuation" > (< / span > < span class = "token operator" > -< / span > < span class = "token number" > 20.0< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ;< / span >
< span class = "token keyword" > let< / span > projection < span class = "token operator" > =< / span > < span class = "token namespace" > camera< span class = "token punctuation" > ::< / span > < / span > < span class = "token class-name" > Projection< / span > < span class = "token punctuation" > ::< / span > < span class = "token function" > new< / span > < span class = "token punctuation" > (< / span > sc_desc< span class = "token punctuation" > .< / span > width< span class = "token punctuation" > ,< / span > sc_desc< span class = "token punctuation" > .< / span > height< span class = "token punctuation" > ,< / span > < span class = "token namespace" > cgmath< span class = "token punctuation" > ::< / span > < / span > < span class = "token class-name" > Deg< / span > < span class = "token punctuation" > (< / span > < span class = "token number" > 45.0< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ,< / span > < span class = "token number" > 0.1< / span > < span class = "token punctuation" > ,< / span > < span class = "token number" > 100.0< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ;< / span >
< span class = "token keyword" > let< / span > camera_controller < span class = "token operator" > =< / span > < span class = "token namespace" > camera< span class = "token punctuation" > ::< / span > < / span > < span class = "token class-name" > CameraController< / span > < span class = "token punctuation" > ::< / span > < span class = "token function" > new< / span > < span class = "token punctuation" > (< / span > < span class = "token number" > 4.0< / span > < span class = "token punctuation" > ,< / span > < span class = "token number" > 0.4< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ;< / span >
< span class = "token comment" > // ...< / span >
< span class = "token keyword" > Self< / span > < span class = "token punctuation" > {< / span >
< span class = "token comment" > // ...< / span >
camera< span class = "token punctuation" > ,< / span >
projection< span class = "token punctuation" > ,< / span >
camera_controller< span class = "token punctuation" > ,< / span >
< span class = "token comment" > // ...< / span >
< span class = "token comment" > // NEW!< / span >
mouse_pressed< span class = "token punctuation" > :< / span > < span class = "token boolean" > false< / span > < span class = "token punctuation" > ,< / span >
< span class = "token punctuation" > }< / span >
< span class = "token punctuation" > }< / span >
< span class = "token punctuation" > }< / span >
< / code > < / pre > < / div > < p > We need to change our < code > projection< / code > in < code > resize< / code > as well.< / p > < div class = "language-rust extra-class" > < pre class = "language-rust" > < code > < span class = "token keyword" > fn< / span > < span class = "token function-definition function" > resize< / span > < span class = "token punctuation" > (< / span > < span class = "token operator" > & < / span > < span class = "token keyword" > mut< / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > ,< / span > new_size< span class = "token punctuation" > :< / span > < span class = "token namespace" > winit< span class = "token punctuation" > ::< / span > dpi< span class = "token punctuation" > ::< / span > < / span > < span class = "token class-name" > PhysicalSize< / span > < span class = "token operator" > < < / span > < span class = "token keyword" > u32< / span > < span class = "token operator" > > < / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > {< / span >
< span class = "token comment" > // UPDATED!< / span >
< span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > projection< span class = "token punctuation" > .< / span > < span class = "token function" > resize< / span > < span class = "token punctuation" > (< / span > new_size< span class = "token punctuation" > .< / span > width< span class = "token punctuation" > ,< / span > new_size< span class = "token punctuation" > .< / span > height< span class = "token punctuation" > )< / span > < span class = "token punctuation" > ;< / span >
< span class = "token comment" > // ...< / span >
< span class = "token punctuation" > }< / span >
< / code > < / pre > < / div > < p > < code > input()< / code > will need to be updated as well. Up to this point we have been using < code > WindowEvent< / code > s for our camera controls. While this works, it's not the best solution. The < a href = "https://docs.rs/winit/0.23.0/winit/event/enum.WindowEvent.html?search=#variant.CursorMoved" target = "_blank" rel = "noopener noreferrer" > winit docs< svg xmlns = "http://www.w3.org/2000/svg" aria-hidden = "true" x = "0px" y = "0px" viewBox = "0 0 100 100" width = "15" height = "15" class = "icon outbound" > < path fill = "currentColor" d = "M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z" > < / path > < polygon fill = "currentColor" points = "45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9" > < / polygon > < / svg > < / a > inform us that OS will often transform the data for the < code > CursorMoved< / code > event to allow effects such as cursor acceleration. Because of this, we're going to change our < code > input()< / code > function to use < code > DeviceEvent< / code > instead of < code > WindowEvent< / code > .< / p > < div class = "language-rust extra-class" > < pre class = "language-rust" > < code > < span class = "token comment" > // UPDATED!< / span >
< span class = "token keyword" > fn< / span > < span class = "token function-definition function" > input< / span > < span class = "token punctuation" > (< / span > < span class = "token operator" > & < / span > < span class = "token keyword" > mut< / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > ,< / span > event< span class = "token punctuation" > :< / span > < span class = "token operator" > & < / span > < span class = "token class-name" > DeviceEvent< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > -> < / span > < span class = "token keyword" > bool< / span > < span class = "token punctuation" > {< / span >
< span class = "token keyword" > match< / span > event < span class = "token punctuation" > {< / span >
< span class = "token class-name" > DeviceEvent< / span > < span class = "token punctuation" > ::< / span > < span class = "token class-name" > Key< / span > < span class = "token punctuation" > (< / span >
< span class = "token class-name" > KeyboardInput< / span > < span class = "token punctuation" > {< / span >
virtual_keycode< span class = "token punctuation" > :< / span > < span class = "token class-name" > Some< / span > < span class = "token punctuation" > (< / span > key< span class = "token punctuation" > )< / span > < span class = "token punctuation" > ,< / span >
state< span class = "token punctuation" > ,< / span >
< span class = "token punctuation" > ..< / span >
< span class = "token punctuation" > }< / span >
< span class = "token punctuation" > )< / span > < span class = "token operator" > => < / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > camera_controller< span class = "token punctuation" > .< / span > < span class = "token function" > process_keyboard< / span > < span class = "token punctuation" > (< / span > < span class = "token operator" > *< / span > key< span class = "token punctuation" > ,< / span > < span class = "token operator" > *< / span > state< span class = "token punctuation" > )< / span > < span class = "token punctuation" > ,< / span >
< span class = "token class-name" > DeviceEvent< / span > < span class = "token punctuation" > ::< / span > < span class = "token class-name" > MouseWheel< / span > < span class = "token punctuation" > {< / span > delta< span class = "token punctuation" > ,< / span > < span class = "token punctuation" > ..< / span > < span class = "token punctuation" > }< / span > < span class = "token operator" > => < / span > < span class = "token punctuation" > {< / span >
< span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > camera_controller< span class = "token punctuation" > .< / span > < span class = "token function" > process_scroll< / span > < span class = "token punctuation" > (< / span > delta< span class = "token punctuation" > )< / span > < span class = "token punctuation" > ;< / span >
< span class = "token boolean" > true< / span >
< span class = "token punctuation" > }< / span >
< span class = "token class-name" > DeviceEvent< / span > < span class = "token punctuation" > ::< / span > < span class = "token class-name" > Button< / span > < span class = "token punctuation" > {< / span >
button< span class = "token punctuation" > :< / span > < span class = "token number" > 1< / span > < span class = "token punctuation" > ,< / span > < span class = "token comment" > // Left Mouse Button< / span >
state< span class = "token punctuation" > ,< / span >
< span class = "token punctuation" > }< / span > < span class = "token operator" > => < / span > < span class = "token punctuation" > {< / span >
< span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > mouse_pressed < span class = "token operator" > =< / span > < span class = "token operator" > *< / span > state < span class = "token operator" > ==< / span > < span class = "token class-name" > ElementState< / span > < span class = "token punctuation" > ::< / span > < span class = "token class-name" > Pressed< / span > < span class = "token punctuation" > ;< / span >
< span class = "token boolean" > true< / span >
< span class = "token punctuation" > }< / span >
< span class = "token class-name" > DeviceEvent< / span > < span class = "token punctuation" > ::< / span > < span class = "token class-name" > MouseMotion< / span > < span class = "token punctuation" > {< / span > delta < span class = "token punctuation" > }< / span > < span class = "token operator" > => < / span > < span class = "token punctuation" > {< / span >
< span class = "token keyword" > if< / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > mouse_pressed < span class = "token punctuation" > {< / span >
< span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > camera_controller< span class = "token punctuation" > .< / span > < span class = "token function" > process_mouse< / span > < span class = "token punctuation" > (< / span > delta< span class = "token number" > .0< / span > < span class = "token punctuation" > ,< / span > delta< span class = "token number" > .1< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ;< / span >
< span class = "token punctuation" > }< / span >
< span class = "token boolean" > true< / span >
< span class = "token punctuation" > }< / span >
_ < span class = "token operator" > => < / span > < span class = "token boolean" > false< / span > < span class = "token punctuation" > ,< / span >
< span class = "token punctuation" > }< / span >
< span class = "token punctuation" > }< / span >
< / code > < / pre > < / div > < p > This change means will have to modify the event loop in < code > main()< / code > as well.< / p > < div class = "language-rust extra-class" > < pre class = "language-rust" > < code > < span class = "token keyword" > fn< / span > < span class = "token function-definition function" > main< / span > < span class = "token punctuation" > (< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > {< / span >
< span class = "token comment" > // ...< / span >
event_loop< span class = "token punctuation" > .< / span > < span class = "token function" > run< / span > < span class = "token punctuation" > (< / span > < span class = "token keyword" > move< / span > < span class = "token closure-params" > < span class = "token closure-punctuation punctuation" > |< / span > event< span class = "token punctuation" > ,< / span > _< span class = "token punctuation" > ,< / span > control_flow< span class = "token closure-punctuation punctuation" > |< / span > < / span > < span class = "token punctuation" > {< / span >
< span class = "token operator" > *< / span > control_flow < span class = "token operator" > =< / span > < span class = "token class-name" > ControlFlow< / span > < span class = "token punctuation" > ::< / span > < span class = "token class-name" > Poll< / span > < span class = "token punctuation" > ;< / span >
< span class = "token keyword" > match< / span > event < span class = "token punctuation" > {< / span >
< span class = "token comment" > // ...< / span >
< span class = "token comment" > // NEW!< / span >
< span class = "token class-name" > Event< / span > < span class = "token punctuation" > ::< / span > < span class = "token class-name" > DeviceEvent< / span > < span class = "token punctuation" > {< / span >
< span class = "token keyword" > ref< / span > event< span class = "token punctuation" > ,< / span >
< span class = "token punctuation" > ..< / span > < span class = "token comment" > // We're not using device_id currently< / span >
< span class = "token punctuation" > }< / span > < span class = "token operator" > => < / span > < span class = "token punctuation" > {< / span >
state< span class = "token punctuation" > .< / span > < span class = "token function" > input< / span > < span class = "token punctuation" > (< / span > event< span class = "token punctuation" > )< / span > < span class = "token punctuation" > ;< / span >
< span class = "token punctuation" > }< / span >
< span class = "token comment" > // UPDATED!< / span >
< span class = "token class-name" > Event< / span > < span class = "token punctuation" > ::< / span > < span class = "token class-name" > WindowEvent< / span > < span class = "token punctuation" > {< / span >
< span class = "token keyword" > ref< / span > event< span class = "token punctuation" > ,< / span >
window_id< span class = "token punctuation" > ,< / span >
< span class = "token punctuation" > }< / span > < span class = "token keyword" > if< / span > window_id < span class = "token operator" > ==< / span > window< span class = "token punctuation" > .< / span > < span class = "token function" > id< / span > < span class = "token punctuation" > (< / span > < span class = "token punctuation" > )< / span > < span class = "token operator" > => < / span > < span class = "token punctuation" > {< / span >
< span class = "token keyword" > match< / span > event < span class = "token punctuation" > {< / span >
< span class = "token class-name" > WindowEvent< / span > < span class = "token punctuation" > ::< / span > < span class = "token class-name" > CloseRequested< / span > < span class = "token operator" > => < / span > < span class = "token operator" > *< / span > control_flow < span class = "token operator" > =< / span > < span class = "token class-name" > ControlFlow< / span > < span class = "token punctuation" > ::< / span > < span class = "token class-name" > Exit< / span > < span class = "token punctuation" > ,< / span >
< span class = "token class-name" > WindowEvent< / span > < span class = "token punctuation" > ::< / span > < span class = "token class-name" > KeyboardInput< / span > < span class = "token punctuation" > {< / span > input< span class = "token punctuation" > ,< / span > < span class = "token punctuation" > ..< / span > < span class = "token punctuation" > }< / span > < span class = "token operator" > => < / span > < span class = "token keyword" > match< / span > input < span class = "token punctuation" > {< / span >
< span class = "token class-name" > KeyboardInput< / span > < span class = "token punctuation" > {< / span >
state< span class = "token punctuation" > :< / span > < span class = "token class-name" > ElementState< / span > < span class = "token punctuation" > ::< / span > < span class = "token class-name" > Pressed< / span > < span class = "token punctuation" > ,< / span >
virtual_keycode< span class = "token punctuation" > :< / span > < span class = "token class-name" > Some< / span > < span class = "token punctuation" > (< / span > < span class = "token class-name" > VirtualKeyCode< / span > < span class = "token punctuation" > ::< / span > < span class = "token class-name" > Escape< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ,< / span >
< span class = "token punctuation" > ..< / span >
< span class = "token punctuation" > }< / span > < span class = "token operator" > => < / span > < span class = "token punctuation" > {< / span >
< span class = "token operator" > *< / span > control_flow < span class = "token operator" > =< / span > < span class = "token class-name" > ControlFlow< / span > < span class = "token punctuation" > ::< / span > < span class = "token class-name" > Exit< / span > < span class = "token punctuation" > ;< / span >
< span class = "token punctuation" > }< / span >
_ < span class = "token operator" > => < / span > < span class = "token punctuation" > {< / span > < span class = "token punctuation" > }< / span >
< span class = "token punctuation" > }< / span > < span class = "token punctuation" > ,< / span >
< span class = "token class-name" > WindowEvent< / span > < span class = "token punctuation" > ::< / span > < span class = "token class-name" > Resized< / span > < span class = "token punctuation" > (< / span > physical_size< span class = "token punctuation" > )< / span > < span class = "token operator" > => < / span > < span class = "token punctuation" > {< / span >
state< span class = "token punctuation" > .< / span > < span class = "token function" > resize< / span > < span class = "token punctuation" > (< / span > < span class = "token operator" > *< / span > physical_size< span class = "token punctuation" > )< / span > < span class = "token punctuation" > ;< / span >
< span class = "token punctuation" > }< / span >
< span class = "token class-name" > WindowEvent< / span > < span class = "token punctuation" > ::< / span > < span class = "token class-name" > ScaleFactorChanged< / span > < span class = "token punctuation" > {< / span > new_inner_size< span class = "token punctuation" > ,< / span > < span class = "token punctuation" > ..< / span > < span class = "token punctuation" > }< / span > < span class = "token operator" > => < / span > < span class = "token punctuation" > {< / span >
state< span class = "token punctuation" > .< / span > < span class = "token function" > resize< / span > < span class = "token punctuation" > (< / span > < span class = "token operator" > *< / span > < span class = "token operator" > *< / span > new_inner_size< span class = "token punctuation" > )< / span > < span class = "token punctuation" > ;< / span >
< span class = "token punctuation" > }< / span >
_ < span class = "token operator" > => < / span > < span class = "token punctuation" > {< / span > < span class = "token punctuation" > }< / span >
< span class = "token punctuation" > }< / span >
< span class = "token punctuation" > }< / span >
< span class = "token comment" > // ...< / span >
< span class = "token punctuation" > }< / span >
< span class = "token punctuation" > }< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ;< / span >
< span class = "token punctuation" > }< / span >
< / code > < / pre > < / div > < p > The < code > update< / code > function requires a bit more explanation. The < code > update_camera< / code > function on the < code > CameraController< / code > has a parameter < code > dt: Duration< / code > which is the delta time or time between frames. This is to help smooth out the camera movement so that it's not locked be the framerate. Currently we aren't calculating < code > dt< / code > , so I decided to pass it into < code > update< / code > as a parameter.< / p > < div class = "language-rust extra-class" > < pre class = "language-rust" > < code > < span class = "token keyword" > fn< / span > < span class = "token function-definition function" > update< / span > < span class = "token punctuation" > (< / span > < span class = "token operator" > & < / span > < span class = "token keyword" > mut< / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > ,< / span > dt< span class = "token punctuation" > :< / span > < span class = "token namespace" > std< span class = "token punctuation" > ::< / span > time< span class = "token punctuation" > ::< / span > < / span > < span class = "token class-name" > Duration< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > {< / span >
< span class = "token comment" > // UPDATED!< / span >
< span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > camera_controller< span class = "token punctuation" > .< / span > < span class = "token function" > update_camera< / span > < span class = "token punctuation" > (< / span > < span class = "token operator" > & < / span > < span class = "token keyword" > mut< / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > camera< span class = "token punctuation" > ,< / span > dt< span class = "token punctuation" > )< / span > < span class = "token punctuation" > ;< / span >
< span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > uniforms< span class = "token punctuation" > .< / span > < span class = "token function" > update_view_proj< / span > < span class = "token punctuation" > (< / span > < span class = "token operator" > & < / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > camera< span class = "token punctuation" > ,< / span > < span class = "token operator" > & < / span > < span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > projection< span class = "token punctuation" > )< / span > < span class = "token punctuation" > ;< / span >
< span class = "token comment" > // ..< / span >
< span class = "token punctuation" > }< / span >
< / code > < / pre > < / div > < p > While we're at it, let's use < code > dt< / code > for the light's rotation as well.< / p > < div class = "language-rust extra-class" > < pre class = "language-rust" > < code > < span class = "token keyword" > self< / span > < span class = "token punctuation" > .< / span > light< span class = "token punctuation" > .< / span > position < span class = "token operator" > =< / span >
< span class = "token namespace" > cgmath< span class = "token punctuation" > ::< / span > < / span > < span class = "token class-name" > Quaternion< / span > < span class = "token punctuation" > ::< / span > < span class = "token function" > from_axis_angle< / span > < span class = "token punctuation" > (< / span > < span class = "token punctuation" > (< / span > < span class = "token number" > 0.0< / span > < span class = "token punctuation" > ,< / span > < span class = "token number" > 1.0< / span > < span class = "token punctuation" > ,< / span > < span class = "token number" > 0.0< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > .< / span > < span class = "token function" > into< / span > < span class = "token punctuation" > (< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ,< / span > < span class = "token namespace" > cgmath< span class = "token punctuation" > ::< / span > < / span > < span class = "token class-name" > Deg< / span > < span class = "token punctuation" > (< / span > < span class = "token number" > 60.0< / span > < span class = "token operator" > *< / span > dt< span class = "token punctuation" > .< / span > < span class = "token function" > as_secs_f32< / span > < span class = "token punctuation" > (< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > )< / span >
< span class = "token operator" > *< / span > old_position< span class = "token punctuation" > ;< / span > < span class = "token comment" > // UPDATED!< / span >
< / code > < / pre > < / div > < p > We still need to calculate < code > dt< / code > . Let's do that in the < code > main< / code > function.< / p > < div class = "language-rust extra-class" > < pre class = "language-rust" > < code > < span class = "token keyword" > fn< / span > < span class = "token function-definition function" > main< / span > < span class = "token punctuation" > (< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > {< / span >
< span class = "token comment" > // ...< / span >
< span class = "token keyword" > let< / span > < span class = "token keyword" > mut< / span > state < span class = "token operator" > =< / span > < span class = "token function" > block_on< / span > < span class = "token punctuation" > (< / span > < span class = "token class-name" > State< / span > < span class = "token punctuation" > ::< / span > < span class = "token function" > new< / span > < span class = "token punctuation" > (< / span > < span class = "token operator" > & < / span > window< span class = "token punctuation" > )< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ;< / span >
< span class = "token keyword" > let< / span > < span class = "token keyword" > mut< / span > last_render_time < span class = "token operator" > =< / span > < span class = "token namespace" > std< span class = "token punctuation" > ::< / span > time< span class = "token punctuation" > ::< / span > < / span > < span class = "token class-name" > Instant< / span > < span class = "token punctuation" > ::< / span > < span class = "token function" > now< / span > < span class = "token punctuation" > (< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ;< / span >
event_loop< span class = "token punctuation" > .< / span > < span class = "token function" > run< / span > < span class = "token punctuation" > (< / span > < span class = "token keyword" > move< / span > < span class = "token closure-params" > < span class = "token closure-punctuation punctuation" > |< / span > event< span class = "token punctuation" > ,< / span > _< span class = "token punctuation" > ,< / span > control_flow< span class = "token closure-punctuation punctuation" > |< / span > < / span > < span class = "token punctuation" > {< / span >
< span class = "token operator" > *< / span > control_flow < span class = "token operator" > =< / span > < span class = "token class-name" > ControlFlow< / span > < span class = "token punctuation" > ::< / span > < span class = "token class-name" > Poll< / span > < span class = "token punctuation" > ;< / span >
< span class = "token keyword" > match< / span > event < span class = "token punctuation" > {< / span >
< span class = "token comment" > // ...< / span >
< span class = "token comment" > // UPDATED!< / span >
< span class = "token class-name" > Event< / span > < span class = "token punctuation" > ::< / span > < span class = "token class-name" > RedrawRequested< / span > < span class = "token punctuation" > (< / span > _< span class = "token punctuation" > )< / span > < span class = "token operator" > => < / span > < span class = "token punctuation" > {< / span >
< span class = "token keyword" > let< / span > now < span class = "token operator" > =< / span > < span class = "token namespace" > std< span class = "token punctuation" > ::< / span > time< span class = "token punctuation" > ::< / span > < / span > < span class = "token class-name" > Instant< / span > < span class = "token punctuation" > ::< / span > < span class = "token function" > now< / span > < span class = "token punctuation" > (< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ;< / span >
< span class = "token keyword" > let< / span > dt < span class = "token operator" > =< / span > now < span class = "token operator" > -< / span > last_render_time< span class = "token punctuation" > ;< / span >
last_render_time < span class = "token operator" > =< / span > now< span class = "token punctuation" > ;< / span >
state< span class = "token punctuation" > .< / span > < span class = "token function" > update< / span > < span class = "token punctuation" > (< / span > dt< span class = "token punctuation" > )< / span > < span class = "token punctuation" > ;< / span >
< span class = "token comment" > // ...< / span >
< span class = "token punctuation" > }< / span >
_ < span class = "token operator" > => < / span > < span class = "token punctuation" > {< / span > < span class = "token punctuation" > }< / span >
< span class = "token punctuation" > }< / span >
< span class = "token punctuation" > }< / span > < span class = "token punctuation" > )< / span > < span class = "token punctuation" > ;< / span >
< span class = "token punctuation" > }< / span >
< / code > < / pre > < / div > < p > With that we should be able to move our camera wherever we want.< / p > < p > < img src = "/learn-wgpu/assets/img/screenshot.4f5740bc.png" alt = "./screenshot.png" > < / p > < div class = "auto-github-link" > < a href = "https://github.com/sotrh/learn-wgpu/tree/master/code/intermediate/tutorial12-camera/" target = "_blank" rel = "noopener noreferrer" > Check out the code!< / a > < svg xmlns = "http://www.w3.org/2000/svg" aria-hidden = "true" x = "0px" y = "0px" viewBox = "0 0 100 100" width = "15" height = "15" class = "icon outbound" > < path fill = "currentColor" d = "M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z" > < / path > < polygon fill = "currentColor" points = "45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9" > < / polygon > < / svg > < / div > < / div > < footer class = "page-edit" > <!-- --> < div class = "last-updated" > < span class = "prefix" > Last Updated: < / span > < span class = "time" > 11/25/2020, 11:51:22 PM< / span > < / div > < / footer > < div class = "page-nav" > < p class = "inner" > < span class = "prev" >
←
< a href = "/learn-wgpu/intermediate/tutorial11-normals/" class = "prev" >
Normal Mapping
< / a > < / span > < span class = "next" > < a href = "/learn-wgpu/intermediate/tutorial13-threading/" >
Multi-threading with Wgpu and Rayon
< / a >
→
< / span > < / p > < / div > < / main > < / div > < / div > < div class = "global-ui" > <!-- --> < / div > < / div >
< script src = "/learn-wgpu/assets/js/app.00a40aeb.js" defer > < / script > < script src = "/learn-wgpu/assets/js/2.da3fd46f.js" defer > < / script > < script src = "/learn-wgpu/assets/js/14.f852c057.js" defer > < / script > < script src = "/learn-wgpu/assets/js/22.2132e362.js" defer > < / script >
< / body >
< / html >