Example #1
0
		public void CollisionCheck(){
			IEnumerator<Collider> prevCols = prevCollisions.Keys.GetEnumerator();
			while (prevCols.MoveNext ()) {
				Collider c = prevCols.Current;
				if (collisions.ContainsKey (c)) {
					continue;
				}
				if (Mathf.Abs((transform.position - c.transform.position).sqrMagnitude - (
					((Transform)transform.previous).position - ((Transform)c.transform.previous).position).sqrMagnitude) <= Util.thin ){
					Collision selfOldCollision = this.prevCollisions [c];

					Collision selfCollision = new Collision (
						this, 
						c, 
						new Vector2[]{selfOldCollision.contactPoints[selfOldCollision.contactPoints.Length-1]}, 
						new Vector2[]{Vector2.zero}, 
						new Vector2[]{selfOldCollision.normals[selfOldCollision.normals.Length-1]},
						new float[]{0}
					);
					Collision otherOldCollision = c.prevCollisions [this];
					Collision otherCollision = new Collision (
						c,
						this,
						new Vector2[]{otherOldCollision.contactPoints[otherOldCollision.contactPoints.Length-1]}, 
						new Vector2[]{Vector2.zero}, 
						new Vector2[]{otherOldCollision.normals[otherOldCollision.normals.Length-1]},
						new float[]{0}
					);
					this.AddCollision (selfCollision);
					c.AddCollision (otherCollision);
				}
			}
		}
Example #2
0
        public static UnityEngine.Vector3Int RotateBySector(this UnityEngine.Vector3Int vecUp, FLOAT3 dir)
        {
            var p = vecUp;
            var x = Mathf.Abs(dir.x);
            var z = Mathf.Abs(dir.z);

            if (dir.x >= 0f &&
                x >= z)
            {
                // right
                vecUp = vecUp.Rotate90();
            }
            else if (dir.z >= 0f &&
                     z >= x)
            {
                // up
            }
            else if (dir.z <= 0f &&
                     z >= x)
            {
                // down
                vecUp = vecUp.Rotate90();
                vecUp = vecUp.Rotate90();
            }
            else if (dir.x <= 0f &&
                     x >= z)
            {
                // left
                vecUp = vecUp.Rotate90();
                vecUp = vecUp.Rotate90();
                vecUp = vecUp.Rotate90();
            }

            return(vecUp);
        }
Example #3
0
        public static Vector2 MaxRequirement(Vector2 a, Vector2 b)
        {
            float x = Mathf.Abs(a.x) > Mathf.Abs(b.x) ? a.x : b.x;
            float y = Mathf.Abs(a.y) > Mathf.Abs(b.y) ? a.y : b.y;

            return(new Vector2(x, y));
        }
Example #4
0
        public void Validate()
        {
            if (surfaceDefinition == null)
            {
                surfaceDefinition = new ChiselSurfaceDefinition();
            }

            stepHeight = Mathf.Max(kMinStepHeight, stepHeight);

            innerDiameter = Mathf.Min(outerDiameter - kMinStairsDepth, innerDiameter);
            innerDiameter = Mathf.Max(kMinInnerDiameter, innerDiameter);
            outerDiameter = Mathf.Max(innerDiameter + kMinStairsDepth, outerDiameter);
            outerDiameter = Mathf.Max(kMinOuterDiameter, outerDiameter);
            height        = Mathf.Max(stepHeight, Mathf.Abs(height)) * (height < 0 ? -1 : 1);
            treadHeight   = Mathf.Max(0, treadHeight);
            nosingDepth   = Mathf.Max(0, nosingDepth);
            nosingWidth   = Mathf.Max(0, nosingWidth);

            riserDepth = Mathf.Max(kMinRiserDepth, riserDepth);

            rotation = Mathf.Max(kMinRotation, Mathf.Abs(rotation)) * (rotation < 0 ? -1 : 1);

            innerSegments = Mathf.Max(kMinSegments, innerSegments);
            outerSegments = Mathf.Max(kMinSegments, outerSegments);

            surfaceDefinition.EnsureSize(8);
        }
Example #5
0
        public void Validate()
        {
            if (surfaceDefinition == null)
            {
                surfaceDefinition = new ChiselSurfaceDefinition();
            }

            if (surfaceDefinition.EnsureSize((int)SurfaceSides.TotalSides))
            {
                var defaultRenderMaterial  = CSGMaterialManager.DefaultWallMaterial;
                var defaultPhysicsMaterial = CSGMaterialManager.DefaultPhysicsMaterial;

                surfaceDefinition.surfaces[(int)SurfaceSides.Top].brushMaterial     = ChiselBrushMaterial.CreateInstance(CSGMaterialManager.DefaultFloorMaterial, defaultPhysicsMaterial);
                surfaceDefinition.surfaces[(int)SurfaceSides.Bottom].brushMaterial  = ChiselBrushMaterial.CreateInstance(CSGMaterialManager.DefaultFloorMaterial, defaultPhysicsMaterial);
                surfaceDefinition.surfaces[(int)SurfaceSides.Left].brushMaterial    = ChiselBrushMaterial.CreateInstance(CSGMaterialManager.DefaultWallMaterial, defaultPhysicsMaterial);
                surfaceDefinition.surfaces[(int)SurfaceSides.Right].brushMaterial   = ChiselBrushMaterial.CreateInstance(CSGMaterialManager.DefaultWallMaterial, defaultPhysicsMaterial);
                surfaceDefinition.surfaces[(int)SurfaceSides.Forward].brushMaterial = ChiselBrushMaterial.CreateInstance(CSGMaterialManager.DefaultWallMaterial, defaultPhysicsMaterial);
                surfaceDefinition.surfaces[(int)SurfaceSides.Back].brushMaterial    = ChiselBrushMaterial.CreateInstance(CSGMaterialManager.DefaultWallMaterial, defaultPhysicsMaterial);
                surfaceDefinition.surfaces[(int)SurfaceSides.Tread].brushMaterial   = ChiselBrushMaterial.CreateInstance(CSGMaterialManager.DefaultTreadMaterial, defaultPhysicsMaterial);
                surfaceDefinition.surfaces[(int)SurfaceSides.Step].brushMaterial    = ChiselBrushMaterial.CreateInstance(CSGMaterialManager.DefaultStepMaterial, defaultPhysicsMaterial);

                for (int i = 0; i < surfaceDefinition.surfaces.Length; i++)
                {
                    if (surfaceDefinition.surfaces[i].brushMaterial == null)
                    {
                        surfaceDefinition.surfaces[i].brushMaterial = ChiselBrushMaterial.CreateInstance(defaultRenderMaterial, defaultPhysicsMaterial);
                    }
                }
            }


            stepHeight  = Mathf.Max(kMinStepHeight, stepHeight);
            stepDepth   = Mathf.Clamp(stepDepth, kMinStepDepth, Mathf.Abs(depth));
            treadHeight = Mathf.Max(0, treadHeight);
            nosingDepth = Mathf.Max(0, nosingDepth);
            nosingWidth = Mathf.Max(0, nosingWidth);

            width = Mathf.Max(kMinWidth, Mathf.Abs(width)) * (width < 0 ? -1 : 1);
            depth = Mathf.Max(stepDepth, Mathf.Abs(depth)) * (depth < 0 ? -1 : 1);

            riserDepth = Mathf.Max(kMinRiserDepth, riserDepth);
            sideDepth  = Mathf.Max(0, sideDepth);
            sideWidth  = Mathf.Max(kMinSideWidth, sideWidth);
            sideHeight = Mathf.Max(0, sideHeight);

            var absHeight        = Mathf.Max(stepHeight, Mathf.Abs(height));
            var maxPlateauHeight = absHeight - stepHeight;

            plateauHeight = Mathf.Clamp(plateauHeight, 0, maxPlateauHeight);

            var totalSteps      = Mathf.Max(1, Mathf.FloorToInt((absHeight - plateauHeight) / stepHeight));
            var totalStepHeight = totalSteps * stepHeight;

            plateauHeight = Mathf.Max(0, absHeight - totalStepHeight);
            stepDepth     = Mathf.Clamp(stepDepth, kMinStepDepth, Mathf.Abs(depth) / totalSteps);
        }
