added swing-twist constraint and constraint debug size control
This commit is contained in:
Binary file not shown.
+115
-21
@@ -30,6 +30,23 @@ void ConstraintWindow::Create(EditorComponent* _editor)
|
||||
infoLabel.SetText("Constraints can be added to bind one or two rigid bodies. If only one body is specified, then it will be bound to the constraint's location. If two bodies are specified, they will be bound together with the constraint acting as the pivot between them at the time of binding.");
|
||||
AddWidget(&infoLabel);
|
||||
|
||||
physicsDebugCheckBox.Create(ICON_EYE " Physics visualizer: ");
|
||||
physicsDebugCheckBox.SetTooltip("Visualize the physics world");
|
||||
physicsDebugCheckBox.OnClick([=](wi::gui::EventArgs args) {
|
||||
wi::physics::SetDebugDrawEnabled(args.bValue);
|
||||
editor->generalWnd.physicsDebugCheckBox.SetCheck(args.bValue);
|
||||
editor->componentsWnd.rigidWnd.physicsDebugCheckBox.SetCheck(args.bValue);
|
||||
});
|
||||
physicsDebugCheckBox.SetCheck(wi::physics::IsDebugDrawEnabled());
|
||||
AddWidget(&physicsDebugCheckBox);
|
||||
|
||||
constraintDebugSlider.Create(0, 10, 1, 100, "Debug size: ");
|
||||
constraintDebugSlider.SetValue(wi::physics::GetConstraintDebugSize());
|
||||
constraintDebugSlider.OnSlide([](wi::gui::EventArgs args) {
|
||||
wi::physics::SetConstraintDebugSize(args.fValue);
|
||||
});
|
||||
AddWidget(&constraintDebugSlider);
|
||||
|
||||
rebindButton.Create("Rebind Constraint");
|
||||
rebindButton.OnClick([this](wi::gui::EventArgs args) {
|
||||
wi::scene::Scene& scene = editor->GetCurrentScene();
|
||||
@@ -51,6 +68,7 @@ void ConstraintWindow::Create(EditorComponent* _editor)
|
||||
typeComboBox.AddItem("Hinge", (uint64_t)PhysicsConstraintComponent::Type::Hinge);
|
||||
typeComboBox.AddItem("Cone", (uint64_t)PhysicsConstraintComponent::Type::Cone);
|
||||
typeComboBox.AddItem("Six DOF", (uint64_t)PhysicsConstraintComponent::Type::SixDOF);
|
||||
typeComboBox.AddItem("Swing Twist", (uint64_t)PhysicsConstraintComponent::Type::SwingTwist);
|
||||
typeComboBox.OnSelect([&](wi::gui::EventArgs args) {
|
||||
wi::scene::Scene& scene = editor->GetCurrentScene();
|
||||
for (auto& x : editor->translator.selected)
|
||||
@@ -121,6 +139,9 @@ void ConstraintWindow::Create(EditorComponent* _editor)
|
||||
case PhysicsConstraintComponent::Type::Cone:
|
||||
physicscomponent->cone_constraint.half_cone_angle = wi::math::DegreesToRadians(args.fValue);
|
||||
break;
|
||||
case PhysicsConstraintComponent::Type::SwingTwist:
|
||||
physicscomponent->swing_twist.min_twist_angle = wi::math::DegreesToRadians(args.fValue);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -146,6 +167,9 @@ void ConstraintWindow::Create(EditorComponent* _editor)
|
||||
case PhysicsConstraintComponent::Type::Hinge:
|
||||
physicscomponent->hinge_constraint.max_angle = wi::math::DegreesToRadians(args.fValue);
|
||||
break;
|
||||
case PhysicsConstraintComponent::Type::SwingTwist:
|
||||
physicscomponent->swing_twist.max_twist_angle = wi::math::DegreesToRadians(args.fValue);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -157,6 +181,38 @@ void ConstraintWindow::Create(EditorComponent* _editor)
|
||||
|
||||
|
||||
|
||||
normalConeSlider.Create(0, 90, 1, 90, "Normal Angle: ");
|
||||
normalConeSlider.OnSlide([&](wi::gui::EventArgs args) {
|
||||
wi::scene::Scene& scene = editor->GetCurrentScene();
|
||||
for (auto& x : editor->translator.selected)
|
||||
{
|
||||
PhysicsConstraintComponent* physicscomponent = scene.constraints.GetComponent(x.entity);
|
||||
if (physicscomponent != nullptr)
|
||||
{
|
||||
physicscomponent->swing_twist.normal_half_cone_angle = wi::math::DegreesToRadians(args.fValue);
|
||||
physicscomponent->SetRefreshParametersNeeded(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
AddWidget(&normalConeSlider);
|
||||
|
||||
planeConeSlider.Create(0, 90, 1, 90, "Plane Angle: ");
|
||||
planeConeSlider.OnSlide([&](wi::gui::EventArgs args) {
|
||||
wi::scene::Scene& scene = editor->GetCurrentScene();
|
||||
for (auto& x : editor->translator.selected)
|
||||
{
|
||||
PhysicsConstraintComponent* physicscomponent = scene.constraints.GetComponent(x.entity);
|
||||
if (physicscomponent != nullptr)
|
||||
{
|
||||
physicscomponent->swing_twist.plane_half_cone_angle = wi::math::DegreesToRadians(args.fValue);
|
||||
physicscomponent->SetRefreshParametersNeeded(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
AddWidget(&planeConeSlider);
|
||||
|
||||
|
||||
|
||||
|
||||
fixedXButton.Create("Fix X");
|
||||
fixedXButton.OnClick([=](wi::gui::EventArgs args) {
|
||||
@@ -479,6 +535,16 @@ void ConstraintWindow::SetEntity(Entity entity)
|
||||
minSlider.SetRange(0, 90);
|
||||
minSlider.SetValue(wi::math::RadiansToDegrees(physicsComponent->cone_constraint.half_cone_angle));
|
||||
break;
|
||||
case PhysicsConstraintComponent::Type::SwingTwist:
|
||||
minSlider.SetText("Min twist angle: ");
|
||||
maxSlider.SetText("Max twist angle: ");
|
||||
minSlider.SetRange(-180, 0);
|
||||
maxSlider.SetRange(0, 180);
|
||||
minSlider.SetValue(wi::math::RadiansToDegrees(physicsComponent->swing_twist.min_twist_angle));
|
||||
maxSlider.SetValue(wi::math::RadiansToDegrees(physicsComponent->swing_twist.max_twist_angle));
|
||||
normalConeSlider.SetValue(wi::math::RadiansToDegrees(physicsComponent->swing_twist.normal_half_cone_angle));
|
||||
planeConeSlider.SetValue(wi::math::RadiansToDegrees(physicsComponent->swing_twist.plane_half_cone_angle));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -569,6 +635,7 @@ void ConstraintWindow::ResizeLayout()
|
||||
const PhysicsConstraintComponent* physicsComponent = scene.constraints.GetComponent(entity);
|
||||
if (physicsComponent != nullptr)
|
||||
{
|
||||
|
||||
switch (physicsComponent->type)
|
||||
{
|
||||
case PhysicsConstraintComponent::Type::Distance:
|
||||
@@ -576,6 +643,34 @@ void ConstraintWindow::ResizeLayout()
|
||||
minSlider.SetVisible(true);
|
||||
maxSlider.SetVisible(true);
|
||||
|
||||
normalConeSlider.SetVisible(false);
|
||||
planeConeSlider.SetVisible(false);
|
||||
|
||||
fixedXButton.SetVisible(false);
|
||||
fixedYButton.SetVisible(false);
|
||||
fixedZButton.SetVisible(false);
|
||||
fixedXRotationButton.SetVisible(false);
|
||||
fixedYRotationButton.SetVisible(false);
|
||||
fixedZRotationButton.SetVisible(false);
|
||||
minTranslationXSlider.SetVisible(false);
|
||||
minTranslationYSlider.SetVisible(false);
|
||||
minTranslationZSlider.SetVisible(false);
|
||||
maxTranslationXSlider.SetVisible(false);
|
||||
maxTranslationYSlider.SetVisible(false);
|
||||
maxTranslationZSlider.SetVisible(false);
|
||||
minRotationXSlider.SetVisible(false);
|
||||
minRotationYSlider.SetVisible(false);
|
||||
minRotationZSlider.SetVisible(false);
|
||||
maxRotationXSlider.SetVisible(false);
|
||||
maxRotationYSlider.SetVisible(false);
|
||||
maxRotationZSlider.SetVisible(false);
|
||||
break;
|
||||
case PhysicsConstraintComponent::Type::SwingTwist:
|
||||
minSlider.SetVisible(true);
|
||||
maxSlider.SetVisible(true);
|
||||
normalConeSlider.SetVisible(true);
|
||||
planeConeSlider.SetVisible(true);
|
||||
|
||||
fixedXButton.SetVisible(false);
|
||||
fixedYButton.SetVisible(false);
|
||||
fixedZButton.SetVisible(false);
|
||||
@@ -599,6 +694,9 @@ void ConstraintWindow::ResizeLayout()
|
||||
minSlider.SetVisible(true);
|
||||
maxSlider.SetVisible(false);
|
||||
|
||||
normalConeSlider.SetVisible(false);
|
||||
planeConeSlider.SetVisible(false);
|
||||
|
||||
fixedXButton.SetVisible(false);
|
||||
fixedYButton.SetVisible(false);
|
||||
fixedZButton.SetVisible(false);
|
||||
@@ -622,6 +720,9 @@ void ConstraintWindow::ResizeLayout()
|
||||
minSlider.SetVisible(false);
|
||||
maxSlider.SetVisible(false);
|
||||
|
||||
normalConeSlider.SetVisible(false);
|
||||
planeConeSlider.SetVisible(false);
|
||||
|
||||
fixedXButton.SetVisible(true);
|
||||
fixedYButton.SetVisible(true);
|
||||
fixedZButton.SetVisible(true);
|
||||
@@ -661,30 +762,20 @@ void ConstraintWindow::ResizeLayout()
|
||||
add(maxRotationZSlider);
|
||||
break;
|
||||
default:
|
||||
minSlider.SetVisible(false);
|
||||
maxSlider.SetVisible(false);
|
||||
|
||||
fixedXButton.SetVisible(false);
|
||||
fixedYButton.SetVisible(false);
|
||||
fixedZButton.SetVisible(false);
|
||||
fixedXRotationButton.SetVisible(false);
|
||||
fixedYRotationButton.SetVisible(false);
|
||||
fixedZRotationButton.SetVisible(false);
|
||||
minTranslationXSlider.SetVisible(false);
|
||||
minTranslationYSlider.SetVisible(false);
|
||||
minTranslationZSlider.SetVisible(false);
|
||||
maxTranslationXSlider.SetVisible(false);
|
||||
maxTranslationYSlider.SetVisible(false);
|
||||
maxTranslationZSlider.SetVisible(false);
|
||||
minRotationXSlider.SetVisible(false);
|
||||
minRotationYSlider.SetVisible(false);
|
||||
minRotationZSlider.SetVisible(false);
|
||||
maxRotationXSlider.SetVisible(false);
|
||||
maxRotationYSlider.SetVisible(false);
|
||||
maxRotationZSlider.SetVisible(false);
|
||||
break;
|
||||
}
|
||||
|
||||
margin_right = 40;
|
||||
|
||||
if (normalConeSlider.IsVisible())
|
||||
{
|
||||
add(normalConeSlider);
|
||||
}
|
||||
if (planeConeSlider.IsVisible())
|
||||
{
|
||||
add(planeConeSlider);
|
||||
}
|
||||
|
||||
if (minSlider.IsVisible())
|
||||
{
|
||||
add(minSlider);
|
||||
@@ -693,5 +784,8 @@ void ConstraintWindow::ResizeLayout()
|
||||
{
|
||||
add(maxSlider);
|
||||
}
|
||||
|
||||
add_right(physicsDebugCheckBox);
|
||||
add(constraintDebugSlider);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ public:
|
||||
void SetEntity(wi::ecs::Entity entity);
|
||||
|
||||
wi::gui::Label infoLabel;
|
||||
wi::gui::CheckBox physicsDebugCheckBox;
|
||||
wi::gui::Slider constraintDebugSlider;
|
||||
wi::gui::Button rebindButton;
|
||||
wi::gui::ComboBox typeComboBox;
|
||||
wi::gui::ComboBox bodyAComboBox;
|
||||
@@ -18,6 +20,9 @@ public:
|
||||
wi::gui::Slider minSlider;
|
||||
wi::gui::Slider maxSlider;
|
||||
|
||||
wi::gui::Slider normalConeSlider;
|
||||
wi::gui::Slider planeConeSlider;
|
||||
|
||||
wi::gui::Button fixedXButton;
|
||||
wi::gui::Button fixedYButton;
|
||||
wi::gui::Button fixedZButton;
|
||||
|
||||
@@ -33,6 +33,7 @@ void GeneralWindow::Create(EditorComponent* _editor)
|
||||
physicsDebugCheckBox.OnClick([=](wi::gui::EventArgs args) {
|
||||
wi::physics::SetDebugDrawEnabled(args.bValue);
|
||||
editor->componentsWnd.rigidWnd.physicsDebugCheckBox.SetCheck(args.bValue);
|
||||
editor->componentsWnd.constraintWnd.physicsDebugCheckBox.SetCheck(args.bValue);
|
||||
});
|
||||
physicsDebugCheckBox.SetCheck(wi::physics::IsDebugDrawEnabled());
|
||||
AddWidget(&physicsDebugCheckBox);
|
||||
|
||||
@@ -355,6 +355,7 @@ void RigidBodyWindow::Create(EditorComponent* _editor)
|
||||
physicsDebugCheckBox.OnClick([=](wi::gui::EventArgs args) {
|
||||
wi::physics::SetDebugDrawEnabled(args.bValue);
|
||||
editor->generalWnd.physicsDebugCheckBox.SetCheck(args.bValue);
|
||||
editor->componentsWnd.constraintWnd.physicsDebugCheckBox.SetCheck(args.bValue);
|
||||
});
|
||||
physicsDebugCheckBox.SetCheck(wi::physics::IsDebugDrawEnabled());
|
||||
AddWidget(&physicsDebugCheckBox);
|
||||
|
||||
@@ -30,6 +30,10 @@ namespace wi::physics
|
||||
void SetDebugDrawEnabled(bool value);
|
||||
bool IsDebugDrawEnabled();
|
||||
|
||||
// Adjust constraint debugging sizes
|
||||
void SetConstraintDebugSize(float value);
|
||||
float GetConstraintDebugSize();
|
||||
|
||||
// Set the accuracy of the simulation
|
||||
// This value corresponds to maximum simulation step count
|
||||
// Higher values will be slower but more accurate
|
||||
|
||||
@@ -81,6 +81,7 @@ namespace wi::physics
|
||||
bool ENABLED = true;
|
||||
bool SIMULATION_ENABLED = true;
|
||||
bool DEBUGDRAW_ENABLED = false;
|
||||
float CONSTRAINT_DEBUGSIZE = 1;
|
||||
int ACCURACY = 4;
|
||||
int softbodyIterationCount = 6;
|
||||
float TIMESTEP = 1.0f / 60.0f;
|
||||
@@ -1056,6 +1057,19 @@ namespace wi::physics
|
||||
settings.mLimitMax[SixDOFConstraintSettings::EAxis::RotationZ] = physicscomponent.six_dof.maxRotationAxes.z;
|
||||
physicsobject.constraint = settings.Create(*body1, *body2);
|
||||
}
|
||||
else if (physicscomponent.type == PhysicsConstraintComponent::Type::SwingTwist)
|
||||
{
|
||||
SwingTwistConstraintSettings settings;
|
||||
settings.mSpace = EConstraintSpace::WorldSpace;
|
||||
settings.mPosition1 = settings.mPosition2 = cast(transform.GetPosition());
|
||||
settings.mTwistAxis1 = settings.mTwistAxis2 = cast(transform.GetRight()).Normalized();
|
||||
settings.mPlaneAxis1 = settings.mPlaneAxis2 = cast(transform.GetUp()).Normalized();
|
||||
settings.mNormalHalfConeAngle = physicscomponent.swing_twist.normal_half_cone_angle;
|
||||
settings.mPlaneHalfConeAngle = physicscomponent.swing_twist.plane_half_cone_angle;
|
||||
settings.mTwistMinAngle = physicscomponent.swing_twist.min_twist_angle;
|
||||
settings.mTwistMaxAngle = physicscomponent.swing_twist.max_twist_angle;
|
||||
physicsobject.constraint = settings.Create(*body1, *body2);
|
||||
}
|
||||
else
|
||||
{
|
||||
wilog("Constraint creation failed: constraint type is not valid!");
|
||||
@@ -1812,6 +1826,9 @@ namespace wi::physics
|
||||
bool IsDebugDrawEnabled() { return DEBUGDRAW_ENABLED; }
|
||||
void SetDebugDrawEnabled(bool value) { DEBUGDRAW_ENABLED = value; }
|
||||
|
||||
void SetConstraintDebugSize(float value) { CONSTRAINT_DEBUGSIZE = value; }
|
||||
float GetConstraintDebugSize() { return CONSTRAINT_DEBUGSIZE; }
|
||||
|
||||
int GetAccuracy() { return ACCURACY; }
|
||||
void SetAccuracy(int value) { ACCURACY = value; }
|
||||
|
||||
@@ -1989,6 +2006,14 @@ namespace wi::physics
|
||||
ptr->SetTranslationLimits(cast(physicscomponent.six_dof.minTranslationAxes), cast(physicscomponent.six_dof.maxTranslationAxes));
|
||||
ptr->SetRotationLimits(cast(physicscomponent.six_dof.minRotationAxes), cast(physicscomponent.six_dof.maxRotationAxes));
|
||||
}
|
||||
else if (physicscomponent.type == PhysicsConstraintComponent::Type::SwingTwist)
|
||||
{
|
||||
SwingTwistConstraint* ptr = ((SwingTwistConstraint*)constraint.constraint.GetPtr());
|
||||
ptr->SetNormalHalfConeAngle(physicscomponent.swing_twist.normal_half_cone_angle);
|
||||
ptr->SetPlaneHalfConeAngle(physicscomponent.swing_twist.plane_half_cone_angle);
|
||||
ptr->SetTwistMinAngle(physicscomponent.swing_twist.min_twist_angle);
|
||||
ptr->SetTwistMaxAngle(physicscomponent.swing_twist.max_twist_angle);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -2345,6 +2370,7 @@ namespace wi::physics
|
||||
if (physicscomponent.physicsobject == nullptr)
|
||||
return;
|
||||
Constraint& constraint = GetConstraint(physicscomponent);
|
||||
constraint.constraint->SetDrawConstraintSize(CONSTRAINT_DEBUGSIZE);
|
||||
if (constraint.body1_self.IsInvalid() && constraint.body2_self.IsInvalid())
|
||||
return;
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace wi::scene
|
||||
wi::ecs::ComponentManager<wi::VoxelGrid>& voxel_grids = componentLibrary.Register<wi::VoxelGrid>("wi::scene::Scene::voxel_grids");
|
||||
wi::ecs::ComponentManager<MetadataComponent>& metadatas = componentLibrary.Register<MetadataComponent>("wi::scene::Scene::metadatas");
|
||||
wi::ecs::ComponentManager<CharacterComponent>& characters = componentLibrary.Register<CharacterComponent>("wi::scene::Scene::characters");
|
||||
wi::ecs::ComponentManager<PhysicsConstraintComponent>& constraints = componentLibrary.Register<PhysicsConstraintComponent>("wi::scene::Scene::constraints", 1); // version = 1
|
||||
wi::ecs::ComponentManager<PhysicsConstraintComponent>& constraints = componentLibrary.Register<PhysicsConstraintComponent>("wi::scene::Scene::constraints", 2); // version = 2
|
||||
|
||||
// Non-serialized attributes:
|
||||
float dt = 0;
|
||||
|
||||
@@ -543,6 +543,7 @@ namespace wi::scene
|
||||
Hinge, // rotation around a point on the UP axis of the contraint transform
|
||||
Cone, // constrain to a cone shape specified by the cone angle
|
||||
SixDOF, // manual specification of axes movement and rotation limits
|
||||
SwingTwist, // cone + rotational limits
|
||||
} type = Type::Fixed;
|
||||
|
||||
wi::ecs::Entity bodyA = wi::ecs::INVALID_ENTITY;
|
||||
@@ -587,6 +588,14 @@ namespace wi::scene
|
||||
void SetFreeRotationZ() { minRotationAxes.z = -XM_PI; maxRotationAxes.z = XM_PI; }
|
||||
} six_dof;
|
||||
|
||||
struct SwingTwistConstraintSettings
|
||||
{
|
||||
float normal_half_cone_angle = 0; // radians
|
||||
float plane_half_cone_angle = 0; // radians
|
||||
float min_twist_angle = 0; // radians [-PI, PI]
|
||||
float max_twist_angle = 0; // radians [-PI, PI]
|
||||
} swing_twist;
|
||||
|
||||
// Non-serialized attributes:
|
||||
std::shared_ptr<void> physicsobject = nullptr; // You can set to null to recreate the physics object the next time phsyics system will be running.
|
||||
|
||||
|
||||
@@ -929,6 +929,13 @@ namespace wi::scene
|
||||
archive >> six_dof.minRotationAxes;
|
||||
archive >> six_dof.maxRotationAxes;
|
||||
}
|
||||
if (seri.GetVersion() >= 2)
|
||||
{
|
||||
archive >> swing_twist.normal_half_cone_angle;
|
||||
archive >> swing_twist.plane_half_cone_angle;
|
||||
archive >> swing_twist.min_twist_angle;
|
||||
archive >> swing_twist.max_twist_angle;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -948,6 +955,13 @@ namespace wi::scene
|
||||
archive << six_dof.minRotationAxes;
|
||||
archive << six_dof.maxRotationAxes;
|
||||
}
|
||||
if (seri.GetVersion() >= 2)
|
||||
{
|
||||
archive << swing_twist.normal_half_cone_angle;
|
||||
archive << swing_twist.plane_half_cone_angle;
|
||||
archive << swing_twist.min_twist_angle;
|
||||
archive << swing_twist.max_twist_angle;
|
||||
}
|
||||
}
|
||||
}
|
||||
void SoftBodyPhysicsComponent::Serialize(wi::Archive& archive, EntitySerializer& seri)
|
||||
|
||||
@@ -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 = 732;
|
||||
const int revision = 733;
|
||||
|
||||
const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user