diff --git a/Content/Documentation/ScriptingAPI-Documentation.md b/Content/Documentation/ScriptingAPI-Documentation.md index 32b1f801f..350ce8181 100644 --- a/Content/Documentation/ScriptingAPI-Documentation.md +++ b/Content/Documentation/ScriptingAPI-Documentation.md @@ -138,7 +138,7 @@ You can use the Renderer with the following functions, all of which are in the g - SetShadowPropsCube(int resolution) - SetDebugPartitionTreeEnabled(bool enabled) - SetDebugBonesEnabled(bool enabled) -- SetDebugEittersEnabled(bool enabled) +- SetDebugEmittersEnabled(bool enabled) - SetDebugEnvProbesEnabled(bool enabled) - SetDebugForceFieldsEnabled(bool enabled) - SetDebugCamerasEnabled(bool value) @@ -1201,7 +1201,7 @@ A lua script bound to an entity #### RigidBodyPhysicsComponent Describes a Rigid Body Physics object. - Shape : int -- Mass : float +- Mass : float -- Set mass to 0 to have completely static rigid body (if you want to move it, it's better to use `SetKinematic(true)` as it will be moved continuously with the physics update rate) - Friction : float - Restitution : float - LinearDamping : float @@ -1216,14 +1216,25 @@ Describes a Rigid Body Physics object. - IsDisableDeactivation() : bool return -- Check if the rigidbody is able to deactivate after inactivity - IsKinematic() : bool return -- Check if the rigidbody is movable or just static -- SetDisableDeactivation(bool value = true) -- Sets if the rigidbody is able to deactivate after inactivity -- SetKinematic(bool value = true) -- Sets if the rigidbody is movable or just static +- IsStartDeactivated() : bool return -- Checks whether rigid body is set to be deactivated when added to simulation +- SetDisableDeactivation(bool value) -- Sets if the rigidbody is able to deactivate after inactivity +- SetKinematic(bool value) -- Set the rigid body to be kinematic (which means it is optimized for being moved by the system or user logic, not the physics engine) +- SetStartDeactivated(bool value) -- If true, rigid body will be deactivated when added to the simulation (if it's dynamic, it won't fall) #### SoftBodyPhysicsComponent Describes a Soft Body Physics object. - Mass : float - Friction : float - Restitution : float +- VertexRadius : float -- how much distance vertices keep from other physics bodies + +- SetDetail(float value) -- Set how much detail the soft body simulation has compared to the graphics mesh. Setting this will rebuild the soft body, so individual physics vertex settings will be lost. +- GetDetail() : float +- SetDisableDeactivation(bool value) +- IsDisableDeactivation() : bool +- SetWindEnabled(bool value) +- IsWindEnabled() : bool +- CreateFromMesh(MeshComponent mesh) #### ForceFieldComponent Describes a Force Field effector. diff --git a/Content/models/Sponza/sponza.wiscene b/Content/models/Sponza/sponza.wiscene index 00ff791f1..0b6fc40f5 100644 Binary files a/Content/models/Sponza/sponza.wiscene and b/Content/models/Sponza/sponza.wiscene differ diff --git a/Editor/ComponentsWindow.cpp b/Editor/ComponentsWindow.cpp index 06365f044..f82eaf1a2 100644 --- a/Editor/ComponentsWindow.cpp +++ b/Editor/ComponentsWindow.cpp @@ -220,238 +220,247 @@ void ComponentsWindow::Create(EditorComponent* _editor) newComponentCombo.AddItem("Voxel Grid " ICON_VOXELGRID, ADD_VOXELGRID); newComponentCombo.OnSelect([=](wi::gui::EventArgs args) { newComponentCombo.SetSelectedWithoutCallback(-1); - if (editor->translator.selected.empty()) - return; - Scene& scene = editor->GetCurrentScene(); - Entity entity = editor->translator.selected.back().entity; - if (args.userdata == ADD_SOFTBODY) + wi::scene::Scene& scene = editor->GetCurrentScene(); + wi::vector entities; + for (auto& x : editor->translator.selected) { - // explanation: for softbody, we want to create it for the MeshComponent, if it's also selected together with the object: - ObjectComponent* object = scene.objects.GetComponent(entity); - if (object != nullptr) + Entity entity = x.entity; + if (args.userdata == ADD_SOFTBODY) { - entity = object->meshID; + // explanation: for softbody, we want to create it for the MeshComponent, if it's also selected together with the object: + ObjectComponent* object = scene.objects.GetComponent(entity); + if (object != nullptr) + { + entity = object->meshID; + } } - } - if (entity == INVALID_ENTITY) - { - assert(0); - return; - } + if (entity == INVALID_ENTITY) + continue; - // Can early exit before creating history entry! - switch (args.userdata) - { - case ADD_NAME: - if (scene.names.Contains(entity)) - return; - break; - case ADD_LAYER: - if (scene.layers.Contains(entity)) - return; - break; - case ADD_TRANSFORM: - if (scene.transforms.Contains(entity)) - return; - break; - case ADD_LIGHT: - if (scene.lights.Contains(entity)) - return; - break; - case ADD_MATERIAL: - if (scene.materials.Contains(entity)) - return; - break; - case ADD_SPRING: - if (scene.springs.Contains(entity)) - return; - break; - case ADD_IK: - if (scene.inverse_kinematics.Contains(entity)) - return; - break; - case ADD_SOUND: - if (scene.sounds.Contains(entity)) - return; - break; - case ADD_ENVPROBE: - if (scene.probes.Contains(entity)) - return; - break; - case ADD_EMITTER: - if (scene.emitters.Contains(entity)) - return; - break; - case ADD_HAIR: - if (scene.hairs.Contains(entity)) - return; - break; - case ADD_DECAL: - if (scene.decals.Contains(entity)) - return; - break; - case ADD_WEATHER: - if (scene.weathers.Contains(entity)) - return; - break; - case ADD_FORCE: - if (scene.forces.Contains(entity)) - return; - break; - case ADD_ANIMATION: - if (scene.animations.Contains(entity)) - return; - break; - case ADD_SCRIPT: - if (scene.scripts.Contains(entity)) - return; - break; - case ADD_RIGIDBODY: - if (scene.rigidbodies.Contains(entity)) - return; - break; - case ADD_SOFTBODY: - if (scene.softbodies.Contains(entity)) - return; - break; - case ADD_COLLIDER: - if (scene.colliders.Contains(entity)) - return; - break; - case ADD_HIERARCHY: - if (scene.hierarchy.Contains(entity)) - return; - break; - case ADD_CAMERA: - if (scene.cameras.Contains(entity)) - return; - break; - case ADD_OBJECT: - if (scene.objects.Contains(entity)) - return; - break; - case ADD_VIDEO: - if (scene.videos.Contains(entity)) - return; - break; - case ADD_SPRITE: - if (scene.sprites.Contains(entity)) - return; - break; - case ADD_FONT: - if (scene.fonts.Contains(entity)) - return; - break; - case ADD_VOXELGRID: - if (scene.voxel_grids.Contains(entity)) - return; - break; - default: - return; + // Can early exit before creating history entry! + bool valid = true; + switch (args.userdata) + { + case ADD_NAME: + if (scene.names.Contains(entity)) + valid = false; + break; + case ADD_LAYER: + if (scene.layers.Contains(entity)) + valid = false; + break; + case ADD_TRANSFORM: + if (scene.transforms.Contains(entity)) + valid = false; + break; + case ADD_LIGHT: + if (scene.lights.Contains(entity)) + valid = false; + break; + case ADD_MATERIAL: + if (scene.materials.Contains(entity)) + valid = false; + break; + case ADD_SPRING: + if (scene.springs.Contains(entity)) + valid = false; + break; + case ADD_IK: + if (scene.inverse_kinematics.Contains(entity)) + valid = false; + break; + case ADD_SOUND: + if (scene.sounds.Contains(entity)) + valid = false; + break; + case ADD_ENVPROBE: + if (scene.probes.Contains(entity)) + valid = false; + break; + case ADD_EMITTER: + if (scene.emitters.Contains(entity)) + valid = false; + break; + case ADD_HAIR: + if (scene.hairs.Contains(entity)) + valid = false; + break; + case ADD_DECAL: + if (scene.decals.Contains(entity)) + valid = false; + break; + case ADD_WEATHER: + if (scene.weathers.Contains(entity)) + valid = false; + break; + case ADD_FORCE: + if (scene.forces.Contains(entity)) + valid = false; + break; + case ADD_ANIMATION: + if (scene.animations.Contains(entity)) + valid = false; + break; + case ADD_SCRIPT: + if (scene.scripts.Contains(entity)) + valid = false; + break; + case ADD_RIGIDBODY: + if (scene.rigidbodies.Contains(entity)) + valid = false; + break; + case ADD_SOFTBODY: + if (scene.softbodies.Contains(entity)) + valid = false; + break; + case ADD_COLLIDER: + if (scene.colliders.Contains(entity)) + valid = false; + break; + case ADD_HIERARCHY: + if (scene.hierarchy.Contains(entity)) + valid = false; + break; + case ADD_CAMERA: + if (scene.cameras.Contains(entity)) + valid = false; + break; + case ADD_OBJECT: + if (scene.objects.Contains(entity)) + valid = false; + break; + case ADD_VIDEO: + if (scene.videos.Contains(entity)) + valid = false; + break; + case ADD_SPRITE: + if (scene.sprites.Contains(entity)) + valid = false; + break; + case ADD_FONT: + if (scene.fonts.Contains(entity)) + valid = false; + break; + case ADD_VOXELGRID: + if (scene.voxel_grids.Contains(entity)) + valid = false; + break; + default: + valid = false; + break; + } + + if (valid) + { + entities.push_back(entity); + } } wi::Archive& archive = editor->AdvanceHistory(); archive << EditorComponent::HISTORYOP_COMPONENT_DATA; - editor->RecordEntity(archive, entity); + editor->RecordEntity(archive, entities); - switch (args.userdata) + for (Entity entity : entities) { - case ADD_NAME: - scene.names.Create(entity); - break; - case ADD_LAYER: - scene.layers.Create(entity); - break; - case ADD_TRANSFORM: - scene.transforms.Create(entity); - break; - case ADD_LIGHT: - scene.lights.Create(entity); - break; - case ADD_MATERIAL: - scene.materials.Create(entity); - break; - case ADD_SPRING: - scene.springs.Create(entity); - break; - case ADD_IK: - scene.inverse_kinematics.Create(entity); - break; - case ADD_SOUND: - scene.sounds.Create(entity); - break; - case ADD_ENVPROBE: - scene.probes.Create(entity); - break; - case ADD_EMITTER: - if (!scene.materials.Contains(entity)) + switch (args.userdata) + { + case ADD_NAME: + scene.names.Create(entity); + break; + case ADD_LAYER: + scene.layers.Create(entity); + break; + case ADD_TRANSFORM: + scene.transforms.Create(entity); + break; + case ADD_LIGHT: + scene.lights.Create(entity); + break; + case ADD_MATERIAL: scene.materials.Create(entity); - scene.emitters.Create(entity); - break; - case ADD_HAIR: - if (!scene.materials.Contains(entity)) - scene.materials.Create(entity); - scene.hairs.Create(entity); - break; - case ADD_DECAL: - if (!scene.materials.Contains(entity)) - scene.materials.Create(entity); - scene.decals.Create(entity); - break; - case ADD_WEATHER: - scene.weathers.Create(entity); - break; - case ADD_FORCE: - scene.forces.Create(entity); - break; - case ADD_ANIMATION: - scene.animations.Create(entity); - break; - case ADD_SCRIPT: - scene.scripts.Create(entity); - break; - case ADD_RIGIDBODY: + break; + case ADD_SPRING: + scene.springs.Create(entity); + break; + case ADD_IK: + scene.inverse_kinematics.Create(entity); + break; + case ADD_SOUND: + scene.sounds.Create(entity); + break; + case ADD_ENVPROBE: + scene.probes.Create(entity); + break; + case ADD_EMITTER: + if (!scene.materials.Contains(entity)) + scene.materials.Create(entity); + scene.emitters.Create(entity); + break; + case ADD_HAIR: + if (!scene.materials.Contains(entity)) + scene.materials.Create(entity); + scene.hairs.Create(entity); + break; + case ADD_DECAL: + if (!scene.materials.Contains(entity)) + scene.materials.Create(entity); + scene.decals.Create(entity); + break; + case ADD_WEATHER: + scene.weathers.Create(entity); + break; + case ADD_FORCE: + scene.forces.Create(entity); + break; + case ADD_ANIMATION: + scene.animations.Create(entity); + break; + case ADD_SCRIPT: + scene.scripts.Create(entity); + break; + case ADD_RIGIDBODY: { RigidBodyPhysicsComponent& rigidbody = scene.rigidbodies.Create(entity); - rigidbody.SetKinematic(true); // Set it to kinematic so that it doesn't immediately fall + rigidbody.SetKinematic(true); // Set it to kinematic so that it can be easily placed } break; - case ADD_SOFTBODY: - scene.softbodies.Create(entity); - break; - case ADD_COLLIDER: - scene.colliders.Create(entity); - break; - case ADD_HIERARCHY: - scene.hierarchy.Create(entity); - break; - case ADD_CAMERA: - scene.cameras.Create(entity); - break; - case ADD_OBJECT: - scene.objects.Create(entity); - break; - case ADD_VIDEO: - scene.videos.Create(entity); - break; - case ADD_SPRITE: - scene.sprites.Create(entity); - break; - case ADD_FONT: - scene.fonts.Create(entity); - break; - case ADD_VOXELGRID: - scene.voxel_grids.Create(entity); - break; - default: - break; + case ADD_SOFTBODY: + scene.softbodies.Create(entity); + break; + case ADD_COLLIDER: + scene.colliders.Create(entity); + break; + case ADD_HIERARCHY: + scene.hierarchy.Create(entity); + break; + case ADD_CAMERA: + scene.cameras.Create(entity); + break; + case ADD_OBJECT: + scene.objects.Create(entity); + break; + case ADD_VIDEO: + scene.videos.Create(entity); + break; + case ADD_SPRITE: + scene.sprites.Create(entity); + break; + case ADD_FONT: + scene.fonts.Create(entity); + break; + case ADD_VOXELGRID: + scene.voxel_grids.Create(entity); + break; + default: + break; + } } - editor->RecordEntity(archive, entity); + editor->RecordEntity(archive, entities); RefreshEntityTree(); - }); + }); AddWidget(&newComponentCombo); diff --git a/Editor/ContentBrowserWindow.cpp b/Editor/ContentBrowserWindow.cpp index e59ef5d8b..733058c45 100644 --- a/Editor/ContentBrowserWindow.cpp +++ b/Editor/ContentBrowserWindow.cpp @@ -172,6 +172,22 @@ void ContentBrowserWindow::RefreshContent() current_selection = SELECTION_RECENT; } } + if (wi::helper::DirectoryExists(content_folder + "models")) + { + wi::gui::Button& button = folderButtons[SELECTION_MODELS]; + button.Create("Models"); + button.SetTooltip(content_folder + "models"); + button.SetLocalizationEnabled(false); + button.SetSize(XMFLOAT2(wid, hei)); + button.OnClick([this](wi::gui::EventArgs args) { + SetSelection(SELECTION_MODELS); + }); + AddWidget(&button, wi::gui::Window::AttachmentOptions::NONE); + if (current_selection == SELECTION_COUNT) + { + current_selection = SELECTION_MODELS; + } + } if (wi::helper::DirectoryExists(content_folder + "scripts")) { wi::gui::Button& button = folderButtons[SELECTION_SCRIPTS]; @@ -188,22 +204,6 @@ void ContentBrowserWindow::RefreshContent() current_selection = SELECTION_SCRIPTS; } } - if (wi::helper::DirectoryExists(content_folder + "models")) - { - wi::gui::Button& button = folderButtons[SELECTION_MODELS]; - button.Create("Models"); - button.SetTooltip(content_folder + "models"); - button.SetLocalizationEnabled(false); - button.SetSize(XMFLOAT2(wid, hei)); - button.OnClick([this](wi::gui::EventArgs args) { - SetSelection(SELECTION_MODELS); - }); - AddWidget(&button, wi::gui::Window::AttachmentOptions::NONE); - if (current_selection == SELECTION_COUNT) - { - current_selection = SELECTION_MODELS; - } - } for (size_t i = 0; i < editor->recentFolders.size(); ++i) { diff --git a/Editor/PaintToolWindow.cpp b/Editor/PaintToolWindow.cpp index 8ae84ac06..df6086081 100644 --- a/Editor/PaintToolWindow.cpp +++ b/Editor/PaintToolWindow.cpp @@ -1173,14 +1173,13 @@ void PaintToolWindow::Update(float dt) if (softbody == nullptr || !softbody->HasVertices()) continue; - // Painting: - if (painting) + size_t j = 0; + for (auto& ind : softbody->physicsToGraphicsVertexMapping) { - size_t j = 0; - for (auto& ind : softbody->physicsToGraphicsVertexMapping) - { - XMVECTOR P = softbody->vertex_positions_simulation[ind].LoadPOS(); + XMVECTOR P = softbody->vertex_positions_simulation[ind].LoadPOS(); + if (painting) + { const float dist = wi::math::Distance(P, CENTER); if (dist <= pressure_radius) { @@ -1188,64 +1187,22 @@ void PaintToolWindow::Update(float dt) softbody->weights[j] = (mode == MODE_SOFTBODY_PINNING ? 0.0f : 1.0f); softbody->_flags |= SoftBodyPhysicsComponent::FORCE_RESET; } - j++; } - } - // Visualizing: - const XMMATRIX W = XMLoadFloat4x4(&softbody->worldMatrix); - uint32_t first_subset = 0; - uint32_t last_subset = 0; - mesh->GetLODSubsetRange(0, first_subset, last_subset); - for (uint32_t subsetIndex = first_subset; subsetIndex < last_subset; ++subsetIndex) - { - const MeshComponent::MeshSubset& subset = mesh->subsets[subsetIndex]; - for (size_t j = 0; j < subset.indexCount; j += 3) + wi::renderer::RenderablePoint point; + point.size = 0.01f; + XMStoreFloat3(&point.position, P); + if (softbody->weights[j] == 0) { - const uint32_t graphicsIndex0 = mesh->indices[j + 0]; - const uint32_t graphicsIndex1 = mesh->indices[j + 1]; - const uint32_t graphicsIndex2 = mesh->indices[j + 2]; - const uint32_t physicsIndex0 = softbody->graphicsToPhysicsVertexMapping[graphicsIndex0]; - const uint32_t physicsIndex1 = softbody->graphicsToPhysicsVertexMapping[graphicsIndex1]; - const uint32_t physicsIndex2 = softbody->graphicsToPhysicsVertexMapping[graphicsIndex2]; - const float weight0 = softbody->weights[physicsIndex0]; - const float weight1 = softbody->weights[physicsIndex1]; - const float weight2 = softbody->weights[physicsIndex2]; - wi::renderer::RenderableTriangle tri; - if (softbody->HasVertices()) - { - tri.positionA = softbody->vertex_positions_simulation[graphicsIndex0].GetPOS(); - tri.positionB = softbody->vertex_positions_simulation[graphicsIndex1].GetPOS(); - tri.positionC = softbody->vertex_positions_simulation[graphicsIndex2].GetPOS(); - } - else - { - XMStoreFloat3(&tri.positionA, XMVector3Transform(XMLoadFloat3(&mesh->vertex_positions[graphicsIndex0]), W)); - XMStoreFloat3(&tri.positionB, XMVector3Transform(XMLoadFloat3(&mesh->vertex_positions[graphicsIndex1]), W)); - XMStoreFloat3(&tri.positionC, XMVector3Transform(XMLoadFloat3(&mesh->vertex_positions[graphicsIndex2]), W)); - } - if (weight0 == 0) - tri.colorA = XMFLOAT4(1, 1, 0, 1); - else - tri.colorA = XMFLOAT4(1, 1, 1, 1); - if (weight1 == 0) - tri.colorB = XMFLOAT4(1, 1, 0, 1); - else - tri.colorB = XMFLOAT4(1, 1, 1, 1); - if (weight2 == 0) - tri.colorC = XMFLOAT4(1, 1, 0, 1); - else - tri.colorC = XMFLOAT4(1, 1, 1, 1); - if (wireframe) - { - wi::renderer::DrawTriangle(tri, true); - } - if (weight0 == 0 && weight1 == 0 && weight2 == 0) - { - tri.colorA = tri.colorB = tri.colorC = XMFLOAT4(1, 0, 0, 0.8f); - wi::renderer::DrawTriangle(tri); - } + point.color = XMFLOAT4(1, 0, 0, 1); } + else + { + point.color = XMFLOAT4(0, 1, 0, 1); + } + wi::renderer::DrawPoint(point); + + j++; } } } diff --git a/Editor/SoftBodyWindow.cpp b/Editor/SoftBodyWindow.cpp index e550353c9..941595a45 100644 --- a/Editor/SoftBodyWindow.cpp +++ b/Editor/SoftBodyWindow.cpp @@ -8,9 +8,9 @@ void SoftBodyWindow::Create(EditorComponent* _editor) { editor = _editor; wi::gui::Window::Create(ICON_SOFTBODY " Soft Body Physics", wi::gui::Window::WindowControls::COLLAPSE | wi::gui::Window::WindowControls::CLOSE); - SetSize(XMFLOAT2(580, 200)); + SetSize(XMFLOAT2(580, 260)); - closeButton.SetTooltip("Delete MeshComponent"); + closeButton.SetTooltip("Delete SoftBodyPhysicsComponent"); OnClose([=](wi::gui::EventArgs args) { wi::Archive& archive = editor->AdvanceHistory(); @@ -22,7 +22,7 @@ void SoftBodyWindow::Create(EditorComponent* _editor) editor->RecordEntity(archive, entity); editor->componentsWnd.RefreshEntityTree(); - }); + }); float x = 95; float y = 0; @@ -35,18 +35,57 @@ void SoftBodyWindow::Create(EditorComponent* _editor) infoLabel.SetSize(XMFLOAT2(100, 90)); AddWidget(&infoLabel); + detailSlider.Create(10, 100, 1, 90, "Detail: "); + detailSlider.SetTooltip("Set the detail to keep between simulation and graphics mesh. This will recreate the soft body, vertex changes will be lost.\nLower = less detailed, higher = more detailed."); + detailSlider.SetSize(XMFLOAT2(wid, hei)); + detailSlider.SetPos(XMFLOAT2(x, y)); + detailSlider.OnSlide([&](wi::gui::EventArgs args) { + wi::scene::Scene& scene = editor->GetCurrentScene(); + for (auto& x : editor->translator.selected) + { + SoftBodyPhysicsComponent* physicscomponent = scene.softbodies.GetComponent(x.entity); + if (physicscomponent == nullptr) + { + // Try also getting it through object's mesh: + ObjectComponent* object = scene.objects.GetComponent(x.entity); + if (object != nullptr) + { + physicscomponent = scene.softbodies.GetComponent(object->meshID); + } + } + if (physicscomponent != nullptr) + { + physicscomponent->SetDetail(args.fValue); + } + } + }); + AddWidget(&detailSlider); + massSlider.Create(0, 10, 1, 100000, "Mass: "); massSlider.SetTooltip("Set the mass amount for the physics engine."); massSlider.SetSize(XMFLOAT2(wid, hei)); massSlider.SetPos(XMFLOAT2(x, y)); massSlider.OnSlide([&](wi::gui::EventArgs args) { - SoftBodyPhysicsComponent* physicscomponent = editor->GetCurrentScene().softbodies.GetComponent(entity); - if (physicscomponent != nullptr) + wi::scene::Scene& scene = editor->GetCurrentScene(); + for (auto& x : editor->translator.selected) { - physicscomponent->physicsobject = {}; - physicscomponent->mass = args.fValue; + SoftBodyPhysicsComponent* physicscomponent = scene.softbodies.GetComponent(x.entity); + if (physicscomponent == nullptr) + { + // Try also getting it through object's mesh: + ObjectComponent* object = scene.objects.GetComponent(x.entity); + if (object != nullptr) + { + physicscomponent = scene.softbodies.GetComponent(object->meshID); + } + } + if (physicscomponent != nullptr) + { + physicscomponent->physicsobject = {}; + physicscomponent->mass = args.fValue; + } } - }); + }); AddWidget(&massSlider); frictionSlider.Create(0, 1, 0.5f, 100000, "Friction: "); @@ -54,12 +93,25 @@ void SoftBodyWindow::Create(EditorComponent* _editor) frictionSlider.SetSize(XMFLOAT2(wid, hei)); frictionSlider.SetPos(XMFLOAT2(x, y += step)); frictionSlider.OnSlide([&](wi::gui::EventArgs args) { - SoftBodyPhysicsComponent* physicscomponent = editor->GetCurrentScene().softbodies.GetComponent(entity); - if (physicscomponent != nullptr) + wi::scene::Scene& scene = editor->GetCurrentScene(); + for (auto& x : editor->translator.selected) { - physicscomponent->friction = args.fValue; + SoftBodyPhysicsComponent* physicscomponent = scene.softbodies.GetComponent(x.entity); + if (physicscomponent == nullptr) + { + // Try also getting it through object's mesh: + ObjectComponent* object = scene.objects.GetComponent(x.entity); + if (object != nullptr) + { + physicscomponent = scene.softbodies.GetComponent(object->meshID); + } + } + if (physicscomponent != nullptr) + { + physicscomponent->friction = args.fValue; + } } - }); + }); AddWidget(&frictionSlider); restitutionSlider.Create(0, 1, 0, 100000, "Restitution: "); @@ -67,14 +119,80 @@ void SoftBodyWindow::Create(EditorComponent* _editor) restitutionSlider.SetSize(XMFLOAT2(wid, hei)); restitutionSlider.SetPos(XMFLOAT2(x, y += step)); restitutionSlider.OnSlide([&](wi::gui::EventArgs args) { - SoftBodyPhysicsComponent* physicscomponent = editor->GetCurrentScene().softbodies.GetComponent(entity); - if (physicscomponent != nullptr) + wi::scene::Scene& scene = editor->GetCurrentScene(); + for (auto& x : editor->translator.selected) { - physicscomponent->restitution = args.fValue; + SoftBodyPhysicsComponent* physicscomponent = scene.softbodies.GetComponent(x.entity); + if (physicscomponent == nullptr) + { + // Try also getting it through object's mesh: + ObjectComponent* object = scene.objects.GetComponent(x.entity); + if (object != nullptr) + { + physicscomponent = scene.softbodies.GetComponent(object->meshID); + } + } + if (physicscomponent != nullptr) + { + physicscomponent->restitution = args.fValue; + } } - }); + }); AddWidget(&restitutionSlider); + vertexRadiusSlider.Create(0, 1, 0, 100000, "Vertex Radius: "); + vertexRadiusSlider.SetTooltip("Set how much distance vertices should keep from other physics bodies."); + vertexRadiusSlider.SetSize(XMFLOAT2(wid, hei)); + vertexRadiusSlider.SetPos(XMFLOAT2(x, y += step)); + vertexRadiusSlider.OnSlide([&](wi::gui::EventArgs args) { + wi::scene::Scene& scene = editor->GetCurrentScene(); + for (auto& x : editor->translator.selected) + { + SoftBodyPhysicsComponent* physicscomponent = scene.softbodies.GetComponent(x.entity); + if (physicscomponent == nullptr) + { + // Try also getting it through object's mesh: + ObjectComponent* object = scene.objects.GetComponent(x.entity); + if (object != nullptr) + { + physicscomponent = scene.softbodies.GetComponent(object->meshID); + } + } + if (physicscomponent != nullptr) + { + physicscomponent->physicsobject = {}; + physicscomponent->vertex_radius = args.fValue; + } + } + }); + AddWidget(&vertexRadiusSlider); + + windCheckbox.Create("Wind: "); + windCheckbox.SetTooltip("Enable/disable wind force on this soft body."); + windCheckbox.SetSize(XMFLOAT2(hei, hei)); + windCheckbox.SetPos(XMFLOAT2(x, y += step)); + windCheckbox.OnClick([&](wi::gui::EventArgs args) { + wi::scene::Scene& scene = editor->GetCurrentScene(); + for (auto& x : editor->translator.selected) + { + SoftBodyPhysicsComponent* physicscomponent = scene.softbodies.GetComponent(x.entity); + if (physicscomponent == nullptr) + { + // Try also getting it through object's mesh: + ObjectComponent* object = scene.objects.GetComponent(x.entity); + if (object != nullptr) + { + physicscomponent = scene.softbodies.GetComponent(object->meshID); + } + } + if (physicscomponent != nullptr) + { + physicscomponent->SetWindEnabled(args.bValue); + } + } + }); + AddWidget(&windCheckbox); + SetMinimized(true); @@ -92,9 +210,12 @@ void SoftBodyWindow::SetEntity(Entity entity) const SoftBodyPhysicsComponent* physicscomponent = scene.softbodies.GetComponent(entity); if (physicscomponent != nullptr) { + detailSlider.SetValue(physicscomponent->detail); massSlider.SetValue(physicscomponent->mass); frictionSlider.SetValue(physicscomponent->friction); restitutionSlider.SetValue(physicscomponent->restitution); + vertexRadiusSlider.SetValue(physicscomponent->vertex_radius); + windCheckbox.SetCheck(physicscomponent->IsWindEnabled()); } } @@ -136,8 +257,11 @@ void SoftBodyWindow::ResizeLayout() }; add_fullwidth(infoLabel); + add(detailSlider); add(massSlider); add(frictionSlider); add(restitutionSlider); + add(vertexRadiusSlider); + add_right(windCheckbox); } diff --git a/Editor/SoftBodyWindow.h b/Editor/SoftBodyWindow.h index 1e73eb40c..dba11716a 100644 --- a/Editor/SoftBodyWindow.h +++ b/Editor/SoftBodyWindow.h @@ -11,9 +11,12 @@ public: void SetEntity(wi::ecs::Entity entity); wi::gui::Label infoLabel; + wi::gui::Slider detailSlider; wi::gui::Slider massSlider; wi::gui::Slider frictionSlider; wi::gui::Slider restitutionSlider; + wi::gui::Slider vertexRadiusSlider; + wi::gui::CheckBox windCheckbox; void ResizeLayout() override; }; diff --git a/WickedEngine/wiBacklog.cpp b/WickedEngine/wiBacklog.cpp index 6fe0041f8..36bff9080 100644 --- a/WickedEngine/wiBacklog.cpp +++ b/WickedEngine/wiBacklog.cpp @@ -336,7 +336,7 @@ namespace wi::backlog entries.clear(); scroll = 0; } - void post(const std::string& input, LogLevel level) + void post(const char* input, LogLevel level) { if (logLevel > level) { @@ -397,6 +397,10 @@ namespace wi::backlog write_logfile(); // will lock mutex } } + void post(const std::string& input, LogLevel level) + { + post(input.c_str(), level); + } void historyPrev() { diff --git a/WickedEngine/wiBacklog.h b/WickedEngine/wiBacklog.h index 36ec866d8..98ca5c4fc 100644 --- a/WickedEngine/wiBacklog.h +++ b/WickedEngine/wiBacklog.h @@ -33,6 +33,7 @@ namespace wi::backlog std::string getText(); void clear(); + void post(const char* input, LogLevel level = LogLevel::Default); void post(const std::string& input, LogLevel level = LogLevel::Default); void historyPrev(); diff --git a/WickedEngine/wiPhysics_Jolt.cpp b/WickedEngine/wiPhysics_Jolt.cpp index 00be3c5a0..edf4c8692 100644 --- a/WickedEngine/wiPhysics_Jolt.cpp +++ b/WickedEngine/wiPhysics_Jolt.cpp @@ -258,6 +258,7 @@ namespace wi::physics SoftBodySharedSettings shared_settings; Array simulation_normals; + Array position_offsets; ~SoftBody() { @@ -387,8 +388,9 @@ namespace wi::physics if (!shape_result.IsValid()) { - physicscomponent.physicsobject = nullptr; - wi::backlog::post("AddRigidBody failed: shape couldn't be created!", wi::backlog::LogLevel::Error); + char text[1024] = {}; + snprintf(text, arraysize(text), "AddRigidBody failed, shape_result: %s", shape_result.GetError().c_str()); + wi::backlog::post(text, wi::backlog::LogLevel::Error); return; } else @@ -442,8 +444,7 @@ namespace wi::physics physicsobject.bodyID = body_interface.CreateAndAddBody(settings, activation); if (physicsobject.bodyID.IsInvalid()) { - physicscomponent.physicsobject = nullptr; - wi::backlog::post("AddRigidBody failed: body couldn't be created!", wi::backlog::LogLevel::Error); + wi::backlog::post("AddRigidBody failed: body couldn't be created! This could mean that there are too many physics objects.", wi::backlog::LogLevel::Error); return; } @@ -471,6 +472,7 @@ namespace wi::physics PhysicsScene& physics_scene = GetPhysicsScene(scene); physicsobject.shared_settings.SetEmbedded(); + physicsobject.shared_settings.mVertexRadius = physicscomponent.vertex_radius; const XMMATRIX worldMatrix = XMLoadFloat4x4(&physicscomponent.worldMatrix); @@ -508,7 +510,6 @@ namespace wi::physics SoftBodySharedSettings::VertexAttributes vertexAttributes = { 1.0e-5f, 1.0e-5f, 1.0e-5f }; physicsobject.shared_settings.CreateConstraints(&vertexAttributes, 1); - physicsobject.shared_settings.Optimize(); SoftBodyCreationSettings settings(&physicsobject.shared_settings, Vec3::sZero(), Quat::sIdentity(), Layers::MOVING); @@ -525,12 +526,25 @@ namespace wi::physics if (physicsobject.bodyID.IsInvalid()) { - physicscomponent.physicsobject = nullptr; - wi::backlog::post("AddSoftBody failed: body couldn't be created!", wi::backlog::LogLevel::Error); + wi::backlog::post("AddSoftBody failed: body couldn't be created! This could mean that there are too many physics objects.", wi::backlog::LogLevel::Error); return; } physicsobject.simulation_normals.resize(physicsobject.shared_settings.mVertices.size()); + + physicsobject.position_offsets.resize(mesh.vertex_positions.size()); + for (size_t i = 0; i < mesh.vertex_positions.size(); ++i) + { + XMFLOAT3 position = mesh.vertex_positions[i]; + XMVECTOR P = XMLoadFloat3(&position); + P = XMVector3Transform(P, worldMatrix); + XMStoreFloat3(&position, P); + + uint32_t physicsInd = physicscomponent.graphicsToPhysicsVertexMapping[i]; + Float3 physicsPosF3 = physicsobject.shared_settings.mVertices[physicsInd].mPosition; + Vec3 physicsPos(physicsPosF3.x, physicsPosF3.y, physicsPosF3.z); + physicsobject.position_offsets[i] = cast(position) - physicsPos; + } } struct Ragdoll @@ -1188,12 +1202,18 @@ namespace wi::physics if (IsSimulationEnabled()) { + const Vec3 position = cast(transform->GetPosition()); + const Quat rotation = cast(transform->GetRotation()); + + Mat44 m = Mat44::sTranslation(position) * Mat44::sRotation(rotation); + m = m * physicsobject.additionalTransform; + if (currentMotionType == EMotionType::Kinematic) { body_interface.MoveKinematic( physicsobject.bodyID, - cast(transform->GetPosition()), - cast(transform->GetRotation()), + m.GetTranslation(), + m.GetQuaternion().Normalized(), physics_scene.GetKinematicDT(scene.dt) ); } @@ -1201,8 +1221,8 @@ namespace wi::physics { body_interface.SetPositionAndRotation( physicsobject.bodyID, - cast(transform->GetPosition()), - cast(transform->GetRotation()), + m.GetTranslation(), + m.GetQuaternion().Normalized(), EActivation::DontActivate ); } @@ -1255,7 +1275,7 @@ namespace wi::physics body_interface.SetFriction(physicsobject.bodyID, physicscomponent.friction); body_interface.SetRestitution(physicsobject.bodyID, physicscomponent.restitution); - if (IsSimulationEnabled()) + if (IsSimulationEnabled() && physicscomponent.IsWindEnabled()) { // Add wind: const Vec3 wind = cast(scene.weather.windDirection); @@ -1384,7 +1404,8 @@ namespace wi::physics wi::jobsystem::Wait(ctx); - //physics_scene.physics_system.OptimizeBroadPhase(); + static wi::jobsystem::context broadphase_optimization_ctx; + wi::jobsystem::Wait(broadphase_optimization_ctx); // Perform internal simulation step: if (IsSimulationEnabled()) @@ -1441,6 +1462,11 @@ namespace wi::physics physics_scene.alpha = physics_scene.accumulator / TIMESTEP; } + broadphase_optimization_ctx.priority = wi::jobsystem::Priority::Streaming; + wi::jobsystem::Execute(broadphase_optimization_ctx, [&](wi::jobsystem::JobArgs args) { + physics_scene.physics_system.OptimizeBroadPhase(); + }); + // Feedback physics objects to system: wi::jobsystem::Dispatch(ctx, (uint32_t)scene.rigidbodies.GetCount(), 64, [&scene, &physics_scene](wi::jobsystem::JobArgs args) { @@ -1522,9 +1548,10 @@ namespace wi::physics // Soft body simulation nodes will update graphics mesh: for (size_t ind = 0; ind < mesh->vertex_positions.size(); ++ind) { + const Vec3& offset = physicsobject.position_offsets[ind]; uint32_t physicsInd = physicscomponent.graphicsToPhysicsVertexMapping[ind]; - const XMFLOAT3 position = cast(soft_vertices[physicsInd].mPosition); + const XMFLOAT3 position = cast(soft_vertices[physicsInd].mPosition + offset); const XMFLOAT3 normal = cast(physicsobject.simulation_normals[physicsInd]); physicscomponent.vertex_positions_simulation[ind].FromFULL(position); diff --git a/WickedEngine/wiScene.h b/WickedEngine/wiScene.h index b498f559e..12c48ae6d 100644 --- a/WickedEngine/wiScene.h +++ b/WickedEngine/wiScene.h @@ -37,7 +37,7 @@ namespace wi::scene wi::ecs::ComponentManager& impostors = componentLibrary.Register("wi::scene::Scene::impostors"); wi::ecs::ComponentManager& objects = componentLibrary.Register("wi::scene::Scene::objects", 3); // version = 3 wi::ecs::ComponentManager& rigidbodies = componentLibrary.Register("wi::scene::Scene::rigidbodies", 3); // version = 3 - wi::ecs::ComponentManager& softbodies = componentLibrary.Register("wi::scene::Scene::softbodies"); + wi::ecs::ComponentManager& softbodies = componentLibrary.Register("wi::scene::Scene::softbodies", 1); // version = 1 wi::ecs::ComponentManager& armatures = componentLibrary.Register("wi::scene::Scene::armatures"); wi::ecs::ComponentManager& lights = componentLibrary.Register("wi::scene::Scene::lights", 2); // version = 2 wi::ecs::ComponentManager& cameras = componentLibrary.Register("wi::scene::Scene::cameras"); diff --git a/WickedEngine/wiScene_BindLua.cpp b/WickedEngine/wiScene_BindLua.cpp index 363d9eda4..58eb02811 100644 --- a/WickedEngine/wiScene_BindLua.cpp +++ b/WickedEngine/wiScene_BindLua.cpp @@ -5675,8 +5675,10 @@ int ScriptComponent_BindLua::Stop(lua_State* L) Luna::FunctionType RigidBodyPhysicsComponent_BindLua::methods[] = { lunamethod(RigidBodyPhysicsComponent_BindLua, IsDisableDeactivation), lunamethod(RigidBodyPhysicsComponent_BindLua, IsKinematic), + lunamethod(RigidBodyPhysicsComponent_BindLua, IsStartDeactivated), lunamethod(RigidBodyPhysicsComponent_BindLua, SetDisableDeactivation), lunamethod(RigidBodyPhysicsComponent_BindLua, SetKinematic), + lunamethod(RigidBodyPhysicsComponent_BindLua, SetStartDeactivated), { NULL, NULL } }; Luna::PropertyType RigidBodyPhysicsComponent_BindLua::properties[] = { @@ -5732,6 +5734,25 @@ int RigidBodyPhysicsComponent_BindLua::SetKinematic(lua_State* L) } return 0; } +int RigidBodyPhysicsComponent_BindLua::IsStartDeactivated(lua_State* L) +{ + wi::lua::SSetBool(L, component->IsStartDeactivated()); + return 1; +} +int RigidBodyPhysicsComponent_BindLua::SetStartDeactivated(lua_State* L) +{ + int argc = wi::lua::SGetArgCount(L); + if (argc > 0) + { + bool value = wi::lua::SGetBool(L, 1); + component->SetStartDeactivated(value); + } + else + { + wi::lua::SError(L, "SetStartDeactivated(bool value) not enough arguments!"); + } + return 0; +} @@ -5740,8 +5761,12 @@ int RigidBodyPhysicsComponent_BindLua::SetKinematic(lua_State* L) Luna::FunctionType SoftBodyPhysicsComponent_BindLua::methods[] = { + lunamethod(SoftBodyPhysicsComponent_BindLua, SetDetail), + lunamethod(SoftBodyPhysicsComponent_BindLua, GetDetail), lunamethod(SoftBodyPhysicsComponent_BindLua, SetDisableDeactivation), lunamethod(SoftBodyPhysicsComponent_BindLua, IsDisableDeactivation), + lunamethod(SoftBodyPhysicsComponent_BindLua, SetWindEnabled), + lunamethod(SoftBodyPhysicsComponent_BindLua, IsWindEnabled), lunamethod(SoftBodyPhysicsComponent_BindLua, CreateFromMesh), { NULL, NULL } }; @@ -5749,9 +5774,21 @@ Luna::PropertyType SoftBodyPhysicsComponent_Bi lunaproperty(SoftBodyPhysicsComponent_BindLua, Mass), lunaproperty(SoftBodyPhysicsComponent_BindLua, Friction), lunaproperty(SoftBodyPhysicsComponent_BindLua, Restitution), + lunaproperty(SoftBodyPhysicsComponent_BindLua, VertexRadius), { NULL, NULL } }; +int SoftBodyPhysicsComponent_BindLua::SetDetail(lua_State* L) +{ + float value = wi::lua::SGetFloat(L, 1); + component->SetDetail(value); + return 0; +} +int SoftBodyPhysicsComponent_BindLua::GetDetail(lua_State* L) +{ + wi::lua::SSetFloat(L, component->detail); + return 1; +} int SoftBodyPhysicsComponent_BindLua::SetDisableDeactivation(lua_State *L) { bool value = wi::lua::SGetBool(L, 1); @@ -5763,10 +5800,24 @@ int SoftBodyPhysicsComponent_BindLua::IsDisableDeactivation(lua_State *L) wi::lua::SSetBool(L, component->IsDisableDeactivation()); return 1; } +int SoftBodyPhysicsComponent_BindLua::SetWindEnabled(lua_State* L) +{ + bool value = wi::lua::SGetBool(L, 1); + component->SetWindEnabled(value); + return 0; +} +int SoftBodyPhysicsComponent_BindLua::IsWindEnabled(lua_State* L) +{ + wi::lua::SSetBool(L, component->IsWindEnabled()); + return 1; +} int SoftBodyPhysicsComponent_BindLua::CreateFromMesh(lua_State *L) { - //TODO - //wi::lua::SSetBool(L, component->IsDisableDeactivation()); + MeshComponent_BindLua* mesh = Luna::lightcheck(L, 1); + if (mesh != nullptr) + { + component->CreateFromMesh(*mesh->component); + } return 0; } diff --git a/WickedEngine/wiScene_BindLua.h b/WickedEngine/wiScene_BindLua.h index fa0811268..76b87de6e 100644 --- a/WickedEngine/wiScene_BindLua.h +++ b/WickedEngine/wiScene_BindLua.h @@ -948,9 +948,11 @@ namespace wi::lua::scene int SetDisableDeactivation(lua_State* L); int SetKinematic(lua_State* L); + int SetStartDeactivated(lua_State* L); int IsDisableDeactivation(lua_State* L); int IsKinematic(lua_State* L); + int IsStartDeactivated(lua_State* L); }; class SoftBodyPhysicsComponent_BindLua @@ -969,6 +971,7 @@ namespace wi::lua::scene Mass = wi::lua::FloatProperty(&component->mass); Friction = wi::lua::FloatProperty(&component->friction); Restitution = wi::lua::FloatProperty(&component->restitution); + VertexRadius = wi::lua::FloatProperty(&component->vertex_radius); } SoftBodyPhysicsComponent_BindLua(wi::scene::SoftBodyPhysicsComponent* component) :component(component) @@ -983,13 +986,19 @@ namespace wi::lua::scene wi::lua::FloatProperty Mass; wi::lua::FloatProperty Friction; wi::lua::FloatProperty Restitution; + wi::lua::FloatProperty VertexRadius; PropertyFunction(Mass) PropertyFunction(Friction) PropertyFunction(Restitution) + PropertyFunction(VertexRadius) + int SetDetail(lua_State* L); + int GetDetail(lua_State* L); int SetDisableDeactivation(lua_State* L); int IsDisableDeactivation(lua_State* L); + int SetWindEnabled(lua_State* L); + int IsWindEnabled(lua_State* L); int CreateFromMesh(lua_State* L); }; diff --git a/WickedEngine/wiScene_Components.cpp b/WickedEngine/wiScene_Components.cpp index 8b63a3def..25167d6f4 100644 --- a/WickedEngine/wiScene_Components.cpp +++ b/WickedEngine/wiScene_Components.cpp @@ -1460,20 +1460,21 @@ namespace wi::scene XMFLOAT3& v1 = vertex_positions[i1]; XMFLOAT3& v2 = vertex_positions[i2]; + bool match_pos0 = - fabs(v_search_pos.x - v0.x) < FLT_EPSILON && - fabs(v_search_pos.y - v0.y) < FLT_EPSILON && - fabs(v_search_pos.z - v0.z) < FLT_EPSILON; + wi::math::float_equal(v_search_pos.x, v0.x) && + wi::math::float_equal(v_search_pos.y, v0.y) && + wi::math::float_equal(v_search_pos.z, v0.z); bool match_pos1 = - fabs(v_search_pos.x - v1.x) < FLT_EPSILON && - fabs(v_search_pos.y - v1.y) < FLT_EPSILON && - fabs(v_search_pos.z - v1.z) < FLT_EPSILON; + wi::math::float_equal(v_search_pos.x, v1.x) && + wi::math::float_equal(v_search_pos.y, v1.y) && + wi::math::float_equal(v_search_pos.z, v1.z); bool match_pos2 = - fabs(v_search_pos.x - v2.x) < FLT_EPSILON && - fabs(v_search_pos.y - v2.y) < FLT_EPSILON && - fabs(v_search_pos.z - v2.z) < FLT_EPSILON; + wi::math::float_equal(v_search_pos.x, v2.x) && + wi::math::float_equal(v_search_pos.y, v2.y) && + wi::math::float_equal(v_search_pos.z, v2.z); if (match_pos0 || match_pos1 || match_pos2) { @@ -1520,21 +1521,21 @@ namespace wi::scene const XMFLOAT2& at1 = vertex_atlas.empty() ? XMFLOAT2(0, 0) : vertex_atlas[ind1]; const bool duplicated_pos = - fabs(p0.x - p1.x) < FLT_EPSILON && - fabs(p0.y - p1.y) < FLT_EPSILON && - fabs(p0.z - p1.z) < FLT_EPSILON; + wi::math::float_equal(p0.x, p1.x) && + wi::math::float_equal(p0.y, p1.y) && + wi::math::float_equal(p0.z, p1.z); const bool duplicated_uv0 = - fabs(u00.x - u01.x) < FLT_EPSILON && - fabs(u00.y - u01.y) < FLT_EPSILON; + wi::math::float_equal(u00.x, u01.x) && + wi::math::float_equal(u00.y, u01.y); const bool duplicated_uv1 = - fabs(u10.x - u11.x) < FLT_EPSILON && - fabs(u10.y - u11.y) < FLT_EPSILON; + wi::math::float_equal(u10.x, u11.x) && + wi::math::float_equal(u10.y, u11.y); const bool duplicated_atl = - fabs(at0.x - at1.x) < FLT_EPSILON && - fabs(at0.y - at1.y) < FLT_EPSILON; + wi::math::float_equal(at0.x, at1.x) && + wi::math::float_equal(at0.y, at1.y); if (duplicated_pos && duplicated_uv0 && duplicated_uv1 && duplicated_atl) { @@ -2008,9 +2009,9 @@ namespace wi::scene const XMFLOAT3& position = mesh.vertex_positions[i]; size_t hashes[] = { - std::hash{}(position.x), - std::hash{}(position.y), - std::hash{}(position.z), + std::hash{}(int(position.x * detail)), + std::hash{}(int(position.y * detail)), + std::hash{}(int(position.z * detail)), }; size_t vertexHash = (((hashes[0] ^ (hashes[1] << 1) >> 1) ^ (hashes[2] << 1)) >> 1); diff --git a/WickedEngine/wiScene_Components.h b/WickedEngine/wiScene_Components.h index f8102d32a..56368cd0f 100644 --- a/WickedEngine/wiScene_Components.h +++ b/WickedEngine/wiScene_Components.h @@ -965,12 +965,15 @@ namespace wi::scene SAFE_TO_REGISTER = 1 << 0, DISABLE_DEACTIVATION = 1 << 1, FORCE_RESET = 1 << 2, + WIND = 1 << 3, }; uint32_t _flags = DISABLE_DEACTIVATION; float mass = 1.0f; float friction = 0.5f; float restitution = 0.0f; + float vertex_radius = 0.2f; // how much distance vertices keep from other physics bodies + float detail = 100; // precision to keep within a unit wi::vector physicsToGraphicsVertexMapping; // maps graphics vertex index to physics vertex index of the same position wi::vector graphicsToPhysicsVertexMapping; // maps a physics vertex index to first graphics vertex index of the same position wi::vector weights; // weight per physics vertex controlling the mass. (0: disable weight (no physics, only animation), 1: default weight) @@ -985,8 +988,18 @@ namespace wi::scene wi::primitive::AABB aabb; inline void SetDisableDeactivation(bool value) { if (value) { _flags |= DISABLE_DEACTIVATION; } else { _flags &= ~DISABLE_DEACTIVATION; } } + inline void SetWindEnabled(bool value) { if (value) { _flags |= WIND; } else { _flags &= ~DISABLE_DEACTIVATION; } } inline bool IsDisableDeactivation() const { return _flags & DISABLE_DEACTIVATION; } + inline bool IsWindEnabled() const { return _flags & WIND; } + + void SetDetail(float value) + { + detail = value; + physicsToGraphicsVertexMapping.clear(); + physicsToGraphicsVertexMapping.shrink_to_fit(); + physicsobject = {}; + } inline bool HasVertices() const { diff --git a/WickedEngine/wiScene_Serializers.cpp b/WickedEngine/wiScene_Serializers.cpp index 926469c0c..9d980a98f 100644 --- a/WickedEngine/wiScene_Serializers.cpp +++ b/WickedEngine/wiScene_Serializers.cpp @@ -772,6 +772,16 @@ namespace wi::scene friction = 0.5f; } + if (seri.version >= 1) + { + archive >> vertex_radius; + archive >> detail; + } + else + { + SetWindEnabled(true); + } + _flags &= ~SAFE_TO_REGISTER; } else @@ -787,6 +797,12 @@ namespace wi::scene { archive << restitution; } + + if (seri.version >= 1) + { + archive << vertex_radius; + archive << detail; + } } } void ArmatureComponent::Serialize(wi::Archive& archive, EntitySerializer& seri) diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 86b4dea5a..c0e3c5a26 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 = 495; + const int revision = 496; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);