Path Constraint - Findings #116
Replies: 3 comments 2 replies
-
Hello, To maybe make some things more clear. The requirements of the path are that:
The reason for all this is that the constraint acts like a slider constraint with the sliding axis being the tangent vector (the assumption here is that delta time will be small enough so that the path is linear for that delta time). I think you figured most of these things out already with your experiments. When you do not want the body to face the tangent of the path, I would not restrict the rotation using EPathRotationConstraintType::Free. You can then use a 2nd constraint that only constrains the rotation and not translation (e.g. with a sixdof constraint). W.r.t. what's most intuitive for users: In PathConstraintPathHermite I opted to specify tangent and normal on each point and interpolate between the 2. This gives a nice smooth path but does mean the normal is constantly changing. I guess your solution could work equally well, it depends a bit on what kind of paths you want. |
Beta Was this translation helpful? Give feedback.
-
Catmull Rom in the middle, regular chained Cubic Hermite Spline on the top. Slight difficulty getting a Catmull Rom to join smoothly into a loop (smoothing approaching and leaving normals on control-points), so I may need to check into that. There are multiple slight V-shape in the middle of the loop on the inside/far-side, though not super visible at runtime regarding Body2 on the Path Constraint. I think the more I force the Cubic Hermite Spline into wilder shapes with non-normalized tangent (ex 10/15x times a normalized-vector, ex driving with a tangent = (0,10,0) ), the harder it is to get the "nice" normal to traverse the entire segment without awkward twists. In both cases, it may just require In general, all routes now work as-is. I can just do something like const pathConstraint = new JoltPathConstraint(hermitePath, 'ConstrainToPath');
// I tend to fallback to 'take a Best-Guess, find closest on Path,
// then take that point on the line as my startPoint'
pathConstraint.setPathFraction(startPoint);
box1.physics.addJoint(box2.physics, pathConstraint);
pathConstraint.motor.mode = MotorMode.Velocity;
pathConstraint.motor.target = 0.4; I probably just need to get myself to stop fidgeting with them and actually work on the next things. I know for practical purposes, I'd probably wouldn't vary my normals on a Hermite Spline, but looks fun to use with a 'FullyConstrained' Body2 platform |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
Given this is more brainstorming and findings, I did not flag this as a Question or other tag.
I got around to finally porting Path Constraints over to my library as a more dynamic component, and was going to document some of the things I ran into as well as brainstorming I'd done around it.
Findings
I kind of lucked out when I first implemented them for the Example, and finally found out how and why some of the features I implemented worked the way they did.
https://github.com/jrouwe/JoltPhysics/blob/master/Jolt/Physics/Constraints/PathConstraint.cpp
The first I found is that the Tangents used must be along the path of traveling. Looking through the PositionConstraints and PositionMotor code (an axis constraint part), you will see a lot of usage of the path Tangent. The body will take the last fed tangent and then attempt to push the object in that direction?
This explains some of the jumping and awkward behavior I had around corners. Looking at the below image, you can see that if you are traveling clockwise, traveling along the lines using the red-tangents will force (slide constraint style) the body towards the next vertex in the line segment. Upon finally hitting this vertex, the path will (hopefully) then flip the tangent and drive you towards the subsequent point. The issue is, if you run it backwards, you will see that negative tangents (used for a reverse motor) will never push the object towards another vertex with a different tangent, and you risk that the last valid tangent is one forcing the body off the path, leading to a "flying off into the void" scenario. The only reason this 'just 4 point' path even works at a corner of points A,B,C is if when leaving path AB and a corner is hit clockwise, the equations usually choose the BC path and jumps track to that new tangent.
My solve for this was to take any sequence of 3 points, [A,B,C] and check the transition angles of AB, and BC, and then remove point B and replace the entire corner (offset by a standardized delta) with a Quadratic Bezier. This ensures that when the object hits that point in the path and subsequent tangents are much more likely to drive the object towards a future vertex in either positive or negative directions. Since then, I haven't had any stutter or confusion where following any arbitrary tangent derails or doesn't push the Body2 towards a future vertex.
Tangent Restrictions
Regarding the requirement that the Tangent is used for PositionConstraint, I need to run some extra tests to confirm how limiting this is is for
ConstrainToPath
. Given a restriction that Tangent must face towards the path, you can kind of view the ConstrainToPath as a roller-coster. Whatever you start off facing towards the path will always go that down-stream of the path, but you can wildly twist and corkscrew the item by varying the normal in any direction around the tangent/pathNote: Binormal was calc'd
Vector3.CrossToRef(tangent, normal, bi)
. Originally I'd had it flipped negative and the constraint just didn't work.Note: Vectors - Tangent (red), Normal (green), Binormal (blue)
I had originally thought that the constraint would check
mFraction
andmFraction + 1-delta
and use this to transition between points, allowing you to transition to arbitrary Tan/Norm/BiNorm at any given point in the path, allowing near uncontrolled path rotation constraints, ex "at path fraction 45, make the platform backflip in-place over the next 2 units by transitioning the ortho-vectors". Ex: in the Gif below, having the normal flip backwards mid-wayNon-ortho normals appear to just temp-derail the Body2 until it gets back to a valid set of axis:
Just specifying a valid ortho-set that points the tangent up on the path causes the Body2 to fly upward off the path, following the tangent, until it also snaps back once the motor drives it to the valid end segments with valid axis
Even if this Tangent restriction is the case, and no way around it, random 'traps on the path' can still be done. It is just that the logic would not be built into the path, but instead:
Possibly even "Go Wild" and have Body C bound to Body B via a Swing/Twist or 6-DOF motorized constraint that feeds from a parallel path data-set to force the arbitrary SetTargetOrientationCS at every path mFraction.
Specifying Normals - Most intuitive method for users
I'm currently brainstorming the best way to allow for specifying normals along the path. My current thought is that Normals will be tied to line segments, not vertex. This means that for N points, you can specify N-1 normals. The combination position/normals will then be fed into the corner-generator code to ensure smooth tangents, and every new corner-segment of lines generated will just slerp the two normals over the course of the curves.
Beta Was this translation helpful? Give feedback.
All reactions