diff --git a/Editor/ComponentsWindow.cpp b/Editor/ComponentsWindow.cpp index 4820f2086..c01bc7522 100644 --- a/Editor/ComponentsWindow.cpp +++ b/Editor/ComponentsWindow.cpp @@ -66,8 +66,8 @@ void ComponentsWindow::Create(EditorComponent* _editor) newComponentCombo.AddItem("Force Field " ICON_FORCE, 13); newComponentCombo.AddItem("Animation " ICON_ANIMATION, 14); newComponentCombo.AddItem("Script " ICON_SCRIPT, 15); - newComponentCombo.AddItem("Rigid Body " ICON_RIGIDBODY, 16); - newComponentCombo.AddItem("Soft Body " ICON_SOFTBODY, 17); + newComponentCombo.AddItem("Rigid Body Physics " ICON_RIGIDBODY, 16); + newComponentCombo.AddItem("Soft Body Physics " ICON_SOFTBODY, 17); newComponentCombo.AddItem("Collider " ICON_COLLIDER, 18); newComponentCombo.AddItem("Camera " ICON_CAMERA, 20); newComponentCombo.AddItem("Object " ICON_OBJECT, 21); diff --git a/Editor/Editor_SOURCE.vcxitems b/Editor/Editor_SOURCE.vcxitems index 8dbe8f2e2..8c12175ac 100644 --- a/Editor/Editor_SOURCE.vcxitems +++ b/Editor/Editor_SOURCE.vcxitems @@ -192,15 +192,7 @@ true true - - true - true - - - true - true - - + true true @@ -244,33 +236,6 @@ - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - - - true - true - + \ No newline at end of file diff --git a/Editor/Editor_SOURCE.vcxitems.filters b/Editor/Editor_SOURCE.vcxitems.filters index d76dbcbcf..1784e052e 100644 --- a/Editor/Editor_SOURCE.vcxitems.filters +++ b/Editor/Editor_SOURCE.vcxitems.filters @@ -135,16 +135,10 @@ - - terrain - - - terrain - - - terrain - + + terrain + @@ -184,25 +178,7 @@ - - terrain - - - terrain - - - terrain - - - terrain - - - terrain - - - terrain - - + terrain diff --git a/Editor/ObjectWindow.cpp b/Editor/ObjectWindow.cpp index ea84fef74..56bc2e174 100644 --- a/Editor/ObjectWindow.cpp +++ b/Editor/ObjectWindow.cpp @@ -369,6 +369,19 @@ void ObjectWindow::Create(EditorComponent* _editor) }); AddWidget(&lodSlider); + drawdistanceSlider.Create(0, 1000, 1, 10000, "Draw Distance: "); + drawdistanceSlider.SetTooltip("Specify the draw distance of the object"); + drawdistanceSlider.SetSize(XMFLOAT2(wid, hei)); + drawdistanceSlider.SetPos(XMFLOAT2(x, y += step)); + drawdistanceSlider.OnSlide([&](wi::gui::EventArgs args) { + ObjectComponent* object = editor->GetCurrentScene().objects.GetComponent(entity); + if (object != nullptr) + { + object->draw_distance = args.fValue; + } + }); + AddWidget(&drawdistanceSlider); + y += step; @@ -597,6 +610,7 @@ void ObjectWindow::SetEntity(Entity entity) cascadeMaskSlider.SetValue((float)object->cascadeMask); ditherSlider.SetValue(object->GetTransparency()); lodSlider.SetValue(object->lod_distance_multiplier); + drawdistanceSlider.SetValue(object->draw_distance); switch (colorComboBox.GetSelected()) { @@ -667,6 +681,7 @@ void ObjectWindow::ResizeLayout() add(ditherSlider); add(cascadeMaskSlider); add(lodSlider); + add(drawdistanceSlider); add(colorComboBox); add_fullwidth(colorPicker); add(lightmapResolutionSlider); diff --git a/Editor/ObjectWindow.h b/Editor/ObjectWindow.h index 712f08a50..bf3124671 100644 --- a/Editor/ObjectWindow.h +++ b/Editor/ObjectWindow.h @@ -18,6 +18,7 @@ public: wi::gui::Slider ditherSlider; wi::gui::Slider cascadeMaskSlider; wi::gui::Slider lodSlider; + wi::gui::Slider drawdistanceSlider; wi::gui::ComboBox colorComboBox; wi::gui::ColorPicker colorPicker; diff --git a/Editor/RigidBodyWindow.cpp b/Editor/RigidBodyWindow.cpp index 2cabd0328..3db6fe075 100644 --- a/Editor/RigidBodyWindow.cpp +++ b/Editor/RigidBodyWindow.cpp @@ -332,32 +332,7 @@ void RigidBodyWindow::SetEntity(Entity entity) kinematicCheckBox.SetCheck(physicsComponent->IsKinematic()); disabledeactivationCheckBox.SetCheck(physicsComponent->IsDisableDeactivation()); - if (physicsComponent->shape == RigidBodyPhysicsComponent::CollisionShape::BOX) - { - collisionShapeComboBox.SetSelected(1); - } - else if (physicsComponent->shape == RigidBodyPhysicsComponent::CollisionShape::SPHERE) - { - collisionShapeComboBox.SetSelected(2); - } - else if (physicsComponent->shape == RigidBodyPhysicsComponent::CollisionShape::CAPSULE) - { - collisionShapeComboBox.SetSelected(3); - } - else if (physicsComponent->shape == RigidBodyPhysicsComponent::CollisionShape::CONVEX_HULL) - { - collisionShapeComboBox.SetSelected(4); - } - else if (physicsComponent->shape == RigidBodyPhysicsComponent::CollisionShape::TRIANGLE_MESH) - { - collisionShapeComboBox.SetSelected(5); - } - } - else - { - collisionShapeComboBox.SetSelected(0); - kinematicCheckBox.SetCheck(false); - disabledeactivationCheckBox.SetCheck(false); + collisionShapeComboBox.SetSelectedByUserdata((uint64_t)physicsComponent->shape); } } diff --git a/Editor/TerrainWindow.cpp b/Editor/TerrainWindow.cpp index d7a2f7ffa..ce71dba82 100644 --- a/Editor/TerrainWindow.cpp +++ b/Editor/TerrainWindow.cpp @@ -296,6 +296,29 @@ void TerrainWindow::Create(EditorComponent* _editor) float hei = 20; float wid = 120; + auto generate_callback = [&]() { + + terrain->SetCenterToCamEnabled(centerToCamCheckBox.GetCheck()); + terrain->SetRemovalEnabled(removalCheckBox.GetCheck()); + terrain->SetGrassEnabled(grassCheckBox.GetCheck()); + terrain->lod_multiplier = lodSlider.GetValue(); + terrain->texlod = texlodSlider.GetValue(); + terrain->generation = (int)generationSlider.GetValue(); + terrain->prop_generation = (int)propGenerationSlider.GetValue(); + terrain->physics_generation = (int)physicsGenerationSlider.GetValue(); + terrain->prop_density = propDensitySlider.GetValue(); + terrain->grass_density = grassDensitySlider.GetValue(); + terrain->chunk_scale = scaleSlider.GetValue(); + terrain->seed = (uint32_t)seedSlider.GetValue(); + terrain->bottomLevel = bottomLevelSlider.GetValue(); + terrain->topLevel = topLevelSlider.GetValue(); + terrain->region1 = region1Slider.GetValue(); + terrain->region2 = region2Slider.GetValue(); + terrain->region3 = region3Slider.GetValue(); + + terrain->SetGenerationStarted(false); + }; + centerToCamCheckBox.Create("Center to Cam: "); centerToCamCheckBox.SetTooltip("Automatically generate chunks around camera. This sets the center chunk to camera position."); centerToCamCheckBox.SetSize(XMFLOAT2(hei, hei)); @@ -326,6 +349,17 @@ void TerrainWindow::Create(EditorComponent* _editor) }); AddWidget(&grassCheckBox); + physicsCheckBox.Create("Physics: "); + physicsCheckBox.SetTooltip("Specify whether physics is enabled for newly generated terrain chunks."); + physicsCheckBox.SetSize(XMFLOAT2(hei, hei)); + physicsCheckBox.SetPos(XMFLOAT2(x, y += step)); + physicsCheckBox.SetCheck(true); + physicsCheckBox.OnClick([=](wi::gui::EventArgs args) { + terrain->SetPhysicsEnabled(args.bValue); + generate_callback(); + }); + AddWidget(&physicsCheckBox); + lodSlider.Create(0.0001f, 0.01f, 0.005f, 10000, "Mesh LOD Distance: "); lodSlider.SetTooltip("Set the LOD (Level Of Detail) distance multiplier.\nLow values increase LOD detail in distance"); lodSlider.SetSize(XMFLOAT2(wid, hei)); @@ -365,14 +399,23 @@ void TerrainWindow::Create(EditorComponent* _editor) }); AddWidget(&generationSlider); - propSlider.Create(0, 16, 10, 16, "Prop Distance: "); - propSlider.SetTooltip("How far out props will be generated (value is in number of chunks)"); - propSlider.SetSize(XMFLOAT2(wid, hei)); - propSlider.SetPos(XMFLOAT2(x, y += step)); - propSlider.OnSlide([this](wi::gui::EventArgs args) { + propGenerationSlider.Create(0, 16, 10, 16, "Prop Distance: "); + propGenerationSlider.SetTooltip("How far out props will be generated (value is in number of chunks)"); + propGenerationSlider.SetSize(XMFLOAT2(wid, hei)); + propGenerationSlider.SetPos(XMFLOAT2(x, y += step)); + propGenerationSlider.OnSlide([this](wi::gui::EventArgs args) { terrain->prop_generation = args.iValue; }); - AddWidget(&propSlider); + AddWidget(&propGenerationSlider); + + physicsGenerationSlider.Create(0, 16, 3, 16, "Physics Distance: "); + physicsGenerationSlider.SetTooltip("How far out physics meshes will be generated (value is in number of chunks)"); + physicsGenerationSlider.SetSize(XMFLOAT2(wid, hei)); + physicsGenerationSlider.SetPos(XMFLOAT2(x, y += step)); + physicsGenerationSlider.OnSlide([this](wi::gui::EventArgs args) { + terrain->physics_generation = args.iValue; + }); + AddWidget(&physicsGenerationSlider); propDensitySlider.Create(0, 10, 1, 1000, "Prop Density: "); propDensitySlider.SetTooltip("Modifies overall prop density."); @@ -392,28 +435,6 @@ void TerrainWindow::Create(EditorComponent* _editor) }); AddWidget(&grassDensitySlider); - auto generate_callback = [&]() { - - terrain->SetCenterToCamEnabled(centerToCamCheckBox.GetCheck()); - terrain->SetRemovalEnabled(removalCheckBox.GetCheck()); - terrain->SetGrassEnabled(grassCheckBox.GetCheck()); - terrain->lod_multiplier = lodSlider.GetValue(); - terrain->texlod = texlodSlider.GetValue(); - terrain->generation = (int)generationSlider.GetValue(); - terrain->prop_generation = (int)propSlider.GetValue(); - terrain->prop_density = propDensitySlider.GetValue(); - terrain->grass_density = grassDensitySlider.GetValue(); - terrain->chunk_scale = scaleSlider.GetValue(); - terrain->seed = (uint32_t)seedSlider.GetValue(); - terrain->bottomLevel = bottomLevelSlider.GetValue(); - terrain->topLevel = topLevelSlider.GetValue(); - terrain->region1 = region1Slider.GetValue(); - terrain->region2 = region2Slider.GetValue(); - terrain->region3 = region3Slider.GetValue(); - - terrain->SetGenerationStarted(false); - }; - presetCombo.Create("Preset: "); presetCombo.SetTooltip("Select a terrain preset"); presetCombo.SetSize(XMFLOAT2(wid, hei)); @@ -747,10 +768,12 @@ void TerrainWindow::SetEntity(Entity entity) centerToCamCheckBox.SetCheck(terrain->IsCenterToCamEnabled()); removalCheckBox.SetCheck(terrain->IsRemovalEnabled()); grassCheckBox.SetCheck(terrain->IsGrassEnabled()); + physicsCheckBox.SetCheck(terrain->IsPhysicsEnabled()); lodSlider.SetValue(terrain->lod_multiplier); texlodSlider.SetValue(terrain->texlod); generationSlider.SetValue((float)terrain->generation); - propSlider.SetValue((float)terrain->prop_generation); + propGenerationSlider.SetValue((float)terrain->prop_generation); + physicsGenerationSlider.SetValue((float)terrain->physics_generation); propDensitySlider.SetValue(terrain->prop_density); scaleSlider.SetValue(terrain->chunk_scale); seedSlider.SetValue((float)terrain->seed); @@ -836,12 +859,13 @@ void TerrainWindow::SetupAssets() terrain_preset.material_LowAltitude.CreateRenderData(); terrain_preset.material_HighAltitude.CreateRenderData(); terrain_preset.material_GrassParticle.CreateRenderData(); + + Scene props_scene; + wi::scene::LoadModel(props_scene, "terrain/props.wiscene"); + // Tree prop: { - Scene props_scene; - wi::scene::LoadModel(props_scene, "terrain/tree.wiscene"); wi::terrain::Prop& prop = terrain_preset.props.emplace_back(); - prop.name = "tree"; prop.min_count_per_chunk = 0; prop.max_count_per_chunk = 10; prop.region = 0; @@ -853,25 +877,29 @@ void TerrainWindow::SetupAssets() prop.max_size = 8.0f; prop.min_y_offset = -0.5f; prop.max_y_offset = -0.5f; - prop.mesh_entity = props_scene.Entity_FindByName("tree_mesh"); - props_scene.impostors.Create(prop.mesh_entity).swapInDistance = 200; + Entity mesh_entity = props_scene.Entity_FindByName("tree_mesh"); + props_scene.impostors.Create(mesh_entity).swapInDistance = 200; Entity object_entity = props_scene.Entity_FindByName("tree_object"); ObjectComponent* object = props_scene.objects.GetComponent(object_entity); if (object != nullptr) { - prop.object = *object; - prop.object.lod_distance_multiplier = 0.05f; + object->lod_distance_multiplier = 0.05f; //prop.object.cascadeMask = 1; // they won't be rendered into the largest shadow cascade } + wi::Archive archive; + EntitySerializer seri; + props_scene.Entity_Serialize( + archive, + seri, + object_entity, + wi::scene::Scene::EntitySerializeFlags::RECURSIVE | wi::scene::Scene::EntitySerializeFlags::KEEP_INTERNAL_ENTITY_REFERENCES + ); + archive.WriteData(prop.data); props_scene.Entity_Remove(object_entity); // The objects will be placed by terrain generator, we don't need the default object that the scene has anymore - editor->GetCurrentScene().Merge(props_scene); } // Rock prop: { - Scene props_scene; - wi::scene::LoadModel(props_scene, "terrain/rock.wiscene"); wi::terrain::Prop& prop = terrain_preset.props.emplace_back(); - prop.name = "rock"; prop.min_count_per_chunk = 0; prop.max_count_per_chunk = 8; prop.region = 0; @@ -883,25 +911,29 @@ void TerrainWindow::SetupAssets() prop.max_size = 4.0f; prop.min_y_offset = -2; prop.max_y_offset = 0.5f; - prop.mesh_entity = props_scene.Entity_FindByName("rock_mesh"); + Entity mesh_entity = props_scene.Entity_FindByName("rock_mesh"); Entity object_entity = props_scene.Entity_FindByName("rock_object"); ObjectComponent* object = props_scene.objects.GetComponent(object_entity); if (object != nullptr) { - prop.object = *object; - prop.object.lod_distance_multiplier = 0.02f; - prop.object.cascadeMask = 1; // they won't be rendered into the largest shadow cascade - prop.object.draw_distance = 400; + object->lod_distance_multiplier = 0.02f; + object->cascadeMask = 1; // they won't be rendered into the largest shadow cascade + object->draw_distance = 400; } + wi::Archive archive; + EntitySerializer seri; + props_scene.Entity_Serialize( + archive, + seri, + object_entity, + wi::scene::Scene::EntitySerializeFlags::RECURSIVE | wi::scene::Scene::EntitySerializeFlags::KEEP_INTERNAL_ENTITY_REFERENCES + ); + archive.WriteData(prop.data); props_scene.Entity_Remove(object_entity); // The objects will be placed by terrain generator, we don't need the default object that the scene has anymore - editor->GetCurrentScene().Merge(props_scene); } // Bush prop: { - Scene props_scene; - wi::scene::LoadModel(props_scene, "terrain/bush.wiscene"); wi::terrain::Prop& prop = terrain_preset.props.emplace_back(); - prop.name = "bush"; prop.min_count_per_chunk = 0; prop.max_count_per_chunk = 10; prop.region = 0; @@ -913,20 +945,29 @@ void TerrainWindow::SetupAssets() prop.max_size = 1.5f; prop.min_y_offset = -1; prop.max_y_offset = 0; - prop.mesh_entity = props_scene.Entity_FindByName("bush_mesh"); + Entity mesh_entity = props_scene.Entity_FindByName("bush_mesh"); Entity object_entity = props_scene.Entity_FindByName("bush_object"); ObjectComponent* object = props_scene.objects.GetComponent(object_entity); if (object != nullptr) { - prop.object = *object; - prop.object.lod_distance_multiplier = 0.05f; - prop.object.cascadeMask = 1; // they won't be rendered into the largest shadow cascade - prop.object.draw_distance = 200; + object->lod_distance_multiplier = 0.05f; + object->cascadeMask = 1; // they won't be rendered into the largest shadow cascade + object->draw_distance = 200; } + wi::Archive archive; + EntitySerializer seri; + props_scene.Entity_Serialize( + archive, + seri, + object_entity, + wi::scene::Scene::EntitySerializeFlags::RECURSIVE | wi::scene::Scene::EntitySerializeFlags::KEEP_INTERNAL_ENTITY_REFERENCES + ); + archive.WriteData(prop.data); props_scene.Entity_Remove(object_entity); // The objects will be placed by terrain generator, we don't need the default object that the scene has anymore - editor->GetCurrentScene().Merge(props_scene); } + editor->GetCurrentScene().Merge(props_scene); + terrain = &terrain_preset; presetCombo.SetSelected(0); } @@ -984,13 +1025,15 @@ void TerrainWindow::ResizeLayout() widget.SetEnabled(true); }; - add_checkbox(centerToCamCheckBox); add_checkbox(removalCheckBox); + centerToCamCheckBox.SetPos(XMFLOAT2(removalCheckBox.GetPos().x - 100, removalCheckBox.GetPos().y)); add_checkbox(grassCheckBox); + physicsCheckBox.SetPos(XMFLOAT2(grassCheckBox.GetPos().x - 100, grassCheckBox.GetPos().y)); add(lodSlider); add(texlodSlider); add(generationSlider); - add(propSlider); + add(propGenerationSlider); + add(physicsGenerationSlider); add(propDensitySlider); add(grassDensitySlider); add(presetCombo); diff --git a/Editor/TerrainWindow.h b/Editor/TerrainWindow.h index 2673370a8..c885e9dcf 100644 --- a/Editor/TerrainWindow.h +++ b/Editor/TerrainWindow.h @@ -55,10 +55,12 @@ public: wi::gui::CheckBox centerToCamCheckBox; wi::gui::CheckBox removalCheckBox; wi::gui::CheckBox grassCheckBox; + wi::gui::CheckBox physicsCheckBox; wi::gui::Slider lodSlider; wi::gui::Slider texlodSlider; wi::gui::Slider generationSlider; - wi::gui::Slider propSlider; + wi::gui::Slider propGenerationSlider; + wi::gui::Slider physicsGenerationSlider; wi::gui::Slider propDensitySlider; wi::gui::Slider grassDensitySlider; wi::gui::ComboBox presetCombo; diff --git a/Editor/terrain/base-LICENSE.txt b/Editor/terrain/base-LICENSE.txt deleted file mode 100644 index 1b06d2c64..000000000 --- a/Editor/terrain/base-LICENSE.txt +++ /dev/null @@ -1,4 +0,0 @@ -ambientCG (ambientCG.com) -CC0 1.0 Public Domain Dedication (https://creativecommons.org/publicdomain/zero/1.0/) -Grass001 by ambientCG -https://ambientcg.com/a/Grass001 \ No newline at end of file diff --git a/Editor/terrain/bush-LICENSE.txt b/Editor/terrain/bush-LICENSE.txt deleted file mode 100644 index 666fa1848..000000000 --- a/Editor/terrain/bush-LICENSE.txt +++ /dev/null @@ -1 +0,0 @@ -https://www.cgtrader.com/free-3d-models/plant/bush/mediteranean-bush \ No newline at end of file diff --git a/Editor/terrain/bush.wiscene b/Editor/terrain/bush.wiscene deleted file mode 100644 index 97b337498..000000000 Binary files a/Editor/terrain/bush.wiscene and /dev/null differ diff --git a/Editor/terrain/high_altitude-LICENSE.txt b/Editor/terrain/high_altitude-LICENSE.txt deleted file mode 100644 index 1490a7370..000000000 --- a/Editor/terrain/high_altitude-LICENSE.txt +++ /dev/null @@ -1 +0,0 @@ -https://www.sharetextures.com/textures/ground/snow_ground_3/ \ No newline at end of file diff --git a/Editor/terrain/licenses.txt b/Editor/terrain/licenses.txt new file mode 100644 index 000000000..8cbade39e --- /dev/null +++ b/Editor/terrain/licenses.txt @@ -0,0 +1,26 @@ +Bush: +https://www.cgtrader.com/free-3d-models/plant/bush/mediteranean-bush + +Rock: +https://www.cgtrader.com/free-3d-models/plant/other/rocks-56c7a2d1-2e36-4b17-8d79-2a69ab29d860 + +Tree: +https://free3d.com/3d-model/tree02-35663.html + +Grass texture: +ambientCG (ambientCG.com) +CC0 1.0 Public Domain Dedication (https://creativecommons.org/publicdomain/zero/1.0/) +Grass001 by ambientCG +https://ambientcg.com/a/Grass001 + +Snow texture: +https://www.sharetextures.com/textures/ground/snow_ground_3/ + +Sand texture: +https://www.cgbookcase.com/textures/sandy-gravel-01/?source=3dassets.one + +Stone texture: +ambientCG (ambientCG.com) +CC0 1.0 Public Domain Dedication (https://creativecommons.org/publicdomain/zero/1.0/) +Rock048 by ambientCG +https://ambientcg.com/a/Rock048 diff --git a/Editor/terrain/low_altitude-LICENSE.txt b/Editor/terrain/low_altitude-LICENSE.txt deleted file mode 100644 index a755f4192..000000000 --- a/Editor/terrain/low_altitude-LICENSE.txt +++ /dev/null @@ -1 +0,0 @@ -https://www.cgbookcase.com/textures/sandy-gravel-01/?source=3dassets.one \ No newline at end of file diff --git a/Editor/terrain/tree.wiscene b/Editor/terrain/props.wiscene similarity index 58% rename from Editor/terrain/tree.wiscene rename to Editor/terrain/props.wiscene index 14f267114..9de676b49 100644 Binary files a/Editor/terrain/tree.wiscene and b/Editor/terrain/props.wiscene differ diff --git a/Editor/terrain/rock-LICENSE.txt b/Editor/terrain/rock-LICENSE.txt deleted file mode 100644 index 5189c99e3..000000000 --- a/Editor/terrain/rock-LICENSE.txt +++ /dev/null @@ -1 +0,0 @@ -https://www.cgtrader.com/free-3d-models/plant/other/rocks-56c7a2d1-2e36-4b17-8d79-2a69ab29d860 \ No newline at end of file diff --git a/Editor/terrain/rock.wiscene b/Editor/terrain/rock.wiscene deleted file mode 100644 index d193ebbe1..000000000 Binary files a/Editor/terrain/rock.wiscene and /dev/null differ diff --git a/Editor/terrain/slope-LICENSE.txt b/Editor/terrain/slope-LICENSE.txt deleted file mode 100644 index 42892115e..000000000 --- a/Editor/terrain/slope-LICENSE.txt +++ /dev/null @@ -1,4 +0,0 @@ -ambientCG (ambientCG.com) -CC0 1.0 Public Domain Dedication (https://creativecommons.org/publicdomain/zero/1.0/) -Rock048 by ambientCG -https://ambientcg.com/a/Rock048 \ No newline at end of file diff --git a/Editor/terrain/tree-LICENSE.txt b/Editor/terrain/tree-LICENSE.txt deleted file mode 100644 index bbc15ae1e..000000000 --- a/Editor/terrain/tree-LICENSE.txt +++ /dev/null @@ -1 +0,0 @@ -https://free3d.com/3d-model/tree02-35663.html \ No newline at end of file diff --git a/WickedEngine/wiArchive.h b/WickedEngine/wiArchive.h index 9f6589b77..6f2248b16 100644 --- a/WickedEngine/wiArchive.h +++ b/WickedEngine/wiArchive.h @@ -42,7 +42,9 @@ namespace wi Archive& operator=(const Archive&) = default; Archive& operator=(Archive&&) = default; + void WriteData(wi::vector& dest) const { dest.resize(pos); std::memcpy(dest.data(), data_ptr, pos); } const uint8_t* GetData() const { return data_ptr; } + size_t GetPos() const { return pos; } constexpr uint64_t GetVersion() const { return version; } constexpr bool IsReadMode() const { return readMode; } // This can set the archive into either read or write mode, and it will reset it's position diff --git a/WickedEngine/wiScene.cpp b/WickedEngine/wiScene.cpp index df458b261..9fa2407f8 100644 --- a/WickedEngine/wiScene.cpp +++ b/WickedEngine/wiScene.cpp @@ -2742,6 +2742,8 @@ namespace wi::scene for (uint32_t subsetIndex = first_subset; subsetIndex < last_subset; ++subsetIndex) { const MeshComponent::MeshSubset& subset = mesh.subsets[subsetIndex]; + if (materials.GetCount() <= subset.materialIndex) + continue; const MaterialComponent& material = materials[subset.materialIndex]; const uint32_t geometry_index = subsetIndex - first_subset; diff --git a/WickedEngine/wiScene.h b/WickedEngine/wiScene.h index 9ea38c056..68a614888 100644 --- a/WickedEngine/wiScene.h +++ b/WickedEngine/wiScene.h @@ -30,7 +30,7 @@ namespace wi::scene wi::ecs::ComponentManager& impostors = componentLibrary.Register("wi::scene::Scene::impostors"); wi::ecs::ComponentManager& objects = componentLibrary.Register("wi::scene::Scene::objects"); wi::ecs::ComponentManager& aabb_objects = componentLibrary.Register("wi::scene::Scene::aabb_objects"); - wi::ecs::ComponentManager& rigidbodies = componentLibrary.Register("wi::scene::Scene::rigidbodies"); + wi::ecs::ComponentManager& rigidbodies = componentLibrary.Register("wi::scene::Scene::rigidbodies", 1); // version = 1 wi::ecs::ComponentManager& softbodies = componentLibrary.Register("wi::scene::Scene::softbodies"); wi::ecs::ComponentManager& armatures = componentLibrary.Register("wi::scene::Scene::armatures"); wi::ecs::ComponentManager& lights = componentLibrary.Register("wi::scene::Scene::lights"); @@ -52,7 +52,7 @@ namespace wi::scene wi::ecs::ComponentManager& colliders = componentLibrary.Register("wi::scene::Scene::colliders", 1); // version = 1 wi::ecs::ComponentManager& scripts = componentLibrary.Register("wi::scene::Scene::scripts"); wi::ecs::ComponentManager& expressions = componentLibrary.Register("wi::scene::Scene::expressions"); - wi::ecs::ComponentManager& terrains = componentLibrary.Register("wi::scene::Scene::terrains"); + wi::ecs::ComponentManager& terrains = componentLibrary.Register("wi::scene::Scene::terrains", 1); // version = 1 // Non-serialized attributes: float dt = 0; diff --git a/WickedEngine/wiScene_BindLua.cpp b/WickedEngine/wiScene_BindLua.cpp index 52d570c2a..5e3f4924f 100644 --- a/WickedEngine/wiScene_BindLua.cpp +++ b/WickedEngine/wiScene_BindLua.cpp @@ -2709,7 +2709,7 @@ int MaterialComponent_BindLua::SetTexture(lua_State* L) int argc = wi::lua::SGetArgCount(L); if (argc >= 2) { - uint32_t textureindex = wi::lua::SGetLongLong(L, 1); + uint32_t textureindex = (uint32_t)wi::lua::SGetLongLong(L, 1); std::string resourcename = wi::lua::SGetString(L, 2); if(textureindex < MaterialComponent::TEXTURESLOT_COUNT) @@ -2736,7 +2736,7 @@ int MaterialComponent_BindLua::GetTexture(lua_State* L) int argc = wi::lua::SGetArgCount(L); if (argc > 0) { - uint32_t textureindex = wi::lua::SGetLongLong(L, 1); + uint32_t textureindex = (uint32_t)wi::lua::SGetLongLong(L, 1); if(textureindex < MaterialComponent::TEXTURESLOT_COUNT) { @@ -2760,8 +2760,8 @@ int MaterialComponent_BindLua::SetTextureUVSet(lua_State* L) int argc = wi::lua::SGetArgCount(L); if (argc >= 2) { - uint32_t textureindex = wi::lua::SGetLongLong(L, 1); - uint32_t uvset = wi::lua::SGetLongLong(L, 2); + uint32_t textureindex = (uint32_t)wi::lua::SGetLongLong(L, 1); + uint32_t uvset = (uint32_t)wi::lua::SGetLongLong(L, 2); if(textureindex < MaterialComponent::TEXTURESLOT_COUNT) { @@ -2786,7 +2786,7 @@ int MaterialComponent_BindLua::GetTextureUVSet(lua_State* L) int argc = wi::lua::SGetArgCount(L); if (argc > 0) { - uint32_t textureindex = wi::lua::SGetLongLong(L, 1); + uint32_t textureindex = (uint32_t)wi::lua::SGetLongLong(L, 1); if(textureindex < MaterialComponent::TEXTURESLOT_COUNT) { @@ -2849,8 +2849,8 @@ int MeshComponent_BindLua::SetMeshSubsetMaterialID(lua_State* L) int argc = wi::lua::SGetArgCount(L); if (argc >= 2) { - size_t subsetindex = wi::lua::SGetLongLong(L, 1); - uint32_t uvset = wi::lua::SGetLongLong(L, 2); + size_t subsetindex = (uint32_t)wi::lua::SGetLongLong(L, 1); + uint32_t uvset = (uint32_t)wi::lua::SGetLongLong(L, 2); if(subsetindex < component->subsets.size()) { diff --git a/WickedEngine/wiScene_Serializers.cpp b/WickedEngine/wiScene_Serializers.cpp index 08a09be7a..151d225e7 100644 --- a/WickedEngine/wiScene_Serializers.cpp +++ b/WickedEngine/wiScene_Serializers.cpp @@ -624,6 +624,11 @@ namespace wi::scene archive >> capsule.height; archive >> capsule.radius; } + + if (seri.GetVersion() >= 1) + { + archive >> mesh_lod; + } } else { @@ -646,6 +651,11 @@ namespace wi::scene archive << capsule.height; archive << capsule.radius; } + + if (seri.GetVersion() >= 1) + { + archive << mesh_lod; + } } } void SoftBodyPhysicsComponent::Serialize(wi::Archive& archive, EntitySerializer& seri) diff --git a/WickedEngine/wiTerrain.cpp b/WickedEngine/wiTerrain.cpp index 4f1b16ecb..c3350db7f 100644 --- a/WickedEngine/wiTerrain.cpp +++ b/WickedEngine/wiTerrain.cpp @@ -168,7 +168,7 @@ namespace wi::terrain { wi::scene::Scene scene; // The background generation thread can safely add things to this, it will be merged into the main scene when it is safe to do so wi::jobsystem::context workload; - std::atomic_bool cancelled; + std::atomic_bool cancelled{ false }; }; Terrain::Terrain() @@ -282,6 +282,12 @@ namespace wi::terrain return; } + WeatherComponent* weather_component = scene->weathers.GetComponent(terrainEntity); + if (weather_component != nullptr) + { + weather = *weather_component; // feedback default weather + } + // What was generated, will be merged in to the main scene scene->Merge(generator->scene); @@ -388,6 +394,46 @@ namespace wi::terrain } } + RigidBodyPhysicsComponent* rigidbody = scene->rigidbodies.GetComponent(chunk_data.entity); + if (IsPhysicsEnabled()) + { + const int lod_required = std::max(0, dist - 1); + + if (rigidbody != nullptr) + { + if (dist < physics_generation) + { + if (rigidbody->mesh_lod != lod_required) + { + rigidbody->mesh_lod = lod_required; + rigidbody->physicsobject = {}; // will be recreated + } + } + else + { + scene->rigidbodies.Remove(chunk_data.entity); + } + } + else + { + if (dist < physics_generation) + { + RigidBodyPhysicsComponent& newrigidbody = scene->rigidbodies.Create(chunk_data.entity); + newrigidbody.shape = RigidBodyPhysicsComponent::TRIANGLE_MESH; + newrigidbody.SetDisableDeactivation(true); + newrigidbody.SetKinematic(true); + newrigidbody.mesh_lod = lod_required; + } + } + } + else + { + if (rigidbody != nullptr) + { + scene->rigidbodies.Remove(chunk_data.entity); + } + } + // Collect virtual texture update requests: if (max_texture_resolution > 0) { @@ -705,7 +751,7 @@ namespace wi::terrain std::mt19937 prop_rand; prop_rand.seed((uint32_t)chunk.compute_hash() ^ seed); - for (auto& prop : props) + for (const auto& prop : props) { std::uniform_int_distribution gen_distr( uint32_t(prop.min_count_per_chunk * chunk_data.prop_density_current), @@ -748,22 +794,51 @@ namespace wi::terrain const float chance = std::pow(((float*)®ion)[prop.region], prop.region_power) * noise; if (chance > prop.threshold) { - Entity entity = generator->scene.Entity_CreateObject(prop.name + std::to_string(i)); - ObjectComponent* object = generator->scene.objects.GetComponent(entity); - *object = prop.object; + wi::Archive archive = wi::Archive(prop.data.data()); + EntitySerializer seri; + wi::scene::Scene::EntitySerializeFlags flags = wi::scene::Scene::EntitySerializeFlags::RECURSIVE; + if (serializer_state.empty()) + { + // This means the terrain was not serialized, but prop assets provided in this session, so we can keep references to them: + flags |= wi::scene::Scene::EntitySerializeFlags::KEEP_INTERNAL_ENTITY_REFERENCES; + } + else + { + // This means that terrain was serialized, so we have to resolve prop source asset dependencies: + seri.remap = serializer_state; + } + Entity entity = generator->scene.Entity_Serialize( + archive, + seri, + INVALID_ENTITY, + flags + ); + NameComponent* name = generator->scene.names.GetComponent(entity); + if (name != nullptr) + { + name->name += std::to_string(i); + } TransformComponent* transform = generator->scene.transforms.GetComponent(entity); - XMFLOAT3 offset = vertex_pos; - offset.y += wi::math::Lerp(prop.min_y_offset, prop.max_y_offset, float_distr(prop_rand)); - transform->Translate(offset); + if (transform == nullptr) + { + transform = &generator->scene.transforms.Create(entity); + } + transform->translation_local = vertex_pos; + transform->translation_local.y += wi::math::Lerp(prop.min_y_offset, prop.max_y_offset, float_distr(prop_rand)); const float scaling = wi::math::Lerp(prop.min_size, prop.max_size, float_distr(prop_rand)); transform->Scale(XMFLOAT3(scaling, scaling, scaling)); transform->RotateRollPitchYaw(XMFLOAT3(0, XM_2PI * float_distr(prop_rand), 0)); + transform->SetDirty(); transform->UpdateTransform(); generator->scene.Component_Attach(entity, chunk_data.props_entity, true); generated_something = true; } } } + if (!IsPhysicsEnabled()) + { + generator->scene.rigidbodies.Clear(); + } } } } @@ -850,7 +925,7 @@ namespace wi::terrain case MaterialComponent::BASECOLORMAP: case MaterialComponent::SURFACEMAP: case MaterialComponent::NORMALMAP: - if (tex.name.empty() && tex.GetGPUResource() != nullptr) + if (!tex.name.empty() && tex.GetGPUResource() != nullptr) { wi::vector filedata; if (wi::helper::saveTextureToMemory(tex.resource.GetTexture(), filedata)) @@ -943,15 +1018,46 @@ namespace wi::terrain archive >> center_chunk.x; archive >> center_chunk.z; + if (seri.GetVersion() >= 1) + { + archive >> physics_generation; + } + size_t count = 0; archive >> count; props.resize(count); for (size_t i = 0; i < props.size(); ++i) { Prop& prop = props[i]; - archive >> prop.name; - SerializeEntity(archive, prop.mesh_entity, seri); - prop.object.Serialize(archive, seri); + if (seri.GetVersion() >= 1) + { + archive >> prop.data; + } + else + { + // Back compat reading of terrain version 0: + std::string name; + Entity mesh_entity; + ObjectComponent object; + archive >> name; + SerializeEntity(archive, mesh_entity, seri); + object.Serialize(archive, seri); + Scene tmp_scene; + Entity object_entity = CreateEntity(); + tmp_scene.names.Create(object_entity) = name; + tmp_scene.objects.Create(object_entity) = object; + tmp_scene.aabb_objects.Create(object_entity); + tmp_scene.transforms.Create(object_entity); + wi::Archive archive; + EntitySerializer seri; + tmp_scene.Entity_Serialize( + archive, + seri, + object_entity, + wi::scene::Scene::EntitySerializeFlags::RECURSIVE | wi::scene::Scene::EntitySerializeFlags::KEEP_INTERNAL_ENTITY_REFERENCES + ); + archive.WriteData(prop.data); + } archive >> prop.min_count_per_chunk; archive >> prop.max_count_per_chunk; archive >> prop.region; @@ -1036,6 +1142,8 @@ namespace wi::terrain archive >> modifier->weight; archive >> modifier->frequency; } + + serializer_state = seri.remap; } else { @@ -1059,13 +1167,16 @@ namespace wi::terrain archive << center_chunk.x; archive << center_chunk.z; + if (seri.GetVersion() >= 1) + { + archive << physics_generation; + } + archive << props.size(); for (size_t i = 0; i < props.size(); ++i) { Prop& prop = props[i]; - archive << prop.name; - SerializeEntity(archive, prop.mesh_entity, seri); - prop.object.Serialize(archive, seri); + archive << prop.data; archive << prop.min_count_per_chunk; archive << prop.max_count_per_chunk; archive << prop.region; diff --git a/WickedEngine/wiTerrain.h b/WickedEngine/wiTerrain.h index f15292f07..94ff73ed1 100644 --- a/WickedEngine/wiTerrain.h +++ b/WickedEngine/wiTerrain.h @@ -64,9 +64,7 @@ namespace wi::terrain struct Prop { - std::string name = "prop"; - wi::ecs::Entity mesh_entity = wi::ecs::INVALID_ENTITY; - wi::scene::ObjectComponent object; + wi::vector data; // serialized component data storage int min_count_per_chunk = 0; // a chunk will try to generate min this many props of this type int max_count_per_chunk = 10; // a chunk will try to generate max this many props of this type int region = 0; // region selection in range [0,3] (0: base/grass, 1: slopes, 2: low altitude (bottom level-0), 3: high altitude (0-top level)) @@ -92,6 +90,7 @@ namespace wi::terrain REMOVAL = 1 << 1, GRASS = 1 << 2, GENERATION_STARTED = 1 << 4, + PHYSICS = 1 << 5, }; uint32_t _flags = CENTER_TO_CAM | REMOVAL | GRASS; @@ -108,6 +107,7 @@ namespace wi::terrain Chunk center_chunk = {}; wi::noise::Perlin perlin_noise; wi::vector props; + wi::unordered_map serializer_state; // For generating scene on a background thread: std::shared_ptr generator; @@ -125,16 +125,19 @@ namespace wi::terrain constexpr bool IsRemovalEnabled() const { return _flags & REMOVAL; } constexpr bool IsGrassEnabled() const { return _flags & GRASS; } constexpr bool IsGenerationStarted() const { return _flags & GENERATION_STARTED; } + constexpr bool IsPhysicsEnabled() const { return _flags & PHYSICS; } constexpr void SetCenterToCamEnabled(bool value) { if (value) { _flags |= CENTER_TO_CAM; } else { _flags &= ~CENTER_TO_CAM; } } constexpr void SetRemovalEnabled(bool value) { if (value) { _flags |= REMOVAL; } else { _flags &= ~REMOVAL; } } constexpr void SetGrassEnabled(bool value) { if (value) { _flags |= GRASS; } else { _flags &= ~GRASS; } } constexpr void SetGenerationStarted(bool value) { if (value) { _flags |= GENERATION_STARTED; } else { _flags &= ~GENERATION_STARTED; } } + constexpr void SetPhysicsEnabled(bool value) { if (value) { _flags |= PHYSICS; } else { _flags &= ~PHYSICS; } } float lod_multiplier = 0.005f; float texlod = 0.01f; int generation = 12; int prop_generation = 10; + int physics_generation = 3; float prop_density = 1; float grass_density = 1; float chunk_scale = 1; diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index ad8d285d6..2f7a1ae5c 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wi::version // minor features, major updates, breaking compatibility changes const int minor = 71; // minor bug fixes, alterations, refactors, updates - const int revision = 35; + const int revision = 36; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision); @@ -114,6 +114,7 @@ Patreon supporters - Delhills - NI NI - Sherief +- ktopoet )"; return credits;