Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- commit 0962c43915dc6c07110b6826e43891bc826ec049
- Author: Aron Granberg <aron.granberg@gmail.com>
- Date: Fri May 20 16:10:32 2022 +0200
- [ALINE] Fixed some edge cases in Draw.WireCapsule and Draw.WireCapsule which could cause NaNs and other subtle errors.
- diff --git a/Assets/AstarPathfindingProject/Drawing/CommandBuilder.cs b/Assets/AstarPathfindingProject/Drawing/CommandBuilder.cs
- index 3b27ddd9..4690b3f3 100644
- --- a/Assets/AstarPathfindingProject/Drawing/CommandBuilder.cs
- +++ b/Assets/AstarPathfindingProject/Drawing/CommandBuilder.cs
- @@ -944,8 +944,10 @@ namespace Pathfinding.Drawing {
- }
- /** Draws a cylinder.
- - * The cylinder's bottom circle will be centered at the \a position parameter.
- - * The cylinder's orientation will be determined by the \a up and \a height parameters.
- + * \param position The center of the cylinder's "bottom" circle.
- + * \param up The cylinder's main axis. Does not have to be normalized. If zero, nothing will be drawn.
- + * \param height The length of the cylinder, as measured along it's main axis.
- + * \param radius The radius of the cylinder.
- *
- * \snippet DrawingSnippets.cs Draw.WireCylinder2
- *
- @@ -955,18 +957,28 @@ namespace Pathfinding.Drawing {
- var tangent = math.normalizesafe(math.cross(up, new float3(1, 1, 1)));
- // Note: second parameter is normalized (-1,1,1)
- - if (math.all(tangent == float3.zero)) tangent = math.cross(up, new float3(-0.577350269f, 0.577350269f, 0.577350269f));
- + const float SQRT_ONE_THIRD = 0.577350269f;
- + if (math.all(tangent == float3.zero)) tangent = math.cross(up, new float3(-SQRT_ONE_THIRD, SQRT_ONE_THIRD, SQRT_ONE_THIRD));
- - PushMatrix(Matrix4x4.TRS(position, Quaternion.LookRotation(tangent, up), new Vector3(radius, height, radius)));
- - CircleXZ(float3.zero, 1);
- - if (height > 0) {
- - CircleXZ(new float3(0, 1, 0), 1);
- - Line(new float3(1, 0, 0), new float3(1, 1, 0));
- - Line(new float3(-1, 0, 0), new float3(-1, 1, 0));
- - Line(new float3(0, 0, 1), new float3(0, 1, 1));
- - Line(new float3(0, 0, -1), new float3(0, 1, -1));
- + var rotation = quaternion.LookRotation(tangent, up);
- +
- + // If we get a NaN here then either
- + // * one of the input parameters contained nans (bad)
- + // * up is zero, or very close to zero
- + //
- + // In any case, we cannot draw anything.
- + if (!math.any(math.isnan(rotation.value))) {
- + PushMatrix(float4x4.TRS(position, rotation, new float3(radius, height, radius)));
- + CircleXZ(float3.zero, 1);
- + if (height > 0) {
- + CircleXZ(new float3(0, 1, 0), 1);
- + Line(new float3(1, 0, 0), new float3(1, 1, 0));
- + Line(new float3(-1, 0, 0), new float3(-1, 1, 0));
- + Line(new float3(0, 0, 1), new float3(0, 1, 1));
- + Line(new float3(0, 0, -1), new float3(0, 1, -1));
- + }
- + PopMatrix();
- }
- - PopMatrix();
- }
- /** Draws a capsule with a (start,end) parameterization.
- @@ -998,7 +1010,7 @@ namespace Pathfinding.Drawing {
- // TODO: Change to center, up, height parameterization
- /** Draws a capsule with a (position,direction/length) parameterization.
- * \param position One endpoint of the capsule. This is at the edge of the capsule, not at the center of one of the hemispheres.
- - * \param direction The main axis of the capsule.
- + * \param direction The main axis of the capsule. Does not have to be normalized. If zero, nothing will be drawn.
- * \param length Distance between the two endpoints of the capsule. The length will be clamped to be at least 2*radius.
- * \param radius The radius of the capsule.
- *
- @@ -1008,37 +1020,48 @@ namespace Pathfinding.Drawing {
- */
- public void WireCapsule (float3 position, float3 direction, float length, float radius) {
- direction = math.normalizesafe(direction);
- +
- if (radius <= 0) {
- Line(position, position + direction * length);
- } else {
- + const float SQRT_ONE_THIRD = 0.577350269f;
- // Note; second parameter is normalized (1,1,1)
- - var tangent = math.cross(direction, new float3(0.577350269f, 0.577350269f, 0.577350269f));
- + var tangent = math.cross(direction, new float3(SQRT_ONE_THIRD, SQRT_ONE_THIRD, SQRT_ONE_THIRD));
- // Note: second parameter is normalized (-1,1,1)
- - if (math.all(tangent == float3.zero)) tangent = math.cross(direction, new float3(-0.577350269f, 0.577350269f, 0.577350269f));
- + if (math.all(tangent == float3.zero)) tangent = math.cross(direction, new float3(-SQRT_ONE_THIRD, SQRT_ONE_THIRD, SQRT_ONE_THIRD));
- length = math.max(length, radius*2);
- - PushMatrix(Matrix4x4.TRS(position, Quaternion.LookRotation(tangent, direction), Vector3.one));
- - CircleXZ(new float3(0, radius, 0), radius);
- - CircleXY(new float3(0, radius, 0), radius, Mathf.PI, 2 * Mathf.PI);
- - PushMatrix(XZtoYZPlaneMatrix);
- - CircleXZ(new float3(radius, 0, 0), radius, Mathf.PI*0.5f, Mathf.PI*1.5f);
- - PopMatrix();
- - if (length > 0) {
- - var upperY = length - radius;
- - var lowerY = radius;
- - CircleXZ(new float3(0, upperY, 0), radius);
- - CircleXY(new float3(0, upperY, 0), radius, 0, Mathf.PI);
- + var rotation = quaternion.LookRotation(tangent, direction);
- +
- + // If we get a NaN here then either
- + // * one of the input parameters contained nans (bad)
- + // * direction is zero, or very close to zero
- + //
- + // In any case, we cannot draw anything.
- + if (!math.any(math.isnan(rotation.value))) {
- + PushMatrix(float4x4.TRS(position, rotation, 1));
- + CircleXZ(new float3(0, radius, 0), radius);
- + CircleXY(new float3(0, radius, 0), radius, Mathf.PI, 2 * Mathf.PI);
- PushMatrix(XZtoYZPlaneMatrix);
- - CircleXZ(new float3(upperY, 0, 0), radius, -Mathf.PI*0.5f, Mathf.PI*0.5f);
- + CircleXZ(new float3(radius, 0, 0), radius, Mathf.PI*0.5f, Mathf.PI*1.5f);
- + PopMatrix();
- + if (length > 0) {
- + var upperY = length - radius;
- + var lowerY = radius;
- + CircleXZ(new float3(0, upperY, 0), radius);
- + CircleXY(new float3(0, upperY, 0), radius, 0, Mathf.PI);
- + PushMatrix(XZtoYZPlaneMatrix);
- + CircleXZ(new float3(upperY, 0, 0), radius, -Mathf.PI*0.5f, Mathf.PI*0.5f);
- + PopMatrix();
- + Line(new float3(radius, lowerY, 0), new float3(radius, upperY, 0));
- + Line(new float3(-radius, lowerY, 0), new float3(-radius, upperY, 0));
- + Line(new float3(0, lowerY, radius), new float3(0, upperY, radius));
- + Line(new float3(0, lowerY, -radius), new float3(0, upperY, -radius));
- + }
- PopMatrix();
- - Line(new float3(radius, lowerY, 0), new float3(radius, upperY, 0));
- - Line(new float3(-radius, lowerY, 0), new float3(-radius, upperY, 0));
- - Line(new float3(0, lowerY, radius), new float3(0, upperY, radius));
- - Line(new float3(0, lowerY, -radius), new float3(0, upperY, -radius));
- }
- - PopMatrix();
- }
- }
- @@ -1855,7 +1878,8 @@ namespace Pathfinding.Drawing {
- PopMatrix();
- }
- - private float3 calculateTangent (float3 normal) {
- + /** Returns an arbitrary vector which is orthogonal to the given one */
- + private static float3 calculateTangent (float3 normal) {
- var tangent = math.cross(new float3(0, 1, 0), normal);
- if (math.all(tangent == 0)) tangent = math.cross(new float3(1, 0, 0), normal);
- diff --git a/Assets/AstarPathfindingProject/Drawing/CommandBuilderExtensions.cs b/Assets/AstarPathfindingProject/Drawing/CommandBuilderExtensions.cs
- index be852a63..bbfbefb6 100644
- --- a/Assets/AstarPathfindingProject/Drawing/CommandBuilderExtensions.cs
- +++ b/Assets/AstarPathfindingProject/Drawing/CommandBuilderExtensions.cs
- @@ -176,24 +176,36 @@ namespace Pathfinding.Drawing {
- WireCylinder(bottom, top - bottom, math.length(top - bottom), radius, color);
- }
- - /** \copydocref{WireCylinder(float3,float3,float,float)} */
- + /** \copydocref{WireCylinder(float3,float3,float,float)}
- + * \param color Color of the object
- + */
- public void WireCylinder (float3 position, float3 up, float height, float radius, Color color) {
- PushColor(color);
- var tangent = math.normalizesafe(math.cross(up, new float3(1, 1, 1)));
- // Note: second parameter is normalized (-1,1,1)
- - if (math.all(tangent == float3.zero)) tangent = math.cross(up, new float3(-0.577350269f, 0.577350269f, 0.577350269f));
- + const float SQRT_ONE_THIRD = 0.577350269f;
- + if (math.all(tangent == float3.zero)) tangent = math.cross(up, new float3(-SQRT_ONE_THIRD, SQRT_ONE_THIRD, SQRT_ONE_THIRD));
- +
- + var rotation = quaternion.LookRotation(tangent, up);
- - PushMatrix(Matrix4x4.TRS(position, Quaternion.LookRotation(tangent, up), new Vector3(radius, height, radius)));
- - CircleXZ(float3.zero, 1);
- - if (height > 0) {
- - CircleXZ(new float3(0, 1, 0), 1);
- - Line(new float3(1, 0, 0), new float3(1, 1, 0));
- - Line(new float3(-1, 0, 0), new float3(-1, 1, 0));
- - Line(new float3(0, 0, 1), new float3(0, 1, 1));
- - Line(new float3(0, 0, -1), new float3(0, 1, -1));
- + // If we get a NaN here then either
- + // * one of the input parameters contained nans (bad)
- + // * up is zero, or very close to zero
- + //
- + // In any case, we cannot draw anything.
- + if (!math.any(math.isnan(rotation.value))) {
- + PushMatrix(float4x4.TRS(position, rotation, new float3(radius, height, radius)));
- + CircleXZ(float3.zero, 1);
- + if (height > 0) {
- + CircleXZ(new float3(0, 1, 0), 1);
- + Line(new float3(1, 0, 0), new float3(1, 1, 0));
- + Line(new float3(-1, 0, 0), new float3(-1, 1, 0));
- + Line(new float3(0, 0, 1), new float3(0, 1, 1));
- + Line(new float3(0, 0, -1), new float3(0, 1, -1));
- + }
- + PopMatrix();
- }
- - PopMatrix();
- PopColor();
- }
- @@ -223,37 +235,48 @@ namespace Pathfinding.Drawing {
- public void WireCapsule (float3 position, float3 direction, float length, float radius, Color color) {
- PushColor(color);
- direction = math.normalizesafe(direction);
- +
- if (radius <= 0) {
- Line(position, position + direction * length);
- } else {
- + const float SQRT_ONE_THIRD = 0.577350269f;
- // Note; second parameter is normalized (1,1,1)
- - var tangent = math.cross(direction, new float3(0.577350269f, 0.577350269f, 0.577350269f));
- + var tangent = math.cross(direction, new float3(SQRT_ONE_THIRD, SQRT_ONE_THIRD, SQRT_ONE_THIRD));
- // Note: second parameter is normalized (-1,1,1)
- - if (math.all(tangent == float3.zero)) tangent = math.cross(direction, new float3(-0.577350269f, 0.577350269f, 0.577350269f));
- + if (math.all(tangent == float3.zero)) tangent = math.cross(direction, new float3(-SQRT_ONE_THIRD, SQRT_ONE_THIRD, SQRT_ONE_THIRD));
- length = math.max(length, radius*2);
- - PushMatrix(Matrix4x4.TRS(position, Quaternion.LookRotation(tangent, direction), Vector3.one));
- - CircleXZ(new float3(0, radius, 0), radius);
- - CircleXY(new float3(0, radius, 0), radius, Mathf.PI, 2 * Mathf.PI);
- - PushMatrix(XZtoYZPlaneMatrix);
- - CircleXZ(new float3(radius, 0, 0), radius, Mathf.PI*0.5f, Mathf.PI*1.5f);
- - PopMatrix();
- - if (length > 0) {
- - var upperY = length - radius;
- - var lowerY = radius;
- - CircleXZ(new float3(0, upperY, 0), radius);
- - CircleXY(new float3(0, upperY, 0), radius, 0, Mathf.PI);
- + var rotation = quaternion.LookRotation(tangent, direction);
- +
- + // If we get a NaN here then either
- + // * one of the input parameters contained nans (bad)
- + // * direction is zero, or very close to zero
- + //
- + // In any case, we cannot draw anything.
- + if (!math.any(math.isnan(rotation.value))) {
- + PushMatrix(float4x4.TRS(position, rotation, 1));
- + CircleXZ(new float3(0, radius, 0), radius);
- + CircleXY(new float3(0, radius, 0), radius, Mathf.PI, 2 * Mathf.PI);
- PushMatrix(XZtoYZPlaneMatrix);
- - CircleXZ(new float3(upperY, 0, 0), radius, -Mathf.PI*0.5f, Mathf.PI*0.5f);
- + CircleXZ(new float3(radius, 0, 0), radius, Mathf.PI*0.5f, Mathf.PI*1.5f);
- + PopMatrix();
- + if (length > 0) {
- + var upperY = length - radius;
- + var lowerY = radius;
- + CircleXZ(new float3(0, upperY, 0), radius);
- + CircleXY(new float3(0, upperY, 0), radius, 0, Mathf.PI);
- + PushMatrix(XZtoYZPlaneMatrix);
- + CircleXZ(new float3(upperY, 0, 0), radius, -Mathf.PI*0.5f, Mathf.PI*0.5f);
- + PopMatrix();
- + Line(new float3(radius, lowerY, 0), new float3(radius, upperY, 0));
- + Line(new float3(-radius, lowerY, 0), new float3(-radius, upperY, 0));
- + Line(new float3(0, lowerY, radius), new float3(0, upperY, radius));
- + Line(new float3(0, lowerY, -radius), new float3(0, upperY, -radius));
- + }
- PopMatrix();
- - Line(new float3(radius, lowerY, 0), new float3(radius, upperY, 0));
- - Line(new float3(-radius, lowerY, 0), new float3(-radius, upperY, 0));
- - Line(new float3(0, lowerY, radius), new float3(0, upperY, radius));
- - Line(new float3(0, lowerY, -radius), new float3(0, upperY, -radius));
- }
- - PopMatrix();
- }
- PopColor();
- }
- diff --git a/Assets/AstarPathfindingProject/Drawing/changelog.cs b/Assets/AstarPathfindingProject/Drawing/changelog.cs
- index 42662d41..74788cf5 100644
- --- a/Assets/AstarPathfindingProject/Drawing/changelog.cs
- +++ b/Assets/AstarPathfindingProject/Drawing/changelog.cs
- @@ -1,6 +1,9 @@
- /** \page changelog Changelog
- \order{-10}
- +- 1.5.4
- + - Fixed some edge cases in \reflink{Draw.WireCapsule} and \reflink{Draw.WireCapsule} which could cause NaNs and other subtle errors.
- +
- - 1.5.3 (2022-05-14)
- - Breaking changes
- - The minimum supported Unity version is now 2020.3.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement