Files

236 lines
4.5 KiB
C++
Raw Permalink Normal View History

2010-06-07 00:09:54 +02:00
/**
2014-08-22 16:58:23 +02:00
\file G3D/Box.h
2010-06-07 00:09:54 +02:00
Box class
2014-08-22 16:58:23 +02:00
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
2010-06-07 00:09:54 +02:00
2014-08-22 16:58:23 +02:00
\cite Portions based on Dave Eberly's Magic Software Library at <A HREF="http://www.magic-software.com">http://www.magic-software.com</A>
\created 2001-06-02
\edited 2013-04-13
2010-06-07 00:09:54 +02:00
2014-08-22 16:58:23 +02:00
Copyright 2000-2013, Morgan McGuire.
2010-06-07 00:09:54 +02:00
All rights reserved.
*/
2014-08-22 16:58:23 +02:00
#ifndef G3D_Box_h
#define G3D_Box_h
2010-06-07 00:09:54 +02:00
#include "G3D/platform.h"
#include "G3D/Vector3.h"
#include "G3D/Array.h"
#include "G3D/Plane.h"
namespace G3D {
class CoordinateFrame;
2014-08-22 16:58:23 +02:00
class Any;
2010-06-07 00:09:54 +02:00
/**
2014-08-22 16:58:23 +02:00
\brief An arbitrary (oriented) 3D box, useful as a bounding box.
2010-06-07 00:09:54 +02:00
2014-08-22 16:58:23 +02:00
To construct a box from a coordinate frame, center and extent, use the idiom:
2010-06-07 00:09:54 +02:00
<CODE>Box box = cframe.toObjectSpace(Box(center - extent/2, center + extent/2));</CODE>
*/
class Box {
private:
static int32 dummy;
friend class CoordinateFrame;
/**
2014-08-22 16:58:23 +02:00
Axes with length equal to the 4 edges that run along each of them
2010-06-07 00:09:54 +02:00
*/
2014-08-22 16:58:23 +02:00
Vector3 _edgeVector[3];
2010-06-07 00:09:54 +02:00
2014-08-22 16:58:23 +02:00
Point3 _center;
2010-06-07 00:09:54 +02:00
float _area;
2014-08-22 16:58:23 +02:00
2010-06-07 00:09:54 +02:00
float _volume;
void init(
const Vector3& min,
const Vector3& max);
public:
Box();
2014-08-22 16:58:23 +02:00
explicit Box(const Any& a);
2010-06-07 00:09:54 +02:00
/**
Constructs a box from two opposite corners.
*/
2014-08-22 16:58:23 +02:00
Box(const Vector3& min,
2010-06-07 00:09:54 +02:00
const Vector3& max);
2014-08-22 16:58:23 +02:00
Box(const Vector3& osMin,
const Vector3& osMax,
const CoordinateFrame& frame);
2010-06-07 00:09:54 +02:00
2014-08-22 16:58:23 +02:00
Box(class BinaryInput& b);
2010-06-07 00:09:54 +02:00
Box(const class AABox& b);
2014-08-22 16:58:23 +02:00
explicit Box(const Point3& p);
2010-06-07 00:09:54 +02:00
2014-08-22 16:58:23 +02:00
static Box inf();
Any toAny() const;
void serialize(class BinaryOutput& b) const;
void deserialize(class BinaryInput& b);
2010-06-07 00:09:54 +02:00
/**
Returns the object to world transformation for
2014-08-22 16:58:23 +02:00
this box, where the origin is the center of the box. localFrame().worldToObject(...) takes
2010-06-07 00:09:54 +02:00
objects into the space where the box axes are
(1,0,0), (0,1,0), (0,0,1). Note that there
is no scaling in this transformation.
*/
CoordinateFrame localFrame() const;
2014-08-22 16:58:23 +02:00
/** \sa localFrame */
2010-06-07 00:09:54 +02:00
void getLocalFrame(CoordinateFrame& frame) const;
2014-08-22 16:58:23 +02:00
Box operator*(float f) const;
2010-06-07 00:09:54 +02:00
/**
Returns the centroid of the box.
*/
inline Vector3 center() const {
return _center;
}
2014-08-22 16:58:23 +02:00
/**
\htmlonly
<PRE>
2--------3
/ : /|
/ : / |
6--------7 |
| : | |
| 0....|..1
| / | /
|/ |/
4--------5
y
^
|
|-->x
z/
2010-06-07 00:09:54 +02:00
2014-08-22 16:58:23 +02:00
</PRE>
\endhtmlonly
*/
Vector3 corner(int i) const;
2010-06-07 00:09:54 +02:00
/**
Unit length.
*/
inline Vector3 axis(int a) const {
debugAssert(a < 3);
2014-08-22 16:58:23 +02:00
return _edgeVector[a].direction();
2010-06-07 00:09:54 +02:00
}
/**
Distance from corner(0) to the next corner
along the box's local axis a.
*/
inline float extent(int a) const {
debugAssert(a < 3);
2014-08-22 16:58:23 +02:00
return _edgeVector[a].length();
2010-06-07 00:09:54 +02:00
}
inline Vector3 extent() const {
2014-08-22 16:58:23 +02:00
return Vector3(_edgeVector[0].length(), _edgeVector[1].length(), _edgeVector[2].length());
2010-06-07 00:09:54 +02:00
}
/**
Returns the four corners of a face (0 <= f < 6).
2014-08-22 16:58:23 +02:00
The corners are returned to form a clockwise quad facing outwards.
+--------+
/ : /|
/ : / |
+--------+ |
| : | |
| +....|..+
| / | /
|/ |/
+--------+
y
^
|
|-->x
z/
Faces are in the following order:
0: -Z
1: X
2: Z
3: Y
4: -X
5: -Y
*/
2010-06-07 00:09:54 +02:00
void getFaceCorners(
int f,
Vector3& v0,
Vector3& v1,
Vector3& v2,
Vector3& v3) const;
2014-08-22 16:58:23 +02:00
/**
2010-06-07 00:09:54 +02:00
See AABox::culledBy
2014-08-22 16:58:23 +02:00
*/
bool culledBy
(
2014-08-22 16:58:23 +02:00
const Array<Plane>& plane,
int32& cullingPlaneIndex,
const uint32 testMask,
uint32& childMask) const;
2010-06-07 00:09:54 +02:00
/**
Conservative culling test that does not produce a mask for children.
*/
bool culledBy
(
2014-08-22 16:58:23 +02:00
const Array<Plane>& plane,
int32& cullingPlaneIndex = dummy,
const uint32 testMask = -1) const;
2010-06-07 00:09:54 +02:00
bool contains(
const Vector3& point) const;
float area() const;
float volume() const;
void getRandomSurfacePoint(Vector3& P, Vector3& N = Vector3::ignore()) const;
2010-06-07 00:09:54 +02:00
/**
Uniformly distributed on the interior (includes surface)
*/
Vector3 randomInteriorPoint() const;
void getBounds(class AABox&) const;
bool isFinite() const {
return G3D::isFinite(_volume);
}
};
}
#endif