Example #6
0
        public void Validate()
        {
            diameterXYZ.x = Mathf.Max(kMinDiameter, Mathf.Abs(diameterXYZ.x));
            diameterXYZ.y = Mathf.Max(0, Mathf.Abs(diameterXYZ.y)) * (diameterXYZ.y < 0 ? -1 : 1);
            diameterXYZ.z = Mathf.Max(kMinDiameter, Mathf.Abs(diameterXYZ.z));

            horizontalSegments = Mathf.Max(horizontalSegments, 3);
            verticalSegments   = Mathf.Max(verticalSegments, 1);

            if (surfaceAssets == null ||
                surfaceAssets.Length != 6)
            {
                var defaultRenderMaterial  = CSGMaterialManager.DefaultWallMaterial;
                var defaultPhysicsMaterial = CSGMaterialManager.DefaultPhysicsMaterial;
                surfaceAssets = new CSGSurfaceAsset[6]
                {
                    CSGSurfaceAsset.CreateInstance(defaultRenderMaterial, defaultPhysicsMaterial),
                    CSGSurfaceAsset.CreateInstance(defaultRenderMaterial, defaultPhysicsMaterial),
                    CSGSurfaceAsset.CreateInstance(defaultRenderMaterial, defaultPhysicsMaterial),
                    CSGSurfaceAsset.CreateInstance(defaultRenderMaterial, defaultPhysicsMaterial),
                    CSGSurfaceAsset.CreateInstance(defaultRenderMaterial, defaultPhysicsMaterial),
                    CSGSurfaceAsset.CreateInstance(defaultRenderMaterial, defaultPhysicsMaterial)
                };
            }

            if (surfaceDescriptions == null ||
                surfaceDescriptions.Length != 6)
            {
                // TODO: make this independent on plane position somehow
                var surfaceFlags = CSGDefaults.SurfaceFlags;
                surfaceDescriptions = new SurfaceDescription[6]
                {
                    new SurfaceDescription {
                        UV0 = UVMatrix.centered, surfaceFlags = surfaceFlags, smoothingGroup = 0
                    },
                    new SurfaceDescription {
                        UV0 = UVMatrix.centered, surfaceFlags = surfaceFlags, smoothingGroup = 0
                    },
                    new SurfaceDescription {
                        UV0 = UVMatrix.centered, surfaceFlags = surfaceFlags, smoothingGroup = 0
                    },
                    new SurfaceDescription {
                        UV0 = UVMatrix.centered, surfaceFlags = surfaceFlags, smoothingGroup = 0
                    },
                    new SurfaceDescription {
                        UV0 = UVMatrix.centered, surfaceFlags = surfaceFlags, smoothingGroup = 0
                    },
                    new SurfaceDescription {
                        UV0 = UVMatrix.centered, surfaceFlags = surfaceFlags, smoothingGroup = 0
                    }
                };
            }
        }
Example #7
0
        public void Validate()
        {
            stepHeight = Mathf.Max(kMinStepHeight, stepHeight);

            innerDiameter = Mathf.Min(outerDiameter - kMinStairsDepth, innerDiameter);
            innerDiameter = Mathf.Max(kMinInnerDiameter, innerDiameter);
            outerDiameter = Mathf.Max(innerDiameter + kMinStairsDepth, outerDiameter);
            outerDiameter = Mathf.Max(kMinOuterDiameter, outerDiameter);
            height        = Mathf.Max(stepHeight, Mathf.Abs(height)) * (height < 0 ? -1 : 1);
            treadHeight   = Mathf.Max(0, treadHeight);
            nosingDepth   = Mathf.Max(0, nosingDepth);
            nosingWidth   = Mathf.Max(0, nosingWidth);

            riserDepth = Mathf.Max(kMinRiserDepth, riserDepth);

            rotation = Mathf.Max(kMinRotation, Mathf.Abs(rotation)) * (rotation < 0 ? -1 : 1);

            innerSegments = Mathf.Max(kMinSegments, innerSegments);
            outerSegments = Mathf.Max(kMinSegments, outerSegments);

            if (surfaceAssets == null ||
                surfaceAssets.Length != 6)
            {
                var defaultRenderMaterial  = CSGMaterialManager.DefaultWallMaterial;
                var defaultPhysicsMaterial = CSGMaterialManager.DefaultPhysicsMaterial;
                surfaceAssets = new CSGSurfaceAsset[6];
                for (int i = 0; i < 6; i++) // Note: sides share same material
                {
                    surfaceAssets[i] = CSGSurfaceAsset.CreateInstance(defaultRenderMaterial, defaultPhysicsMaterial);
                }
            }

            if (surfaceDescriptions == null ||
                surfaceDescriptions.Length != 6)
            {
                var surfaceFlags = CSGDefaults.SurfaceFlags;
                surfaceDescriptions = new SurfaceDescription[6];
                for (int i = 0; i < 6; i++)
                {
                    surfaceDescriptions[i] = new SurfaceDescription {
                        surfaceFlags = surfaceFlags, UV0 = UVMatrix.centered, smoothingGroup = bottomSmoothingGroup
                    };
                }
            }
            else
            {
                for (int i = 0; i < 6; i++)
                {
                    surfaceDescriptions[i].smoothingGroup = bottomSmoothingGroup;
                }
            }
        }
