[video output=day363 member=cmuratori stream_platform=twitch stream_username=handmade_hero project=code title="Making an Orbiting Debug Camera" vod_platform=youtube id=CTTCf79MgDY annotator=Miblo]
[0:08][Recap and set the stage for the day]
[0:47]["It's always very bad to forget your water bottle"][quote 548]
[2:21][Run the game to see the current camera, and consider unifying the camera and clip rect operations]
[4:43][handmade_render_group.cpp: Put the PushClipRect() functions together]
[6:27][Consider the cleanliness of the 3D pipeline]
[10:32][handmade_entity.cpp: Prevent UpdateAndRenderEntites() from taking DrawBuffer and make it set the AlphaFloorClipRect with PushRenderTarget()]
[12:22][handmade_render_group.cpp: Introduce PushRenderTarget()]
[13:03][handmade_render_group.cpp: Prevent PushClipRect() from taking RenderTargetIndex and rename the main PushClipRect() to PushSetup()]
[15:15][handmade_render_group.h: Change the render_group struct to store an m4x4 LastProj and LastRenderTarget]
[17:17][handmade_render_group.cpp: Make PushSetup() set the render_group values, and implement PushRenderTarget()]
[19:54][handmade_render_group.cpp: Make SetCameraTransform() take the m4x4 CameraTransform and conditionally call Orthographic() and Projection()]
[23:47][handmade_render_group.cpp: Simplify GetRenderEntityBasisP()]
[26:06][handmade_render_group.cpp: Consider the need to invert the projection matrix in Unproject(), and clean up compile errors]
[29:31][handmade_render_group.cpp: Remove Perspective() and Orthographic()]
[31:21][handmade_entity.cpp: Simplify and prevent UpdateAndRenderEntities() from computing the Z for the fog]
[39:03][handmade_render_group.cpp: Enable UpdateAndRenderWorld() to perform perspective projections using SetCameraTransform()]
[42:31][handmade_math.h: Implement PerspectiveProjection() and OrthographicProjection()]
[44:38][Step into UpdateAndRenderWorld() and inspect the camera-related values]
[48:20][Fantastic auto-update][quote 549]
[49:18][Continue stepping through UpdateAndRenderEntities()]
[55:49][Step through OpenGLRenderCommands()]
[56:43][handmade_opengl.cpp: Prevent OpenGLRenderCommands() from setting a cliprect for a render_entry_cliprect]
[59:03][Continue stepping through OpenGLRenderCommands()]
[1:00:54][Investigate why the W is being set to a negative value]
[1:04:27][Continue stepping through OpenGLRenderCommands() and inspect the XAxis and YAxis]
[1:07:05][handmade_math.h: PerspectiveProjection() near and far clip plane]
[1:09:30][Research how OpenGL wants the perspective projection matrix to be set up[ref
    site="Unspecified Behaviour"
    page="Calculating the gluPerspective matrix and other OpenGL matrix maths"
    url="https://unspecified.wordpress.com/2012/06/21/calculating-the-gluperspective-matrix-and-other-opengl-matrix-maths/"]]
[1:18:31][handmade_math.h: Make PerspectiveProjection() set up the matrix as per the diagram]
[1:22:04][handmade_render_group.cpp: Prevent GetRenderEntityBasisP() from negating the Z coordinate]
[1:23:50][Blackboard: Z Inversion]
[1:26:42][Run the game to see that we're getting closer to reasonable]
[1:30:45][Blackboard: Conceptualising rotation around an axis]
[1:32:08][handmade_world_mode.cpp: Enable UpdateAndRenderWorld() to rotate the camera around X]
[1:33:47][Run the game to see the tilted world]
[1:34:22][Blackboard: Tilting the camera]
[1:35:03][handmade_world_mode.cpp: Negate that CameraD computation, with a few words on understanding what's happening]
[1:36:46][handmade_world_mode.cpp: Double-check what this transform is doing, and add a Z rotation]
[1:37:54][Run the game and consider increasing the focal length]
[1:38:32][Blackboard: Moving the camera to maintain focus on the same point]
[1:40:34][handmade_world_mode.cpp: Make UpdateAndRenderWorld() factor in that counter-rotation]
[1:41:37][Blackboard: Camera counter-rotation]
[1:43:36][Step into UpdateAndRenderWorld() and inspect what it's doing]
[1:44:40][handmade_world_mode.cpp: Enable UpdateAndRenderWorld() to set the rotations from the mouse position]
[1:49:26][Run the game to try moving the camera and consider introducing a moveable debug camera]
[1:52:51][handmade_render_group.cpp: Add LastUserProj to the render_group struct]
[1:55:38][handmade_world_mode.cpp: Enable UpdateAndRenderWorld() to zoom the camera]
[1:57:16][Run the game and try zooming]
[1:57:52][A few words on zooming at a speed proportional to the distance to the target with this poor man's differential equation]
[2:01:36][Q&A][:speech]
[2:02:07][@aceflameseer][Sorry for being a dummy: In the camera transform in 3D games (as far as I've been watching tutorials), there's something called an "Up" vector. What's the purpose of it and do we have it in Handmade Hero? Since it's a 2D game I guess it's different. Your explanations have been wonderful and I would love it if you could explain it. And also thanks for doing EU friendly streams Kappa]
[2:03:44][Blackboard: Object- vs Camera Transform]
[2:06:58][Blackboard: Up Vector]
[2:09:37][Blackboard: Constructing a camera transform without already having the camera object itself]
[2:18:16][Blackboard: "Sense of Up" vector]
[2:23:20][Blackboard: Look-at matrix / camera equations]
[2:24:36][@aceflameseer][Wow, that was amazing, thanks a lot!]
[2:24:47][@pileopoop][Would it be weird to change the focal length as the pitch changes or should the focal length always stay constant?]
[2:25:47][@sahfortv][Minor point, you called your variables pitch and orbit: Should probably be pitch and yaw]
[2:26:22][Wrap it up][:speech]
[/video]
