[video output=day545 member=cmuratori stream_platform=twitch stream_username=handmade_hero project=code title="Adding Ground Cover" vod_platform=youtube id=0g79tWCv7x0 annotator=Miblo]
[0:01][Recap and set the stage for the day][:speech]
[2:26][Consider the need to speed up our :lighting solution, determining to generate ground cover to exercise the :"entity system"'s new :caching][:run]
[7:13][Temporarily reduce the MaxUnpackedEntityCount in CreateWorld()][:"entity system"]
[7:47][Take a look at the smaller :memory footprint of our :"entity system"][:run]
[8:40][Revert our MaxUnpackedEntityCount in CreateWorld()][:"entity system"]
[9:34][Determine to produce ground cover to page in and out from the cache][:caching :"entity system" :run]
[9:57][Organise the entity struct with the disposable Lighting and Cover at the bottom, after a DiscardEverythingAfter value][:"entity system"]
[13:50][Set up to discard the Lighting and Cover when packing][:"entity system" :run]
[14:26][Set up to enable EnsureRegionIsUnpacked() to stream our minimally-stored entities into packed storage, based on the PNG reader][:caching :"entity system" :research]
[18:10][Enable EnsureRegionIsUnpacked() to stream our minimally-stored entities into packed storage][:caching :"entity system"]
[28:47][Check out the smaller :memory footprint of our packed entities][:caching :"entity system" :run]
[30:19][Introduce FillUnpackedEntity()][:"entity system"]
[32:15][Plug the grass distribution solution for The Witness[ref
    site="Casey's Blog"
    page="Visually pleasing distributions"
    url=https://caseymuratori.com/blog_0009]][:"procedural generation" :research]
[33:45][Implement FillUnpackedEntity(), introducing a ground_cover_spec struct for entity to contain][:"entity system" :"procedural generation"]
[47:17][A few words on white and blue noise][:prng :speech :statistics]
[49:04][Enable FillUnpackedEntity() to distribute grass in a white noise "pattern", introducing RandomSeedOffset() and PointFromUVW()][:"entity system" :prng :"procedural generation"]
[1:05:31][A few words on :API design and delivering assets to the game in a way it wants to use them][:"asset system" :speech]
[1:06:36][Fix compile errors, passing the GameState->Assets through to FillUnpackedEntity(), and augmenting the world_generator with Assets][:"entity system"]
[1:13:40][Pack all entities for dispersal on initialisation, introducing ClearUnpackedEntityCache() and PackEntity()][:"entity system"]
[1:23:15][Crash on EndWorldGen()][:"entity system" :"procedural generation" :run]
[1:23:57][Investigate our crash on the ClearUnpackedEntityCache() call in EndWorldGen()][:"entity system" :"procedural generation" :run]
[1:24:43][Fix EndWorldGen() to call ClearUnpackedEntityCache() before clearing our :memory][:"entity system" :"procedural generation"]
[1:24:54][Check out our profiler to see that everything is as expected][:"entity system" :"procedural generation" :run]
[1:26:16][Enable GenerateRoom() to request ground cover for outdoor areas][:"entity system" :"procedural generation"]
[1:27:27][See 0 calls to FillUnpackedEntity()][:"entity system" :"procedural generation" :run]
[1:28:17][Introduce DrawGroundCover() for UpdateAndRenderEntities() to call, fixing FillUnpackedEntity() to keep ground cover affixed to entities, e.g. moving platforms][:"entity system"]
[1:38:06][See no ground cover][:"entity system" :"procedural generation" :run]
[1:38:34][Break in to FillUnpackedEntity()][:"entity system" :"procedural generation" :run]
[1:39:25][Fix FillUnpackedEntity() to set the Entity->GroundCoverCount][:"entity system"]
[1:40:04][Break in to FillUnpackedEntity() to see that our ground cover's P and the CollisionVolume of its containing entity are unset][:"entity system" :"procedural generation" :run]
[1:42:01][Enable GenerateRoom() to produce collision volumes for all floor entities][:"entity system" :"procedural generation"]
[1:44:30][Break in to FillUnpackedEntity() to see that our ground cover's P is now set][:"entity system" :"procedural generation" :run]
[1:45:04][Fix DrawGroundCover() to offset the sprite by the entity's position][:"entity system" :"procedural generation"]
[1:46:29][Step in to DrawGroundCover() to see pretty reasonable values for our Sprite][:"entity system" :"procedural generation" :run]
[1:49:22][Enable GenerateApron() to request ground cover][:"entity system" :"procedural generation"]
[1:49:54][See grass on our apron][:"entity system" :"procedural generation" :run]
[1:50:10][Fix DrawGroundCover() to offset the sprite by the ground cover's position][:"entity system" :"procedural generation"]
[1:51:08][See our lush ground cover][:"entity system" :"procedural generation" :run]
[1:51:46][Scale down the ground cover to 0.25f in UpdateAndRenderEntities() and make GenerateRoom() produce collision volumes the same way GenerateApron() does it][:"entity system"]
[1:54:18][Note that we are not offsetting the ground cover's collision volume by the floor tile's stagger][:"entity system" :run]
[1:54:35][Fix GenerateRoom() to offset the ground cover's collision volume by the floor tile's stagger][:"entity system"]
[1:56:39][Find that we are sunken into the ground][:"entity system" :run]
[1:56:55][Fix GenerateRoom() to correctly set the traversable position][:"entity system"]
[2:01:04][Traverse the orphanage and surrounding areas][:"entity system" :run]
[2:01:40][Scale up the ground cover to 0.5f in UpdateAndRenderEntities() and increase their density in GenerateRoom()][:"entity system"]
[2:02:21][Admire our (unlit) ground cover][:"entity system" :run]
[2:03:23][Scale down the ground cover to 0.3f in UpdateAndRenderEntities()][:"entity system"]
[2:03:42][Admire our correctly sized ground cover][:"entity system" :run]
[2:04:19][Max out the density of our ground cover in GenerateApron()][:"entity system"]
[2:04:31][Q&A][:speech]
[2:04:45][Gauge the :performance of our ground cover :rendering][:"entity system" :run]
[2:06:01][@longboolean][Q: Do you intend cover to be used for things like footprints, and do you want cover to be interacted with? Like grass shifting as you walk through it to show a path where someone has walked][:"entity system"]
[2:06:40][Plant flowers everywhere we hop, augmenting the ground_cover_spec with two Reserved values and introducing StompOnEntity() for UpdateAndRenderEntities() to call][:"entity system"]
[2:14:00][Plant flowers][:"entity system" :run]
[2:14:21][Increase the ENTITY_MAX_GROUND_COVER to provide more space for our planted flowers][:"entity system"]
[2:14:41][Plant flowers outdoors and in the dungeon][:"entity system" :run]
[2:16:04][@printf_armin][Q: Will there be a sort of transition from the doors to the outside? I suspect yes but curious of how?][:"entity system" :"procedural generation"]
[2:16:54][@printf_armin][Q: Of the grass?][:"entity system" :"procedural generation"]
[2:17:41][@staythirsty90][Q: If you step on a tile more than once do the flowers stack?][:"entity system" :"procedural generation"]
[2:17:57][Enable StompOnEntity() to plant more flowers on each stomp][:"entity system" :"procedural generation"]
[2:18:19][Plant flowers until we wrap the 8-bit density count][:"entity system" :"procedural generation" :run]
[2:21:33][Toggle off the flower planting in StompOnEntity()][:"entity system" :"procedural generation"]
[2:22:00][We're done][:speech]
[/video]