Example #8
0
 public bool Equals(CSGPlane other)
 {
     if (System.Object.ReferenceEquals(this, other))
     {
         return(true);
     }
     if (System.Object.ReferenceEquals(other, null))
     {
         return(false);
     }
     return(Mathf.Abs(this.Distance(other.pointOnPlane)) <= MathConstants.DistanceEpsilon &&
            Mathf.Abs(other.Distance(this.pointOnPlane)) <= MathConstants.DistanceEpsilon &&
            Mathf.Abs(a - other.a) <= MathConstants.NormalEpsilon &&
            Mathf.Abs(b - other.b) <= MathConstants.NormalEpsilon &&
            Mathf.Abs(c - other.c) <= MathConstants.NormalEpsilon);
 }
Example #9
0
        public void Validate()
        {
            if (surfaceDefinition == null)
            {
                surfaceDefinition = new ChiselSurfaceDefinition();
            }

            diameterXYZ.x = Mathf.Max(kMinDiameter, Mathf.Abs(diameterXYZ.x));
            diameterXYZ.y = Mathf.Max(0, Mathf.Abs(diameterXYZ.y)) * (diameterXYZ.y < 0 ? -1 : 1);
            diameterXYZ.z = Mathf.Max(kMinDiameter, Mathf.Abs(diameterXYZ.z));

            horizontalSegments = Mathf.Max(horizontalSegments, 3);
            verticalSegments   = Mathf.Max(verticalSegments, 1);

            surfaceDefinition.EnsureSize(6);
        }
Example #10
0
        public static bool IsValid(UnityEngine.Vector3 min, UnityEngine.Vector3 max)
        {
            const float kMinSize = 0.0001f;

            if (Mathf.Abs(max.x - min.x) < kMinSize ||
                Mathf.Abs(max.y - min.y) < kMinSize ||
                Mathf.Abs(max.z - min.z) < kMinSize ||
                float.IsInfinity(min.x) || float.IsInfinity(min.y) || float.IsInfinity(min.z) ||
                float.IsInfinity(max.x) || float.IsInfinity(max.y) || float.IsInfinity(max.z) ||
                float.IsNaN(min.x) || float.IsNaN(min.y) || float.IsNaN(min.z) ||
                float.IsNaN(max.x) || float.IsNaN(max.y) || float.IsNaN(max.z))
            {
                return(false);
            }
            return(true);
        }
Example #11
0
        public void Validate()
        {
            topLength    = Mathf.Max(topLength, 0);
            bottomLength = Mathf.Max(bottomLength, 0);
            length       = Mathf.Max(Mathf.Abs(length), (haveRoundedTop ? topLength : 0) + (haveRoundedBottom ? bottomLength : 0));
            length       = Mathf.Max(Mathf.Abs(length), kMinLength);

            height   = Mathf.Max(Mathf.Abs(height), kMinHeight);
            diameter = Mathf.Max(Mathf.Abs(diameter), kMinDiameter);

            topSides    = Mathf.Max(topSides, 1);
            bottomSides = Mathf.Max(bottomSides, 1);

            var sides             = 2 + Mathf.Max(topSides, 1) + Mathf.Max(bottomSides, 1);
            int kMinSurfaceAssets = 2 + sides;

            if (surfaceAssets == null ||
                surfaceAssets.Length != kMinSurfaceAssets)
            {
                var defaultRenderMaterial  = CSGMaterialManager.DefaultWallMaterial;
                var defaultPhysicsMaterial = CSGMaterialManager.DefaultPhysicsMaterial;
                surfaceAssets = new CSGSurfaceAsset[kMinSurfaceAssets];
                for (int a = 0; a < kMinSurfaceAssets; a++)
                {
                    surfaceAssets[a] = CSGSurfaceAsset.CreateInstance(defaultRenderMaterial, defaultPhysicsMaterial);
                }
            }

            int kMinSurfaceDescriptions = 2 + sides;

            if (surfaceDescriptions == null ||
                surfaceDescriptions.Length != kMinSurfaceDescriptions)
            {
                // TODO: make this independent on plane position somehow
                var surfaceFlags = CSGDefaults.SurfaceFlags;
                surfaceDescriptions = new SurfaceDescription[kMinSurfaceDescriptions];
                for (int s = 0; s < kMinSurfaceDescriptions; s++)
                {
                    surfaceDescriptions[s] = new SurfaceDescription {
                        UV0 = UVMatrix.centered, surfaceFlags = surfaceFlags, smoothingGroup = 0
                    }
                }
                ;
            }
        }
    }
Example #12
0
 public static bool operator !=(CSGPlane left, CSGPlane right)
 {
     if (System.Object.ReferenceEquals(left, right))
     {
         return(false);
     }
     if (System.Object.ReferenceEquals(left, null) ||
         System.Object.ReferenceEquals(right, null))
     {
         return(true);
     }
     return(Mathf.Abs(left.Distance(right.pointOnPlane)) > MathConstants.DistanceEpsilon &&
            Mathf.Abs(right.Distance(left.pointOnPlane)) > MathConstants.DistanceEpsilon &&
            Mathf.Abs(left.a - right.a) > MathConstants.NormalEpsilon ||
            Mathf.Abs(left.b - right.b) > MathConstants.NormalEpsilon ||
            Mathf.Abs(left.c - right.c) > MathConstants.NormalEpsilon);
 }
        public void Validate()
        {
            topHeight    = Mathf.Max(topHeight, 0);
            bottomHeight = Mathf.Max(bottomHeight, 0);
            height       = Mathf.Max(topHeight + bottomHeight, Mathf.Abs(height)) * (height < 0 ? -1 : 1);

            diameterX = Mathf.Max(Mathf.Abs(diameterX), kMinDiameter);
            diameterZ = Mathf.Max(Mathf.Abs(diameterZ), kMinDiameter);

            topSegments    = Mathf.Max(topSegments, 0);
            bottomSegments = Mathf.Max(bottomSegments, 0);
            sides          = Mathf.Max(sides, 3);

            var minSurfaceAssets = 2 + sides;

            if (surfaceAssets == null ||
                surfaceAssets.Length != minSurfaceAssets)
            {
                var defaultRenderMaterial  = CSGMaterialManager.DefaultWallMaterial;
                var defaultPhysicsMaterial = CSGMaterialManager.DefaultPhysicsMaterial;
                surfaceAssets = new CSGSurfaceAsset[minSurfaceAssets];
                for (int a = 0; a < minSurfaceAssets; a++)
                {
                    surfaceAssets[a] = CSGSurfaceAsset.CreateInstance(defaultRenderMaterial, defaultPhysicsMaterial);
                }
            }

            var minSurfaceDescriptions = 2 + sides;

            if (surfaceDescriptions == null ||
                surfaceDescriptions.Length != minSurfaceDescriptions)
            {
                // TODO: make this independent on plane position somehow
                var surfaceFlags = CSGDefaults.SurfaceFlags;
                surfaceDescriptions = new SurfaceDescription[minSurfaceDescriptions];
                for (int s = 0; s < minSurfaceDescriptions; s++)
                {
                    surfaceDescriptions[s] = new SurfaceDescription {
                        UV0 = UVMatrix.centered, surfaceFlags = surfaceFlags, smoothingGroup = 0
                    }
                }
                ;
            }
        }
    }
