Castle Game Engine: CastleBoxes: Object TBox3D

# Object TBox3D
Description | Hierarchy | Fields | Methods | Properties
## Unit CastleBoxes ## Declaration `type TBox3D = object(TObject)` ## Description Axis-aligned box. Rectangular prism with all sides parallel to basic planes X = 0, Y = 0 and Z = 0. This is sometimes called AABB, "axis-aligned bounding box". Many geometric operations are fast and easy on this type. The actual box dimensions are stored inside the Data field, as two 3D points. First point has always all the smaller coords, second point has all the larger coords. I.e. always
      Data[0, 0] <= Data[1, 0] and
      Data[0, 1] <= Data[1, 1] and
      Data[0, 2] <= Data[1, 2]
The only exception is the special value EmptyBox3D. Note that the box may still have all sizes equal 0. Consider a 3D model with only a single 3D point — it's not empty, but all the sizes must be 0. This is an old-style object (withut any virtual methods). This way there's no need for using constructors / destructors to manage this, you can simply declare `TBox3D` type and copy / pass around this box to other procedures. ## Hierarchy TObject TBox3D ## Overview ### Fields
| `Data: array [0..1 ] of TVector3Single;`
### Methods
| `function IsEmpty: boolean;`
| `function IsEmptyOrZero: boolean;`
| `procedure CheckNonEmpty;`
| `function Middle: TVector3Single;`
| `function AverageSize: Single; overload;`
| `function MaxSize: Single; overload;`
| `function MinSize: Single;`
| `function SizeX: Single;`
| `function SizeY: Single;`
| `function SizeZ: Single;`
| `function AverageSize(const AllowZero: boolean; const EmptyBoxSize: Single): Single; overload;`
| `function MaxSize(const AllowZero: boolean; const EmptyBoxSize: Single): Single; overload;`
| `function Area(const AllowZero: boolean; const EmptyBoxArea: Single): Single;`
| `procedure ExpandMe(const AExpand: Single); overload;`
| `procedure ExpandMe(const AExpand: TVector3Single); overload;`
| `function Expand(const AExpand: Single): TBox3D; overload;`
| `function Expand(const AExpand: TVector3Single): TBox3D; overload;`
| `function PointInside(const Point: TVector3Single): boolean; overload;`
| `function PointInside(const Point: TVector3Double): boolean; overload;`
| `function PointInside2D(const Point: TVector3Single; const IgnoreIndex: Integer): boolean;`
| `procedure Add(const box2: TBox3D); overload;`
| `procedure Add(const Point: TVector3Single); overload;`
| `function Sizes: TVector3Single;`
| `procedure GetAllPoints(allpoints: PVector3Single);`
| `function Transform(const Matrix: TMatrix4Single): TBox3D;`
| `function Translate(const Translation: TVector3Single): TBox3D;`
| `function AntiTranslate(const Translation: TVector3Single): TBox3D;`
| `function ToNiceStr: string;`
| `function ToRawStr: string;`
| `procedure Clamp(var point: TVector3Single); overload;`
| `procedure Clamp(var point: TVector3Double); overload;`
| `function TryRayClosestIntersection( out Intersection: TVector3Single; out IntersectionDistance: Single; const RayOrigin, RayDirection: TVector3Single): boolean; overload;`
| `function TryRayClosestIntersection( out Intersection: TVector3Single; const RayOrigin, RayDirection: TVector3Single): boolean; overload;`
| `function TryRayClosestIntersection( out IntersectionDistance: Single; const RayOrigin, RayDirection: TVector3Single): boolean; overload;`
| `function TryRayEntrance( out Entrance: TVector3Single; out EntranceDistance: Single; const RayOrigin, RayDirection: TVector3Single): boolean; overload;`
| `function TryRayEntrance( out Entrance: TVector3Single; const RayOrigin, RayDirection: TVector3Single): boolean; overload;`
| `function SegmentCollision( const Segment1, Segment2: TVector3Single): boolean;`
| `function PlaneCollision(const Plane: TVector4Single): TPlaneCollision;`
| `function PlaneCollisionInside(const Plane: TVector4Single): boolean;`
| `function PlaneCollisionOutside(const Plane: TVector4Single): boolean;`
| `function IsTriangleCollision( const Triangle: TTriangle3Single): boolean;`
| `procedure BoundingSphere( var SphereCenter: TVector3Single; var SphereRadiusSqr: Single);`
| `function Collision(const Box2: TBox3D): boolean;`
| `function Radius: Single;`
| `function Radius2D(const IgnoreIndex: Integer): Single;`
| `function SphereSimpleCollision( const SphereCenter: TVector3Single; const SphereRadius: Single): boolean;`
| `function SphereCollision( const SphereCenter: TVector3Single; const SphereRadius: Single): boolean;`
| `function MaximumPlane(const Direction: TVector3Single): TVector4Single;`
| `function MinimumPlane(const Direction: TVector3Single): TVector4Single;`
| `procedure PointDistances(const P: TVector3Single; out MinDistance, MaxDistance: Single);`
| `procedure DirectionDistances( const Point, Dir: TVector3Single; out MinDistance, MaxDistance: Single);`
| `function PointDistance(const Point: TVector3Single): Single;`
| `function PointMaxDistance(const Point: TVector3Single; const EmptyBoxDistance: Single): Single;`
| `function Equal(const Box2: TBox3D): boolean;`
| `function Equal(const Box2: TBox3D; const EqualityEpsilon: Single): boolean;`
| `function Diagonal: Single;`
## Description ### Fields
| `Data: array [0..1 ] of TVector3Single;`
### Methods
| `function IsEmpty: boolean;`
Check is box empty. You can think of this function as "compare Box with EmptyBox3D". But actually it works a little faster, by utilizing the assumption that EmptyBox3D is the only allowed value that breaks `Data[0, 0] <= Data[1, 0]` rule.
| `function IsEmptyOrZero: boolean;`
Check is box empty or has all the sizes equal 0.
| `procedure CheckNonEmpty;`
| `function Middle: TVector3Single;`
These functions calculate the middle point, average size, max size and particular sizes of given bounding box. ###### Exceptions raised EBox3DEmpty If the Box is empty.
| `function AverageSize: Single; overload;`
| `function MaxSize: Single; overload;`
| `function MinSize: Single;`
| `function SizeX: Single;`
| `function SizeY: Single;`
| `function SizeZ: Single;`
| `function AverageSize(const AllowZero: boolean; const EmptyBoxSize: Single): Single; overload;`
Average size of TBox3D, or EmptyBoxSize if box is empty. ###### Parameters AllowZero Decides what to do when box is not empty but the result would be zero, which means that the box is infinitely thin in all axes. If `True`, then result is just 0, otherwise it's EmptyBoxSize.
| `function MaxSize(const AllowZero: boolean; const EmptyBoxSize: Single): Single; overload;`
Largest size of TBox3D, or EmptyBoxSize if box is empty. ###### Parameters AllowZero Decides what to do when box is not empty but the result would be zero, which means that the box is infinitely thin in all axes. If `True`, then result is just 0, otherwise it's EmptyBoxSize.
| `function Area(const AllowZero: boolean; const EmptyBoxArea: Single): Single;`
Area of the six TBox3D sides, EmptyBoxArea if box is empty. ###### Parameters AllowZero Decides what to do when box is not empty but the result would be zero, which means that the box is infinitely thin in all axes. If `True`, then result is just 0, otherwise it's EmptyBoxSize.
| `procedure ExpandMe(const AExpand: Single); overload;`
This decreases Data[0, 0], Data[0, 1], Data[0, 2] by AExpand and increases Data[1, 0], Data[1, 1], Data[1, 2] by AExpand. So you get Box with all sizes increased by 2 * AExpand. Box must not be empty. Note that AExpand may be negative, but then you must be sure that it doesn't make Box empty.
| `procedure ExpandMe(const AExpand: TVector3Single); overload;`
This decreases Data[0] by AExpand, and increases Data[1] by AExpand. So you get Box with all sizes increased by 2 * AExpand. Box must not be empty. Note that AExpand may be negative, but then you must be sure that it doesn't make Box empty.
| `function Expand(const AExpand: Single): TBox3D; overload;`
| `function Expand(const AExpand: TVector3Single): TBox3D; overload;`
| `function PointInside(const Point: TVector3Single): boolean; overload;`
Check is the point inside the box. Always false if Box is empty (obviously, no point is inside an empty box).
| `function PointInside(const Point: TVector3Double): boolean; overload;`
| `function PointInside2D(const Point: TVector3Single; const IgnoreIndex: Integer): boolean;`
Is the 2D point inside the 2D projection of the box. 2D projection (of point and box) is obtained by rejecting the IgnoreIndex coordinate (must be 0, 1 or 2).
| `procedure Add(const box2: TBox3D); overload;`
Sum two TBox3D values. This calculates the smallest box that encloses both Box1 and Box2. You can also use + operator.
| `procedure Add(const Point: TVector3Single); overload;`
Make box larger, if necessary, to contain given Point.
| `function Sizes: TVector3Single;`
Three box sizes.
| `procedure GetAllPoints(allpoints: PVector3Single);`
Calculate eight corners of the box. Place them in AllPointsˆ[0..7].
| `function Transform(const Matrix: TMatrix4Single): TBox3D;`
Transform the Box by given matrix. Since this is still an axis-aligned box, rotating etc. of the box usually makes larger box. Note that this is very optimized for Matrix with no projection (where last row of the last matrix = [0, 0, 0, 1]). It still works for all matrices (eventually fallbacks to simple "transform 8 corners and get box enclosing them" method). ###### Exceptions raised ETransformedResultInvalid When the Matrix will transform some point to a direction (vector with 4th component equal zero). In this case we just cannot interpret the result as a 3D point, so we also cannot interpret the final result as a box.
| `function Translate(const Translation: TVector3Single): TBox3D;`
Move Box. Does nothing if Box is empty.
| `function AntiTranslate(const Translation: TVector3Single): TBox3D;`
Move Box, by -Translation. Does nothing if Box is empty.
| `function ToNiceStr: string;`
| `function ToRawStr: string;`
| `procedure Clamp(var point: TVector3Single); overload;`
| `procedure Clamp(var point: TVector3Double); overload;`
| `function TryRayClosestIntersection( out Intersection: TVector3Single; out IntersectionDistance: Single; const RayOrigin, RayDirection: TVector3Single): boolean; overload;`
TryBoxRayClosestIntersection calculates intersection between the ray (returns closest intersection to RayOrigin) and the box. The box is treated just like a set of 6 rectangles in 3D. This means that the intersection will always be placed on one of the box sides, even if RayOrigin starts inside the box. See TryBoxRayEntrance for the other version. Returns also IntersectionDistance, which is the distance to the Intersection relative to RayDirection (i.e. Intersection is always = RayOrigin + IntersectionDistance * RayDirection).
| `function TryRayClosestIntersection( out Intersection: TVector3Single; const RayOrigin, RayDirection: TVector3Single): boolean; overload;`
| `function TryRayClosestIntersection( out IntersectionDistance: Single; const RayOrigin, RayDirection: TVector3Single): boolean; overload;`
| `function TryRayEntrance( out Entrance: TVector3Single; out EntranceDistance: Single; const RayOrigin, RayDirection: TVector3Single): boolean; overload;`
Intersection between the ray (returns closest intersection to RayOrigin) and the box, treating the box as a filled volume. If RayOrigin is inside the box, TryBoxRayEntrance simply returns RayOrigin. If RayOrigin is outside of the box, the answer is the same as with TryBoxRayClosestIntersection.
| `function TryRayEntrance( out Entrance: TVector3Single; const RayOrigin, RayDirection: TVector3Single): boolean; overload;`
| `function SegmentCollision( const Segment1, Segment2: TVector3Single): boolean;`
| `function PlaneCollision(const Plane: TVector4Single): TPlaneCollision;`
Collision between axis-aligned box (TBox3D) and 3D plane. Returns detailed result as TPlaneCollision.
| `function PlaneCollisionInside(const Plane: TVector4Single): boolean;`
Check is axis-aligned box (TBox3D) fully inside/outside the plane. Inside/outside are defined as for TPlaneCollision: Outside is where plane direction (normal) points. Inside is where the inverted plane direction (normal) points. They work exactly like Box3DPlaneCollision, except they returns `True` when box is inside/outside (when Box3DPlaneCollision returned pcInside/pcOutside), and `False` otherwise. For example Box3DPlaneCollisionInside doesn't differentiate between case when box is empty, of partially intersects the plane, and is on the outside. But it works (very slightly) faster.
| `function PlaneCollisionOutside(const Plane: TVector4Single): boolean;`
| `function IsTriangleCollision( const Triangle: TTriangle3Single): boolean;`
| `procedure BoundingSphere( var SphereCenter: TVector3Single; var SphereRadiusSqr: Single);`
Smallest possible sphere completely enclosing given Box. When Box is empty we return SphereRadiusSqr = 0 and undefined SphereCenter.
| `function Collision(const Box2: TBox3D): boolean;`
| `function Radius: Single;`
Radius of the minimal sphere that contains this box. Sphere center is assumed to be in (0, 0, 0). 0 if box is empty.
| `function Radius2D(const IgnoreIndex: Integer): Single;`
Radius of the minimal circle that contains the 2D projection of this box. 2D box projection is obtained by rejecting the IgnoreIndex coordinate (must be 0, 1 or 2). Circle center is assumed to be in (0, 0). 0 if box is empty.
| `function SphereSimpleCollision( const SphereCenter: TVector3Single; const SphereRadius: Single): boolean;`
Check for collision between box and sphere, fast but not entirely correct. This considers a Box enlarged by SphereRadius in each direction. Then checks whether SphereCenter is inside such enlarged Box. So this check will incorrectly report collision while in fact there's no collision in the case when the sphere center is near the corner of the Box. So this check is not 100% correct. But often this is good enough — in games, if you know that the SphereRadius is going to be relatively small compared to the Box, this may be perfectly acceptable. And it's fast.
| `function SphereCollision( const SphereCenter: TVector3Single; const SphereRadius: Single): boolean;`
Check for box <-> sphere collision. This is a little slower than SphereSimpleCollision, although still damn fast, and it's a precise check.
| `function MaximumPlane(const Direction: TVector3Single): TVector4Single;`
Calculate a plane in 3D space with direction = given Direction, moved maximally in Direction and still intersecting the given Box. For example, if Direction = -Z = (0, 0, -1), then this will return the bottom plane of this box. For Direction = (1, 1, 1), this will return a plane intersecting the Data[1] (maximum) point, with slope = (1, 1, 1). The resulting plane always intersects at least one of the 8 corners of the box. ###### Exceptions raised EBox3DEmpty If the Box is empty.
| `function MinimumPlane(const Direction: TVector3Single): TVector4Single;`
Calculate a plane in 3D space with direction = given Direction, moved such that it touches the Box but takes minimum volume of this box. For example, if Direction = +Z = (0, 0, 1), then this will return the bottom plane of this box. For Direction = (1, 1, 1), this will return a plane intersecting the Data[0] (minimum) point, with slope = (1, 1, 1). The resulting plane always intersects at least one of the 8 corners of the box. ###### Exceptions raised EBox3DEmpty If the Box is empty.
| `procedure PointDistances(const P: TVector3Single; out MinDistance, MaxDistance: Single);`
Calculate the distances between a given 3D point and a box. MinDistance is the distance to the closest point of the box, MaxDistance is the distance to the farthest point of the box. Note that always MinDistance <= MaxDistance. Note that both distances are always >= 0. When the point is inside the box, it works correct too: minimum distance is zero in this case. TODO: calculation of MinDistance is not perfect now. We assume that the closest/farthest point of the box is one of the 8 box corners. Which may not be true in case of the closest point, because it may lie in the middle of some box face (imagine a sphere with increasing radius reaching from a point to a box). So our minimum may be a *little* too large. ###### Exceptions raised EBox3DEmpty When used with an empty box.
| `procedure DirectionDistances( const Point, Dir: TVector3Single; out MinDistance, MaxDistance: Single);`
Calculate the distances along a direction to a box. The idea is that you have a 3D plane orthogonal to direction Dir and passing through Point. You can move this plane, but you have to keep it's direction constant. MinDistance is the minimal distance along the Dir that you can move this plane, such that it touches the box. MaxDistance is the maximum such distance. Note that always MinDistance <= MaxDistance. Note that one distance (MinDistance) or both distances may be negative. As a practical example: imagine a DirectionalLight (light rays are parallel) that has a location. Now MinDistance and MaxDistance give ranges of depth where the Box is, as seen from the light source. ###### Exceptions raised EBox3DEmpty When used with an empty box.
| `function PointDistance(const Point: TVector3Single): Single;`
Shortest distance between the box and a point. Always zero when the point is inside the box. ###### Exceptions raised EBox3DEmpty When used with an empty box.
| `function PointMaxDistance(const Point: TVector3Single; const EmptyBoxDistance: Single): Single;`
Maximum distance between the box and a point. Returns EmptyBoxDistance when box is empty.
| `function Equal(const Box2: TBox3D): boolean;`
| `function Equal(const Box2: TBox3D; const EqualityEpsilon: Single): boolean;`
| `function Diagonal: Single;`
`Diagonal` of the box, zero if empty.
Generated by PasDoc 0.13.0 on 2015-06-15 04:43:08