/// <inheritdoc/>
        public override Aabb GetAabb(Vector3 scale, Pose pose)
        {
            // If we have a spatial partition, we can use the AABB of the whole spatial partition to
            // quickly get an approximate AABB.
            if (Partition != null)
            {
                // Get AABB of spatial partition and compute the AABB in world space.
                return(Partition.Aabb.GetAabb(scale, pose));
            }

            // No children? - Return arbitrary AABB.
            var numberOfGeometries = Children.Count;

            if (numberOfGeometries == 0)
            {
                return(new Aabb(pose.Position, pose.Position));
            }

            // See also comments in TransformShape.GetAabb().

            if (scale.X == scale.Y && scale.Y == scale.Z)
            {
                // Uniform scaling.

                // Get union of children's AABBs. scale is applied at the end.
                var child = Children[0];

                // Scale child pose.
                Pose childPose = new Pose(child.Pose.Position * scale.X, child.Pose.Orientation);

                // Get child aabb in final space.
                Aabb aabb = child.Shape.GetAabb(scale.X * child.Scale, pose * childPose);
                for (int i = 1; i < numberOfGeometries; i++)
                {
                    child     = Children[i];
                    childPose = new Pose(child.Pose.Position * scale.X, child.Pose.Orientation);
                    aabb.Grow(child.Shape.GetAabb(scale.X * child.Scale, pose * childPose));
                }

                return(aabb);
            }
            else
            {
                // Get AABB of children in the parent space without scale.
                Aabb aabb = Children[0].Aabb;
                for (int i = 1; i < numberOfGeometries; i++)
                {
                    aabb.Grow(Children[i].Aabb);
                }

                // Now, from this compute an AABB in world space.
                return(aabb.GetAabb(scale, pose));
            }
        }
        /// <inheritdoc/>
        public override Aabb GetAabb(Vector3 scale, Pose pose)
        {
            // Recompute local cached AABB if it is invalid.
            if (Numeric.IsNaN(_aabbLocal.Minimum.X))
            {
                _aabbLocal = base.GetAabb(Vector3.One, Pose.Identity);
            }

            // Apply scale and pose to AABB.
            return(_aabbLocal.GetAabb(scale, pose));
        }
Exemple #3
0
        /// <inheritdoc/>
        public override Aabb GetAabb(Vector3 scale, Pose pose)
        {
            if (Numeric.IsNaN(_aabbLocal.Minimum.X))
            {
                // ----- Recompute local cached AABB if it is invalid.

                if (Partition == null)
                {
                    // ----- No spatial partition.
                    _aabbLocal = new Aabb();

                    if (_mesh != null && _mesh.NumberOfTriangles > 0)
                    {
                        bool isFirst = true;

                        // Get AABB that contains all triangles.
                        for (int i = 0; i < _mesh.NumberOfTriangles; i++)
                        {
                            Triangle triangle = _mesh.GetTriangle(i);

                            for (int j = 0; j < 3; j++)
                            {
                                Vector3 vertex = triangle[j];
                                if (isFirst)
                                {
                                    isFirst    = false;
                                    _aabbLocal = new Aabb(vertex, vertex);
                                }
                                else
                                {
                                    _aabbLocal.Grow(vertex);
                                }
                            }
                        }
                    }
                }
                else
                {
                    // ----- With spatial partition.
                    // Use spatial partition to determine local AABB.
                    _aabbLocal = Partition.Aabb;
                }
            }

            // Apply scale and pose to AABB.
            return(_aabbLocal.GetAabb(scale, pose));
        }
        /// <inheritdoc/>
        public override Aabb GetAabb(Vector3 scale, Pose pose)
        {
            // Recompute local cached AABB if it is invalid.
            if (Numeric.IsNaN(_minHeight))
            {
                // Find min and max height.
                // TODO: We could cache that beforehand.
                _minHeight = float.PositiveInfinity;
                _maxHeight = float.NegativeInfinity;
                foreach (float height in _samples)
                {
                    if (height < _minHeight)
                    {
                        _minHeight = height;
                    }
                    if (height > _maxHeight)
                    {
                        _maxHeight = height;
                    }
                }
            }

            Vector3 minimum = new Vector3(_originX, _minHeight, _originZ);
            Vector3 maximum = new Vector3(_originX + _widthX, _maxHeight, _originZ + _widthZ);

            // Apply scale.
            var scaledLocalAabb = new Aabb(minimum, maximum);

            scaledLocalAabb.Scale(scale);

            // Add depth after scaling because scaleY = 0 makes sense to flatten the height field
            // but the bounding box should have a height > 0 to avoid tunneling.
            scaledLocalAabb.Minimum.Y = Math.Min(scaledLocalAabb.Minimum.Y - _depth, -_depth);

            // Apply pose.
            return(scaledLocalAabb.GetAabb(pose));
        }
 /// <inheritdoc/>
 public override Aabb GetAabb(Vector3 scale, Pose pose)
 {
     // Apply scale and pose to AABB.
     return(_aabbLocal.GetAabb(scale, pose));
 }