Example #14
0
        private static bool ProjectOverlapTest(Vector3 axis, Vector3[] srcPoints, Vector3[] dstPoints, out float overlap)
        {
            float srcMin = float.MaxValue;
            float dstMin = float.MaxValue;
            float srcMax = float.MinValue;
            float dstMax = float.MinValue;

            for (int i = 0; i < srcPoints.Length; i++)
            {
                var p = Vector3.Dot(axis, srcPoints[i]);
                if (p < srcMin)
                {
                    srcMin = p;
                }
                if (p > srcMax)
                {
                    srcMax = p;
                }
            }
            for (int i = 0; i < dstPoints.Length; i++)
            {
                var p = Vector3.Dot(axis, dstPoints[i]);
                if (p < dstMin)
                {
                    dstMin = p;
                }
                if (p > dstMax)
                {
                    dstMax = p;
                }
            }
            if (srcMax < dstMin || srcMin > dstMax)
            {
                overlap = 0;
                return(false);
            }
            overlap = Mathf.Min(srcMax, dstMax) - Mathf.Max(srcMin, dstMin);
            if ((srcMax > dstMax && srcMin < dstMin) || (srcMax < dstMax && srcMin > dstMin))
            {
                var min = Mathf.Abs(srcMin - dstMin);
                var max = Mathf.Abs(srcMax - dstMax);
                overlap += Mathf.Min(min, max);
            }
            return(true);
        }
Example #15
0
        static float ApproximateEdgeDelta(float gx, float gy, float a)
        {
            // (gx, gy) can be either the local pixel gradient or the direction to the pixel

            if (gx == 0f || gy == 0f)
            {
                // linear function is correct if both gx and gy are zero
                // and still fair if only one of them is zero
                return(0.5f - a);
            }

            // normalize (gx, gy)
            float length = (float)Math.Sqrt(gx * gx + gy * gy);

            gx = gx / length;
            gy = gy / length;

            // reduce symmetrical equation to first octant only
            // gx >= 0, gy >= 0, gx >= gy
            gx = Math.Abs(gx);
            gy = Math.Abs(gy);
            if (gx < gy)
            {
                float temp = gx;
                gx = gy;
                gy = temp;
            }

            // compute delta
            float a1 = 0.5f * gy / gx;

            if (a < a1)
            {
                // 0 <= a < a1
                return(0.5f * (gx + gy) - (float)Math.Sqrt(2f * gx * gy * a));
            }
            if (a < (1f - a1))
            {
                // a1 <= a <= 1 - a1
                return((0.5f - a) * gx);
            }
            // 1-a1 < a <= 1
            return(-0.5f * (gx + gy) + (float)Math.Sqrt(2f * gx * gy * (1f - a)));
        }
        public void Validate()
        {
            if (surfaceDefinition == null)
            {
                surfaceDefinition = new ChiselSurfaceDefinition();
            }

            topHeight    = Mathf.Max(topHeight, 0);
            bottomHeight = Mathf.Max(bottomHeight, 0);
            height       = Mathf.Max(topHeight + bottomHeight, Mathf.Abs(height)) * (height < 0 ? -1 : 1);

            diameterX = Mathf.Max(Mathf.Abs(diameterX), kMinDiameter);
            diameterZ = Mathf.Max(Mathf.Abs(diameterZ), kMinDiameter);

            topSegments    = Mathf.Max(topSegments, 0);
            bottomSegments = Mathf.Max(bottomSegments, 0);
            sides          = Mathf.Max(sides, 3);

            surfaceDefinition.EnsureSize(2 + sides);
        }
Example #17
0
        public static bool Intersect(CubeXCollider src, CubeXCollider dst, out XContact?contact)
        {
            Vector3 normal;
            float   penetration;

            if (!SATTest(src, dst, out normal, out penetration))
            {
                contact = null;
                return(false);
            }
            var srcExtents = src.Size * 0.5f;
            var dstExtents = dst.Size * 0.5f;
            var srcMinY    = src.Position.y - srcExtents.y;
            var srcMaxY    = src.Position.y + srcExtents.y;
            var dstMinY    = dst.Position.y - dstExtents.y;
            var dstMaxY    = dst.Position.y + dstExtents.y;

            var overlapY = Mathf.Min(srcMaxY, dstMaxY) - Mathf.Max(srcMinY, dstMinY);

            if ((srcMaxY > dstMaxY && srcMinY < dstMinY) || (srcMaxY < dstMaxY && srcMinY > dstMinY))
            {
                var min = Mathf.Abs(srcMinY - dstMinY);
                var max = Mathf.Abs(srcMaxY - dstMaxY);
                overlapY += Mathf.Min(min, max);
            }

            if (overlapY < penetration)
            {
                penetration = overlapY;
                normal      = Vector3.up;
            }

            if (Vector3.Dot(normal, dst.Position - src.Position) < 0)
            {
                normal = -normal;
            }

            contact = new XContact(src, dst, normal, penetration);
            return(true);
        }
Example #18
0
        static void PostProcess(float maxDistance)
        {
            // adjust distances near edges based on the local edge gradient
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    Pixel p = pixels[x, y];
                    if ((p.dX == 0 && p.dY == 0) || p.distance >= maxDistance)
                    {
                        // ignore edge, inside, and beyond max distance
                        continue;
                    }
                    float
                        dX          = p.dX,
                        dY          = p.dY;
                    Pixel   closest = pixels[x - p.dX, y - p.dY];
                    Vector2 g       = closest.gradient;

                    if (g.x == 0f && g.y == 0f)
                    {
                        // ignore unknown gradients (inside)
                        continue;
                    }

                    // compute hit point offset on gradient inside pixel
                    float df = ApproximateEdgeDelta(g.x, g.y, closest.alpha);
                    float t  = dY * g.x - dX * g.y;
                    float u  = -df * g.x + t * g.y;
                    float v  = -df * g.y - t * g.x;

                    // use hit point to compute distance
                    if (Math.Abs(u) <= 0.5f && Math.Abs(v) <= 0.5f)
                    {
                        p.distance = (float)Math.Sqrt((dX + u) * (dX + u) + (dY + v) * (dY + v));
                    }
                }
            }
        }
