Terrain physics (#552)

* terrain physics

* terrain props physics configuration

* asset refactors

* fix

* warning
This commit is contained in:
Turánszki János
2022-09-03 19:58:14 +02:00
committed by GitHub
parent 018f5d003d
commit c359395cea
27 changed files with 311 additions and 192 deletions
+2 -2
View File
@@ -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);
+2 -37
View File
@@ -192,15 +192,7 @@
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">true</DeploymentContent>
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</DeploymentContent>
</None>
<None Include="$(MSBuildThisFileDirectory)terrain\bush.wiscene">
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent>
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent>
</None>
<None Include="$(MSBuildThisFileDirectory)terrain\rock.wiscene">
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent>
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent>
</None>
<None Include="$(MSBuildThisFileDirectory)terrain\tree.wiscene">
<None Include="$(MSBuildThisFileDirectory)terrain\props.wiscene">
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent>
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent>
</None>
@@ -244,33 +236,6 @@
</Image>
</ItemGroup>
<ItemGroup>
<Text Include="$(MSBuildThisFileDirectory)terrain\base-LICENSE.txt">
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent>
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent>
</Text>
<Text Include="$(MSBuildThisFileDirectory)terrain\bush-LICENSE.txt">
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent>
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent>
</Text>
<Text Include="$(MSBuildThisFileDirectory)terrain\high_altitude-LICENSE.txt">
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent>
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent>
</Text>
<Text Include="$(MSBuildThisFileDirectory)terrain\low_altitude-LICENSE.txt">
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent>
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent>
</Text>
<Text Include="$(MSBuildThisFileDirectory)terrain\rock-LICENSE.txt">
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent>
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent>
</Text>
<Text Include="$(MSBuildThisFileDirectory)terrain\slope-LICENSE.txt">
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent>
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent>
</Text>
<Text Include="$(MSBuildThisFileDirectory)terrain\tree-LICENSE.txt">
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent>
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent>
</Text>
<Text Include="$(MSBuildThisFileDirectory)terrain\licenses.txt" />
</ItemGroup>
</Project>
+4 -28
View File
@@ -135,16 +135,10 @@
</ItemGroup>
<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)startup.lua" />
<None Include="$(MSBuildThisFileDirectory)terrain\bush.wiscene">
<Filter>terrain</Filter>
</None>
<None Include="$(MSBuildThisFileDirectory)terrain\rock.wiscene">
<Filter>terrain</Filter>
</None>
<None Include="$(MSBuildThisFileDirectory)terrain\tree.wiscene">
<Filter>terrain</Filter>
</None>
<None Include="$(MSBuildThisFileDirectory)config.ini" />
<None Include="$(MSBuildThisFileDirectory)terrain\props.wiscene">
<Filter>terrain</Filter>
</None>
</ItemGroup>
<ItemGroup>
<Filter Include="meshoptimizer">
@@ -184,25 +178,7 @@
</Image>
</ItemGroup>
<ItemGroup>
<Text Include="$(MSBuildThisFileDirectory)terrain\base-LICENSE.txt">
<Filter>terrain</Filter>
</Text>
<Text Include="$(MSBuildThisFileDirectory)terrain\high_altitude-LICENSE.txt">
<Filter>terrain</Filter>
</Text>
<Text Include="$(MSBuildThisFileDirectory)terrain\low_altitude-LICENSE.txt">
<Filter>terrain</Filter>
</Text>
<Text Include="$(MSBuildThisFileDirectory)terrain\slope-LICENSE.txt">
<Filter>terrain</Filter>
</Text>
<Text Include="$(MSBuildThisFileDirectory)terrain\bush-LICENSE.txt">
<Filter>terrain</Filter>
</Text>
<Text Include="$(MSBuildThisFileDirectory)terrain\rock-LICENSE.txt">
<Filter>terrain</Filter>
</Text>
<Text Include="$(MSBuildThisFileDirectory)terrain\tree-LICENSE.txt">
<Text Include="$(MSBuildThisFileDirectory)terrain\licenses.txt">
<Filter>terrain</Filter>
</Text>
</ItemGroup>
+15
View File
@@ -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);
+1
View File
@@ -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;
+1 -26
View File
@@ -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);
}
}
+100 -57
View File
@@ -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);
+3 -1
View File
@@ -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;
-4
View File
@@ -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
-1
View File
@@ -1 +0,0 @@
https://www.cgtrader.com/free-3d-models/plant/bush/mediteranean-bush
Binary file not shown.
-1
View File
@@ -1 +0,0 @@
https://www.sharetextures.com/textures/ground/snow_ground_3/
+26
View File
@@ -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
-1
View File
@@ -1 +0,0 @@
https://www.cgbookcase.com/textures/sandy-gravel-01/?source=3dassets.one
-1
View File
@@ -1 +0,0 @@
https://www.cgtrader.com/free-3d-models/plant/other/rocks-56c7a2d1-2e36-4b17-8d79-2a69ab29d860
Binary file not shown.
-4
View File
@@ -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
-1
View File
@@ -1 +0,0 @@
https://free3d.com/3d-model/tree02-35663.html
+2
View File
@@ -42,7 +42,9 @@ namespace wi
Archive& operator=(const Archive&) = default;
Archive& operator=(Archive&&) = default;
void WriteData(wi::vector<uint8_t>& 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
+2
View File
@@ -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;
+2 -2
View File
@@ -30,7 +30,7 @@ namespace wi::scene
wi::ecs::ComponentManager<ImpostorComponent>& impostors = componentLibrary.Register<ImpostorComponent>("wi::scene::Scene::impostors");
wi::ecs::ComponentManager<ObjectComponent>& objects = componentLibrary.Register<ObjectComponent>("wi::scene::Scene::objects");
wi::ecs::ComponentManager<wi::primitive::AABB>& aabb_objects = componentLibrary.Register<wi::primitive::AABB>("wi::scene::Scene::aabb_objects");
wi::ecs::ComponentManager<RigidBodyPhysicsComponent>& rigidbodies = componentLibrary.Register<RigidBodyPhysicsComponent>("wi::scene::Scene::rigidbodies");
wi::ecs::ComponentManager<RigidBodyPhysicsComponent>& rigidbodies = componentLibrary.Register<RigidBodyPhysicsComponent>("wi::scene::Scene::rigidbodies", 1); // version = 1
wi::ecs::ComponentManager<SoftBodyPhysicsComponent>& softbodies = componentLibrary.Register<SoftBodyPhysicsComponent>("wi::scene::Scene::softbodies");
wi::ecs::ComponentManager<ArmatureComponent>& armatures = componentLibrary.Register<ArmatureComponent>("wi::scene::Scene::armatures");
wi::ecs::ComponentManager<LightComponent>& lights = componentLibrary.Register<LightComponent>("wi::scene::Scene::lights");
@@ -52,7 +52,7 @@ namespace wi::scene
wi::ecs::ComponentManager<ColliderComponent>& colliders = componentLibrary.Register<ColliderComponent>("wi::scene::Scene::colliders", 1); // version = 1
wi::ecs::ComponentManager<ScriptComponent>& scripts = componentLibrary.Register<ScriptComponent>("wi::scene::Scene::scripts");
wi::ecs::ComponentManager<ExpressionComponent>& expressions = componentLibrary.Register<ExpressionComponent>("wi::scene::Scene::expressions");
wi::ecs::ComponentManager<wi::terrain::Terrain>& terrains = componentLibrary.Register<wi::terrain::Terrain>("wi::scene::Scene::terrains");
wi::ecs::ComponentManager<wi::terrain::Terrain>& terrains = componentLibrary.Register<wi::terrain::Terrain>("wi::scene::Scene::terrains", 1); // version = 1
// Non-serialized attributes:
float dt = 0;
+7 -7
View File
@@ -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())
{
+10
View File
@@ -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)
+126 -15
View File
@@ -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<uint32_t> 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*)&region)[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<uint8_t> 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;
+6 -3
View File
@@ -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<uint8_t> 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<Prop> props;
wi::unordered_map<uint64_t, wi::ecs::Entity> serializer_state;
// For generating scene on a background thread:
std::shared_ptr<Generator> 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;
+2 -1
View File
@@ -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;