Terrain physics (#552)
* terrain physics * terrain props physics configuration * asset refactors * fix * warning
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 +0,0 @@
|
||||
https://www.cgtrader.com/free-3d-models/plant/bush/mediteranean-bush
|
||||
Binary file not shown.
@@ -1 +0,0 @@
|
||||
https://www.sharetextures.com/textures/ground/snow_ground_3/
|
||||
@@ -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 +0,0 @@
|
||||
https://www.cgbookcase.com/textures/sandy-gravel-01/?source=3dassets.one
|
||||
Binary file not shown.
@@ -1 +0,0 @@
|
||||
https://www.cgtrader.com/free-3d-models/plant/other/rocks-56c7a2d1-2e36-4b17-8d79-2a69ab29d860
|
||||
Binary file not shown.
@@ -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 +0,0 @@
|
||||
https://free3d.com/3d-model/tree02-35663.html
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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
@@ -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*)®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<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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user