Example #19
0
        public void Validate()
        {
            if (surfaceDefinition == null)
            {
                surfaceDefinition = new ChiselSurfaceDefinition();
            }

            topLength    = Mathf.Max(topLength, 0);
            bottomLength = Mathf.Max(bottomLength, 0);
            length       = Mathf.Max(Mathf.Abs(length), (haveRoundedTop ? topLength : 0) + (haveRoundedBottom ? bottomLength : 0));
            length       = Mathf.Max(Mathf.Abs(length), kMinLength);

            height   = Mathf.Max(Mathf.Abs(height), kMinHeight);
            diameter = Mathf.Max(Mathf.Abs(diameter), kMinDiameter);

            topSides    = Mathf.Max(topSides, 1);
            bottomSides = Mathf.Max(bottomSides, 1);

            var sides = 2 + Mathf.Max(topSides, 1) + Mathf.Max(bottomSides, 1);

            surfaceDefinition.EnsureSize(2 + sides);
        }
Example #20
0
        public void Validate()
        {
            if (surfaceDefinition == null)
            {
                surfaceDefinition = new ChiselSurfaceDefinition();
            }

            topDiameterX    = Mathf.Abs(topDiameterX);
            topDiameterZ    = Mathf.Abs(topDiameterZ);
            bottomDiameterX = Mathf.Abs(bottomDiameterX);
            bottomDiameterZ = Mathf.Abs(bottomDiameterZ);

            sides = Mathf.Max(3, sides);

            if (surfaceDefinition.EnsureSize(2 + sides))
            {
                // Top plane
                surfaceDefinition.surfaces[0].surfaceDescription.UV0 = UVMatrix.centered;

                // Bottom plane
                surfaceDefinition.surfaces[1].surfaceDescription.UV0 = UVMatrix.centered;

                float radius     = topDiameterX * 0.5f;
                float angle      = (360.0f / sides);
                float sideLength = (2 * Mathf.Sin((angle / 2.0f) * Mathf.Deg2Rad)) * radius;

                // Side planes
                for (int i = 2; i < 2 + sides; i++)
                {
                    var uv0 = UVMatrix.identity;
                    uv0.U.w = ((i - 2) + 0.5f) * sideLength;
                    // TODO: align with bottom
                    //uv0.V.w = 0.5f;
                    surfaceDefinition.surfaces[i].surfaceDescription.UV0            = uv0;
                    surfaceDefinition.surfaces[i].surfaceDescription.smoothingGroup = smoothingGroup;
                }
            }
        }
        private IEnumerator Tick()
        {
            while (true)
            {
                var tankMovementSoundEntityViews = entityViewsDB.QueryEntityViews <TankMovementSoundEntityView>();

                if (tankMovementSoundEntityViews.Count > 0)
                {
                    for (int i = 0; i < tankMovementSoundEntityViews.Count; i++)
                    {
                        IAudioSourceComponent        audioSourceComponent = tankMovementSoundEntityViews[i].AudioSourceComponent;
                        ITankMovementSoundsComponent soundComponent       = tankMovementSoundEntityViews[i].TankMovementSoundsComponent;
                        ITankInputComponent          inputComponent       = tankMovementSoundEntityViews[i].TankInputComponent;
                        if (Mathf.Abs(inputComponent.Input.z) < 0.1f && Mathf.Abs(inputComponent.Input.x) < 0.1f)
                        {
                            if (audioSourceComponent.Clip == soundComponent.EngineDrivingAudioClip)
                            {
                                audioSourceComponent.Clip  = soundComponent.IdleAudioClip;
                                audioSourceComponent.Pitch = Random.Range(1 - 0.1f, 1 + 0.1f);
                                audioSourceComponent.Play();
                            }
                        }
                        else
                        {
                            if (audioSourceComponent.Clip == soundComponent.IdleAudioClip)
                            {
                                // ... change the clip to driving and play.
                                audioSourceComponent.Clip  = soundComponent.EngineDrivingAudioClip;
                                audioSourceComponent.Pitch = Random.Range(1 - 0.1f, 1 + 0.1f);
                                audioSourceComponent.Play();
                            }
                        }
                    }
                }

                yield return(null);
            }
        }
Example #22
0
        public static bool Intersect(CylinderXCollider src, SphereXCollider dst, out XContact?contact)
        {
            var n = dst.Position - src.Position;

            Vector3 closest = n;
            var     extents = src.bounds.Extents;

            closest.x = Mathf.Clamp(closest.x, -extents.x, extents.x);
            closest.y = Mathf.Clamp(closest.y, -extents.y, extents.y);
            closest.z = Mathf.Clamp(closest.z, -extents.z, extents.z);

            var v = new Vector2(closest.x, closest.z);

            if (v.sqrMagnitude > src.Radius * src.Radius)
            {
                v         = v.normalized * src.Radius;
                closest.x = v.x;
                closest.z = v.y;
            }

            bool inside = false;

            if (n == closest)
            {
                inside = true;
                // 往上下移动的最短距离
                var dist1 = extents.y - Mathf.Abs(closest.y);
                // 往水平四周移动的最短距离
                var dist2 = src.Radius - v.magnitude;

                if (dist1 < dist2)
                {
                    closest.y = closest.y > 0 ? extents.y : -extents.y;
                }
                else
                {
                    v         = v.normalized * src.Radius;
                    closest.x = v.x;
                    closest.z = v.y;
                }
            }

            var dir      = n - closest;
            var sqrDist  = dir.sqrMagnitude;
            var space    = dst.Radius;
            var sqrSpace = space * space;

            if (sqrDist < sqrSpace || inside)
            {
                var dist        = Mathf.Sqrt(sqrDist);
                var normal      = dir.normalized;
                var penetration = space - dist;
                if (inside)
                {
                    normal      = -normal;
                    penetration = space + dist;
                }
                if (normal == Vector3.zero)
                {
                    normal = Vector3.up;
                }
                contact = new XContact(src, dst, normal, penetration);
                return(true);
            }
            contact = null;
            return(false);
        }
