Giter Club home page Giter Club logo

Comments (7)

floppyhammer avatar floppyhammer commented on May 10, 2024

By the way, do we have SpringJoint (or something similar) in bevy_xpbd?

image

In the case of a DistanceJoint (the green line), the blue ball will move towards the red one. A so-called SpringJoint will try to keep the blue ball in its rest position (but will deform like a spring depending on the exerted forces).

from bevy_xpbd.

Jondolf avatar Jondolf commented on May 10, 2024

I use DistanceJoint to connect hair joints. When I move the model's root entity, the hair will not be affected. But when I change the rotation, it does have effect on the hair.

I'm not 100% sure, but if the strands of hair are children of the body you're moving, I think this is somewhat expected. Changes in the parent's Transform will propagate to the children, so the positions of the hair strands will change instantly as well. The relative position of the hair and the hair's "roots" (the joints) won't change, so you don't see any effect on the hair.

However, the rotation does have an effect, because the hair will snap to the parent's rotation just like the position. The hair won't be pointing directly down anymore, so it will move due to gravity.

If you instead change the parent's Position component, does that affect the hair? There might be an inconsistency in how hierarchies are handled differently when changing Transform vs. Position. Changing the Position should currently leave the children unaffected if that's what you want.

In the future I'll try to make this consistent and maybe have some component for controlling how transform changes affect children.

By the way, do we have SpringJoint (or something similar) in bevy_xpbd?

So you want to not allow the blue ball to "swing" around the red ball when the red ball is stationary, and to be kept at some rest distance along one axis (the green line) with a given stiffness?

The PrismaticJoint is very close to this. It only allows translation along one axis like you described, and you can use joint limits to determine the minimum and maximum rest distance. You can control the compliance (inverse of stiffness), but it currently affects the strength of the joint along all axes, not just the specified axis.

If you want a custom spring joint, it should be pretty easy to add by just copying PrismaticJoint and changing a few lines. Let me know if this is something you want and I can give more help as needed.

from bevy_xpbd.

floppyhammer avatar floppyhammer commented on May 10, 2024

If you instead change the parent's Position component, does that affect the hair?

The parent doesn't have Position component. Only hair joints were added a rigidbody, so I can't really answer this question.

The translation and rotation effect I expected is that if I move the parent, it will affect the child like below (maybe through the component PreviousPosition and PreviousRotation):

8

However, this might be something beyond what a standard physics engine provides. I may need to implement such behaviour with xpbd myself.

from bevy_xpbd.

floppyhammer avatar floppyhammer commented on May 10, 2024

If you want a custom spring joint, it should be pretty easy to add by just copying PrismaticJoint and changing a few lines. Let me know if this is something you want and I can give more help as needed.

PrismaticJoint is not really what I wanted. I realize my expression isn't accurate. I wanted something like this

7

Such a joint won't allow movement in the axis direction but allow rotation along all axes (like hair or clothes).

image

from bevy_xpbd.

floppyhammer avatar floppyhammer commented on May 10, 2024

I managed to get a close effect using custom constraint:

9

I'll just leave the code here in case someone is interested.

#[derive(Component)]
struct SpringConstraint {
    entity1: Entity,
    entity2: Entity,
    // Relative position from entity2 to entity1.
    relative_rest_position: Vector,
    lagrange: Scalar,
    compliance: Scalar,
}

impl PositionConstraint for SpringConstraint {}

impl XpbdConstraint<2> for SpringConstraint {
    fn entities(&self) -> [Entity; 2] {
        [self.entity1, self.entity2]
    }

    fn clear_lagrange_multipliers(&mut self) {
        self.lagrange = 0.0;
    }

    fn solve(&mut self, bodies: [&mut RigidBodyQueryItem; 2], dt: Scalar) {
        let [body1, body2] = bodies;

        // Local attachment points at the centers of the bodies for simplicity.
        let [r1, r2] = [Vector::ZERO, Vector::ZERO];

        // Compute the positional difference.
        let delta_pos = body1.current_position() - body2.current_position();

        // The current separation distance.
        let length = delta_pos.length();

        // The value of the constraint function. When this is zero, the constraint is satisfied.
        let c = delta_pos - self.relative_rest_position;

        // Avoid division by zero and unnecessary computation.
        if length <= 0.0 || c.length() == 0.0 {
            return;
        }

        let n = c.normalize();

        // Compute generalized inverse masses (method from PositionConstraint).
        let w1 = self.compute_generalized_inverse_mass(body1, r1, n);
        let w2 = self.compute_generalized_inverse_mass(body2, r2, n);
        let w = [w1, w2];

        // Constraint gradients, i.e. how the bodies should be moved
        // relative to each other in order to satisfy the constraint.
        let gradients = [n, -n];

        // Compute Lagrange multiplier update, essentially the signed magnitude of the correction.
        let delta_lagrange =
            self.compute_lagrange_update(self.lagrange, c.length(), &gradients, &w, self.compliance, dt);
        self.lagrange += delta_lagrange;

        // Apply positional correction (method from PositionConstraint).
        self.apply_positional_correction(body1, body2, delta_lagrange, n, r1, r2);
    }
}

from bevy_xpbd.

Jondolf avatar Jondolf commented on May 10, 2024

Isn't that just the DistanceJoint? It allows setting a rest distance (and optional min/max distance limits), which is what your custom constraint does.

from bevy_xpbd.

floppyhammer avatar floppyhammer commented on May 10, 2024

From my limited experience of using DistanceJoint, not exactly. This custom constraint keeps the body at its rest position (relative), while a DistanceJoint only limits movement along the joint direction.

Initial setup

image

How a DistanceJoint behaves (with gravity)

image

How this custom joint behaves (with gravity)

image

from bevy_xpbd.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.