public void TestConvexColliderCalculateAabbLocal()
        {
            var points = new NativeArray <float3>(6, Allocator.Temp)
            {
                [0] = new float3(1.45f, 8.67f, 3.45f),
                [1] = new float3(8.75f, 1.23f, 6.44f),
                [2] = new float3(100.34f, 5.33f, -2.55f),
                [3] = new float3(8.76f, 4.56f, -4.54f),
                [4] = new float3(9.75f, -0.45f, -8.99f),
                [5] = new float3(7.66f, 3.44f, 0.0f)
            };
            float convexRadius = 1.25f;

            Aabb expectedAabb = Aabb.CreateFromPoints(new float3x4(points[0], points[1], points[2], points[3]));

            expectedAabb.Include(points[4]);
            expectedAabb.Include(points[5]);

            // Currently the convex hull is not shrunk, so we have to expand by the convex radius
            expectedAabb.Expand(convexRadius);

            var collider = ConvexCollider.Create(points, convexRadius);

            points.Dispose();

            Aabb actualAabb = collider.Value.CalculateAabb();

            TestUtils.AreEqual(expectedAabb.Min, actualAabb.Min, 1e-3f);
            TestUtils.AreEqual(expectedAabb.Max, actualAabb.Max, 1e-3f);
        }
예제 #2
0
    public bool Query(Aabb bounds, QueryCallbcak callback = null)
    {
        m_stack.Clear();
        m_stack.Push(m_root);

        bool touchedAnyBounds = false;

        while (m_stack.Count > 0)
        {
            int index = m_stack.Pop();
            if (index == Null)
            {
                continue;
            }

            Aabb tightBounds = m_nodes[index].Bounds;
            tightBounds.Expand(-FatBoundsRadius);
            if (!Aabb.Intersects(bounds, tightBounds))
            {
                continue;
            }

            if (m_nodes[index].IsLeaf)
            {
                touchedAnyBounds = true;

                bool proceed =
                    callback != null
            ? callback(m_nodes[index].UserData)
            : true;

                if (!proceed)
                {
                    return(true);
                }
            }
            else
            {
                m_stack.Push(m_nodes[index].ChildA);
                m_stack.Push(m_nodes[index].ChildB);
            }
        }

        return(touchedAnyBounds);
    }
        public void TestConvexColliderCalculateAabbTransformed()
        {
            var points = new NativeArray <float3>(6, Allocator.Temp)
            {
                [0] = new float3(1.45f, 8.67f, 3.45f),
                [1] = new float3(8.75f, 1.23f, 6.44f),
                [2] = new float3(100.34f, 5.33f, -2.55f),
                [3] = new float3(8.76f, 4.56f, -4.54f),
                [4] = new float3(9.75f, -0.45f, -8.99f),
                [5] = new float3(7.66f, 3.44f, 0.0f)
            };

            float      convexRadius = 1.25f;
            float3     translation  = new float3(43.56f, -87.32f, -0.02f);
            quaternion rotation     = quaternion.AxisAngle(math.normalize(new float3(8.45f, -2.34f, 0.82f)), 43.21f);

            float3[] transformedPoints = new float3[points.Length];
            for (int i = 0; i < points.Length; ++i)
            {
                transformedPoints[i] = translation + math.mul(rotation, points[i]);
            }

            Aabb expectedAabb = Aabb.CreateFromPoints(new float3x4(transformedPoints[0], transformedPoints[1], transformedPoints[2], transformedPoints[3]));

            expectedAabb.Include(transformedPoints[4]);
            expectedAabb.Include(transformedPoints[5]);

            // Currently the convex hull is not shrunk, so we have to expand by the convex radius
            expectedAabb.Expand(convexRadius);

            var collider = ConvexCollider.Create(points, convexRadius);

            points.Dispose();

            Aabb actualAabb = collider.Value.CalculateAabb(new RigidTransform(rotation, translation));

            TestUtils.AreEqual(expectedAabb.Min, actualAabb.Min, 1e-3f);
            TestUtils.AreEqual(expectedAabb.Max, actualAabb.Max, 1e-3f);
        }
예제 #4
0
    public int Fill(ComputeBuffer buffer, float aabbTightenRadius = 0.0f)
    {
        if (m_root == Null)
        {
            return(Null);
        }

        if (m_pods.Length != m_nodes.Length)
        {
            m_pods = new NodePod[m_nodes.Length];
        }

        for (int i = 0; i < m_nodes.Length; ++i)
        {
            if (m_nodes[i].IsFree)
            {
                continue;
            }

            Aabb tightBounds = m_nodes[i].Bounds;
            tightBounds.Expand(-aabbTightenRadius);

            m_pods[i].Bounds = tightBounds;
            m_pods[i].Parent = m_nodes[i].Parent;
            m_pods[i].ChildA = m_nodes[i].ChildA;
            m_pods[i].ChildB = m_nodes[i].ChildB;

            var shape = m_nodes[i].UserData as RayMarchedShape;
            if (shape != null)
            {
                m_pods[i].UserDataIndex = shape.ShapeIndex;
            }
        }

        buffer.SetData(m_pods);

        return(m_root);
    }
예제 #5
0
    public bool RayCast(Vector3 from, Vector3 to, RayCastCallback callback = null)
    {
        Vector3 r = to - from;

        r.Normalize();

        float maxFraction = 1.0f;

        // v is perpendicular to the segment.
        Vector3 v    = VectorUtil.FindOrthogonal(r).normalized;
        Vector3 absV = VectorUtil.Abs(v);

        // build a bounding box for the segment.
        Aabb rayBounds = Aabb.Empty;

        rayBounds.Include(from);
        rayBounds.Include(to);

        m_stack.Clear();
        m_stack.Push(m_root);

        bool hitAnyBounds = false;

        while (m_stack.Count > 0)
        {
            int index = m_stack.Pop();
            if (index == Null)
            {
                continue;
            }

            if (!Aabb.Intersects(m_nodes[index].Bounds, rayBounds))
            {
                continue;
            }

            // Separating axis for segment (Gino, p80).
            // |dot(v, a - c)| > dot(|v|, h)
            Vector3 c          = m_nodes[index].Bounds.Center;
            Vector3 h          = m_nodes[index].Bounds.HalfExtents;
            float   separation = Mathf.Abs(Vector3.Dot(v, from - c)) - Vector3.Dot(absV, h);
            if (separation > 0.0f)
            {
                continue;
            }

            if (m_nodes[index].IsLeaf)
            {
                Aabb tightBounds = m_nodes[index].Bounds;
                tightBounds.Expand(-FatBoundsRadius);
                float t = tightBounds.RayCast(from, to, maxFraction);
                if (t < 0.0f)
                {
                    continue;
                }

                hitAnyBounds = true;

                float newMaxFraction =
                    callback != null
            ? callback(from, to, m_nodes[index].UserData)
            : maxFraction;

                if (newMaxFraction >= 0.0f)
                {
                    // Update segment bounding box.
                    maxFraction = newMaxFraction;
                    Vector3 newTo = from + maxFraction * (to - from);
                    rayBounds.Min = VectorUtil.Min(from, newTo);
                    rayBounds.Max = VectorUtil.Max(from, newTo);
                }
            }
            else
            {
                m_stack.Push(m_nodes[index].ChildA);
                m_stack.Push(m_nodes[index].ChildB);
            }
        }

        return(hitAnyBounds);
    }