Example #23
0
        public static bool Intersect(CubeXCollider src, CylinderXCollider dst, out XContact?contact)
        {
            var     invP = Quaternion.Inverse(src.Quaternion) * (dst.Position - src.Position);
            Vector3 n    = Vector3.zero;

            n.x = invP.x;
            n.z = invP.z;

            var extents = src.Size * 0.5f;
            var halfHa  = extents.y;
            var topA    = halfHa;
            var bottomA = -halfHa;
            var halfHb  = dst.Height * 0.5f;
            var topB    = invP.y + halfHb;
            var bottomB = invP.y - halfHb;

            var space    = dst.Radius;
            var sqrSpace = space * space;

            // 相撞时,俯视图下的圆和矩形必然相交
            var closest = n;

            closest.x = Mathf.Clamp(closest.x, -extents.x, extents.x);
            closest.z = Mathf.Clamp(closest.z, -extents.z, extents.z);

            if ((n - closest).sqrMagnitude > sqrSpace)
            {
                contact = null;
                return(false);
            }

            // 处理相交的情况
            Vector3 normal;
            float   penetration;
            float   verticalP = float.PositiveInfinity;
            float   horizontalP;

            var inside = false;

            if (n == closest)
            {
                inside = true;
                var disX = extents.x - Mathf.Abs(n.x);
                var disZ = extents.z - Mathf.Abs(n.z);
                //找到最近的一个面
                if (disX < disZ)
                {
                    // 沿X轴
                    if (n.x > 0)
                    {
                        closest.x = extents.x;
                    }
                    else
                    {
                        closest.x = -extents.x;
                    }
                }
                else
                {
                    // 沿Z轴
                    if (n.z > 0)
                    {
                        closest.z = extents.z;
                    }
                    else
                    {
                        closest.z = -extents.z;
                    }
                }
                horizontalP = space + (n - closest).magnitude;
            }
            else
            {
                horizontalP = space - (n - closest).magnitude;
            }

            if (Mathf.Sign(topA - topB) != Mathf.Sign(bottomB - bottomA))
            {
                // 斜向相撞
                if (topB > topA)
                {
                    verticalP = topA - bottomB;
                }
                else
                {
                    verticalP = topB - bottomA;
                }
            }

            if (horizontalP < verticalP)
            {
                normal = (src.Quaternion * (n - closest)).normalized;
                if (inside)
                {
                    normal = -normal;
                }
                penetration = horizontalP;
            }
            else
            {
                normal      = topB > topA ? Vector3.up : Vector3.down;
                penetration = verticalP;
            }
            if (normal == Vector3.zero)
            {
                normal = Vector3.up;
            }
            contact = new XContact(src, dst, normal, penetration);
            return(true);
        }
Example #24
0
        public static bool Intersect(CubeXCollider src, SphereXCollider dst, out XContact?contact)
        {
            // 反向旋转sphere的位置,使得可以在cube的坐标系下进行碰撞判断
            var extents = src.Size * 0.5f;
            var invQ    = Quaternion.Inverse(src.Quaternion);
            var invP    = invQ * (dst.Position - src.Position);

            // 以下所有操作都是在cube的坐标系下,随后的实际方向需要进行坐标系转换
            var n       = invP;
            var closest = n;

            closest.x = Mathf.Clamp(closest.x, -extents.x, extents.x);
            closest.y = Mathf.Clamp(closest.y, -extents.y, extents.y);
            closest.z = Mathf.Clamp(closest.z, -extents.z, extents.z);
            var inside = false;

            if (n == closest)
            {
                inside = true;
                var disX = extents.x - Mathf.Abs(n.x);
                var disY = extents.y - Mathf.Abs(n.y);
                var disZ = extents.z - Mathf.Abs(n.z);
                //找到最近的一个面
                if (disX < disY && disX < disZ)
                {
                    // 沿X轴
                    if (n.x > 0)
                    {
                        closest.x = extents.x;
                    }
                    else
                    {
                        closest.x = -extents.x;
                    }
                }
                else if (disY < disX && disY < disZ)
                {
                    // 沿Y轴
                    if (n.y > 0)
                    {
                        closest.y = extents.y;
                    }
                    else
                    {
                        closest.y = -extents.y;
                    }
                }
                else
                {
                    // 沿Z轴
                    if (n.z > 0)
                    {
                        closest.z = extents.z;
                    }
                    else
                    {
                        closest.z = -extents.z;
                    }
                }
            }
            var dir      = n - closest;
            var sqrDist  = dir.sqrMagnitude;
            var space    = dst.Radius;
            var sqrSpace = space * space;

            if (sqrDist < sqrSpace || inside)
            {
                var dist        = Mathf.Sqrt(sqrDist);
                var normal      = (src.Quaternion * dir).normalized;
                var penetration = space - dist;
                if (inside)
                {
                    normal      = -normal;
                    penetration = space + dist;
                }
                if (normal == Vector3.zero)
                {
                    normal = Vector3.up;
                }
                contact = new XContact(src, dst, normal, penetration);
                return(true);
            }
            contact = null;
            return(false);
        }
Example #25
0
        public void OnEdit(IChiselHandles handles)
        {
            // Store our allocated handles in generatorState to avoid reallocating them every frame
            var cylinderHandles = handles.generatorState as CylinderHandles;

            if (cylinderHandles == null)
            {
                cylinderHandles = new CylinderHandles();
                cylinderHandles.Init(handles, this);
                handles.generatorState = cylinderHandles;
            }
            cylinderHandles.Update(handles, this);


            // Render vertical lines at the horizon of the cylinder
            handles.DoRenderHandles(new[] { cylinderHandles.verticalHandle1, cylinderHandles.verticalHandle2 });


            // Move the cylinder top/bottom up/down
            var prevModified = handles.modified;

            {
                handles.DoSlider1DHandle(ref cylinderHandles.bottomPoint, -cylinderHandles.normal, cylinderHandles.bottomHandles);
                var haveFocus = handles.lastHandleHadFocus;
                handles.DoSlider1DHandle(ref cylinderHandles.topPoint, cylinderHandles.normal, cylinderHandles.topHandles);
                haveFocus = haveFocus || handles.lastHandleHadFocus;
                if (haveFocus)
                {
                    handles.RenderDistanceMeasurement(cylinderHandles.topPoint, cylinderHandles.bottomPoint, Mathf.Abs(height));
                }
            }
            if (prevModified != handles.modified)
            {
                cylinderHandles.topY    = Vector3.Dot(Vector3.up, cylinderHandles.topPoint);
                cylinderHandles.bottomY = Vector3.Dot(Vector3.up, cylinderHandles.bottomPoint);

                height       = cylinderHandles.topY - cylinderHandles.bottomY;
                bottomOffset = cylinderHandles.bottomY;
            }


            // Resize the top/bottom circle by grabbing and dragging it
            prevModified = handles.modified;
            {
                // Make the bottom circle draggable
                DraggableRadius(handles, ref bottomDiameterX, ref bottomDiameterZ, cylinderHandles.bottomPoint, -cylinderHandles.normal, cylinderHandles.bottomXVector, cylinderHandles.bottomZVector, cylinderHandles.bottomRadiusHandles, this.isEllipsoid);
                // If we're a Cylinder, the top circle actually changes the bottom circle too
                if (type == CylinderShapeType.Cylinder)
                {
                    DraggableRadius(handles, ref bottomDiameterX, ref bottomDiameterZ, cylinderHandles.topPoint, cylinderHandles.normal, cylinderHandles.topXVector, cylinderHandles.topZVector, cylinderHandles.topRadiusHandles, this.isEllipsoid);
                }
                else
                // If we're a Conical Frustum, the top circle can be resized independently from the bottom circle
                if (type == CylinderShapeType.ConicalFrustum)
                {
                    DraggableRadius(handles, ref topDiameterX, ref topDiameterZ, cylinderHandles.topPoint, cylinderHandles.normal, cylinderHandles.topXVector, cylinderHandles.topZVector, cylinderHandles.topRadiusHandles, this.isEllipsoid);
                }
                // else; If we're a Cone, we ignore the top circle
            }
            if (prevModified != handles.modified)
            {
                // Ensure that when our shape is circular and we modify it, that when we convert back to an ellipsoid, it'll still be circular
                if (!this.isEllipsoid)
                {
                    topDiameterZ    = topDiameterX;
                    bottomDiameterZ = bottomDiameterX;
                }
            }
        }
