diff --git a/CHANGELOG.txt b/CHANGELOG.txt index e2799180c..ebcd0717c 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,20 @@ +* 1.3.9 + +- Implemented VoronoiNoise3D + +- Implemented ComputeNormalsForChunkFromNoiseValues + +This adds the ability to vary the terrain surface by the normal of the surface + +- Combined VoronoiNoise3D and ComputeNormalsForChunkFromNoiseValues in +terrain_gen to make some craggy cliffs + +- Generally improved terrain generation performance by quite a bit. It's still pretty slow + +* 1.3.8 + +- Uploading build artifacts to release page + * 1.3.0 - Major improvement to serialization code diff --git a/examples/terrain_gen/game.cpp b/examples/terrain_gen/game.cpp index e530d586f..0f00a5d4f 100644 --- a/examples/terrain_gen/game.cpp +++ b/examples/terrain_gen/game.cpp @@ -146,7 +146,7 @@ GrassyIslandTerrain( perlin_noise *Noise, } #if 1 - GrowGrass( Chunk, V3i(x,y,z), NoiseValue, 1.f, SrcToDest, WorldChunkDim, WorldZBiased, &ThisColor, &NoiseChoice ); + GrowGrassPerlin( Chunk, V3i(x,y,z), NoiseValue, 1.f, SrcToDest, WorldChunkDim, WorldZBiased, &ThisColor, &NoiseChoice ); #else s32 Below = TryGetIndex(x, y, z-1, Dim); s32 B0 = TryGetIndex(x+1, y, z-1, Dim); @@ -413,12 +413,24 @@ BONSAI_API_WORKER_THREAD_CALLBACK() { // Bumpy Sin(x)+Cos(y) noise. Useful for visualizing the polylines/splines mapping noise values to their final values. s32 Frequency = 100; - s32 Amplititude = 50; + s32 Amplititude = 250; + /* s32 Frequency = 100; */ + /* s32 Amplititude = 2500; */ s32 StartingZDepth = -1; chunk_init_flags InitFlags = ChunkInitFlag_Noop; InitializeChunkWithNoise( SinCosTerrain, Thread, Chunk, Chunk->Dim, 0, Frequency, Amplititude, StartingZDepth, Ignored, InitFlags, 0); } break; + case TerrainGenType_Voronoi: + { + // Voronoi noise .. looks like rocks. + s32 Frequency = 100; + s32 Amplititude = 50; + s32 StartingZDepth = -1; + chunk_init_flags InitFlags = ChunkInitFlag_Noop; + InitializeChunkWithNoise( VoronoiTerrain, Thread, Chunk, Chunk->Dim, 0, Frequency, Amplititude, StartingZDepth, Ignored, InitFlags, 0); + } break; + case TerrainGenType_Checkerboard: { // Custom flat noise function that produces a checkerboard @@ -516,13 +528,13 @@ BONSAI_API_WORKER_THREAD_CALLBACK() s32 Frequency = 0; // Ignored s32 Amplititude = 0; // Ignored s32 StartingZDepth = -100; - u32 OctaveCount = 1; + u32 OctaveCount = 2; octave_buffer OctaveBuf = { OctaveCount, {} }; OctaveBuf.Octaves = Allocate(octave, Thread->TempMemory, OctaveCount); OctaveBuf.Octaves[0] = {V3(1400, 1400, 800), 350, V3(1.f)}; - /* OctaveBuf.Octaves[1] = {V3(400, 400, 200), 150, V3(1.f)}; */ + OctaveBuf.Octaves[1] = {V3(400, 400, 200), 150, V3(1.f)}; /* OctaveBuf.Octaves[2] = {V3(35, 35, 50), 6, V3(2.f)}; */ /* OctaveBuf.Octaves[2] = {V3(500, 500, 20), 200, V3(2.f)}; */ /* OctaveBuf.Octaves[2] = {75, 60, 1}; */ @@ -535,6 +547,28 @@ BONSAI_API_WORKER_THREAD_CALLBACK() InitializeChunkWithNoise( GrassyTerracedTerrain3, Thread, Chunk, Chunk->Dim, 0, Frequency, Amplititude, StartingZDepth, MeshBit_Lod0, InitFlags, (void*)&OctaveBuf); } break; + case TerrainGenType_GrassyTerracedTerrain4: + { + // Custom FBM noise example generating slightly-more-complex game-world-like terrain + s32 Frequency = 0; // Ignored + s32 Amplititude = 0; // Ignored + s32 StartingZDepth = -100; + u32 OctaveCount = 3; + + octave_buffer OctaveBuf = { OctaveCount, {} }; + OctaveBuf.Octaves = Allocate(octave, Thread->TempMemory, OctaveCount); + + OctaveBuf.Octaves[0] = {V3(800, 800, 1700), 350, V3(1.f)}; + OctaveBuf.Octaves[1] = {V3(400, 400, 200), 350, V3(1.f)}; + OctaveBuf.Octaves[2] = {V3(35, 35, 25), 6, V3(2.f)}; + + /* chunk_init_flags InitFlags = ChunkInitFlag_ComputeStandingSpots; */ + /* chunk_init_flags InitFlags = ChunkInitFlag_GenMipMapLODs; */ + chunk_init_flags InitFlags = ChunkInitFlag_Noop; + InitializeChunkWithNoise( GrassyTerracedTerrain4, Thread, Chunk, Chunk->Dim, 0, Frequency, Amplititude, StartingZDepth, MeshBit_Lod0, InitFlags, (void*)&OctaveBuf); + } break; + + case TerrainGenType_TerracedTerrain: { // Custom FBM noise example generating slightly-more-complex game-world-like terrain @@ -675,7 +709,7 @@ BONSAI_API_MAIN_THREAD_INIT_CALLBACK() world_position WorldCenter = {}; canonical_position CameraTargetP = {}; - StandardCamera(Graphics->Camera, 10000.0f, 1000.0f, DEFAULT_CAMERA_BLENDING, CameraTargetP); + StandardCamera(Graphics->Camera, 10000.0f, 5000.0f, DEFAULT_CAMERA_BLENDING, CameraTargetP); AllocateWorld(World, WorldCenter, WORLD_CHUNK_DIM, g_VisibleRegion); @@ -683,12 +717,22 @@ BONSAI_API_MAIN_THREAD_INIT_CALLBACK() /* GameState->TerrainGenType = TerrainGenType_GrassyTerracedTerrain; */ - GameState->TerrainGenType = TerrainGenType_GrassyLargeTerracedTerrain; + GameState->TerrainGenType = TerrainGenType_SinCos; + /* GameState->TerrainGenType = TerrainGenType_GrassyTerracedTerrain4; */ + /* GameState->TerrainGenType = TerrainGenType_Voronoi; */ /* World->Center = V3i(-22, 101, 1); */ Camera->GhostId = GetFreeEntity(EntityTable); entity *CameraGhost = GetEntity(EntityTable, Camera->GhostId); - CameraGhost->P.WorldP = V3i(-22, 101, 1); + /* CameraGhost->P.WorldP = V3i(-53, -93, 2); */ + /* CameraGhost->P.WorldP = V3i(-25, -75, 2); */ + /* CameraGhost->P.WorldP = V3i(-5, -121, 2); */ + + CameraGhost->P.WorldP = V3i(330, -87, 2); + /* CameraGhost->P.WorldP = V3i(33, -87, 2); */ + /* CameraGhost->P.WorldP = V3i(5, -73, 2); */ + CameraGhost->Behavior = entity_behavior_flags(CameraGhost->Behavior|EntityBehaviorFlags_DefatulCameraGhostBehavior|EntityBehaviorFlags_WorldCenter); + SpawnEntity(CameraGhost); return GameState; @@ -702,12 +746,6 @@ BONSAI_API_MAIN_THREAD_CALLBACK() TIMED_FUNCTION(); UNPACK_ENGINE_RESOURCES(Resources); - entity *Ghost = GetEntity(EntityTable, Camera->GhostId); - if (Ghost && Ghost->Id == Resources->Graphics->GameCamera.GhostId) - { - Ghost->Behavior = entity_behavior_flags(Ghost->Behavior|EntityBehaviorFlags_WorldCenter); - } - f32 dt = Plat->dt; f32 Speed = 80.f; @@ -721,7 +759,7 @@ BONSAI_API_MAIN_THREAD_CALLBACK() { GetRadioEnum(&TerrainGenTypeRadio, &GameState->TerrainGenType); SignalAndWaitForWorkers(&Plat->WorkerThreadsSuspendFutex); - HardResetWorld(Resources); + HardResetWorld(Resources, HardResetFlag_NoResetCamera); UnsignalFutex(&Plat->WorkerThreadsSuspendFutex); } } diff --git a/examples/terrain_gen/game_constants.h b/examples/terrain_gen/game_constants.h index 3c156ada7..29d4fdb92 100644 --- a/examples/terrain_gen/game_constants.h +++ b/examples/terrain_gen/game_constants.h @@ -16,17 +16,33 @@ global_variable chunk_dimension /* g_VisibleRegion = Chunk_Dimension(64, 64, 6); */ /* g_VisibleRegion = Chunk_Dimension(32, 32, 16); */ /* g_VisibleRegion = Chunk_Dimension(32, 32, 10); */ -g_VisibleRegion = Chunk_Dimension(32, 32, 6); +/* g_VisibleRegion = Chunk_Dimension(32, 32, 8); */ +/* g_VisibleRegion = Chunk_Dimension(32, 32, 6); */ /* g_VisibleRegion = Chunk_Dimension(32, 32, 4); */ /* g_VisibleRegion = Chunk_Dimension(24, 24, 4); */ /* g_VisibleRegion = Chunk_Dimension(24, 24, 6); */ +g_VisibleRegion = Chunk_Dimension(16, 16, 8); /* g_VisibleRegion = Chunk_Dimension(16, 16, 6); */ /* g_VisibleRegion = Chunk_Dimension(10, 10, 10); */ +/* g_VisibleRegion = Chunk_Dimension(8, 8, 6); */ +/* global_variable chunk_dimension */ +/* WORLD_CHUNK_DIM = Chunk_Dimension(16, 16, 16); */ + +/* global_variable chunk_dimension */ +/* WORLD_CHUNK_DIM = Chunk_Dimension(16, 16, 16); */ + +/* global_variable chunk_dimension */ +/* WORLD_CHUNK_DIM = Chunk_Dimension(28, 28, 28); */ + /* global_variable chunk_dimension */ /* WORLD_CHUNK_DIM = Chunk_Dimension(32, 32, 32); */ +/* global_variable chunk_dimension */ +/* WORLD_CHUNK_DIM = Chunk_Dimension(64, 64, 64); */ + + global_variable chunk_dimension WORLD_CHUNK_DIM = Chunk_Dimension(64, 64, 64); diff --git a/examples/terrain_gen/game_types.h b/examples/terrain_gen/game_types.h index eabcc0777..0b44c0fea 100644 --- a/examples/terrain_gen/game_types.h +++ b/examples/terrain_gen/game_types.h @@ -5,17 +5,19 @@ enum terrain_gen_type TerrainGenType_Flat = (1 << 0), TerrainGenType_Checkerboard = (1 << 1), TerrainGenType_SinCos = (1 << 2), - TerrainGenType_Perlin2D = (1 << 3), - TerrainGenType_Perlin3D = (1 << 4), - TerrainGenType_FBM2D = (1 << 5), - TerrainGenType_TerracedTerrain = (1 << 6), - TerrainGenType_GrassyTerracedTerrain = (1 << 7), - TerrainGenType_GrassyLargeTerracedTerrain = (1 << 8), - TerrainGenType_GrassyTerracedTerrain2 = (1 << 9), - TerrainGenType_GrassyTerracedTerrain3 = (1 << 10), - TerrainGenType_GrassyIsland = (1 << 11), - TerrainGenType_Hoodoo = (1 << 12), - TerrainGenType_Warped = (1 << 13), + TerrainGenType_Voronoi = (1 << 3), + TerrainGenType_Perlin2D = (1 << 4), + TerrainGenType_Perlin3D = (1 << 5), + TerrainGenType_FBM2D = (1 << 6), + TerrainGenType_TerracedTerrain = (1 << 7), + TerrainGenType_GrassyTerracedTerrain = (1 << 8), + TerrainGenType_GrassyLargeTerracedTerrain = (1 << 9), + TerrainGenType_GrassyTerracedTerrain2 = (1 << 10), + TerrainGenType_GrassyTerracedTerrain3 = (1 << 11), + TerrainGenType_GrassyTerracedTerrain4 = (1 << 12), + TerrainGenType_GrassyIsland = (1 << 13), + TerrainGenType_Hoodoo = (1 << 14), + TerrainGenType_Warped = (1 << 15), }; poof(radio_button_group_for_bitfield_enum(terrain_gen_type)) diff --git a/examples/turn_based/game.cpp b/examples/turn_based/game.cpp index a25ef68c9..322a91e36 100644 --- a/examples/turn_based/game.cpp +++ b/examples/turn_based/game.cpp @@ -424,7 +424,7 @@ GameEntityUpdate(engine_resources *Engine, entity *Entity ) Assert(Spawned(Entity)); - if (Entity->Carrying) + if (Entity->Carrying.Generation) { entity *Carrying = GetEntity(EntityTable, Entity->Carrying); v3 EntitySimP = GetSimSpaceBaseP(World, Entity); @@ -520,7 +520,7 @@ FireballPhysics() link_internal b32 HoldingItem(entity *Player) { - b32 Result = Player->Carrying; + b32 Result = Player->Carrying.Generation > 0; return Result; } diff --git a/external/bonsai_debug b/external/bonsai_debug index f7a6c4717..a34650e60 160000 --- a/external/bonsai_debug +++ b/external/bonsai_debug @@ -1 +1 @@ -Subproject commit f7a6c471763f0da204e50033548fb4ab8f0e8353 +Subproject commit a34650e6050c0249880cb87966f315dfe70956cb diff --git a/external/bonsai_stdlib b/external/bonsai_stdlib index ce2c7c7b3..2ae42049c 160000 --- a/external/bonsai_stdlib +++ b/external/bonsai_stdlib @@ -1 +1 @@ -Subproject commit ce2c7c7b327fcf0f4b0700c28ab1243614cc8125 +Subproject commit 2ae42049c34d414f52facd2a7d0b4ffef97e7641 diff --git a/generated/are_equal_bonsai_type_info.h b/generated/are_equal_bonsai_type_info.h index e25517feb..63d8e9986 100644 --- a/generated/are_equal_bonsai_type_info.h +++ b/generated/are_equal_bonsai_type_info.h @@ -13,4 +13,16 @@ AreEqual(bonsai_type_info *Thing1, bonsai_type_info *Thing2) return Result; } +link_internal b32 +AreEqual(bonsai_type_info Thing1, bonsai_type_info Thing2) +{ + b32 Result = True; + Result &= AreEqual(Thing1.Name, Thing2.Name); + + Result &= AreEqual(Thing1.Version, Thing2.Version); + + Result &= AreEqual(Thing1.SizeOfInBytes, Thing2.SizeOfInBytes); + + return Result; +} diff --git a/generated/are_equal_debug_profile_scope.h b/generated/are_equal_debug_profile_scope.h new file mode 100644 index 000000000..60172c833 --- /dev/null +++ b/generated/are_equal_debug_profile_scope.h @@ -0,0 +1,18 @@ +// external/bonsai_debug/src/api.h:110:0 + +link_internal b32 +AreEqual(debug_profile_scope *Thing1, debug_profile_scope *Thing2) +{ + b32 Result = MemoryIsEqual((u8*)Thing1, (u8*)Thing2, sizeof( debug_profile_scope ) ); + + return Result; +} + +link_internal b32 +AreEqual(debug_profile_scope Thing1, debug_profile_scope Thing2) +{ + b32 Result = MemoryIsEqual((u8*)&Thing1, (u8*)&Thing2, sizeof( debug_profile_scope ) ); + + return Result; +} + diff --git a/generated/are_equal_file_traversal_node.h b/generated/are_equal_file_traversal_node.h index 823bd260a..5d10d4b7c 100644 --- a/generated/are_equal_file_traversal_node.h +++ b/generated/are_equal_file_traversal_node.h @@ -13,4 +13,16 @@ AreEqual(file_traversal_node *Thing1, file_traversal_node *Thing2) return Result; } +link_internal b32 +AreEqual(file_traversal_node Thing1, file_traversal_node Thing2) +{ + b32 Result = True; + Result &= AreEqual(Thing1.Type, Thing2.Type); + + Result &= AreEqual(Thing1.Dir, Thing2.Dir); + + Result &= AreEqual(Thing1.Name, Thing2.Name); + + return Result; +} diff --git a/generated/are_equal_memory_arena_stats.h b/generated/are_equal_memory_arena_stats.h index a97846597..4cf4b0e9c 100644 --- a/generated/are_equal_memory_arena_stats.h +++ b/generated/are_equal_memory_arena_stats.h @@ -8,4 +8,11 @@ AreEqual(memory_arena_stats *Thing1, memory_arena_stats *Thing2) return Result; } +link_internal b32 +AreEqual(memory_arena_stats Thing1, memory_arena_stats Thing2) +{ + b32 Result = MemoryIsEqual((u8*)&Thing1, (u8*)&Thing2, sizeof( memory_arena_stats ) ); + + return Result; +} diff --git a/generated/are_equal_texture.h b/generated/are_equal_texture.h index 57777a666..4ae9db53e 100644 --- a/generated/are_equal_texture.h +++ b/generated/are_equal_texture.h @@ -19,4 +19,22 @@ AreEqual(texture *Thing1, texture *Thing2) return Result; } +link_internal b32 +AreEqual(texture Thing1, texture Thing2) +{ + b32 Result = True; + Result &= AreEqual(Thing1.ID, Thing2.ID); + + Result &= AreEqual(Thing1.Dim, Thing2.Dim); + + Result &= AreEqual(Thing1.Slices, Thing2.Slices); + + Result &= AreEqual(Thing1.Channels, Thing2.Channels); + + Result &= AreEqual(Thing1.IsDepthTexture, Thing2.IsDepthTexture); + + Result &= AreEqual(Thing1.DebugName, Thing2.DebugName); + + return Result; +} diff --git a/generated/are_equal_ui_toggle.h b/generated/are_equal_ui_toggle.h index 378ae7d5a..2f454e277 100644 --- a/generated/are_equal_ui_toggle.h +++ b/generated/are_equal_ui_toggle.h @@ -8,4 +8,11 @@ AreEqual(ui_toggle *Thing1, ui_toggle *Thing2) return Result; } +link_internal b32 +AreEqual(ui_toggle Thing1, ui_toggle Thing2) +{ + b32 Result = MemoryIsEqual((u8*)&Thing1, (u8*)&Thing2, sizeof( ui_toggle ) ); + + return Result; +} diff --git a/generated/are_equal_voxel_synthesis_change_propagation_info.h b/generated/are_equal_voxel_synthesis_change_propagation_info.h index 8c67fb595..5ea293598 100644 --- a/generated/are_equal_voxel_synthesis_change_propagation_info.h +++ b/generated/are_equal_voxel_synthesis_change_propagation_info.h @@ -8,4 +8,11 @@ AreEqual(voxel_synthesis_change_propagation_info *Thing1, voxel_synthesis_change return Result; } +link_internal b32 +AreEqual(voxel_synthesis_change_propagation_info Thing1, voxel_synthesis_change_propagation_info Thing2) +{ + b32 Result = MemoryIsEqual((u8*)&Thing1, (u8*)&Thing2, sizeof( voxel_synthesis_change_propagation_info ) ); + + return Result; +} diff --git a/generated/are_equal_xml_tag.h b/generated/are_equal_xml_tag.h index fc5c0f11c..3114da2e1 100644 --- a/generated/are_equal_xml_tag.h +++ b/generated/are_equal_xml_tag.h @@ -8,4 +8,11 @@ AreEqual(xml_tag *Thing1, xml_tag *Thing2) return Result; } +link_internal b32 +AreEqual(xml_tag Thing1, xml_tag Thing2) +{ + b32 Result = MemoryIsEqual((u8*)&Thing1, (u8*)&Thing2, sizeof( xml_tag ) ); + + return Result; +} diff --git a/generated/block_array_entity_ptr_688856411.h b/generated/block_array_entity_ptr_688856411.h index c50dea686..bb0d01d91 100644 --- a/generated/block_array_entity_ptr_688856411.h +++ b/generated/block_array_entity_ptr_688856411.h @@ -1,4 +1,4 @@ -// src/engine/world_chunk.h:320:0 +// src/engine/world_chunk.h:326:0 struct entity_ptr_block { diff --git a/generated/block_array_h_asset_thumbnail_688856411.h b/generated/block_array_h_asset_thumbnail_688856411.h index 8ca757ae3..faed36335 100644 --- a/generated/block_array_h_asset_thumbnail_688856411.h +++ b/generated/block_array_h_asset_thumbnail_688856411.h @@ -1,4 +1,4 @@ -// src/engine/editor.h:244:0 +// src/engine/editor.h:238:0 struct asset_thumbnail_block { diff --git a/generated/block_array_standing_spot_688853862.h b/generated/block_array_standing_spot_688853862.h index 8a79aa130..d70fa854a 100644 --- a/generated/block_array_standing_spot_688853862.h +++ b/generated/block_array_standing_spot_688853862.h @@ -1,4 +1,4 @@ -// src/engine/world_chunk.h:462:0 +// src/engine/world_chunk.h:474:0 struct standing_spot_block { diff --git a/generated/block_array_voxel_stack_element_688853862.h b/generated/block_array_voxel_stack_element_688853862.h index 833d0f045..a0989040b 100644 --- a/generated/block_array_voxel_stack_element_688853862.h +++ b/generated/block_array_voxel_stack_element_688853862.h @@ -1,4 +1,4 @@ -// src/engine/world_chunk.cpp:3863:0 +// src/engine/world_chunk.cpp:4029:0 struct voxel_stack_element_block { diff --git a/generated/buffer_standing_spot.h b/generated/buffer_standing_spot.h index 7e86df306..5e15ba199 100644 --- a/generated/buffer_standing_spot.h +++ b/generated/buffer_standing_spot.h @@ -1,4 +1,4 @@ -// src/engine/world_chunk.h:505:0 +// src/engine/world_chunk.h:517:0 struct standing_spot_buffer { diff --git a/generated/buffer_world_chunk_ptr.h b/generated/buffer_world_chunk_ptr.h index 0872cabbc..62b868113 100644 --- a/generated/buffer_world_chunk_ptr.h +++ b/generated/buffer_world_chunk_ptr.h @@ -1,4 +1,4 @@ -// src/engine/world_chunk.h:399:0 +// src/engine/world_chunk.h:411:0 struct world_chunk_ptr_buffer { diff --git a/generated/deserialize_struct_level_header.h b/generated/deserialize_struct_level_header.h index 95e534809..80c0ab7bb 100644 --- a/generated/deserialize_struct_level_header.h +++ b/generated/deserialize_struct_level_header.h @@ -1,4 +1,4 @@ -// src/engine/serdes.cpp:429:0 +// src/engine/serdes.cpp:438:0 link_internal b32 Deserialize(u8_cursor *Bytes, level_header *Element, memory_arena *Memory, umm Count = 1); diff --git a/generated/deserialize_struct_level_header_0.h b/generated/deserialize_struct_level_header_0.h index 4fcaab279..88a46e312 100644 --- a/generated/deserialize_struct_level_header_0.h +++ b/generated/deserialize_struct_level_header_0.h @@ -1,4 +1,4 @@ -// src/engine/serdes.cpp:420:0 +// src/engine/serdes.cpp:429:0 link_internal b32 Deserialize(u8_cursor *Bytes, level_header_0 *Element, memory_arena *Memory, umm Count = 1); diff --git a/generated/deserialize_struct_level_header_1.h b/generated/deserialize_struct_level_header_1.h index d88a0031b..e460fcebf 100644 --- a/generated/deserialize_struct_level_header_1.h +++ b/generated/deserialize_struct_level_header_1.h @@ -1,4 +1,4 @@ -// src/engine/serdes.cpp:423:0 +// src/engine/serdes.cpp:432:0 link_internal b32 Deserialize(u8_cursor *Bytes, level_header_1 *Element, memory_arena *Memory, umm Count = 1); diff --git a/generated/deserialize_struct_level_header_2.h b/generated/deserialize_struct_level_header_2.h index a85fc6b37..71424590c 100644 --- a/generated/deserialize_struct_level_header_2.h +++ b/generated/deserialize_struct_level_header_2.h @@ -1,4 +1,4 @@ -// src/engine/serdes.cpp:426:0 +// src/engine/serdes.cpp:435:0 link_internal b32 Deserialize(u8_cursor *Bytes, level_header_2 *Element, memory_arena *Memory, umm Count = 1); diff --git a/generated/do_editor_ui_for_compound_type_engine_debug.h b/generated/do_editor_ui_for_compound_type_engine_debug.h index 2237b52bc..cba8b5368 100644 --- a/generated/do_editor_ui_for_compound_type_engine_debug.h +++ b/generated/do_editor_ui_for_compound_type_engine_debug.h @@ -11,6 +11,12 @@ DoEditorUi(renderer_2d *Ui, window_layout *Window, engine_debug *Element, cs Nam PushTableStart(Ui); PushForceUpdateBasis(Ui, V2(20.f, 0.f)); + DoEditorUi(Ui, Window, Element->Memory, CSz("memory_arena Memory"), EDITOR_UI_FUNCTION_INSTANCE_NAMES); + + + + + DoEditorUi(Ui, Window, &Element->PickedChunks, CSz("picked_world_chunk_static_buffer PickedChunks"), EDITOR_UI_FUNCTION_INSTANCE_NAMES); @@ -123,6 +129,24 @@ DoEditorUi(renderer_2d *Ui, window_layout *Window, engine_debug *Element, cs Nam PushNewRow(Ui); DoEditorUi(Ui, Window, &Element->SelectedEntity, CSz("entity_id SelectedEntity"), EDITOR_UI_FUNCTION_INSTANCE_NAMES); + + + + + + + + + DoEditorUi(Ui, Window, &Element->WorldEditDebugMesh, CSz("untextured_3d_geometry_buffer WorldEditDebugMesh"), EDITOR_UI_FUNCTION_INSTANCE_NAMES); + + + + + + + + + DoEditorUi(Ui, Window, &Element->WorldEditDebugThumb, CSz("asset_thumbnail WorldEditDebugThumb"), EDITOR_UI_FUNCTION_INSTANCE_NAMES); PushForceUpdateBasis(Ui, V2(-20.f, 0.f)); PushTableEnd(Ui); } diff --git a/generated/do_editor_ui_for_compound_type_entity_id.h b/generated/do_editor_ui_for_compound_type_entity_id.h index 2a8665697..795a6aca2 100644 --- a/generated/do_editor_ui_for_compound_type_entity_id.h +++ b/generated/do_editor_ui_for_compound_type_entity_id.h @@ -30,8 +30,6 @@ DoEditorUi(renderer_2d *Ui, window_layout *Window, entity_id *Element, cs Name, PushNewRow(Ui); - - PushForceUpdateBasis(Ui, V2(-20.f, 0.f)); PushTableEnd(Ui); } diff --git a/generated/do_editor_ui_for_compound_type_lighting_settings.h b/generated/do_editor_ui_for_compound_type_lighting_settings.h index 83217e856..710a9dce8 100644 --- a/generated/do_editor_ui_for_compound_type_lighting_settings.h +++ b/generated/do_editor_ui_for_compound_type_lighting_settings.h @@ -36,16 +36,15 @@ DoEditorUi(renderer_2d *Ui, window_layout *Window, lighting_settings *Element, c - DoEditorUi(Ui, Window, &Element->DawnColor, CSz("v3 DawnColor"), EDITOR_UI_FUNCTION_INSTANCE_NAMES); - + DoEditorUi(Ui, Window, &Element->DawnIntensity, CSz("f32 DawnIntensity"), EDITOR_UI_FUNCTION_INSTANCE_NAMES,0.f, 3.f); + PushNewRow(Ui); - - DoEditorUi(Ui, Window, &Element->SunColor, CSz("v3 SunColor"), EDITOR_UI_FUNCTION_INSTANCE_NAMES); + DoEditorUi(Ui, Window, &Element->DawnColor, CSz("v3 DawnColor"), EDITOR_UI_FUNCTION_INSTANCE_NAMES); @@ -54,16 +53,15 @@ DoEditorUi(renderer_2d *Ui, window_layout *Window, lighting_settings *Element, c - DoEditorUi(Ui, Window, &Element->DuskColor, CSz("v3 DuskColor"), EDITOR_UI_FUNCTION_INSTANCE_NAMES); - + DoEditorUi(Ui, Window, &Element->SunIntensity, CSz("f32 SunIntensity"), EDITOR_UI_FUNCTION_INSTANCE_NAMES,0.f, 3.f); + PushNewRow(Ui); - - DoEditorUi(Ui, Window, &Element->MoonColor, CSz("v3 MoonColor"), EDITOR_UI_FUNCTION_INSTANCE_NAMES); + DoEditorUi(Ui, Window, &Element->SunColor, CSz("v3 SunColor"), EDITOR_UI_FUNCTION_INSTANCE_NAMES); @@ -72,7 +70,7 @@ DoEditorUi(renderer_2d *Ui, window_layout *Window, lighting_settings *Element, c - DoEditorUi(Ui, Window, &Element->SunIntensity, CSz("f32 SunIntensity"), EDITOR_UI_FUNCTION_INSTANCE_NAMES,0.f, 3.f); + DoEditorUi(Ui, Window, &Element->DuskIntensity, CSz("f32 DuskIntensity"), EDITOR_UI_FUNCTION_INSTANCE_NAMES,0.f, 3.f); @@ -80,15 +78,16 @@ DoEditorUi(renderer_2d *Ui, window_layout *Window, lighting_settings *Element, c PushNewRow(Ui); - DoEditorUi(Ui, Window, &Element->MoonIntensity, CSz("f32 MoonIntensity"), EDITOR_UI_FUNCTION_INSTANCE_NAMES,0.f, 3.f); + DoEditorUi(Ui, Window, &Element->DuskColor, CSz("v3 DuskColor"), EDITOR_UI_FUNCTION_INSTANCE_NAMES); - PushNewRow(Ui); - DoEditorUi(Ui, Window, &Element->DawnIntensity, CSz("f32 DawnIntensity"), EDITOR_UI_FUNCTION_INSTANCE_NAMES,0.f, 3.f); + + + DoEditorUi(Ui, Window, &Element->MoonIntensity, CSz("f32 MoonIntensity"), EDITOR_UI_FUNCTION_INSTANCE_NAMES,0.f, 3.f); @@ -96,14 +95,15 @@ DoEditorUi(renderer_2d *Ui, window_layout *Window, lighting_settings *Element, c PushNewRow(Ui); - DoEditorUi(Ui, Window, &Element->DuskIntensity, CSz("f32 DuskIntensity"), EDITOR_UI_FUNCTION_INSTANCE_NAMES,0.f, 3.f); + DoEditorUi(Ui, Window, &Element->MoonColor, CSz("v3 MoonColor"), EDITOR_UI_FUNCTION_INSTANCE_NAMES); + - PushNewRow(Ui); + DoEditorUi(Ui, Window, &Element->CurrentSunColor, CSz("v3 CurrentSunColor"), EDITOR_UI_FUNCTION_INSTANCE_NAMES); PushForceUpdateBasis(Ui, V2(-20.f, 0.f)); PushTableEnd(Ui); diff --git a/generated/gen_common_vector_v2.h b/generated/gen_common_vector_v2.h index 9cd0c2705..1ae19d314 100644 --- a/generated/gen_common_vector_v2.h +++ b/generated/gen_common_vector_v2.h @@ -79,6 +79,17 @@ ClampPositive( v2 V ) return Result; } +inline v2 +Clamp01( v2 V ) +{ + v2 Result = V; + if ( V.E[0] < r32(0) ) Result.E[0] = r32(0); + if ( V.E[0] > r32(1) ) Result.E[0] = r32(1); + if ( V.E[1] < r32(0) ) Result.E[1] = r32(0); + if ( V.E[1] > r32(1) ) Result.E[1] = r32(1); + return Result; +} + diff --git a/generated/gen_common_vector_v3.h b/generated/gen_common_vector_v3.h index 6e5edc4de..f252203f4 100644 --- a/generated/gen_common_vector_v3.h +++ b/generated/gen_common_vector_v3.h @@ -86,6 +86,19 @@ ClampPositive( v3 V ) return Result; } +inline v3 +Clamp01( v3 V ) +{ + v3 Result = V; + if ( V.E[0] < r32(0) ) Result.E[0] = r32(0); + if ( V.E[0] > r32(1) ) Result.E[0] = r32(1); + if ( V.E[1] < r32(0) ) Result.E[1] = r32(0); + if ( V.E[1] > r32(1) ) Result.E[1] = r32(1); + if ( V.E[2] < r32(0) ) Result.E[2] = r32(0); + if ( V.E[2] > r32(1) ) Result.E[2] = r32(1); + return Result; +} + diff --git a/generated/gen_common_vector_v3i.h b/generated/gen_common_vector_v3i.h index 3e88ceea0..93423adbe 100644 --- a/generated/gen_common_vector_v3i.h +++ b/generated/gen_common_vector_v3i.h @@ -86,6 +86,19 @@ ClampPositive( v3i V ) return Result; } +inline v3i +Clamp01( v3i V ) +{ + v3i Result = V; + if ( V.E[0] < s32(0) ) Result.E[0] = s32(0); + if ( V.E[0] > s32(1) ) Result.E[0] = s32(1); + if ( V.E[1] < s32(0) ) Result.E[1] = s32(0); + if ( V.E[1] > s32(1) ) Result.E[1] = s32(1); + if ( V.E[2] < s32(0) ) Result.E[2] = s32(0); + if ( V.E[2] > s32(1) ) Result.E[2] = s32(1); + return Result; +} + diff --git a/generated/gen_constructor_voxel_lighting.h b/generated/gen_constructor_voxel_lighting.h index f61fce16e..d8b22c005 100644 --- a/generated/gen_constructor_voxel_lighting.h +++ b/generated/gen_constructor_voxel_lighting.h @@ -1,4 +1,4 @@ -// src/engine/world_chunk.h:121:0 +// src/engine/world_chunk.h:127:0 link_internal voxel_lighting VoxelLighting( u8 Emission ) diff --git a/generated/gen_constructor_voxel_stack_element.h b/generated/gen_constructor_voxel_stack_element.h index 33b7a3619..20a9c9f91 100644 --- a/generated/gen_constructor_voxel_stack_element.h +++ b/generated/gen_constructor_voxel_stack_element.h @@ -1,4 +1,4 @@ -// src/engine/world_chunk.cpp:3860:0 +// src/engine/world_chunk.cpp:4026:0 link_internal voxel_stack_element VoxelStackElement( v3i VoxSimP , voxel_rule_direction Dir ) diff --git a/generated/gen_lerp_f32.h b/generated/gen_lerp_f32.h index 96618ece0..45c76da18 100644 --- a/generated/gen_lerp_f32.h +++ b/generated/gen_lerp_f32.h @@ -9,3 +9,12 @@ Lerp(r32 t, f32 P1, f32 P2) return Result; } +// https://paulbourke.net/miscellaneous/interpolation/ +// +link_internal f32 +CosineInterpolate( f32 t, f32 y1, f32 y2 ) +{ + f32 t2 = (1.f-Cos(t*PI32))/2.f; + return(y1*(1.f-t2)+y2*t2); +} + diff --git a/generated/gen_lerp_v2.h b/generated/gen_lerp_v2.h index de7e06989..069fb7480 100644 --- a/generated/gen_lerp_v2.h +++ b/generated/gen_lerp_v2.h @@ -9,3 +9,12 @@ Lerp(r32 t, v2 P1, v2 P2) return Result; } +// https://paulbourke.net/miscellaneous/interpolation/ +// +link_internal v2 +CosineInterpolate( f32 t, v2 y1, v2 y2 ) +{ + f32 t2 = (1.f-Cos(t*PI32))/2.f; + return(y1*(1.f-t2)+y2*t2); +} + diff --git a/generated/gen_lerp_v3.h b/generated/gen_lerp_v3.h index 34d70ed26..ab8bff6b1 100644 --- a/generated/gen_lerp_v3.h +++ b/generated/gen_lerp_v3.h @@ -9,3 +9,12 @@ Lerp(r32 t, v3 P1, v3 P2) return Result; } +// https://paulbourke.net/miscellaneous/interpolation/ +// +link_internal v3 +CosineInterpolate( f32 t, v3 y1, v3 y2 ) +{ + f32 t2 = (1.f-Cos(t*PI32))/2.f; + return(y1*(1.f-t2)+y2*t2); +} + diff --git a/generated/gen_map_value_to_range_r32.h b/generated/gen_map_value_to_range_r32.h index ba9d04902..f90e86615 100644 --- a/generated/gen_map_value_to_range_r32.h +++ b/generated/gen_map_value_to_range_r32.h @@ -1,4 +1,4 @@ -// external/bonsai_stdlib/src/random.h:82:0 +// external/bonsai_stdlib/src/random.h:183:0 link_internal r32 MapValueToRange( r32 LowestPossibleValue, r32 Value, r32 HighestPossibleValue) @@ -10,3 +10,15 @@ MapValueToRange( r32 LowestPossibleValue, r32 Value, r32 HighestPossibleValue) return Result; } +link_internal r32 +MapValueToUnilateral( r32 LowestPossibleValue, r32 Value, r32 HighestPossibleValue) +{ + Assert(Value >= LowestPossibleValue); + Assert(Value <= HighestPossibleValue); + r32 Range = r32(HighestPossibleValue - LowestPossibleValue); + r32 Result = (Value-r32(LowestPossibleValue)) / Range; + Assert(Result >= 0.f); + Assert(Result <= 1.f); + return Result; +} + diff --git a/generated/gen_map_value_to_range_s32.h b/generated/gen_map_value_to_range_s32.h index 722e6fcb9..69afe79a6 100644 --- a/generated/gen_map_value_to_range_s32.h +++ b/generated/gen_map_value_to_range_s32.h @@ -1,4 +1,4 @@ -// external/bonsai_stdlib/src/random.h:88:0 +// external/bonsai_stdlib/src/random.h:189:0 link_internal s32 MapValueToRange( s32 LowestPossibleValue, r32 Value, s32 HighestPossibleValue) @@ -10,3 +10,15 @@ MapValueToRange( s32 LowestPossibleValue, r32 Value, s32 HighestPossibleValue) return Result; } +link_internal r32 +MapValueToUnilateral( s32 LowestPossibleValue, r32 Value, s32 HighestPossibleValue) +{ + Assert(Value >= LowestPossibleValue); + Assert(Value <= HighestPossibleValue); + r32 Range = r32(HighestPossibleValue - LowestPossibleValue); + r32 Result = (Value-r32(LowestPossibleValue)) / Range; + Assert(Result >= 0.f); + Assert(Result <= 1.f); + return Result; +} + diff --git a/generated/gen_map_value_to_range_u32.h b/generated/gen_map_value_to_range_u32.h index 2ff4dfb96..d4fb6c9d7 100644 --- a/generated/gen_map_value_to_range_u32.h +++ b/generated/gen_map_value_to_range_u32.h @@ -1,4 +1,4 @@ -// external/bonsai_stdlib/src/random.h:85:0 +// external/bonsai_stdlib/src/random.h:186:0 link_internal u32 MapValueToRange( u32 LowestPossibleValue, r32 Value, u32 HighestPossibleValue) @@ -10,3 +10,15 @@ MapValueToRange( u32 LowestPossibleValue, r32 Value, u32 HighestPossibleValue) return Result; } +link_internal r32 +MapValueToUnilateral( u32 LowestPossibleValue, r32 Value, u32 HighestPossibleValue) +{ + Assert(Value >= LowestPossibleValue); + Assert(Value <= HighestPossibleValue); + r32 Range = r32(HighestPossibleValue - LowestPossibleValue); + r32 Result = (Value-r32(LowestPossibleValue)) / Range; + Assert(Result >= 0.f); + Assert(Result <= 1.f); + return Result; +} + diff --git a/generated/gen_random_between_r32.h b/generated/gen_random_between_r32.h index dd17718bd..8c29a392d 100644 --- a/generated/gen_random_between_r32.h +++ b/generated/gen_random_between_r32.h @@ -1,4 +1,4 @@ -// external/bonsai_stdlib/src/random.h:108:0 +// external/bonsai_stdlib/src/random.h:209:0 link_internal r32 RandomBetween( r32 LowestPossibleValue, random_series *Entropy, r32 HighestPossibleValue) diff --git a/generated/gen_random_between_s32.h b/generated/gen_random_between_s32.h index fc7b3569e..f3aea7d4d 100644 --- a/generated/gen_random_between_s32.h +++ b/generated/gen_random_between_s32.h @@ -1,4 +1,4 @@ -// external/bonsai_stdlib/src/random.h:114:0 +// external/bonsai_stdlib/src/random.h:215:0 link_internal s32 RandomBetween( s32 LowestPossibleValue, random_series *Entropy, s32 HighestPossibleValue) diff --git a/generated/gen_random_between_u32.h b/generated/gen_random_between_u32.h index a9d3b4965..5d3a78c3d 100644 --- a/generated/gen_random_between_u32.h +++ b/generated/gen_random_between_u32.h @@ -1,4 +1,4 @@ -// external/bonsai_stdlib/src/random.h:111:0 +// external/bonsai_stdlib/src/random.h:212:0 link_internal u32 RandomBetween( u32 LowestPossibleValue, random_series *Entropy, u32 HighestPossibleValue) diff --git a/generated/generate_cursor_debug_profile_scope.h b/generated/generate_cursor_debug_profile_scope.h new file mode 100644 index 000000000..53936a841 --- /dev/null +++ b/generated/generate_cursor_debug_profile_scope.h @@ -0,0 +1,183 @@ +// external/bonsai_debug/src/api.h:113:0 + +struct debug_profile_scope_cursor +{ + debug_profile_scope *Start; + // TODO(Jesse)(immediate): For the love of fucksakes change these to indices + debug_profile_scope *At; + debug_profile_scope *End; + /* OWNED_BY_THREAD_MEMBER(); */ +}; + + + +link_internal debug_profile_scope_cursor +DebugProfileScopeCursor(umm ElementCount, memory_arena* Memory) +{ + debug_profile_scope *Start = (debug_profile_scope*)PushStruct(Memory, sizeof(debug_profile_scope)*ElementCount, 1, 0); + debug_profile_scope_cursor Result = { + .Start = Start, + .End = Start+ElementCount, + .At = Start, + /* OWNED_BY_THREAD_MEMBER_INIT() */ + }; + return Result; +} + +link_internal debug_profile_scope* +GetPtr(debug_profile_scope_cursor *Cursor, umm ElementIndex) +{ + /* ENSURE_OWNED_BY_THREAD(Cursor); */ + + debug_profile_scope *Result = {}; + if (ElementIndex < AtElements(Cursor)) { Result = Cursor->Start+ElementIndex; } + return Result; +} + +link_internal debug_profile_scope* +GetPtrUnsafe(debug_profile_scope_cursor *Cursor, umm ElementIndex) +{ + /* ENSURE_OWNED_BY_THREAD(Cursor); */ + + debug_profile_scope *Result = {}; + if (ElementIndex < TotalElements(Cursor)) { Result = Cursor->Start+ElementIndex; } + return Result; +} + +link_internal debug_profile_scope +Get(debug_profile_scope_cursor *Cursor, umm ElementIndex) +{ + /* ENSURE_OWNED_BY_THREAD(Cursor); */ + + Assert(ElementIndex < CurrentCount(Cursor)); + debug_profile_scope Result = Cursor->Start[ElementIndex]; + return Result; +} + +link_internal void +Set(debug_profile_scope_cursor *Cursor, umm ElementIndex, debug_profile_scope Element) +{ + /* ENSURE_OWNED_BY_THREAD(Cursor); */ + + umm CurrentElementCount = CurrentCount(Cursor); + Assert (ElementIndex <= CurrentElementCount); + + Cursor->Start[ElementIndex] = Element; + if (ElementIndex == CurrentElementCount) + { + Cursor->At++; + } +} + +link_internal debug_profile_scope* +Advance(debug_profile_scope_cursor *Cursor) +{ + /* ENSURE_OWNED_BY_THREAD(Cursor); */ + + debug_profile_scope * Result = {}; + if ( Cursor->At < Cursor->End ) { Result = Cursor->At++; } + return Result; +} + +link_internal debug_profile_scope * +Push(debug_profile_scope_cursor *Cursor, debug_profile_scope Element) +{ + /* ENSURE_OWNED_BY_THREAD(Cursor); */ + + Assert( Cursor->At < Cursor->End ); + debug_profile_scope *Result = Cursor->At; + *Cursor->At++ = Element; + return Result; +} + +link_internal debug_profile_scope +Pop(debug_profile_scope_cursor *Cursor) +{ + /* ENSURE_OWNED_BY_THREAD(Cursor); */ + + Assert( Cursor->At > Cursor->Start ); + debug_profile_scope Result = Cursor->At[-1]; + Cursor->At--; + return Result; +} + +link_internal s32 +LastIndex(debug_profile_scope_cursor *Cursor) +{ + /* ENSURE_OWNED_BY_THREAD(Cursor); */ + + s32 Result = s32(CurrentCount(Cursor))-1; + return Result; +} + +link_internal debug_profile_scope* +LastElement(debug_profile_scope_cursor *Cursor) +{ + debug_profile_scope *Result = {}; + s32 I = LastIndex(Cursor); + if (I > -1) { Result = Cursor->Start + I; } + return Result; +} + +link_internal b32 +Remove(debug_profile_scope_cursor *Cursor, debug_profile_scope Query) +{ + /* ENSURE_OWNED_BY_THREAD(Cursor); */ + + b32 Result = False; + CursorIterator(ElementIndex, Cursor) + { + debug_profile_scope Element = Get(Cursor, ElementIndex); + if (AreEqual(Element, Query)) + { + b32 IsLastIndex = LastIndex(Cursor) == s32(ElementIndex); + debug_profile_scope Tmp = Pop(Cursor); + + if (IsLastIndex) { Assert(AreEqual(Tmp, Query)); } + else { Set(Cursor, ElementIndex, Tmp); } + Result = True; + } + } + return Result; +} + + +link_internal b32 +ResizeCursor(debug_profile_scope_cursor *Cursor, umm Count, memory_arena *Memory) +{ + /* ENSURE_OWNED_BY_THREAD(Cursor); */ + + umm CurrentSize = TotalSize(Cursor); + + TruncateToElementCount(Cursor, Count); + umm NewSize = TotalSize(Cursor); + + Assert(NewSize/sizeof(debug_profile_scope) == Count); + + /* Info("Attempting to reallocate CurrentSize(%u), NewSize(%u)", CurrentSize, NewSize); */ + Ensure(Reallocate((u8*)Cursor->Start, Memory, CurrentSize, NewSize)); + return 0; +} + +link_internal void +Unshift( debug_profile_scope_cursor *Cursor ) +{ + /* ENSURE_OWNED_BY_THREAD(Cursor); */ + umm Count = AtElements(Cursor); + if (Count) + { + for (umm Index = 1; Index < Count; ++Index) + { + Cursor->Start[Index-1] = Cursor->Start[Index]; + } + + // NOTE(Jesse): This is actually correct, even though it doesn't look + // like it at first glance. At is OnePastLast, so decrementing and + // then clearing overwrites the last value that was set. + Cursor->At--; + *Cursor->At = {}; + } +} + + + diff --git a/generated/generate_cursor_debug_profile_scope_ptr.h b/generated/generate_cursor_debug_profile_scope_ptr.h new file mode 100644 index 000000000..7747685dd --- /dev/null +++ b/generated/generate_cursor_debug_profile_scope_ptr.h @@ -0,0 +1,183 @@ +// external/bonsai_debug/src/api.h:114:0 + +struct debug_profile_scope_ptr_cursor +{ + debug_profile_scope_ptr *Start; + // TODO(Jesse)(immediate): For the love of fucksakes change these to indices + debug_profile_scope_ptr *At; + debug_profile_scope_ptr *End; + /* OWNED_BY_THREAD_MEMBER(); */ +}; + + + +link_internal debug_profile_scope_ptr_cursor +DebugProfileScopePtrCursor(umm ElementCount, memory_arena* Memory) +{ + debug_profile_scope_ptr *Start = (debug_profile_scope_ptr*)PushStruct(Memory, sizeof(debug_profile_scope_ptr)*ElementCount, 1, 0); + debug_profile_scope_ptr_cursor Result = { + .Start = Start, + .End = Start+ElementCount, + .At = Start, + /* OWNED_BY_THREAD_MEMBER_INIT() */ + }; + return Result; +} + +link_internal debug_profile_scope_ptr* +GetPtr(debug_profile_scope_ptr_cursor *Cursor, umm ElementIndex) +{ + /* ENSURE_OWNED_BY_THREAD(Cursor); */ + + debug_profile_scope_ptr *Result = {}; + if (ElementIndex < AtElements(Cursor)) { Result = Cursor->Start+ElementIndex; } + return Result; +} + +link_internal debug_profile_scope_ptr* +GetPtrUnsafe(debug_profile_scope_ptr_cursor *Cursor, umm ElementIndex) +{ + /* ENSURE_OWNED_BY_THREAD(Cursor); */ + + debug_profile_scope_ptr *Result = {}; + if (ElementIndex < TotalElements(Cursor)) { Result = Cursor->Start+ElementIndex; } + return Result; +} + +link_internal debug_profile_scope_ptr +Get(debug_profile_scope_ptr_cursor *Cursor, umm ElementIndex) +{ + /* ENSURE_OWNED_BY_THREAD(Cursor); */ + + Assert(ElementIndex < CurrentCount(Cursor)); + debug_profile_scope_ptr Result = Cursor->Start[ElementIndex]; + return Result; +} + +link_internal void +Set(debug_profile_scope_ptr_cursor *Cursor, umm ElementIndex, debug_profile_scope_ptr Element) +{ + /* ENSURE_OWNED_BY_THREAD(Cursor); */ + + umm CurrentElementCount = CurrentCount(Cursor); + Assert (ElementIndex <= CurrentElementCount); + + Cursor->Start[ElementIndex] = Element; + if (ElementIndex == CurrentElementCount) + { + Cursor->At++; + } +} + +link_internal debug_profile_scope_ptr* +Advance(debug_profile_scope_ptr_cursor *Cursor) +{ + /* ENSURE_OWNED_BY_THREAD(Cursor); */ + + debug_profile_scope_ptr * Result = {}; + if ( Cursor->At < Cursor->End ) { Result = Cursor->At++; } + return Result; +} + +link_internal debug_profile_scope_ptr * +Push(debug_profile_scope_ptr_cursor *Cursor, debug_profile_scope_ptr Element) +{ + /* ENSURE_OWNED_BY_THREAD(Cursor); */ + + Assert( Cursor->At < Cursor->End ); + debug_profile_scope_ptr *Result = Cursor->At; + *Cursor->At++ = Element; + return Result; +} + +link_internal debug_profile_scope_ptr +Pop(debug_profile_scope_ptr_cursor *Cursor) +{ + /* ENSURE_OWNED_BY_THREAD(Cursor); */ + + Assert( Cursor->At > Cursor->Start ); + debug_profile_scope_ptr Result = Cursor->At[-1]; + Cursor->At--; + return Result; +} + +link_internal s32 +LastIndex(debug_profile_scope_ptr_cursor *Cursor) +{ + /* ENSURE_OWNED_BY_THREAD(Cursor); */ + + s32 Result = s32(CurrentCount(Cursor))-1; + return Result; +} + +link_internal debug_profile_scope_ptr* +LastElement(debug_profile_scope_ptr_cursor *Cursor) +{ + debug_profile_scope_ptr *Result = {}; + s32 I = LastIndex(Cursor); + if (I > -1) { Result = Cursor->Start + I; } + return Result; +} + +link_internal b32 +Remove(debug_profile_scope_ptr_cursor *Cursor, debug_profile_scope_ptr Query) +{ + /* ENSURE_OWNED_BY_THREAD(Cursor); */ + + b32 Result = False; + CursorIterator(ElementIndex, Cursor) + { + debug_profile_scope_ptr Element = Get(Cursor, ElementIndex); + if (AreEqual(Element, Query)) + { + b32 IsLastIndex = LastIndex(Cursor) == s32(ElementIndex); + debug_profile_scope_ptr Tmp = Pop(Cursor); + + if (IsLastIndex) { Assert(AreEqual(Tmp, Query)); } + else { Set(Cursor, ElementIndex, Tmp); } + Result = True; + } + } + return Result; +} + + +link_internal b32 +ResizeCursor(debug_profile_scope_ptr_cursor *Cursor, umm Count, memory_arena *Memory) +{ + /* ENSURE_OWNED_BY_THREAD(Cursor); */ + + umm CurrentSize = TotalSize(Cursor); + + TruncateToElementCount(Cursor, Count); + umm NewSize = TotalSize(Cursor); + + Assert(NewSize/sizeof(debug_profile_scope_ptr) == Count); + + /* Info("Attempting to reallocate CurrentSize(%u), NewSize(%u)", CurrentSize, NewSize); */ + Ensure(Reallocate((u8*)Cursor->Start, Memory, CurrentSize, NewSize)); + return 0; +} + +link_internal void +Unshift( debug_profile_scope_ptr_cursor *Cursor ) +{ + /* ENSURE_OWNED_BY_THREAD(Cursor); */ + umm Count = AtElements(Cursor); + if (Count) + { + for (umm Index = 1; Index < Count; ++Index) + { + Cursor->Start[Index-1] = Cursor->Start[Index]; + } + + // NOTE(Jesse): This is actually correct, even though it doesn't look + // like it at first glance. At is OnePastLast, so decrementing and + // then clearing overwrites the last value that was set. + Cursor->At--; + *Cursor->At = {}; + } +} + + + diff --git a/generated/generate_cursor_texture.h b/generated/generate_cursor_texture.h index 40abb7d39..f3f0727b7 100644 --- a/generated/generate_cursor_texture.h +++ b/generated/generate_cursor_texture.h @@ -1,4 +1,4 @@ -// external/bonsai_stdlib/src/texture_cursor.cpp:17:0 +// external/bonsai_stdlib/src/texture_cursor.cpp:10:0 struct texture_cursor { diff --git a/generated/generate_cursor_voxel_stack_element.h b/generated/generate_cursor_voxel_stack_element.h index 72e38c3c0..b331e48a5 100644 --- a/generated/generate_cursor_voxel_stack_element.h +++ b/generated/generate_cursor_voxel_stack_element.h @@ -1,4 +1,4 @@ -// src/engine/world_chunk.cpp:3866:0 +// src/engine/world_chunk.cpp:4032:0 struct voxel_stack_element_cursor { diff --git a/generated/generate_stack_voxel_synthesis_change_propagation_info_803395170.h b/generated/generate_stack_voxel_synthesis_change_propagation_info_803395170.h index 884418040..2595ece0a 100644 --- a/generated/generate_stack_voxel_synthesis_change_propagation_info_803395170.h +++ b/generated/generate_stack_voxel_synthesis_change_propagation_info_803395170.h @@ -1,4 +1,4 @@ -// src/engine/voxel_synthesis.h:333:0 +// src/engine/voxel_synthesis.h:327:0 struct voxel_synthesis_change_propagation_info_stack { diff --git a/generated/generate_stream_compact_standing_spot.h b/generated/generate_stream_compact_standing_spot.h index 8a7d0ae69..132287591 100644 --- a/generated/generate_stream_compact_standing_spot.h +++ b/generated/generate_stream_compact_standing_spot.h @@ -1,4 +1,4 @@ -// src/engine/world_chunk.h:511:0 +// src/engine/world_chunk.h:523:0 link_internal standing_spot_buffer Compact(standing_spot_stream *Stream, memory_arena *PermMemory) diff --git a/generated/generate_stream_compact_v3i.h b/generated/generate_stream_compact_v3i.h index 2c42e9086..e6ed58bda 100644 --- a/generated/generate_stream_compact_v3i.h +++ b/generated/generate_stream_compact_v3i.h @@ -1,4 +1,4 @@ -// src/engine/world_chunk.cpp:2779:0 +// src/engine/world_chunk.cpp:2916:0 link_internal v3i_buffer Compact(v3i_stream *Stream, memory_arena *PermMemory) diff --git a/generated/generate_stream_standing_spot.h b/generated/generate_stream_standing_spot.h index 3e17a22d6..ed69b7ae5 100644 --- a/generated/generate_stream_standing_spot.h +++ b/generated/generate_stream_standing_spot.h @@ -1,4 +1,4 @@ -// src/engine/world_chunk.h:508:0 +// src/engine/world_chunk.h:520:0 struct standing_spot_stream_chunk { diff --git a/generated/generate_string_table_world_chunk_mesh_bitfield.h b/generated/generate_string_table_world_chunk_mesh_bitfield.h index bab34ccc1..61d1f2337 100644 --- a/generated/generate_string_table_world_chunk_mesh_bitfield.h +++ b/generated/generate_string_table_world_chunk_mesh_bitfield.h @@ -1,4 +1,4 @@ -// src/engine/world_chunk.h:220:0 +// src/engine/world_chunk.h:226:0 link_internal counted_string ToString(world_chunk_mesh_bitfield Type) diff --git a/generated/generate_string_table_world_chunk_mesh_index.h b/generated/generate_string_table_world_chunk_mesh_index.h index 8f5f75a34..49e5429ed 100644 --- a/generated/generate_string_table_world_chunk_mesh_index.h +++ b/generated/generate_string_table_world_chunk_mesh_index.h @@ -1,4 +1,4 @@ -// src/engine/world_chunk.h:223:0 +// src/engine/world_chunk.h:229:0 link_internal counted_string ToString(world_chunk_mesh_index Type) diff --git a/generated/maybe_standing_spot.h b/generated/maybe_standing_spot.h index 5c66e849b..655572951 100644 --- a/generated/maybe_standing_spot.h +++ b/generated/maybe_standing_spot.h @@ -1,4 +1,4 @@ -// src/engine/world_chunk.h:459:0 +// src/engine/world_chunk.h:471:0 struct maybe_standing_spot { diff --git a/generated/radio_button_group_for_bitfield_enum_asset_spawn_mode.h b/generated/radio_button_group_for_bitfield_enum_asset_spawn_mode.h index dfb27d727..1b22a1f4b 100644 --- a/generated/radio_button_group_for_bitfield_enum_asset_spawn_mode.h +++ b/generated/radio_button_group_for_bitfield_enum_asset_spawn_mode.h @@ -1,4 +1,4 @@ -// src/engine/debug.h:132:0 +// src/engine/debug.h:145:0 link_internal void RadioSelect(ui_toggle_button_group *RadioGroup, asset_spawn_mode Selection) diff --git a/generated/radio_button_group_for_bitfield_enum_level_editor_flags.h b/generated/radio_button_group_for_bitfield_enum_level_editor_flags.h index 41fb6f9ba..154c27a6a 100644 --- a/generated/radio_button_group_for_bitfield_enum_level_editor_flags.h +++ b/generated/radio_button_group_for_bitfield_enum_level_editor_flags.h @@ -1,4 +1,4 @@ -// src/engine/editor.h:259:0 +// src/engine/editor.h:253:0 link_internal void RadioSelect(ui_toggle_button_group *RadioGroup, level_editor_flags Selection) diff --git a/generated/radio_button_group_for_bitfield_enum_terrain_gen_type.h b/generated/radio_button_group_for_bitfield_enum_terrain_gen_type.h index 10459b7e4..fa6fa85f7 100644 --- a/generated/radio_button_group_for_bitfield_enum_terrain_gen_type.h +++ b/generated/radio_button_group_for_bitfield_enum_terrain_gen_type.h @@ -1,4 +1,4 @@ -// examples/terrain_gen/game_types.h:21:0 +// examples/terrain_gen/game_types.h:23:0 link_internal void RadioSelect(ui_toggle_button_group *RadioGroup, terrain_gen_type Selection) @@ -17,7 +17,7 @@ GetRadioEnum(ui_toggle_button_group *RadioGroup, terrain_gen_type *Result) { Assert(CountBitsSet_Kernighan(RadioGroup->ToggleBits) == 1); // NOTE(Jesse): This is better; it asserts that we've actually got a bitfield - Assert(((RadioGroup->ToggleBits == TerrainGenType_Flat||RadioGroup->ToggleBits == TerrainGenType_Checkerboard||RadioGroup->ToggleBits == TerrainGenType_SinCos||RadioGroup->ToggleBits == TerrainGenType_Perlin2D||RadioGroup->ToggleBits == TerrainGenType_Perlin3D||RadioGroup->ToggleBits == TerrainGenType_FBM2D||RadioGroup->ToggleBits == TerrainGenType_TerracedTerrain||RadioGroup->ToggleBits == TerrainGenType_GrassyTerracedTerrain||RadioGroup->ToggleBits == TerrainGenType_GrassyLargeTerracedTerrain||RadioGroup->ToggleBits == TerrainGenType_GrassyTerracedTerrain2||RadioGroup->ToggleBits == TerrainGenType_GrassyTerracedTerrain3||RadioGroup->ToggleBits == TerrainGenType_GrassyIsland||RadioGroup->ToggleBits == TerrainGenType_Hoodoo||RadioGroup->ToggleBits == TerrainGenType_Warped))); + Assert(((RadioGroup->ToggleBits == TerrainGenType_Flat||RadioGroup->ToggleBits == TerrainGenType_Checkerboard||RadioGroup->ToggleBits == TerrainGenType_SinCos||RadioGroup->ToggleBits == TerrainGenType_Voronoi||RadioGroup->ToggleBits == TerrainGenType_Perlin2D||RadioGroup->ToggleBits == TerrainGenType_Perlin3D||RadioGroup->ToggleBits == TerrainGenType_FBM2D||RadioGroup->ToggleBits == TerrainGenType_TerracedTerrain||RadioGroup->ToggleBits == TerrainGenType_GrassyTerracedTerrain||RadioGroup->ToggleBits == TerrainGenType_GrassyLargeTerracedTerrain||RadioGroup->ToggleBits == TerrainGenType_GrassyTerracedTerrain2||RadioGroup->ToggleBits == TerrainGenType_GrassyTerracedTerrain3||RadioGroup->ToggleBits == TerrainGenType_GrassyTerracedTerrain4||RadioGroup->ToggleBits == TerrainGenType_GrassyIsland||RadioGroup->ToggleBits == TerrainGenType_Hoodoo||RadioGroup->ToggleBits == TerrainGenType_Warped))); /* Assert((((enum_t.map(value).sep(|) {value.name})) & RadioGroup->ToggleBits) != 0); */ } @@ -49,6 +49,7 @@ RadioButtonGroup_terrain_gen_type(renderer_2d *Ui, window_layout *Window, const CSz("Flat"), CSz("Checkerboard"), CSz("SinCos"), + CSz("Voronoi"), CSz("Perlin2D"), CSz("Perlin3D"), CSz("FBM2D"), @@ -57,6 +58,7 @@ RadioButtonGroup_terrain_gen_type(renderer_2d *Ui, window_layout *Window, const CSz("GrassyLargeTerracedTerrain"), CSz("GrassyTerracedTerrain2"), CSz("GrassyTerracedTerrain3"), + CSz("GrassyTerracedTerrain4"), CSz("GrassyIsland"), CSz("Hoodoo"), CSz("Warped"), diff --git a/generated/radio_button_group_for_bitfield_enum_world_edit_mode.h b/generated/radio_button_group_for_bitfield_enum_world_edit_mode.h index 1baf06caf..5b4073b01 100644 --- a/generated/radio_button_group_for_bitfield_enum_world_edit_mode.h +++ b/generated/radio_button_group_for_bitfield_enum_world_edit_mode.h @@ -1,4 +1,4 @@ -// src/engine/editor.h:340:0 +// src/engine/editor.h:334:0 link_internal void RadioSelect(ui_toggle_button_group *RadioGroup, world_edit_mode Selection) diff --git a/generated/scalar_math_fuctions_451039071.h b/generated/scalar_math_fuctions_451039071.h new file mode 100644 index 000000000..e87afb62a --- /dev/null +++ b/generated/scalar_math_fuctions_451039071.h @@ -0,0 +1,45 @@ +// external/bonsai_stdlib/src/math.h:326:0 + +inline r32 +Clamp( r32 Min, r32 Value, r32 Max ) +{ + if (Value > Max) { Value = Max; } + if (Value < Min) { Value = Min; } + return Value; +} +inline r64 +Clamp( r64 Min, r64 Value, r64 Max ) +{ + if (Value > Max) { Value = Max; } + if (Value < Min) { Value = Min; } + return Value; +} +inline u32 +Clamp( u32 Min, u32 Value, u32 Max ) +{ + if (Value > Max) { Value = Max; } + if (Value < Min) { Value = Min; } + return Value; +} +inline u64 +Clamp( u64 Min, u64 Value, u64 Max ) +{ + if (Value > Max) { Value = Max; } + if (Value < Min) { Value = Min; } + return Value; +} +inline s32 +Clamp( s32 Min, s32 Value, s32 Max ) +{ + if (Value > Max) { Value = Max; } + if (Value < Min) { Value = Min; } + return Value; +} +inline s64 +Clamp( s64 Min, s64 Value, s64 Max ) +{ + if (Value > Max) { Value = Max; } + if (Value < Min) { Value = Min; } + return Value; +} + diff --git a/generated/serdes_struct_bonsai_type_info.h b/generated/serdes_struct_bonsai_type_info.h index a18f03de0..67ddcb659 100644 --- a/generated/serdes_struct_bonsai_type_info.h +++ b/generated/serdes_struct_bonsai_type_info.h @@ -1,4 +1,4 @@ -// src/engine/serdes.cpp:371:0 +// src/engine/serdes.cpp:380:0 link_internal bonsai_type_info TypeInfo(bonsai_type_info *Ignored) diff --git a/generated/serdes_struct_bonsai_type_info_buffer.h b/generated/serdes_struct_bonsai_type_info_buffer.h index 674aec457..36e5e777c 100644 --- a/generated/serdes_struct_bonsai_type_info_buffer.h +++ b/generated/serdes_struct_bonsai_type_info_buffer.h @@ -1,4 +1,4 @@ -// src/engine/serdes.cpp:373:0 +// src/engine/serdes.cpp:382:0 link_internal bonsai_type_info TypeInfo(bonsai_type_info_buffer *Ignored) diff --git a/generated/serdes_struct_entity_id.h b/generated/serdes_struct_entity_id.h index 8cd4e0f06..5b16f3e7b 100644 --- a/generated/serdes_struct_entity_id.h +++ b/generated/serdes_struct_entity_id.h @@ -42,12 +42,6 @@ Serialize(u8_cursor_block_array *Bytes, entity_id *BaseElement, umm Count = 1) Result &= Serialize(Bytes, &Element->Generation); - - - - - - MAYBE_WRITE_DEBUG_OBJECT_DELIM(); @@ -81,12 +75,6 @@ DeserializeCurrentVersion(u8_cursor *Bytes, entity_id *Element, memory_arena *Me // strings are considered primitive, but need memory to deserialize Result &= Deserialize(Bytes, &Element->Generation, Memory); - - - - - - MAYBE_READ_DEBUG_OBJECT_DELIM(); diff --git a/generated/serdes_struct_lighting_settings.h b/generated/serdes_struct_lighting_settings.h index 599a2edb2..0f5687314 100644 --- a/generated/serdes_struct_lighting_settings.h +++ b/generated/serdes_struct_lighting_settings.h @@ -1,4 +1,4 @@ -// src/engine/serdes.cpp:359:0 +// src/engine/serdes.cpp:368:0 link_internal bonsai_type_info TypeInfo(lighting_settings *Ignored) @@ -6,7 +6,7 @@ TypeInfo(lighting_settings *Ignored) bonsai_type_info Result = {}; Result.Name = CSz("lighting_settings"); - Result.Version = 0 ; + Result.Version =1 ; /* type.map(member) */ /* { */ @@ -29,7 +29,10 @@ Serialize(u8_cursor_block_array *Bytes, lighting_settings *BaseElement, umm Coun b32 Result = True; - + Upsert(TypeInfo(BaseElement), &Global_SerializeTypeTable, Global_SerializeTypeTableArena ); + u64 VersionNumber =1; + Serialize(Bytes, &VersionNumber); + RangeIterator_t(umm, ElementIndex, Count) { @@ -52,49 +55,49 @@ Serialize(u8_cursor_block_array *Bytes, lighting_settings *BaseElement, umm Coun - Result &= Serialize(Bytes, &Element->DawnColor); + Result &= Serialize(Bytes, &Element->DawnIntensity); - Result &= Serialize(Bytes, &Element->SunColor); + Result &= Serialize(Bytes, &Element->DawnColor); - Result &= Serialize(Bytes, &Element->DuskColor); + Result &= Serialize(Bytes, &Element->SunIntensity); - Result &= Serialize(Bytes, &Element->MoonColor); + Result &= Serialize(Bytes, &Element->SunColor); - Result &= Serialize(Bytes, &Element->SunIntensity); + Result &= Serialize(Bytes, &Element->DuskIntensity); - Result &= Serialize(Bytes, &Element->MoonIntensity); + Result &= Serialize(Bytes, &Element->DuskColor); - Result &= Serialize(Bytes, &Element->DawnIntensity); + Result &= Serialize(Bytes, &Element->MoonIntensity); - Result &= Serialize(Bytes, &Element->DuskIntensity); + Result &= Serialize(Bytes, &Element->MoonColor); @@ -117,6 +120,28 @@ link_internal b32 DeserializeCurrentVersion(u8_cursor *Bytes, lighting_settings *Element, memory_arena *Memory); +link_internal b32 +DeserializeVersioned(u8_cursor *Bytes, lighting_settings *Element, bonsai_type_info *TypeInfo, u64 Version, memory_arena *Memory) +{ + Assert(Version <=1); + + b32 Result = True; + + if (Version == 0) + { + lighting_settings_0 T0 = {}; + Result &= Deserialize(Bytes, &T0, Memory); + Marshal(&T0, Element); + } + + + if (Version ==1) + { + Result &= DeserializeCurrentVersion(Bytes, Element, Memory); + } + + return Result; +} link_internal b32 @@ -149,7 +174,7 @@ DeserializeCurrentVersion(u8_cursor *Bytes, lighting_settings *Element, memory_a // NOTE(Jesse): Unfortunately we can't check for primitives because // strings are considered primitive, but need memory to deserialize - Result &= Deserialize(Bytes, &Element->DawnColor, Memory); + Result &= Deserialize(Bytes, &Element->DawnIntensity, Memory); @@ -157,7 +182,7 @@ DeserializeCurrentVersion(u8_cursor *Bytes, lighting_settings *Element, memory_a // NOTE(Jesse): Unfortunately we can't check for primitives because // strings are considered primitive, but need memory to deserialize - Result &= Deserialize(Bytes, &Element->SunColor, Memory); + Result &= Deserialize(Bytes, &Element->DawnColor, Memory); @@ -165,7 +190,7 @@ DeserializeCurrentVersion(u8_cursor *Bytes, lighting_settings *Element, memory_a // NOTE(Jesse): Unfortunately we can't check for primitives because // strings are considered primitive, but need memory to deserialize - Result &= Deserialize(Bytes, &Element->DuskColor, Memory); + Result &= Deserialize(Bytes, &Element->SunIntensity, Memory); @@ -173,7 +198,7 @@ DeserializeCurrentVersion(u8_cursor *Bytes, lighting_settings *Element, memory_a // NOTE(Jesse): Unfortunately we can't check for primitives because // strings are considered primitive, but need memory to deserialize - Result &= Deserialize(Bytes, &Element->MoonColor, Memory); + Result &= Deserialize(Bytes, &Element->SunColor, Memory); @@ -181,7 +206,7 @@ DeserializeCurrentVersion(u8_cursor *Bytes, lighting_settings *Element, memory_a // NOTE(Jesse): Unfortunately we can't check for primitives because // strings are considered primitive, but need memory to deserialize - Result &= Deserialize(Bytes, &Element->SunIntensity, Memory); + Result &= Deserialize(Bytes, &Element->DuskIntensity, Memory); @@ -189,7 +214,7 @@ DeserializeCurrentVersion(u8_cursor *Bytes, lighting_settings *Element, memory_a // NOTE(Jesse): Unfortunately we can't check for primitives because // strings are considered primitive, but need memory to deserialize - Result &= Deserialize(Bytes, &Element->MoonIntensity, Memory); + Result &= Deserialize(Bytes, &Element->DuskColor, Memory); @@ -197,7 +222,7 @@ DeserializeCurrentVersion(u8_cursor *Bytes, lighting_settings *Element, memory_a // NOTE(Jesse): Unfortunately we can't check for primitives because // strings are considered primitive, but need memory to deserialize - Result &= Deserialize(Bytes, &Element->DawnIntensity, Memory); + Result &= Deserialize(Bytes, &Element->MoonIntensity, Memory); @@ -205,7 +230,7 @@ DeserializeCurrentVersion(u8_cursor *Bytes, lighting_settings *Element, memory_a // NOTE(Jesse): Unfortunately we can't check for primitives because // strings are considered primitive, but need memory to deserialize - Result &= Deserialize(Bytes, &Element->DuskIntensity, Memory); + Result &= Deserialize(Bytes, &Element->MoonColor, Memory); @@ -229,7 +254,22 @@ Deserialize(u8_cursor *Bytes, lighting_settings *Element, memory_arena *Memory, b32 Result = True; RangeIterator_t(umm, ElementIndex, Count) { - Result &= DeserializeCurrentVersion(Bytes, Element+ElementIndex, Memory); + maybe_bonsai_type_info MaybeSerializedType = GetByName(&Global_SerializeTypeTable, CSz("lighting_settings")); + + if (MaybeSerializedType.Tag) + { + + u64 VersionNumber = 0; + if (MaybeSerializedType.Value.Version > 0) + { + Deserialize(Bytes, &VersionNumber, Memory); + } + Result &= DeserializeVersioned(Bytes, Element+ElementIndex, &MaybeSerializedType.Value, VersionNumber, Memory); + } + else + { + Result &= DeserializeCurrentVersion(Bytes, Element+ElementIndex, Memory); + } } diff --git a/generated/serdes_struct_lighting_settings_0.h b/generated/serdes_struct_lighting_settings_0.h new file mode 100644 index 000000000..89fd5add6 --- /dev/null +++ b/generated/serdes_struct_lighting_settings_0.h @@ -0,0 +1,239 @@ +// src/engine/serdes.cpp:365:0 + +link_internal bonsai_type_info +TypeInfo(lighting_settings_0 *Ignored) +{ + bonsai_type_info Result = {}; + + Result.Name = CSz("lighting_settings_0"); + Result.Version = 0 ; + + /* type.map(member) */ + /* { */ + /* { */ + /* member_info Member = {CSz("member.name"), CSz("member.name"), 0x(member.hash)}; */ + /* Push(&Result.Members, &Member); */ + /* } */ + /* } */ + + return Result; +} + +link_internal b32 +Serialize(u8_cursor_block_array *Bytes, lighting_settings_0 *BaseElement, umm Count = 1) +{ + Assert(Count > 0); + + u64 PointerTrue = True; + u64 PointerFalse = False; + + b32 Result = True; + + + + RangeIterator_t(umm, ElementIndex, Count) + { + lighting_settings_0 *Element = BaseElement + ElementIndex; + Result &= Serialize(Bytes, &Element->AutoDayNightCycle); + + + + + + Result &= Serialize(Bytes, &Element->tDay); + + + + + + Result &= Serialize(Bytes, &Element->SunP); + + + + + + Result &= Serialize(Bytes, &Element->DawnColor); + + + + + + Result &= Serialize(Bytes, &Element->SunColor); + + + + + + Result &= Serialize(Bytes, &Element->DuskColor); + + + + + + Result &= Serialize(Bytes, &Element->MoonColor); + + + + + + Result &= Serialize(Bytes, &Element->SunIntensity); + + + + + + Result &= Serialize(Bytes, &Element->MoonIntensity); + + + + + + Result &= Serialize(Bytes, &Element->DawnIntensity); + + + + + + Result &= Serialize(Bytes, &Element->DuskIntensity); + + + + + + Result &= Serialize(Bytes, &Element->CurrentSunColor); + + + + MAYBE_WRITE_DEBUG_OBJECT_DELIM(); + } + + return Result; +} + +link_internal b32 +Deserialize(u8_cursor *Bytes, lighting_settings_0 *Element, memory_arena *Memory, umm Count = 1); + +link_internal b32 +DeserializeCurrentVersion(u8_cursor *Bytes, lighting_settings_0 *Element, memory_arena *Memory); + + + + +link_internal b32 +DeserializeCurrentVersion(u8_cursor *Bytes, lighting_settings_0 *Element, memory_arena *Memory) +{ + b32 Result = True; + // NOTE(Jesse): Unfortunately we can't check for primitives because + // strings are considered primitive, but need memory to deserialize + Result &= Deserialize(Bytes, &Element->AutoDayNightCycle, Memory); + + + + + + // NOTE(Jesse): Unfortunately we can't check for primitives because + // strings are considered primitive, but need memory to deserialize + Result &= Deserialize(Bytes, &Element->tDay, Memory); + + + + + + // NOTE(Jesse): Unfortunately we can't check for primitives because + // strings are considered primitive, but need memory to deserialize + Result &= Deserialize(Bytes, &Element->SunP, Memory); + + + + + + // NOTE(Jesse): Unfortunately we can't check for primitives because + // strings are considered primitive, but need memory to deserialize + Result &= Deserialize(Bytes, &Element->DawnColor, Memory); + + + + + + // NOTE(Jesse): Unfortunately we can't check for primitives because + // strings are considered primitive, but need memory to deserialize + Result &= Deserialize(Bytes, &Element->SunColor, Memory); + + + + + + // NOTE(Jesse): Unfortunately we can't check for primitives because + // strings are considered primitive, but need memory to deserialize + Result &= Deserialize(Bytes, &Element->DuskColor, Memory); + + + + + + // NOTE(Jesse): Unfortunately we can't check for primitives because + // strings are considered primitive, but need memory to deserialize + Result &= Deserialize(Bytes, &Element->MoonColor, Memory); + + + + + + // NOTE(Jesse): Unfortunately we can't check for primitives because + // strings are considered primitive, but need memory to deserialize + Result &= Deserialize(Bytes, &Element->SunIntensity, Memory); + + + + + + // NOTE(Jesse): Unfortunately we can't check for primitives because + // strings are considered primitive, but need memory to deserialize + Result &= Deserialize(Bytes, &Element->MoonIntensity, Memory); + + + + + + // NOTE(Jesse): Unfortunately we can't check for primitives because + // strings are considered primitive, but need memory to deserialize + Result &= Deserialize(Bytes, &Element->DawnIntensity, Memory); + + + + + + // NOTE(Jesse): Unfortunately we can't check for primitives because + // strings are considered primitive, but need memory to deserialize + Result &= Deserialize(Bytes, &Element->DuskIntensity, Memory); + + + + + + // NOTE(Jesse): Unfortunately we can't check for primitives because + // strings are considered primitive, but need memory to deserialize + Result &= Deserialize(Bytes, &Element->CurrentSunColor, Memory); + + + + MAYBE_READ_DEBUG_OBJECT_DELIM(); + return Result; +} + +link_internal b32 +Deserialize(u8_cursor *Bytes, lighting_settings_0 *Element, memory_arena *Memory, umm Count) +{ + Assert(Count > 0); + + b32 Result = True; + RangeIterator_t(umm, ElementIndex, Count) + { + Result &= DeserializeCurrentVersion(Bytes, Element+ElementIndex, Memory); + + } + + return Result; +} + + diff --git a/generated/serdes_struct_render_settings.h b/generated/serdes_struct_render_settings.h index cd46d9dbf..fcefb89ea 100644 --- a/generated/serdes_struct_render_settings.h +++ b/generated/serdes_struct_render_settings.h @@ -1,4 +1,4 @@ -// src/engine/serdes.cpp:362:0 +// src/engine/serdes.cpp:371:0 link_internal bonsai_type_info TypeInfo(render_settings *Ignored) diff --git a/generated/serialize_struct_level_header.h b/generated/serialize_struct_level_header.h index 542cf3c0e..f324de156 100644 --- a/generated/serialize_struct_level_header.h +++ b/generated/serialize_struct_level_header.h @@ -1,4 +1,4 @@ -// src/engine/serdes.cpp:432:0 +// src/engine/serdes.cpp:441:0 link_internal bonsai_type_info TypeInfo(level_header *Ignored) diff --git a/generated/string_and_value_tables_terrain_gen_type.h b/generated/string_and_value_tables_terrain_gen_type.h index 065ec1547..91cffcaf5 100644 --- a/generated/string_and_value_tables_terrain_gen_type.h +++ b/generated/string_and_value_tables_terrain_gen_type.h @@ -1,4 +1,4 @@ -// examples/terrain_gen/game_types.h:24:0 +// examples/terrain_gen/game_types.h:26:0 link_internal counted_string ToString(terrain_gen_type Type) @@ -9,6 +9,7 @@ ToString(terrain_gen_type Type) case TerrainGenType_Flat: { Result = CSz("TerrainGenType_Flat"); } break; case TerrainGenType_Checkerboard: { Result = CSz("TerrainGenType_Checkerboard"); } break; case TerrainGenType_SinCos: { Result = CSz("TerrainGenType_SinCos"); } break; + case TerrainGenType_Voronoi: { Result = CSz("TerrainGenType_Voronoi"); } break; case TerrainGenType_Perlin2D: { Result = CSz("TerrainGenType_Perlin2D"); } break; case TerrainGenType_Perlin3D: { Result = CSz("TerrainGenType_Perlin3D"); } break; case TerrainGenType_FBM2D: { Result = CSz("TerrainGenType_FBM2D"); } break; @@ -17,6 +18,7 @@ ToString(terrain_gen_type Type) case TerrainGenType_GrassyLargeTerracedTerrain: { Result = CSz("TerrainGenType_GrassyLargeTerracedTerrain"); } break; case TerrainGenType_GrassyTerracedTerrain2: { Result = CSz("TerrainGenType_GrassyTerracedTerrain2"); } break; case TerrainGenType_GrassyTerracedTerrain3: { Result = CSz("TerrainGenType_GrassyTerracedTerrain3"); } break; + case TerrainGenType_GrassyTerracedTerrain4: { Result = CSz("TerrainGenType_GrassyTerracedTerrain4"); } break; case TerrainGenType_GrassyIsland: { Result = CSz("TerrainGenType_GrassyIsland"); } break; case TerrainGenType_Hoodoo: { Result = CSz("TerrainGenType_Hoodoo"); } break; case TerrainGenType_Warped: { Result = CSz("TerrainGenType_Warped"); } break; @@ -34,6 +36,7 @@ TerrainGenType(counted_string S) if (StringsMatch(S, CSz("TerrainGenType_Flat"))) { return TerrainGenType_Flat; } if (StringsMatch(S, CSz("TerrainGenType_Checkerboard"))) { return TerrainGenType_Checkerboard; } if (StringsMatch(S, CSz("TerrainGenType_SinCos"))) { return TerrainGenType_SinCos; } + if (StringsMatch(S, CSz("TerrainGenType_Voronoi"))) { return TerrainGenType_Voronoi; } if (StringsMatch(S, CSz("TerrainGenType_Perlin2D"))) { return TerrainGenType_Perlin2D; } if (StringsMatch(S, CSz("TerrainGenType_Perlin3D"))) { return TerrainGenType_Perlin3D; } if (StringsMatch(S, CSz("TerrainGenType_FBM2D"))) { return TerrainGenType_FBM2D; } @@ -42,6 +45,7 @@ TerrainGenType(counted_string S) if (StringsMatch(S, CSz("TerrainGenType_GrassyLargeTerracedTerrain"))) { return TerrainGenType_GrassyLargeTerracedTerrain; } if (StringsMatch(S, CSz("TerrainGenType_GrassyTerracedTerrain2"))) { return TerrainGenType_GrassyTerracedTerrain2; } if (StringsMatch(S, CSz("TerrainGenType_GrassyTerracedTerrain3"))) { return TerrainGenType_GrassyTerracedTerrain3; } + if (StringsMatch(S, CSz("TerrainGenType_GrassyTerracedTerrain4"))) { return TerrainGenType_GrassyTerracedTerrain4; } if (StringsMatch(S, CSz("TerrainGenType_GrassyIsland"))) { return TerrainGenType_GrassyIsland; } if (StringsMatch(S, CSz("TerrainGenType_Hoodoo"))) { return TerrainGenType_Hoodoo; } if (StringsMatch(S, CSz("TerrainGenType_Warped"))) { return TerrainGenType_Warped; } diff --git a/generated/string_and_value_tables_world_edit_mode.h b/generated/string_and_value_tables_world_edit_mode.h index 7fd061bde..5164078fc 100644 --- a/generated/string_and_value_tables_world_edit_mode.h +++ b/generated/string_and_value_tables_world_edit_mode.h @@ -1,4 +1,4 @@ -// src/engine/editor.h:337:0 +// src/engine/editor.h:331:0 link_internal counted_string ToString(world_edit_mode Type) diff --git a/generated/to_hex_64_272205387.h b/generated/to_hex_64_272205387.h index 3d6651ea6..3090e3bee 100644 --- a/generated/to_hex_64_272205387.h +++ b/generated/to_hex_64_272205387.h @@ -1,4 +1,4 @@ -// external/bonsai_stdlib/src/counted_string.cpp:725:0 +// external/bonsai_stdlib/src/counted_string.cpp:730:0 link_internal cs ToHex( s64 Value ) diff --git a/generated/toggle_button_group_for_enum_engine_debug_view_mode.h b/generated/toggle_button_group_for_enum_engine_debug_view_mode.h index a5f262586..5980d6ca4 100644 --- a/generated/toggle_button_group_for_enum_engine_debug_view_mode.h +++ b/generated/toggle_button_group_for_enum_engine_debug_view_mode.h @@ -1,4 +1,4 @@ -// src/engine/debug.h:158:0 +// src/engine/debug.h:171:0 link_internal b32 ToggledOn(ui_toggle_button_group *ButtonGroup, engine_debug_view_mode Enum) diff --git a/jesse.bonsai.rdbg b/jesse.bonsai.rdbg index b97a3cf49..283ccbaeb 100644 Binary files a/jesse.bonsai.rdbg and b/jesse.bonsai.rdbg differ diff --git a/jesse.make.sh b/jesse.make.sh index 3f493f529..d949cbedb 100644 --- a/jesse.make.sh +++ b/jesse.make.sh @@ -2,8 +2,8 @@ OPT="-O2" -# ./make.sh RunPoof -# [ $? -ne 0 ] && exit 1 +./make.sh RunPoof +[ $? -ne 0 ] && exit 1 # exit 1 # exit 0 diff --git a/make.sh b/make.sh index dd3e2c2ae..90eaa79c6 100755 --- a/make.sh +++ b/make.sh @@ -512,6 +512,11 @@ while (( "$#" )); do OPTIMIZATION_LEVEL="-O2" ;; + "-O3") + OPTIMIZATION_LEVEL="-O3" + ;; + + *) echo "Unrecognized Build Option ($CliArg), exiting." && exit 1 ;; diff --git a/readme.md b/readme.md index 170561335..a31156631 100644 --- a/readme.md +++ b/readme.md @@ -49,14 +49,17 @@ compiler, and a few appropriate system headers. * Context Switches (windows only) * Physical Core (windows only) -![banner](screenshots/8_skele.png) # Getting Started +![banner](screenshots/8_skele.png) + ## Building See the docs on the [build process](docs/01_build_process.md). +![banner](screenshots/grass.png) + # Wishlist ------------------------------------------------------------------------------- @@ -68,6 +71,8 @@ See the docs on the [build process](docs/01_build_process.md). [ ] Better shadows : https://developer.nvidia.com/gpugems/gpugems3/part-ii-light-and-shadows/chapter-8-summed-area-variance-shadow-maps +[ ] Screen Space Shadows : https://panoskarabelas.com/posts/screen_space_shadows/ + [ ] Motion Blur : https://developer.nvidia.com/gpugems/gpugems3/part-iv-image-effects/chapter-27-motion-blur-post-processing-effect [ ] TAA? @@ -88,12 +93,8 @@ See the docs on the [build process](docs/01_build_process.md). * https://xing-mei.github.io/files/erosion.pdf * https://nickmcd.me/2020/04/15/procedural-hydrology/ -[ ] Better perlin noise (with derivitives!) -* https://www.scratchapixel.com/lessons/procedural-generation-virtual-worlds/perlin-noise-part-2/perlin-noise-computing-derivatives.html - -[ ] Inigo Quilez noise? -* Value Noise : https://www.shadertoy.com/view/lsf3WH -* Gradient Noise : https://www.shadertoy.com/view/Xsl3Dl +[ ] Biomes +* https://en.wikipedia.org/wiki/Holdridge_life_zones ------------------------------------------------------------------------------- ## Sound @@ -114,3 +115,5 @@ See the docs on the [build process](docs/01_build_process.md). [ ] Better floating-point rng : https://www.corsix.org/content/higher-quality-random-floats [ ] Better greedy meshing? https://www.youtube.com/watch?v=4xs66m1Of4A + +[ ] More interpolation goodies : https://paulbourke.net/miscellaneous/interpolation/ diff --git a/screenshots/dusk_defence.png b/screenshots/dusk_defence.png index 4031c8256..6ae6936fc 100644 Binary files a/screenshots/dusk_defence.png and b/screenshots/dusk_defence.png differ diff --git a/screenshots/grass.png b/screenshots/grass.png new file mode 100644 index 000000000..ecc639fc5 Binary files /dev/null and b/screenshots/grass.png differ diff --git a/screenshots/profiler.png b/screenshots/profiler.png index 95463b8a4..3c4e0b688 100644 Binary files a/screenshots/profiler.png and b/screenshots/profiler.png differ diff --git a/src/engine/api.cpp b/src/engine/api.cpp index f90688834..89fa3068e 100644 --- a/src/engine/api.cpp +++ b/src/engine/api.cpp @@ -23,45 +23,10 @@ Bonsai_Init(engine_resources *Resources) { TIMED_FUNCTION(); - platform *Plat = &Resources->Stdlib.Plat; - b32 Result = True; - memory_arena *BonsaiInitArena = AllocateArena(Megabytes(256));; - DEBUG_REGISTER_ARENA(BonsaiInitArena, 0); - - Resources->Memory = BonsaiInitArena; - Resources->Heap = InitHeap(Gigabytes(2)); // TODO(Jesse): Is this actually used? - - Resources->AssetMemory = InitHeap(Gigabytes(1)); - - Init_Global_QuadVertexBuffer(); - - Resources->World = Allocate(world, BonsaiInitArena, 1); - if (!Resources->World) { Error("Allocating World"); return False; } - - Resources->Graphics = GraphicsInit(AllocateArena()); - if (!Resources->Graphics) { Error("Initializing Graphics"); return False; } - - { - memory_arena *UiMemory = AllocateArena(); - InitRenderer2D(&Resources->Ui, &Resources->Heap, UiMemory, &Plat->MouseP, &Plat->MouseDP, &Plat->ScreenDim, &Plat->Input); - /* Resources->UiSpriteTexture = LoadBitmap("assets/mystic_rpg_icon_pack/Sprites/300%/Tool_6.bmp", UiMemory); */ - /* Resources->UiSpriteTexture = LoadBitmap("assets/mystic_rpg_icon_pack/Sprites/300%/Tool_13.bmp", UiMemory); */ - - bitmap_block_array Bitmaps = {}; - LoadBitmapsFromFolder(CSz("assets/mystic_rpg_icon_pack/Sprites/300%/64x64_sprites"), &Bitmaps); - LoadBitmapsFromFolder(CSz("assets/mystic_rpg_icon_pack/Sprites/300%/44x44_sprites"), &Bitmaps); - Resources->Ui.SpriteTextureArray = CreateTextureArrayFromBitmapArray(&Bitmaps, V2i(64,64), UiMemory); - - /* Resources->UiSpriteTexture = LoadBitmap("assets/mystic_rpg_icon_pack/Sprites/300%/Tool_20.bmp", UiMemory); */ - /* Resources->UiSpriteTexture = LoadBitmap("assets/mystic_rpg_icon_pack/Sprites/300%/Inventory_0.bmp", UiMemory); */ - /* Resources->UiSpriteTexture = LoadBitmap("assets/test.bmp", UiMemory); */ - /* Resources->UiSpriteTexture = LoadBitmap("assets/test_1.bmp", UiMemory); */ - /* Resources->UiSpriteTexture = LoadBitmap("assets/test_2.bmp", UiMemory); */ - } - - Resources->EntityTable = AllocateEntityTable(BonsaiInitArena, TOTAL_ENTITY_COUNT); + Result &= InitEngineDebug(&Resources->EngineDebug); + Result &= InitEngineResources(Resources); return Result; } diff --git a/src/engine/camera.cpp b/src/engine/camera.cpp index 03bcafe63..3a8d48b3b 100644 --- a/src/engine/camera.cpp +++ b/src/engine/camera.cpp @@ -102,7 +102,12 @@ GetMouseDelta(platform *Plat) } link_internal void -UpdateGameCamera(world *World, v2 MouseDelta, r32 CameraZoomDelta, cp TargetViewP, camera *Camera, r32 Dt) +UpdateGameCamera( world *World, + v2 MouseDelta, + r32 CameraZoomDelta, + cp TargetViewP, + camera *Camera, + r32 Dt ) { // TODO(Jesse): Make these vary by DistanceFromTarget, such that the mouse feels the same amount of sensitive zoomed in as out. Camera->TargetYaw += MouseDelta.x; @@ -173,7 +178,7 @@ StandardCamera(camera* Camera, f32 FarClip, f32 DistanceFromTarget, f32 Blend, c Camera->Right = WORLD_X; Camera->TargetPitch = PI32 - (PI32*0.25f); - Camera->TargetYaw = PI32*0.15f; + Camera->TargetYaw = -PI32*0.15f; Camera->DistanceFromTarget = DistanceFromTarget; } diff --git a/src/engine/debug.cpp b/src/engine/debug.cpp index ef7a412fa..0c46f28f0 100644 --- a/src/engine/debug.cpp +++ b/src/engine/debug.cpp @@ -220,9 +220,9 @@ DoLevelWindow(engine_resources *Engine) } #endif - QueueChunkForMeshRebuild(&GetEngineResources()->Stdlib.Plat.LowPriority, Chunk, Flags); - InsertChunkIntoWorld(World, Chunk); + + QueueChunkForMeshRebuild(&GetEngineResources()->Stdlib.Plat.LowPriority, Chunk, Flags); } } @@ -616,6 +616,31 @@ DoAssetWindow(engine_resources *Engine) } } +link_internal void +DoWorldEditDebugWindow(engine_resources *Engine) +{ + UNPACK_ENGINE_RESOURCES(Engine); + + engine_debug *Debug = &Engine->EngineDebug; + + local_persist window_layout Window = WindowLayout("WorldEditDebug"); + { + PushWindowStart(Ui, &Window); + + /* camera C = {};; */ + /* StandardCamera(&C, 10000.f, 100.f, DEFAULT_CAMERA_BLENDING, {}); */ + + UpdateGameCamera(World, {}, {}, {}, &Debug->WorldEditDebugThumb.Camera, {}); + if (Debug->WorldEditDebugMesh.At) + { + RenderToTexture(Engine, &Debug->WorldEditDebugThumb, &Debug->WorldEditDebugMesh, {}); + PushTexturedQuad(Ui, Debug->WorldEditDebugThumb.Texture, V2(512), zDepth_Text); + } + + PushWindowEnd(Ui, &Window); + } +} + link_internal void DoEngineDebug(engine_resources *Engine) { @@ -672,6 +697,7 @@ DoEngineDebug(engine_resources *Engine) if (EngineDebug->PickedChunk) { + WorldChunkWindow.Title = FSz("World Chunk : (%p)", EngineDebug->PickedChunk); /* DebugUi(Engine, CSz("PickedChunk"), EngineDebug->PickedChunk ); */ DoEditorUi(Ui, &WorldChunkWindow, EngineDebug->PickedChunk, CSz("PickedChunk")); } @@ -793,6 +819,7 @@ DoEngineDebug(engine_resources *Engine) DoGraphicsDebugWindow(Engine); + DoWorldEditDebugWindow(Engine); } /* Debug_DrawTextureToDebugQuad(&Engine->RTTGroup.DebugShader); */ @@ -802,3 +829,4 @@ DoEngineDebug(engine_resources *Engine) DoAssetWindow(Engine); } } + diff --git a/src/engine/debug.h b/src/engine/debug.h index dd9fe7072..cd764473b 100644 --- a/src/engine/debug.h +++ b/src/engine/debug.h @@ -1,4 +1,11 @@ +// TODO(Jesse): rename this to just thumbnail and move to renderer? +struct asset_thumbnail +{ + texture *Texture; + camera Camera; +}; + struct render_debug { u32 BytesSolidGeoLastFrame; @@ -9,6 +16,7 @@ struct render_debug struct engine_debug { + memory_arena *Memory; picked_world_chunk_static_buffer PickedChunks; texture_ptr_block_array Textures; @@ -28,6 +36,11 @@ struct engine_debug u64 ModelIndex; entity_id SelectedEntity; + + // World Edit debug + // + untextured_3d_geometry_buffer WorldEditDebugMesh; + asset_thumbnail WorldEditDebugThumb; }; diff --git a/src/engine/editor.cpp b/src/engine/editor.cpp index 7753aacf6..0a7ca04f2 100644 --- a/src/engine/editor.cpp +++ b/src/engine/editor.cpp @@ -559,6 +559,137 @@ DoSelectonModification( engine_resources *Engine, return Result; } +link_internal void +DoSelectedVoxelDebugWindow(engine_resources *Engine, cp VoxelCP) +{ + UNPACK_ENGINE_RESOURCES(Engine); + + voxel *V = TryGetVoxelPointer(World, VoxelCP); + + + v3 SimP = Floor(GetSimSpaceP(World, VoxelCP)); +#if VOXEL_DEBUG_COLOR + if (V) + { + DEBUG_DrawSimSpaceVectorAt(Engine, SimP, Normalize(V->DebugColor)* 40.f, GREEN, 0.25f); + DEBUG_DrawSimSpaceVectorAt(Engine, SimP, Normalize(V->DebugColor)*-40.f, YELLOW, 0.25f); + DEBUG_HighlightVoxel(Engine, SimP, YELLOW, DEFAULT_LINE_THICKNESS*2.f); + } +#endif + + + { + local_persist window_layout Window = WindowLayout("Voxel Debug Window", V2(150.f, 150.f)); + PushWindowStart(Ui, &Window); + + if (V) + { + DoEditorUi(Ui, &Window, &V->Flags, CSz("Voxel Flags")); + PushNewRow(Ui); + + DoEditorUi(Ui, &Window, &VoxelCP, CSz("CP")); + +#if VOXEL_DEBUG_COLOR + DoEditorUi(Ui, &Window, &V->DebugNoiseValue, CSz("Noise Value")); + PushNewRow(Ui); + + DoEditorUi(Ui, &Window, &V->DebugColor, CSz("DebugColor")); + + r32 DotP = Dot(V->DebugColor, V3(0,0,1)); + DoEditorUi(Ui, &Window, &DotP, CSz("Dot against V3(0,0,1)")); + PushNewRow(Ui); + PushNewRow(Ui); + + + world_chunk *ThisChunk = GetWorldChunkFromHashtable(World, VoxelCP.WorldP); + + PushTableStart(Ui); + PushNewRow(Ui); + PushColumn(Ui, CSz("Contributed")); + PushColumn(Ui, CSz(" ")); + PushColumn(Ui, CSz(" ")); + PushColumn(Ui, CSz("Expected")); + PushNewRow(Ui); + + PushColumn(Ui, CSz("To Normal")); + PushColumn(Ui, CSz("Offset")); + PushColumn(Ui, CSz("NoiseValue")); + PushColumn(Ui, CSz("NoiseValue")); + PushColumn(Ui, CSz("")); + PushNewRow(Ui); + v3i Dim = V3i(3,3,3); + for (s32 dz = -1; dz < 2; ++dz) + { + for (s32 dy = -1; dy < 2; ++dy) + { + for (s32 dx = -1; dx < 2; ++dx) + { + /* if (dz == 0 && dy == 0 && dx == 0) continue; // ? */ + + s32 NormalIndex = GetIndex(VoxelCP.Offset+V3(dx,dy,dz)+1, ThisChunk->Dim+2); + s32 NoiseIndex = GetIndex(VoxelCP.Offset+V3(dx,dy,dz)+2, ThisChunk->Dim+4); + v3 ExpectedNormalValue = V3(f32_MAX); + r32 ExpectedNoiseValue = f32_MAX; + if (ThisChunk->NoiseValues) { ExpectedNoiseValue = ThisChunk->NoiseValues[NoiseIndex]; } + if (ThisChunk->NormalValues) { ExpectedNormalValue = ThisChunk->NormalValues[NormalIndex]; } + + voxel *dV = TryGetVoxelPointer(World, Canonicalize(World, VoxelCP + V3(dx,dy,dz))); + + ui_style *Style = &DefaultStyle; + + b32 ValueContributedToNormal = False; + if (dV && dV->DebugNoiseValue-dz > Truncate(V->DebugNoiseValue)) + { + Style = &DefaultSelectedStyle; + ValueContributedToNormal = True; + } + + { + if (ValueContributedToNormal) + { + PushColumn(Ui, CSz("+")); + } + else + { + PushColumn(Ui, CSz(" ")); + } + + PushColumn(Ui, FSz("(%d %d %d)", dx, dy, dz), Style); + if (dV) { PushColumn(Ui, CS(dV->DebugNoiseValue)); } + else { PushColumn(Ui, CSz("(INVALID NOISE INDEX)")); } + + if (dV && ExpectedNoiseValue != dV->DebugNoiseValue) { Style = &Global_DefaultErrorStyle; DEBUG_HighlightVoxel(Engine, SimP+V3(dx,dy,dz), RED); } + else { Style = &DefaultStyle; } + + if (ExpectedNoiseValue < f32_MAX) { PushColumn(Ui, FSz("(%.2f)", r64(ExpectedNoiseValue)), Style); } + else { PushColumn(Ui, FSz("(THIS CHUNK (%p) DID NOT HAVE VALID NOISE VALUE POINTER)", ThisChunk)); } + + if (dV && ExpectedNormalValue != dV->DebugColor) { Style = &Global_DefaultErrorStyle; DEBUG_HighlightVoxel(Engine, SimP+V3(dx,dy,dz), PINK); } + else { Style = &DefaultStyle; } + + if (ExpectedNormalValue.x < f32_MAX) { PushColumn(Ui, FSz("(%.2f,%.2f,%.2f)", r64(ExpectedNormalValue.x), r64(ExpectedNormalValue.y), r64(ExpectedNormalValue.z) ), Style); } + else { PushColumn(Ui, FSz("(THIS CHUNK (%p) DID NOT HAVE VALID NORMAL VALUE POINTER)", ThisChunk)); } + + + PushNewRow(Ui); + } + } + PushNewRow(Ui); + } + PushNewRow(Ui); + } + PushTableEnd(Ui); +#endif + + } + else + { + PushColumn(Ui, CSz("(null)")); + } + PushWindowEnd(Ui, &Window); + } +} + link_internal void DoWorldEditor(engine_resources *Engine) { @@ -994,61 +1125,25 @@ DoWorldEditor(engine_resources *Engine) } } - - // - // Highlight moused over voxel - // - if (Engine->MousedOverVoxel.Tag) +#if VOXEL_DEBUG_COLOR { -#if 0 + cp DebugVoxel = {}; + if (Editor->SelectionClicks > 0) { - v3 SimP = Floor(GetSimSpaceP(Engine->World, &Engine->MousedOverVoxel.Value, HighlightVoxel)); - DEBUG_HighlightVoxel( Engine, SimP, RED, 0.075f); - - voxel *V = GetVoxelPointer(&Engine->MousedOverVoxel.Value, PickedVoxel_FirstFilled); - - - local_persist window_layout Window = WindowLayout("DEBUG DELETE ME", V2(150.f, 150.f)); - PushWindowStart(Ui, &Window); - - v3 Tangent, Bitangent, Normal; - CalculateTBN(V->Derivs, &Tangent, &Bitangent, &Normal); - - /* DEBUG_DrawSimSpaceVectorAt(Engine, SimP+V3(0,0,5), Normalize(Tangent)*20.f, RED, 0.75f); */ - /* DEBUG_DrawSimSpaceVectorAt(Engine, SimP+V3(0,0,5), Normalize(Bitangent)*20.f, GREEN, 0.75f); */ - /* DEBUG_DrawSimSpaceVectorAt(Engine, SimP+V3(0,0,5), Normalize(Normal)*20.f, BLUE, 0.75f); */ - - /* DEBUG_DrawSimSpaceVectorAt(Engine, SimP, Normalize(tangent)*20.f, RED, 0.75f); */ - /* DEBUG_DrawSimSpaceVectorAt(Engine, SimP, Normalize(bitangent)*20.f, GREEN, 0.75f); */ - /* DEBUG_DrawSimSpaceVectorAt(Engine, SimP, Normalize(normal)*20.f, BLUE, 0.75f); */ - - - DEBUG_DrawSimSpaceVectorAt(Engine, SimP, Normalize(V->DebugColor)* 40.f, GREEN, 0.75f); - DEBUG_DrawSimSpaceVectorAt(Engine, SimP, Normalize(V->DebugColor)*-40.f, YELLOW, 0.75f); - /* DEBUG_DrawSimSpaceVectorAt(Engine, SimP, Normalize(V->Derivs)*-20.f, YELLOW, 0.75f); */ - - DoEditorUi(Ui, &V->Derivs, "derivs"); - DoEditorUi(Ui, &V->DebugColor, "DebugColor"); - - r32 DotP = Dot(V->DebugColor, V3(0,0,1)); - DoEditorUi(Ui, &DotP, "Dot"); - - v3 AbsP = GetAbsoluteP(&Engine->MousedOverVoxel.Value); - DoEditorUi(Ui, &AbsP, "AbsP"); - - PushWindowEnd(Ui, &Window); - + DebugVoxel = Editor->SelectionRegion.Min; } -#else + else if (Engine->MousedOverVoxel.Tag) { - v3 SimP = Floor(GetSimSpaceP(Engine->World, &Engine->MousedOverVoxel.Value, PickedVoxel_FirstFilled)); - DEBUG_HighlightVoxel( Engine, SimP, RED, 0.075f); + DebugVoxel = Canonical_Position(&Engine->MousedOverVoxel.Value, PickedVoxel_FirstFilled); } - /* { */ - /* v3 SimP = Floor(GetSimSpaceP(Engine->World, &Engine->MousedOverVoxel.Value, PickedVoxel_LastEmpty)); */ - /* DebugLine("%f %f %f", SimP.x, SimP.y, SimP.z); */ - /* DEBUG_HighlightVoxel( Engine, SimP, BLUE, 0.075f); */ - /* } */ + + DoSelectedVoxelDebugWindow(Engine, DebugVoxel); + } #endif + + if (Engine->MousedOverVoxel.Tag) + { + v3 SimP = Floor(GetSimSpaceP(Engine->World, &Engine->MousedOverVoxel.Value, PickedVoxel_FirstFilled)); + DEBUG_HighlightVoxel( Engine, SimP, RED, 0.075f); } } diff --git a/src/engine/editor.h b/src/engine/editor.h index 73a210d6d..0f9ffcd0b 100644 --- a/src/engine/editor.h +++ b/src/engine/editor.h @@ -235,12 +235,6 @@ poof( /* link_internal void */ /* DoEditorUi(renderer_2d *Ui, v3i *Element, cs Name, EDITOR_UI_FUNCTION_PROTO_ARGUMENTS); */ -struct asset_thumbnail -{ - texture *Texture; - camera Camera; -}; - poof(block_array_h(asset_thumbnail, {8}, {})) #include diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 048c31f37..45fb4c2d0 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -22,6 +22,7 @@ #include #include #include // TODO(Jesse): Probably time to split this up? +#include #include #include diff --git a/src/engine/entity_id.h b/src/engine/entity_id.h index b3f21e391..67645a3bb 100644 --- a/src/engine/entity_id.h +++ b/src/engine/entity_id.h @@ -2,12 +2,6 @@ struct entity_id { u32 Index; u32 Generation; - - operator bool() - { - b32 Result = (this->Generation != 0); - return Result; - } }; link_internal b32 diff --git a/src/engine/game_effects.cpp b/src/engine/game_effects.cpp index 7385b7e54..7046eaf8a 100644 --- a/src/engine/game_effects.cpp +++ b/src/engine/game_effects.cpp @@ -21,12 +21,12 @@ SpawnFire(entity *Entity, random_series *Entropy, v3 Offset, r32 Dim, b32 Colorf if (Colorful) { - System->Colors[0] = (u8)Clamp(0, RandomU32(Entropy), 254); - System->Colors[1] = (u8)Clamp(0, RandomU32(Entropy), 254); - System->Colors[2] = (u8)Clamp(0, RandomU32(Entropy), 254); - System->Colors[3] = (u8)Clamp(0, RandomU32(Entropy), 254); - System->Colors[4] = (u8)Clamp(0, RandomU32(Entropy), 254); - System->Colors[5] = (u8)Clamp(0, RandomU32(Entropy), 254); + System->Colors[0] = (u8)Clamp(0u, RandomU32(Entropy), 254u); + System->Colors[1] = (u8)Clamp(0u, RandomU32(Entropy), 254u); + System->Colors[2] = (u8)Clamp(0u, RandomU32(Entropy), 254u); + System->Colors[3] = (u8)Clamp(0u, RandomU32(Entropy), 254u); + System->Colors[4] = (u8)Clamp(0u, RandomU32(Entropy), 254u); + System->Colors[5] = (u8)Clamp(0u, RandomU32(Entropy), 254u); } else { diff --git a/src/engine/graphics.h b/src/engine/graphics.h index 2291251fe..cb6be5705 100644 --- a/src/engine/graphics.h +++ b/src/engine/graphics.h @@ -32,7 +32,31 @@ struct bloom_render_group shader Shader; }; -struct lighting_settings +struct lighting_settings poof(@version(1)) +{ + b8 AutoDayNightCycle; + + r32 tDay; poof(@ui_value_range(-PI32, PI32)) + + v3 SunP; poof(@ui_value_range(-1.f, 1.f)) + + f32 DawnIntensity; poof(@ui_value_range(0.f, 3.f)) + v3 DawnColor; + + f32 SunIntensity; poof(@ui_value_range(0.f, 3.f)) + v3 SunColor; + + f32 DuskIntensity; poof(@ui_value_range(0.f, 3.f)) + v3 DuskColor; + + f32 MoonIntensity; poof(@ui_value_range(0.f, 3.f)) + v3 MoonColor; + + // Computed from the above parameters and passed to the shader + v3 CurrentSunColor; +}; + +struct lighting_settings_0 { b8 AutoDayNightCycle; diff --git a/src/engine/mesh.h b/src/engine/mesh.h index dd401a308..cd7dc9c4a 100644 --- a/src/engine/mesh.h +++ b/src/engine/mesh.h @@ -21,8 +21,8 @@ struct mesh_freelist volatile free_mesh* Containers; }; -#define TIERED_MESH_FREELIST_MAX_ELEMENTS (32) -#define WORLD_CHUNK_MESH_MIN_SIZE (1024) +#define TIERED_MESH_FREELIST_MAX_ELEMENTS (64) +#define WORLD_CHUNK_MESH_MIN_SIZE (2048) #define ELEMENTS_PER_TEMP_MESH (WORLD_CHUNK_MESH_MIN_SIZE*TIERED_MESH_FREELIST_MAX_ELEMENTS) poof( staticbuffer(mesh_freelist, {TIERED_MESH_FREELIST_MAX_ELEMENTS}, {tiered_mesh_freelist}) ) @@ -94,6 +94,28 @@ BufferVertsDirect( } #endif +inline void +BufferFaceData( + untextured_3d_geometry_buffer *Dest, + v3 *Positions, v3 *Normals, vertex_material *Mats + ) +{ + if (BufferHasRoomFor(Dest, 6)) + { + MemCopy((u8*)Positions, (u8*)&Dest->Verts[Dest->At], sizeof(*Positions)*6 ); + MemCopy((u8*)Normals, (u8*)&Dest->Normals[Dest->At], sizeof(*Normals)*6 ); + MemCopy((u8*)Mats, (u8*)&Dest->Mat[Dest->At], sizeof(*Mats)*6 ); + /* MemCopy((u8*)TransEmiss, (u8*)&Dest->TransEmiss[Dest->At], sizeof(*TransEmiss)*NumVerts ); */ + + Dest->At += 6; + } + else + { + MarkBufferForGrowth(Dest, 6); + SoftError("Ran out of memory pushing %d Verts onto Mesh with %d/%d used", 6, Dest->At, Dest->End -1); + } +} + inline void BufferVertsDirect( untextured_3d_geometry_buffer *Dest, diff --git a/src/engine/resources.cpp b/src/engine/resources.cpp new file mode 100644 index 000000000..066006d6d --- /dev/null +++ b/src/engine/resources.cpp @@ -0,0 +1,61 @@ + +link_internal b32 +InitEngineResources(engine_resources *Engine) +{ + b32 Result = True; + + platform *Plat = &Engine->Stdlib.Plat; + + memory_arena *BonsaiInitArena = AllocateArena(Megabytes(256));; + DEBUG_REGISTER_ARENA(BonsaiInitArena, 0); + + Engine->Memory = BonsaiInitArena; + Engine->Heap = InitHeap(Gigabytes(2)); // TODO(Jesse): Is this actually used? + + Engine->AssetMemory = InitHeap(Gigabytes(1)); + + Init_Global_QuadVertexBuffer(); + + Engine->World = Allocate(world, BonsaiInitArena, 1); + if (!Engine->World) { Error("Allocating World"); Result = False; } + + Engine->Graphics = GraphicsInit(AllocateArena()); + if (!Engine->Graphics) { Error("Initializing Graphics"); Result = False; } + + { + memory_arena *UiMemory = AllocateArena(); + InitRenderer2D(&Engine->Ui, &Engine->Heap, UiMemory, &Plat->MouseP, &Plat->MouseDP, &Plat->ScreenDim, &Plat->Input); + /* Engine->UiSpriteTexture = LoadBitmap("assets/mystic_rpg_icon_pack/Sprites/300%/Tool_6.bmp", UiMemory); */ + /* Engine->UiSpriteTexture = LoadBitmap("assets/mystic_rpg_icon_pack/Sprites/300%/Tool_13.bmp", UiMemory); */ + + bitmap_block_array Bitmaps = {}; + LoadBitmapsFromFolder(CSz("assets/mystic_rpg_icon_pack/Sprites/300%/64x64_sprites"), &Bitmaps); + LoadBitmapsFromFolder(CSz("assets/mystic_rpg_icon_pack/Sprites/300%/44x44_sprites"), &Bitmaps); + Engine->Ui.SpriteTextureArray = CreateTextureArrayFromBitmapArray(&Bitmaps, V2i(64,64), UiMemory); + + /* Engine->UiSpriteTexture = LoadBitmap("assets/mystic_rpg_icon_pack/Sprites/300%/Tool_20.bmp", UiMemory); */ + /* Engine->UiSpriteTexture = LoadBitmap("assets/mystic_rpg_icon_pack/Sprites/300%/Inventory_0.bmp", UiMemory); */ + /* Engine->UiSpriteTexture = LoadBitmap("assets/test.bmp", UiMemory); */ + /* Engine->UiSpriteTexture = LoadBitmap("assets/test_1.bmp", UiMemory); */ + /* Engine->UiSpriteTexture = LoadBitmap("assets/test_2.bmp", UiMemory); */ + } + + Engine->EntityTable = AllocateEntityTable(BonsaiInitArena, TOTAL_ENTITY_COUNT); + return Result; +} + +link_internal b32 +InitEngineDebug(engine_debug *Debug) +{ + b32 Result = True; + + Debug->Memory = AllocateArena(); + + { + Debug->WorldEditDebugThumb.Texture = MakeTexture_RGB(V2i(1024,1024), 0, Debug->Memory, CSz("WorldEditDebugTexture")); + StandardCamera(&Debug->WorldEditDebugThumb.Camera, 10000.f, 1000.f, 30.f, {}); + AllocateMesh(&Debug->WorldEditDebugMesh, u32(Kilobytes(64*16)), Debug->Memory); + } + + return Result; +} diff --git a/src/engine/serdes.cpp b/src/engine/serdes.cpp index 2fca1f5ec..a02efea93 100644 --- a/src/engine/serdes.cpp +++ b/src/engine/serdes.cpp @@ -356,6 +356,15 @@ Marshal(entity_1 *E0, entity_2 *E1) } #endif +link_internal void +Marshal(lighting_settings_0 *E0, lighting_settings *E1) +{ + NotImplemented; +} + +poof(serdes_struct(lighting_settings_0)) +#include + poof(serdes_struct(lighting_settings)) #include diff --git a/src/engine/terrain.cpp b/src/engine/terrain.cpp index 4fdb34879..c3f8188ce 100644 --- a/src/engine/terrain.cpp +++ b/src/engine/terrain.cpp @@ -1,11 +1,10 @@ link_internal void -GrowGrass( world_chunk *Chunk, v3i P, r32 NoiseValue, r32 MaskValue, v3i SrcToDest, v3i WorldChunkDim, r32 WorldZSubZMin, u16 *ThisColor, b32 *IsFilled ) +GrowGrassPerlin( world_chunk *Chunk, v3i P, r32 NoiseValue, r32 MaskValue, v3i SrcToDest, v3i WorldChunkDim, r32 WorldZSubZMin, u16 *ThisColor, b32 *IsFilled ) { s32 x = P.x; s32 y = P.y; s32 z = P.z; - // NOTE(Jesse): This is pretty henious .. the math to compute GrassAreaX here // (and, actually, maybe most of these calculations to turn positions into floats) // is generating a fucked up index for the voxels along the exterior edge. @@ -23,12 +22,16 @@ GrowGrass( world_chunk *Chunk, v3i P, r32 NoiseValue, r32 MaskValue, v3i SrcToDe f32 GrassAreaX = (x + SrcToDest.x + (WorldChunkDim.x*Chunk->WorldP.x)) / 16.f; f32 GrassAreaY = (y + SrcToDest.y + (WorldChunkDim.y*Chunk->WorldP.y)) / 16.f; + /* f32 GrassAreaX = (x + SrcToDest.x + (WorldChunkDim.x*Chunk->WorldP.x)); */ + /* f32 GrassAreaY = (y + SrcToDest.y + (WorldChunkDim.y*Chunk->WorldP.y)); */ // TODO(Jesse): Does this actually help reduce stuff 'growing' in places // it shouldn't? - f32 GrassAreaZ = 1.f; //(z + SrcToDest.z + (WorldChunkDim.z*Chunk->WorldP.z)) / 32.f; + /* f32 GrassAreaZ = 1.f; //(z + SrcToDest.z + (WorldChunkDim.z*Chunk->WorldP.z)) / 32.f; */ + f32 GrassAreaZ = (z + SrcToDest.z + (WorldChunkDim.z*Chunk->WorldP.z)) / 32.f; - r32 GrassyAreaValue = PerlinNoise(GrassAreaX, GrassAreaY, GrassAreaZ); + r32 GrassyAreaValue = MaskValue * PerlinNoise(GrassAreaX, GrassAreaY, GrassAreaZ); + /* r32 GrassyAreaValue = MaskValue * (VoronoiNoise3D(V3(GrassAreaX, GrassAreaY, GrassAreaZ)/5.f)*2.f); */ if (*ThisColor == GRASS_GREEN) { if (GrassyAreaValue > 0.4f) @@ -37,10 +40,10 @@ GrowGrass( world_chunk *Chunk, v3i P, r32 NoiseValue, r32 MaskValue, v3i SrcToDe if (GrassyAreaValue > 0.6f) { - if ((NoiseValue+(MaskValue*GrassyAreaValue*3.f)) > WorldZSubZMin) + if ((NoiseValue+(GrassyAreaValue*3.f)) > WorldZSubZMin) { - f32 HashX = hash_f32(f32(x)); - f32 HashY = hash_f32(f32(y)); + f32 HashX = hash_f32(GrassAreaX); + f32 HashY = hash_f32(GrassAreaY); s32 iHashX = *(s32*)&HashX; s32 iHashY = *(s32*)&HashY; @@ -59,13 +62,13 @@ GrowGrass( world_chunk *Chunk, v3i P, r32 NoiseValue, r32 MaskValue, v3i SrcToDe if (GrassColor > 0.88f) *ThisColor = LONG_GREEN_GRASS1; - if (GrassColor > 0.98f) + if (GrassColor > 0.993f) *ThisColor = LONG_YELLOW_GRASS0; - if (GrassColor > 0.99f) + if (GrassColor > 0.995f) *ThisColor = LONG_YELLOW_GRASS1; - if (GrassColor > 0.999f) + if (GrassColor > 0.998f) *ThisColor = PINK; } } @@ -74,21 +77,321 @@ GrowGrass( world_chunk *Chunk, v3i P, r32 NoiseValue, r32 MaskValue, v3i SrcToDe } } +link_internal void +GrowGrassPerlin_8x( world_chunk *Chunk, v3i P, r32 *NoiseValue, v3 *Normal, r32 MaskValue, v3i SrcToDest, v3i WorldChunkDim, r32 WorldZSubZMin, u16 *ThisColor ) +{ + RangeIterator(Index, 8) + { + s32 x = P.x + Index; + s32 y = P.y; + s32 z = P.z; + + // NOTE(Jesse): This is pretty henious .. the math to compute GrassAreaX here + // (and, actually, maybe most of these calculations to turn positions into floats) + // is generating a fucked up index for the voxels along the exterior edge. + // + // The thing that's wrong is that the 0th still gets the Chunk->WorldP position, + // when it should get the previous chunks worldp. Similar story with the max-edge + // + // I think this was actually also manifesting when doing mip-meshing, but I + // wasn't aware of this tom-fuckery then, and didn't catch it. + // + // TODO(Jesse): Should go audit the terrain-gen functions and find a better + // way of computing these float values. + // + if (x == 0 || y == 0 || x == Chunk->Dim.x-1 || y == Chunk->Dim.y-1) { return; } + + f32 GrassAreaX = (x + SrcToDest.x + (WorldChunkDim.x*Chunk->WorldP.x)) / 16.f; + f32 GrassAreaY = (y + SrcToDest.y + (WorldChunkDim.y*Chunk->WorldP.y)) / 16.f; + /* f32 GrassAreaX = (x + SrcToDest.x + (WorldChunkDim.x*Chunk->WorldP.x)); */ + /* f32 GrassAreaY = (y + SrcToDest.y + (WorldChunkDim.y*Chunk->WorldP.y)); */ + + // TODO(Jesse): Does this actually help reduce stuff 'growing' in places + // it shouldn't? + /* f32 GrassAreaZ = 1.f; //(z + SrcToDest.z + (WorldChunkDim.z*Chunk->WorldP.z)) / 32.f; */ + f32 GrassAreaZ = (z + SrcToDest.z + (WorldChunkDim.z*Chunk->WorldP.z)) / 32.f; + + r32 GrassyAreaValue = MaskValue * PerlinNoise(GrassAreaX, GrassAreaY, GrassAreaZ); + /* r32 GrassyAreaValue = MaskValue * (VoronoiNoise3D(V3(GrassAreaX, GrassAreaY, GrassAreaZ)/5.f)*2.f); */ + if (ThisColor[Index] == GRASS_GREEN) + { + if (GrassyAreaValue > 0.4f) + { + ThisColor[Index] = GRASS_GREEN-1; + + if (GrassyAreaValue > 0.6f) + { + if ((NoiseValue[Index]+(GrassyAreaValue*3.f)) > WorldZSubZMin) + { + f32 HashX = hash_f32(GrassAreaX); + f32 HashY = hash_f32(GrassAreaY); + + s32 iHashX = *(s32*)&HashX; + s32 iHashY = *(s32*)&HashY; + + random_series S0 { u64(x + y) | u64( (iHashX | (iHashY << 31)) ^ (iHashY << 16)) }; + random_series S1 { RandomU32(&S0) | RandomU32(&S0)<<31 }; + + if (RandomUnilateral(&S1) > 0.92f) + { + NoiseValue[Index] += 1.f; + + r32 GrassColor = RandomUnilateral(&S1); + if (GrassColor > 0.8f) + ThisColor[Index] = LONG_GREEN_GRASS0; + + if (GrassColor > 0.88f) + ThisColor[Index] = LONG_GREEN_GRASS1; + + if (GrassColor > 0.993f) + ThisColor[Index] = LONG_YELLOW_GRASS0; + + if (GrassColor > 0.995f) + ThisColor[Index] = LONG_YELLOW_GRASS1; + + if (GrassColor > 0.998f) + ThisColor[Index] = PINK; + } + } + } + } + } + } +} + +link_internal void +RandomVoronoiRocks_8x( world_chunk *Chunk, v3i P, r32 *NoiseValue, v3 *Normals, v3i SrcToDest, v3i WorldChunkDim, r32 WorldZSubZMin, u16 *ThisColor ) +{ + /* s32 GrassMaskCount = 0; */ + r32 GrassMasks[8]; + r32 _xGrassMapped[8]; + RangeIterator(Index, 8) + { + r32 DotNormal = Dot(Normals[Index], V3(0,0,1)); + r32 Thresh = 0.85f; + r32 ClampedDotNormal = Clamp(Thresh, DotNormal, 1.f); + GrassMasks[Index] = 1.f;// MapValueToUnilateral(Thresh, ClampedDotNormal, 1.f); + /* if (GrassMasks[Index] > 0.f) ++GrassMaskCount; */ + + _xGrassMapped[Index] = (Index + P.x + SrcToDest.x + (WorldChunkDim.x*Chunk->WorldP.x)) / 64.f; + } + + /* if (GrassMaskCount == 0) return; */ + + f32 yMapped = (P.y + SrcToDest.y + (WorldChunkDim.y*Chunk->WorldP.y)) / 64.f; + f32 zMapped = (P.z + SrcToDest.z + (WorldChunkDim.z*Chunk->WorldP.z)) / 64.f; + + f32 VoronoiResults[8]; + VoronoiNoise3D_8x(VoronoiResults, _xGrassMapped, V2(yMapped, zMapped), 0.f, 0.1f); + + RangeIterator(Index, 8) + { + r32 GrassMask = GrassMasks[Index]; + + if (GrassMask > 0.f) + { + /* f32 GrassAreaPower = 6.f; */ + f32 GrassAreaPower = 1.f; + r32 MaskedVoronoi = GrassAreaPower * GrassMask * VoronoiResults[Index]; + if (ThisColor[Index] == GRASS_GREEN) + { + /* NoiseValue[Index] += 5.f; */ + if (MaskedVoronoi > 0.1f) + { + /* ThisColor[Index] = RED; */ + + if (MaskedVoronoi > 0.2f) + { + f32 GrassHeightPower = 50.f; + if ((NoiseValue[Index]+(MaskedVoronoi*GrassHeightPower)) > WorldZSubZMin) + { + ThisColor[Index] = STONE; + /* NoiseValue[Index] = WorldZSubZMin + 10.f; */ + NoiseValue[Index] += 10.f; + } + } + } + } + } + } +} +link_internal void +GrowGrassVoronoi( world_chunk *Chunk, v3i P, r32 *NoiseValue, v3 *Normals, v3i SrcToDest, v3i WorldChunkDim, r32 WorldZSubZMin, u16 *ThisColor ) +{ + s32 GrassMaskCount = 0; + + r32 GrassMasks[8]; + r32 _xGrassMapped[8]; + s32 Index= 0; + /* RangeIterator(Index, 8) */ + { + r32 DotNormal = Dot(Normals[Index], V3(0,0,1)); + r32 Thresh = 0.85f; + r32 ClampedDotNormal = Clamp(Thresh, DotNormal, 1.f); + GrassMasks[Index] = MapValueToUnilateral(Thresh, ClampedDotNormal, 1.f); + if (GrassMasks[Index] > 0.f) ++GrassMaskCount; + + _xGrassMapped[Index] = (Index + P.x + SrcToDest.x + (WorldChunkDim.x*Chunk->WorldP.x)) / 16.f; + } + + if (GrassMaskCount == 0) return; + + f32 yMapped = (P.y + SrcToDest.y + (WorldChunkDim.y*Chunk->WorldP.y)) / 16.f; + f32 zMapped = (P.z + SrcToDest.z + (WorldChunkDim.z*Chunk->WorldP.z)) / 32.f; + + f32 VoronoiResults[8]; + VoronoiNoise3D_8x_Masked(VoronoiResults, -0.2f, GrassMasks, _xGrassMapped, V2(yMapped, zMapped)); + + /* RangeIterator(Index, 8) */ + { + r32 GrassMask = GrassMasks[Index]; + + /* v3i Basis = V3i(P.x + Index + SrcToDest.x, P.y + SrcToDest.y, 0); */ + v3 Offset = V3(P) + SrcToDest + V3(Index,0,0); + Offset.z = 0; + v3i Basis = V3i(Canonical_Position(GetWorld()->ChunkDim, Offset, V3i(0)).Offset); + random_series Entropy = RandomSeriesFromV3i(Basis); + + r32 MaskedVoronoi = GrassMask * VoronoiResults[Index]; + if (ThisColor[Index] == GRASS_GREEN) + { + /* NoiseValue[Index] += 5.f; */ + if (MaskedVoronoi > 0.1f) + { + /* ThisColor[Index] = RED; */ + + if (MaskedVoronoi > 0.2f) + { + f32 GrassHeightPower = 50.f; + if ((NoiseValue[Index]+(MaskedVoronoi*GrassHeightPower)) > WorldZSubZMin) + { + if (RandomUnilateral(&Entropy) > 0.7f) + { + ThisColor[Index] = GRASS_GREEN-1; + if (MaskedVoronoi+RandomUnilateral(&Entropy) > 0.8f) + { + NoiseValue[Index] += MaskedVoronoi * 10.f; + + r32 GrassColor = RandomUnilateral(&Entropy); + if (GrassColor > 0.8f) + ThisColor[Index] = LONG_GREEN_GRASS0; + + if (GrassColor > 0.88f) + ThisColor[Index] = LONG_GREEN_GRASS1; + + if (GrassColor > 0.993f) + ThisColor[Index] = LONG_YELLOW_GRASS0; + + if (GrassColor > 0.995f) + ThisColor[Index] = LONG_YELLOW_GRASS1; + + if (GrassColor > 0.998f) + ThisColor[Index] = PINK; + } + } + } + } + } + } + } +} +link_internal void +GrowGrassVoronoi_8x( world_chunk *Chunk, v3i P, r32 *NoiseValue, v3 *Normals, v3i SrcToDest, v3i WorldChunkDim, r32 WorldZSubZMin, u16 *ThisColor ) +{ + s32 GrassMaskCount = 0; + + r32 GrassMasks[8]; + r32 _xGrassMapped[8]; + RangeIterator(Index, 8) + { + r32 DotNormal = Dot(Normals[Index], V3(0,0,1)); + r32 Thresh = 0.85f; + r32 ClampedDotNormal = Clamp(Thresh, DotNormal, 1.f); + GrassMasks[Index] = MapValueToUnilateral(Thresh, ClampedDotNormal, 1.f); + if (GrassMasks[Index] > 0.f) ++GrassMaskCount; + + _xGrassMapped[Index] = (Index + P.x + SrcToDest.x + (WorldChunkDim.x*Chunk->WorldP.x)) / 16.f; + } + + if (GrassMaskCount == 0) return; + + f32 yMapped = (P.y + SrcToDest.y + (WorldChunkDim.y*Chunk->WorldP.y)) / 16.f; + f32 zMapped = (P.z + SrcToDest.z + (WorldChunkDim.z*Chunk->WorldP.z)) / 32.f; + + f32 VoronoiResults[8]; + VoronoiNoise3D_8x_Masked(VoronoiResults, -0.2f, GrassMasks, _xGrassMapped, V2(yMapped, zMapped)); + + RangeIterator(Index, 8) + { + r32 GrassMask = GrassMasks[Index]; + + /* v3 Basis = V3(f32(P.x + Index + SrcToDest.x), f32(P.y + SrcToDest.y), 0.f); */ + /* v3i Basis = V3i(-1+P.x + Index + SrcToDest.x, P.y + SrcToDest.y, 0); */ + v3 Offset = V3(P) + SrcToDest + V3(Index,0,0); + Offset.z = 0; + v3i Basis = V3i(Canonical_Position(GetWorld()->ChunkDim, Offset, V3i(0)).Offset); + /* v3i Basis = V3i(P.x + Index , P.y , 0); */ + random_series Entropy = RandomSeriesFromV3i(Basis); + + r32 MaskedVoronoi = GrassMask * VoronoiResults[Index]; + if (ThisColor[Index] == GRASS_GREEN) + { + /* NoiseValue[Index] += 5.f; */ + if (MaskedVoronoi > 0.1f) + { + /* ThisColor[Index] = RED; */ + + if (MaskedVoronoi > 0.2f) + { + f32 GrassHeightPower = 50.f; + if ((NoiseValue[Index]+(MaskedVoronoi*GrassHeightPower)) > WorldZSubZMin) + { + if (RandomUnilateral(&Entropy) > 0.7f) + { + ThisColor[Index] = GRASS_GREEN-1; + if (MaskedVoronoi+RandomUnilateral(&Entropy) > 0.8f) + { + NoiseValue[Index] += MaskedVoronoi * 10.f; + + r32 GrassColor = RandomUnilateral(&Entropy); + if (GrassColor > 0.8f) + ThisColor[Index] = LONG_GREEN_GRASS0; + + if (GrassColor > 0.88f) + ThisColor[Index] = LONG_GREEN_GRASS1; + + if (GrassColor > 0.993f) + ThisColor[Index] = LONG_YELLOW_GRASS0; + + if (GrassColor > 0.995f) + ThisColor[Index] = LONG_YELLOW_GRASS1; + + if (GrassColor > 0.998f) + ThisColor[Index] = PINK; + } + } + } + } + } + } + } +} + link_internal void -ComputeNormalsForChunk(world_chunk *Chunk, v3i Dim) +ComputeNormalsForChunkFromFilledFlag(world_chunk *Chunk, v3i WorldChunkDim, v3 *Normals) { TIMED_FUNCTION(); - NotImplemented; -#if 0 - for ( s32 z = 0; z < Dim.z; ++ z) + v3i ChunkDim = Chunk->Dim; + + for ( s32 z = 0; z < ChunkDim.z; ++ z) { - for ( s32 y = 0; y < Dim.y; ++ y) + for ( s32 y = 0; y < ChunkDim.y; ++ y) { - for ( s32 x = 0; x < Dim.x; ++ x) + for ( s32 x = 0; x < ChunkDim.x; ++ x) { - s32 VoxIndex = GetIndex(Voxel_Position(x,y,z), Dim); + s32 VoxIndex = GetIndex(V3i(x,y,z), ChunkDim); if ( Chunk->Voxels[VoxIndex].Flags & Voxel_Filled ) { @@ -101,35 +404,38 @@ ComputeNormalsForChunk(world_chunk *Chunk, v3i Dim) { if (dz == 0 && dy == 0 && dx == 0) continue; // Skip the middle-most voxel - s32 dP = TryGetIndex(Voxel_Position(x+dx,y+dy,z+dz), Dim); + s32 dP = TryGetIndex(V3i(x+dx,y+dy,z+dz), ChunkDim); if (dP > -1) { if ( Chunk->Voxels[dP].Flags & Voxel_Filled ) { - /* Normal += Normalize(V3(dx,dy,dz)); */ Normal += V3(dx,dy,dz); } } } } } - Chunk->Voxels[VoxIndex].DebugColor = Normalize(Normal); + + Normals[VoxIndex] = Normalize(Normal) * -1.f; // Invert because we tally'd up all filled voxels } } } } - for ( s32 z = 0; z < Dim.z; ++ z) +#if 0 + // TODO(Jesse): Parameterize this iteratin in terms of the min offset in case + // we change it + for ( s32 z = 1; z < WorldChunkDim.z+1; ++ z) { - for ( s32 y = 0; y < Dim.y; ++ y) + for ( s32 y = 1; y < WorldChunkDim.y+1; ++ y) { - for ( s32 x = 0; x < Dim.x; ++ x) + for ( s32 x = 1; x < WorldChunkDim.x+1; ++ x) { - s32 VoxIndex = GetIndex(Voxel_Position(x,y,z), Dim); + s32 VoxIndex = GetIndex(V3i(x,y,z), ChunkDim); if ( Chunk->Voxels[VoxIndex].Flags & Voxel_Filled ) { - v3 Normal = Chunk->Voxels[VoxIndex].DebugColor; + v3 Normal = Normals[VoxIndex]; for ( s32 dz = -1; dz < 2; ++ dz) { for ( s32 dy = -1; dy < 2; ++ dy) @@ -138,23 +444,171 @@ ComputeNormalsForChunk(world_chunk *Chunk, v3i Dim) { if (dz == 0 && dy == 0 && dx == 0) continue; // Skip the middle-most voxel - s32 dP = TryGetIndex(Voxel_Position(x+dx,y+dy,z+dz), Dim); - if (dP > -1) + s32 dP = GetIndex(V3i(x+dx,y+dy,z+dz), ChunkDim); + Normal += 0.05f*Normals[dP]; + } + } + } + Normals[VoxIndex] = Normalize(Normal); + } + + } + } + } +#endif + +} + +#if 1 +link_internal void +ComputeNormalsForChunkFromNoiseValues_Opt(v3i Dim, r32 ChunkWorldZ, r32 *NoiseValues, v3 *Normals) +{ + TIMED_FUNCTION(); + /* HISTOGRAM_FUNCTION(); */ + + s32 MaxIndex = Volume(Dim); + s32 StartingIndex = 1 + Dim.x + (Dim.x*Dim.y); + + s32 VoxIndex = StartingIndex; + for ( s32 z = 1; z < Dim.z-1; ++ z) + { + for ( s32 y = 1; y < Dim.y-1; ++ y) + { + for ( s32 x = 1; x < Dim.x-1; ++ x) + { + r32 CurrentNoiseValue = NoiseValues[VoxIndex]; + /* s32 TestVoxIndex = GetIndex(V3i(x,y,z), Dim); */ + /* Assert(VoxIndex == TestVoxIndex); */ + + v3 Normal = {}; + s32 dPIndex = VoxIndex-StartingIndex; + for ( s32 dz = -1; dz < 2; ++ dz) + { + for ( s32 dy = -1; dy < 2; ++ dy) + { + for ( s32 dx = -1; dx < 2; ++ dx) + { + if (dz == 0 && dy == 0 && dx == 0) + { + dPIndex += 1; + continue; // Skip the middle-most voxel + } + + /* s32 TestdPIndex = GetIndex(V3i(x+dx,y+dy,z+dz), Dim); */ + /* Assert(dPIndex == TestdPIndex); */ + /* if (dPIndex > -1) */ + { + /* Assert(dPIndex < MaxIndex); */ + r32 Diff = NoiseValues[dPIndex]-dz - Truncate(CurrentNoiseValue); + if ( Diff > 0.f ) + { + // TODO(Jesse): Recompute with a small random variance to the weight if this is 0? + Normal += V3(dx,dy,dz)*Diff; + } + } + dPIndex += 1; + } + dPIndex += Dim.x-3; // Skip to the next row + } + dPIndex += (Dim.x*Dim.y)-(3*Dim.x); // Skip to the next plate + } + + /* Assert(VoxIndex < MaxIndex); */ + Normals[VoxIndex] = Normalize(Normal) * -1.f; + + VoxIndex += 1; + } + + VoxIndex += 2; // Skip the last one in the row, and the first one in the next + } + + VoxIndex += (2*Dim.y); // Skip the last row, and the next + } +} +#endif + +link_internal void +ComputeNormalsForChunkFromNoiseValues( r32 ChunkWorldZ, r32 *NoiseValues, v3i NoiseDim, v3 *Normals, v3i NormalsDim) +{ + TIMED_FUNCTION(); + +#if 1 + for ( s32 z = 0; z < NormalsDim.z; ++ z) + { + for ( s32 y = 0; y < NormalsDim.y; ++ y) + { + for ( s32 x = 0; x < NormalsDim.x; ++ x) + { + s32 NoiseIndex = GetIndex(V3i(x,y,z)+1, NoiseDim); + r32 CurrentNoiseValue = NoiseValues[NoiseIndex]; + + v3 Normal = {}; + for ( s32 dz = -1; dz < 2; ++ dz) + { + for ( s32 dy = -1; dy < 2; ++ dy) + { + for ( s32 dx = -1; dx < 2; ++ dx) + { + if (dz == 0 && dy == 0 && dx == 0) continue; // Skip the middle-most voxel + + s32 dNoiseIndex = GetIndex(V3i(x+dx,y+dy,z+dz)+1, NoiseDim); + { + r32 Diff = NoiseValues[dNoiseIndex]-dz - Truncate(CurrentNoiseValue); + if ( Diff > 0.f ) { - Normal += 0.05f*Chunk->Voxels[dP].DebugColor; + // TODO(Jesse): Recompute with a small random variance to the weight if this is 0? + Normal += V3(dx,dy,dz)*Diff; } } } } - Chunk->Voxels[VoxIndex].DebugColor = Normalize(Normal); } + s32 NormalIndex = GetIndex(V3i(x,y,z), NormalsDim); + Normals[NormalIndex] = Normalize(Normal) * -1.f; + } + } + } +#else + for ( s32 z = 1; z < NoiseDim.z-1; ++ z) + { + for ( s32 y = 1; y < NoiseDim.y-1; ++ y) + { + for ( s32 x = 1; x < NoiseDim.x-1; ++ x) + { + s32 NormalIndex = GetIndex(V3i(x,y,z)-1, NormalsDim); + s32 NoiseIndex = GetIndex(V3i(x,y,z), NoiseDim); + r32 CurrentNoiseValue = NoiseValues[NoiseIndex]; + + v3 Normal = {}; + for ( s32 dz = -1; dz < 2; ++ dz) + { + for ( s32 dy = -1; dy < 2; ++ dy) + { + for ( s32 dx = -1; dx < 2; ++ dx) + { + if (dz == 0 && dy == 0 && dx == 0) continue; // Skip the middle-most voxel + + s32 dPIndex = GetIndex(V3i(x+dx,y+dy,z+dz), NoiseDim); + { + r32 Diff = NoiseValues[dPIndex]-dz - Truncate(CurrentNoiseValue); + if ( Diff > 0.f ) + { + // TODO(Jesse): Recompute with a small random variance to the weight if this is 0? + Normal += V3(dx,dy,dz)*Diff; + } + } + } + } + } + Normals[NormalIndex] = Normalize(Normal) * -1.f; } } } #endif } + link_internal u32 HoodooTerrain( perlin_noise *Noise, world_chunk *Chunk, @@ -188,7 +642,7 @@ HoodooTerrain( perlin_noise *Noise, { s64 WorldX = x + SrcToDest.x + (WorldChunkDim.x*Chunk->WorldP.x); r32 NoiseValue = 0.f; - s32 VoxIndex = GetIndex(Voxel_Position(x,y,z), Dim); + s32 VoxIndex = GetIndex(V3i(x,y,z), Dim); Chunk->Voxels[VoxIndex].Flags = Voxel_Empty; Assert( NotSet(&Chunk->Voxels[VoxIndex], Voxel_Filled) ); @@ -372,7 +826,7 @@ TerracedTerrain( perlin_noise *Noise, for ( s32 x = 0; x < Dim.x; ++ x) { /* s64 WorldX = x + SrcToDest.x + (WorldChunkDim.x*Chunk->WorldP.x); */ - s32 VoxIndex = GetIndex(Voxel_Position(x,y,z), Dim); + s32 VoxIndex = GetIndex(V3i(x,y,z), Dim); Chunk->Voxels[VoxIndex].Flags = Voxel_Empty; /* Assert( NotSet(&Chunk->Voxels[VoxIndex], Voxel_Filled) ); */ @@ -654,7 +1108,7 @@ GrassyTerracedTerrain2( perlin_noise *Noise, } /* s64 WorldX = x + SrcToDest.x + (WorldChunkDim.x*Chunk->WorldP.x); */ - s32 VoxIndex = GetIndex(Voxel_Position(x,y,z), Dim); + s32 VoxIndex = GetIndex(V3i(x,y,z), Dim); Chunk->Voxels[VoxIndex].Flags = Voxel_Empty; /* Assert( NotSet(&Chunk->Voxels[VoxIndex], Voxel_Filled) ); */ @@ -731,7 +1185,7 @@ GrassyTerracedTerrain2( perlin_noise *Noise, } } - GrowGrass( Chunk, V3i(x,y,z), NoiseValue, 1.f-TerraceMask, SrcToDest, WorldChunkDim, WorldZSubZMin, &ThisColor, &IsFilled ); + GrowGrassPerlin( Chunk, V3i(x,y,z), NoiseValue, 1.f-TerraceMask, SrcToDest, WorldChunkDim, WorldZSubZMin, &ThisColor, &IsFilled ); SetFlag(&Chunk->Voxels[VoxIndex], (voxel_flag)(Voxel_Filled*IsFilled)); Chunk->Voxels[VoxIndex].Color = ThisColor*u8(IsFilled); @@ -806,7 +1260,7 @@ GrassyTerracedTerrain3( perlin_noise *Noise, /* s64 WorldZSubZMin = zMin; */ for ( s32 y = 0; y < Dim.y; ++ y) { - /* s64 WorldY = y + SrcToDest.y + (WorldChunkDim.y*Chunk->WorldP.y); */ + s64 WorldY = y + SrcToDest.y + (WorldChunkDim.y*Chunk->WorldP.y); for ( s32 x = 0; x < Dim.x; ++ x) { @@ -831,8 +1285,8 @@ GrassyTerracedTerrain3( perlin_noise *Noise, } #endif - /* s64 WorldX = x + SrcToDest.x + (WorldChunkDim.x*Chunk->WorldP.x); */ - s32 VoxIndex = GetIndex(Voxel_Position(x,y,z), Dim); + s64 WorldX = x + SrcToDest.x + (WorldChunkDim.x*Chunk->WorldP.x); + s32 VoxIndex = GetIndex(V3i(x,y,z), Dim); Chunk->Voxels[VoxIndex].Flags = Voxel_Empty; /* Assert( NotSet(&Chunk->Voxels[VoxIndex], Voxel_Filled) ); */ @@ -874,55 +1328,27 @@ GrassyTerracedTerrain3( perlin_noise *Noise, /* NoiseValue = BaseNoiseValue / TerraceMask; */ NoiseValue = BaseNoiseValue; - b32 IsFilled = r32(NoiseValue) > r32(WorldZSubZMin) ; - - u16 ThisColor = DIRT; + u16 ThisColor = MapNoiseValueToMaterial(BaseNoiseValue/MaxValue); u8 ThisTransparency = 0; - s32 SandThreshold = 3; - s32 GravelThreshold = 1; - s32 WaterThreshold = 0; - - r32 StoneThresh = r32(WorldZSubZMin) + 2.f; - r32 DirtThresh = r32(WorldZSubZMin) + 1.f; - - if (IsFilled) + if (ThisColor == STONE) { - ThisColor = GRASS_GREEN; - - if (NoiseValue > StoneThresh) + r32 Voronoi = VoronoiNoise3D(V3(s32(WorldX), s32(WorldY), s32(WorldZ)) * 0.04f) * 25.f; + if (Voronoi < 2.f) { - ThisColor = DIRT; + NoiseValue -= 2.f; } - } - - if (!IsFilled) - { - f32 GrassAreaX = (x + SrcToDest.x + (WorldChunkDim.x*Chunk->WorldP.x)) / 32.f; - f32 GrassAreaY = (y + SrcToDest.y + (WorldChunkDim.y*Chunk->WorldP.y)) / 32.f; - f32 GrassAreaZ = (z + SrcToDest.z + (WorldChunkDim.z*Chunk->WorldP.z)) / 32.f; - r32 GrassyAreaValue = PerlinNoise(GrassAreaX, GrassAreaY, GrassAreaZ); - if (ThisColor == GRASS_GREEN) + if (Voronoi < 5.f) { - if (GrassyAreaValue > 0.5f && NoiseValue+(GrassyAreaValue*5.f) > WorldZSubZMin) - { - f32 GrassX = (x + SrcToDest.x + (WorldChunkDim.x*Chunk->WorldP.x)) / 30.1f; - f32 GrassY = (y + SrcToDest.y + (WorldChunkDim.y*Chunk->WorldP.y)) / 30.1f; - f32 GrassZ = (z + SrcToDest.z + (WorldChunkDim.z*Chunk->WorldP.z)) / 450.f; - - r32 GrassValue = PerlinNoise(GrassX, GrassY, GrassZ); - - /* if (NoiseValue+(GrassValue*2.5f) > WorldZSubZMin) */ - { - IsFilled = True; - } - } + ThisColor = DARK_STONE; } } - GrowGrass( Chunk, V3i(x,y,z), NoiseValue, 1.f-TerraceMask, SrcToDest, WorldChunkDim, WorldZSubZMin, &ThisColor, &IsFilled ); + b32 IsFilled = r32(NoiseValue) > r32(WorldZSubZMin); + + GrowGrassPerlin( Chunk, V3i(x,y,z), NoiseValue, 1.f-TerraceMask, SrcToDest, WorldChunkDim, WorldZSubZMin, &ThisColor, &IsFilled ); SetFlag(&Chunk->Voxels[VoxIndex], (voxel_flag)(Voxel_Filled*IsFilled)); Chunk->Voxels[VoxIndex].Color = ThisColor*u8(IsFilled); @@ -966,15 +1392,538 @@ GrassyTerracedTerrain3( perlin_noise *Noise, return ChunkSum; } -link_internal u32 -GrassyTerracedTerrain( perlin_noise *Noise, - world_chunk *Chunk, - v3i Dim, - v3i SrcToDest, - u16 ColorIndex, +link_internal s32 +UnilateralToThesholdIndex(f32 Value, s32 ClipPoints) +{ + Assert(Value <= 1.f); + Assert(Value >= 0.f); - s32 IgnoredFrequency, - s32 IgnoredAmplitude, + s32 Result = s32(Value*ClipPoints); + return Result; +} + +link_internal void +MakeCliffs(world_chunk *Chunk, s32 VoxIndex, s32 WorldX, s32 WorldY, s32 WorldZ, r32 *NoiseValue, v3 *Normal, u16 *ThisColor) +{ + random_series ColorEntropy = RandomSeriesFromV3i(V3i(WorldX, WorldY, WorldZ)); + s32 Index = 0; + /* RangeIterator(Index, 8) */ + { + r32 DotNormal = Dot(Normal[Index], V3(0,0,1)); + + r32 Thresh = 0.43f; // Lower == more cliffy + r32 ClampedDotNormal = Clamp(Thresh, 1.f-DotNormal, 1.f); + + // 1.f when the cliff is at it's most cliffy (terrain is vertical) + r32 CliffBlend = MapValueToUnilateral(Thresh, ClampedDotNormal, 1.f); + + if (CliffBlend > 0.f) + { + /* Chunk->Voxels[NormalsIndex].DebugColor.x = CliffBlend; */ + + /* r32 Squareness = 0.1f; */ + r32 Squareness = 0.25f; + /* r32 Squareness = 0.55f; */ + /* r32 Squareness = 0.75f; */ + /* r32 Squareness = 0.8f; */ + /* r32 Squareness = 1.f; */ + + v3 BaseCellSize = V3(5.f, 5.f, 5.f); // Increasing this increases the size of the cells + + v3 CellSizes[] = { + {BaseCellSize}, + {BaseCellSize*V3(3.f, 3.f, 6.f)}, + {BaseCellSize*V3(7.f, 7.f, 18.f)}, + }; + + s32 CellIndex = UnilateralToThesholdIndex(CliffBlend, ArrayCount(CellSizes)-1); + Assert(CellIndex < s32(ArrayCount(CellSizes))); + v3 CellSize = CellSizes[CellIndex]; + + v3 CellMultiplier = (1.f/CellSize); + v3 WorldP = V3(WorldX+Index, WorldY, WorldZ); + r32 RockMaskChance = CliffBlend*6.f; // Higher = less rocks + r32 Voronoi = VoronoiNoise3D(WorldP * CellMultiplier, Squareness, RockMaskChance); + + NoiseValue[Index] += CliffBlend*Voronoi*10.f; + + r32 DarkStoneThresh = 0.08f; // Increasing this increases the amount of darkness + if (Voronoi < DarkStoneThresh) + { + if (CliffBlend > 0.1f) + { + if (RandomUnilateral(&ColorEntropy)-0.75f < CliffBlend) + { + NoiseValue[Index] -= 2.f*(CliffBlend); + ThisColor[Index] = DARK_STONE; + } + } + else + { + f32 ColorPick = RandomUnilateral(&ColorEntropy); + if (ColorPick > 0.94f) + { + ThisColor[Index] = DARK_GRASS_GREEN; + } + else if (ColorPick > 0.88f) + { + ThisColor[Index] = MOSS_GREEN; + } + else if (ColorPick > 0.80f) + { + ThisColor[Index] = LIGHT_MOSS_GREEN; + } + } + } + else + { + ThisColor[Index] = STONE; + } + } + } +} + +link_internal void +MakeCliffs_8x(world_chunk *Chunk, s32 NormalsIndex, s32 WorldX, s32 WorldY, s32 WorldZ, r32 *NoiseValue, v3 *Normal, u16 *ThisColor) +{ +#if 0 + RangeIterator(Index, 8) + { + MakeCliffs(Chunk, NormalsIndex, WorldX+Index, WorldY, WorldZ, NoiseValue+Index, Normal+Index, ThisColor+Index); + } +#else + random_series ColorEntropy = RandomSeriesFromV3i(V3i(WorldX, WorldY, WorldZ)); + RangeIterator(Index, 8) + { + r32 DotNormal = Dot(Normal[Index], V3(0,0,1)); + + r32 Thresh = 0.43f; // Lower == more cliffy + r32 ClampedDotNormal = Clamp(Thresh, 1.f-DotNormal, 1.f); + + // 1.f when the cliff is at it's most cliffy (terrain is vertical) + r32 CliffBlend = MapValueToUnilateral(Thresh, ClampedDotNormal, 1.f); + + if (CliffBlend > 0.f) + { + /* Chunk->Voxels[NormalsIndex].DebugColor.x = CliffBlend; */ + + /* r32 Squareness = 0.1f; */ + r32 Squareness = 0.25f; + /* r32 Squareness = 0.55f; */ + /* r32 Squareness = 0.75f; */ + /* r32 Squareness = 0.8f; */ + /* r32 Squareness = 1.f; */ + + v3 BaseCellSize = V3(5.f, 5.f, 5.f); // Increasing this increases the size of the cells + + v3 CellSizes[] = { + {BaseCellSize}, + {BaseCellSize*V3(3.f, 3.f, 6.f)}, + {BaseCellSize*V3(7.f, 7.f, 18.f)}, + }; + + s32 CellIndex = UnilateralToThesholdIndex(CliffBlend, ArrayCount(CellSizes)-1); + Assert(CellIndex < s32(ArrayCount(CellSizes))); + v3 CellSize = CellSizes[CellIndex]; + + v3 CellMultiplier = (1.f/CellSize); + v3 WorldP = V3(WorldX+Index, WorldY, WorldZ); + r32 RockMaskChance = CliffBlend*6.f; // Higher = less rocks + r32 Voronoi = VoronoiNoise3D(WorldP * CellMultiplier, Squareness, RockMaskChance); + + NoiseValue[Index] += CliffBlend*Voronoi*10.f; + + r32 DarkStoneThresh = 0.08f; // Increasing this increases the amount of darkness + if (Voronoi < DarkStoneThresh) + { + if (CliffBlend > 0.1f) + { + if (RandomUnilateral(&ColorEntropy)-0.75f < CliffBlend) + { + NoiseValue[Index] -= 2.f*(CliffBlend); + ThisColor[Index] = DARK_STONE; + } + } + else + { + f32 ColorPick = RandomUnilateral(&ColorEntropy); + if (ColorPick > 0.94f) + { + ThisColor[Index] = DARK_GRASS_GREEN; + } + else if (ColorPick > 0.88f) + { + ThisColor[Index] = MOSS_GREEN; + } + else if (ColorPick > 0.80f) + { + ThisColor[Index] = LIGHT_MOSS_GREEN; + } + } + } + else + { + ThisColor[Index] = STONE; + } + } + } +#endif +} + +link_internal u32 +GrassyTerracedTerrain4( perlin_noise *Noise, + world_chunk *Chunk, + v3i _Dim, + v3i SrcToDest, + u16 ColorIndex, + + s32 IgnoredFrequency, + s32 IgnoredAmplitude, + + s64 zMin, + v3i WorldChunkDim, + void *OctavesIn ) +{ + TIMED_FUNCTION(); + /* HISTOGRAM_FUNCTION(); */ + u32 ChunkSum = 0; + + Assert(_Dim == Chunk->Dim); + + octave_buffer *OctaveBuf = (octave_buffer*)OctavesIn; + u32 OctaveCount = OctaveBuf->Count; + + f32 MaxNoiseValue = 0.f; + for (u32 OctaveIndex = 0; OctaveIndex < OctaveCount; ++OctaveIndex) + { + octave *Octave = OctaveBuf->Octaves+OctaveIndex; + MaxNoiseValue += Octave->Amp; + } + + v3i NormalDim = _Dim; + v3i NoiseDim = _Dim+2; + /* b32 *NoiseHit = Allocate(b32, GetTranArena(), Volume(NoiseDim)); */ + /* b32 *NormalsHit = Allocate(b32, GetTranArena(), Volume(NormalDim)); */ + +#if VOXEL_DEBUG_COLOR + memory_arena *TempArena = GetThreadLocalState(ThreadLocal_ThreadIndex)->PermMemory; +#else + memory_arena *TempArena = GetTranArena(); +#endif + + r32 *NoiseValues = Allocate(r32, TempArena, Volume(NoiseDim)); + v3 *Normals = Allocate( v3, TempArena, Volume(NormalDim)); + +#if VOXEL_DEBUG_COLOR + Chunk->NoiseValues = NoiseValues; + Chunk->NormalValues = Normals; +#endif + + // NOTE(Jesse): Perlin_8x needs a multiple of 8 here. + /* Assert(Dim.x % 8 == 0); */ + + s32 xNoiseBlockCount = NoiseDim.x / 8; + { + TIMED_NAMED_BLOCK("Octaves"); + for ( s32 z = 0; z < NoiseDim.z; ++ z) + { + f32 zCoord = (-1 + z + SrcToDest.z + (WorldChunkDim.z*Chunk->WorldP.z)); + for ( s32 y = 0; y < NoiseDim.y; ++ y) + { + f32 yCoord = (-1 + y + SrcToDest.y + (WorldChunkDim.y*Chunk->WorldP.y)); + for ( s32 xBlock = 0; xBlock < xNoiseBlockCount; ++xBlock ) + { + s32 x = xBlock*8; + + s32 NoiseIndex = GetIndex(x,y,z, NoiseDim); + r32 *NoiseValue = NoiseValues + NoiseIndex; + /* RangeIterator(Index, 8) */ + /* { */ + /* Assert(NoiseHit[NoiseIndex+Index] == 0); */ + /* NoiseHit[NoiseIndex+Index] += 1; */ + /* } */ + + for (u32 OctaveIndex = 0; OctaveIndex < OctaveCount; ++OctaveIndex) + { + octave *Octave = OctaveBuf->Octaves+OctaveIndex; + + f32 InZ = (-1 + z + SrcToDest.z + (WorldChunkDim.z*Chunk->WorldP.z)) / Octave->Freq.z; + f32 InY = (-1 + y + SrcToDest.y + (WorldChunkDim.y*Chunk->WorldP.y)) / Octave->Freq.y; + + f32 xCoords[8] = + { + (-1 + x + SrcToDest.x + (WorldChunkDim.x*Chunk->WorldP.x)) / Octave->Freq.x, + (-1 + 1 + x + SrcToDest.x + (WorldChunkDim.x*Chunk->WorldP.x)) / Octave->Freq.x, + (-1 + 2 + x + SrcToDest.x + (WorldChunkDim.x*Chunk->WorldP.x)) / Octave->Freq.x, + (-1 + 3 + x + SrcToDest.x + (WorldChunkDim.x*Chunk->WorldP.x)) / Octave->Freq.x, + (-1 + 4 + x + SrcToDest.x + (WorldChunkDim.x*Chunk->WorldP.x)) / Octave->Freq.x, + (-1 + 5 + x + SrcToDest.x + (WorldChunkDim.x*Chunk->WorldP.x)) / Octave->Freq.x, + (-1 + 6 + x + SrcToDest.x + (WorldChunkDim.x*Chunk->WorldP.x)) / Octave->Freq.x, + (-1 + 7 + x + SrcToDest.x + (WorldChunkDim.x*Chunk->WorldP.x)) / Octave->Freq.x, + }; + + f32 TmpPerlinResults[8]; + PerlinNoise_8x(xCoords, InY, InZ, TmpPerlinResults); + + RangeIterator(Index, 8) + { + f32 N = TmpPerlinResults[Index]; + if (OctaveIndex == 0) + { + NoiseValue[Index] += MapNoiseValueToFinal(N) * Octave->Amp; + } + else + { + NoiseValue[Index] += N * Octave->Amp; + } + } + + } + } + +#if 1 + s32 xFixupBase = (xNoiseBlockCount * 8); + for ( s32 x = xFixupBase; x < NoiseDim.x; ++x ) + { + s32 NoiseIndex = GetIndex(x,y,z, NoiseDim); + /* Assert(NoiseHit[NoiseIndex] == 0); */ + /* NoiseHit[NoiseIndex] += 1; */ + + for (u32 OctaveIndex = 0; OctaveIndex < OctaveCount; ++OctaveIndex) + { + octave *Octave = OctaveBuf->Octaves+OctaveIndex; + + + v3 In = (-1 + V3(x,y,z) + SrcToDest + (WorldChunkDim*Chunk->WorldP)) / Octave->Freq; + f32 N = PerlinNoise(In.x, In.y, In.z); + /* f32 N = PerlinNoise(InX, InY, InZ); */ + if (OctaveIndex == 0) + { + NoiseValues[NoiseIndex] += MapNoiseValueToFinal(N) * Octave->Amp; + } + else + { + NoiseValues[NoiseIndex] += N * Octave->Amp; + } + } + } +#endif + } + } + } + +#if 0 + { + TIMED_NAMED_BLOCK("OctavesLeftovers"); + s32 xFixupBase = (xNoiseBlockCount * 8); + for ( s32 z = 0; z < NoiseDim.z; ++ z) + { + for ( s32 y = 0; y < NoiseDim.y; ++ y) + { + for ( s32 x = xFixupBase; x < NoiseDim.x; ++x ) + { + s32 NoiseIndex = GetIndex(x,y,z, NoiseDim); + Assert(NoiseHit[NoiseIndex] == 0); + NoiseHit[NoiseIndex] = 1; + + for (u32 OctaveIndex = 0; OctaveIndex < OctaveCount; ++OctaveIndex) + { + octave *Octave = OctaveBuf->Octaves+OctaveIndex; + + f32 InY = (-1 + y + SrcToDest.y + (WorldChunkDim.y*Chunk->WorldP.y)) / Octave->Freq.y; + f32 InZ = (-1 + z + SrcToDest.z + (WorldChunkDim.z*Chunk->WorldP.z)) / Octave->Freq.z; + f32 InX = (-1 + x + SrcToDest.x + (WorldChunkDim.x*Chunk->WorldP.x)) / Octave->Freq.x; + + /* v3 In = (-1 + V3(x,y,z) + SrcToDest + (WorldChunkDim*Chunk->WorldP)) / Octave->Freq; */ + /* f32 N = PerlinNoise(In.x, In.y, In.z); */ + f32 N = PerlinNoise(InX, InY, InZ); + if (OctaveIndex == 0) + { + NoiseValues[NoiseIndex] += MapNoiseValueToFinal(N) * Octave->Amp; + } + else + { + NoiseValues[NoiseIndex] += N * Octave->Amp; + } + } + } + } + } + } +#endif + + s64 ChunkWorldZThresh = SrcToDest.z + (WorldChunkDim.z*Chunk->WorldP.z) - zMin; + ComputeNormalsForChunkFromNoiseValues(ChunkWorldZThresh, NoiseValues, NoiseDim, Normals, NormalDim); + + s32 xShapingBlockCount = NormalDim.x/8; + { + TIMED_NAMED_BLOCK("Shaping"); + for ( s32 z = 0; z < NormalDim.z; ++ z) + { + s64 WorldZ = z + SrcToDest.z + (WorldChunkDim.z*Chunk->WorldP.z); + s64 WorldZSubZMin = WorldZ - zMin; + for ( s32 y = 0; y < NormalDim.y; ++ y) + { + s64 WorldY = y + SrcToDest.y + (WorldChunkDim.y*Chunk->WorldP.y); + for ( s32 xBlock = 0; xBlock < xShapingBlockCount; ++xBlock ) + { + s32 x = xBlock * 8; + s64 WorldX = x + SrcToDest.x + (WorldChunkDim.x*Chunk->WorldP.x); + + s32 NormalIndex = GetIndex(V3i(x,y,z), NormalDim); + s32 NoiseIndex = GetIndex(V3i(x+1,y+1,z+1), NoiseDim); + /* s32 TestVoxIndex = GetIndex(V3i(x,y,z), NormalDim); */ + /* Assert(NormalIndex == TestVoxIndex); */ + + r32 *NoiseValue = NoiseValues + NoiseIndex; + v3 *Normal = Normals + NormalIndex; + + u16 ThisColor[8] = { GRASS_GREEN, GRASS_GREEN, GRASS_GREEN, GRASS_GREEN, GRASS_GREEN, GRASS_GREEN, GRASS_GREEN, GRASS_GREEN }; + +#if 1 + /* Chunk->Voxels[NormalIndex].DebugColor.x = *NoiseValue; */ + MakeCliffs_8x(Chunk, NormalIndex, s32(WorldX), s32(WorldY), s32(WorldZ), NoiseValue, Normal, ThisColor); + GrowGrassVoronoi_8x( Chunk, V3i(x,y,z), NoiseValue, Normal, SrcToDest, WorldChunkDim, WorldZSubZMin, ThisColor); + /* RandomVoronoiRocks_8x( Chunk, V3i(x,y,z), NoiseValue, Normal, SrcToDest, WorldChunkDim, WorldZSubZMin, ThisColor); */ + /* GrowGrassPerlin_8x( Chunk, V3i(x,y,z), NoiseValue, Normal, 1.f, SrcToDest, WorldChunkDim, WorldZSubZMin, ThisColor); */ +#endif + + RangeIterator(Index, 8) + { + /* Assert(NormalsHit[NormalIndex+Index] == 0); */ + /* NormalsHit[NormalIndex+Index] = 1; */ + + b32 IsFilled = NoiseValues[NoiseIndex+Index] > r32(z+ChunkWorldZThresh); + SetFlag(&Chunk->Voxels[NormalIndex+Index], (voxel_flag)(Voxel_Filled*IsFilled)); + Chunk->Voxels[NormalIndex+Index].Color = ThisColor[Index]*u8(IsFilled); + /* Chunk->Voxels[NormalIndex].Transparency = ThisTransparency; */ + ChunkSum += IsFilled; + } + +#if 0 + Assert( (Chunk->Voxels[NormalIndex].Flags&VoxelFaceMask) == 0); + + if (IsFilled) + { + Assert( IsSet(&Chunk->Voxels[NormalIndex], Voxel_Filled) ); + } + else + { + Assert( NotSet(&Chunk->Voxels[NormalIndex], Voxel_Filled) ); + } +#endif + } + + s32 xFixupBase = (xShapingBlockCount * 8); + for ( s32 x = xFixupBase; x < NormalDim.x; ++x ) + { + s64 WorldX = x + SrcToDest.x + (WorldChunkDim.x*Chunk->WorldP.x); + + s32 NormalIndex = GetIndex(V3i(x,y,z), NormalDim); + /* Assert(NormalsHit[NormalIndex] == 0); */ + /* NormalsHit[NormalIndex] = 1; */ + + s32 NoiseIndex = GetIndex(V3i(x+1,y+1,z+1), NoiseDim); + r32 *NoiseValue = NoiseValues + NoiseIndex; + v3 *Normal = Normals + NormalIndex; + + u16 ThisColor = GRASS_GREEN; + MakeCliffs(Chunk, NormalIndex, s32(WorldX), s32(WorldY), s32(WorldZ), NoiseValue, Normal, &ThisColor); + GrowGrassVoronoi( Chunk, V3i(x,y,z), NoiseValue, Normal, SrcToDest, WorldChunkDim, WorldZSubZMin, &ThisColor); + + b32 IsFilled = NoiseValues[NoiseIndex] > r32(z+ChunkWorldZThresh); + SetFlag(&Chunk->Voxels[NormalIndex], (voxel_flag)(Voxel_Filled*IsFilled)); + Chunk->Voxels[NormalIndex].Color = ThisColor*u8(IsFilled); + /* Chunk->Voxels[NormalIndex].Transparency = ThisTransparency; */ + ChunkSum += IsFilled; + } + } + } + } + +#if 0 + { + TIMED_NAMED_BLOCK("ShapingLeftovers"); + s32 xFixupBase = (xShapingBlockCount * 8); + for ( s32 z = 0; z < NormalDim.z; ++ z) + { + s64 WorldZ = z + SrcToDest.z + (WorldChunkDim.z*Chunk->WorldP.z); + + for ( s32 y = 0; y < NormalDim.y; ++ y) + { + s64 WorldY = y + SrcToDest.y + (WorldChunkDim.y*Chunk->WorldP.y); + + for ( s32 x = xFixupBase; x < NormalDim.x; ++x ) + { + s64 WorldX = x + SrcToDest.x + (WorldChunkDim.x*Chunk->WorldP.x); + + s32 NormalIndex = GetIndex(V3i(x,y,z), NormalDim); + Assert(NormalsHit[NormalIndex] == 0); + NormalsHit[NormalIndex] = 1; + s32 NoiseIndex = GetIndex(V3i(x+1,y+1,z+1), NoiseDim); + + u16 ThisColor = GRASS_GREEN; + MakeCliffs_8x(Chunk, NormalIndex, s32(WorldX), s32(WorldY), s32(WorldZ), NoiseValue, Normal, ThisColor); + + b32 IsFilled = NoiseValues[NoiseIndex] > r32(z+ChunkWorldZThresh); + SetFlag(&Chunk->Voxels[NormalIndex], (voxel_flag)(Voxel_Filled*IsFilled)); + Chunk->Voxels[NormalIndex].Color = ThisColor*u8(IsFilled); + /* Chunk->Voxels[NormalIndex].Transparency = ThisTransparency; */ + ChunkSum += IsFilled; + } + } + } + } +#endif + + /* RangeIterator(Index, Volume(NoiseDim)) */ + /* { */ + /* Assert(NoiseHit[Index] == 1); */ + /* } */ + + + /* RangeIterator(Index, Volume(NormalDim)) */ + /* { */ + /* Assert(NormalsHit[Index] == 1); */ + /* } */ + + +#if 0 + v3 *Normals = Allocate(v3, GetTranArena(), Volume(Dim)); + ComputeNormalsForChunkFromFilledFlag(Chunk, WorldChunkDim, Normals); +#endif + +#if VOXEL_DEBUG_COLOR +#if 0 + for ( s32 z = 0; z < Chunk->Dim.z; ++ z) + { + for ( s32 y = 0; y < Chunk->Dim.y; ++ y) + { + for ( s32 x = 0; x < Chunk->Dim.x; ++ x) + { + /* s32 Index = GetIndex(V3i(x,y,z), NormalDim); */ + s32 NormalIndex = GetIndex(V3i(x,y,z), NormalDim); + s32 NoiseIndex = GetIndex(V3i(x,y,z)+1, NoiseDim); + Chunk->Voxels[NormalIndex].DebugColor = Normals[NormalIndex]; + Chunk->Voxels[NormalIndex].DebugNoiseValue = NoiseValues[NoiseIndex]; + } + } + } +#endif +#endif + + return ChunkSum; +} + +link_internal u32 +GrassyTerracedTerrain( perlin_noise *Noise, + world_chunk *Chunk, + v3i Dim, + v3i SrcToDest, + u16 ColorIndex, + + s32 IgnoredFrequency, + s32 IgnoredAmplitude, s64 zMin, v3i WorldChunkDim, @@ -1000,7 +1949,7 @@ GrassyTerracedTerrain( perlin_noise *Noise, for ( s32 x = 0; x < Dim.x; ++ x) { /* s64 WorldX = x + SrcToDest.x + (WorldChunkDim.x*Chunk->WorldP.x); */ - s32 VoxIndex = GetIndex(Voxel_Position(x,y,z), Dim); + s32 VoxIndex = GetIndex(V3i(x,y,z), Dim); Chunk->Voxels[VoxIndex].Flags = Voxel_Empty; /* Assert( NotSet(&Chunk->Voxels[VoxIndex], Voxel_Filled) ); */ @@ -1099,7 +2048,7 @@ GrassyTerracedTerrain( perlin_noise *Noise, } } - GrowGrass( Chunk, V3i(x,y,z), NoiseValue, 1.f, SrcToDest, WorldChunkDim, WorldZSubZMin, &ThisColor, &IsFilled ); + GrowGrassPerlin( Chunk, V3i(x,y,z), NoiseValue, 1.f, SrcToDest, WorldChunkDim, WorldZSubZMin, &ThisColor, &IsFilled ); SetFlag(&Chunk->Voxels[VoxIndex], (voxel_flag)(Voxel_Filled*IsFilled)); Chunk->Voxels[VoxIndex].Color = ThisColor*u8(IsFilled); @@ -1197,7 +2146,7 @@ GrassyLargeTerracedTerrain( perlin_noise *Noise, } /* s64 WorldX = x + SrcToDest.x + (WorldChunkDim.x*Chunk->WorldP.x); */ - s32 VoxIndex = GetIndex(Voxel_Position(x,y,z), Dim); + s32 VoxIndex = GetIndex(V3i(x,y,z), Dim); Chunk->Voxels[VoxIndex].Flags = Voxel_Empty; /* Assert( NotSet(&Chunk->Voxels[VoxIndex], Voxel_Filled) ); */ @@ -1263,9 +2212,9 @@ GrassyLargeTerracedTerrain( perlin_noise *Noise, Assert(TerraceMask >= 0.f); Assert(TerraceMask <= 1.1f); - /* GrowGrass( Chunk, V3i(x,y,z), NoiseValue, 0.7f-TerraceMask, SrcToDest, WorldChunkDim, WorldZSubZMin, &ThisColor, &IsFilled ); */ - GrowGrass( Chunk, V3i(x,y,z), NoiseValue, 1.f-Clamp01(TerraceMask), SrcToDest, WorldChunkDim, WorldZSubZMin, &ThisColor, &IsFilled ); - /* GrowGrass( Chunk, V3i(x,y,z), NoiseValue, Clamp01(TerraceMask), SrcToDest, WorldChunkDim, WorldZSubZMin, &ThisColor, &IsFilled ); */ + /* GrowGrassPerlin( Chunk, V3i(x,y,z), NoiseValue, 0.7f-TerraceMask, SrcToDest, WorldChunkDim, WorldZSubZMin, &ThisColor, &IsFilled ); */ + GrowGrassPerlin( Chunk, V3i(x,y,z), NoiseValue, 1.f-Clamp01(TerraceMask), SrcToDest, WorldChunkDim, WorldZSubZMin, &ThisColor, &IsFilled ); + /* GrowGrassPerlin( Chunk, V3i(x,y,z), NoiseValue, Clamp01(TerraceMask), SrcToDest, WorldChunkDim, WorldZSubZMin, &ThisColor, &IsFilled ); */ SetFlag(&Chunk->Voxels[VoxIndex], (voxel_flag)(Voxel_Filled*IsFilled)); Chunk->Voxels[VoxIndex].Color = ThisColor*u8(IsFilled); @@ -1326,6 +2275,87 @@ SinCosTerrain( perlin_noise *Noise, TIMED_FUNCTION(); Assert(OctavesIn == 0); + r32 *NoiseValues = Allocate(r32, GetTranArena(), Volume(Dim)); + v3 *Normals = Allocate( v3, GetTranArena(), Volume(Dim)); + + u32 ChunkSum = 0; + + s32 MinZ = Chunk->WorldP.z*WorldChunkDim.z; + s32 MaxZ = MinZ+WorldChunkDim.z ; + + for ( s32 z = 0; z < Dim.z; ++ z) + { + s64 WorldZ = z + SrcToDest.z + (WorldChunkDim.z*Chunk->WorldP.z); + s64 WorldZSubZMin = WorldZ - zMin; + for ( s32 y = 0; y < Dim.y; ++ y) + { + s64 WorldY = y + SrcToDest.y + (WorldChunkDim.y*Chunk->WorldP.y); + for ( s32 x = 0; x < Dim.x; ++ x) + { + s64 WorldX = x + SrcToDest.x + (WorldChunkDim.x*Chunk->WorldP.x); + s32 VoxIndex = GetIndex(V3i(x,y,z), Dim); + r32 NoiseValue = ((Sin(r32(WorldX)/r32(Frequency))+1.f)/2.f) + ((Cos(r32(WorldY)/r32(Frequency))+1.f)/4.f); + + /* NoiseValue = MapNoiseValueToFinal(NoiseValue); */ + NoiseValue *= Amplitude; + + NoiseValues[VoxIndex] = NoiseValue; + } + } + } + +/* s64 ChunkWorldZThresh = SrcToDest.z + (WorldChunkDim.z*Chunk->WorldP.z) - zMin; */ +/* NotImplemented; */ +/* /1* ComputeNormalsForChunkFromNoiseValues(ChunkWorldZThresh, NoiseValues, Normals); *1/ */ + + + for ( s32 z = 0; z < Dim.z; ++ z) + { + s64 WorldZ = z + SrcToDest.z + (WorldChunkDim.z*Chunk->WorldP.z); + s64 WorldZSubZMin = WorldZ - zMin; + for ( s32 y = 0; y < Dim.y; ++ y) + { + s64 WorldY = y + SrcToDest.y + (WorldChunkDim.y*Chunk->WorldP.y); + for ( s32 x = 0; x < Dim.x; ++ x) + { + s64 WorldX = x + SrcToDest.x + (WorldChunkDim.x*Chunk->WorldP.x); + + s32 VoxIndex = GetIndex(V3i(x,y,z), Dim); + r32 *NoiseValue = NoiseValues+VoxIndex; + v3 *Normal = Normals+VoxIndex; + + u16 ThisColor = GRASS_GREEN; + /* MakeCliffs(Chunk, VoxIndex, s32(WorldX), s32(WorldY), s32(WorldZ), NoiseValue, Normal, &ThisColor); */ + + b32 IsFilled = r32(*NoiseValue) > r32(WorldZSubZMin); + + SetFlag(&Chunk->Voxels[VoxIndex], (voxel_flag)(Voxel_Filled*IsFilled)); + Chunk->Voxels[VoxIndex].Color = ThisColor; + ChunkSum += IsFilled; + } + } + } + + return ChunkSum; +} + +link_internal u32 +VoronoiTerrain( perlin_noise *Noise, + world_chunk *Chunk, + v3i Dim, + v3i SrcToDest, + u16 ColorIndex, + + s32 Frequency, + s32 Amplitude, + + s64 zMin, + v3i WorldChunkDim, + void *OctavesIn ) +{ + TIMED_FUNCTION(); + Assert(OctavesIn == 0); + u32 ChunkSum = 0; s32 MinZ = Chunk->WorldP.z*WorldChunkDim.z; @@ -1341,11 +2371,12 @@ SinCosTerrain( perlin_noise *Noise, for ( s32 x = 0; x < Dim.x; ++ x) { s64 WorldX = x + SrcToDest.x + (WorldChunkDim.x*Chunk->WorldP.x); - s32 VoxIndex = GetIndex(Voxel_Position(x,y,z), Dim); + s32 VoxIndex = GetIndex(V3i(x,y,z), Dim); Chunk->Voxels[VoxIndex].Flags = Voxel_Empty; - r32 NoiseValue = ((Sin(r32(WorldX)/r32(Frequency))+1.f)/4.f) + ((Cos(r32(WorldY)/r32(Frequency))+1.f)/4.f); - NoiseValue = MapNoiseValueToFinal(NoiseValue); + r32 NoiseValue = VoronoiNoise3D(V3(s32(WorldX), s32(WorldY), s32(WorldZ)) * 0.01f); + NoiseValue = Clamp01(NoiseValue); + /* NoiseValue = MapNoiseValueToFinal(NoiseValue); */ // Crazyballs NoiseValue *= Amplitude; b32 IsFilled = r32(NoiseValue) > r32(WorldZSubZMin) ; diff --git a/src/engine/terrain.h b/src/engine/terrain.h index 63bc759f5..9fa68ca52 100644 --- a/src/engine/terrain.h +++ b/src/engine/terrain.h @@ -1,9 +1,48 @@ +struct noise_value_to_material_index +{ + f32 NoiseValue; + u16 MaterialIndex; +}; + +link_internal u16 +MapNoiseValueToMaterial(f32 Value) +{ + noise_value_to_material_index Points[] = + { + {1.0f, SNOW }, + {0.5f, STONE }, + {0.35f, GRASS_GREEN }, + {0.3f, GRASS_GREEN }, + {0.2f, GRASS_GREEN }, + {0.0f, GRASS_GREEN }, + }; + + + b32 Hit = False;; + r32 Result = Value; + s32 PointCount = s32(ArrayCount(Points)); + RangeIterator(PointIndex, PointCount) + { + noise_value_to_material_index *P = Points + PointIndex; + + // This is sort of a hack to fix the degenerate case when the value is 0 or 1. + // TODO(Jesse): Make this branchless + if (Value == P->NoiseValue) return P->MaterialIndex; + + if (Value > P->NoiseValue) + { + return P->MaterialIndex; + } + } + return 0; +} + link_internal f32 MapNoiseValueToFinal(f32 Value) { - Assert(Value <= 1.f); - Assert(Value >= 0.f); + /* Assert(Value <= 1.f); */ + /* Assert(Value >= 0.f); */ // NOTE(Jesse): Descending order so we can scan from the front and find the interval we care about /* v2 Points[] = */ @@ -16,14 +55,48 @@ MapNoiseValueToFinal(f32 Value) /* {{0.0f, 0.0f }}, */ /* }; */ + /* v2 Points[] = */ + /* { */ + /* {{1.0f, 1.0f }}, */ + /* {{0.5f, 0.7f }}, */ + /* {{0.35f, 0.43f }}, */ + /* {{0.3f, 0.4f }}, */ + /* {{0.2f, 0.1f }}, */ + /* {{0.0f, 0.0f }}, */ + /* }; */ + + // Pretty nice +/* v2 Points[] = */ +/* { */ +/* {{1.0f, 1.0f }}, */ +/* {{0.7f, 0.7f }}, */ +/* {{0.65f, 0.43f }}, */ +/* {{0.6f, 0.4f }}, */ +/* {{0.5f, 0.1f }}, */ +/* {{0.0f, 0.0f }}, */ +/* }; */ + + // Pillar-y v2 Points[] = { - {{1.0f, 1.0f }}, - {{0.5f, 0.7f }}, - {{0.2f, 0.1f }}, - {{0.0f, 0.0f }}, + {{1.0f, 0.5f }}, + {{0.6f, 0.3f }}, + {{0.1f, 0.2f }}, + {{0.05f, 0.45f }}, + {{0.0f , 0.5f }}, }; +/* v2 Points[] = */ +/* { */ +/* {{1.0f, 0.0f }}, */ +/* {{0.9f, 1.0f }}, */ +/* {{0.6f, 0.3f }}, */ +/* {{0.1f, 0.1f }}, */ +/* {{0.05f, 0.45f }}, */ +/* {{0.0f , 0.5f }}, */ +/* }; */ + + b32 Hit = False;; r32 Result = Value; @@ -31,28 +104,38 @@ MapNoiseValueToFinal(f32 Value) RangeIterator(PointIndex, PointCount) { v2 *P = Points + PointIndex; + + // This is sort of a hack to fix the degenerate case when the value is 0 or 1. + // TODO(Jesse): Make this branchless + if (Value == P->x) return P->y; + if (Value > P->x) { Hit = True; - Assert(PointIndex > 0); + /* Assert(PointIndex > 0); */ v2 *PNext = Points + PointIndex - 1; r32 Range = PNext->x - P->x; - Assert(Range > 0.f); + /* Assert(Range > 0.f); */ r32 t = (Value-P->x) / Range; - Result = Lerp(t, P->y, PNext->y); - Assert(Result >= 0.f); - Assert(Result <= 1.f); + /* Result = Lerp(t, P->y, PNext->y); */ + Result = CosineInterpolate(t, P->y, PNext->y); + /* Assert(Result >= 0.f); */ + /* Assert(Result <= 1.f); */ break; } } - Assert(Hit); - Assert(Result <= 1.f); - Assert(Result >= 0.f); - return Smoothstep(Result); + /* Assert(Hit); */ + /* Assert(Result <= 1.f); */ + /* Assert(Result >= 0.f); */ + + return Result; } + +link_internal void +ComputeNormalsForChunkFromNoiseValues( r32 ChunkWorldZ, r32 *NoiseValues, v3i NoiseDim, v3 *Normals, v3i NormalsDim); diff --git a/src/engine/voxel_face.h b/src/engine/voxel_face.h index f1e4392a2..0a6abc98d 100644 --- a/src/engine/voxel_face.h +++ b/src/engine/voxel_face.h @@ -19,8 +19,8 @@ /* global_variable f32 ShimmerStrength = 0.0005f; */ /* global_variable f32 ShimmerStrength = -0.0005f; */ // TODO(Jesse): Remove this -global_variable f32 ShimmerStrength = 0.f; -global_variable v3 ShimmerFix = {{ShimmerStrength, ShimmerStrength, ShimmerStrength}}; +/* global_variable f32 ShimmerStrength = 0.f; */ +/* global_variable v3 ShimmerFix = {{ShimmerStrength, ShimmerStrength, ShimmerStrength}}; */ global_variable v3 TopPlane = {{ 1.f, 1.f, 0.f }}; global_variable v3 BotPlane = {{ 1.f, 1.f, 0.f }}; @@ -50,8 +50,7 @@ enum face_index inline void RightFaceVertexData( v3 MinP, v3 Diameter, v3 *Result) { - v3 MaxP = MinP + Diameter + (ShimmerFix*RightPlane); - MinP -= ShimmerFix; + v3 MaxP = MinP + Diameter; /* Round(MaxP); */ /* Round(MinP); */ @@ -84,8 +83,7 @@ global_variable v3 RightFaceNormalData[] = inline void LeftFaceVertexData( v3 MinP, v3 Diameter, v3 *Result) { - v3 MaxP = MinP + Diameter + (ShimmerFix*LeftPlane); - MinP -= ShimmerFix; + v3 MaxP = MinP + Diameter; /* Round(MaxP); */ /* Round(MinP); */ @@ -118,8 +116,7 @@ global_variable v3 LeftFaceNormalData[] = inline void BackFaceVertexData( v3 MinP, v3 Diameter, v3 *Result) { - v3 MaxP = MinP + Diameter + (ShimmerFix*BackPlane); - MinP -= ShimmerFix; + v3 MaxP = MinP + Diameter; /* Round(MaxP); */ /* Round(MinP); */ @@ -152,8 +149,7 @@ global_variable v3 BackFaceNormalData[] = inline void FrontFaceVertexData( v3 MinP, v3 Diameter, v3 *Result) { - v3 MaxP = MinP + Diameter + (ShimmerFix*FrontPlane); - MinP -= ShimmerFix; + v3 MaxP = MinP + Diameter; /* Round(MaxP); */ /* Round(MinP); */ @@ -187,8 +183,7 @@ global_variable v3 FrontFaceNormalData[] = inline void TopFaceVertexData( v3 MinP, v3 Diameter, v3 *Result) { - v3 MaxP = MinP + Diameter + (ShimmerFix*TopPlane); - MinP -= ShimmerFix; + v3 MaxP = MinP + Diameter; /* Round(MaxP); */ /* Round(MinP); */ @@ -223,8 +218,7 @@ inline void BottomFaceVertexData( v3 MinP, v3 Diameter, v3 *Result) { /* TIMED_FUNCTION(); */ - v3 MaxP = MinP + Diameter + (ShimmerFix*BotPlane); - MinP -= ShimmerFix; + v3 MaxP = MinP + Diameter; /* Round(MaxP); */ /* Round(MinP); */ diff --git a/src/engine/voxel_synthesis.h b/src/engine/voxel_synthesis.h index c382a37d5..3dab29103 100644 --- a/src/engine/voxel_synthesis.h +++ b/src/engine/voxel_synthesis.h @@ -324,12 +324,6 @@ poof(gen_constructor(voxel_synthesis_change_propagation_info)) poof(are_equal(voxel_synthesis_change_propagation_info)) #include -link_internal b32 -AreEqual(voxel_synthesis_change_propagation_info O1, voxel_synthesis_change_propagation_info O2) -{ - return AreEqual(&O1, &O2); -} - poof(generate_stack(voxel_synthesis_change_propagation_info, {v3i Min, Max;} )) #include diff --git a/src/engine/world.cpp b/src/engine/world.cpp index d6a7697a9..21beab71e 100644 --- a/src/engine/world.cpp +++ b/src/engine/world.cpp @@ -56,9 +56,9 @@ HardResetWorld(engine_resources *Engine, hard_reset_flags Flags = HardResetFlag_ } } - RangeIterator(EntityIndex, TOTAL_ENTITY_COUNT) + RangeIterator_t(u32, EntityIndex, TOTAL_ENTITY_COUNT) { - if ( (Flags&HardResetFlag_NoResetCamera) && Graphics->GameCamera.GhostId == EntityIndex ) { continue; } + if ( (Flags&HardResetFlag_NoResetCamera) && Graphics->GameCamera.GhostId.Index == EntityIndex ) { continue; } Unspawn(EntityTable[EntityIndex]); } @@ -158,8 +158,11 @@ GatherVoxelsOverlappingArea(world *World, rect3i SimSpaceAABB, world_chunk_ptr_b u32 TotalVoxels = (u32)TotalVoxels_signed; // TODO(Jesse): Put this behind a debug/internal flag ? +#if VOXEL_DEBUG_COLOR + voxel UnsetVoxel = { 0xff, 0xff, 0xffff, {}, {} }; +#else voxel UnsetVoxel = { 0xff, 0xff, 0xffff }; - /* voxel UnsetVoxel = { 0xff, 0xff, 0xffff, {}, {}, }; */ +#endif for (u32 VoxelIndex = 0; VoxelIndex < TotalVoxels; ++VoxelIndex) { Voxels[VoxelIndex] = UnsetVoxel; } v3i SimSpaceQueryMinP = SimSpaceAABB.Min; diff --git a/src/engine/world_chunk.cpp b/src/engine/world_chunk.cpp index 60c97ab4b..a595f4ac3 100644 --- a/src/engine/world_chunk.cpp +++ b/src/engine/world_chunk.cpp @@ -616,6 +616,22 @@ Noise_FBM2D( perlin_noise *Noise, if (MinZ > Amplitude) return ChunkSum; +#if VOXEL_DEBUG_COLOR + memory_arena *TempArena = GetThreadLocalState(ThreadLocal_ThreadIndex)->PermMemory; +#else + memory_arena *TempArena = GetTranArena(); +#endif + + v3i NoiseDim = Chunk->Dim + 2; + v3i NormalDim = Chunk->Dim; + r32 *NoiseValues = Allocate(r32, TempArena, Volume(NoiseDim)); + v3 *Normals = Allocate( v3, TempArena, Volume(NormalDim)); + +#if VOXEL_DEBUG_COLOR + Chunk->NoiseValues = NoiseValues; + Chunk->NormalValues = Normals; +#endif + Frequency = Max(Frequency, 1); Assert(Frequency != s32_MIN); @@ -662,6 +678,10 @@ Noise_FBM2D( perlin_noise *Noise, InteriorFreq = Max(1, InteriorFreq/2); } +#if VOXEL_DEBUG_COLOR + s32 NoiseIndex = GetIndex(V3i(x,y,z)+1, NoiseDim); + Chunk->NoiseValues[NoiseIndex] = NoiseValue; +#endif b32 NoiseChoice = r64(NoiseValue) > r64(WorldZBiased); u16 ThisColor = SafeTruncateToU16(RandomBetween(u32(ColorIndex), &GenColorEntropy, u32(ColorIndex)+2));; @@ -684,6 +704,9 @@ Noise_FBM2D( perlin_noise *Noise, } } + s64 ChunkWorldZThresh = SrcToDest.z + (WorldChunkDim.z*Chunk->WorldP.z) - zMin; + ComputeNormalsForChunkFromNoiseValues(ChunkWorldZThresh, NoiseValues, NoiseDim, Normals, NormalDim); + return ChunkSum; } @@ -768,6 +791,44 @@ Noise_Perlin3D( perlin_noise *Noise, typedef u32 (*chunk_init_callback)( perlin_noise *Noise, world_chunk *Chunk, chunk_dimension Dim, chunk_dimension SrcToDest, u16 ColorIndex, s32 Frequency, s32 Amplitude, s64 zMin, chunk_dimension WorldChunkDim, void* UserData); +// NOTE(Jesse): Asserts are commented out for perf +link_internal b32 +TransparencyIncreases(voxel *SrcVox, voxel *DstVox) +{ + /* s32 DestIndex = GetIndex(DestP, SrcChunkDim); */ + /* voxel *SrcVox = Voxels+SrcIndex; */ + /* voxel *DstVox = Voxels+DestIndex; */ + + /* Assert(SrcVox->Flags & Voxel_Filled); */ + + b32 Result = False; + if (SrcVox->Transparency) + { + // Transparent source voxels can only increase in transparency if the dest is unfilled + if ( (DstVox->Flags&Voxel_Filled) == False) + { + /* Assert(DstVox->Transparency == 0); */ + Result = True; + } + } + else + { + // Opaque source voxels can increase in transparency if the dest is unfilled or filled and transparent + if ( (DstVox->Flags&Voxel_Filled) == False) + { + /* Assert(DstVox->Transparency == 0); */ + Result = True; + } + + if ( (DstVox->Flags&Voxel_Filled) && DstVox->Transparency) + { + Result = True; + } + + } + + return Result; +} link_internal b32 TransparencyIncreases(voxel *Voxels, s32 SrcIndex, v3i DestP, v3i SrcChunkDim) { @@ -895,6 +956,105 @@ MarkBoundaryVoxels_MakeExteriorFaces( voxel *Voxels, link_internal void MarkBoundaryVoxels_NoExteriorFaces( voxel *Voxels, + v3i SrcChunkDim, + v3i SrcChunkMin, + v3i SrcChunkMax, + random_series *Entropy = 0, + u8 NewColorMin = 0, + u8 NewColorMax = 0 ) +{ + /* HISTOGRAM_FUNCTION(); */ + TIMED_FUNCTION(); + + auto MinDim = SrcChunkMin; + auto MaxDim = Min(SrcChunkDim, SrcChunkMax); // SrcChunkMin+DestChunkDim+1 + + v3i InnerDim = MaxDim-MinDim; + + s32 MaxIndex = Volume(SrcChunkDim); + for ( s32 z = MinDim.z; z < MaxDim.z ; ++z ) + { + for ( s32 y = MinDim.y; y < MaxDim.y ; ++y ) + { + for ( s32 x = MinDim.x; x < MaxDim.x ; ++x ) + { + v3i SrcP = V3i(x,y,z); + s32 SrcIndex = GetIndex(SrcP, SrcChunkDim); + voxel *Voxel = Voxels + SrcIndex; + if (Voxel->Flags & Voxel_Filled) + { + Voxel->Flags = Voxel_Filled; + + s32 RightIndex = GetIndex(SrcP + V3i(1, 0, 0), SrcChunkDim); + s32 LeftIndex = GetIndex(SrcP - V3i(1, 0, 0), SrcChunkDim); + s32 TopIndex = GetIndex(SrcP + V3i(0, 0, 1), SrcChunkDim); + s32 BottomIndex= GetIndex(SrcP - V3i(0, 0, 1), SrcChunkDim); + s32 FrontIndex = GetIndex(SrcP + V3i(0, 1, 0), SrcChunkDim); + s32 BackIndex = GetIndex(SrcP - V3i(0, 1, 0), SrcChunkDim); + + if ( RightIndex >= 0 && RightIndex < MaxIndex ) + { + voxel *NextVoxel = Voxels + RightIndex; + if ( !(NextVoxel->Flags&Voxel_Filled) || TransparencyIncreases(Voxel, NextVoxel)) + { + Voxel->Flags |= Voxel_RightFace; + } + } + if ( LeftIndex >= 0 && LeftIndex < MaxIndex ) + { + voxel *NextVoxel = Voxels + LeftIndex; + if ( !(NextVoxel->Flags&Voxel_Filled) || TransparencyIncreases(Voxel, NextVoxel)) + { + Voxel->Flags |= Voxel_LeftFace; + } + } + + if ( TopIndex >= 0 && TopIndex < MaxIndex ) + { + voxel *NextVoxel = Voxels + TopIndex; + if ( !(NextVoxel->Flags&Voxel_Filled) || TransparencyIncreases(Voxel, NextVoxel)) + { + Voxel->Flags |= Voxel_TopFace; + } + } + if ( BottomIndex >= 0 && BottomIndex < MaxIndex ) + { + voxel *NextVoxel = Voxels + BottomIndex; + if ( !(NextVoxel->Flags&Voxel_Filled) || TransparencyIncreases(Voxel, NextVoxel)) + { + Voxel->Flags |= Voxel_BottomFace; + } + } + + + if ( FrontIndex >= 0 && FrontIndex < MaxIndex ) + { + voxel *NextVoxel = Voxels + FrontIndex; + if ( !(NextVoxel->Flags&Voxel_Filled) || TransparencyIncreases(Voxel, NextVoxel)) + { + Voxel->Flags |= Voxel_FrontFace; + } + } + if ( BackIndex >= 0 && BackIndex < MaxIndex ) + { + voxel *NextVoxel = Voxels + BackIndex; + if ( !(NextVoxel->Flags&Voxel_Filled) || TransparencyIncreases(Voxel, NextVoxel)) + { + Voxel->Flags |= Voxel_BackFace; + } + } + + } + + } + + } + + } +} + +link_internal void +MarkBoundaryVoxels_NoExteriorFaces_( voxel *Voxels, chunk_dimension SrcChunkDim, chunk_dimension SrcChunkMin, chunk_dimension SrcChunkMax, @@ -902,7 +1062,8 @@ MarkBoundaryVoxels_NoExteriorFaces( voxel *Voxels, u8 NewColorMin = 0, u8 NewColorMax = 0 ) { - TIMED_FUNCTION(); + HISTOGRAM_FUNCTION(); + /* TIMED_FUNCTION(); */ auto MinDim = SrcChunkMin; auto MaxDim = Min(SrcChunkDim, SrcChunkMax); // SrcChunkMin+DestChunkDim+1 @@ -956,24 +1117,6 @@ MarkBoundaryVoxels_NoExteriorFaces( voxel *Voxels, Voxel->Flags |= Voxel_BackFace; } } - b32 IsExteriorVoxel = (Voxel->Flags & VoxelFaceMask) != 0; - - // If we marked the voxel, and it's getting uncovered, change it's - // color to the one we specified. - // - // This is basically a special-purpose hack to change the surface color - // of holes we create - /* if (Entropy) */ - /* { */ - /* if ( WasMarked && */ - /* WasExteriorVoxel == False && */ - /* IsExteriorVoxel == True) */ - /* { */ - /* u32 NewColor = RandomBetween((u32)NewColorMin, Entropy, (u32)NewColorMax+1); */ - /* Voxel->Color = SafeTruncateU8(NewColor); */ - /* } */ - /* UnSetFlag((voxel_flag*)&Voxel->Flags, Voxel_MarkBit); */ - /* } */ } } } @@ -1031,32 +1174,32 @@ DrawDebugVoxels( voxel *Voxels, if (Voxel->Flags & Voxel_RightFace) { RightFaceVertexData( V3(SrcP-SrcChunkMin), Diameter, VertexData); - BufferVertsDirect(DestGeometry, 6, VertexData, RightFaceNormalData, Materials); + BufferFaceData(DestGeometry, VertexData, RightFaceNormalData, Materials); } if (Voxel->Flags & Voxel_LeftFace) { LeftFaceVertexData( V3(SrcP-SrcChunkMin), Diameter, VertexData); - BufferVertsDirect(DestGeometry, 6, VertexData, LeftFaceNormalData, Materials); + BufferFaceData(DestGeometry, VertexData, LeftFaceNormalData, Materials); } if (Voxel->Flags & Voxel_BottomFace) { BottomFaceVertexData( V3(SrcP-SrcChunkMin), Diameter, VertexData); - BufferVertsDirect(DestGeometry, 6, VertexData, BottomFaceNormalData, Materials); + BufferFaceData(DestGeometry, VertexData, BottomFaceNormalData, Materials); } if (Voxel->Flags & Voxel_TopFace) { TopFaceVertexData( V3(SrcP-SrcChunkMin), Diameter, VertexData); - BufferVertsDirect(DestGeometry, 6, VertexData, TopFaceNormalData, Materials); + BufferFaceData(DestGeometry, VertexData, TopFaceNormalData, Materials); } if (Voxel->Flags & Voxel_FrontFace) { FrontFaceVertexData( V3(SrcP-SrcChunkMin), Diameter, VertexData); - BufferVertsDirect(DestGeometry, 6, VertexData, FrontFaceNormalData, Materials); + BufferFaceData(DestGeometry, VertexData, FrontFaceNormalData, Materials); } if (Voxel->Flags & Voxel_BackFace) { BackFaceVertexData( V3(SrcP-SrcChunkMin), Diameter, VertexData); - BufferVertsDirect(DestGeometry, 6, VertexData, BackFaceNormalData, Materials); + BufferFaceData(DestGeometry, VertexData, BackFaceNormalData, Materials); } } } @@ -1135,7 +1278,7 @@ Step(voxel *Voxels, v3i SrcDim, v3i StepDir, v3i StepShape, v3i *AtP, voxel_flag return Result; } -global_variable random_series ColorEntropy = {33453}; +/* global_variable random_series ColorEntropy = {33453}; */ link_internal v3 DoXStepping(voxel *Voxels, v3i SrcChunkDim, v3i SrcP, voxel_flag Face, u16 Color, u8 Transparency) @@ -1294,27 +1437,27 @@ BuildWorldChunkMesh_DebugVoxels( voxel *Voxels, { RightFaceVertexData( DestP, Diameter, VertexData); - BufferVertsDirect(DestGeometry, 6, VertexData, RightFaceNormalData, Materials); + BufferFaceData(DestGeometry, VertexData, RightFaceNormalData, Materials); } { LeftFaceVertexData( DestP, Diameter, VertexData); - BufferVertsDirect(DestGeometry, 6, VertexData, LeftFaceNormalData, Materials); + BufferFaceData(DestGeometry, VertexData, LeftFaceNormalData, Materials); } { BottomFaceVertexData( DestP, Diameter, VertexData); - BufferVertsDirect(DestGeometry, 6, VertexData, BottomFaceNormalData, Materials); + BufferFaceData(DestGeometry, VertexData, BottomFaceNormalData, Materials); } { TopFaceVertexData( DestP, Diameter, VertexData); - BufferVertsDirect(DestGeometry, 6, VertexData, TopFaceNormalData, Materials); + BufferFaceData(DestGeometry, VertexData, TopFaceNormalData, Materials); } { FrontFaceVertexData( DestP, Diameter, VertexData); - BufferVertsDirect(DestGeometry, 6, VertexData, FrontFaceNormalData, Materials); + BufferFaceData(DestGeometry, VertexData, FrontFaceNormalData, Materials); } { BackFaceVertexData( DestP, Diameter, VertexData); - BufferVertsDirect(DestGeometry, 6, VertexData, BackFaceNormalData, Materials); + BufferFaceData(DestGeometry, VertexData, BackFaceNormalData, Materials); } } TmpIndex++; @@ -1343,33 +1486,15 @@ BuildWorldChunkMeshFromMarkedVoxels_Greedy( voxel *Voxels, // entity models about 0 and rotation works properly. v3 VertexOffset = {}) { + /* HISTOGRAM_FUNCTION(); */ TIMED_FUNCTION(); - /* Assert(IsSet(SrcChunk, Chunk_VoxelsInitialized)); */ - /* Assert(IsSet(DestChunk, Chunk_VoxelsInitialized)); */ - - voxel_position rightVoxel; - voxel_position leftVoxel; - voxel_position topVoxel; - voxel_position botVoxel; - voxel_position frontVoxel; - voxel_position backVoxel; - - s32 rightVoxelReadIndex; - s32 leftVoxelReadIndex; - s32 topVoxelReadIndex; - s32 botVoxelReadIndex; - s32 frontVoxelReadIndex; - s32 backVoxelReadIndex; - v3 VertexData[VERTS_PER_FACE]; - /* v3 FaceColors[VERTS_PER_FACE]; */ - /* v2 TransEmiss[VERTS_PER_FACE]; */ matl Materials[VERTS_PER_FACE]; auto SrcMinP = SrcChunkMin; - auto MaxDim = Min(SrcChunkDim, SrcChunkMax); // SrcChunkMin+DestChunkDim+1 + auto MaxDim = Min(SrcChunkDim, SrcChunkMax); auto TmpDim = MaxDim-SrcMinP; @@ -1396,7 +1521,7 @@ BuildWorldChunkMeshFromMarkedVoxels_Greedy( voxel *Voxels, { voxel_position SrcP = SrcMinP + Voxel_Position(xIndex, yIndex, zIndex); s32 SrcIndex = GetIndex(SrcP, SrcChunkDim); - Assert(TmpIndex < TmpVol); + /* Assert(TmpIndex < TmpVol); */ TempVoxels[TmpIndex] = Voxels[SrcIndex]; TmpIndex++; } @@ -1405,17 +1530,18 @@ BuildWorldChunkMeshFromMarkedVoxels_Greedy( voxel *Voxels, Assert(TmpIndex == TmpVol); + s32 Index = 0; for ( s32 z = 0; z < TmpDim.z ; ++z ) { for ( s32 y = 0; y < TmpDim.y ; ++y ) { for ( s32 x = 0; x < TmpDim.x ; ++x ) { - voxel_position TmpVoxP = Voxel_Position(x,y,z); - s32 Index = GetIndex(TmpVoxP, TmpDim); + v3i TmpVoxP = V3i(x,y,z); voxel *Voxel = TempVoxels + Index; - f32 Trans = (f32)Voxel->Transparency / 255.f; + f32 Trans = f32(Voxel->Transparency) / 255.f; + v3 Color = GetColorData(Voxel->Color); FillArray(VertexMaterial(Color, Trans, 0.f), Materials, VERTS_PER_FACE); @@ -1429,40 +1555,42 @@ BuildWorldChunkMeshFromMarkedVoxels_Greedy( voxel *Voxels, { v3 Dim = DoXStepping(TempVoxels, TmpDim, TmpVoxP, Voxel_RightFace, Voxel->Color, Voxel->Transparency); RightFaceVertexData( V3(TmpVoxP)+VertexOffset, Dim, VertexData); - BufferVertsDirect(Dest, 6, VertexData, RightFaceNormalData, Materials); + BufferFaceData(Dest, VertexData, RightFaceNormalData, Materials); } if (Voxel->Flags & Voxel_LeftFace) { v3 Dim = DoXStepping(TempVoxels, TmpDim, TmpVoxP, Voxel_LeftFace, Voxel->Color, Voxel->Transparency); LeftFaceVertexData( V3(TmpVoxP)+VertexOffset, Dim, VertexData); - BufferVertsDirect(Dest, 6, VertexData, LeftFaceNormalData, Materials); + BufferFaceData(Dest, VertexData, LeftFaceNormalData, Materials); } if (Voxel->Flags & Voxel_BottomFace) { v3 Dim = DoZStepping(TempVoxels, TmpDim, TmpVoxP, Voxel_BottomFace, Voxel->Color, Voxel->Transparency); BottomFaceVertexData( V3(TmpVoxP)+VertexOffset, Dim, VertexData); - BufferVertsDirect(Dest, 6, VertexData, BottomFaceNormalData, Materials); + BufferFaceData(Dest, VertexData, BottomFaceNormalData, Materials); } if (Voxel->Flags & Voxel_TopFace) { v3 Dim = DoZStepping(TempVoxels, TmpDim, TmpVoxP, Voxel_TopFace, Voxel->Color, Voxel->Transparency); TopFaceVertexData( V3(TmpVoxP)+VertexOffset, Dim, VertexData); - BufferVertsDirect(Dest, 6, VertexData, TopFaceNormalData, Materials); + BufferFaceData(Dest, VertexData, TopFaceNormalData, Materials); } if (Voxel->Flags & Voxel_FrontFace) { v3 Dim = DoYStepping(TempVoxels, TmpDim, TmpVoxP, Voxel_FrontFace, Voxel->Color, Voxel->Transparency); FrontFaceVertexData( V3(TmpVoxP)+VertexOffset, Dim, VertexData); - BufferVertsDirect(Dest, 6, VertexData, FrontFaceNormalData, Materials); + BufferFaceData(Dest, VertexData, FrontFaceNormalData, Materials); } if (Voxel->Flags & Voxel_BackFace) { v3 Dim = DoYStepping(TempVoxels, TmpDim, TmpVoxP, Voxel_BackFace, Voxel->Color, Voxel->Transparency); BackFaceVertexData( V3(TmpVoxP)+VertexOffset, Dim, VertexData); - BufferVertsDirect(Dest, 6, VertexData, BackFaceNormalData, Materials); + BufferFaceData(Dest, VertexData, BackFaceNormalData, Materials); } } + + ++Index; } } } @@ -1677,13 +1805,13 @@ BuildMipMesh( voxel *Voxels, { v3 Dim = DoXStepping(FilterVoxels, FilterDim, TmpVoxP, Voxel_RightFace, Voxel->Color, Voxel->Transparency); RightFaceVertexData( V3(ActualP)*MipLevel, Dim*MipLevel, VertexData); - BufferVertsDirect(DestGeometry, 6, VertexData, RightFaceNormalData, Materials); + BufferFaceData(DestGeometry, VertexData, RightFaceNormalData, Materials); } if (Voxel->Flags & Voxel_LeftFace) { v3 Dim = DoXStepping(FilterVoxels, FilterDim, TmpVoxP, Voxel_LeftFace, Voxel->Color, Voxel->Transparency); LeftFaceVertexData( V3(ActualP)*MipLevel, Dim*MipLevel, VertexData); - BufferVertsDirect(DestGeometry, 6, VertexData, LeftFaceNormalData, Materials); + BufferFaceData(DestGeometry, VertexData, LeftFaceNormalData, Materials); } @@ -1691,13 +1819,13 @@ BuildMipMesh( voxel *Voxels, { v3 Dim = DoZStepping(FilterVoxels, FilterDim, TmpVoxP, Voxel_BottomFace, Voxel->Color, Voxel->Transparency); BottomFaceVertexData( V3(ActualP)*MipLevel, Dim*MipLevel, VertexData); - BufferVertsDirect(DestGeometry, 6, VertexData, BottomFaceNormalData, Materials); + BufferFaceData(DestGeometry, VertexData, BottomFaceNormalData, Materials); } if (Voxel->Flags & Voxel_TopFace) { v3 Dim = DoZStepping(FilterVoxels, FilterDim, TmpVoxP, Voxel_TopFace, Voxel->Color, Voxel->Transparency); TopFaceVertexData( V3(ActualP)*MipLevel, Dim*MipLevel, VertexData); - BufferVertsDirect(DestGeometry, 6, VertexData, TopFaceNormalData, Materials); + BufferFaceData(DestGeometry, VertexData, TopFaceNormalData, Materials); } @@ -1705,13 +1833,13 @@ BuildMipMesh( voxel *Voxels, { v3 Dim = DoYStepping(FilterVoxels, FilterDim, TmpVoxP, Voxel_FrontFace, Voxel->Color, Voxel->Transparency); FrontFaceVertexData( V3(ActualP)*MipLevel, Dim*MipLevel, VertexData); - BufferVertsDirect(DestGeometry, 6, VertexData, FrontFaceNormalData, Materials); + BufferFaceData(DestGeometry, VertexData, FrontFaceNormalData, Materials); } if (Voxel->Flags & Voxel_BackFace) { v3 Dim = DoYStepping(FilterVoxels, FilterDim, TmpVoxP, Voxel_BackFace, Voxel->Color, Voxel->Transparency); BackFaceVertexData( V3(ActualP)*MipLevel, Dim*MipLevel, VertexData); - BufferVertsDirect(DestGeometry, 6, VertexData, BackFaceNormalData, Materials); + BufferFaceData(DestGeometry, VertexData, BackFaceNormalData, Materials); } } } @@ -1776,8 +1904,12 @@ BuildWorldChunkMeshFromMarkedVoxels_Naieve( voxel *Voxels, // TODO(Jesse): This copy could be avoided in multiple ways, and should be. /* FillColorArray(Voxel->Color, FaceColors, ColorPallette, VERTS_PER_FACE); */ +#if VOXEL_DEBUG_COLOR + v3 Color = Abs(Voxel->DebugColor); +#else v3 Color = GetColorData(Voxel->Color); - /* v3 Color = Voxel->DebugColor; */ +#endif + f32 Trans = (f32)Voxel->Transparency / 255.f; FillArray(VertexMaterial(Color, Trans, 0.f), Materials, VERTS_PER_FACE); @@ -1789,32 +1921,32 @@ BuildWorldChunkMeshFromMarkedVoxels_Naieve( voxel *Voxels, if (Voxel->Flags & Voxel_RightFace) { RightFaceVertexData( V3(DestP-SrcChunkMin), Diameter, VertexData); - BufferVertsDirect(Dest, 6, VertexData, RightFaceNormalData, Materials); + BufferFaceData(Dest, VertexData, RightFaceNormalData, Materials); } if (Voxel->Flags & Voxel_LeftFace) { LeftFaceVertexData( V3(DestP-SrcChunkMin), Diameter, VertexData); - BufferVertsDirect(Dest, 6, VertexData, LeftFaceNormalData, Materials); + BufferFaceData(Dest, VertexData, LeftFaceNormalData, Materials); } if (Voxel->Flags & Voxel_BottomFace) { BottomFaceVertexData( V3(DestP-SrcChunkMin), Diameter, VertexData); - BufferVertsDirect(Dest, 6, VertexData, BottomFaceNormalData, Materials); + BufferFaceData(Dest, VertexData, BottomFaceNormalData, Materials); } if (Voxel->Flags & Voxel_TopFace) { TopFaceVertexData( V3(DestP-SrcChunkMin), Diameter, VertexData); - BufferVertsDirect(Dest, 6, VertexData, TopFaceNormalData, Materials); + BufferFaceData(Dest, VertexData, TopFaceNormalData, Materials); } if (Voxel->Flags & Voxel_FrontFace) { FrontFaceVertexData( V3(DestP-SrcChunkMin), Diameter, VertexData); - BufferVertsDirect(Dest, 6, VertexData, FrontFaceNormalData, Materials); + BufferFaceData(Dest, VertexData, FrontFaceNormalData, Materials); } if (Voxel->Flags & Voxel_BackFace) { BackFaceVertexData( V3(DestP-SrcChunkMin), Diameter, VertexData); - BufferVertsDirect(Dest, 6, VertexData, BackFaceNormalData, Materials); + BufferFaceData(Dest, VertexData, BackFaceNormalData, Materials); } } } @@ -1907,32 +2039,32 @@ BuildWorldChunkMesh_Direct( voxel *Voxels, if ( !IsInsideDim( VoxDim, rightVoxel) || NotFilled( Voxels, rightVoxel, VoxDim) ) { RightFaceVertexData( V3(DestP-SrcChunkMin), Diameter, VertexData); - BufferVertsDirect(DestGeometry, 6, VertexData, RightFaceNormalData, Materials); + BufferFaceData(DestGeometry, VertexData, RightFaceNormalData, Materials); } if ( !IsInsideDim( VoxDim, leftVoxel) || NotFilled( Voxels, leftVoxel, VoxDim) ) { LeftFaceVertexData( V3(DestP-SrcChunkMin), Diameter, VertexData); - BufferVertsDirect(DestGeometry, 6, VertexData, LeftFaceNormalData, Materials); + BufferFaceData(DestGeometry, VertexData, LeftFaceNormalData, Materials); } if ( !IsInsideDim( VoxDim, botVoxel) || NotFilled( Voxels, botVoxel, VoxDim) ) { BottomFaceVertexData( V3(DestP-SrcChunkMin), Diameter, VertexData); - BufferVertsDirect(DestGeometry, 6, VertexData, BottomFaceNormalData, Materials); + BufferFaceData(DestGeometry, VertexData, BottomFaceNormalData, Materials); } if ( !IsInsideDim( VoxDim, topVoxel) || NotFilled( Voxels, topVoxel, VoxDim) ) { TopFaceVertexData( V3(DestP-SrcChunkMin), Diameter, VertexData); - BufferVertsDirect(DestGeometry, 6, VertexData, TopFaceNormalData, Materials); + BufferFaceData(DestGeometry, VertexData, TopFaceNormalData, Materials); } if ( !IsInsideDim( VoxDim, frontVoxel) || NotFilled( Voxels, frontVoxel, VoxDim) ) { FrontFaceVertexData( V3(DestP-SrcChunkMin), Diameter, VertexData); - BufferVertsDirect(DestGeometry, 6, VertexData, FrontFaceNormalData, Materials); + BufferFaceData(DestGeometry, VertexData, FrontFaceNormalData, Materials); } if ( !IsInsideDim( VoxDim, backVoxel) || NotFilled( Voxels, backVoxel, VoxDim) ) { BackFaceVertexData( V3(DestP-SrcChunkMin), Diameter, VertexData); - BufferVertsDirect(DestGeometry, 6, VertexData, BackFaceNormalData, Materials); + BufferFaceData(DestGeometry, VertexData, BackFaceNormalData, Materials); } } } @@ -3279,8 +3411,11 @@ RebuildWorldChunkMesh(thread_local_state *Thread, world_chunk *Chunk, v3i MinOff if (MeshBit == MeshBit_Lod0) { +#if VOXEL_DEBUG_COLOR + BuildWorldChunkMeshFromMarkedVoxels_Naieve( Chunk->Voxels, Chunk->Dim, MinOffset, MaxOffset, TempMesh, 0); +#else BuildWorldChunkMeshFromMarkedVoxels_Greedy( Chunk->Voxels, Chunk->Dim, MinOffset, MaxOffset, TempMesh, 0, TempMem ); - /* BuildWorldChunkMeshFromMarkedVoxels_Naieve( Chunk->Voxels, Chunk->Dim, {}, Chunk->Dim, TempMesh, 0); */ +#endif } else { @@ -3372,19 +3507,46 @@ InitializeChunkWithNoise( chunk_init_callback NoiseCallback, #else u32 SyntheticChunkSum = NoiseCallback( Thread->PerlinNoise, - SyntheticChunk, SynChunkDim, Global_ChunkApronMinDim, + SyntheticChunk, SynChunkDim, -1*Global_ChunkApronMinDim, GRASS_GREEN, Frequency, Amplititude, zMin, WorldChunkDim, UserData ); + Assert(SyntheticChunk->Dim == SynChunkDim); + +#if 1 && VOXEL_DEBUG_COLOR + DestChunk->NoiseValues = SyntheticChunk->NoiseValues; + DestChunk->NormalValues = SyntheticChunk->NormalValues; + +#if 1 + if (DestChunk->NoiseValues) + { + for ( s32 z = 0; z < SyntheticChunk->Dim.z; ++ z) + { + for ( s32 y = 0; y < SyntheticChunk->Dim.y; ++ y) + { + for ( s32 x = 0; x < SyntheticChunk->Dim.x; ++ x) + { + s32 NormalIndex = GetIndex(V3i(x,y,z), SyntheticChunk->Dim); + s32 NoiseIndex = GetIndex(V3i(x,y,z)+1, SyntheticChunk->Dim+2); + SyntheticChunk->Voxels[NormalIndex].DebugColor = SyntheticChunk->NormalValues[NormalIndex]; + SyntheticChunk->Voxels[NormalIndex].DebugNoiseValue = SyntheticChunk->NoiseValues[NoiseIndex]; + } + } + } + } +#endif + +#endif + MarkBoundaryVoxels_NoExteriorFaces(SyntheticChunk->Voxels, SynChunkDim, {}, SynChunkDim); CopyChunkOffset(SyntheticChunk, SynChunkDim, DestChunk, WorldChunkDim, Global_ChunkApronMinDim); + #endif // NOTE(Jesse): You can use this for debug, but it doesn't work if you change it to NoExteriorFaces /* MarkBoundaryVoxels_MakeExteriorFaces(DestChunk->Voxels, WorldChunkDim, {}, WorldChunkDim); */ - FullBarrier; SetFlag(DestChunk, Chunk_VoxelsInitialized); @@ -3786,7 +3948,7 @@ QueueWorldUpdateForRegion(engine_resources *Engine, world_update_op_mode Mode, w /* } */ /* world_position Delta = Max(MaxP.WorldP - MinP.WorldP, World_Position(1)); */ - world_position Delta = MaxP.WorldP - MinP.WorldP + 1; + v3i Delta = MaxP.WorldP - MinP.WorldP + 1; u32 TotalChunkCount = Abs(Volume(Delta)); // TODO(Jesse)(leak): Each one of these gets leaked at the moment @@ -3870,7 +4032,7 @@ DoWorldUpdate(work_queue *Queue, world *World, thread_local_state *Thread, work_ { TIMED_FUNCTION(); - random_series Entropy = {43246}; + random_series ColorEntropy = {4654376543246}; world_update_op_mode Mode = Job->Mode; world_update_op_mode_modifier Modifier = Job->Modifier; @@ -3904,8 +4066,11 @@ DoWorldUpdate(work_queue *Queue, world *World, thread_local_state *Thread, work_ voxel *CopiedVoxels = Allocate(voxel, Thread->PermMemory, TotalVoxels); - voxel UnsetVoxel = { 0xff, 0xff, 0xffff}; - /* voxel UnsetVoxel = { 0xff, 0xff, 0xffff, {}, {}}; */ +#if VOXEL_DEBUG_COLOR + voxel UnsetVoxel = { 0xff, 0xff, 0xffff, {}, {}}; +#else + voxel UnsetVoxel = { 0xff, 0xff, 0xffff }; +#endif for (u32 VoxelIndex = 0; VoxelIndex < TotalVoxels; ++VoxelIndex) { CopiedVoxels[VoxelIndex] = UnsetVoxel; } v3i SimSpaceQueryMinP = SimSpaceQueryAABB.Min; @@ -4082,7 +4247,7 @@ DoWorldUpdate(work_queue *Queue, world *World, thread_local_state *Thread, work_ { if (V->Flags & Voxel_Filled) { - V->Color = SafeTruncateU8(RandomBetween((u32)NewColorMin, &Entropy, (u32)NewColorMax+1)); + V->Color = SafeTruncateU8(RandomBetween((u32)NewColorMin, &ColorEntropy, (u32)NewColorMax+1)); } } @@ -4176,7 +4341,11 @@ DoWorldUpdate(work_queue *Queue, world *World, thread_local_state *Thread, work_ case WorldUpdateOperationMode_Additive: { +#if VOXEL_DEBUG_COLOR + NewVoxelValue = { Voxel_Filled, NewTransparency, NewColor, {}, {}}; +#else NewVoxelValue = { Voxel_Filled, NewTransparency, NewColor}; +#endif DimIterator(x, y, z, SimSpaceQueryDim) { v3i SimRelVoxP = V3i(x,y,z); @@ -4267,15 +4436,14 @@ DoWorldUpdate(work_queue *Queue, world *World, thread_local_state *Thread, work_ if (Asset) { UnlockAsset(GetEngineResources(), Asset); Asset = 0; } } break; } - } } // NOTE(Jesse): We can actually do the entire dim here, but it's probably // better (faster) to just do what we actually need to - MarkBoundaryVoxels_NoExteriorFaces( CopiedVoxels, QueryDim, {{1,1,1}}, QueryDim-1, &Entropy, GREY_5, GREY_7); - /* MarkBoundaryVoxels_NoExteriorFaces( CopiedVoxels, QueryDim, {}, QueryDim, &Entropy, GREY_5, GREY_7); */ + MarkBoundaryVoxels_NoExteriorFaces( CopiedVoxels, QueryDim, {{1,1,1}}, QueryDim-1, &ColorEntropy, GREY_5, GREY_7); + /* MarkBoundaryVoxels_NoExteriorFaces( CopiedVoxels, QueryDim, {}, QueryDim, &ColorEntropy, GREY_5, GREY_7); */ /* MarkBoundaryVoxels_MakeExteriorFaces( CopiedVoxels, QueryDim, {{1,1,1}}, QueryDim-1); */ /* MarkBoundaryVoxels_MakeExteriorFaces( CopiedVoxels, QueryDim, {}, QueryDim); */ @@ -4311,30 +4479,37 @@ DoWorldUpdate(work_queue *Queue, world *World, thread_local_state *Thread, work_ Assert(Index < TotalVoxels); Assert(CopiedVoxels[Index] != UnsetVoxel); - // nochicken turn asserts back on Assert( (V->Flags & Voxel_MarkBit) == 0); +#if VOXEL_DEBUG_COLOR + V->Flags = CopiedVoxels[Index].Flags; + V->Color = CopiedVoxels[Index].Color; + V->Transparency = CopiedVoxels[Index].Transparency; +#else *V = CopiedVoxels[Index]; +#endif Assert( (V->Flags & Voxel_MarkBit) == 0); } } } - } // DEBUG CODE - untextured_3d_geometry_buffer *DebugMesh = {}; + untextured_3d_geometry_buffer *DebugMesh = &GetEngineDebug()->WorldEditDebugMesh; #define DEBUG_VIEW_WORLD_UPDATE 0 #if DEBUG_VIEW_WORLD_UPDATE // TODO(Jesse): Need to copy the voxels because the Greedy thing blows away // the face flags as it does the traversal. - NotImplemented; + /* NotImplemented; */ - auto DebugMesh = AllocateMesh(Thread->PermMemory, (u32)Kilobytes(64*32)); - // GetMeshForChunk(&EngineResources->MeshFreelist, Thread->PermMemory); - BuildWorldChunkMeshFromMarkedVoxels_Greedy( CopiedVoxels, QueryDim, {}, QueryDim, DebugMesh ); - /* BuildWorldChunkMeshFromMarkedVoxels_Naieve( CopiedVoxels, QueryDim, {}, QueryDim, DebugMesh ); */ + chunk_data CD = { Chunk_VoxelsInitialized, QueryDim, CopiedVoxels, 0 }; + vox_data Vox = {&CD}; +#if VOXEL_DEBUG_COLOR + BuildWorldChunkMeshFromMarkedVoxels_Naieve( CopiedVoxels, QueryDim, {}, QueryDim, DebugMesh ); +#else + BuildWorldChunkMeshFromMarkedVoxels_Greedy( &Vox, DebugMesh, 0, GetTranArena()); +#endif /* aabb QueryAABB = AABBMinMax( {}, V3i(7.f + Radius*2.f) ); */ @@ -4342,21 +4517,12 @@ DoWorldUpdate(work_queue *Queue, world *World, thread_local_state *Thread, work_ DEBUG_DrawAABB(DebugMesh, AABBMinDim(V3(-1), V3(2)), PINK); - world_chunk *TempChunk = AllocateWorldChunk(Thread->PermMemory, MinP.WorldP, QueryDim); - picked_world_chunk *PickedChunk = Allocate(picked_world_chunk, Thread->PermMemory, 1); - PickedChunk->Chunk = TempChunk; - - if (untextured_3d_geometry_buffer *Buf = AtomicReplaceMesh( &TempChunk->Meshes, MeshBit_Main, DebugMesh, DebugMesh->Timestamp)) - { - Leak("Leaking mesh"); - }; +/* world_chunk *TempChunk = AllocateWorldChunk(Thread->PermMemory, MinP.WorldP, QueryDim); */ +/* picked_world_chunk *PickedChunk = Allocate(picked_world_chunk, Thread->PermMemory, 1); */ +/* PickedChunk->Chunk = TempChunk; */ -#if BONSAI_DEBUG_SYSTEM_API - AtomicWrite((volatile void **)&GetDebugState()->PickedChunk, (void*) PickedChunk); -#endif - - v3 QueryRelLocation = V3(SimSphereP) - SimSpaceQueryMinP; - DrawVoxel_MinDim(DebugMesh, QueryRelLocation, V4(1,0,0,1), V3(1.f)); + /* v3 QueryRelLocation = V3(SimSphereP) - SimSpaceQueryMinP; */ + /* DrawVoxel_MinDim(DebugMesh, QueryRelLocation, V4(1,0,0,1), V3(1.f)); */ #endif voxel_position_cursor StandingSpots = V3iCursor(ChunkCount*WORLD_CHUNK_STANDING_SPOT_COUNT, Thread->TempMemory); @@ -4380,7 +4546,7 @@ DoWorldUpdate(work_queue *Queue, world *World, thread_local_state *Thread, work_ rect3i SimSpaceChunkAABB = GetSimSpaceAABBi(World, Chunk); auto QueryRelChunkAABB = SimSpaceChunkAABB - SimSpaceQueryMinP; #if DEBUG_VIEW_WORLD_UPDATE - DEBUG_DrawAABB(DebugMesh, QueryRelChunkAABB, RED); + DEBUG_DrawAABB(DebugMesh, &QueryRelChunkAABB, RED); #endif /* DebugLine("Start StandingSpotCount(%d)/(%d)", AtElements(&Chunk->StandingSpots), Count(&Chunk->StandingSpots)); */ @@ -4453,7 +4619,7 @@ DoWorldUpdate(work_queue *Queue, world *World, thread_local_state *Thread, work_ if (!Skip) { #if DEBUG_VIEW_WORLD_UPDATE - DrawStandingSpot(Mesh, V3(QueryRelSpot), V3(Global_StandingSpotDim), TEAL, DEFAULT_STANDING_SPOT_THICKNESS*1.5f); + DrawStandingSpot(DebugMesh, V3(QueryRelSpot), V3(Global_StandingSpotDim), TEAL, DEFAULT_STANDING_SPOT_THICKNESS*1.5f); #endif if ( Contains(SimSpaceChunkAABB, SimSpot) ) { @@ -4895,6 +5061,24 @@ MousePickVoxel(engine_resources *Resources) return Result; } +link_internal voxel * +TryGetVoxelPointer(world *World, cp Pos) +{ + voxel *Result = 0; + + world_chunk *Chunk = GetWorldChunkFromHashtable(World, Pos.WorldP); + if (Chunk) + { + s32 Index = TryGetIndex(V3i(Pos.Offset), Chunk->Dim); + if (Index > -1) + { + Result = Chunk->Voxels + Index; + } + } + + return Result; +} + link_internal voxel * GetVoxelPointer(picked_voxel *Pick, picked_voxel_position Pos) { diff --git a/src/engine/world_chunk.h b/src/engine/world_chunk.h index 8b6feeb60..dbdcdaab8 100644 --- a/src/engine/world_chunk.h +++ b/src/engine/world_chunk.h @@ -102,6 +102,8 @@ CAssert(Voxel_MarkBit < u8_MAX); global_variable u8 VoxelFaceMask = Voxel_LeftFace | Voxel_RightFace | Voxel_TopFace | Voxel_BottomFace | Voxel_FrontFace | Voxel_BackFace; +#define VOXEL_DEBUG_COLOR (0) + // TODO(Jesse): Surely we can compress this.. but do we care? struct voxel { @@ -110,8 +112,12 @@ struct voxel u16 Color; /* v3 Derivs; */ - /* v3 DebugColor; */ +#if VOXEL_DEBUG_COLOR + v3 DebugColor; poof(@no_serialize) + f32 DebugNoiseValue; poof(@no_serialize) +#endif }; +/* CAssert(sizeof(voxel) == 8); */ struct voxel_lighting { @@ -379,7 +385,13 @@ struct world_chunk // considered for collision detection. entity_ptr_block_array Entities; - u8 _Pad1[32]; +#if VOXEL_DEBUG_COLOR + f32 *NoiseValues; poof(@no_serialize @array_length(Volume(Element->Dim))) + v3 *NormalValues; poof(@no_serialize @array_length(Volume(Element->Dim))) + u8 _Pad1[16]; poof(@no_serialize) +#else + u8 _Pad1[32]; poof(@no_serialize) +#endif }; // TODO(Jesse, id: 87, tags: speed, cache_friendly): Re-enable this // @world-chunk-cache-line-size @@ -597,6 +609,7 @@ global_variable v3i Global_ChunkApronDim = V3i(2,2,4); global_variable v3i Global_ChunkApronMinDim = V3i(1,1,1); global_variable v3i Global_ChunkApronMaxDim = V3i(1,1,3); + // NOTE(Jesse): Unfortunately C++ is too braindead to do this at compile time // (even if you mark the variables as const). I also tried all kinds of // ridiculous const-casting trickery to no avail, so I'm doing it at runtime