/// <inheritdoc/> public override Aabb GetAabb(Vector3F 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(Vector3F scale, Pose pose) { // Recompute local cached AABB if it is invalid. if (Numeric.IsNaN(_aabbLocal.Minimum.X)) { _aabbLocal = base.GetAabb(Vector3F.One, Pose.Identity); } // Apply scale and pose to AABB. return(_aabbLocal.GetAabb(scale, pose)); }
/// <inheritdoc/> public override Aabb GetAabb(Vector3F 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++) { Vector3F 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(Vector3F 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; } } } Vector3F minimum = new Vector3F(_originX, _minHeight, _originZ); Vector3F maximum = new Vector3F(_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(Vector3F scale, Pose pose) { // Apply scale and pose to AABB. return(_aabbLocal.GetAabb(scale, pose)); }