Example #26
0
 public static FLOAT2 Abs(FLOAT2 v)
 {
     return(new FLOAT2(Mathf.Abs(v.x), Mathf.Abs(v.y)));
 }
        public void Validate()
        {
            if (surfaceAssets == null ||
                surfaceDescriptions.Length != (int)SurfaceSides.TotalSides)
            {
                var defaultRenderMaterial  = CSGMaterialManager.DefaultWallMaterial;
                var defaultPhysicsMaterial = CSGMaterialManager.DefaultPhysicsMaterial;
                surfaceAssets = new CSGSurfaceAsset[(int)SurfaceSides.TotalSides];

                surfaceAssets[(int)SurfaceSides.Top]     = CSGSurfaceAsset.CreateInstance(CSGMaterialManager.DefaultFloorMaterial, defaultPhysicsMaterial);
                surfaceAssets[(int)SurfaceSides.Bottom]  = CSGSurfaceAsset.CreateInstance(CSGMaterialManager.DefaultFloorMaterial, defaultPhysicsMaterial);
                surfaceAssets[(int)SurfaceSides.Left]    = CSGSurfaceAsset.CreateInstance(CSGMaterialManager.DefaultWallMaterial, defaultPhysicsMaterial);
                surfaceAssets[(int)SurfaceSides.Right]   = CSGSurfaceAsset.CreateInstance(CSGMaterialManager.DefaultWallMaterial, defaultPhysicsMaterial);
                surfaceAssets[(int)SurfaceSides.Forward] = CSGSurfaceAsset.CreateInstance(CSGMaterialManager.DefaultWallMaterial, defaultPhysicsMaterial);
                surfaceAssets[(int)SurfaceSides.Back]    = CSGSurfaceAsset.CreateInstance(CSGMaterialManager.DefaultWallMaterial, defaultPhysicsMaterial);
                surfaceAssets[(int)SurfaceSides.Tread]   = CSGSurfaceAsset.CreateInstance(CSGMaterialManager.DefaultTreadMaterial, defaultPhysicsMaterial);
                surfaceAssets[(int)SurfaceSides.Step]    = CSGSurfaceAsset.CreateInstance(CSGMaterialManager.DefaultStepMaterial, defaultPhysicsMaterial);

                for (int i = 0; i < surfaceAssets.Length; i++)
                {
                    if (surfaceAssets[i] == null)
                    {
                        surfaceAssets[i] = CSGSurfaceAsset.CreateInstance(defaultRenderMaterial, defaultPhysicsMaterial);
                    }
                }

                topSurface     = surfaceAssets[(int)SurfaceSides.Top];
                bottomSurface  = surfaceAssets[(int)SurfaceSides.Bottom];
                leftSurface    = surfaceAssets[(int)SurfaceSides.Left];
                rightSurface   = surfaceAssets[(int)SurfaceSides.Right];
                forwardSurface = surfaceAssets[(int)SurfaceSides.Forward];
                backSurface    = surfaceAssets[(int)SurfaceSides.Back];
                treadSurface   = surfaceAssets[(int)SurfaceSides.Tread];
                stepSurface    = surfaceAssets[(int)SurfaceSides.Step];
            }

            if (surfaceDescriptions == null ||
                surfaceDescriptions.Length != 6)
            {
                var surfaceFlags = CSGDefaults.SurfaceFlags;
                surfaceDescriptions = new SurfaceDescription[6];
                for (int i = 0; i < 6; i++)
                {
                    surfaceDescriptions[i] = new SurfaceDescription {
                        surfaceFlags = surfaceFlags, UV0 = UVMatrix.centered
                    };
                }
            }


            stepHeight  = Mathf.Max(kMinStepHeight, stepHeight);
            stepDepth   = Mathf.Clamp(stepDepth, kMinStepDepth, Mathf.Abs(depth));
            treadHeight = Mathf.Max(0, treadHeight);
            nosingDepth = Mathf.Max(0, nosingDepth);
            nosingWidth = Mathf.Max(0, nosingWidth);

            width = Mathf.Max(kMinWidth, Mathf.Abs(width)) * (width < 0 ? -1 : 1);
            depth = Mathf.Max(stepDepth, Mathf.Abs(depth)) * (depth < 0 ? -1 : 1);

            riserDepth = Mathf.Max(kMinRiserDepth, riserDepth);
            sideDepth  = Mathf.Max(0, sideDepth);
            sideWidth  = Mathf.Max(kMinSideWidth, sideWidth);
            sideHeight = Mathf.Max(0, sideHeight);

            var absHeight        = Mathf.Max(stepHeight, Mathf.Abs(height));
            var maxPlateauHeight = absHeight - stepHeight;

            plateauHeight = Mathf.Clamp(plateauHeight, 0, maxPlateauHeight);

            var totalSteps      = Mathf.Max(1, Mathf.FloorToInt((absHeight - plateauHeight) / stepHeight));
            var totalStepHeight = totalSteps * stepHeight;

            plateauHeight = Mathf.Max(0, absHeight - totalStepHeight);
            stepDepth     = Mathf.Clamp(stepDepth, kMinStepDepth, Mathf.Abs(depth) / totalSteps);
        }
