[video output=day447 member=cmuratori stream_platform=twitch stream_username=handmade_hero project=code title="Placing Adjacent Rooms" vod_platform=youtube id=afCSha34Hg0 annotator=Miblo]
[0:00][Recap and set the stage for the day continuing on :"procedural generation" of level layout][:speech]
[1:47][#if 1 our half-written layout code from yesterday, and implement PushRoom() and PopRoom()][:memory :"procedural generation"]
[12:36][Fix up typos in PlaceRoom() and implement CanBeDirection() and HasEntries()][:"procedural generation"]
[16:32][Create handmade_box.h to contain a new box_surface_mask as a generalised box directional mask based on the existing GetBoxSurface() from the :lighting system, for CanBeDirection() also to use][:"procedural generation" :rendering]
[35:09][Enable Connect() and CanBeDirection() to use the box_surface_mask to connect rooms][:"graph topology" :"procedural generation"]
[39:37][Introduce GetBoxMaskComplement()][:geometry]
[44:04][Rename CanBeDirection() to CouldGoDirection(), and make it flip the incoming mask using GetBoxMaskComplement() if it isn't the mask of Connection->B][:geometry :"graph topology" :"procedural generation"]
[46:50][Introduce PlaceRoomInVolume() for Layout() to call, in order to special-case the placement of the first room][:"graph topology" :"procedural generation"]
[52:10][Augment gen_room with a RoomName string to aid debugging, and #define two versions of GenRoom() for release and debug builds]
[56:04][Step through Layout() to see that the Stack wasn't correctly built][:"graph topology" :"procedural generation" :run]
[57:22][Fix PushConnectedRooms() to push the correct room][:"graph topology" :"procedural generation"]
[57:48][Step back into Layout() to see what happens][:"graph topology" :"procedural generation" :run]
[1:02:25][Introduce GetSurfaceMask() for CouldGoDirection() to call][:geometry]
[1:03:45][Jump back into CouldGoDirection() and through PlaceRoom()][:"graph topology" :"procedural generation" :run]
[1:04:51][Fix PlaceRoom() to clip the rooms to the correct dimensions][:geometry :"procedural generation"]
[1:06:49][Continue to step through PlaceRoom() to see how it works][:geometry :"graph topology" :"procedural generation" :run]
[1:08:48][Make Layout() set the FirstRoom to one unit high][:geometry :"procedural generation"]
[1:09:16][Continue to step through PlaceRoom() into IsMinimumDimensionsForRoom(), to see that it may overflow][:geometry :"graph topology" :"procedural generation" :run]
[1:11:06][Make InfinityVolume() produce a smaller volume to avoid overflowing signed int, and IsMinimumDimensionsForRoom() compute the dimensions individually for ease of inspection][:geometry :"procedural generation"]
[1:12:25][Step in to IsMinimumDimensionsForRoom() and inspect its values to consider that PlaceRoom() may be clipping the room incorrectly][:geometry :"procedural generation" :run]
[1:16:23][Make InfinityVolume() cast its computed min dimensions to signed integers][:geometry]
[1:17:00][Step into InfinityVolume() to see that the Min dimensions now correctly remain negative][:geometry :run]
[1:17:05][Force S32Min and S32Max to be signed integers][:language]
[1:17:41][Continue to step through PlaceRoom()][:"graph topology" :"procedural generation" :run]
[1:18:16][Enable PlaceRoom() to keep chaining up rooms for every room connection][:"graph topology" :"procedural generation"]
[1:20:20][Continue to step through PlaceRoom() to see that the room clipping is incorrect][:geometry :"procedural generation" :run]
[1:22:29][Make PlaceRoom() more correctly clip and handle rooms that cannot be placed, introducing InvertedInfinityVolume()][:geometry :"procedural generation"]
[1:29:27][Step into PlaceRoom() to see that MinVol.MaxZ may be off by 1][:geometry :"procedural generation" :run]
[1:36:56][Make PlaceRoom() consistently clip the new room's Min and Max dimensions such that it exactly abuts the other room or the interior apron, introducing ClipMin() and ClipMax()][:geometry :"procedural generation"]
[2:02:13][Overlapping rooms][:blackboard :geometry]
[2:05:28][Continue to make PlaceRoom() correctly clip to the interior apron][:geometry :"procedural generation"]
[2:08:11][Step into PlaceRoom() to see what it produces][:geometry :"procedural generation" :run]
[2:09:03][Prevent PlaceRoom() from expanding the InteriorApron in Z][:geometry :"procedural generation"]
[2:09:15][Step back into PlaceRoom() to see that the dimensions are looking more sane][:geometry :"procedural generation" :run]
[2:10:34][Make PlaceRoom() offset both the other dimensions only by the interior apron (i.e. without a further +/- 1 offset)][:geometry :"procedural generation"]
[2:14:35][Step in to PlaceRoom() to determine that the clipping should actually be asymmetric][:geometry :"procedural generation" :run]
[2:14:59][Make PlaceRoom() offset the other max dimension by 1][:geometry :"procedural generation"]
[2:15:10][Step in to PlaceRoom() to determine that this room is correctly placed][:geometry :"procedural generation" :run]
[2:15:43][Take a look at our world][:geometry :"procedural generation" :run]
[2:16:12][Simplify CreateOrphanage() to only create two adjoining rooms][:"procedural generation"]
[2:17:56][Step through Layout() to see how it places our two rooms][:"procedural generation" :run]
[2:20:18][Make PlaceRoom() leave the loops][:"procedural generation"]
[2:21:42][:Run the game to see our two placed rooms][:"procedural generation" :run]
[2:22:37][Fix PlaceRoom() to exactly abut the rooms][:"procedural generation"]
[2:24:35][:Run the game to see that the rooms abut][:"procedural generation"]
[2:24:47][Increase the InteriorApron in PlaceRoom()][:"procedural generation"]
[2:24:54][Check out our room abutment with more space][:"procedural generation" :run]
[2:25:05][Reduce the maximum room size][:"procedural generation"]
[2:25:17][Check out the smaller rooms][:"procedural generation" :run]
[2:26:38][Enable PlaceRoom() to knock out the entire abutment of adjoining rooms, introducing Union() and Intersect()][:"procedural generation"]
[2:34:53][:Run the game to see that we knocked it out backwards][:"procedural generation"]
[2:35:14][Fix PlaceRoom() to correctly position the door][:"procedural generation"]
[2:35:45][:Run the game and traverse between the rooms][:"procedural generation"]
[2:36:44][Q&A][:speech]
[2:38:17][@drzool][Q: Would nomenclature like: Low / High / Width be helpful?]
[2:38:36][@nxsy][Q: Would using a range of low values and a range of high values for dimensions be easier than having two volumes?][:geometry]
[2:38:54][@floorislava][Q: Why are you appending 'x' to some of the types?]
[2:40:15][@vkar2][Q: Didn't you want to avoid recursion?]
[2:41:46][@qwindoo][Q: Could the hero walk outside the rooms in this setup (in the gray / void zone)?][:movement]
[2:42:50][@nxsy][Q: Low can be between -30 and 5, and high can be between -4 and 20. As opposed to a min volume of -4 and 5 and a max volume of -30 and 20. (In one dimension). Makes it easier to fit in my brain, at least][:geometry]
[2:43:48][@foocat][Q: Do you think that languages that interact with the GPU directly (like Nvidia's CUDA or AMD HIP) would be useful for game programming?][:hardware :language]
[2:45:04][@thejimjames40][Q: (Off-topic) Do you miss some features that exist in C but are absent in C++?][:language]
[2:46:31][@internal_static_void_][Q: Thoughts on DXR?]
[2:46:38][@0lpbm][Q: will you ever get back to the nicely aligned grass / rocks bitmaps, map them over the current tiles maybe?][:art]
[2:47:31][@tmtow][Q: Sorry, I could not exactly follow, but can you guess at what makes the interval computations tiresome?][:geometry]
[2:51:29][@uebel_andre][Q: Do you feel it'd be worth it to abstract away subsystems (input, audio, lifecycle) with an Event system?]
[2:51:58][@vaualbus][Q: Can we try all the rooms now?]
[2:52:08][Let CreateOrphanage() try and create the whole building][:"procedural generation"]
[2:52:42][:Run the game to show that it's always connecting rooms at the further side, and will inevitably fail when it would need to connect along another side][:"procedural generation"]
[2:54:37][@jim0_o][Q: Have you ever made a visualization tool for working stuff like this out? (I'm thinking of something like live-code-editing combined with showing values on screen and lerping between previous and new values showing how the changes affect the scene when the code reloads.)][:"debug visualisation"]
[2:55:02][@vaualbus][Q: Also, after all of this code on :rendering and this, is code reloading still working?]
[2:55:42][Demonstrate the hot code reloading by making LightingTest() return immediately][:lighting :rendering :run]
[2:56:59][@devblacky][Q: Are you doing custom :memory management?]
[2:58:08][Wrap it up][:speech]
[/video]
