< Summary

Class:GDX.Experimental.DebugDrawShapes
Assembly:GDX
File(s):./Packages/com.dotbunny.gdx/GDX/Experimental/DebugDrawShapes.cs
Covered lines:0
Uncovered lines:197
Coverable lines:197
Total lines:370
Line coverage:0% (0 of 197)
Covered branches:0
Total branches:0
Covered methods:0
Total methods:12
Method coverage:0% (0 of 12)

Coverage History

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
DebugDrawShapes()0%2100%
GetCircleVertices(...)0%6200%
GetCubeSegmentOffset(...)0%2100%
GetCubeSegmentOffsetNonAlloc(...)0%2100%
GetCubeVertices(...)0%2100%
GetCubeVerticesNonAlloc(...)0%2100%
DrawDottedCube(...)0%2100%
DrawWireCapsule(...)0%56700%
DrawWireArc(...)0%12300%
DrawWireCircle(...)0%12300%
DrawWireCube(...)0%2100%
DrawWireSphere(...)0%12300%

File(s)

./Packages/com.dotbunny.gdx/GDX/Experimental/DebugDrawShapes.cs

#LineLine coverage
 1// Copyright (c) 2020-2024 dotBunny Inc.
 2// dotBunny licenses this file to you under the BSL-1.0 license.
 3// See the LICENSE file in the project root for more information.
 4
 5using Unity.Mathematics;
 6using UnityEngine;
 7
 8namespace GDX.Experimental
 9{
 10    public static class DebugDrawShapes
 11    {
 12        const float PI = 3.1415927f;
 13        const float Deg2Rad = 0.017453292f;
 14        const int DefaultCircleVertexCount = 32;
 15
 16        /// <summary>
 17        ///     The ordered segment index pairs used to describe a cube.
 18        /// </summary>
 19        /// <remarks>
 20        ///     This effectively wraps the left side, then the right, then connects the two sides.
 21        /// </remarks>
 022        public static int[] CubeSegmentIndices =
 23        {
 24            0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7
 25        };
 26
 027        static readonly Quaternion k_RotationPrimaryTopLoop = Quaternion.Euler(0, 90, 0);
 028        static readonly Quaternion k_RotationPrimaryBottomLoop = Quaternion.Euler(0, -90, 180);
 29
 030        static readonly Quaternion k_RotationSecondaryTopLoop = Quaternion.Euler(0, 180, 0);
 031        static readonly Quaternion k_RotationSecondaryBottomLoop = Quaternion.Euler(0, 0, 180);
 32
 33
 34        static void GetCircleVertices(ref Vector3[] vertices, int startIndex, Vector3 center, Quaternion rotation,
 35            float radius, int circleVertexCount = DefaultCircleVertexCount)
 036        {
 037            float radiansInterval = PI * 2f / circleVertexCount;
 38
 39            // Loop through and figure out the points
 040            for (int i = 0; i < circleVertexCount; i++)
 041            {
 042                float angle = i * radiansInterval;
 43
 44                // Create base point
 045                vertices[i + startIndex] =
 46                    rotation * new Vector3(0, math.sin(angle) * radius, math.cos(angle) * radius) + center;
 047            }
 048        }
 49
 50        static int[] GetCubeSegmentOffset(int offset)
 051        {
 052            int[] newIndices = new int[24]
 53            {
 54                CubeSegmentIndices[0] + offset, CubeSegmentIndices[1] + offset, CubeSegmentIndices[2] + offset,
 55                CubeSegmentIndices[3] + offset, CubeSegmentIndices[4] + offset, CubeSegmentIndices[5] + offset,
 56                CubeSegmentIndices[6] + offset, CubeSegmentIndices[7] + offset, CubeSegmentIndices[8] + offset,
 57                CubeSegmentIndices[9] + offset, CubeSegmentIndices[10] + offset, CubeSegmentIndices[11] + offset,
 58                CubeSegmentIndices[12] + offset, CubeSegmentIndices[13] + offset, CubeSegmentIndices[14] + offset,
 59                CubeSegmentIndices[15] + offset, CubeSegmentIndices[16] + offset, CubeSegmentIndices[17] + offset,
 60                CubeSegmentIndices[18] + offset, CubeSegmentIndices[19] + offset, CubeSegmentIndices[20] + offset,
 61                CubeSegmentIndices[21] + offset, CubeSegmentIndices[22] + offset, CubeSegmentIndices[23] + offset
 62            };
 063            return newIndices;
 064        }
 65
 66        static void GetCubeSegmentOffsetNonAlloc(int[] indices, int startIndex, int offset)
 067        {
 068            indices[startIndex] = CubeSegmentIndices[0] + offset;
 069            indices[startIndex + 1] = CubeSegmentIndices[1] + offset;
 070            indices[startIndex + 2] = CubeSegmentIndices[2] + offset;
 071            indices[startIndex + 3] = CubeSegmentIndices[3] + offset;
 072            indices[startIndex + 4] = CubeSegmentIndices[4] + offset;
 073            indices[startIndex + 5] = CubeSegmentIndices[5] + offset;
 074            indices[startIndex + 6] = CubeSegmentIndices[6] + offset;
 075            indices[startIndex + 7] = CubeSegmentIndices[7] + offset;
 076            indices[startIndex + 8] = CubeSegmentIndices[8] + offset;
 077            indices[startIndex + 9] = CubeSegmentIndices[9] + offset;
 078            indices[startIndex + 10] = CubeSegmentIndices[10] + offset;
 079            indices[startIndex + 11] = CubeSegmentIndices[11] + offset;
 080            indices[startIndex + 12] = CubeSegmentIndices[12] + offset;
 081            indices[startIndex + 13] = CubeSegmentIndices[13] + offset;
 082            indices[startIndex + 14] = CubeSegmentIndices[14] + offset;
 083            indices[startIndex + 15] = CubeSegmentIndices[15] + offset;
 084            indices[startIndex + 16] = CubeSegmentIndices[16] + offset;
 085            indices[startIndex + 17] = CubeSegmentIndices[17] + offset;
 086            indices[startIndex + 18] = CubeSegmentIndices[18] + offset;
 087            indices[startIndex + 19] = CubeSegmentIndices[19] + offset;
 088            indices[startIndex + 20] = CubeSegmentIndices[20] + offset;
 089            indices[startIndex + 21] = CubeSegmentIndices[21] + offset;
 090            indices[startIndex + 22] = CubeSegmentIndices[22] + offset;
 091            indices[startIndex + 23] = CubeSegmentIndices[23] + offset;
 092        }
 93
 94        /// <summary>
 95        ///     Get the vertices that make up a cube.
 96        /// </summary>
 97        /// <remarks>
 98        ///     Ordered based on <see cref="CubeSegmentIndices" />.
 99        /// </remarks>
 100        /// <param name="center">The world space center location of the cube.</param>
 101        /// <param name="size">The size of the cube.</param>
 102        /// <returns>An array of ordered vertices.</returns>
 103        static Vector3[] GetCubeVertices(Vector3 center, Quaternion rotation, Vector3 size)
 0104        {
 0105            Vector3 half = size / 2f;
 106
 0107            float centerMinusHalfX = center.x - half.x;
 0108            float centerMinusHalfY = center.y - half.y;
 0109            float centerMinusHalfZ = center.z - half.z;
 0110            float centerPlusHalfX = center.x + half.x;
 0111            float centerPlusHalfY = center.y + half.y;
 0112            float centerPlusHalfZ = center.z + half.z;
 113
 0114            Vector3[] points =
 115            {
 116                rotation * new Vector3(centerMinusHalfX, centerMinusHalfY, centerMinusHalfZ), // Front Bottom Left (0)
 117                rotation * new Vector3(centerMinusHalfX, centerMinusHalfY, centerPlusHalfZ), // Back Bottom Left (1)
 118                rotation * new Vector3(centerMinusHalfX, centerPlusHalfY, centerPlusHalfZ), // Back Top Left (2)
 119                rotation * new Vector3(centerMinusHalfX, centerPlusHalfY, centerMinusHalfZ), // Front Top Left (3)
 120                rotation * new Vector3(centerPlusHalfX, centerMinusHalfY, centerMinusHalfZ), // Front Bottom Right (4)
 121                rotation * new Vector3(centerPlusHalfX, centerMinusHalfY, centerPlusHalfZ), // Back Bottom Right (5)
 122                rotation * new Vector3(centerPlusHalfX, centerPlusHalfY, centerPlusHalfZ), // Back Top Right (6)
 123                rotation * new Vector3(centerPlusHalfX, centerPlusHalfY, centerMinusHalfZ) // Front Top Right (7)
 124            };
 125
 0126            return points;
 0127        }
 128
 129        static void GetCubeVerticesNonAlloc(ref Vector3[] points, int startIndex, Vector3 center, Quaternion rotation,
 130            Vector3 size)
 0131        {
 0132            Vector3 half = size / 2f;
 133
 0134            float centerMinusHalfX = center.x - half.x;
 0135            float centerMinusHalfY = center.y - half.y;
 0136            float centerMinusHalfZ = center.z - half.z;
 0137            float centerPlusHalfX = center.x + half.x;
 0138            float centerPlusHalfY = center.y + half.y;
 0139            float centerPlusHalfZ = center.z + half.z;
 140
 0141            points[startIndex] =
 142                rotation * new Vector3(centerMinusHalfX, centerMinusHalfY, centerMinusHalfZ); // Front Bottom Left (0)
 0143            points[startIndex + 1] =
 144                rotation * new Vector3(centerMinusHalfX, centerMinusHalfY, centerPlusHalfZ); // Back Bottom Left (1)
 0145            points[startIndex + 2] =
 146                rotation * new Vector3(centerMinusHalfX, centerPlusHalfY, centerPlusHalfZ); // Back Top Left (2)
 0147            points[startIndex + 3] =
 148                rotation * new Vector3(centerMinusHalfX, centerPlusHalfY, centerMinusHalfZ); // Front Top Left (3)
 0149            points[startIndex + 4] =
 150                rotation * new Vector3(centerPlusHalfX, centerMinusHalfY, centerMinusHalfZ); // Front Bottom Right (4)
 0151            points[startIndex + 5] =
 152                rotation * new Vector3(centerPlusHalfX, centerMinusHalfY, centerPlusHalfZ); // Back Bottom Right (5)
 0153            points[startIndex + 6] =
 154                rotation * new Vector3(centerPlusHalfX, centerPlusHalfY, centerPlusHalfZ); // Back Top Right (6)
 0155            points[startIndex + 7] =
 156                rotation * new Vector3(centerPlusHalfX, centerPlusHalfY, centerMinusHalfZ); // Front Top Right (7)
 0157        }
 158
 159        /// <summary>
 160        ///     Draw a dotted line cube of a specific color to the buffer.
 161        /// </summary>
 162        /// <param name="color">The color which to draw the dotted line cube with.</param>
 163        /// <param name="center">The center world position of the cube.</param>
 164        /// <param name="size">The unit size of the cube</param>
 165        /// <returns>The created cube's invalidation token.</returns>
 166        public static int DrawDottedCube(this DebugDrawBuffer buffer, Color color, Vector3 center, Quaternion rotation,
 167            Vector3 size)
 0168        {
 0169            Vector3[] vertices = GetCubeVertices(center, rotation, size);
 0170            return buffer.DrawDottedLines(color, ref vertices, ref CubeSegmentIndices);
 0171        }
 172
 173
 174        public static int DrawWireCapsule(this DebugDrawBuffer buffer, Color color, Vector3 bottomSpherePosition,
 175            Vector3 topSpherePosition, Quaternion rotation, float radius,
 176            int arcVertexCount = DefaultCircleVertexCount / 2)
 0177        {
 178            // Calculate total vertices
 0179            int totalVertices = arcVertexCount * 4;
 180
 181            // TODO: add circles?
 0182            Vector3[] vertices = new Vector3[totalVertices];
 0183            float baseAngle = 0f;
 0184            float arcLength = 180f;
 0185            int lineCount = arcVertexCount - 1;
 186
 0187            int bottomPrimaryStartIndex = arcVertexCount;
 0188            int topSecondaryStartIndex = bottomPrimaryStartIndex * 2;
 0189            int bottomSecondaryStartIndex = bottomPrimaryStartIndex * 3;
 190
 0191            Quaternion primaryTopRotation = rotation * k_RotationPrimaryTopLoop;
 0192            Quaternion primaryBottomRotation = rotation * k_RotationPrimaryBottomLoop;
 0193            Quaternion secondaryTopRotation = rotation * k_RotationSecondaryTopLoop;
 0194            Quaternion secondaryBottomRotation = rotation * k_RotationSecondaryBottomLoop;
 195
 0196            for (int i = 0; i < arcVertexCount; i++)
 0197            {
 0198                float currentAngle = Deg2Rad * baseAngle;
 199
 0200                Vector3 basePosition =
 201                    new Vector3(0, Mathf.Sin(currentAngle) * radius, Mathf.Cos(currentAngle) * radius);
 202
 0203                vertices[i] = primaryTopRotation * basePosition + topSpherePosition;
 0204                vertices[i + bottomPrimaryStartIndex] = primaryBottomRotation * basePosition + bottomSpherePosition;
 205
 0206                vertices[i + topSecondaryStartIndex] = secondaryTopRotation * basePosition + topSpherePosition;
 0207                vertices[i + bottomSecondaryStartIndex] = secondaryBottomRotation * basePosition + bottomSpherePosition;
 208
 0209                baseAngle += arcLength / lineCount;
 0210            }
 211
 212
 213            // Create segment connections
 0214            int blockSize = lineCount * 2 + 2;
 0215            int[] segments = new int[blockSize * 4];
 216
 0217            int primaryTopBottomConnectionIndex = blockSize - 2;
 0218            int primaryBottomTopConnectionIndex = blockSize * 2 - 2;
 0219            int secondaryTopBottomConnectionIndex = blockSize * 3 - 2;
 0220            int secondaryBottomTopConnectionIndex = blockSize * 4 - 2;
 221
 0222            int segmentCount = segments.Length;
 0223            int baseCount = 0;
 224
 0225            for (int i = 0; i < segmentCount; i += 2)
 0226            {
 0227                if (i == primaryTopBottomConnectionIndex || i == primaryBottomTopConnectionIndex ||
 228                    i == secondaryTopBottomConnectionIndex || i == secondaryBottomTopConnectionIndex)
 0229                {
 0230                    baseCount++;
 0231                    continue;
 232                }
 233
 0234                segments[i] = baseCount;
 0235                baseCount++;
 0236                segments[i + 1] = baseCount;
 0237            }
 238
 0239            segments[primaryTopBottomConnectionIndex] = segments[primaryTopBottomConnectionIndex - 1];
 0240            segments[primaryTopBottomConnectionIndex + 1] = segments[primaryTopBottomConnectionIndex + 2];
 241
 0242            segments[primaryBottomTopConnectionIndex] = segments[primaryBottomTopConnectionIndex - 1];
 0243            segments[primaryBottomTopConnectionIndex + 1] = segments[0];
 244
 0245            segments[secondaryTopBottomConnectionIndex] = segments[secondaryTopBottomConnectionIndex - 1];
 0246            segments[secondaryTopBottomConnectionIndex + 1] = segments[secondaryTopBottomConnectionIndex + 2];
 247
 0248            segments[secondaryBottomTopConnectionIndex] = segments[secondaryBottomTopConnectionIndex - 1];
 0249            segments[secondaryBottomTopConnectionIndex + 1] = segments[primaryBottomTopConnectionIndex + 2];
 250
 251            // Link top to bottom
 0252            return buffer.DrawLines(color, ref vertices, ref segments);
 0253        }
 254
 255        public static int DrawWireArc(this DebugDrawBuffer buffer, Color color, Vector3 center, Quaternion rotation,
 256            float radius, float startAngle = 0f, float endAngle = 180f,
 257            int arcVertexCount = DefaultCircleVertexCount / 2)
 0258        {
 259            // We do the plus one to complete the full arc segment, otherwise it would not be every peice
 0260            Vector3[] vertices = new Vector3[arcVertexCount];
 0261            float baseAngle = startAngle;
 0262            float arcLength = endAngle - startAngle;
 0263            int lineCount = arcVertexCount - 1;
 0264            for (int i = 0; i < arcVertexCount; i++)
 0265            {
 0266                float currentAngle = Deg2Rad * baseAngle;
 0267                vertices[i] =
 268                    rotation * new Vector3(0, Mathf.Sin(currentAngle) * radius, Mathf.Cos(currentAngle) * radius) +
 269                    center;
 0270                baseAngle += arcLength / lineCount;
 0271            }
 272
 273            // Create segment connections
 0274            int[] segments = new int[lineCount * 2];
 0275            int segmentCount = segments.Length;
 0276            int baseCount = 0;
 0277            for (int i = 0; i < segmentCount; i += 2)
 0278            {
 0279                segments[i] = baseCount;
 0280                baseCount++;
 0281                segments[i + 1] = baseCount;
 0282            }
 283
 0284            return buffer.DrawLines(color, ref vertices, ref segments);
 0285        }
 286
 287        public static int DrawWireCircle(this DebugDrawBuffer buffer, Color color, Vector3 center, Quaternion rotation,
 288            float radius, int circleVertexCount = DefaultCircleVertexCount)
 0289        {
 0290            Vector3[] vertices = new Vector3[circleVertexCount];
 0291            float radiansInterval = PI * 2f / circleVertexCount;
 292
 293            // Loop through and figure out the points
 0294            for (int i = 0; i < circleVertexCount; i++)
 0295            {
 0296                float angle = i * radiansInterval;
 297
 298                // Create base point
 0299                vertices[i] = rotation * new Vector3(0, math.sin(angle) * radius, math.cos(angle) * radius) + center;
 0300            }
 301
 0302            int[] segments = new int[circleVertexCount * 2];
 0303            int segmentCount = segments.Length;
 0304            int baseCount = 0;
 305
 0306            for (int i = 0; i < segmentCount; i += 2)
 0307            {
 0308                segments[i] = baseCount;
 0309                baseCount++;
 0310                segments[i + 1] = baseCount;
 0311            }
 312
 0313            segments[segmentCount - 1] = 0;
 314
 0315            return buffer.DrawLines(color, ref vertices, ref segments);
 0316        }
 317
 318        /// <summary>
 319        ///     Draw a wireframe cube of a specific color to the buffer.
 320        /// </summary>
 321        /// <param name="color">The color which to draw the wire cube with.</param>
 322        /// <param name="center">The center world position of the cube.</param>
 323        /// <param name="size">The unit size of the cube</param>
 324        /// <returns>The created cube's invalidation token.</returns>
 325        public static int DrawWireCube(this DebugDrawBuffer buffer, Color color, Vector3 center, Quaternion rotation,
 326            Vector3 size)
 0327        {
 0328            Vector3[] vertices = GetCubeVertices(center, rotation, size);
 0329            return buffer.DrawLines(color, ref vertices, ref CubeSegmentIndices);
 0330        }
 331
 332        public static int DrawWireSphere(this DebugDrawBuffer buffer, Color color, Vector3 center, Quaternion rotation,
 333            float radius, int circleVertexCount = DefaultCircleVertexCount)
 0334        {
 0335            int pointCount = circleVertexCount * 2;
 0336            Vector3[] vertices = new Vector3[pointCount];
 337
 0338            float radiansInterval = PI * 2f / circleVertexCount;
 0339            Quaternion xRotation = Space.Axis.X.ToRotation() * rotation;
 0340            Quaternion yRotation = Space.Axis.Y.ToRotation() * rotation;
 341
 342            // Loop through and figure out the points
 0343            for (int i = 0; i < circleVertexCount; i++)
 0344            {
 0345                float angle = i * radiansInterval;
 346
 347                // Create base points
 0348                vertices[i] = xRotation * new Vector3(0, math.sin(angle) * radius, math.cos(angle) * radius) + center;
 0349                vertices[i + circleVertexCount] =
 350                    yRotation * new Vector3(0, math.sin(angle) * radius, math.cos(angle) * radius) + center;
 0351            }
 352
 353            // Create segment connections
 0354            int[] segments = new int[pointCount * 2];
 0355            int segmentCount = segments.Length;
 0356            int baseCount = 0;
 0357            for (int i = 0; i < segmentCount; i += 2)
 0358            {
 0359                segments[i] = baseCount;
 0360                baseCount++;
 0361                segments[i + 1] = baseCount;
 0362            }
 363
 0364            segments[pointCount - 1] = 0;
 0365            segments[segmentCount - 1] = circleVertexCount;
 366
 0367            return buffer.DrawLines(color, ref vertices, ref segments);
 0368        }
 369    }
 370}