Example #28
0
        //
        // TODO: code below needs to be cleaned up & simplified
        //


        public void OnEdit(IChiselHandles handles)
        {
            var newDefinition = this;

            {
                var stepDepthOffset = this.StepDepthOffset;
                var stepHeight      = this.stepHeight;
                var stepCount       = this.StepCount;
                var bounds          = this.bounds;

                var steps = handles.moveSnappingSteps;
                steps.y = stepHeight;

                if (handles.DoBoundsHandle(ref bounds, snappingSteps: steps))
                {
                    newDefinition.bounds = bounds;
                }

                var min = new Vector3(Mathf.Min(bounds.min.x, bounds.max.x), Mathf.Min(bounds.min.y, bounds.max.y), Mathf.Min(bounds.min.z, bounds.max.z));
                var max = new Vector3(Mathf.Max(bounds.min.x, bounds.max.x), Mathf.Max(bounds.min.y, bounds.max.y), Mathf.Max(bounds.min.z, bounds.max.z));

                var size = (max - min);

                var heightStart = bounds.max.y + (bounds.size.y < 0 ? size.y : 0);

                var edgeHeight = heightStart - stepHeight * stepCount;
                var pHeight0   = new Vector3(min.x, edgeHeight, max.z);
                var pHeight1   = new Vector3(max.x, edgeHeight, max.z);

                var depthStart = bounds.min.z - (bounds.size.z < 0 ? size.z : 0);

                var pDepth0 = new Vector3(min.x, max.y, depthStart + stepDepthOffset);
                var pDepth1 = new Vector3(max.x, max.y, depthStart + stepDepthOffset);

                if (handles.DoTurnHandle(ref bounds))
                {
                    newDefinition.bounds = bounds;
                }

                if (handles.DoEdgeHandle1D(out edgeHeight, Axis.Y, pHeight0, pHeight1, snappingStep: stepHeight))
                {
                    var         totalStepHeight = Mathf.Clamp((heightStart - edgeHeight), size.y % stepHeight, size.y);
                    const float kSmudgeValue    = 0.0001f;
                    var         oldStepCount    = newDefinition.StepCount;
                    var         newStepCount    = Mathf.Max(1, Mathf.FloorToInt((Mathf.Abs(totalStepHeight) + kSmudgeValue) / stepHeight));

                    newDefinition.stepDepth     = (oldStepCount * newDefinition.stepDepth) / newStepCount;
                    newDefinition.plateauHeight = size.y - (stepHeight * newStepCount);
                }

                if (handles.DoEdgeHandle1D(out stepDepthOffset, Axis.Z, pDepth0, pDepth1, snappingStep: ChiselLinearStairsDefinition.kMinStepDepth))
                {
                    stepDepthOffset        -= depthStart;
                    stepDepthOffset         = Mathf.Clamp(stepDepthOffset, 0, this.absDepth - ChiselLinearStairsDefinition.kMinStepDepth);
                    newDefinition.stepDepth = ((this.absDepth - stepDepthOffset) / this.StepCount);
                }

                float heightOffset;
                var   prevModified = handles.modified;
                {
                    var direction = Vector3.Cross(Vector3.forward, pHeight0 - pDepth0).normalized;
                    handles.DoEdgeHandle1DOffset(out var height0vec, Axis.Y, pHeight0, pDepth0, direction, snappingStep: stepHeight);
                    handles.DoEdgeHandle1DOffset(out var height1vec, Axis.Y, pHeight1, pDepth1, direction, snappingStep: stepHeight);
                    var height0 = Vector3.Dot(direction, height0vec);
                    var height1 = Vector3.Dot(direction, height1vec);
                    if (Mathf.Abs(height0) > Mathf.Abs(height1))
                    {
                        heightOffset = height0;
                    }
                    else
                    {
                        heightOffset = height1;
                    }
                }
                if (prevModified != handles.modified)
                {
                    newDefinition.plateauHeight += heightOffset;
                }
            }
            if (handles.modified)
            {
                this = newDefinition;
            }
        }
Example #29
0
        //
        // TODO: code below needs to be cleaned up & simplified
        //

        static void DraggableRadius(IChiselHandles handles, ref float diameterX, ref float diameterZ, Vector3 center, Vector3 up, Vector3 xVector, Vector3 zVector, IChiselHandle[] radiusHandles, bool isEllipsoid)
        {
            if (isEllipsoid)
            {
                Debug.Assert(radiusHandles.Length == 4);
                diameterX = -diameterX; handles.DoSlider1DHandle(ref diameterX, center, xVector, radiusHandles[1]); // right
                if (handles.lastHandleHadFocus)
                {
                    var radiusX = diameterX * 0.5f;
                    var radiusZ = diameterZ * 0.5f;
                    var vecX    = (xVector.normalized * radiusX);
                    var vecZ    = (zVector.normalized * radiusZ);
                    handles.RenderDistanceMeasurement(center, center + vecX, radiusX);
                    handles.RenderDistanceMeasurement(center, center + vecZ, radiusZ);
                }
                diameterX = -diameterX; handles.DoSlider1DHandle(ref diameterX, center, xVector, radiusHandles[0]); // left
                if (handles.lastHandleHadFocus)
                {
                    var radiusX = diameterX * 0.5f;
                    var radiusZ = diameterZ * 0.5f;
                    var vecX    = (xVector.normalized * radiusX);
                    var vecZ    = (zVector.normalized * radiusZ);
                    handles.RenderDistanceMeasurement(center, center + vecX, radiusX);
                    handles.RenderDistanceMeasurement(center, center + vecZ, radiusZ);
                }
                diameterZ = -diameterZ; handles.DoSlider1DHandle(ref diameterZ, center, zVector, radiusHandles[3]); // back
                if (handles.lastHandleHadFocus)
                {
                    var radiusX = diameterX * 0.5f;
                    var radiusZ = diameterZ * 0.5f;
                    var vecX    = (xVector.normalized * radiusX);
                    var vecZ    = (zVector.normalized * radiusZ);
                    handles.RenderDistanceMeasurement(center, center + vecX, radiusX);
                    handles.RenderDistanceMeasurement(center, center + vecZ, radiusZ);
                }
                diameterZ = -diameterZ; handles.DoSlider1DHandle(ref diameterZ, center, zVector, radiusHandles[2]); // forward
                if (handles.lastHandleHadFocus)
                {
                    var radiusX = diameterX * 0.5f;
                    var radiusZ = diameterZ * 0.5f;
                    var vecX    = (xVector.normalized * radiusX);
                    var vecZ    = (zVector.normalized * radiusZ);
                    handles.RenderDistanceMeasurement(center, center + vecX, radiusX);
                    handles.RenderDistanceMeasurement(center, center + vecZ, radiusZ);
                }

                diameterX = Mathf.Abs(diameterX);
                diameterZ = Mathf.Abs(diameterZ);
            }
            else
            {
                Debug.Assert(radiusHandles.Length == 1);

                handles.DoDistanceHandle(ref diameterX, center, up, radiusHandles[0]); // left
                diameterX = Mathf.Abs(diameterX);
                var radiusX = diameterX * 0.5f;

                if (handles.lastHandleHadFocus)
                {
                    if (handles.TryGetClosestPoint(radiusHandles, out var closestPoint, interpolate: false))
                    {
                        var vec = (closestPoint - center);
                        handles.RenderDistanceMeasurement(center, center + vec, radiusX);
                    }
                }
            }
        }