[svn] * Proper SVN structure
--HG-- branch : trunk
This commit is contained in:
@@ -0,0 +1,255 @@
|
||||
/**
|
||||
@file AABox.h
|
||||
|
||||
Axis-aligned box class
|
||||
|
||||
@maintainer Morgan McGuire, [email protected]
|
||||
|
||||
@created 2004-01-10
|
||||
@edited 2006-02-10
|
||||
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_AABOX_H
|
||||
#define G3D_AABOX_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/debug.h"
|
||||
#include "G3D/Array.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
An axis-aligned box.
|
||||
*/
|
||||
class AABox {
|
||||
private:
|
||||
|
||||
/** Optional argument placeholder */
|
||||
static int dummy;
|
||||
|
||||
Vector3 lo;
|
||||
Vector3 hi;
|
||||
|
||||
public:
|
||||
|
||||
/** Does not initialize the fields */
|
||||
inline AABox() {}
|
||||
|
||||
/**
|
||||
Constructs a zero-area AABox at v.
|
||||
*/
|
||||
inline AABox(const Vector3& v) {
|
||||
lo = hi = v;
|
||||
}
|
||||
|
||||
/** Assumes that low is less than or equal to high along each dimension.
|
||||
To have this automatically enforced, use
|
||||
<code>AABox(low.min(high), low.max(high));</code>
|
||||
*/
|
||||
inline AABox(const Vector3& low, const Vector3& high) {
|
||||
set(low, high);
|
||||
}
|
||||
|
||||
/** Assumes that low is less than or equal to high along each dimension.
|
||||
*/
|
||||
inline void set(const Vector3& low, const Vector3& high) {
|
||||
debugAssert(
|
||||
(low.x <= high.x) &&
|
||||
(low.y <= high.y) &&
|
||||
(low.z <= high.z));
|
||||
lo = low;
|
||||
hi = high;
|
||||
}
|
||||
|
||||
|
||||
inline const Vector3& low() const {
|
||||
return lo;
|
||||
}
|
||||
|
||||
inline const Vector3& high() const {
|
||||
return hi;
|
||||
}
|
||||
|
||||
/**
|
||||
The largest possible finite box.
|
||||
*/
|
||||
static inline const AABox& maxFinite() {
|
||||
static const AABox b = AABox(Vector3::minFinite(), Vector3::maxFinite());
|
||||
return b;
|
||||
}
|
||||
|
||||
static inline const AABox& inf() {
|
||||
static const AABox b = AABox(-Vector3::inf(), Vector3::inf());
|
||||
return b;
|
||||
}
|
||||
|
||||
static inline const AABox& zero() {
|
||||
static const AABox b = AABox(Vector3::zero(), Vector3::zero());
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the centroid of the box.
|
||||
*/
|
||||
inline Vector3 center() const {
|
||||
return (lo + hi) * 0.5;
|
||||
}
|
||||
|
||||
/**
|
||||
Distance from corner(0) to the next corner along axis a.
|
||||
*/
|
||||
inline double extent(int a) const {
|
||||
debugAssert(a < 3);
|
||||
return hi[a] - lo[a];
|
||||
}
|
||||
|
||||
inline Vector3 extent() const {
|
||||
return hi - lo;
|
||||
}
|
||||
|
||||
/**
|
||||
@deprecated Use culledBy(Array<Plane>&)
|
||||
*/
|
||||
bool culledBy(
|
||||
const class Plane* plane,
|
||||
int numPlanes,
|
||||
int32& cullingPlaneIndex,
|
||||
const uint32 testMask,
|
||||
uint32& childMask) const;
|
||||
|
||||
/**
|
||||
@deprecated Use culledBy(Array<Plane>&)
|
||||
*/
|
||||
bool culledBy(
|
||||
const class Plane* plane,
|
||||
int numPlanes,
|
||||
int32& cullingPlaneIndex = dummy,
|
||||
const uint32 testMask = 0xFFFFFF) const;
|
||||
|
||||
/**
|
||||
Splits the box into two AABoxes along the specified axis. low contains
|
||||
the part that was closer to negative infinity along axis, high contains
|
||||
the other part. Either may have zero volume.
|
||||
*/
|
||||
void split(const Vector3::Axis& axis, float location, AABox& low, AABox& high) const;
|
||||
|
||||
/**
|
||||
Conservative culling test for up to 32 planes.
|
||||
Returns true if there exists a <CODE>plane[p]</CODE> for
|
||||
which the entire object is in the negative half space
|
||||
(opposite the plane normal).
|
||||
|
||||
<CODE>testMask</CODE> and <CODE>childMask</CODE>
|
||||
are used for optimizing bounding volume hierarchies.
|
||||
The version of this method that produces childMask
|
||||
is slower than the version without; it should only
|
||||
be used for parent nodes.
|
||||
|
||||
@param cullingPlaneIndex The index of the first plane for which
|
||||
the entire object is in the negative half-space. The function
|
||||
exits early when one plane is found. -1 when the function
|
||||
returns false (i.e. when no plane culls the whole object).
|
||||
|
||||
@param testMask If bit <I>p</I> is 0, the
|
||||
bounding volume automatically passes the culling test for
|
||||
<CODE>plane[p]</CODE> (i.e. it is known that the volume
|
||||
is entirely within the positive half space). The function
|
||||
must return false if testMask is 0 and test all planes
|
||||
when testMask is -1 (0xFFFFFFFF).
|
||||
|
||||
@param childMask Test mask for the children of this volume.
|
||||
|
||||
*/
|
||||
bool culledBy(
|
||||
const Array<Plane>& plane,
|
||||
int32& cullingPlaneIndex,
|
||||
const uint32 testMask,
|
||||
uint32& childMask) const;
|
||||
|
||||
/**
|
||||
Conservative culling test that does not produce a mask for children.
|
||||
*/
|
||||
bool culledBy(
|
||||
const Array<Plane>& plane,
|
||||
int32& cullingPlaneIndex = dummy,
|
||||
const uint32 testMask = -1) const;
|
||||
|
||||
inline bool contains(
|
||||
const Vector3& point) const {
|
||||
return
|
||||
(point.x >= lo.x) &&
|
||||
(point.y >= lo.y) &&
|
||||
(point.z >= lo.z) &&
|
||||
(point.x <= hi.x) &&
|
||||
(point.y <= hi.y) &&
|
||||
(point.z <= hi.z);
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
inline float surfaceArea() const {
|
||||
Vector3 diag = hi - lo;
|
||||
return 2.0f * (diag.x * diag.y + diag.y * diag.z + diag.x * diag.z);
|
||||
}
|
||||
|
||||
inline float area() const {
|
||||
return surfaceArea();
|
||||
}
|
||||
|
||||
inline float volume() const {
|
||||
Vector3 diag = hi - lo;
|
||||
return diag.x * diag.y * diag.z;
|
||||
}
|
||||
|
||||
Vector3 randomInteriorPoint() const;
|
||||
|
||||
Vector3 randomSurfacePoint() const;
|
||||
|
||||
/** @deprecated use Box constructor */
|
||||
class Box toBox() const;
|
||||
|
||||
/** Returns true if there is any overlap */
|
||||
bool intersects(const AABox& other) const;
|
||||
|
||||
/** Returns true if there is any overlap.
|
||||
@cite Jim Arvo's algorithm from Graphics Gems II*/
|
||||
bool intersects(const class Sphere& other) const;
|
||||
|
||||
/** Return the intersection of the two boxes */
|
||||
AABox intersect(const AABox& other) const {
|
||||
Vector3 H = hi.min(other.hi);
|
||||
Vector3 L = lo.max(other.lo).min(H);
|
||||
return AABox(L, H);
|
||||
}
|
||||
|
||||
inline unsigned int hashCode() const {
|
||||
return lo.hashCode() + hi.hashCode();
|
||||
}
|
||||
|
||||
inline bool operator==(const AABox& b) const {
|
||||
return (lo == b.lo) && (hi == b.hi);
|
||||
}
|
||||
|
||||
inline bool operator!=(const AABox& b) const {
|
||||
return !((lo == b.lo) && (hi == b.hi));
|
||||
}
|
||||
|
||||
void getBounds(AABox& out) const {
|
||||
out = *this;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Hashing function for use with Table.
|
||||
*/
|
||||
inline unsigned int hashCode(const G3D::AABox& b) {
|
||||
return b.hashCode();
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,228 @@
|
||||
/**
|
||||
@file Box.h
|
||||
|
||||
Box class
|
||||
|
||||
@maintainer Morgan McGuire, [email protected]
|
||||
|
||||
@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 2006-01-05
|
||||
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_BOX_H
|
||||
#define G3D_BOX_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/Plane.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class CoordinateFrame;
|
||||
|
||||
/**
|
||||
An arbitrary 3D box, useful as a bounding box.
|
||||
|
||||
|
||||
To construct a box from a coordinate frame, center and extent, use the idiom:
|
||||
|
||||
<CODE>Box box = cframe.toObjectSpace(Box(center - extent/2, center + extent/2));</CODE>
|
||||
*/
|
||||
class Box {
|
||||
private:
|
||||
|
||||
static int32 dummy;
|
||||
|
||||
friend class CoordinateFrame;
|
||||
|
||||
/**
|
||||
<PRE>
|
||||
3 2 7 6
|
||||
|
||||
0 1 4 5
|
||||
|
||||
front back (seen through front)
|
||||
</PRE>
|
||||
*/
|
||||
Vector3 _corner[8];
|
||||
|
||||
/**
|
||||
Unit axes.
|
||||
*/
|
||||
Vector3 _axis[3];
|
||||
|
||||
Vector3 _center;
|
||||
|
||||
/**
|
||||
Extent along each axis.
|
||||
*/
|
||||
Vector3 _extent;
|
||||
|
||||
float _area;
|
||||
float _volume;
|
||||
|
||||
void init(
|
||||
const Vector3& min,
|
||||
const Vector3& max);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
Does not initialize the fields.
|
||||
*/
|
||||
Box();
|
||||
|
||||
/**
|
||||
Constructs a box from two opposite corners.
|
||||
*/
|
||||
Box(
|
||||
const Vector3& min,
|
||||
const Vector3& max);
|
||||
|
||||
Box(const class AABox& b);
|
||||
|
||||
|
||||
/**
|
||||
Returns the object to world transformation for
|
||||
this box. localFrame().worldToObject(...) takes
|
||||
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;
|
||||
|
||||
void getLocalFrame(CoordinateFrame& frame) const;
|
||||
|
||||
/**
|
||||
Returns the centroid of the box.
|
||||
*/
|
||||
inline Vector3 center() const {
|
||||
return _center;
|
||||
}
|
||||
|
||||
inline Vector3 getCenter() const {
|
||||
return center();
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a corner (0 <= i < 8)
|
||||
@deprecated
|
||||
*/
|
||||
inline Vector3 getCorner(int i) const {
|
||||
debugAssert(i < 8);
|
||||
return _corner[i];
|
||||
}
|
||||
|
||||
inline Vector3 corner(int i) const {
|
||||
debugAssert(i < 8);
|
||||
return _corner[i];
|
||||
}
|
||||
|
||||
/**
|
||||
Unit length.
|
||||
*/
|
||||
inline Vector3 axis(int a) const {
|
||||
debugAssert(a < 3);
|
||||
return _axis[a];
|
||||
}
|
||||
|
||||
/**
|
||||
Distance from corner(0) to the next corner
|
||||
along the box's local axis a.
|
||||
*/
|
||||
inline float extent(int a) const {
|
||||
debugAssert(a < 3);
|
||||
return (float)_extent[a];
|
||||
}
|
||||
|
||||
inline Vector3 extent() const {
|
||||
return _extent;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the four corners of a face (0 <= f < 6).
|
||||
The corners are returned to form a counter clockwise quad facing outwards.
|
||||
*/
|
||||
void getFaceCorners(
|
||||
int f,
|
||||
Vector3& v0,
|
||||
Vector3& v1,
|
||||
Vector3& v2,
|
||||
Vector3& v3) const;
|
||||
|
||||
/**
|
||||
@deprecated Use culledBy(Array<Plane>&)
|
||||
*/
|
||||
bool culledBy(
|
||||
const class Plane* plane,
|
||||
int numPlanes,
|
||||
int32& cullingPlaneIndex,
|
||||
const uint32 testMask,
|
||||
uint32& childMask) const;
|
||||
|
||||
/**
|
||||
@deprecated Use culledBy(Array<Plane>&)
|
||||
*/
|
||||
bool culledBy(
|
||||
const class Plane* plane,
|
||||
int numPlanes,
|
||||
int32& cullingPlaneIndex = dummy,
|
||||
const uint32 testMask = -1) const;
|
||||
|
||||
/**
|
||||
See AABox::culledBy
|
||||
*/
|
||||
bool culledBy(
|
||||
const Array<Plane>& plane,
|
||||
int32& cullingPlaneIndex,
|
||||
const uint32 testMask,
|
||||
uint32& childMask) const;
|
||||
|
||||
/**
|
||||
Conservative culling test that does not produce a mask for children.
|
||||
*/
|
||||
bool culledBy(
|
||||
const Array<Plane>& plane,
|
||||
int32& cullingPlaneIndex = dummy,
|
||||
const uint32 testMask = -1) const;
|
||||
|
||||
bool contains(
|
||||
const Vector3& point) const;
|
||||
|
||||
/** @deprecated */
|
||||
float surfaceArea() const;
|
||||
|
||||
inline float area() const {
|
||||
return surfaceArea();
|
||||
}
|
||||
|
||||
float volume() const;
|
||||
|
||||
void getRandomSurfacePoint(Vector3& P, Vector3& N = Vector3::dummy) const;
|
||||
|
||||
/**
|
||||
@deprecated
|
||||
Uniformly distributed on the surface.
|
||||
*/
|
||||
inline Vector3 randomSurfacePoint() const {
|
||||
Vector3 V;
|
||||
getRandomSurfacePoint(V);
|
||||
return V;
|
||||
}
|
||||
|
||||
/**
|
||||
Uniformly distributed on the interior (includes surface)
|
||||
*/
|
||||
Vector3 randomInteriorPoint() const;
|
||||
|
||||
void getBounds(class AABox&) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,318 @@
|
||||
/**
|
||||
@file CoordinateFrame.h
|
||||
|
||||
@maintainer Morgan McGuire, [email protected]
|
||||
|
||||
@created 2001-03-04
|
||||
@edited 2006-04-07
|
||||
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_COORDINATEFRAME_H
|
||||
#define G3D_COORDINATEFRAME_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Vector4.h"
|
||||
#include "G3D/Matrix3.h"
|
||||
#include "G3D/Array.h"
|
||||
#include <math.h>
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
#include <cstdarg>
|
||||
#include <assert.h>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
A rigid body RT (rotation-translation) transformation.
|
||||
|
||||
CoordinateFrame abstracts a 4x4 matrix that maps object space to world space:
|
||||
|
||||
v_world = C * v_object
|
||||
|
||||
CoordinateFrame::rotation is the upper 3x3 submatrix, CoordinateFrame::translation
|
||||
is the right 3x1 column. The 4th row is always [0 0 0 1], so it isn't stored.
|
||||
So you don't have to remember which way the multiplication and transformation work,
|
||||
it provides explicit toWorldSpace and toObjectSpace methods. Also, points, vectors
|
||||
(directions), and surface normals transform differently, so they have separate methods.
|
||||
|
||||
Some helper functions transform whole primitives like boxes in and out of object space.
|
||||
|
||||
Convert to Matrix4 using CoordinateFrame::toMatrix4. You <I>can</I> construct a CoordinateFrame
|
||||
from a Matrix4 using Matrix4::approxCoordinateFrame, however, because a Matrix4 is more
|
||||
general than a CoordinateFrame, some information may be lost.
|
||||
|
||||
See also: G3D::Matrix4, G3D::Quat
|
||||
*/
|
||||
class CoordinateFrame {
|
||||
public:
|
||||
|
||||
/**
|
||||
Takes object space points to world space.
|
||||
*/
|
||||
Matrix3 rotation;
|
||||
|
||||
/**
|
||||
Takes object space points to world space.
|
||||
*/
|
||||
Vector3 translation;
|
||||
|
||||
/**
|
||||
The direction an object "looks" relative to its own axes.
|
||||
@deprecated This is always -1 and will be fixed at that value in future releases.
|
||||
*/
|
||||
static const float zLookDirection;
|
||||
|
||||
inline bool operator==(const CoordinateFrame& other) const {
|
||||
return (translation == other.translation) && (rotation == other.rotation);
|
||||
}
|
||||
|
||||
inline bool operator!=(const CoordinateFrame& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
bool fuzzyEq(const CoordinateFrame& other) const;
|
||||
|
||||
bool fuzzyIsIdentity() const;
|
||||
|
||||
bool isIdentity() const;
|
||||
|
||||
/**
|
||||
Initializes to the identity coordinate frame.
|
||||
*/
|
||||
inline CoordinateFrame() :
|
||||
rotation(Matrix3::identity()), translation(Vector3::zero()) {
|
||||
}
|
||||
|
||||
CoordinateFrame(const Vector3& _translation) :
|
||||
rotation(Matrix3::identity()), translation(_translation) {
|
||||
}
|
||||
|
||||
CoordinateFrame(const Matrix3 &rotation, const Vector3 &translation) :
|
||||
rotation(rotation), translation(translation) {
|
||||
}
|
||||
|
||||
CoordinateFrame(const Matrix3 &rotation) :
|
||||
rotation(rotation), translation(Vector3::zero()) {
|
||||
}
|
||||
|
||||
CoordinateFrame(const CoordinateFrame &other) :
|
||||
rotation(other.rotation), translation(other.translation) {}
|
||||
|
||||
/**
|
||||
Computes the inverse of this coordinate frame.
|
||||
*/
|
||||
inline CoordinateFrame inverse() const {
|
||||
CoordinateFrame out;
|
||||
out.rotation = rotation.transpose();
|
||||
out.translation = -out.rotation * translation;
|
||||
return out;
|
||||
}
|
||||
|
||||
inline ~CoordinateFrame() {}
|
||||
|
||||
/** See also Matrix4::approxCoordinateFrame */
|
||||
class Matrix4 toMatrix4() const;
|
||||
|
||||
/**
|
||||
Produces an XML serialization of this coordinate frame.
|
||||
*/
|
||||
std::string toXML() const;
|
||||
|
||||
/**
|
||||
Returns the heading of the lookVector as an angle in radians relative to
|
||||
the world -z axis. That is, a counter-clockwise heading where north (-z)
|
||||
is 0 and west (-x) is PI/2.
|
||||
|
||||
Note that the heading ignores the Y axis, so an inverted
|
||||
object has an inverted heading.
|
||||
*/
|
||||
inline float getHeading() const {
|
||||
Vector3 look = rotation.getColumn(2);
|
||||
float angle = -(float) atan2(-look.x, look.z);
|
||||
return angle;
|
||||
}
|
||||
|
||||
/**
|
||||
Takes the coordinate frame into object space.
|
||||
this->inverse() * c
|
||||
*/
|
||||
inline CoordinateFrame toObjectSpace(const CoordinateFrame& c) const {
|
||||
return this->inverse() * c;
|
||||
}
|
||||
|
||||
inline Vector4 toObjectSpace(const Vector4& v) const {
|
||||
return this->inverse().toWorldSpace(v);
|
||||
}
|
||||
|
||||
inline Vector4 toWorldSpace(const Vector4& v) const {
|
||||
return Vector4(rotation * Vector3(v.x, v.y, v.z) + translation * v.w, v.w);
|
||||
}
|
||||
|
||||
/**
|
||||
Transforms the point into world space.
|
||||
*/
|
||||
inline Vector3 pointToWorldSpace(const Vector3& v) const {
|
||||
return Vector3(
|
||||
rotation[0][0] * v[0] + rotation[0][1] * v[1] + rotation[0][2] * v[2] + translation[0],
|
||||
rotation[1][0] * v[0] + rotation[1][1] * v[1] + rotation[1][2] * v[2] + translation[1],
|
||||
rotation[2][0] * v[0] + rotation[2][1] * v[1] + rotation[2][2] * v[2] + translation[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
Transforms the point into object space.
|
||||
*/
|
||||
inline Vector3 pointToObjectSpace(const Vector3& v) const {
|
||||
float p[3];
|
||||
p[0] = v[0] - translation[0];
|
||||
p[1] = v[1] - translation[1];
|
||||
p[2] = v[2] - translation[2];
|
||||
return Vector3(
|
||||
rotation[0][0] * p[0] + rotation[1][0] * p[1] + rotation[2][0] * p[2],
|
||||
rotation[0][1] * p[0] + rotation[1][1] * p[1] + rotation[2][1] * p[2],
|
||||
rotation[0][2] * p[0] + rotation[1][2] * p[1] + rotation[2][2] * p[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
Transforms the vector into world space (no translation).
|
||||
*/
|
||||
inline Vector3 vectorToWorldSpace(const Vector3& v) const {
|
||||
return rotation * v;
|
||||
}
|
||||
|
||||
inline Vector3 normalToWorldSpace(const Vector3& v) const {
|
||||
return rotation * v;
|
||||
}
|
||||
|
||||
class Ray toObjectSpace(const Ray& r) const;
|
||||
|
||||
Ray toWorldSpace(const Ray& r) const;
|
||||
|
||||
/**
|
||||
Transforms the vector into object space (no translation).
|
||||
*/
|
||||
inline Vector3 vectorToObjectSpace(const Vector3 &v) const {
|
||||
// Multiply on the left (same as rotation.transpose() * v)
|
||||
return v * rotation;
|
||||
}
|
||||
|
||||
inline Vector3 normalToObjectSpace(const Vector3 &v) const {
|
||||
// Multiply on the left (same as rotation.transpose() * v)
|
||||
return v * rotation;
|
||||
}
|
||||
|
||||
void pointToWorldSpace(const Array<Vector3>& v, Array<Vector3>& vout) const;
|
||||
|
||||
void normalToWorldSpace(const Array<Vector3>& v, Array<Vector3>& vout) const;
|
||||
|
||||
void vectorToWorldSpace(const Array<Vector3>& v, Array<Vector3>& vout) const;
|
||||
|
||||
void pointToObjectSpace(const Array<Vector3>& v, Array<Vector3>& vout) const;
|
||||
|
||||
void normalToObjectSpace(const Array<Vector3>& v, Array<Vector3>& vout) const;
|
||||
|
||||
void vectorToObjectSpace(const Array<Vector3>& v, Array<Vector3>& vout) const;
|
||||
|
||||
class Box toWorldSpace(const class AABox& b) const;
|
||||
|
||||
class Box toWorldSpace(const class Box& b) const;
|
||||
|
||||
class Cylinder toWorldSpace(const class Cylinder& b) const;
|
||||
|
||||
class Capsule toWorldSpace(const class Capsule& b) const;
|
||||
|
||||
class Plane toWorldSpace(const class Plane& p) const;
|
||||
|
||||
class Sphere toWorldSpace(const class Sphere& b) const;
|
||||
|
||||
class Triangle toWorldSpace(const class Triangle& t) const;
|
||||
|
||||
class Box toObjectSpace(const AABox& b) const;
|
||||
|
||||
class Box toObjectSpace(const Box& b) const;
|
||||
|
||||
class Plane toObjectSpace(const Plane& p) const;
|
||||
|
||||
class Sphere toObjectSpace(const Sphere& b) const;
|
||||
|
||||
Triangle toObjectSpace(const Triangle& t) const;
|
||||
|
||||
/** Compose: create the transformation that is <I>other</I> followed by <I>this</I>.*/
|
||||
CoordinateFrame operator*(const CoordinateFrame &other) const {
|
||||
return CoordinateFrame(rotation * other.rotation,
|
||||
pointToWorldSpace(other.translation));
|
||||
}
|
||||
|
||||
CoordinateFrame operator+(const Vector3& v) const {
|
||||
return CoordinateFrame(rotation, translation + v);
|
||||
}
|
||||
|
||||
CoordinateFrame operator-(const Vector3& v) const {
|
||||
return CoordinateFrame(rotation, translation - v);
|
||||
}
|
||||
|
||||
void lookAt(const Vector3& target);
|
||||
|
||||
void lookAt(
|
||||
const Vector3& target,
|
||||
Vector3 up);
|
||||
|
||||
/** @deprecated See lookVector */
|
||||
inline Vector3 getLookVector() const {
|
||||
return rotation.getColumn(2) * zLookDirection;
|
||||
}
|
||||
|
||||
/** The direction this camera is looking (its negative z axis)*/
|
||||
inline Vector3 lookVector() const {
|
||||
return rotation.getColumn(2) * zLookDirection;
|
||||
}
|
||||
|
||||
/** Returns the ray starting at the camera origin travelling in direction CoordinateFrame::lookVector. */
|
||||
class Ray lookRay() const;
|
||||
|
||||
/** Up direction for this camera (its y axis). */
|
||||
inline Vector3 upVector() const {
|
||||
return rotation.getColumn(1);
|
||||
}
|
||||
|
||||
/**
|
||||
If a viewer looks along the look vector, this is the viewer's "left"
|
||||
@deprecated leftVector
|
||||
*/
|
||||
inline Vector3 getLeftVector() const {
|
||||
return -rotation.getColumn(0);
|
||||
}
|
||||
|
||||
/** @deprecated See rightVector */
|
||||
inline Vector3 getRightVector() const {
|
||||
return rotation.getColumn(0);
|
||||
}
|
||||
|
||||
/**
|
||||
If a viewer looks along the look vector, this is the viewer's "left".
|
||||
Useful for strafing motions and building alternative coordinate frames.
|
||||
*/
|
||||
inline Vector3 leftVector() const {
|
||||
return -rotation.getColumn(0);
|
||||
}
|
||||
|
||||
inline Vector3 rightVector() const {
|
||||
return rotation.getColumn(0);
|
||||
}
|
||||
|
||||
/**
|
||||
Linearly interpolates between two coordinate frames, using
|
||||
Quat::slerp for the rotations.
|
||||
*/
|
||||
CoordinateFrame lerp(
|
||||
const CoordinateFrame& other,
|
||||
float alpha) const;
|
||||
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
@file Crypto.h
|
||||
|
||||
@maintainer Morgan McGuire, [email protected]
|
||||
|
||||
|
||||
@created 2006-03-29
|
||||
@edited 2006-04-06
|
||||
*/
|
||||
|
||||
#ifndef G3D_CRYPTO_H
|
||||
#define G3D_CRYPTO_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include <string>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/** Cryptography and hashing helper functions */
|
||||
class Crypto {
|
||||
public:
|
||||
|
||||
/**
|
||||
Computes the CRC32 value of a byte array. CRC32 is designed to be a hash
|
||||
function that produces different values for similar strings.
|
||||
|
||||
This implementation is compatible with PKZIP and GZIP.
|
||||
|
||||
Based on http://www.gamedev.net/reference/programming/features/crc32/
|
||||
*/
|
||||
static uint32 crc32(const void* bytes, size_t numBytes);
|
||||
|
||||
/**
|
||||
Returns the nth prime less than 2000 in constant time. The first prime has index
|
||||
0 and is the number 2.
|
||||
*/
|
||||
static int smallPrime(int n);
|
||||
|
||||
/** Returns 1 + the largest value that can be passed to smallPrime. */
|
||||
static int numSmallPrimes();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,251 @@
|
||||
/**
|
||||
@file GCamera.h
|
||||
|
||||
@maintainer Morgan McGuire, [email protected]
|
||||
|
||||
@created 2001-06-02
|
||||
@edited 2006-02-11
|
||||
*/
|
||||
|
||||
#ifndef G3D_GCAMERA_H
|
||||
#define G3D_GCAMERA_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/CoordinateFrame.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Plane.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
There is a viewport of width x height size in world space that corresponds to
|
||||
a screenWidth x screenHeight pixel grid on a
|
||||
renderDevice->getWidth() x renderDevice->getHeight()
|
||||
window.
|
||||
|
||||
All viewport arguments are the pixel bounds of the viewport-- e.g.,
|
||||
RenderDevice::getViewport().
|
||||
*/
|
||||
class GCamera {
|
||||
private:
|
||||
|
||||
/**
|
||||
Vertical field of view (in radians)
|
||||
*/
|
||||
float fieldOfView;
|
||||
|
||||
/**
|
||||
The image plane depth corresponding to a vertical field of
|
||||
view, where the film size is 1x1.
|
||||
*/
|
||||
float imagePlaneDepth;
|
||||
|
||||
/**
|
||||
Clipping plane, *not* imaging plane. Positive numbers.
|
||||
*/
|
||||
float nearPlane;
|
||||
|
||||
/**
|
||||
Positive
|
||||
*/
|
||||
float farPlane;
|
||||
|
||||
CoordinateFrame cframe;
|
||||
|
||||
public:
|
||||
|
||||
class Frustum {
|
||||
public:
|
||||
class Face {
|
||||
public:
|
||||
/** Counter clockwise indices into vertexPos */
|
||||
int vertexIndex[4];
|
||||
|
||||
/** The plane containing the face. */
|
||||
Plane plane;
|
||||
};
|
||||
|
||||
/** The vertices, in homogeneous space. If w == 0,
|
||||
a vertex is at infinity. */
|
||||
Array<Vector4> vertexPos;
|
||||
|
||||
/** The faces in the frustum. When the
|
||||
far plane is at infinity, there are 5 faces,
|
||||
otherwise there are 6. The faces are in the order
|
||||
N,R,L,B,T,[F].
|
||||
*/
|
||||
Array<Face> faceArray;
|
||||
};
|
||||
|
||||
GCamera();
|
||||
|
||||
virtual ~GCamera();
|
||||
|
||||
|
||||
CoordinateFrame getCoordinateFrame() const;
|
||||
void getCoordinateFrame(CoordinateFrame& c) const;
|
||||
void setCoordinateFrame(const CoordinateFrame& c);
|
||||
|
||||
/**
|
||||
Sets the horizontal field of view, in radians. The
|
||||
initial angle is toRadians(55).
|
||||
<UL>
|
||||
<LI> toRadians(50) - Telephoto
|
||||
<LI> toRadians(110) - Normal
|
||||
<LI> toRadians(140) - Wide angle
|
||||
</UL>
|
||||
*/
|
||||
void setFieldOfView(float angle);
|
||||
|
||||
/**
|
||||
Sets the field of view based on a desired image plane depth
|
||||
(<I>s'</I>) and film dimensions in world space. Depth must be positive. Width,
|
||||
depth, and height are measured in the same units (meters are
|
||||
recommended). The field of view will span the diagonal to the
|
||||
image.<P> <I>Note</I>: to simulate a 35mm GCamera, set width =
|
||||
0.36 mm and height = 0.24 mm. The width and height used are
|
||||
generally not the pixel dimensions of the image.
|
||||
*/
|
||||
void setImagePlaneDepth(
|
||||
float depth,
|
||||
const class Rect2D& viewport);
|
||||
|
||||
inline double getFieldOfView() const {
|
||||
return fieldOfView;
|
||||
}
|
||||
|
||||
/**
|
||||
Projects a world space point onto a width x height screen. The
|
||||
returned coordinate uses pixmap addressing: x = right and y =
|
||||
down. The resulting z value is <I>rhw</I>.
|
||||
|
||||
If the point is behind the camera, Vector3::inf() is returned.
|
||||
*/
|
||||
G3D::Vector3 project(
|
||||
const G3D::Vector3& point,
|
||||
const class Rect2D& viewport) const;
|
||||
|
||||
/**
|
||||
Returns the pixel area covered by a shape of the given
|
||||
world space area at the given z value (z must be negative).
|
||||
*/
|
||||
float worldToScreenSpaceArea(float area, float z, const class Rect2D& viewport) const;
|
||||
|
||||
/**
|
||||
Returns the world space 3D viewport corners. These
|
||||
are at the near clipping plane. The corners are constructed
|
||||
from the nearPlaneZ, getViewportWidth, and getViewportHeight.
|
||||
"left" and "right" are from the GCamera's perspective.
|
||||
*/
|
||||
void get3DViewportCorners(
|
||||
const class Rect2D& viewport,
|
||||
Vector3& outUR,
|
||||
Vector3& outUL,
|
||||
Vector3& outLL,
|
||||
Vector3& outLR) const;
|
||||
|
||||
/**
|
||||
Returns the image plane depth, <I>s'</I>, given the current field
|
||||
of view for film of dimensions width x height. See
|
||||
setImagePlaneDepth for a discussion of worldspace values width and height.
|
||||
*/
|
||||
float getImagePlaneDepth(
|
||||
const class Rect2D& viewport) const;
|
||||
|
||||
|
||||
/**
|
||||
Returns the world space ray passing through the center of pixel
|
||||
(x, y) on the image plane. The pixel x and y axes are opposite
|
||||
the 3D object space axes: (0,0) is the upper left corner of the screen.
|
||||
They are in viewport coordinates, not screen coordinates.
|
||||
|
||||
|
||||
Integer (x, y) values correspond to
|
||||
the upper left corners of pixels. If you want to cast rays
|
||||
through pixel centers, add 0.5 to x and y.
|
||||
*/
|
||||
Ray worldRay(
|
||||
float x,
|
||||
float y,
|
||||
const class Rect2D& viewport) const;
|
||||
|
||||
|
||||
/**
|
||||
Returns a negative z-value.
|
||||
*/
|
||||
inline float getNearPlaneZ() const {
|
||||
return -nearPlane;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a negative z-value.
|
||||
*/
|
||||
inline float getFarPlaneZ() const {
|
||||
return -farPlane;
|
||||
}
|
||||
|
||||
inline void setFarPlaneZ(float z) {
|
||||
debugAssert(z < 0);
|
||||
farPlane = -z;
|
||||
}
|
||||
|
||||
inline void setNearPlaneZ(float z) {
|
||||
debugAssert(z < 0);
|
||||
nearPlane = -z;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the GCamera space width of the viewport.
|
||||
*/
|
||||
float getViewportWidth(
|
||||
const class Rect2D& viewport) const;
|
||||
|
||||
/**
|
||||
Returns the GCamera space height of the viewport.
|
||||
*/
|
||||
float getViewportHeight(
|
||||
const class Rect2D& viewport) const;
|
||||
|
||||
/**
|
||||
Read back a GCamera space z-value at pixel (x, y) from the depth buffer.
|
||||
double getZValue(
|
||||
double x,
|
||||
double y,
|
||||
const class Rect2D& viewport,
|
||||
double polygonOffset = 0) const;
|
||||
*/
|
||||
|
||||
void setPosition(const Vector3& t);
|
||||
|
||||
void lookAt(const Vector3& position, const Vector3& up = Vector3::unitY());
|
||||
|
||||
/**
|
||||
Returns the clipping planes of the frustum, in world space.
|
||||
The planes have normals facing <B>into</B> the view frustum.
|
||||
|
||||
The plane order is guaranteed to be:
|
||||
Near, Right, Left, Top, Bottom, [Far]
|
||||
|
||||
If the far plane is at infinity, the resulting array will have
|
||||
5 planes, otherwise there will be 6.
|
||||
|
||||
The viewport is used only to determine the aspect ratio of the screen; the
|
||||
absolute dimensions and xy values don't matter.
|
||||
*/
|
||||
void getClipPlanes(
|
||||
const Rect2D& viewport,
|
||||
Array<Plane>& outClip) const;
|
||||
|
||||
/**
|
||||
Returns the world space view frustum, which is a truncated pyramid describing
|
||||
the volume of space seen by this camera.
|
||||
*/
|
||||
void getFrustum(const Rect2D& viewport, GCamera::Frustum& f) const;
|
||||
|
||||
GCamera::Frustum frustum(const Rect2D& viewport) const;
|
||||
|
||||
};
|
||||
|
||||
} // namespace G3D
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
@file Line.h
|
||||
|
||||
Line class
|
||||
|
||||
@maintainer Morgan McGuire, [email protected]
|
||||
|
||||
@created 2001-06-02
|
||||
@edited 2006-02-28
|
||||
*/
|
||||
|
||||
#ifndef G3D_LINE_H
|
||||
#define G3D_LINE_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Vector3.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class Plane;
|
||||
|
||||
/**
|
||||
An infinite 3D line.
|
||||
*/
|
||||
class Line {
|
||||
protected:
|
||||
|
||||
Vector3 _point;
|
||||
Vector3 _direction;
|
||||
|
||||
Line(const Vector3& point, const Vector3& direction) {
|
||||
_point = point;
|
||||
_direction = direction.direction();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/** Undefined (provided for creating Array<Line> only) */
|
||||
inline Line() {}
|
||||
|
||||
virtual ~Line() {}
|
||||
|
||||
/**
|
||||
Constructs a line from two (not equal) points.
|
||||
*/
|
||||
static Line fromTwoPoints(const Vector3 &point1, const Vector3 &point2) {
|
||||
return Line(point1, point2 - point1);
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a line from a point and a (nonzero) direction.
|
||||
*/
|
||||
static Line fromPointAndDirection(const Vector3& point, const Vector3& direction) {
|
||||
return Line(point, direction);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the closest point on the line to point.
|
||||
*/
|
||||
Vector3 closestPoint(const Vector3& pt) const;
|
||||
|
||||
/**
|
||||
Returns the distance between point and the line
|
||||
*/
|
||||
double distance(const Vector3& point) const {
|
||||
return (closestPoint(point) - point).magnitude();
|
||||
}
|
||||
|
||||
/** Returns a point on the line */
|
||||
Vector3 point() const;
|
||||
|
||||
/** Returns the direction (or negative direction) of the line */
|
||||
Vector3 direction() const;
|
||||
|
||||
/**
|
||||
Returns the point where the line and plane intersect. If there
|
||||
is no intersection, returns a point at infinity.
|
||||
*/
|
||||
Vector3 intersection(const Plane &plane) const;
|
||||
};
|
||||
|
||||
};// namespace
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,311 @@
|
||||
/**
|
||||
@file Matrix3.h
|
||||
|
||||
3x3 matrix class
|
||||
|
||||
@maintainer Morgan McGuire, [email protected]
|
||||
|
||||
@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 2006-04-05
|
||||
*/
|
||||
|
||||
#ifndef G3D_MATRIX3_H
|
||||
#define G3D_MATRIX3_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/System.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Vector4.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
3x3 matrix. Do not subclass.
|
||||
*/
|
||||
class Matrix3 {
|
||||
private:
|
||||
|
||||
float elt[3][3];
|
||||
|
||||
// Hidden operators
|
||||
bool operator<(const Matrix3&) const;
|
||||
bool operator>(const Matrix3&) const;
|
||||
bool operator<=(const Matrix3&) const;
|
||||
bool operator>=(const Matrix3&) const;
|
||||
|
||||
public:
|
||||
|
||||
/** Initial values are undefined for performance. See also
|
||||
Matrix3::zero(), Matrix3::identity(), Matrix3::fromAxisAngle, etc.*/
|
||||
inline Matrix3() {}
|
||||
|
||||
Matrix3 (const float aafEntry[3][3]);
|
||||
Matrix3 (const Matrix3& rkMatrix);
|
||||
Matrix3 (float fEntry00, float fEntry01, float fEntry02,
|
||||
float fEntry10, float fEntry11, float fEntry12,
|
||||
float fEntry20, float fEntry21, float fEntry22);
|
||||
|
||||
bool fuzzyEq(const Matrix3& b) const;
|
||||
|
||||
/** Constructs a matrix from a quaternion.
|
||||
@cite Graphics Gems II, p. 351--354
|
||||
@cite Implementation from Watt and Watt, pg 362*/
|
||||
Matrix3(const class Quat& q);
|
||||
|
||||
|
||||
/**
|
||||
Sets all elements.
|
||||
*/
|
||||
void set(float fEntry00, float fEntry01, float fEntry02,
|
||||
float fEntry10, float fEntry11, float fEntry12,
|
||||
float fEntry20, float fEntry21, float fEntry22);
|
||||
|
||||
/**
|
||||
* member access, allows use of construct mat[r][c]
|
||||
*/
|
||||
inline float* operator[] (int iRow) {
|
||||
debugAssert(iRow >= 0);
|
||||
debugAssert(iRow < 3);
|
||||
return (float*)&elt[iRow][0];
|
||||
}
|
||||
|
||||
inline const float* operator[] (int iRow) const {
|
||||
debugAssert(iRow >= 0);
|
||||
debugAssert(iRow < 3);
|
||||
return (const float*)&elt[iRow][0];
|
||||
}
|
||||
|
||||
inline operator float* () {
|
||||
return (float*)&elt[0][0];
|
||||
}
|
||||
|
||||
inline operator const float* () const{
|
||||
return (const float*)&elt[0][0];
|
||||
}
|
||||
|
||||
Vector3 getColumn (int iCol) const;
|
||||
Vector3 getRow (int iRow) const;
|
||||
void setColumn(int iCol, const Vector3 &vector);
|
||||
void setRow(int iRow, const Vector3 &vector);
|
||||
|
||||
// assignment and comparison
|
||||
inline Matrix3& operator= (const Matrix3& rkMatrix) {
|
||||
System::memcpy(elt, rkMatrix.elt, 9 * sizeof(float));
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator== (const Matrix3& rkMatrix) const;
|
||||
bool operator!= (const Matrix3& rkMatrix) const;
|
||||
|
||||
// arithmetic operations
|
||||
Matrix3 operator+ (const Matrix3& rkMatrix) const;
|
||||
Matrix3 operator- (const Matrix3& rkMatrix) const;
|
||||
/** Matrix-matrix multiply */
|
||||
Matrix3 operator* (const Matrix3& rkMatrix) const;
|
||||
Matrix3 operator- () const;
|
||||
|
||||
Matrix3& operator+= (const Matrix3& rkMatrix);
|
||||
Matrix3& operator-= (const Matrix3& rkMatrix);
|
||||
Matrix3& operator*= (const Matrix3& rkMatrix);
|
||||
|
||||
/**
|
||||
* matrix * vector [3x3 * 3x1 = 3x1]
|
||||
*/
|
||||
inline Vector3 operator* (const Vector3& v) const {
|
||||
Vector3 kProd;
|
||||
|
||||
for (int r = 0; r < 3; ++r) {
|
||||
kProd[r] =
|
||||
elt[r][0] * v[0] +
|
||||
elt[r][1] * v[1] +
|
||||
elt[r][2] * v[2];
|
||||
}
|
||||
|
||||
return kProd;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* vector * matrix [1x3 * 3x3 = 1x3]
|
||||
*/
|
||||
friend Vector3 operator* (const Vector3& rkVector,
|
||||
const Matrix3& rkMatrix);
|
||||
|
||||
/**
|
||||
* matrix * scalar
|
||||
*/
|
||||
Matrix3 operator* (float fScalar) const;
|
||||
|
||||
/** scalar * matrix */
|
||||
friend Matrix3 operator* (double fScalar, const Matrix3& rkMatrix);
|
||||
friend Matrix3 operator* (float fScalar, const Matrix3& rkMatrix);
|
||||
friend Matrix3 operator* (int fScalar, const Matrix3& rkMatrix);
|
||||
|
||||
private:
|
||||
/** Multiplication where out != A and out != B */
|
||||
static void _mul(const Matrix3& A, const Matrix3& B, Matrix3& out);
|
||||
public:
|
||||
|
||||
/** Optimized implementation of out = A * B. It is safe (but slow) to call
|
||||
with A, B, and out possibly pointer equal to one another.*/
|
||||
// This is a static method so that it is not ambiguous whether "this"
|
||||
// is an input or output argument.
|
||||
inline static void mul(const Matrix3& A, const Matrix3& B, Matrix3& out) {
|
||||
if ((&out == &A) || (&out == &B)) {
|
||||
// We need a temporary anyway, so revert to the stack method.
|
||||
out = A * B;
|
||||
} else {
|
||||
// Optimized in-place multiplication.
|
||||
_mul(A, B, out);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static void _transpose(const Matrix3& A, Matrix3& out);
|
||||
public:
|
||||
|
||||
/** Optimized implementation of out = A.transpose(). It is safe (but slow) to call
|
||||
with A and out possibly pointer equal to one another.
|
||||
|
||||
Note that <CODE>A.transpose() * v</CODE> can be computed
|
||||
more efficiently as <CODE>v * A</CODE>.
|
||||
*/
|
||||
inline static void transpose(const Matrix3& A, Matrix3& out) {
|
||||
if (&A == &out) {
|
||||
out = A.transpose();
|
||||
} else {
|
||||
_transpose(A, out);
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns true if the rows and column L2 norms are 1.0 and the rows are orthogonal. */
|
||||
bool isOrthonormal() const;
|
||||
|
||||
Matrix3 transpose () const;
|
||||
bool inverse (Matrix3& rkInverse, float fTolerance = 1e-06) const;
|
||||
Matrix3 inverse (float fTolerance = 1e-06) const;
|
||||
float determinant () const;
|
||||
|
||||
/** singular value decomposition */
|
||||
void singularValueDecomposition (Matrix3& rkL, Vector3& rkS,
|
||||
Matrix3& rkR) const;
|
||||
/** singular value decomposition */
|
||||
void singularValueComposition (const Matrix3& rkL,
|
||||
const Vector3& rkS, const Matrix3& rkR);
|
||||
|
||||
/** Gram-Schmidt orthonormalization (applied to columns of rotation matrix) */
|
||||
void orthonormalize();
|
||||
|
||||
/** orthogonal Q, diagonal D, upper triangular U stored as (u01,u02,u12) */
|
||||
void qDUDecomposition (Matrix3& rkQ, Vector3& rkD,
|
||||
Vector3& rkU) const;
|
||||
|
||||
float spectralNorm () const;
|
||||
|
||||
/** matrix must be orthonormal */
|
||||
void toAxisAngle(Vector3& rkAxis, float& rfRadians) const;
|
||||
|
||||
static Matrix3 fromAxisAngle(const Vector3& rkAxis, float fRadians);
|
||||
|
||||
/**
|
||||
* The matrix must be orthonormal. The decomposition is yaw*pitch*roll
|
||||
* where yaw is rotation about the Up vector, pitch is rotation about the
|
||||
* right axis, and roll is rotation about the Direction axis.
|
||||
*/
|
||||
bool toEulerAnglesXYZ (float& rfYAngle, float& rfPAngle,
|
||||
float& rfRAngle) const;
|
||||
bool toEulerAnglesXZY (float& rfYAngle, float& rfPAngle,
|
||||
float& rfRAngle) const;
|
||||
bool toEulerAnglesYXZ (float& rfYAngle, float& rfPAngle,
|
||||
float& rfRAngle) const;
|
||||
bool toEulerAnglesYZX (float& rfYAngle, float& rfPAngle,
|
||||
float& rfRAngle) const;
|
||||
bool toEulerAnglesZXY (float& rfYAngle, float& rfPAngle,
|
||||
float& rfRAngle) const;
|
||||
bool toEulerAnglesZYX (float& rfYAngle, float& rfPAngle,
|
||||
float& rfRAngle) const;
|
||||
static Matrix3 fromEulerAnglesXYZ (float fYAngle, float fPAngle, float fRAngle);
|
||||
static Matrix3 fromEulerAnglesXZY (float fYAngle, float fPAngle, float fRAngle);
|
||||
static Matrix3 fromEulerAnglesYXZ (float fYAngle, float fPAngle, float fRAngle);
|
||||
static Matrix3 fromEulerAnglesYZX (float fYAngle, float fPAngle, float fRAngle);
|
||||
static Matrix3 fromEulerAnglesZXY (float fYAngle, float fPAngle, float fRAngle);
|
||||
static Matrix3 fromEulerAnglesZYX (float fYAngle, float fPAngle, float fRAngle);
|
||||
|
||||
/** eigensolver, matrix must be symmetric */
|
||||
void eigenSolveSymmetric (float afEigenvalue[3],
|
||||
Vector3 akEigenvector[3]) const;
|
||||
|
||||
static void tensorProduct (const Vector3& rkU, const Vector3& rkV,
|
||||
Matrix3& rkProduct);
|
||||
std::string toString() const;
|
||||
|
||||
static const float EPSILON;
|
||||
|
||||
// Special values.
|
||||
// The unguaranteed order of initialization of static variables across
|
||||
// translation units can be a source of annoying bugs, so now the static
|
||||
// special values (like Vector3::ZERO, Color3::WHITE, ...) are wrapped
|
||||
// inside static functions that return references to them.
|
||||
// These functions are intentionally not inlined, because:
|
||||
// "You might be tempted to write [...] them as inline functions
|
||||
// inside their respective header files, but this is something you
|
||||
// must definitely not do. An inline function can be duplicated
|
||||
// in every file in which it appears – and this duplication
|
||||
// includes the static object definition. Because inline functions
|
||||
// automatically default to internal linkage, this would result in
|
||||
// having multiple static objects across the various translation
|
||||
// units, which would certainly cause problems. So you must
|
||||
// ensure that there is only one definition of each wrapping
|
||||
// function, and this means not making the wrapping functions inline",
|
||||
// according to Chapter 10 of "Thinking in C++, 2nd ed. Volume 1" by Bruce Eckel,
|
||||
// http://www.mindview.net/
|
||||
static const Matrix3& zero();
|
||||
static const Matrix3& identity();
|
||||
|
||||
// Deprecated.
|
||||
/** @deprecated Use Matrix3::zero() */
|
||||
static const Matrix3 ZERO;
|
||||
/** @deprecated Use Matrix3::identity() */
|
||||
static const Matrix3 IDENTITY;
|
||||
|
||||
protected:
|
||||
// support for eigensolver
|
||||
void tridiagonal (float afDiag[3], float afSubDiag[3]);
|
||||
bool qLAlgorithm (float afDiag[3], float afSubDiag[3]);
|
||||
|
||||
// support for singular value decomposition
|
||||
static const float ms_fSvdEpsilon;
|
||||
static const int ms_iSvdMaxIterations;
|
||||
static void bidiagonalize (Matrix3& kA, Matrix3& kL,
|
||||
Matrix3& kR);
|
||||
static void golubKahanStep (Matrix3& kA, Matrix3& kL,
|
||||
Matrix3& kR);
|
||||
|
||||
// support for spectral norm
|
||||
static float maxCubicRoot (float afCoeff[3]);
|
||||
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/** <code>v * M == M.transpose() * v</code> */
|
||||
inline Vector3 operator* (const Vector3& rkPoint, const Matrix3& rkMatrix) {
|
||||
Vector3 kProd;
|
||||
|
||||
for (int r = 0; r < 3; ++r) {
|
||||
kProd[r] =
|
||||
rkPoint[0] * rkMatrix.elt[0][r] +
|
||||
rkPoint[1] * rkMatrix.elt[1][r] +
|
||||
rkPoint[2] * rkMatrix.elt[2][r];
|
||||
}
|
||||
|
||||
return kProd;
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
/**
|
||||
@file Plane.h
|
||||
|
||||
Plane class
|
||||
|
||||
@maintainer Morgan McGuire, [email protected]
|
||||
|
||||
@created 2001-06-02
|
||||
@edited 2004-07-18
|
||||
*/
|
||||
|
||||
#ifndef G3D_PLANE_H
|
||||
#define G3D_PLANE_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Vector4.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
An infinite 2D plane in 3D space.
|
||||
*/
|
||||
class Plane {
|
||||
private:
|
||||
|
||||
/** normal.Dot(x,y,z) = distance */
|
||||
Vector3 _normal;
|
||||
float _distance;
|
||||
|
||||
/**
|
||||
Assumes the normal has unit length.
|
||||
*/
|
||||
Plane(const Vector3& n, float d) : _normal(n), _distance(d) {
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Plane() : _normal(Vector3::unitY()), _distance(0) {
|
||||
}
|
||||
|
||||
/**
|
||||
Constructs a plane from three points.
|
||||
*/
|
||||
Plane(
|
||||
const Vector3& point0,
|
||||
const Vector3& point1,
|
||||
const Vector3& point2);
|
||||
|
||||
/**
|
||||
Constructs a plane from three points, where at most two are
|
||||
at infinity (w = 0, not xyz = inf).
|
||||
*/
|
||||
Plane(
|
||||
Vector4 point0,
|
||||
Vector4 point1,
|
||||
Vector4 point2);
|
||||
|
||||
/**
|
||||
The normal will be unitized.
|
||||
*/
|
||||
Plane(
|
||||
const Vector3& __normal,
|
||||
const Vector3& point);
|
||||
|
||||
static Plane fromEquation(float a, float b, float c, float d);
|
||||
|
||||
virtual ~Plane() {}
|
||||
|
||||
/**
|
||||
Returns true if point is on the side the normal points to or
|
||||
is in the plane.
|
||||
*/
|
||||
inline bool halfSpaceContains(Vector3 point) const {
|
||||
// Clamp to a finite range for testing
|
||||
point = point.clamp(Vector3::minFinite(), Vector3::maxFinite());
|
||||
|
||||
// We can get away with putting values *at* the limits of the float32 range into
|
||||
// a dot product, since the dot product is carried out on float64.
|
||||
return _normal.dot(point) >= _distance;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns true if point is on the side the normal points to or
|
||||
is in the plane.
|
||||
*/
|
||||
inline bool halfSpaceContains(const Vector4& point) const {
|
||||
if (point.w == 0) {
|
||||
return _normal.dot(point.xyz()) > 0;
|
||||
} else {
|
||||
return halfSpaceContains(point.xyz() / point.w);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Returns true if point is on the side the normal points to or
|
||||
is in the plane. Only call on finite points. Faster than halfSpaceContains.
|
||||
*/
|
||||
inline bool halfSpaceContainsFinite(const Vector3& point) const {
|
||||
debugAssert(point.isFinite());
|
||||
return _normal.dot(point) >= _distance;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns true if the point is nearly in the plane.
|
||||
*/
|
||||
inline bool fuzzyContains(const Vector3 &point) const {
|
||||
return fuzzyEq(point.dot(_normal), _distance);
|
||||
}
|
||||
|
||||
inline const Vector3& normal() const {
|
||||
return _normal;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns distance from point to plane. Distance is negative if point is behind (not in plane in direction opposite normal) the plane.
|
||||
*/
|
||||
inline float distance(const Vector3& x) const {
|
||||
return (_normal.dot(x) - _distance);
|
||||
}
|
||||
|
||||
inline Vector3 closestPoint(const Vector3& x) const {
|
||||
return x + (_normal * (-distance(x)));
|
||||
}
|
||||
|
||||
/** Returns normal * distance from origin */
|
||||
Vector3 center() const {
|
||||
return _normal * _distance;
|
||||
}
|
||||
|
||||
/**
|
||||
Inverts the facing direction of the plane so the new normal
|
||||
is the inverse of the old normal.
|
||||
*/
|
||||
void flip();
|
||||
|
||||
/**
|
||||
Returns the equation in the form:
|
||||
|
||||
<CODE>normal.Dot(Vector3(<I>x</I>, <I>y</I>, <I>z</I>)) + d = 0</CODE>
|
||||
*/
|
||||
void getEquation(Vector3 &normal, double& d) const;
|
||||
void getEquation(Vector3 &normal, float& d) const;
|
||||
|
||||
/**
|
||||
ax + by + cz + d = 0
|
||||
*/
|
||||
void getEquation(double& a, double& b, double& c, double& d) const;
|
||||
void getEquation(float& a, float& b, float& c, float& d) const;
|
||||
|
||||
std::string toString() const;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,702 @@
|
||||
/**
|
||||
@file Quat.h
|
||||
|
||||
Quaternion
|
||||
|
||||
@maintainer Morgan McGuire, [email protected]
|
||||
|
||||
@created 2002-01-23
|
||||
@edited 2006-05-10
|
||||
*/
|
||||
|
||||
#ifndef G3D_QUAT_H
|
||||
#define G3D_QUAT_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Matrix3.h"
|
||||
#include <string>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Unit quaternions are used in computer graphics to represent
|
||||
rotation about an axis. Any 3x3 rotation matrix can
|
||||
be stored as a quaternion.
|
||||
|
||||
A quaternion represents the sum of a real scalar and
|
||||
an imaginary vector: ix + jy + kz + w. A unit quaternion
|
||||
representing a rotation by A about axis v has the form
|
||||
[sin(A/2)*v, cos(A/2)]. For a unit quaternion, q.conj() == q.inverse()
|
||||
is a rotation by -A about v. -q is the same rotation as q
|
||||
(negate both the axis and angle).
|
||||
|
||||
A non-unit quaterion q represents the same rotation as
|
||||
q.unitize() (Dam98 pg 28).
|
||||
|
||||
Although quaternion-vector operations (eg. Quat + Vector3) are
|
||||
well defined, they are not supported by this class because
|
||||
they typically are bugs when they appear in code.
|
||||
|
||||
Do not subclass.
|
||||
|
||||
<B>BETA API -- subject to change</B>
|
||||
@cite Erik B. Dam, Martin Koch, Martin Lillholm, Quaternions, Interpolation and Animation. Technical Report DIKU-TR-98/5, Department of Computer Science, University of Copenhagen, Denmark. 1998.
|
||||
*/
|
||||
class Quat {
|
||||
private:
|
||||
// Hidden operators
|
||||
bool operator<(const Quat&) const;
|
||||
bool operator>(const Quat&) const;
|
||||
bool operator<=(const Quat&) const;
|
||||
bool operator>=(const Quat&) const;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
q = [sin(angle / 2) * axis, cos(angle / 2)]
|
||||
|
||||
In Watt & Watt's notation, s = w, v = (x, y, z)
|
||||
In the Real-Time Rendering notation, u = (x, y, z), w = w
|
||||
*/
|
||||
float x, y, z, w;
|
||||
|
||||
/**
|
||||
Initializes to a zero degree rotation.
|
||||
*/
|
||||
inline Quat() : x(0), y(0), z(0), w(1) {}
|
||||
|
||||
Quat(
|
||||
const Matrix3& rot);
|
||||
|
||||
inline Quat(float _x, float _y, float _z, float _w) :
|
||||
x(_x), y(_y), z(_z), w(_w) {}
|
||||
|
||||
/** Defaults to a pure vector quaternion */
|
||||
inline Quat(const Vector3& v, float _w = 0) : x(v.x), y(v.y), z(v.z), w(_w) {
|
||||
}
|
||||
|
||||
/**
|
||||
The real part of the quaternion.
|
||||
*/
|
||||
inline const float& real() const {
|
||||
return w;
|
||||
}
|
||||
|
||||
inline float& real() {
|
||||
return w;
|
||||
}
|
||||
|
||||
/** Note: two quats can represent the Quat::sameRotation and not be equal. */
|
||||
bool fuzzyEq(const Quat& q) {
|
||||
return G3D::fuzzyEq(x, q.x) && G3D::fuzzyEq(y, q.y) && G3D::fuzzyEq(z, q.z) && G3D::fuzzyEq(w, q.w);
|
||||
}
|
||||
|
||||
/** True if these quaternions represent the same rotation (note that every rotation is
|
||||
represented by two values; q and -q).
|
||||
*/
|
||||
bool sameRotation(const Quat& q) {
|
||||
return fuzzyEq(q) || fuzzyEq(-q);
|
||||
}
|
||||
|
||||
inline Quat operator-() const {
|
||||
return Quat(-x, -y, -z, -w);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the imaginary part (x, y, z)
|
||||
*/
|
||||
inline const Vector3& imag() const {
|
||||
return *(reinterpret_cast<const Vector3*>(this));
|
||||
}
|
||||
|
||||
inline Vector3& imag() {
|
||||
return *(reinterpret_cast<Vector3*>(this));
|
||||
}
|
||||
|
||||
/** q = [sin(angle/2)*axis, cos(angle/2)] */
|
||||
static Quat fromAxisAngleRotation(
|
||||
const Vector3& axis,
|
||||
float angle);
|
||||
|
||||
/** Returns the axis and angle of rotation represented
|
||||
by this quaternion (i.e. q = [sin(angle/2)*axis, cos(angle/2)]) */
|
||||
void toAxisAngleRotation(
|
||||
Vector3& axis,
|
||||
double& angle) const;
|
||||
|
||||
void toAxisAngleRotation(
|
||||
Vector3& axis,
|
||||
float& angle) const {
|
||||
double d;
|
||||
toAxisAngleRotation(axis, d);
|
||||
angle = (float)d;
|
||||
}
|
||||
|
||||
Matrix3 toRotationMatrix() const;
|
||||
|
||||
void toRotationMatrix(
|
||||
Matrix3& rot) const;
|
||||
|
||||
/**
|
||||
Spherical linear interpolation: linear interpolation along the
|
||||
shortest (3D) great-circle route between two quaternions.
|
||||
|
||||
Note: Correct rotations are expected between 0 and PI in the right order.
|
||||
|
||||
@cite Based on Game Physics -- David Eberly pg 538-540
|
||||
@param threshold Critical angle between between rotations at which
|
||||
the algorithm switches to normalized lerp, which is more
|
||||
numerically stable in those situations. 0.0 will always slerp.
|
||||
*/
|
||||
Quat slerp(
|
||||
const Quat& other,
|
||||
float alpha,
|
||||
float threshold = 0.05f) const;
|
||||
|
||||
/** Normalized linear interpolation of quaternion components. */
|
||||
Quat nlerp(const Quat& other, float alpha) const;
|
||||
|
||||
/**
|
||||
Negates the imaginary part.
|
||||
*/
|
||||
inline Quat conj() const {
|
||||
return Quat(-x, -y, -z, w);
|
||||
}
|
||||
|
||||
inline float sum() const {
|
||||
return x + y + z + w;
|
||||
}
|
||||
|
||||
inline float average() const {
|
||||
return sum() / 4.0f;
|
||||
}
|
||||
|
||||
inline Quat operator*(float s) const {
|
||||
return Quat(x * s, y * s, z * s, w * s);
|
||||
}
|
||||
|
||||
/** @cite Based on Watt & Watt, page 360 */
|
||||
friend Quat operator* (float s, const Quat& q);
|
||||
|
||||
inline Quat operator/(float s) const {
|
||||
return Quat(x / s, y / s, z / s, w / s);
|
||||
}
|
||||
|
||||
inline float dot(const Quat& other) const {
|
||||
return (x * other.x) + (y * other.y) + (z * other.z) + (w * other.w);
|
||||
}
|
||||
|
||||
/** Note that q<SUP>-1</SUP> = q.conj() for a unit quaternion.
|
||||
@cite Dam99 page 13 */
|
||||
inline Quat inverse() const {
|
||||
return conj() / dot(*this);
|
||||
}
|
||||
|
||||
Quat operator-(const Quat& other) const;
|
||||
|
||||
Quat operator+(const Quat& other) const;
|
||||
|
||||
/**
|
||||
Quaternion multiplication (composition of rotations).
|
||||
Note that this does not commute.
|
||||
*/
|
||||
Quat operator*(const Quat& other) const;
|
||||
|
||||
/* (*this) * other.inverse() */
|
||||
Quat operator/(const Quat& other) const {
|
||||
return (*this) * other.inverse();
|
||||
}
|
||||
|
||||
|
||||
/** Is the magnitude nearly 1.0? */
|
||||
inline bool isUnit(float tolerance = 1e-5) const {
|
||||
return abs(dot(*this) - 1.0f) < tolerance;
|
||||
}
|
||||
|
||||
|
||||
inline float magnitude() const {
|
||||
return sqrtf(dot(*this));
|
||||
}
|
||||
|
||||
inline Quat log() const {
|
||||
if ((x == 0) && (y == 0) && (z == 0)) {
|
||||
if (w > 0) {
|
||||
return Quat(0, 0, 0, ::logf(w));
|
||||
} else if (w < 0) {
|
||||
// Log of a negative number. Multivalued, any number of the form
|
||||
// (PI * v, ln(-q.w))
|
||||
return Quat((float)G3D_PI, 0, 0, ::logf(-w));
|
||||
} else {
|
||||
// log of zero!
|
||||
return Quat((float)nan(), (float)nan(), (float)nan(), (float)nan());
|
||||
}
|
||||
} else {
|
||||
// Partly imaginary.
|
||||
float imagLen = sqrtf(x * x + y * y + z * z);
|
||||
float len = sqrtf(imagLen * imagLen + w * w);
|
||||
float theta = atan2f(imagLen, (float)w);
|
||||
float t = theta / imagLen;
|
||||
return Quat(t * x, t * y, t * z, ::logf(len));
|
||||
}
|
||||
}
|
||||
/** log q = [Av, 0] where q = [sin(A) * v, cos(A)].
|
||||
Only for unit quaternions
|
||||
debugAssertM(isUnit(), "Log only defined for unit quaternions");
|
||||
// Solve for A in q = [sin(A)*v, cos(A)]
|
||||
Vector3 u(x, y, z);
|
||||
double len = u.magnitude();
|
||||
|
||||
if (len == 0.0) {
|
||||
return
|
||||
}
|
||||
double A = atan2((double)w, len);
|
||||
Vector3 v = u / len;
|
||||
|
||||
return Quat(v * A, 0);
|
||||
}
|
||||
*/
|
||||
|
||||
/** exp q = [sin(A) * v, cos(A)] where q = [Av, 0].
|
||||
Only defined for pure-vector quaternions */
|
||||
inline Quat exp() const {
|
||||
debugAssertM(w == 0, "exp only defined for vector quaternions");
|
||||
Vector3 u(x, y, z);
|
||||
float A = u.magnitude();
|
||||
Vector3 v = u / A;
|
||||
return Quat(sinf(A) * v, cosf(A));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Raise this quaternion to a power. For a rotation, this is
|
||||
the effect of rotating x times as much as the original
|
||||
quaterion.
|
||||
|
||||
Note that q.pow(a).pow(b) == q.pow(a + b)
|
||||
@cite Dam98 pg 21
|
||||
*/
|
||||
inline Quat pow(float x) const {
|
||||
return (log() * x).exp();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@deprecated
|
||||
Use toUnit()
|
||||
*/
|
||||
inline Quat unitize() const {
|
||||
float mag2 = dot(*this);
|
||||
if (G3D::fuzzyEq(mag2, 1.0f)) {
|
||||
return *this;
|
||||
} else {
|
||||
return *this / sqrtf(mag2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a unit quaterion obtained by dividing through by
|
||||
the magnitude.
|
||||
*/
|
||||
inline Quat toUnit() const {
|
||||
return unitize();
|
||||
}
|
||||
|
||||
/**
|
||||
The linear algebra 2-norm, sqrt(q dot q). This matches
|
||||
the value used in Dam's 1998 tech report but differs from the
|
||||
n(q) value used in Eberly's 1999 paper, which is the square of the
|
||||
norm.
|
||||
*/
|
||||
inline float norm() const {
|
||||
return magnitude();
|
||||
}
|
||||
|
||||
// access quaternion as q[0] = q.x, q[1] = q.y, q[2] = q.z, q[3] = q.w
|
||||
//
|
||||
// WARNING. These member functions rely on
|
||||
// (1) Quat not having virtual functions
|
||||
// (2) the data packed in a 4*sizeof(float) memory block
|
||||
const float& operator[] (int i) const;
|
||||
float& operator[] (int i);
|
||||
|
||||
/** Generate uniform random unit quaternion (i.e. random "direction")
|
||||
@cite From "Uniform Random Rotations", Ken Shoemake, Graphics Gems III.
|
||||
*/
|
||||
static Quat unitRandom();
|
||||
|
||||
// 2-char swizzles
|
||||
|
||||
Vector2 xx() const;
|
||||
Vector2 yx() const;
|
||||
Vector2 zx() const;
|
||||
Vector2 wx() const;
|
||||
Vector2 xy() const;
|
||||
Vector2 yy() const;
|
||||
Vector2 zy() const;
|
||||
Vector2 wy() const;
|
||||
Vector2 xz() const;
|
||||
Vector2 yz() const;
|
||||
Vector2 zz() const;
|
||||
Vector2 wz() const;
|
||||
Vector2 xw() const;
|
||||
Vector2 yw() const;
|
||||
Vector2 zw() const;
|
||||
Vector2 ww() const;
|
||||
|
||||
// 3-char swizzles
|
||||
|
||||
Vector3 xxx() const;
|
||||
Vector3 yxx() const;
|
||||
Vector3 zxx() const;
|
||||
Vector3 wxx() const;
|
||||
Vector3 xyx() const;
|
||||
Vector3 yyx() const;
|
||||
Vector3 zyx() const;
|
||||
Vector3 wyx() const;
|
||||
Vector3 xzx() const;
|
||||
Vector3 yzx() const;
|
||||
Vector3 zzx() const;
|
||||
Vector3 wzx() const;
|
||||
Vector3 xwx() const;
|
||||
Vector3 ywx() const;
|
||||
Vector3 zwx() const;
|
||||
Vector3 wwx() const;
|
||||
Vector3 xxy() const;
|
||||
Vector3 yxy() const;
|
||||
Vector3 zxy() const;
|
||||
Vector3 wxy() const;
|
||||
Vector3 xyy() const;
|
||||
Vector3 yyy() const;
|
||||
Vector3 zyy() const;
|
||||
Vector3 wyy() const;
|
||||
Vector3 xzy() const;
|
||||
Vector3 yzy() const;
|
||||
Vector3 zzy() const;
|
||||
Vector3 wzy() const;
|
||||
Vector3 xwy() const;
|
||||
Vector3 ywy() const;
|
||||
Vector3 zwy() const;
|
||||
Vector3 wwy() const;
|
||||
Vector3 xxz() const;
|
||||
Vector3 yxz() const;
|
||||
Vector3 zxz() const;
|
||||
Vector3 wxz() const;
|
||||
Vector3 xyz() const;
|
||||
Vector3 yyz() const;
|
||||
Vector3 zyz() const;
|
||||
Vector3 wyz() const;
|
||||
Vector3 xzz() const;
|
||||
Vector3 yzz() const;
|
||||
Vector3 zzz() const;
|
||||
Vector3 wzz() const;
|
||||
Vector3 xwz() const;
|
||||
Vector3 ywz() const;
|
||||
Vector3 zwz() const;
|
||||
Vector3 wwz() const;
|
||||
Vector3 xxw() const;
|
||||
Vector3 yxw() const;
|
||||
Vector3 zxw() const;
|
||||
Vector3 wxw() const;
|
||||
Vector3 xyw() const;
|
||||
Vector3 yyw() const;
|
||||
Vector3 zyw() const;
|
||||
Vector3 wyw() const;
|
||||
Vector3 xzw() const;
|
||||
Vector3 yzw() const;
|
||||
Vector3 zzw() const;
|
||||
Vector3 wzw() const;
|
||||
Vector3 xww() const;
|
||||
Vector3 yww() const;
|
||||
Vector3 zww() const;
|
||||
Vector3 www() const;
|
||||
|
||||
// 4-char swizzles
|
||||
|
||||
Vector4 xxxx() const;
|
||||
Vector4 yxxx() const;
|
||||
Vector4 zxxx() const;
|
||||
Vector4 wxxx() const;
|
||||
Vector4 xyxx() const;
|
||||
Vector4 yyxx() const;
|
||||
Vector4 zyxx() const;
|
||||
Vector4 wyxx() const;
|
||||
Vector4 xzxx() const;
|
||||
Vector4 yzxx() const;
|
||||
Vector4 zzxx() const;
|
||||
Vector4 wzxx() const;
|
||||
Vector4 xwxx() const;
|
||||
Vector4 ywxx() const;
|
||||
Vector4 zwxx() const;
|
||||
Vector4 wwxx() const;
|
||||
Vector4 xxyx() const;
|
||||
Vector4 yxyx() const;
|
||||
Vector4 zxyx() const;
|
||||
Vector4 wxyx() const;
|
||||
Vector4 xyyx() const;
|
||||
Vector4 yyyx() const;
|
||||
Vector4 zyyx() const;
|
||||
Vector4 wyyx() const;
|
||||
Vector4 xzyx() const;
|
||||
Vector4 yzyx() const;
|
||||
Vector4 zzyx() const;
|
||||
Vector4 wzyx() const;
|
||||
Vector4 xwyx() const;
|
||||
Vector4 ywyx() const;
|
||||
Vector4 zwyx() const;
|
||||
Vector4 wwyx() const;
|
||||
Vector4 xxzx() const;
|
||||
Vector4 yxzx() const;
|
||||
Vector4 zxzx() const;
|
||||
Vector4 wxzx() const;
|
||||
Vector4 xyzx() const;
|
||||
Vector4 yyzx() const;
|
||||
Vector4 zyzx() const;
|
||||
Vector4 wyzx() const;
|
||||
Vector4 xzzx() const;
|
||||
Vector4 yzzx() const;
|
||||
Vector4 zzzx() const;
|
||||
Vector4 wzzx() const;
|
||||
Vector4 xwzx() const;
|
||||
Vector4 ywzx() const;
|
||||
Vector4 zwzx() const;
|
||||
Vector4 wwzx() const;
|
||||
Vector4 xxwx() const;
|
||||
Vector4 yxwx() const;
|
||||
Vector4 zxwx() const;
|
||||
Vector4 wxwx() const;
|
||||
Vector4 xywx() const;
|
||||
Vector4 yywx() const;
|
||||
Vector4 zywx() const;
|
||||
Vector4 wywx() const;
|
||||
Vector4 xzwx() const;
|
||||
Vector4 yzwx() const;
|
||||
Vector4 zzwx() const;
|
||||
Vector4 wzwx() const;
|
||||
Vector4 xwwx() const;
|
||||
Vector4 ywwx() const;
|
||||
Vector4 zwwx() const;
|
||||
Vector4 wwwx() const;
|
||||
Vector4 xxxy() const;
|
||||
Vector4 yxxy() const;
|
||||
Vector4 zxxy() const;
|
||||
Vector4 wxxy() const;
|
||||
Vector4 xyxy() const;
|
||||
Vector4 yyxy() const;
|
||||
Vector4 zyxy() const;
|
||||
Vector4 wyxy() const;
|
||||
Vector4 xzxy() const;
|
||||
Vector4 yzxy() const;
|
||||
Vector4 zzxy() const;
|
||||
Vector4 wzxy() const;
|
||||
Vector4 xwxy() const;
|
||||
Vector4 ywxy() const;
|
||||
Vector4 zwxy() const;
|
||||
Vector4 wwxy() const;
|
||||
Vector4 xxyy() const;
|
||||
Vector4 yxyy() const;
|
||||
Vector4 zxyy() const;
|
||||
Vector4 wxyy() const;
|
||||
Vector4 xyyy() const;
|
||||
Vector4 yyyy() const;
|
||||
Vector4 zyyy() const;
|
||||
Vector4 wyyy() const;
|
||||
Vector4 xzyy() const;
|
||||
Vector4 yzyy() const;
|
||||
Vector4 zzyy() const;
|
||||
Vector4 wzyy() const;
|
||||
Vector4 xwyy() const;
|
||||
Vector4 ywyy() const;
|
||||
Vector4 zwyy() const;
|
||||
Vector4 wwyy() const;
|
||||
Vector4 xxzy() const;
|
||||
Vector4 yxzy() const;
|
||||
Vector4 zxzy() const;
|
||||
Vector4 wxzy() const;
|
||||
Vector4 xyzy() const;
|
||||
Vector4 yyzy() const;
|
||||
Vector4 zyzy() const;
|
||||
Vector4 wyzy() const;
|
||||
Vector4 xzzy() const;
|
||||
Vector4 yzzy() const;
|
||||
Vector4 zzzy() const;
|
||||
Vector4 wzzy() const;
|
||||
Vector4 xwzy() const;
|
||||
Vector4 ywzy() const;
|
||||
Vector4 zwzy() const;
|
||||
Vector4 wwzy() const;
|
||||
Vector4 xxwy() const;
|
||||
Vector4 yxwy() const;
|
||||
Vector4 zxwy() const;
|
||||
Vector4 wxwy() const;
|
||||
Vector4 xywy() const;
|
||||
Vector4 yywy() const;
|
||||
Vector4 zywy() const;
|
||||
Vector4 wywy() const;
|
||||
Vector4 xzwy() const;
|
||||
Vector4 yzwy() const;
|
||||
Vector4 zzwy() const;
|
||||
Vector4 wzwy() const;
|
||||
Vector4 xwwy() const;
|
||||
Vector4 ywwy() const;
|
||||
Vector4 zwwy() const;
|
||||
Vector4 wwwy() const;
|
||||
Vector4 xxxz() const;
|
||||
Vector4 yxxz() const;
|
||||
Vector4 zxxz() const;
|
||||
Vector4 wxxz() const;
|
||||
Vector4 xyxz() const;
|
||||
Vector4 yyxz() const;
|
||||
Vector4 zyxz() const;
|
||||
Vector4 wyxz() const;
|
||||
Vector4 xzxz() const;
|
||||
Vector4 yzxz() const;
|
||||
Vector4 zzxz() const;
|
||||
Vector4 wzxz() const;
|
||||
Vector4 xwxz() const;
|
||||
Vector4 ywxz() const;
|
||||
Vector4 zwxz() const;
|
||||
Vector4 wwxz() const;
|
||||
Vector4 xxyz() const;
|
||||
Vector4 yxyz() const;
|
||||
Vector4 zxyz() const;
|
||||
Vector4 wxyz() const;
|
||||
Vector4 xyyz() const;
|
||||
Vector4 yyyz() const;
|
||||
Vector4 zyyz() const;
|
||||
Vector4 wyyz() const;
|
||||
Vector4 xzyz() const;
|
||||
Vector4 yzyz() const;
|
||||
Vector4 zzyz() const;
|
||||
Vector4 wzyz() const;
|
||||
Vector4 xwyz() const;
|
||||
Vector4 ywyz() const;
|
||||
Vector4 zwyz() const;
|
||||
Vector4 wwyz() const;
|
||||
Vector4 xxzz() const;
|
||||
Vector4 yxzz() const;
|
||||
Vector4 zxzz() const;
|
||||
Vector4 wxzz() const;
|
||||
Vector4 xyzz() const;
|
||||
Vector4 yyzz() const;
|
||||
Vector4 zyzz() const;
|
||||
Vector4 wyzz() const;
|
||||
Vector4 xzzz() const;
|
||||
Vector4 yzzz() const;
|
||||
Vector4 zzzz() const;
|
||||
Vector4 wzzz() const;
|
||||
Vector4 xwzz() const;
|
||||
Vector4 ywzz() const;
|
||||
Vector4 zwzz() const;
|
||||
Vector4 wwzz() const;
|
||||
Vector4 xxwz() const;
|
||||
Vector4 yxwz() const;
|
||||
Vector4 zxwz() const;
|
||||
Vector4 wxwz() const;
|
||||
Vector4 xywz() const;
|
||||
Vector4 yywz() const;
|
||||
Vector4 zywz() const;
|
||||
Vector4 wywz() const;
|
||||
Vector4 xzwz() const;
|
||||
Vector4 yzwz() const;
|
||||
Vector4 zzwz() const;
|
||||
Vector4 wzwz() const;
|
||||
Vector4 xwwz() const;
|
||||
Vector4 ywwz() const;
|
||||
Vector4 zwwz() const;
|
||||
Vector4 wwwz() const;
|
||||
Vector4 xxxw() const;
|
||||
Vector4 yxxw() const;
|
||||
Vector4 zxxw() const;
|
||||
Vector4 wxxw() const;
|
||||
Vector4 xyxw() const;
|
||||
Vector4 yyxw() const;
|
||||
Vector4 zyxw() const;
|
||||
Vector4 wyxw() const;
|
||||
Vector4 xzxw() const;
|
||||
Vector4 yzxw() const;
|
||||
Vector4 zzxw() const;
|
||||
Vector4 wzxw() const;
|
||||
Vector4 xwxw() const;
|
||||
Vector4 ywxw() const;
|
||||
Vector4 zwxw() const;
|
||||
Vector4 wwxw() const;
|
||||
Vector4 xxyw() const;
|
||||
Vector4 yxyw() const;
|
||||
Vector4 zxyw() const;
|
||||
Vector4 wxyw() const;
|
||||
Vector4 xyyw() const;
|
||||
Vector4 yyyw() const;
|
||||
Vector4 zyyw() const;
|
||||
Vector4 wyyw() const;
|
||||
Vector4 xzyw() const;
|
||||
Vector4 yzyw() const;
|
||||
Vector4 zzyw() const;
|
||||
Vector4 wzyw() const;
|
||||
Vector4 xwyw() const;
|
||||
Vector4 ywyw() const;
|
||||
Vector4 zwyw() const;
|
||||
Vector4 wwyw() const;
|
||||
Vector4 xxzw() const;
|
||||
Vector4 yxzw() const;
|
||||
Vector4 zxzw() const;
|
||||
Vector4 wxzw() const;
|
||||
Vector4 xyzw() const;
|
||||
Vector4 yyzw() const;
|
||||
Vector4 zyzw() const;
|
||||
Vector4 wyzw() const;
|
||||
Vector4 xzzw() const;
|
||||
Vector4 yzzw() const;
|
||||
Vector4 zzzw() const;
|
||||
Vector4 wzzw() const;
|
||||
Vector4 xwzw() const;
|
||||
Vector4 ywzw() const;
|
||||
Vector4 zwzw() const;
|
||||
Vector4 wwzw() const;
|
||||
Vector4 xxww() const;
|
||||
Vector4 yxww() const;
|
||||
Vector4 zxww() const;
|
||||
Vector4 wxww() const;
|
||||
Vector4 xyww() const;
|
||||
Vector4 yyww() const;
|
||||
Vector4 zyww() const;
|
||||
Vector4 wyww() const;
|
||||
Vector4 xzww() const;
|
||||
Vector4 yzww() const;
|
||||
Vector4 zzww() const;
|
||||
Vector4 wzww() const;
|
||||
Vector4 xwww() const;
|
||||
Vector4 ywww() const;
|
||||
Vector4 zwww() const;
|
||||
Vector4 wwww() const;
|
||||
};
|
||||
|
||||
inline Quat exp(const Quat& q) {
|
||||
return q.exp();
|
||||
}
|
||||
|
||||
inline Quat log(const Quat& q) {
|
||||
return q.log();
|
||||
}
|
||||
|
||||
inline G3D::Quat operator*(double s, const G3D::Quat& q) {
|
||||
return q * (float)s;
|
||||
}
|
||||
|
||||
inline G3D::Quat operator*(float s, const G3D::Quat& q) {
|
||||
return q * s;
|
||||
}
|
||||
|
||||
} // Namespace G3D
|
||||
|
||||
// Outside the namespace to avoid overloading confusion for C++
|
||||
inline G3D::Quat pow(const G3D::Quat& q, double x) {
|
||||
return q.pow((float)x);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include "Quat.inl"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
Quat.inl
|
||||
|
||||
@cite Quaternion implementation based on Watt & Watt page 363.
|
||||
Thanks to Max McGuire for slerp optimizations.
|
||||
|
||||
@maintainer Morgan McGuire, [email protected]
|
||||
|
||||
@created 2002-01-23
|
||||
@edited 2004-03-04
|
||||
*/
|
||||
|
||||
namespace G3D {
|
||||
|
||||
inline float& Quat::operator[] (int i) {
|
||||
debugAssert(i >= 0);
|
||||
debugAssert(i < 4);
|
||||
return ((float*)this)[i];
|
||||
}
|
||||
|
||||
inline const float& Quat::operator[] (int i) const {
|
||||
debugAssert(i >= 0);
|
||||
debugAssert(i < 4);
|
||||
return ((float*)this)[i];
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Quat Quat::operator-(const Quat& other) const {
|
||||
return Quat(x - other.x, y - other.y, z - other.z, w - other.w);
|
||||
}
|
||||
|
||||
inline Quat Quat::operator+(const Quat& other) const {
|
||||
return Quat(x + other.x, y + other.y, z + other.z, w + other.w);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,327 @@
|
||||
/**
|
||||
@file Ray.h
|
||||
|
||||
Ray class
|
||||
|
||||
@maintainer Morgan McGuire, [email protected]
|
||||
|
||||
@created 2002-07-12
|
||||
@edited 2006-02-21
|
||||
*/
|
||||
|
||||
#ifndef G3D_RAY_H
|
||||
#define G3D_RAY_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Triangle.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
A 3D Ray.
|
||||
*/
|
||||
class Ray {
|
||||
private:
|
||||
Ray(const Vector3& origin, const Vector3& direction) {
|
||||
this->origin = origin;
|
||||
this->direction = direction;
|
||||
}
|
||||
|
||||
public:
|
||||
Vector3 origin;
|
||||
|
||||
/**
|
||||
Not unit length
|
||||
*/
|
||||
Vector3 direction;
|
||||
|
||||
Ray() : origin(Vector3::zero()), direction(Vector3::zero()) {}
|
||||
|
||||
virtual ~Ray() {}
|
||||
|
||||
/**
|
||||
Creates a Ray from a origin and a (nonzero) direction.
|
||||
*/
|
||||
static Ray fromOriginAndDirection(const Vector3& point, const Vector3& direction) {
|
||||
return Ray(point, direction);
|
||||
}
|
||||
|
||||
Ray unit() const {
|
||||
return Ray(origin, direction.unit());
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the closest point on the Ray to point.
|
||||
*/
|
||||
Vector3 closestPoint(const Vector3& point) const {
|
||||
float t = direction.dot(point - this->origin);
|
||||
if (t < 0) {
|
||||
return this->origin;
|
||||
} else {
|
||||
return this->origin + direction * t;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the closest distance between point and the Ray
|
||||
*/
|
||||
float distance(const Vector3& point) const {
|
||||
return (closestPoint(point) - point).magnitude();
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the point where the Ray and plane intersect. If there
|
||||
is no intersection, returns a point at infinity.
|
||||
|
||||
Planes are considered one-sided, so the ray will not intersect
|
||||
a plane where the normal faces in the traveling direction.
|
||||
*/
|
||||
Vector3 intersection(const class Plane& plane) const;
|
||||
|
||||
/**
|
||||
Returns the distance until intersection with the (solid) sphere.
|
||||
Will be 0 if inside the sphere, inf if there is no intersection.
|
||||
|
||||
The ray direction is <B>not</B> normalized. If the ray direction
|
||||
has unit length, the distance from the origin to intersection
|
||||
is equal to the time. If the direction does not have unit length,
|
||||
the distance = time * direction.length().
|
||||
|
||||
See also the G3D::CollisionDetection "movingPoint" methods,
|
||||
which give more information about the intersection.
|
||||
*/
|
||||
float intersectionTime(const class Sphere& sphere) const;
|
||||
|
||||
float intersectionTime(const class Plane& plane) const;
|
||||
|
||||
float intersectionTime(const class Box& box) const;
|
||||
|
||||
float intersectionTime(const class AABox& box) const;
|
||||
|
||||
/**
|
||||
The three extra arguments are the weights of vertices 0, 1, and 2
|
||||
at the intersection point; they are useful for texture mapping
|
||||
and interpolated normals.
|
||||
*/
|
||||
float intersectionTime(
|
||||
const Vector3& v0, const Vector3& v1, const Vector3& v2,
|
||||
const Vector3& edge01, const Vector3& edge02,
|
||||
double& w0, double& w1, double& w2) const;
|
||||
|
||||
/**
|
||||
Ray-triangle intersection for a 1-sided triangle. Fastest version.
|
||||
@cite http://www.acm.org/jgt/papers/MollerTrumbore97/
|
||||
http://www.graphics.cornell.edu/pubs/1997/MT97.html
|
||||
*/
|
||||
inline float intersectionTime(
|
||||
const Vector3& vert0,
|
||||
const Vector3& vert1,
|
||||
const Vector3& vert2,
|
||||
const Vector3& edge01,
|
||||
const Vector3& edge02) const;
|
||||
|
||||
|
||||
inline float intersectionTime(
|
||||
const Vector3& vert0,
|
||||
const Vector3& vert1,
|
||||
const Vector3& vert2) const {
|
||||
|
||||
return intersectionTime(vert0, vert1, vert2, vert1 - vert0, vert2 - vert0);
|
||||
}
|
||||
|
||||
|
||||
inline float intersectionTime(
|
||||
const Vector3& vert0,
|
||||
const Vector3& vert1,
|
||||
const Vector3& vert2,
|
||||
double& w0,
|
||||
double& w1,
|
||||
double& w2) const {
|
||||
|
||||
return intersectionTime(vert0, vert1, vert2, vert1 - vert0, vert2 - vert0, w0, w1, w2);
|
||||
}
|
||||
|
||||
/* One-sided triangle
|
||||
*/
|
||||
inline float intersectionTime(const Triangle& triangle) const {
|
||||
return intersectionTime(
|
||||
triangle.vertex(0), triangle.vertex(1), triangle.vertex(2),
|
||||
triangle.edge01, triangle.edge02);
|
||||
}
|
||||
|
||||
inline float intersectionTime(
|
||||
const Triangle& triangle,
|
||||
double& w0,
|
||||
double& w1,
|
||||
double& w2) const {
|
||||
return intersectionTime(triangle.vertex(0), triangle.vertex(1), triangle.vertex(2),
|
||||
triangle.edge01, triangle.edge02, w0, w1, w2);
|
||||
}
|
||||
|
||||
/** Refracts about the normal
|
||||
using G3D::Vector3::refractionDirection
|
||||
and bumps the ray slightly from the newOrigin. */
|
||||
Ray refract(
|
||||
const Vector3& newOrigin,
|
||||
const Vector3& normal,
|
||||
float iInside,
|
||||
float iOutside) const;
|
||||
|
||||
/** Reflects about the normal
|
||||
using G3D::Vector3::reflectionDirection
|
||||
and bumps the ray slightly from
|
||||
the newOrigin. */
|
||||
Ray reflect(
|
||||
const Vector3& newOrigin,
|
||||
const Vector3& normal) const;
|
||||
};
|
||||
|
||||
|
||||
#define EPSILON 0.000001
|
||||
#define CROSS(dest,v1,v2) \
|
||||
dest[0]=v1[1]*v2[2]-v1[2]*v2[1]; \
|
||||
dest[1]=v1[2]*v2[0]-v1[0]*v2[2]; \
|
||||
dest[2]=v1[0]*v2[1]-v1[1]*v2[0];
|
||||
|
||||
#define DOT(v1,v2) (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2])
|
||||
|
||||
#define SUB(dest,v1,v2) \
|
||||
dest[0]=v1[0]-v2[0]; \
|
||||
dest[1]=v1[1]-v2[1]; \
|
||||
dest[2]=v1[2]-v2[2];
|
||||
|
||||
inline float Ray::intersectionTime(
|
||||
const Vector3& vert0,
|
||||
const Vector3& vert1,
|
||||
const Vector3& vert2,
|
||||
const Vector3& edge1,
|
||||
const Vector3& edge2) const {
|
||||
|
||||
(void)vert1;
|
||||
(void)vert2;
|
||||
|
||||
// Barycenteric coords
|
||||
float u, v;
|
||||
|
||||
float tvec[3], pvec[3], qvec[3];
|
||||
|
||||
// begin calculating determinant - also used to calculate U parameter
|
||||
CROSS(pvec, direction, edge2);
|
||||
|
||||
// if determinant is near zero, ray lies in plane of triangle
|
||||
const float det = DOT(edge1, pvec);
|
||||
|
||||
if (det < EPSILON) {
|
||||
return (float)inf();
|
||||
}
|
||||
|
||||
// calculate distance from vert0 to ray origin
|
||||
SUB(tvec, origin, vert0);
|
||||
|
||||
// calculate U parameter and test bounds
|
||||
u = DOT(tvec, pvec);
|
||||
if ((u < 0.0f) || (u > det)) {
|
||||
// Hit the plane outside the triangle
|
||||
return (float)inf();
|
||||
}
|
||||
|
||||
// prepare to test V parameter
|
||||
CROSS(qvec, tvec, edge1);
|
||||
|
||||
// calculate V parameter and test bounds
|
||||
v = DOT(direction, qvec);
|
||||
if ((v < 0.0f) || (u + v > det)) {
|
||||
// Hit the plane outside the triangle
|
||||
return (float)inf();
|
||||
}
|
||||
|
||||
|
||||
// Case where we don't need correct (u, v):
|
||||
const float t = DOT(edge2, qvec);
|
||||
|
||||
if (t >= 0.0f) {
|
||||
// Note that det must be positive
|
||||
return t / det;
|
||||
} else {
|
||||
// We had to travel backwards in time to intersect
|
||||
return (float)inf();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline float Ray::intersectionTime(
|
||||
const Vector3& vert0,
|
||||
const Vector3& vert1,
|
||||
const Vector3& vert2,
|
||||
const Vector3& edge1,
|
||||
const Vector3& edge2,
|
||||
double& w0,
|
||||
double& w1,
|
||||
double& w2) const {
|
||||
|
||||
(void)vert1;
|
||||
(void)vert2;
|
||||
|
||||
// Barycenteric coords
|
||||
float u, v;
|
||||
|
||||
float tvec[3], pvec[3], qvec[3];
|
||||
|
||||
// begin calculating determinant - also used to calculate U parameter
|
||||
CROSS(pvec, direction, edge2);
|
||||
|
||||
// if determinant is near zero, ray lies in plane of triangle
|
||||
const float det = DOT(edge1, pvec);
|
||||
|
||||
if (det < EPSILON) {
|
||||
return (float)inf();
|
||||
}
|
||||
|
||||
// calculate distance from vert0 to ray origin
|
||||
SUB(tvec, origin, vert0);
|
||||
|
||||
// calculate U parameter and test bounds
|
||||
u = DOT(tvec, pvec);
|
||||
if ((u < 0.0f) || (u > det)) {
|
||||
// Hit the plane outside the triangle
|
||||
return (float)inf();
|
||||
}
|
||||
|
||||
// prepare to test V parameter
|
||||
CROSS(qvec, tvec, edge1);
|
||||
|
||||
// calculate V parameter and test bounds
|
||||
v = DOT(direction, qvec);
|
||||
if ((v < 0.0f) || (u + v > det)) {
|
||||
// Hit the plane outside the triangle
|
||||
return (float)inf();
|
||||
}
|
||||
|
||||
float t = DOT(edge2, qvec);
|
||||
|
||||
if (t >= 0) {
|
||||
const float inv_det = 1.0f / det;
|
||||
t *= inv_det;
|
||||
u *= inv_det;
|
||||
v *= inv_det;
|
||||
|
||||
w0 = (1.0f - u - v);
|
||||
w1 = u;
|
||||
w2 = v;
|
||||
|
||||
return t;
|
||||
} else {
|
||||
// We had to travel backwards in time to intersect
|
||||
return (float)inf();
|
||||
}
|
||||
}
|
||||
|
||||
#undef EPSILON
|
||||
#undef CROSS
|
||||
#undef DOT
|
||||
#undef SUB
|
||||
|
||||
}// namespace
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
@file RegistryUtil.h
|
||||
|
||||
@created 2006-04-06
|
||||
@edited 2006-04-06
|
||||
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_REGISTRYUTIL_H
|
||||
#define G3D_REGISTRYUTIL_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
|
||||
// This file is only used on Windows
|
||||
#ifdef G3D_WIN32
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Provides generalized Windows registry querying.
|
||||
|
||||
All key names are one string in the format:
|
||||
"[base key]\[sub-keys]\value"
|
||||
|
||||
[base key] can be any of the following:
|
||||
HKEY_CLASSES_ROOT
|
||||
HKEY_CURRENT_CONFIG
|
||||
HKEY_CURRENT_USER
|
||||
HKEY_LOCAL_MACHINE
|
||||
HKEY_PERFORMANCE_DATA
|
||||
HKEY_PERFORMANCE_NLSTEXT
|
||||
HKEY_PERFORMANCE_TEXT
|
||||
HKEY_USERS
|
||||
|
||||
keyExists() should be used to validate a key before reading or writing
|
||||
to ensure that a debug assert or false return is for a different error.
|
||||
*/
|
||||
class RegistryUtil {
|
||||
|
||||
public:
|
||||
/** returns true if the key exists */
|
||||
static bool keyExists(const std::string& key);
|
||||
|
||||
/** returns false if the key could not be read for any reason. */
|
||||
static bool readInt32(const std::string& key, int32& valueData);
|
||||
|
||||
/**
|
||||
Reads an arbitrary amount of data from a binary registry key.
|
||||
returns false if the key could not be read for any reason.
|
||||
|
||||
@beta
|
||||
@param valueData pointer to the output buffer of sufficient size. Pass NULL as valueData in order to have available data size returned in dataSize.
|
||||
@param dataSize size of the output buffer. When NULL is passed for valueData, contains the size of available data on successful return.
|
||||
*/
|
||||
static bool readBytes(const std::string& key, uint8* valueData, uint32& dataSize);
|
||||
|
||||
/** returns false if the key could not be read for any reason. */
|
||||
static bool readString(const std::string& key, std::string& valueData);
|
||||
|
||||
/** returns false if the key could not be written for any reason. */
|
||||
static bool writeInt32(const std::string& key, int32 valueData);
|
||||
|
||||
/**
|
||||
Writes an arbitrary amount of data to a binary registry key.
|
||||
returns false if the key could not be written for any reason.
|
||||
|
||||
@param valueData pointer to the input buffer
|
||||
@param dataSize size of the input buffer that should be written
|
||||
*/
|
||||
static bool writeBytes(const std::string& key, const uint8* valueData, uint32 dataSize);
|
||||
|
||||
/** returns false if the key could not be written for any reason. */
|
||||
static bool writeString(const std::string& key, const std::string& valueData);
|
||||
|
||||
};
|
||||
|
||||
} // namespace G3D
|
||||
|
||||
#endif // G3D_WIN32
|
||||
|
||||
#endif // G3D_REGISTRYTUIL_H
|
||||
@@ -0,0 +1,128 @@
|
||||
/**
|
||||
@file Sphere.h
|
||||
|
||||
Sphere class
|
||||
|
||||
@maintainer Morgan McGuire, [email protected]
|
||||
|
||||
@created 2001-06-02
|
||||
@edited 2004-07-05
|
||||
*/
|
||||
|
||||
#ifndef G3D_SPHERE_H
|
||||
#define G3D_SPHERE_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/Sphere.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Sphere.
|
||||
*/
|
||||
class Sphere {
|
||||
private:
|
||||
|
||||
static int32 dummy;
|
||||
|
||||
public:
|
||||
Vector3 center;
|
||||
float radius;
|
||||
|
||||
Sphere() {
|
||||
center = Vector3::zero();
|
||||
radius = 0;
|
||||
}
|
||||
|
||||
Sphere(
|
||||
const Vector3& center,
|
||||
float radius) {
|
||||
|
||||
this->center = center;
|
||||
this->radius = radius;
|
||||
}
|
||||
|
||||
virtual ~Sphere() {}
|
||||
|
||||
bool operator==(const Sphere& other) const {
|
||||
return (center == other.center) && (radius == other.radius);
|
||||
}
|
||||
|
||||
bool operator!=(const Sphere& other) const {
|
||||
return !((center == other.center) && (radius == other.radius));
|
||||
}
|
||||
|
||||
/**
|
||||
Returns true if point is less than or equal to radius away from
|
||||
the center.
|
||||
*/
|
||||
bool contains(const Vector3& point) const;
|
||||
|
||||
/**
|
||||
@deprecated Use culledBy(Array<Plane>&)
|
||||
*/
|
||||
bool culledBy(
|
||||
const class Plane* plane,
|
||||
int numPlanes,
|
||||
int32& cullingPlaneIndex,
|
||||
const uint32 testMask,
|
||||
uint32& childMask) const;
|
||||
|
||||
/**
|
||||
@deprecated Use culledBy(Array<Plane>&)
|
||||
*/
|
||||
bool culledBy(
|
||||
const class Plane* plane,
|
||||
int numPlanes,
|
||||
int32& cullingPlaneIndex = dummy,
|
||||
const uint32 testMask = -1) const;
|
||||
|
||||
/**
|
||||
See AABox::culledBy
|
||||
*/
|
||||
bool culledBy(
|
||||
const Array<Plane>& plane,
|
||||
int32& cullingPlaneIndex,
|
||||
const uint32 testMask,
|
||||
uint32& childMask) const;
|
||||
|
||||
/**
|
||||
Conservative culling test that does not produce a mask for children.
|
||||
*/
|
||||
bool culledBy(
|
||||
const Array<Plane>& plane,
|
||||
int32& cullingPlaneIndex = dummy,
|
||||
const uint32 testMask = -1) const;
|
||||
virtual std::string toString() const;
|
||||
|
||||
float volume() const;
|
||||
|
||||
/** @deprecated */
|
||||
float surfaceArea() const;
|
||||
|
||||
inline float area() const {
|
||||
return surfaceArea();
|
||||
}
|
||||
|
||||
/**
|
||||
Uniformly distributed on the surface.
|
||||
*/
|
||||
Vector3 randomSurfacePoint() const;
|
||||
|
||||
/**
|
||||
Uniformly distributed on the interior (includes surface)
|
||||
*/
|
||||
Vector3 randomInteriorPoint() const;
|
||||
|
||||
void getBounds(class AABox& out) const;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
inline unsigned int hashCode(const G3D::Sphere& sphere) {
|
||||
return (unsigned int)(hashCode(sphere.center) + (sphere.radius * 13));
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
@file System.h
|
||||
|
||||
@maintainer Morgan McGuire, [email protected]
|
||||
|
||||
@cite Rob Wyatt http://www.gamasutra.com/features/wyatts_world/19990709/processor_detection_01.htm
|
||||
@cite Benjamin Jurke http://www.flipcode.com/cgi-bin/msg.cgi?showThread=COTD-ProcessorDetectionClass&forum=cotd&id=-1
|
||||
@cite Michael Herf http://www.stereopsis.com/memcpy.html
|
||||
|
||||
@created 2003-01-25
|
||||
@edited 2006-04-26
|
||||
*/
|
||||
|
||||
#ifndef G3D_SYSTEM_H
|
||||
#define G3D_SYSTEM_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include <string>
|
||||
|
||||
#ifdef G3D_OSX
|
||||
# include <CoreServices/CoreServices.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace G3D {
|
||||
|
||||
typedef double RealTime;
|
||||
|
||||
class System {
|
||||
public:
|
||||
|
||||
/** Called automatically by the other System routines.*/
|
||||
static void init();
|
||||
|
||||
/**
|
||||
Guarantees that the start of the array is aligned to the
|
||||
specified number of bytes.
|
||||
*/
|
||||
static void* alignedMalloc(size_t bytes, size_t alignment);
|
||||
|
||||
/**
|
||||
Uses pooled storage to optimize small allocations (1 byte to 5 kilobytes).
|
||||
Can be 10x to 100x faster than calling ::malloc or new.
|
||||
|
||||
The result must be freed with free.
|
||||
|
||||
Threadsafe on Win32.
|
||||
|
||||
@sa calloc realloc OutOfMemoryCallback free
|
||||
*/
|
||||
static void* malloc(size_t bytes);
|
||||
|
||||
static void* calloc(size_t n, size_t x);
|
||||
|
||||
/**
|
||||
@param size Size of memory that the system was trying to allocate
|
||||
@param recoverable If true, the system will attempt to allocate again
|
||||
if the callback returns true. If false, malloc is going to return
|
||||
NULL and this invocation is just to notify the application.
|
||||
@return Return true to force malloc to attempt allocation again if the
|
||||
error was recoverable.
|
||||
*/
|
||||
typedef bool (*OutOfMemoryCallback)(size_t size, bool recoverable);
|
||||
|
||||
/**
|
||||
When System::malloc fails to allocate memory because the system is
|
||||
out of memory, it invokes this handler (if it is not NULL).
|
||||
The argument to the callback is the amount of memory that malloc
|
||||
was trying to allocate when it ran out. If the callback returns
|
||||
true, System::malloc will attempt to allocate the memory again.
|
||||
If the callback returns false, then System::malloc will return NULL.
|
||||
|
||||
You can use outOfMemoryCallback to free data structures or to
|
||||
register the failure.
|
||||
*/
|
||||
static OutOfMemoryCallback outOfMemoryCallback;
|
||||
|
||||
/**
|
||||
Version of realloc that works with System::malloc.
|
||||
*/
|
||||
static void* realloc(void* block, size_t bytes);
|
||||
|
||||
/** Returns a string describing how well System::malloc is using its internal pooled storage.
|
||||
"heap" memory was slow to allocate; the other data sizes are comparatively fast.*/
|
||||
static std::string mallocPerformance();
|
||||
static void resetMallocPerformanceCounters();
|
||||
|
||||
/**
|
||||
Returns a string describing the current usage of the buffer pools used for
|
||||
optimizing System::malloc.
|
||||
*/
|
||||
static std::string mallocStatus();
|
||||
|
||||
/**
|
||||
Free data allocated with System::malloc.
|
||||
|
||||
Threadsafe on Win32.
|
||||
*/
|
||||
static void free(void* p);
|
||||
|
||||
/**
|
||||
Frees memory allocated with alignedMalloc.
|
||||
*/
|
||||
static void alignedFree(void* ptr);
|
||||
|
||||
/** An implementation of memcpy that may be up to 2x as fast as the C library
|
||||
one on some processors. Guaranteed to have the same behavior as memcpy
|
||||
in all cases. */
|
||||
static void memcpy(void* dst, const void* src, size_t numBytes);
|
||||
|
||||
/** An implementation of memset that may be up to 2x as fast as the C library
|
||||
one on some processors. Guaranteed to have the same behavior as memset
|
||||
in all cases. */
|
||||
static void memset(void* dst, uint8 value, size_t numBytes);
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,695 @@
|
||||
/**
|
||||
@file Table.h
|
||||
|
||||
Templated hash table class.
|
||||
|
||||
@maintainer Morgan McGuire, [email protected]
|
||||
@created 2001-04-22
|
||||
@edited 2006-10-14
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_TABLE_H
|
||||
#define G3D_TABLE_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/debug.h"
|
||||
#include "G3D/System.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/Crypto.h"
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
|
||||
#ifdef G3D_WIN32
|
||||
# pragma warning (push)
|
||||
// Debug name too long warning
|
||||
# pragma warning (disable : 4786)
|
||||
#endif
|
||||
|
||||
|
||||
template<typename Key>
|
||||
struct GHashCode{};
|
||||
|
||||
template <>
|
||||
struct GHashCode<int>
|
||||
{
|
||||
size_t operator()(int key) const { return static_cast<size_t>(key); }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct GHashCode<G3D::uint32>
|
||||
{
|
||||
size_t operator()(G3D::uint32 key) const { return static_cast<size_t>(key); }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct GHashCode<G3D::uint64>
|
||||
{
|
||||
size_t operator()(G3D::uint64 key) const { return static_cast<size_t>(key); }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct GHashCode<void*>
|
||||
{
|
||||
size_t operator()(const void* key) const { return reinterpret_cast<size_t>(key); }
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct GHashCode<T*>
|
||||
{
|
||||
size_t operator()(const T* key) const { return reinterpret_cast<size_t>(key); }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct GHashCode<const std::string>
|
||||
{
|
||||
size_t operator()(const std::string& key) const { return static_cast<size_t>(G3D::Crypto::crc32(key.c_str(), key.size())); }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct GHashCode<std::string>
|
||||
{
|
||||
size_t operator()(const std::string& key) const { return static_cast<size_t>(G3D::Crypto::crc32(key.c_str(), key.size())); }
|
||||
};
|
||||
|
||||
namespace G3D {
|
||||
|
||||
|
||||
/**
|
||||
An unordered data structure mapping keys to values.
|
||||
|
||||
Key must be a pointer, an int, a std::string, a class with a hashCode() method,
|
||||
or provide overloads for:
|
||||
|
||||
<PRE>
|
||||
template<> struct GHashCode<class Key> {
|
||||
size_t operator()(Key key) const { return reinterpret_cast<size_t>( ... ); }
|
||||
};
|
||||
|
||||
bool operator==(const Key&, const Key&);
|
||||
</PRE>
|
||||
|
||||
G3D pre-defines GHashCode functions for common types (like <CODE>int</CODE> and <CODE>std::string</CODE>).
|
||||
If you use a Table with a different type you must write those functions yourself. For example,
|
||||
an enum would use:
|
||||
|
||||
<PRE>
|
||||
template<> struct GHashCode<MyEnum> {
|
||||
size_t operator()(MyEnum key) const { return reinterpret_cast<size_t>( key ); }
|
||||
};
|
||||
</PRE>
|
||||
|
||||
And rely on the default enum operator==.
|
||||
|
||||
|
||||
Periodically check that debugGetLoad() is low (> 0.1). When it gets near
|
||||
1.0 your hash function is badly designed and maps too many inputs to
|
||||
the same output.
|
||||
*/
|
||||
template<class Key, class Value, class HashFunc = GHashCode<Key> >
|
||||
class Table {
|
||||
public:
|
||||
|
||||
/**
|
||||
The pairs returned by iterator.
|
||||
*/
|
||||
class Entry {
|
||||
public:
|
||||
Key key;
|
||||
Value value;
|
||||
};
|
||||
|
||||
private:
|
||||
/**
|
||||
Linked list nodes used internally by HashTable.
|
||||
*/
|
||||
class Node {
|
||||
public:
|
||||
size_t hashCode;
|
||||
Entry entry;
|
||||
Node* next;
|
||||
|
||||
|
||||
/** Provide pooled allocation for speed. */
|
||||
inline void* operator new (size_t size) {
|
||||
return System::malloc(size);
|
||||
}
|
||||
|
||||
inline void operator delete (void* p) {
|
||||
System::free(p);
|
||||
}
|
||||
|
||||
|
||||
Node(Key key, Value value, size_t hashCode, Node* next) {
|
||||
this->entry.key = key;
|
||||
this->entry.value = value;
|
||||
this->hashCode = hashCode;
|
||||
this->next = next;
|
||||
}
|
||||
|
||||
/**
|
||||
Clones a whole chain;
|
||||
*/
|
||||
Node* clone() {
|
||||
return new Node(this->entry.key, this->entry.value, hashCode, (next == NULL) ? NULL : next->clone());
|
||||
}
|
||||
};
|
||||
|
||||
HashFunc m_HashFunc;
|
||||
|
||||
/**
|
||||
Number of elements in the table.
|
||||
*/
|
||||
size_t _size;
|
||||
|
||||
/**
|
||||
Array of Node*.
|
||||
We don't use Array<Node*> because Table is lower level.
|
||||
Some elements may be NULL.
|
||||
*/
|
||||
Node** bucket;
|
||||
|
||||
/**
|
||||
Length of the bucket array.
|
||||
*/
|
||||
size_t numBuckets;
|
||||
|
||||
/**
|
||||
Re-hashes for a larger bucket size.
|
||||
*/
|
||||
void resize(size_t numBuckets) {
|
||||
|
||||
Node** oldBucket = bucket;
|
||||
bucket = (Node**)System::alignedMalloc(sizeof(Node*) * numBuckets, 16);
|
||||
System::memset(bucket, 0, sizeof(Node*) * numBuckets);
|
||||
|
||||
for (size_t b = 0; b < this->numBuckets; b++) {
|
||||
Node* node = oldBucket[b];
|
||||
|
||||
while (node != NULL) {
|
||||
Node* nextNode = node->next;
|
||||
|
||||
// insert at the head of the list for bucket[i]
|
||||
size_t i = node->hashCode % numBuckets;
|
||||
node->next = bucket[i];
|
||||
bucket[i] = node;
|
||||
|
||||
node = nextNode;
|
||||
}
|
||||
}
|
||||
|
||||
System::alignedFree(oldBucket);
|
||||
this->numBuckets = numBuckets;
|
||||
}
|
||||
|
||||
void copyFrom(const Table<Key, Value>& h) {
|
||||
this->_size = h._size;
|
||||
this->numBuckets = h.numBuckets;
|
||||
this->bucket = (Node**)System::alignedMalloc(sizeof(Node*) * numBuckets, 16);
|
||||
System::memset(this->bucket, 0, sizeof(Node*) * numBuckets);
|
||||
for (size_t b = 0; b < this->numBuckets; b++) {
|
||||
if (h.bucket[b] != NULL) {
|
||||
bucket[b] = h.bucket[b]->clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Frees the heap structures for the nodes.
|
||||
*/
|
||||
void freeMemory() {
|
||||
for (size_t b = 0; b < numBuckets; b++) {
|
||||
Node* node = bucket[b];
|
||||
while (node != NULL) {
|
||||
Node* next = node->next;
|
||||
delete node;
|
||||
node = next;
|
||||
}
|
||||
}
|
||||
System::alignedFree(bucket);
|
||||
bucket = NULL;
|
||||
numBuckets = 0;
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
Creates an empty hash table. This causes some heap allocation to occur.
|
||||
*/
|
||||
Table() {
|
||||
numBuckets = 10;
|
||||
_size = 0;
|
||||
bucket = (Node**)System::alignedMalloc(sizeof(Node*) * numBuckets, 16);
|
||||
System::memset(bucket, 0, sizeof(Node*) * numBuckets);
|
||||
}
|
||||
|
||||
/**
|
||||
Destroys all of the memory allocated by the table, but does <B>not</B>
|
||||
call delete on keys or values if they are pointers. If you want to
|
||||
deallocate things that the table points at, use getKeys() and Array::deleteAll()
|
||||
to delete them.
|
||||
*/
|
||||
virtual ~Table() {
|
||||
freeMemory();
|
||||
}
|
||||
|
||||
Table(const Table<Key, Value>& h) {
|
||||
this->copyFrom(h);
|
||||
}
|
||||
|
||||
Table& operator=(const Table<Key, Value>& h) {
|
||||
// No need to copy if the argument is this
|
||||
if (this != &h) {
|
||||
// Free the existing nodes
|
||||
freeMemory();
|
||||
this->copyFrom(h);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the length of the deepest bucket.
|
||||
*/
|
||||
size_t debugGetDeepestBucketSize() const {
|
||||
size_t deepest = 0;
|
||||
|
||||
for (size_t b = 0; b < numBuckets; b++) {
|
||||
size_t count = 0;
|
||||
Node* node = bucket[b];
|
||||
while (node != NULL) {
|
||||
node = node->next;
|
||||
++count;
|
||||
}
|
||||
|
||||
if (count > deepest) {
|
||||
deepest = count;
|
||||
}
|
||||
}
|
||||
|
||||
return deepest;
|
||||
}
|
||||
|
||||
/**
|
||||
A small load (close to zero) means the hash table is acting very
|
||||
efficiently most of the time. A large load (close to 1) means
|
||||
the hash table is acting poorly-- all operations will be very slow.
|
||||
A large load will result from a bad hash function that maps too
|
||||
many keys to the same code.
|
||||
*/
|
||||
double debugGetLoad() const {
|
||||
return debugGetDeepestBucketSize() / (double)size();
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the number of buckets.
|
||||
*/
|
||||
size_t debugGetNumBuckets() const {
|
||||
return numBuckets;
|
||||
}
|
||||
|
||||
/**
|
||||
C++ STL style iterator variable. See begin().
|
||||
*/
|
||||
class Iterator {
|
||||
private:
|
||||
friend class Table<Key, Value>;
|
||||
|
||||
/**
|
||||
Bucket index.
|
||||
*/
|
||||
size_t index;
|
||||
|
||||
/**
|
||||
Linked list node.
|
||||
*/
|
||||
Node* node;
|
||||
Table<Key, Value>* table;
|
||||
size_t numBuckets;
|
||||
Node** bucket;
|
||||
bool isDone;
|
||||
|
||||
/**
|
||||
Creates the end iterator.
|
||||
*/
|
||||
Iterator(const Table<Key, Value>* table) : table(const_cast<Table<Key, Value>*>(table)) {
|
||||
isDone = true;
|
||||
}
|
||||
|
||||
Iterator(const Table<Key, Value>* table, size_t numBuckets, Node** bucket) :
|
||||
table(const_cast<Table<Key, Value>*>(table)),
|
||||
numBuckets(numBuckets),
|
||||
bucket(bucket) {
|
||||
|
||||
if (numBuckets == 0) {
|
||||
// Empty table
|
||||
isDone = true;
|
||||
return;
|
||||
}
|
||||
|
||||
index = 0;
|
||||
node = bucket[index];
|
||||
isDone = false;
|
||||
findNext();
|
||||
}
|
||||
|
||||
/**
|
||||
Finds the next element, setting isDone if one can't be found.
|
||||
Looks at the current element first.
|
||||
*/
|
||||
void findNext() {
|
||||
while (node == NULL) {
|
||||
index++;
|
||||
if (index >= numBuckets) {
|
||||
isDone = true;
|
||||
break;
|
||||
} else {
|
||||
node = bucket[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
inline bool operator!=(const Iterator& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
bool operator==(const Iterator& other) const {
|
||||
if (other.isDone || isDone) {
|
||||
// Common case; check against isDone.
|
||||
return (isDone == other.isDone) && (other.table == table);
|
||||
} else {
|
||||
return
|
||||
(table == other.table) &&
|
||||
(node == other.node) &&
|
||||
(index == other.index);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Pre increment.
|
||||
*/
|
||||
Iterator& operator++() {
|
||||
node = node->next;
|
||||
findNext();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
Post increment (slower than preincrement).
|
||||
*/
|
||||
Iterator operator++(int) {
|
||||
Iterator old = *this;
|
||||
++(*this);
|
||||
return old;
|
||||
}
|
||||
|
||||
const Entry& operator*() const {
|
||||
return node->entry;
|
||||
}
|
||||
|
||||
Entry* operator->() const {
|
||||
return &(node->entry);
|
||||
}
|
||||
|
||||
operator Entry*() const {
|
||||
return &(node->entry);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
C++ STL style iterator method. Returns the first Entry, which
|
||||
contains a key and value. Use preincrement (++entry) to get to
|
||||
the next element. Do not modify the table while iterating.
|
||||
*/
|
||||
Iterator begin() const {
|
||||
return Iterator(this, numBuckets, bucket);
|
||||
}
|
||||
|
||||
/**
|
||||
C++ STL style iterator method. Returns one after the last iterator
|
||||
element.
|
||||
*/
|
||||
const Iterator end() const {
|
||||
return Iterator(this);
|
||||
}
|
||||
|
||||
/**
|
||||
Removes all elements
|
||||
*/
|
||||
void clear() {
|
||||
freeMemory();
|
||||
numBuckets = 20;
|
||||
_size = 0;
|
||||
bucket = (Node**)System::alignedMalloc(sizeof(Node*) * numBuckets, 16);
|
||||
System::memset(bucket, 0, sizeof(Node*) * numBuckets);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Returns the number of keys.
|
||||
*/
|
||||
size_t size() const {
|
||||
return _size;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
If you insert a pointer into the key or value of a table, you are
|
||||
responsible for deallocating the object eventually. Inserting
|
||||
key into a table is O(1), but may cause a potentially slow rehashing.
|
||||
*/
|
||||
void set(const Key& key, const Value& value) {
|
||||
size_t code = m_HashFunc(key);
|
||||
size_t b = code % numBuckets;
|
||||
|
||||
// Go to the bucket
|
||||
Node* n = bucket[b];
|
||||
|
||||
// No bucket, so this must be the first
|
||||
if (n == NULL) {
|
||||
bucket[b] = new Node(key, value, code, NULL);
|
||||
++_size;
|
||||
return;
|
||||
}
|
||||
|
||||
size_t bucketLength = 1;
|
||||
|
||||
// Sometimes a bad hash code will cause all elements
|
||||
// to collide. Detect this case and don't rehash when
|
||||
// it occurs; nothing good will come from the rehashing.
|
||||
bool allSameCode = true;
|
||||
|
||||
// Try to find the node
|
||||
do {
|
||||
allSameCode = allSameCode && (code == n->hashCode);
|
||||
|
||||
if ((code == n->hashCode) && (n->entry.key == key)) {
|
||||
// Replace the existing node.
|
||||
n->entry.value = value;
|
||||
return;
|
||||
}
|
||||
|
||||
n = n->next;
|
||||
++bucketLength;
|
||||
} while (n != NULL);
|
||||
|
||||
const size_t maxBucketLength = 5;
|
||||
if ((bucketLength > maxBucketLength) & ! allSameCode && (numBuckets < _size * 20)) {
|
||||
// This bucket was really large; rehash if all elements
|
||||
// don't have the same hashcode the number of buckets is reasonable.
|
||||
resize(numBuckets * 2 + 1);
|
||||
}
|
||||
|
||||
// Not found; insert at the head.
|
||||
b = code % numBuckets;
|
||||
bucket[b] = new Node(key, value, code, bucket[b]);
|
||||
++_size;
|
||||
}
|
||||
|
||||
/**
|
||||
Removes an element from the table if it is present. It is an error
|
||||
to remove an element that isn't present.
|
||||
*/
|
||||
void remove(const Key& key) {
|
||||
|
||||
size_t code = m_HashFunc(key);
|
||||
size_t b = code % numBuckets;
|
||||
|
||||
// Go to the bucket
|
||||
Node* n = bucket[b];
|
||||
|
||||
// Make sure it was found
|
||||
alwaysAssertM(n != NULL, "Tried to remove a key that was not in the table.");
|
||||
|
||||
Node* previous = NULL;
|
||||
|
||||
// Try to find the node
|
||||
do {
|
||||
if ((code == n->hashCode) && (n->entry.key == key)) {
|
||||
// This is the node; remove it
|
||||
if (previous == NULL) {
|
||||
bucket[b] = n->next;
|
||||
} else {
|
||||
previous->next = n->next;
|
||||
}
|
||||
// Delete the node
|
||||
delete n;
|
||||
--_size;
|
||||
return;
|
||||
}
|
||||
|
||||
previous = n;
|
||||
n = n->next;
|
||||
} while (n != NULL);
|
||||
|
||||
|
||||
alwaysAssertM(false, "Tried to remove a key that was not in the table.");
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the value associated with key.
|
||||
@deprecated Use get(key, val) or
|
||||
*/
|
||||
Value& get(const Key& key) const {
|
||||
|
||||
size_t code = m_HashFunc(key);
|
||||
size_t b = code % numBuckets;
|
||||
|
||||
Node* node = bucket[b];
|
||||
|
||||
while (node != NULL) {
|
||||
if ((node->hashCode == code) && (node->entry.key == key)) {
|
||||
return node->entry.value;
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
debugAssertM(false, "Key not found");
|
||||
// The next line is here just to make
|
||||
// a compiler warning go away.
|
||||
return node->entry.value;
|
||||
}
|
||||
|
||||
/**
|
||||
If the key is present in the table, val is set to the associated value and returns true.
|
||||
If the key is not present, returns false.
|
||||
*/
|
||||
bool get(const Key& key, Value& val) const {
|
||||
size_t code = m_HashFunc(key);
|
||||
size_t b = code % numBuckets;
|
||||
|
||||
Node* node = bucket[b];
|
||||
|
||||
while (node != NULL) {
|
||||
if ((node->hashCode == code) && (node->entry.key == key)) {
|
||||
// found key
|
||||
val = node->entry.value;
|
||||
return true;
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
// Failed to find key
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns true if key is in the table.
|
||||
*/
|
||||
bool containsKey(const Key& key) const {
|
||||
size_t code = m_HashFunc(key);
|
||||
size_t b = code % numBuckets;
|
||||
|
||||
Node* node = bucket[b];
|
||||
|
||||
while (node != NULL) {
|
||||
if ((node->hashCode == code) && (node->entry.key == key)) {
|
||||
return true;
|
||||
}
|
||||
node = node->next;
|
||||
} while (node != NULL);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Short syntax for get.
|
||||
*/
|
||||
inline Value& operator[](const Key &key) const {
|
||||
return get(key);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Returns an array of all of the keys in the table.
|
||||
You can iterate over the keys to get the values.
|
||||
*/
|
||||
Array<Key> getKeys() const {
|
||||
Array<Key> keyArray;
|
||||
getKeys(keyArray);
|
||||
return keyArray;
|
||||
}
|
||||
|
||||
void getKeys(Array<Key>& keyArray) const {
|
||||
keyArray.resize(0, DONT_SHRINK_UNDERLYING_ARRAY);
|
||||
for (size_t i = 0; i < numBuckets; i++) {
|
||||
Node* node = bucket[i];
|
||||
while (node != NULL) {
|
||||
keyArray.append(node->entry.key);
|
||||
node = node->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Calls delete on all of the keys. Does not clear the table,
|
||||
however, so you are left with a table of dangling pointers.
|
||||
|
||||
Same as <CODE>getKeys().deleteAll();</CODE>
|
||||
|
||||
To delete all of the values, you may want something like
|
||||
<PRE>
|
||||
Array<Key> keys = table.getKeys();
|
||||
Set<Value> value;
|
||||
for (int k = 0; k < keys.length(); k++) {
|
||||
value.insert(keys[k]);
|
||||
}
|
||||
value.getMembers().deleteAll();
|
||||
keys.deleteAll();
|
||||
</PRE>
|
||||
*/
|
||||
void deleteKeys() {
|
||||
getKeys().deleteAll();
|
||||
}
|
||||
|
||||
/**
|
||||
Calls delete on all of the values. This is unsafe--
|
||||
do not call unless you know that each value appears
|
||||
at most once.
|
||||
|
||||
Does not clear the table, so you are left with a table
|
||||
of dangling pointers.
|
||||
*/
|
||||
void deleteValues() {
|
||||
for (int i = 0; i < numBuckets; i++) {
|
||||
Node* node = bucket[i];
|
||||
while (node != NULL) {
|
||||
delete node->entry.value;
|
||||
node = node->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#ifdef G3D_WIN32
|
||||
# pragma warning (pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
@file Triangle.h
|
||||
|
||||
@maintainer Morgan McGuire, [email protected]
|
||||
|
||||
@created 2003-04-05
|
||||
@edited 2004-03-14
|
||||
|
||||
@cite Random point method by Greg Turk, Generating random points in triangles. In A. S. Glassner, ed., Graphics Gems, pp. 24-28. Academic Press, 1990
|
||||
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_TRIANGLE_H
|
||||
#define G3D_TRIANGLE_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Plane.h"
|
||||
#include <string>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
A generic triangle representation. This should not be used
|
||||
as the underlying triangle for creating models; it is intended
|
||||
for providing fast property queries but requires a lot of
|
||||
storage and is mostly immutable.
|
||||
*/
|
||||
class Triangle {
|
||||
private:
|
||||
friend class CollisionDetection;
|
||||
friend class Ray;
|
||||
|
||||
Vector3 _vertex[3];
|
||||
|
||||
/** edgeDirection[i] is the normalized vector v[i+1] - v[i] */
|
||||
Vector3 edgeDirection[3];
|
||||
double edgeMagnitude[3];
|
||||
Plane _plane;
|
||||
Vector3::Axis _primaryAxis;
|
||||
|
||||
/** vertex[1] - vertex[0] */
|
||||
Vector3 edge01;
|
||||
/** vertex[2] - vertex[0] */
|
||||
Vector3 edge02;
|
||||
|
||||
float _area;
|
||||
|
||||
void init(const Vector3& v0, const Vector3& v1, const Vector3& v2);
|
||||
|
||||
public:
|
||||
|
||||
Triangle();
|
||||
|
||||
Triangle(const Vector3& v0, const Vector3& v1, const Vector3& v2);
|
||||
|
||||
~Triangle();
|
||||
|
||||
/** 0, 1, or 2 */
|
||||
inline const Vector3& vertex(int n) const {
|
||||
debugAssert((n >= 0) && (n < 3));
|
||||
return _vertex[n];
|
||||
}
|
||||
|
||||
double area() const;
|
||||
|
||||
Vector3::Axis primaryAxis() const {
|
||||
return _primaryAxis;
|
||||
}
|
||||
|
||||
const Vector3& normal() const;
|
||||
|
||||
/** Barycenter */
|
||||
Vector3 center() const;
|
||||
|
||||
const Plane& plane() const;
|
||||
|
||||
/** Returns a random point in the triangle. */
|
||||
Vector3 randomPoint() const;
|
||||
|
||||
/**
|
||||
For two triangles to be equal they must have
|
||||
the same vertices <I>in the same order</I>.
|
||||
That is, vertex[0] == vertex[0], etc.
|
||||
*/
|
||||
inline bool operator==(const Triangle& other) const {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
if (_vertex[i] != other._vertex[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline unsigned int hashCode() const {
|
||||
return
|
||||
_vertex[0].hashCode() +
|
||||
(_vertex[1].hashCode() >> 2) +
|
||||
_vertex[2].hashCode();
|
||||
}
|
||||
|
||||
void getBounds(class AABox&) const;
|
||||
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
inline unsigned int hashCode(const G3D::Triangle& t) {
|
||||
return t.hashCode();
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,438 @@
|
||||
/**
|
||||
@file Vector2.h
|
||||
|
||||
2D vector class
|
||||
|
||||
@maintainer Morgan McGuire, [email protected]
|
||||
|
||||
@created 2001-06-02
|
||||
@edited 2006-01-14
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_VECTOR2_H
|
||||
#define G3D_VECTOR2_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "Vector2int16.h"
|
||||
#include <string>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class Vector2;
|
||||
class Vector3;
|
||||
class Vector4;
|
||||
|
||||
/**
|
||||
Do not subclass-- this implementation makes assumptions about the
|
||||
memory layout.
|
||||
*/
|
||||
class Vector2 {
|
||||
private:
|
||||
// Hidden operators
|
||||
bool operator<(const Vector2&) const;
|
||||
bool operator>(const Vector2&) const;
|
||||
bool operator<=(const Vector2&) const;
|
||||
bool operator>=(const Vector2&) const;
|
||||
|
||||
public:
|
||||
// coordinates
|
||||
float x, y;
|
||||
|
||||
// construction
|
||||
Vector2();
|
||||
Vector2(float x, float y);
|
||||
Vector2(float coordinate[2]);
|
||||
Vector2(double coordinate[2]);
|
||||
Vector2(const Vector2& rkVector);
|
||||
Vector2(const class Vector2int16& v);
|
||||
|
||||
float& operator[] (int i);
|
||||
const float& operator[] (int i) const;
|
||||
operator float* ();
|
||||
operator const float* () const;
|
||||
|
||||
// assignment and comparison
|
||||
Vector2& operator= (const Vector2& rkVector);
|
||||
bool operator== (const Vector2& rkVector) const;
|
||||
bool operator!= (const Vector2& rkVector) const;
|
||||
unsigned int hashCode() const;
|
||||
bool fuzzyEq(const Vector2& other) const;
|
||||
bool fuzzyNe(const Vector2& other) const;
|
||||
/** Returns true if this vector has finite length */
|
||||
bool isFinite() const;
|
||||
|
||||
/** Returns true if this vector has length == 0 */
|
||||
bool isZero() const;
|
||||
|
||||
/** Returns true if this vector has length == 1 */
|
||||
bool isUnit() const;
|
||||
|
||||
// arithmetic operations
|
||||
Vector2 operator+ (const Vector2& rkVector) const;
|
||||
Vector2 operator- (const Vector2& rkVector) const;
|
||||
Vector2 operator* (float fScalar) const;
|
||||
Vector2 operator* (const Vector2& rkVector) const;
|
||||
Vector2 operator/ (const Vector2& rkVector) const;
|
||||
Vector2 operator/ (float fScalar) const;
|
||||
Vector2 operator- () const;
|
||||
|
||||
inline float sum() const {
|
||||
return x + y;
|
||||
}
|
||||
|
||||
/**
|
||||
Linear interpolation
|
||||
*/
|
||||
inline Vector2 lerp(const Vector2& v, float alpha) const {
|
||||
return (*this) + (v - *this) * alpha;
|
||||
}
|
||||
|
||||
inline Vector2 clamp(const Vector2& low, const Vector2& high) const {
|
||||
return Vector2(
|
||||
G3D::clamp(x, low.x, high.x),
|
||||
G3D::clamp(y, low.y, high.y));
|
||||
}
|
||||
|
||||
inline Vector2 clamp(float low, float high) const {
|
||||
return Vector2(
|
||||
(float)G3D::clamp(x, low, high),
|
||||
(float)G3D::clamp(y, low, high));
|
||||
}
|
||||
|
||||
// arithmetic updates
|
||||
Vector2& operator+= (const Vector2& rkVector);
|
||||
Vector2& operator-= (const Vector2& rkVector);
|
||||
Vector2& operator*= (float fScalar);
|
||||
Vector2& operator/= (float fScalar);
|
||||
Vector2& operator*= (const Vector2& rkVector);
|
||||
Vector2& operator/= (const Vector2& rkVector);
|
||||
|
||||
// vector operations
|
||||
float length() const;
|
||||
Vector2 direction() const;
|
||||
/**
|
||||
Potentially less accurate but faster than direction().
|
||||
Only works if System::hasSSE is true.
|
||||
*/
|
||||
Vector2 fastDirection() const {
|
||||
return direction();
|
||||
}
|
||||
|
||||
float squaredLength () const;
|
||||
float dot (const Vector2& rkVector) const;
|
||||
float unitize (float fTolerance = 1e-06);
|
||||
|
||||
Vector2 min(const Vector2 &v) const;
|
||||
Vector2 max(const Vector2 &v) const;
|
||||
|
||||
// Random unit vector
|
||||
static Vector2 random();
|
||||
|
||||
// Special values.
|
||||
// Intentionally not inlined: see Matrix3::identity() for details.
|
||||
static const Vector2& zero();
|
||||
inline static const Vector2& one() { static const Vector2 v(1, 1); return v; }
|
||||
static const Vector2& unitX();
|
||||
static const Vector2& unitY();
|
||||
static const Vector2& inf();
|
||||
static const Vector2& nan();
|
||||
/** smallest (most negative) representable vector */
|
||||
static const Vector2& minFinite();
|
||||
/** Largest representable vector */
|
||||
static const Vector2& maxFinite();
|
||||
|
||||
|
||||
|
||||
// Deprecated. See Matrix3::identity() for details.
|
||||
/** @deprecated Use Vector2::zero() */
|
||||
static const Vector2 ZERO;
|
||||
/** @deprecated Use Vector2::unitX() */
|
||||
static const Vector2 UNIT_S;
|
||||
/** @deprecated Use Vector2::unitY() */
|
||||
static const Vector2 UNIT_T;
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
// 2-char swizzles
|
||||
|
||||
Vector2 xx() const;
|
||||
Vector2 yx() const;
|
||||
Vector2 xy() const;
|
||||
Vector2 yy() const;
|
||||
|
||||
// 3-char swizzles
|
||||
|
||||
Vector3 xxx() const;
|
||||
Vector3 yxx() const;
|
||||
Vector3 xyx() const;
|
||||
Vector3 yyx() const;
|
||||
Vector3 xxy() const;
|
||||
Vector3 yxy() const;
|
||||
Vector3 xyy() const;
|
||||
Vector3 yyy() const;
|
||||
|
||||
// 4-char swizzles
|
||||
|
||||
Vector4 xxxx() const;
|
||||
Vector4 yxxx() const;
|
||||
Vector4 xyxx() const;
|
||||
Vector4 yyxx() const;
|
||||
Vector4 xxyx() const;
|
||||
Vector4 yxyx() const;
|
||||
Vector4 xyyx() const;
|
||||
Vector4 yyyx() const;
|
||||
Vector4 xxxy() const;
|
||||
Vector4 yxxy() const;
|
||||
Vector4 xyxy() const;
|
||||
Vector4 yyxy() const;
|
||||
Vector4 xxyy() const;
|
||||
Vector4 yxyy() const;
|
||||
Vector4 xyyy() const;
|
||||
Vector4 yyyy() const;
|
||||
|
||||
};
|
||||
|
||||
inline Vector2 operator*(double s, const Vector2& v) {
|
||||
return v * (float)s;
|
||||
}
|
||||
|
||||
inline Vector2 operator*(float s, const Vector2& v) {
|
||||
return v * s;
|
||||
}
|
||||
|
||||
inline Vector2 operator*(int s, const Vector2& v) {
|
||||
return v * (float)s;
|
||||
}
|
||||
|
||||
|
||||
inline unsigned int hashCode(const G3D::Vector2& v) {
|
||||
return v.hashCode();
|
||||
}
|
||||
|
||||
|
||||
inline Vector2::Vector2 () : x(0.0f), y(0.0f) {
|
||||
}
|
||||
|
||||
|
||||
inline Vector2::Vector2(float _x, float _y) : x(_x), y(_y) {
|
||||
}
|
||||
|
||||
|
||||
inline Vector2::Vector2 (float afCoordinate[2]) {
|
||||
x = afCoordinate[0];
|
||||
y = afCoordinate[1];
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Vector2::Vector2 (double afCoordinate[2]) {
|
||||
x = (float)afCoordinate[0];
|
||||
y = (float)afCoordinate[1];
|
||||
}
|
||||
|
||||
|
||||
inline Vector2::Vector2 (const Vector2& rkVector) {
|
||||
x = rkVector.x;
|
||||
y = rkVector.y;
|
||||
}
|
||||
|
||||
|
||||
inline Vector2::Vector2 (const Vector2int16& v) : x(v.x), y(v.y) {
|
||||
}
|
||||
|
||||
|
||||
inline float& Vector2::operator[] (int i) {
|
||||
return ((float*)this)[i];
|
||||
}
|
||||
|
||||
|
||||
inline const float& Vector2::operator[] (int i) const {
|
||||
return ((float*)this)[i];
|
||||
}
|
||||
|
||||
|
||||
inline Vector2::operator float* () {
|
||||
return (float*)this;
|
||||
}
|
||||
|
||||
inline Vector2::operator const float* () const {
|
||||
return (float*)this;
|
||||
}
|
||||
|
||||
|
||||
inline Vector2& Vector2::operator= (const Vector2& rkVector) {
|
||||
x = rkVector.x;
|
||||
y = rkVector.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
inline bool Vector2::operator== (const Vector2& rkVector) const {
|
||||
return ( x == rkVector.x && y == rkVector.y);
|
||||
}
|
||||
|
||||
|
||||
inline bool Vector2::operator!= (const Vector2& rkVector) const {
|
||||
return ( x != rkVector.x || y != rkVector.y);
|
||||
}
|
||||
|
||||
|
||||
inline Vector2 Vector2::operator+ (const Vector2& rkVector) const {
|
||||
return Vector2(x + rkVector.x, y + rkVector.y);
|
||||
}
|
||||
|
||||
|
||||
inline Vector2 Vector2::operator- (const Vector2& rkVector) const {
|
||||
return Vector2(x - rkVector.x, y - rkVector.y);
|
||||
}
|
||||
|
||||
|
||||
inline Vector2 Vector2::operator* (float fScalar) const {
|
||||
return Vector2(fScalar*x, fScalar*y);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Vector2 Vector2::operator- () const {
|
||||
return Vector2( -x, -y);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Vector2& Vector2::operator+= (const Vector2& rkVector) {
|
||||
x += rkVector.x;
|
||||
y += rkVector.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Vector2& Vector2::operator-= (const Vector2& rkVector) {
|
||||
x -= rkVector.x;
|
||||
y -= rkVector.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Vector2& Vector2::operator*= (float fScalar) {
|
||||
x *= fScalar;
|
||||
y *= fScalar;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
inline Vector2& Vector2::operator*= (const Vector2& rkVector) {
|
||||
x *= rkVector.x;
|
||||
y *= rkVector.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Vector2& Vector2::operator/= (const Vector2& rkVector) {
|
||||
x /= rkVector.x;
|
||||
y /= rkVector.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
inline Vector2 Vector2::operator* (const Vector2& rkVector) const {
|
||||
return Vector2(x * rkVector.x, y * rkVector.y);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Vector2 Vector2::operator/ (const Vector2& rkVector) const {
|
||||
return Vector2(x / rkVector.x, y / rkVector.y);
|
||||
}
|
||||
|
||||
|
||||
inline float Vector2::squaredLength () const {
|
||||
return x*x + y*y;
|
||||
}
|
||||
|
||||
|
||||
inline float Vector2::length () const {
|
||||
return sqrtf(x*x + y*y);
|
||||
}
|
||||
|
||||
|
||||
inline Vector2 Vector2::direction () const {
|
||||
float lenSquared = x * x + y * y;
|
||||
|
||||
if (lenSquared != 1.0f) {
|
||||
return *this / sqrtf(lenSquared);
|
||||
} else {
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline float Vector2::dot (const Vector2& rkVector) const {
|
||||
return x*rkVector.x + y*rkVector.y;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Vector2 Vector2::min(const Vector2 &v) const {
|
||||
return Vector2(G3D::min(v.x, x), G3D::min(v.y, y));
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Vector2 Vector2::max(const Vector2 &v) const {
|
||||
return Vector2(G3D::max(v.x, x), G3D::max(v.y, y));
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline bool Vector2::fuzzyEq(const Vector2& other) const {
|
||||
return G3D::fuzzyEq((*this - other).squaredLength(), 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline bool Vector2::fuzzyNe(const Vector2& other) const {
|
||||
return G3D::fuzzyNe((*this - other).squaredLength(), 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline bool Vector2::isFinite() const {
|
||||
return G3D::isFinite(x) && G3D::isFinite(y);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline bool Vector2::isZero() const {
|
||||
return (x == 0.0f) && (y == 0.0f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline bool Vector2::isUnit() const {
|
||||
return squaredLength() == 1.0f;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Intentionally outside namespace to avoid operator overloading confusion
|
||||
inline G3D::Vector2 operator*(double s, const G3D::Vector2& v) {
|
||||
return v * (float)s;
|
||||
}
|
||||
inline G3D::Vector2 operator*(int s, const G3D::Vector2& v) {
|
||||
return v * (float)s;
|
||||
}
|
||||
|
||||
|
||||
inline unsigned int hashCode(const G3D::Vector2& v);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
@file Vector2.inl
|
||||
|
||||
@maintainer Morgan McGuire, [email protected]
|
||||
@cite Portions by Laura Wollstadt, graphics3d.com
|
||||
|
||||
@cite Portions based on Dave Eberly'x Magic Software Library
|
||||
at http://www.magic-software.com
|
||||
|
||||
|
||||
@created 2001-06-02
|
||||
@edited 2006-01-14
|
||||
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
@file Vector2int16.h
|
||||
|
||||
@maintainer Morgan McGuire, [email protected]
|
||||
|
||||
@created 2003-08-09
|
||||
@edited 2004-01-03
|
||||
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef VECTOR2INT16_H
|
||||
#define VECTOR2INT16_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
A Vector2 that packs its fields into uint16s.
|
||||
*/
|
||||
#ifdef G3D_WIN32
|
||||
// Switch to tight alignment
|
||||
#pragma pack(push, 2)
|
||||
#endif
|
||||
|
||||
class Vector2int16 {
|
||||
private:
|
||||
// Hidden operators
|
||||
bool operator<(const Vector2int16&) const;
|
||||
bool operator>(const Vector2int16&) const;
|
||||
bool operator<=(const Vector2int16&) const;
|
||||
bool operator>=(const Vector2int16&) const;
|
||||
|
||||
public:
|
||||
G3D::int16 x;
|
||||
G3D::int16 y;
|
||||
|
||||
Vector2int16() : x(0), y(0) {}
|
||||
Vector2int16(G3D::int16 _x, G3D::int16 _y) : x(_x), y(_y){}
|
||||
Vector2int16(const class Vector2& v);
|
||||
|
||||
inline G3D::int16& operator[] (int i) {
|
||||
debugAssert(((unsigned int)i) <= 1);
|
||||
return ((G3D::int16*)this)[i];
|
||||
}
|
||||
|
||||
inline const G3D::int16& operator[] (int i) const {
|
||||
debugAssert(((unsigned int)i) <= 1);
|
||||
return ((G3D::int16*)this)[i];
|
||||
}
|
||||
|
||||
|
||||
inline bool operator== (const Vector2int16& rkVector) const {
|
||||
return ((int32*)this)[0] == ((int32*)&rkVector)[0];
|
||||
}
|
||||
|
||||
inline bool operator!= (const Vector2int16& rkVector) const {
|
||||
return ((int32*)this)[0] != ((int32*)&rkVector)[0];
|
||||
}
|
||||
|
||||
}
|
||||
#if defined(G3D_LINUX) || defined(G3D_OSX)
|
||||
__attribute((aligned(1)))
|
||||
#endif
|
||||
;
|
||||
|
||||
#ifdef G3D_WIN32
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,504 @@
|
||||
/**
|
||||
@file Vector3.h
|
||||
|
||||
3D vector class
|
||||
|
||||
@maintainer Morgan McGuire, [email protected]
|
||||
|
||||
@created 2001-06-02
|
||||
@edited 2005-08-23
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_VECTOR3_H
|
||||
#define G3D_VECTOR3_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/Vector2.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class Vector2;
|
||||
class Vector3;
|
||||
class Vector4;
|
||||
|
||||
/**
|
||||
<B>Swizzles</B>
|
||||
Vector classes have swizzle operators, e.g. <CODE>v.xy()</CODE>, that
|
||||
allow selection of arbitrary sub-fields. These cannot be used as write
|
||||
masks. Examples
|
||||
|
||||
<PRE>
|
||||
Vector3 v(1, 2, 3);
|
||||
Vector3 j;
|
||||
Vector2 b;
|
||||
|
||||
b = v.xz();
|
||||
j = b.xx();
|
||||
</PRE>
|
||||
|
||||
|
||||
<B>Warning</B>
|
||||
|
||||
Do not subclass-- this implementation makes assumptions about the
|
||||
memory layout.
|
||||
*/
|
||||
class Vector3 {
|
||||
private:
|
||||
/**
|
||||
Reflect this vector about the (not necessarily unit) normal.
|
||||
Note that if used for a collision or ray reflection you
|
||||
must negate the resulting vector to get a direction pointing
|
||||
<I>away</I> from the collision.
|
||||
|
||||
<PRE>
|
||||
V' N V
|
||||
|
||||
r ^ -,
|
||||
\ | /
|
||||
\|/
|
||||
</PRE>
|
||||
|
||||
See also Vector3::reflectionDirection
|
||||
*/
|
||||
Vector3 reflectAbout(const Vector3& normal) const;
|
||||
|
||||
// Hidden operators
|
||||
bool operator<(const Vector3&) const;
|
||||
bool operator>(const Vector3&) const;
|
||||
bool operator<=(const Vector3&) const;
|
||||
bool operator>=(const Vector3&) const;
|
||||
|
||||
public:
|
||||
// construction
|
||||
Vector3();
|
||||
Vector3(float _x, float _y, float _z);
|
||||
Vector3(const class Vector2& v, float _z);
|
||||
Vector3(float coordinate[3]);
|
||||
Vector3(double coordinate[3]);
|
||||
Vector3(const Vector3& rkVector);
|
||||
Vector3(const class Vector3int16& v);
|
||||
|
||||
// coordinates
|
||||
float x, y, z;
|
||||
|
||||
// access vector V as V[0] = V.x, V[1] = V.y, V[2] = V.z
|
||||
//
|
||||
// WARNING. These member functions rely on
|
||||
// (1) Vector3 not having virtual functions
|
||||
// (2) the data packed in a 3*sizeof(float) memory block
|
||||
const float& operator[] (int i) const;
|
||||
float& operator[] (int i);
|
||||
|
||||
inline operator float* () {
|
||||
return (float*)this;
|
||||
}
|
||||
|
||||
operator const float* () const {
|
||||
return (float*)this;
|
||||
}
|
||||
|
||||
enum Axis {X_AXIS=0, Y_AXIS=1, Z_AXIS=2, DETECT_AXIS=-1};
|
||||
|
||||
/**
|
||||
Returns the largest dimension. Particularly convenient for determining
|
||||
which plane to project a triangle onto for point-in-polygon tests.
|
||||
*/
|
||||
Axis primaryAxis() const;
|
||||
|
||||
// assignment and comparison
|
||||
Vector3& operator= (const Vector3& rkVector);
|
||||
bool operator== (const Vector3& rkVector) const;
|
||||
bool operator!= (const Vector3& rkVector) const;
|
||||
unsigned int hashCode() const;
|
||||
bool fuzzyEq(const Vector3& other) const;
|
||||
bool fuzzyNe(const Vector3& other) const;
|
||||
|
||||
/** Returns true if this vector has finite length. */
|
||||
bool isFinite() const;
|
||||
|
||||
/** Returns true if this vector has length ~= 0 */
|
||||
bool isZero() const;
|
||||
|
||||
/** Returns true if this vector has length ~= 1 */
|
||||
bool isUnit() const;
|
||||
|
||||
// arithmetic operations
|
||||
Vector3 operator+ (const Vector3& v) const;
|
||||
Vector3 operator- (const Vector3& v) const;
|
||||
Vector3 operator* (float s) const;
|
||||
Vector3 operator/ (float s) const;
|
||||
Vector3 operator* (const Vector3& v) const;
|
||||
Vector3 operator/ (const Vector3& v) const;
|
||||
Vector3 operator- () const;
|
||||
|
||||
// arithmetic updates
|
||||
Vector3& operator+= (const Vector3& v);
|
||||
Vector3& operator-= (const Vector3& v);
|
||||
Vector3& operator*= (float s);
|
||||
Vector3& operator/= (float s);
|
||||
Vector3& operator*= (const Vector3& v);
|
||||
Vector3& operator/= (const Vector3& v);
|
||||
|
||||
/** @deprecated Use magnitude */
|
||||
float G3D_DEPRECATED length() const;
|
||||
|
||||
float magnitude() const;
|
||||
|
||||
/**
|
||||
The result is a nan vector if the length is almost zero.
|
||||
*/
|
||||
Vector3 direction() const;
|
||||
|
||||
/**
|
||||
Potentially less accurate but faster than direction().
|
||||
Only works if System::hasSSE is true.
|
||||
*/
|
||||
Vector3 fastDirection() const;
|
||||
|
||||
|
||||
/**
|
||||
See also G3D::Ray::reflect.
|
||||
The length is 1.
|
||||
<PRE>
|
||||
V' N V
|
||||
|
||||
r ^ /
|
||||
\ | /
|
||||
\|'-
|
||||
</PRE>
|
||||
*/
|
||||
Vector3 reflectionDirection(const Vector3& normal) const;
|
||||
|
||||
|
||||
/**
|
||||
Returns Vector3::zero() if the length is nearly zero, otherwise
|
||||
returns a unit vector.
|
||||
*/
|
||||
inline Vector3 directionOrZero() const {
|
||||
float mag = magnitude();
|
||||
if (G3D::fuzzyEq(mag, 0.0f)) {
|
||||
return Vector3::zero();
|
||||
} else if (G3D::fuzzyEq(mag, 1.0f)) {
|
||||
return *this;
|
||||
} else {
|
||||
return *this * (1.0f / mag);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the direction of a refracted ray,
|
||||
where iExit is the index of refraction for the
|
||||
previous material and iEnter is the index of refraction
|
||||
for the new material. Like Vector3::reflectionDirection,
|
||||
the result has length 1 and is
|
||||
pointed <I>away</I> from the intersection.
|
||||
|
||||
Returns Vector3::zero() in the case of total internal refraction.
|
||||
|
||||
@param iOutside The index of refraction (eta) outside
|
||||
(on the <I>positive</I> normal side) of the surface.
|
||||
|
||||
@param iInside The index of refraction (eta) inside
|
||||
(on the <I>negative</I> normal side) of the surface.
|
||||
|
||||
See also G3D::Ray::refract.
|
||||
<PRE>
|
||||
N V
|
||||
|
||||
^ /
|
||||
| /
|
||||
|'-
|
||||
__--
|
||||
V'<--
|
||||
</PRE>
|
||||
*/
|
||||
Vector3 refractionDirection(
|
||||
const Vector3& normal,
|
||||
float iInside,
|
||||
float iOutside) const;
|
||||
|
||||
/** Synonym for direction */
|
||||
inline Vector3 unit() const {
|
||||
return direction();
|
||||
}
|
||||
|
||||
/** Returns a normalized vector. May be computed with lower precision than unit */
|
||||
inline Vector3 fastUnit() const {
|
||||
return fastDirection();
|
||||
}
|
||||
|
||||
/** @deprecated Use squaredMagnitude */
|
||||
float G3D_DEPRECATED squaredLength() const;
|
||||
|
||||
float squaredMagnitude () const;
|
||||
|
||||
/** @deprecated Use squaredMagnitude */
|
||||
inline float G3D_DEPRECATED norm() const {
|
||||
return squaredMagnitude();
|
||||
}
|
||||
|
||||
float dot(const Vector3& rkVector) const;
|
||||
|
||||
float G3D_DEPRECATED unitize(float fTolerance = 1e-06);
|
||||
|
||||
/** Cross product. Note that two cross products in a row
|
||||
can be computed more cheaply: v1 x (v2 x v3) = (v1 dot v3) v2 - (v1 dot v2) v3.
|
||||
*/
|
||||
Vector3 cross(const Vector3& rkVector) const;
|
||||
Vector3 unitCross (const Vector3& rkVector) const;
|
||||
|
||||
/**
|
||||
Returns a matrix such that v.cross() * w = v.cross(w).
|
||||
<PRE>
|
||||
[ 0 -v.z v.y ]
|
||||
[ v.z 0 -v.x ]
|
||||
[ -v.y v.x 0 ]
|
||||
</PRE>
|
||||
*/
|
||||
class Matrix3 cross() const;
|
||||
|
||||
Vector3 min(const Vector3 &v) const;
|
||||
Vector3 max(const Vector3 &v) const;
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
inline Vector3 clamp(const Vector3& low, const Vector3& high) const {
|
||||
return Vector3(
|
||||
G3D::clamp(x, low.x, high.x),
|
||||
G3D::clamp(y, low.y, high.y),
|
||||
G3D::clamp(z, low.z, high.z));
|
||||
}
|
||||
|
||||
inline Vector3 clamp(float low, float high) const {
|
||||
return Vector3(
|
||||
G3D::clamp(x, low, high),
|
||||
G3D::clamp(y, low, high),
|
||||
G3D::clamp(z, low, high));
|
||||
}
|
||||
|
||||
/**
|
||||
Linear interpolation
|
||||
*/
|
||||
inline Vector3 lerp(const Vector3& v, float alpha) const {
|
||||
return (*this) + (v - *this) * alpha;
|
||||
}
|
||||
|
||||
/** Gram-Schmidt orthonormalization. */
|
||||
static void orthonormalize (Vector3 akVector[3]);
|
||||
|
||||
/** Random unit vector, uniformly distributed */
|
||||
static Vector3 random();
|
||||
|
||||
/** Random unit vector, distributed
|
||||
so that the probability of V is proportional
|
||||
to max(V dot Normal, 0).
|
||||
|
||||
@cite Henrik Wann Jensen, Realistic Image Synthesis using Photon Mapping eqn 2.24
|
||||
*/
|
||||
static Vector3 cosRandom(const Vector3& normal);
|
||||
|
||||
|
||||
/**
|
||||
Random vector distributed over the hemisphere about normal.
|
||||
*/
|
||||
static Vector3 hemiRandom(const Vector3& normal);
|
||||
|
||||
// Input W must be initialize to a nonzero vector, output is {U,V,W}
|
||||
// an orthonormal basis. A hint is provided about whether or not W
|
||||
// is already unit length.
|
||||
static void generateOrthonormalBasis (Vector3& rkU, Vector3& rkV,
|
||||
Vector3& rkW, bool bUnitLengthW = true);
|
||||
|
||||
inline float sum() const {
|
||||
return x + y + z;
|
||||
}
|
||||
|
||||
inline float average() const {
|
||||
return sum() / 3.0f;
|
||||
}
|
||||
|
||||
// Special values.
|
||||
inline static const Vector3& zero() { static Vector3 v(0, 0, 0); return v; }
|
||||
inline static const Vector3& one() { static Vector3 v(1, 1, 1); return v; }
|
||||
inline static const Vector3& unitX() { static Vector3 v(1, 0, 0); return v; }
|
||||
inline static const Vector3& unitY() { static Vector3 v(0, 1, 0); return v; }
|
||||
inline static const Vector3& unitZ() { static Vector3 v(0, 0, 1); return v; }
|
||||
inline static const Vector3& inf() { static Vector3 v((float)G3D::inf(), (float)G3D::inf(), (float)G3D::inf()); return v; }
|
||||
inline static const Vector3& nan() { static Vector3 v((float)G3D::nan(), (float)G3D::nan(), (float)G3D::nan()); return v; }
|
||||
/** Smallest (most negative) representable vector */
|
||||
inline static const Vector3& minFinite(){ static Vector3 v(-FLT_MAX, -FLT_MAX, -FLT_MAX); return v; }
|
||||
/** Largest representable vector */
|
||||
inline static const Vector3& maxFinite(){ static Vector3 v(FLT_MAX, FLT_MAX, FLT_MAX); return v; }
|
||||
|
||||
// Deprecated. See Matrix3::identity() for details.
|
||||
/** @deprecated Use Vector3::zero() */
|
||||
static const Vector3 ZERO;
|
||||
/** @deprecated Use Vector3::zero() */
|
||||
static const Vector3 ZERO3;
|
||||
/** @deprecated Use Vector3::unitX() */
|
||||
static const Vector3 UNIT_X;
|
||||
/** @deprecated Use Vector3::unitY() */
|
||||
static const Vector3 UNIT_Y;
|
||||
/** @deprecated Use Vector3::unitZ() */
|
||||
static const Vector3 UNIT_Z;
|
||||
/** @deprecated Use Vector3::inf() */
|
||||
static const Vector3 INF3;
|
||||
/** @deprecated Use Vector3::nan() */
|
||||
static const Vector3 NAN3;
|
||||
|
||||
// 2-char swizzles
|
||||
|
||||
Vector2 xx() const;
|
||||
Vector2 yx() const;
|
||||
Vector2 zx() const;
|
||||
Vector2 xy() const;
|
||||
Vector2 yy() const;
|
||||
Vector2 zy() const;
|
||||
Vector2 xz() const;
|
||||
Vector2 yz() const;
|
||||
Vector2 zz() const;
|
||||
|
||||
// 3-char swizzles
|
||||
|
||||
Vector3 xxx() const;
|
||||
Vector3 yxx() const;
|
||||
Vector3 zxx() const;
|
||||
Vector3 xyx() const;
|
||||
Vector3 yyx() const;
|
||||
Vector3 zyx() const;
|
||||
Vector3 xzx() const;
|
||||
Vector3 yzx() const;
|
||||
Vector3 zzx() const;
|
||||
Vector3 xxy() const;
|
||||
Vector3 yxy() const;
|
||||
Vector3 zxy() const;
|
||||
Vector3 xyy() const;
|
||||
Vector3 yyy() const;
|
||||
Vector3 zyy() const;
|
||||
Vector3 xzy() const;
|
||||
Vector3 yzy() const;
|
||||
Vector3 zzy() const;
|
||||
Vector3 xxz() const;
|
||||
Vector3 yxz() const;
|
||||
Vector3 zxz() const;
|
||||
Vector3 xyz() const;
|
||||
Vector3 yyz() const;
|
||||
Vector3 zyz() const;
|
||||
Vector3 xzz() const;
|
||||
Vector3 yzz() const;
|
||||
Vector3 zzz() const;
|
||||
|
||||
// 4-char swizzles
|
||||
|
||||
Vector4 xxxx() const;
|
||||
Vector4 yxxx() const;
|
||||
Vector4 zxxx() const;
|
||||
Vector4 xyxx() const;
|
||||
Vector4 yyxx() const;
|
||||
Vector4 zyxx() const;
|
||||
Vector4 xzxx() const;
|
||||
Vector4 yzxx() const;
|
||||
Vector4 zzxx() const;
|
||||
Vector4 xxyx() const;
|
||||
Vector4 yxyx() const;
|
||||
Vector4 zxyx() const;
|
||||
Vector4 xyyx() const;
|
||||
Vector4 yyyx() const;
|
||||
Vector4 zyyx() const;
|
||||
Vector4 xzyx() const;
|
||||
Vector4 yzyx() const;
|
||||
Vector4 zzyx() const;
|
||||
Vector4 xxzx() const;
|
||||
Vector4 yxzx() const;
|
||||
Vector4 zxzx() const;
|
||||
Vector4 xyzx() const;
|
||||
Vector4 yyzx() const;
|
||||
Vector4 zyzx() const;
|
||||
Vector4 xzzx() const;
|
||||
Vector4 yzzx() const;
|
||||
Vector4 zzzx() const;
|
||||
Vector4 xxxy() const;
|
||||
Vector4 yxxy() const;
|
||||
Vector4 zxxy() const;
|
||||
Vector4 xyxy() const;
|
||||
Vector4 yyxy() const;
|
||||
Vector4 zyxy() const;
|
||||
Vector4 xzxy() const;
|
||||
Vector4 yzxy() const;
|
||||
Vector4 zzxy() const;
|
||||
Vector4 xxyy() const;
|
||||
Vector4 yxyy() const;
|
||||
Vector4 zxyy() const;
|
||||
Vector4 xyyy() const;
|
||||
Vector4 yyyy() const;
|
||||
Vector4 zyyy() const;
|
||||
Vector4 xzyy() const;
|
||||
Vector4 yzyy() const;
|
||||
Vector4 zzyy() const;
|
||||
Vector4 xxzy() const;
|
||||
Vector4 yxzy() const;
|
||||
Vector4 zxzy() const;
|
||||
Vector4 xyzy() const;
|
||||
Vector4 yyzy() const;
|
||||
Vector4 zyzy() const;
|
||||
Vector4 xzzy() const;
|
||||
Vector4 yzzy() const;
|
||||
Vector4 zzzy() const;
|
||||
Vector4 xxxz() const;
|
||||
Vector4 yxxz() const;
|
||||
Vector4 zxxz() const;
|
||||
Vector4 xyxz() const;
|
||||
Vector4 yyxz() const;
|
||||
Vector4 zyxz() const;
|
||||
Vector4 xzxz() const;
|
||||
Vector4 yzxz() const;
|
||||
Vector4 zzxz() const;
|
||||
Vector4 xxyz() const;
|
||||
Vector4 yxyz() const;
|
||||
Vector4 zxyz() const;
|
||||
Vector4 xyyz() const;
|
||||
Vector4 yyyz() const;
|
||||
Vector4 zyyz() const;
|
||||
Vector4 xzyz() const;
|
||||
Vector4 yzyz() const;
|
||||
Vector4 zzyz() const;
|
||||
Vector4 xxzz() const;
|
||||
Vector4 yxzz() const;
|
||||
Vector4 zxzz() const;
|
||||
Vector4 xyzz() const;
|
||||
Vector4 yyzz() const;
|
||||
Vector4 zyzz() const;
|
||||
Vector4 xzzz() const;
|
||||
Vector4 yzzz() const;
|
||||
Vector4 zzzz() const;
|
||||
|
||||
/** A value that can be passed to ignore a parameter. Never look at the result of dummy. */
|
||||
static Vector3 dummy;
|
||||
};
|
||||
|
||||
inline G3D::Vector3 operator*(float s, const G3D::Vector3& v) {
|
||||
return v * s;
|
||||
}
|
||||
|
||||
inline G3D::Vector3 operator*(double s, const G3D::Vector3& v) {
|
||||
return v * (float)s;
|
||||
}
|
||||
|
||||
inline G3D::Vector3 operator*(int s, const G3D::Vector3& v) {
|
||||
return v * (float)s;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const Vector3&);
|
||||
|
||||
}
|
||||
|
||||
unsigned int hashCode(const G3D::Vector3& v);
|
||||
|
||||
#include "Vector3.inl"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,250 @@
|
||||
/**
|
||||
@file Vector3.inl
|
||||
|
||||
@maintainer Morgan McGuire, [email protected]
|
||||
|
||||
@cite Portions based on Dave Eberly's Magic Software Library at http://www.magic-software.com
|
||||
|
||||
@created 2001-06-02
|
||||
@edited 2004-05-21
|
||||
Copyright 2000-2004, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
#ifdef SSE
|
||||
// If you receive an error on this line, it is because you do not have the file
|
||||
// xmmintrin.h needed for MMX & SSE extensions. Download and install
|
||||
//
|
||||
// http://download.microsoft.com/download/vstudio60ent/SP5/Wideband-Full/WIN98Me/EN-US/vs6sp5.exe
|
||||
// and
|
||||
// http://download.microsoft.com/download/vb60ent/Update/6/W9X2KXP/EN-US/vcpp5.exe
|
||||
//
|
||||
// to get this file.
|
||||
# include <xmmintrin.h>
|
||||
#endif
|
||||
|
||||
inline unsigned int hashCode(const G3D::Vector3& v) {
|
||||
return v.hashCode();
|
||||
}
|
||||
|
||||
namespace G3D {
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector3::Vector3() : x(0.0f), y(0.0f), z(0.0f) {
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline Vector3::Vector3 (float fX, float fY, float fZ) : x(fX), y(fY), z(fZ) {
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector3::Vector3 (float V[3]) : x(V[0]), y(V[1]), z(V[2]){
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector3::Vector3 (double V[3]) : x((float)V[0]), y((float)V[1]), z((float)V[2]){
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector3::Vector3 (const Vector3& V) : x(V.x), y(V.y), z(V.z) {
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//inline Vector3::Vector3 (const __m128& m) {
|
||||
// Cast from SSE packed floats
|
||||
// *this = *(Vector3*)&m;
|
||||
//}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline const float& Vector3::operator[] (int i) const {
|
||||
return ((float*)this)[i];
|
||||
}
|
||||
|
||||
inline float& Vector3::operator[] (int i) {
|
||||
return ((float*)this)[i];
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector3& Vector3::operator= (const Vector3& rkVector) {
|
||||
x = rkVector.x;
|
||||
y = rkVector.y;
|
||||
z = rkVector.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline bool Vector3::fuzzyEq(const Vector3& other) const {
|
||||
return G3D::fuzzyEq((*this - other).squaredMagnitude(), 0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline bool Vector3::fuzzyNe(const Vector3& other) const {
|
||||
return G3D::fuzzyNe((*this - other).squaredMagnitude(), 0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline bool Vector3::isFinite() const {
|
||||
return G3D::isFinite(x) && G3D::isFinite(y) && G3D::isFinite(z);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline bool Vector3::operator== (const Vector3& rkVector) const {
|
||||
return ( x == rkVector.x && y == rkVector.y && z == rkVector.z );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline bool Vector3::operator!= (const Vector3& rkVector) const {
|
||||
return ( x != rkVector.x || y != rkVector.y || z != rkVector.z );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector3 Vector3::operator+ (const Vector3& rkVector) const {
|
||||
return Vector3(x + rkVector.x, y + rkVector.y, z + rkVector.z);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector3 Vector3::operator- (const Vector3& rkVector) const {
|
||||
return Vector3(x - rkVector.x, y - rkVector.y, z - rkVector.z);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector3 Vector3::operator* (const Vector3& rkVector) const {
|
||||
return Vector3(x * rkVector.x, y * rkVector.y, z * rkVector.z);
|
||||
}
|
||||
|
||||
inline Vector3 Vector3::operator*(float f) const {
|
||||
return Vector3(x * f, y * f, z * f);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector3 Vector3::operator/ (const Vector3& rkVector) const {
|
||||
return Vector3(x / rkVector.x, y / rkVector.y, z / rkVector.z);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector3 Vector3::operator- () const {
|
||||
return Vector3(-x, -y, -z);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector3& Vector3::operator+= (const Vector3& rkVector) {
|
||||
x += rkVector.x;
|
||||
y += rkVector.y;
|
||||
z += rkVector.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector3& Vector3::operator-= (const Vector3& rkVector) {
|
||||
x -= rkVector.x;
|
||||
y -= rkVector.y;
|
||||
z -= rkVector.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector3& Vector3::operator*= (float fScalar) {
|
||||
x *= fScalar;
|
||||
y *= fScalar;
|
||||
z *= fScalar;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector3& Vector3::operator*= (const Vector3& rkVector) {
|
||||
x *= rkVector.x;
|
||||
y *= rkVector.y;
|
||||
z *= rkVector.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector3& Vector3::operator/= (const Vector3& rkVector) {
|
||||
x /= rkVector.x;
|
||||
y /= rkVector.y;
|
||||
z /= rkVector.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline float Vector3::squaredMagnitude () const {
|
||||
return x*x + y*y + z*z;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline float Vector3::squaredLength () const {
|
||||
return squaredMagnitude();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline float Vector3::magnitude() const {
|
||||
return sqrtf(x*x + y*y + z*z);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline float Vector3::length() const {
|
||||
return magnitude();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector3 Vector3::direction () const {
|
||||
float lenSquared = squaredMagnitude();
|
||||
float invSqrt = 1.0f / sqrtf(lenSquared);
|
||||
return Vector3(x * invSqrt, y * invSqrt, z * invSqrt);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline Vector3 Vector3::fastDirection () const {
|
||||
float lenSquared = x * x + y * y + z * z;
|
||||
float invSqrt = rsq(lenSquared);
|
||||
return Vector3(x * invSqrt, y * invSqrt, z * invSqrt);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline float Vector3::dot (const Vector3& rkVector) const {
|
||||
return x*rkVector.x + y*rkVector.y + z*rkVector.z;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector3 Vector3::cross (const Vector3& rkVector) const {
|
||||
return Vector3(y*rkVector.z - z*rkVector.y, z*rkVector.x - x*rkVector.z,
|
||||
x*rkVector.y - y*rkVector.x);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector3 Vector3::unitCross (const Vector3& rkVector) const {
|
||||
Vector3 kCross(y*rkVector.z - z*rkVector.y, z*rkVector.x - x*rkVector.z,
|
||||
x*rkVector.y - y*rkVector.x);
|
||||
kCross.unitize();
|
||||
return kCross;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector3 Vector3::min(const Vector3 &v) const {
|
||||
return Vector3(G3D::min(v.x, x), G3D::min(v.y, y), G3D::min(v.z, z));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector3 Vector3::max(const Vector3 &v) const {
|
||||
return Vector3(G3D::max(v.x, x), G3D::max(v.y, y), G3D::max(v.z, z));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline bool Vector3::isZero() const {
|
||||
return G3D::fuzzyEq(squaredMagnitude(), 0.0f);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline bool Vector3::isUnit() const {
|
||||
return G3D::fuzzyEq(squaredMagnitude(), 1.0f);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
@file Vector3int16.h
|
||||
|
||||
@maintainer Morgan McGuire, [email protected]
|
||||
|
||||
@created 2003-04-07
|
||||
@edited 2003-06-24
|
||||
Copyright 2000-2004, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef VECTOR3INT16_H
|
||||
#define VECTOR3INT16_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
A Vector3 that packs its fields into uint16s.
|
||||
*/
|
||||
#ifdef G3D_WIN32
|
||||
// Switch to tight alignment
|
||||
#pragma pack(push, 2)
|
||||
#endif
|
||||
|
||||
class Vector3int16 {
|
||||
private:
|
||||
// Hidden operators
|
||||
bool operator<(const Vector3int16&) const;
|
||||
bool operator>(const Vector3int16&) const;
|
||||
bool operator<=(const Vector3int16&) const;
|
||||
bool operator>=(const Vector3int16&) const;
|
||||
|
||||
public:
|
||||
G3D::int16 x;
|
||||
G3D::int16 y;
|
||||
G3D::int16 z;
|
||||
|
||||
Vector3int16() : x(0), y(0), z(0) {}
|
||||
Vector3int16(G3D::int16 _x, G3D::int16 _y, G3D::int16 _z) : x(_x), y(_y), z(_z) {}
|
||||
Vector3int16(const class Vector3& v);
|
||||
}
|
||||
#if defined(G3D_LINUX) || defined(G3D_OSX)
|
||||
__attribute((aligned(1)))
|
||||
#endif
|
||||
;
|
||||
|
||||
#ifdef G3D_WIN32
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,524 @@
|
||||
/**
|
||||
@file Vector4.h
|
||||
|
||||
Homogeneous vector class.
|
||||
|
||||
@maintainer Morgan McGuire, [email protected]
|
||||
|
||||
@created 2002-07-09
|
||||
@edited 2005-03-28
|
||||
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_VECTOR4_H
|
||||
#define G3D_VECTOR4_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Vector2.h"
|
||||
#include <string>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class Vector2;
|
||||
class Vector3;
|
||||
class Vector4;
|
||||
|
||||
/**
|
||||
Do not subclass-- this implementation makes assumptions about the
|
||||
memory layout.
|
||||
*/
|
||||
class Vector4 {
|
||||
private:
|
||||
// Hidden operators
|
||||
bool operator<(const Vector4&) const;
|
||||
bool operator>(const Vector4&) const;
|
||||
bool operator<=(const Vector4&) const;
|
||||
bool operator>=(const Vector4&) const;
|
||||
|
||||
public:
|
||||
// construction
|
||||
Vector4();
|
||||
Vector4(float fX, float fY, float fZ, float fW);
|
||||
Vector4(float afCoordinate[4]);
|
||||
Vector4(const Vector4& rkVector);
|
||||
Vector4(const class Color4& c);
|
||||
Vector4(const Vector3& rkVector, float fW);
|
||||
Vector4(const Vector2& v1, const Vector2& v2);
|
||||
Vector4(const Vector2& v1, float fz, float fw);
|
||||
|
||||
// coordinates
|
||||
float x, y, z, w;
|
||||
|
||||
// access vector V as V[0] = V.x, V[1] = V.y, V[2] = V.z, etc.
|
||||
//
|
||||
// WARNING. These member functions rely on
|
||||
// (1) Vector4 not having virtual functions
|
||||
// (2) the data packed in a 4*sizeof(float) memory block
|
||||
float& operator[] (int i);
|
||||
const float& operator[] (int i) const;
|
||||
operator float* ();
|
||||
operator const float* () const;
|
||||
|
||||
// assignment and comparison
|
||||
Vector4& operator= (const Vector4& rkVector);
|
||||
bool operator== (const Vector4& rkVector) const;
|
||||
bool operator!= (const Vector4& rkVector) const;
|
||||
|
||||
inline void set(float _x, float _y, float _z, float _w) {
|
||||
x = _x;
|
||||
y = _y;
|
||||
z = _z;
|
||||
w = _w;
|
||||
}
|
||||
|
||||
inline void set(const Vector3& v, float _w) {
|
||||
x = v.x;
|
||||
y = v.y;
|
||||
z = v.z;
|
||||
w = _w;
|
||||
}
|
||||
|
||||
inline void set(const Vector2& v, float _z, float _w) {
|
||||
x = v.x;
|
||||
y = v.y;
|
||||
z = _z;
|
||||
w = _w;
|
||||
}
|
||||
|
||||
unsigned int hashCode() const;
|
||||
bool fuzzyEq(const Vector4& other) const;
|
||||
bool fuzzyNe(const Vector4& other) const;
|
||||
|
||||
inline static const Vector4& inf() { static Vector4 v((float)G3D::inf(), (float)G3D::inf(), (float)G3D::inf(), (float)G3D::inf()); return v; }
|
||||
inline static const Vector4& nan() { static Vector4 v((float)G3D::nan(), (float)G3D::nan(), (float)G3D::nan(), (float)G3D::nan()); return v; }
|
||||
|
||||
/** sqrt(this->dot(*this)) */
|
||||
float length() const;
|
||||
float squaredLength() const;
|
||||
|
||||
inline float sum() const {
|
||||
return x + y + z + w;
|
||||
}
|
||||
|
||||
/** Returns true if this vector has finite length */
|
||||
bool isFinite() const;
|
||||
|
||||
/** Returns true if this vector has length == 0 */
|
||||
bool isZero() const;
|
||||
|
||||
/** Returns true if this vector has length == 1 */
|
||||
bool isUnit() const;
|
||||
|
||||
// arithmetic operations
|
||||
Vector4 operator+ (const Vector4& rkVector) const;
|
||||
Vector4 operator- (const Vector4& rkVector) const;
|
||||
|
||||
inline Vector4 operator*(const Vector4& rkVector) const {
|
||||
return Vector4(x * rkVector.x, y * rkVector.y, z * rkVector.z, w * rkVector.w);
|
||||
}
|
||||
|
||||
inline Vector4 operator/(const Vector4& rkVector) const {
|
||||
return Vector4(x / rkVector.x, y / rkVector.y, z / rkVector.z, w / rkVector.w);
|
||||
}
|
||||
|
||||
Vector4 operator* (float fScalar) const;
|
||||
Vector4 operator/ (float fScalar) const;
|
||||
Vector4 operator- () const;
|
||||
friend Vector4 operator* (float, const Vector4& rkVector);
|
||||
|
||||
// arithmetic updates
|
||||
Vector4& operator+= (const Vector4& rkVector);
|
||||
Vector4& operator-= (const Vector4& rkVector);
|
||||
Vector4& operator*= (float fScalar);
|
||||
Vector4& operator/= (float fScalar);
|
||||
|
||||
inline Vector4 clamp(const Vector4& low, const Vector4& high) const {
|
||||
return Vector4(
|
||||
G3D::clamp(x, low.x, high.x),
|
||||
G3D::clamp(y, low.y, high.y),
|
||||
G3D::clamp(z, low.z, high.z),
|
||||
G3D::clamp(w, low.w, high.w));
|
||||
}
|
||||
|
||||
inline Vector4 clamp(float low, float high) const {
|
||||
return Vector4(
|
||||
G3D::clamp(x, low, high),
|
||||
G3D::clamp(y, low, high),
|
||||
G3D::clamp(z, low, high),
|
||||
G3D::clamp(w, low, high));
|
||||
}
|
||||
|
||||
float dot (const Vector4& rkVector) const;
|
||||
|
||||
Vector4 min(const Vector4& v) const;
|
||||
Vector4 max(const Vector4& v) const;
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
/**
|
||||
Linear interpolation
|
||||
*/
|
||||
Vector4 lerp(const Vector4& v, float alpha) const;
|
||||
|
||||
// 2-char swizzles
|
||||
|
||||
Vector2 xx() const;
|
||||
Vector2 yx() const;
|
||||
Vector2 zx() const;
|
||||
Vector2 wx() const;
|
||||
Vector2 xy() const;
|
||||
Vector2 yy() const;
|
||||
Vector2 zy() const;
|
||||
Vector2 wy() const;
|
||||
Vector2 xz() const;
|
||||
Vector2 yz() const;
|
||||
Vector2 zz() const;
|
||||
Vector2 wz() const;
|
||||
Vector2 xw() const;
|
||||
Vector2 yw() const;
|
||||
Vector2 zw() const;
|
||||
Vector2 ww() const;
|
||||
|
||||
// 3-char swizzles
|
||||
|
||||
Vector3 xxx() const;
|
||||
Vector3 yxx() const;
|
||||
Vector3 zxx() const;
|
||||
Vector3 wxx() const;
|
||||
Vector3 xyx() const;
|
||||
Vector3 yyx() const;
|
||||
Vector3 zyx() const;
|
||||
Vector3 wyx() const;
|
||||
Vector3 xzx() const;
|
||||
Vector3 yzx() const;
|
||||
Vector3 zzx() const;
|
||||
Vector3 wzx() const;
|
||||
Vector3 xwx() const;
|
||||
Vector3 ywx() const;
|
||||
Vector3 zwx() const;
|
||||
Vector3 wwx() const;
|
||||
Vector3 xxy() const;
|
||||
Vector3 yxy() const;
|
||||
Vector3 zxy() const;
|
||||
Vector3 wxy() const;
|
||||
Vector3 xyy() const;
|
||||
Vector3 yyy() const;
|
||||
Vector3 zyy() const;
|
||||
Vector3 wyy() const;
|
||||
Vector3 xzy() const;
|
||||
Vector3 yzy() const;
|
||||
Vector3 zzy() const;
|
||||
Vector3 wzy() const;
|
||||
Vector3 xwy() const;
|
||||
Vector3 ywy() const;
|
||||
Vector3 zwy() const;
|
||||
Vector3 wwy() const;
|
||||
Vector3 xxz() const;
|
||||
Vector3 yxz() const;
|
||||
Vector3 zxz() const;
|
||||
Vector3 wxz() const;
|
||||
Vector3 xyz() const;
|
||||
Vector3 yyz() const;
|
||||
Vector3 zyz() const;
|
||||
Vector3 wyz() const;
|
||||
Vector3 xzz() const;
|
||||
Vector3 yzz() const;
|
||||
Vector3 zzz() const;
|
||||
Vector3 wzz() const;
|
||||
Vector3 xwz() const;
|
||||
Vector3 ywz() const;
|
||||
Vector3 zwz() const;
|
||||
Vector3 wwz() const;
|
||||
Vector3 xxw() const;
|
||||
Vector3 yxw() const;
|
||||
Vector3 zxw() const;
|
||||
Vector3 wxw() const;
|
||||
Vector3 xyw() const;
|
||||
Vector3 yyw() const;
|
||||
Vector3 zyw() const;
|
||||
Vector3 wyw() const;
|
||||
Vector3 xzw() const;
|
||||
Vector3 yzw() const;
|
||||
Vector3 zzw() const;
|
||||
Vector3 wzw() const;
|
||||
Vector3 xww() const;
|
||||
Vector3 yww() const;
|
||||
Vector3 zww() const;
|
||||
Vector3 www() const;
|
||||
|
||||
// 4-char swizzles
|
||||
|
||||
Vector4 xxxx() const;
|
||||
Vector4 yxxx() const;
|
||||
Vector4 zxxx() const;
|
||||
Vector4 wxxx() const;
|
||||
Vector4 xyxx() const;
|
||||
Vector4 yyxx() const;
|
||||
Vector4 zyxx() const;
|
||||
Vector4 wyxx() const;
|
||||
Vector4 xzxx() const;
|
||||
Vector4 yzxx() const;
|
||||
Vector4 zzxx() const;
|
||||
Vector4 wzxx() const;
|
||||
Vector4 xwxx() const;
|
||||
Vector4 ywxx() const;
|
||||
Vector4 zwxx() const;
|
||||
Vector4 wwxx() const;
|
||||
Vector4 xxyx() const;
|
||||
Vector4 yxyx() const;
|
||||
Vector4 zxyx() const;
|
||||
Vector4 wxyx() const;
|
||||
Vector4 xyyx() const;
|
||||
Vector4 yyyx() const;
|
||||
Vector4 zyyx() const;
|
||||
Vector4 wyyx() const;
|
||||
Vector4 xzyx() const;
|
||||
Vector4 yzyx() const;
|
||||
Vector4 zzyx() const;
|
||||
Vector4 wzyx() const;
|
||||
Vector4 xwyx() const;
|
||||
Vector4 ywyx() const;
|
||||
Vector4 zwyx() const;
|
||||
Vector4 wwyx() const;
|
||||
Vector4 xxzx() const;
|
||||
Vector4 yxzx() const;
|
||||
Vector4 zxzx() const;
|
||||
Vector4 wxzx() const;
|
||||
Vector4 xyzx() const;
|
||||
Vector4 yyzx() const;
|
||||
Vector4 zyzx() const;
|
||||
Vector4 wyzx() const;
|
||||
Vector4 xzzx() const;
|
||||
Vector4 yzzx() const;
|
||||
Vector4 zzzx() const;
|
||||
Vector4 wzzx() const;
|
||||
Vector4 xwzx() const;
|
||||
Vector4 ywzx() const;
|
||||
Vector4 zwzx() const;
|
||||
Vector4 wwzx() const;
|
||||
Vector4 xxwx() const;
|
||||
Vector4 yxwx() const;
|
||||
Vector4 zxwx() const;
|
||||
Vector4 wxwx() const;
|
||||
Vector4 xywx() const;
|
||||
Vector4 yywx() const;
|
||||
Vector4 zywx() const;
|
||||
Vector4 wywx() const;
|
||||
Vector4 xzwx() const;
|
||||
Vector4 yzwx() const;
|
||||
Vector4 zzwx() const;
|
||||
Vector4 wzwx() const;
|
||||
Vector4 xwwx() const;
|
||||
Vector4 ywwx() const;
|
||||
Vector4 zwwx() const;
|
||||
Vector4 wwwx() const;
|
||||
Vector4 xxxy() const;
|
||||
Vector4 yxxy() const;
|
||||
Vector4 zxxy() const;
|
||||
Vector4 wxxy() const;
|
||||
Vector4 xyxy() const;
|
||||
Vector4 yyxy() const;
|
||||
Vector4 zyxy() const;
|
||||
Vector4 wyxy() const;
|
||||
Vector4 xzxy() const;
|
||||
Vector4 yzxy() const;
|
||||
Vector4 zzxy() const;
|
||||
Vector4 wzxy() const;
|
||||
Vector4 xwxy() const;
|
||||
Vector4 ywxy() const;
|
||||
Vector4 zwxy() const;
|
||||
Vector4 wwxy() const;
|
||||
Vector4 xxyy() const;
|
||||
Vector4 yxyy() const;
|
||||
Vector4 zxyy() const;
|
||||
Vector4 wxyy() const;
|
||||
Vector4 xyyy() const;
|
||||
Vector4 yyyy() const;
|
||||
Vector4 zyyy() const;
|
||||
Vector4 wyyy() const;
|
||||
Vector4 xzyy() const;
|
||||
Vector4 yzyy() const;
|
||||
Vector4 zzyy() const;
|
||||
Vector4 wzyy() const;
|
||||
Vector4 xwyy() const;
|
||||
Vector4 ywyy() const;
|
||||
Vector4 zwyy() const;
|
||||
Vector4 wwyy() const;
|
||||
Vector4 xxzy() const;
|
||||
Vector4 yxzy() const;
|
||||
Vector4 zxzy() const;
|
||||
Vector4 wxzy() const;
|
||||
Vector4 xyzy() const;
|
||||
Vector4 yyzy() const;
|
||||
Vector4 zyzy() const;
|
||||
Vector4 wyzy() const;
|
||||
Vector4 xzzy() const;
|
||||
Vector4 yzzy() const;
|
||||
Vector4 zzzy() const;
|
||||
Vector4 wzzy() const;
|
||||
Vector4 xwzy() const;
|
||||
Vector4 ywzy() const;
|
||||
Vector4 zwzy() const;
|
||||
Vector4 wwzy() const;
|
||||
Vector4 xxwy() const;
|
||||
Vector4 yxwy() const;
|
||||
Vector4 zxwy() const;
|
||||
Vector4 wxwy() const;
|
||||
Vector4 xywy() const;
|
||||
Vector4 yywy() const;
|
||||
Vector4 zywy() const;
|
||||
Vector4 wywy() const;
|
||||
Vector4 xzwy() const;
|
||||
Vector4 yzwy() const;
|
||||
Vector4 zzwy() const;
|
||||
Vector4 wzwy() const;
|
||||
Vector4 xwwy() const;
|
||||
Vector4 ywwy() const;
|
||||
Vector4 zwwy() const;
|
||||
Vector4 wwwy() const;
|
||||
Vector4 xxxz() const;
|
||||
Vector4 yxxz() const;
|
||||
Vector4 zxxz() const;
|
||||
Vector4 wxxz() const;
|
||||
Vector4 xyxz() const;
|
||||
Vector4 yyxz() const;
|
||||
Vector4 zyxz() const;
|
||||
Vector4 wyxz() const;
|
||||
Vector4 xzxz() const;
|
||||
Vector4 yzxz() const;
|
||||
Vector4 zzxz() const;
|
||||
Vector4 wzxz() const;
|
||||
Vector4 xwxz() const;
|
||||
Vector4 ywxz() const;
|
||||
Vector4 zwxz() const;
|
||||
Vector4 wwxz() const;
|
||||
Vector4 xxyz() const;
|
||||
Vector4 yxyz() const;
|
||||
Vector4 zxyz() const;
|
||||
Vector4 wxyz() const;
|
||||
Vector4 xyyz() const;
|
||||
Vector4 yyyz() const;
|
||||
Vector4 zyyz() const;
|
||||
Vector4 wyyz() const;
|
||||
Vector4 xzyz() const;
|
||||
Vector4 yzyz() const;
|
||||
Vector4 zzyz() const;
|
||||
Vector4 wzyz() const;
|
||||
Vector4 xwyz() const;
|
||||
Vector4 ywyz() const;
|
||||
Vector4 zwyz() const;
|
||||
Vector4 wwyz() const;
|
||||
Vector4 xxzz() const;
|
||||
Vector4 yxzz() const;
|
||||
Vector4 zxzz() const;
|
||||
Vector4 wxzz() const;
|
||||
Vector4 xyzz() const;
|
||||
Vector4 yyzz() const;
|
||||
Vector4 zyzz() const;
|
||||
Vector4 wyzz() const;
|
||||
Vector4 xzzz() const;
|
||||
Vector4 yzzz() const;
|
||||
Vector4 zzzz() const;
|
||||
Vector4 wzzz() const;
|
||||
Vector4 xwzz() const;
|
||||
Vector4 ywzz() const;
|
||||
Vector4 zwzz() const;
|
||||
Vector4 wwzz() const;
|
||||
Vector4 xxwz() const;
|
||||
Vector4 yxwz() const;
|
||||
Vector4 zxwz() const;
|
||||
Vector4 wxwz() const;
|
||||
Vector4 xywz() const;
|
||||
Vector4 yywz() const;
|
||||
Vector4 zywz() const;
|
||||
Vector4 wywz() const;
|
||||
Vector4 xzwz() const;
|
||||
Vector4 yzwz() const;
|
||||
Vector4 zzwz() const;
|
||||
Vector4 wzwz() const;
|
||||
Vector4 xwwz() const;
|
||||
Vector4 ywwz() const;
|
||||
Vector4 zwwz() const;
|
||||
Vector4 wwwz() const;
|
||||
Vector4 xxxw() const;
|
||||
Vector4 yxxw() const;
|
||||
Vector4 zxxw() const;
|
||||
Vector4 wxxw() const;
|
||||
Vector4 xyxw() const;
|
||||
Vector4 yyxw() const;
|
||||
Vector4 zyxw() const;
|
||||
Vector4 wyxw() const;
|
||||
Vector4 xzxw() const;
|
||||
Vector4 yzxw() const;
|
||||
Vector4 zzxw() const;
|
||||
Vector4 wzxw() const;
|
||||
Vector4 xwxw() const;
|
||||
Vector4 ywxw() const;
|
||||
Vector4 zwxw() const;
|
||||
Vector4 wwxw() const;
|
||||
Vector4 xxyw() const;
|
||||
Vector4 yxyw() const;
|
||||
Vector4 zxyw() const;
|
||||
Vector4 wxyw() const;
|
||||
Vector4 xyyw() const;
|
||||
Vector4 yyyw() const;
|
||||
Vector4 zyyw() const;
|
||||
Vector4 wyyw() const;
|
||||
Vector4 xzyw() const;
|
||||
Vector4 yzyw() const;
|
||||
Vector4 zzyw() const;
|
||||
Vector4 wzyw() const;
|
||||
Vector4 xwyw() const;
|
||||
Vector4 ywyw() const;
|
||||
Vector4 zwyw() const;
|
||||
Vector4 wwyw() const;
|
||||
Vector4 xxzw() const;
|
||||
Vector4 yxzw() const;
|
||||
Vector4 zxzw() const;
|
||||
Vector4 wxzw() const;
|
||||
Vector4 xyzw() const;
|
||||
Vector4 yyzw() const;
|
||||
Vector4 zyzw() const;
|
||||
Vector4 wyzw() const;
|
||||
Vector4 xzzw() const;
|
||||
Vector4 yzzw() const;
|
||||
Vector4 zzzw() const;
|
||||
Vector4 wzzw() const;
|
||||
Vector4 xwzw() const;
|
||||
Vector4 ywzw() const;
|
||||
Vector4 zwzw() const;
|
||||
Vector4 wwzw() const;
|
||||
Vector4 xxww() const;
|
||||
Vector4 yxww() const;
|
||||
Vector4 zxww() const;
|
||||
Vector4 wxww() const;
|
||||
Vector4 xyww() const;
|
||||
Vector4 yyww() const;
|
||||
Vector4 zyww() const;
|
||||
Vector4 wyww() const;
|
||||
Vector4 xzww() const;
|
||||
Vector4 yzww() const;
|
||||
Vector4 zzww() const;
|
||||
Vector4 wzww() const;
|
||||
Vector4 xwww() const;
|
||||
Vector4 ywww() const;
|
||||
Vector4 zwww() const;
|
||||
Vector4 wwww() const;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
inline G3D::Vector4 operator* (float s, const G3D::Vector4& v) {
|
||||
return v * s;
|
||||
}
|
||||
|
||||
unsigned int hashCode(const G3D::Vector4& v);
|
||||
|
||||
#include "Vector4.inl"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,193 @@
|
||||
/**
|
||||
@file Vector4.inl
|
||||
|
||||
@maintainer Morgan McGuire, [email protected]
|
||||
|
||||
@created 2002-07-09
|
||||
@edited 2003-02-10
|
||||
*/
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline unsigned int hashCode(const G3D::Vector4& v) {
|
||||
return v.hashCode();
|
||||
}
|
||||
|
||||
namespace G3D {
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector4::Vector4() {
|
||||
x = y = z = w = 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline Vector4::Vector4 (float fX, float fY, float fZ, float fW) {
|
||||
x = fX;
|
||||
y = fY;
|
||||
z = fZ;
|
||||
w = fW;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector4::Vector4 (float afCoordinate[4]) {
|
||||
x = afCoordinate[0];
|
||||
y = afCoordinate[1];
|
||||
z = afCoordinate[2];
|
||||
w = afCoordinate[3];
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector4::Vector4(const Vector4& rkVector) {
|
||||
x = rkVector.x;
|
||||
y = rkVector.y;
|
||||
z = rkVector.z;
|
||||
w = rkVector.w;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector4::Vector4(const Vector3& rkVector, float fW) {
|
||||
x = rkVector.x;
|
||||
y = rkVector.y;
|
||||
z = rkVector.z;
|
||||
w = fW;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline float& Vector4::operator[] (int i) {
|
||||
return ((float*)this)[i];
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline const float& Vector4::operator[] (int i) const {
|
||||
return ((float*)this)[i];
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector4::operator float* () {
|
||||
return (float*)this;
|
||||
}
|
||||
|
||||
inline Vector4::operator const float* () const {
|
||||
return (float*)this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector4& Vector4::operator= (const Vector4& rkVector) {
|
||||
x = rkVector.x;
|
||||
y = rkVector.y;
|
||||
z = rkVector.z;
|
||||
w = rkVector.w;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline bool Vector4::operator== (const Vector4& rkVector) const {
|
||||
return ( (x == rkVector.x) && (y == rkVector.y) && (z == rkVector.z) && (w == rkVector.w));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline bool Vector4::operator!= (const Vector4& rkVector) const {
|
||||
return ( x != rkVector.x || y != rkVector.y || z != rkVector.z || w != rkVector.w);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector4 Vector4::operator+ (const Vector4& rkVector) const {
|
||||
return Vector4(x + rkVector.x, y + rkVector.y, z + rkVector.z, w + rkVector.w);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector4 Vector4::operator- (const Vector4& rkVector) const {
|
||||
return Vector4(x - rkVector.x, y - rkVector.y, z - rkVector.z, w - rkVector.w);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector4 Vector4::operator* (float fScalar) const {
|
||||
return Vector4(fScalar*x, fScalar*y, fScalar*z, fScalar*w);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector4 Vector4::operator- () const {
|
||||
return Vector4( -x, -y, -z, -w);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector4& Vector4::operator+= (const Vector4& rkVector) {
|
||||
x += rkVector.x;
|
||||
y += rkVector.y;
|
||||
z += rkVector.z;
|
||||
w += rkVector.w;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector4& Vector4::operator-= (const Vector4& rkVector) {
|
||||
x -= rkVector.x;
|
||||
y -= rkVector.y;
|
||||
z -= rkVector.z;
|
||||
w -= rkVector.w;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline Vector4 Vector4::lerp(const Vector4& v, float alpha) const {
|
||||
return (*this) + (v - *this) * alpha;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector4& Vector4::operator*= (float fScalar) {
|
||||
x *= fScalar;
|
||||
y *= fScalar;
|
||||
z *= fScalar;
|
||||
w *= fScalar;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline float Vector4::dot(const Vector4& rkVector) const {
|
||||
return x*rkVector.x + y*rkVector.y + z*rkVector.z + w*rkVector.w;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector4 Vector4::min(const Vector4 &v) const {
|
||||
return Vector4(G3D::min(v.x, x), G3D::min(v.y, y), G3D::min(v.z, z), G3D::min(v.w, w));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Vector4 Vector4::max(const Vector4 &v) const {
|
||||
return Vector4(G3D::max(v.x, x), G3D::max(v.y, y), G3D::max(v.z, z), G3D::max(v.w, w));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline bool Vector4::isZero() const {
|
||||
return (x == 0.0f) && (y == 0.0f) && (z == 0.0f) && (w == 0.0f);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline bool Vector4::isFinite() const {
|
||||
return G3D::isFinite(x) && G3D::isFinite(y) && G3D::isFinite(z) && G3D::isFinite(w);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline bool Vector4::isUnit() const {
|
||||
return squaredLength() == 1.0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline float Vector4::length() const {
|
||||
return sqrtf(squaredLength());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline float Vector4::squaredLength() const {
|
||||
return x * x + y * y + z * z + w * w;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
#ifndef G3D_LITE_DEBUG_H
|
||||
#define G3D_LITE_DEBUG_H
|
||||
|
||||
#define debugStatement(x)
|
||||
#define debugAssert(x)
|
||||
#define debugAssertM(x, y)
|
||||
#define alwaysAssertM(x, y)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
@file format.h
|
||||
|
||||
@maintainer Morgan McGuire, [email protected]
|
||||
|
||||
@author 2000-09-09
|
||||
@edited 2005-11-03
|
||||
|
||||
Copyright 2000-2005, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_FORMAT_H
|
||||
#define G3D_FORMAT_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
#include <cstdarg>
|
||||
#include <assert.h>
|
||||
#ifndef G3D_WIN32
|
||||
// Don't include varargs.h for some random
|
||||
// gcc reason
|
||||
//#include <varargs.h>
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#ifndef __cdecl
|
||||
#define __cdecl __attribute__((cdecl))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Produces a string from arguments of the style of printf. This avoids
|
||||
problems with buffer overflows when using sprintf and makes it easy
|
||||
to use the result functionally. This function is fast when the resulting
|
||||
string is under 160 characters (not including terminator) and slower
|
||||
when the string is longer.
|
||||
*/
|
||||
std::string format(
|
||||
const char* fmt
|
||||
...) G3D_CHECK_PRINTF_ARGS;
|
||||
|
||||
/**
|
||||
Like format, but can be called with the argument list from a ... function.
|
||||
*/
|
||||
std::string vformat(
|
||||
const char* fmt,
|
||||
va_list argPtr) G3D_CHECK_VPRINTF_ARGS;
|
||||
|
||||
|
||||
}; // namespace
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,525 @@
|
||||
/**
|
||||
@file g3dmath.h
|
||||
|
||||
Math util class.
|
||||
|
||||
@maintainer Morgan McGuire, [email protected]
|
||||
@cite highestBit by Jukka Liimatta
|
||||
|
||||
@created 2001-06-02
|
||||
@edited 2006-01-16
|
||||
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3DMATH_H
|
||||
#define G3DMATH_H
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Disable conditional expression is constant, which occurs incorrectly on inlined functions
|
||||
# pragma warning (push)
|
||||
# pragma warning (disable : 4127)
|
||||
// disable: "C++ exception handler used"
|
||||
# pragma warning (disable : 4530)
|
||||
#endif
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include <ctype.h>
|
||||
#include <string>
|
||||
#include <float.h>
|
||||
#include <limits>
|
||||
|
||||
/*These defines enable functionality introduced with the 1999 ISO C
|
||||
**standard. They must be defined before the inclusion of math.h to
|
||||
**engage them. If optimisation is enabled, these functions will be
|
||||
**inlined. With optimisation switched off, you have to link in the
|
||||
**maths library using -lm.
|
||||
*/
|
||||
|
||||
#define _ISOC9X_SOURCE1
|
||||
#define _ISOC99_SOURCE1
|
||||
#define __USE_ISOC9X1
|
||||
#define __USE_ISOC991
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "G3D/debug.h"
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
namespace G3D {
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
#if !defined(_WIN64)
|
||||
|
||||
/**
|
||||
Win32 implementation of the C99 fast rounding routines.
|
||||
|
||||
@cite routines are
|
||||
Copyright (C) 2001 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this file for any
|
||||
purpose is hereby granted without fee, provided that the above copyright
|
||||
and this permission notice appear in all copies. No representations are
|
||||
made about the suitability of this software for any purpose. It is
|
||||
provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
__inline long int lrint (double flt) {
|
||||
int intgr;
|
||||
|
||||
_asm {
|
||||
fld flt
|
||||
fistp intgr
|
||||
};
|
||||
|
||||
return intgr;
|
||||
}
|
||||
|
||||
__inline long int lrintf(float flt) {
|
||||
int intgr;
|
||||
|
||||
_asm {
|
||||
fld flt
|
||||
fistp intgr
|
||||
};
|
||||
|
||||
return intgr;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
__inline long int lrint (double flt) {
|
||||
return (long int)floor(flt+0.5f);
|
||||
}
|
||||
|
||||
__inline long int lrintf(float flt) {
|
||||
return (long int)floorf(flt+0.5f);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
const double fuzzyEpsilon = 0.00001;
|
||||
|
||||
/** Returns a reference to a static double.
|
||||
This value should not be tested against directly, instead
|
||||
G3D::isNan() and G3D::isFinite() will return reliable results. */
|
||||
inline const double& inf() {
|
||||
|
||||
// We already have <limits> included but
|
||||
// not using it in older gcc for safe compilations
|
||||
#if (__GNUC__ == 2)
|
||||
static const double i = 1.0/sin(0.0);
|
||||
#else
|
||||
// double is a standard type and should have infinity
|
||||
static const double i = std::numeric_limits<double>::infinity();
|
||||
#endif
|
||||
return i;
|
||||
}
|
||||
|
||||
/** Returns a reference to a static double.
|
||||
This value should not be tested against directly, instead
|
||||
G3D::isNan() and G3D::isFinite() will return reliable results. */
|
||||
inline const double& nan() {
|
||||
|
||||
// We already have <limits> included but
|
||||
// not using it in older gcc for safe compilations
|
||||
#if (__GNUC__ == 2)
|
||||
static const double n = 0.0/sin(0.0);
|
||||
#else
|
||||
// double is a standard type and should have quiet NaN
|
||||
static const double n = std::numeric_limits<double>::quiet_NaN();
|
||||
#endif
|
||||
return n;
|
||||
}
|
||||
|
||||
/** Returns a reference to a static double. Use instead of G3D_PI. */
|
||||
inline const double& pi() {
|
||||
static const double p = 3.1415926535898;
|
||||
return p;
|
||||
}
|
||||
|
||||
/** Returns a reference to a static double. Use instead of G3D_HALF_PI. */
|
||||
inline const double& halfPi() {
|
||||
static const double p = 1.5707963267949;
|
||||
return p;
|
||||
}
|
||||
|
||||
/** Returns a reference to a static double. Use instead of G3D_TWO_PI. */
|
||||
inline const double& twoPi() {
|
||||
static const double p = 6.283185;
|
||||
return p;
|
||||
}
|
||||
|
||||
/** @def G3D_PI
|
||||
@deprecated Use G3D::pi() instead. */
|
||||
#define G3D_PI (3.1415926535898)
|
||||
/** @def G3D_HALF_PI
|
||||
@deprecated Use G3D::halfPi() instead. */
|
||||
#define G3D_HALF_PI (1.5707963267949)
|
||||
/** @def G3D_TWO_PI
|
||||
@deprecated Use G3D::twoPi() instead. */
|
||||
#define G3D_TWO_PI (6.283185)
|
||||
|
||||
typedef signed char int8;
|
||||
typedef unsigned char uint8;
|
||||
typedef short int16;
|
||||
typedef unsigned short uint16;
|
||||
typedef int int32;
|
||||
typedef unsigned int uint32;
|
||||
|
||||
#ifdef _MSC_EXTENSIONS
|
||||
typedef __int64 int64;
|
||||
typedef unsigned __int64 uint64;
|
||||
#else
|
||||
typedef long long int64;
|
||||
typedef unsigned long long uint64;
|
||||
#endif
|
||||
typedef unsigned int uint;
|
||||
|
||||
typedef float float32;
|
||||
typedef double float64;
|
||||
|
||||
int iAbs(int iValue);
|
||||
int iCeil(double fValue);
|
||||
|
||||
/**
|
||||
Clamps the value to the range [low, hi] (inclusive)
|
||||
*/
|
||||
int iClamp(int val, int low, int hi);
|
||||
double clamp(double val, double low, double hi);
|
||||
float clamp(float val, float low, float hi);
|
||||
|
||||
/**
|
||||
Returns a + (b - a) * f;
|
||||
*/
|
||||
inline double lerp(double a, double b, double f) {
|
||||
return a + (b - a) * f;
|
||||
}
|
||||
|
||||
inline float lerp(float a, float b, float f) {
|
||||
return a + (b - a) * f;
|
||||
}
|
||||
|
||||
/**
|
||||
Wraps the value to the range [0, hi) (exclusive
|
||||
on the high end). This is like the clock arithmetic
|
||||
produced by % (modulo) except the result is guaranteed
|
||||
to be positive.
|
||||
*/
|
||||
int iWrap(int val, int hi);
|
||||
|
||||
int iFloor(double fValue);
|
||||
|
||||
int iSign(int iValue);
|
||||
int iSign(double fValue);
|
||||
|
||||
inline int iSign(float f) {
|
||||
return iSign((double)f);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Fast round to integer using the lrint routine.
|
||||
Typically 6x faster than casting to integer.
|
||||
*/
|
||||
inline int iRound(double fValue) {
|
||||
return lrint(fValue);
|
||||
}
|
||||
|
||||
/**
|
||||
Fast round to integer using the lrint routine.
|
||||
Typically 6x faster than casting to integer.
|
||||
*/
|
||||
inline int iRound(float f) {
|
||||
return lrintf(f);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a random number uniformly at random between low and hi
|
||||
(inclusive).
|
||||
*/
|
||||
int iRandom(int low, int hi);
|
||||
|
||||
double abs (double fValue);
|
||||
double aCos (double fValue);
|
||||
double aSin (double fValue);
|
||||
double aTan (double fValue);
|
||||
double aTan2 (double fY, double fX);
|
||||
double sign (double fValue);
|
||||
double square (double fValue);
|
||||
|
||||
/**
|
||||
Returns true if the argument is a finite real number.
|
||||
*/
|
||||
bool isFinite(double x);
|
||||
|
||||
/**
|
||||
Returns true if the argument is NaN (not a number).
|
||||
You can't use x == nan to test this because all
|
||||
comparisons against nan return false.
|
||||
*/
|
||||
bool isNaN(double x);
|
||||
|
||||
/**
|
||||
Computes x % 3.
|
||||
*/
|
||||
int iMod3(int x);
|
||||
|
||||
/**
|
||||
[0, 1]
|
||||
@deprecated use uniformRandom()
|
||||
*/
|
||||
double unitRandom ();
|
||||
|
||||
/**
|
||||
Uniform random number between low and hi, inclusive.
|
||||
@deprecated use uniformRandom()
|
||||
*/
|
||||
double random(double low, double hi);
|
||||
|
||||
/**
|
||||
[-1, 1]
|
||||
@deprecated use uniformRandom()
|
||||
*/
|
||||
double symmetricRandom ();
|
||||
|
||||
/**
|
||||
Uniform random number between low and hi, inclusive. [low, hi]
|
||||
*/
|
||||
float uniformRandom(float low = 0.0f, float hi = 1.0f);
|
||||
|
||||
/**
|
||||
Normally distributed random number.
|
||||
*/
|
||||
float gaussRandom(float mean = 0.0f, float stdev = 1.0f);
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER <= 1200)
|
||||
|
||||
/** VC6 lacks std::min and std::max */
|
||||
inline double min(double x, double y) {
|
||||
return std::_cpp_min(x, y);
|
||||
}
|
||||
|
||||
/** VC6 lacks std::min and std::max */
|
||||
inline float min(float x, float y) {
|
||||
return std::_cpp_min(x, y);
|
||||
}
|
||||
|
||||
/** VC6 lacks std::min and std::max */
|
||||
inline int min(int x, int y) {
|
||||
return std::_cpp_min(x, y);
|
||||
}
|
||||
|
||||
/** VC6 lacks std::min and std::max */
|
||||
inline double max(double x, double y) {
|
||||
return std::_cpp_max(x, y);
|
||||
}
|
||||
|
||||
/** VC6 lacks std::min and std::max */
|
||||
inline float max(float x, float y) {
|
||||
return std::_cpp_max(x, y);
|
||||
}
|
||||
|
||||
/** VC6 lacks std::min and std::max */
|
||||
inline int max(int x, int y) {
|
||||
return std::_cpp_max(x, y);
|
||||
}
|
||||
|
||||
#else
|
||||
template <class T>
|
||||
inline T min(const T& x, const T& y) {
|
||||
return std::min<T>(x, y);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T max(const T& x, const T& y) {
|
||||
return std::max<T>(x, y);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int iMin(int x, int y);
|
||||
int iMax(int x, int y);
|
||||
|
||||
double square(double x);
|
||||
double sumSquares(double x, double y);
|
||||
double sumSquares(double x, double y, double z);
|
||||
double distance(double x, double y);
|
||||
double distance(double x, double y, double z);
|
||||
|
||||
/**
|
||||
Returnes the 0-based index of the highest 1 bit from
|
||||
the left. -1 means the number was 0.
|
||||
|
||||
@cite Based on code by [email protected]
|
||||
*/
|
||||
int highestBit(uint32 x);
|
||||
|
||||
/**
|
||||
Note that fuzzyEq(a, b) && fuzzyEq(b, c) does not imply
|
||||
fuzzyEq(a, c), although that will be the case on some
|
||||
occasions.
|
||||
*/
|
||||
bool fuzzyEq(double a, double b);
|
||||
|
||||
/** True if a is definitely not equal to b.
|
||||
Guaranteed false if a == b.
|
||||
Possibly false when a != b.*/
|
||||
bool fuzzyNe(double a, double b);
|
||||
|
||||
/** Is a strictly greater than b? (Guaranteed false if a <= b).
|
||||
(Possibly false if a > b) */
|
||||
bool fuzzyGt(double a, double b);
|
||||
|
||||
/** Is a near or greater than b? */
|
||||
bool fuzzyGe(double a, double b);
|
||||
|
||||
/** Is a strictly less than b? (Guaranteed false if a >= b)*/
|
||||
bool fuzzyLt(double a, double b);
|
||||
|
||||
/** Is a near or less than b? */
|
||||
bool fuzzyLe(double a, double b);
|
||||
|
||||
/**
|
||||
Computes 1 / sqrt(x).
|
||||
*/
|
||||
inline float rsq(float x) {
|
||||
return 1.0f / sqrtf(x);
|
||||
}
|
||||
|
||||
/**
|
||||
Uses SSE to implement rsq.
|
||||
@cite Nick [email protected]
|
||||
*/
|
||||
inline float SSErsq(float x) {
|
||||
|
||||
#if defined(SSE) && defined(G3D_WIN32) && !defined(_WIN64)
|
||||
__asm {
|
||||
movss xmm0, x
|
||||
rsqrtss xmm0, xmm0
|
||||
movss x, xmm0
|
||||
}
|
||||
return x;
|
||||
#else
|
||||
return 1.0f / sqrt(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
Return the next power of 2 higher than the input
|
||||
If the input is already a power of 2, the output will be the same
|
||||
as the input.
|
||||
*/
|
||||
int ceilPow2(unsigned int in);
|
||||
|
||||
/**
|
||||
* True if num is a power of two.
|
||||
*/
|
||||
bool isPow2(int num);
|
||||
|
||||
bool isOdd(int num);
|
||||
bool isEven(int num);
|
||||
|
||||
double toRadians(double deg);
|
||||
double toDegrees(double rad);
|
||||
|
||||
/**
|
||||
Returns true if x is not exactly equal to 0.0f.
|
||||
*/
|
||||
inline bool any(float x) {
|
||||
return x != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns true if x is not exactly equal to 0.0f.
|
||||
*/
|
||||
inline bool all(float x) {
|
||||
return x != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
v / v (for DirectX/Cg support)
|
||||
*/
|
||||
inline float normalize(float v) {
|
||||
return v / v;
|
||||
}
|
||||
|
||||
/**
|
||||
a * b (for DirectX/Cg support)
|
||||
*/
|
||||
inline float dot(float a, float b) {
|
||||
return a * b;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
a * b (for DirectX/Cg support)
|
||||
*/
|
||||
inline float mul(float a, float b) {
|
||||
return a * b;
|
||||
}
|
||||
|
||||
/**
|
||||
2^x
|
||||
*/
|
||||
inline double exp2(double x) {
|
||||
return pow(2.0, x);
|
||||
}
|
||||
|
||||
inline double rsqrt(double x) {
|
||||
return 1.0 / sqrt(x);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
sin(x)/x
|
||||
*/
|
||||
inline double sinc(double x) {
|
||||
double r = sin(x) / x;
|
||||
|
||||
if (isNaN(r)) {
|
||||
return 1.0;
|
||||
} else {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Computes a floating point modulo; the result is t wrapped to the range [lo, hi).
|
||||
*/
|
||||
inline double wrap(double t, double lo, double hi) {
|
||||
if ((t >= lo) && (t < hi)) {
|
||||
return t;
|
||||
}
|
||||
|
||||
debugAssert(hi > lo);
|
||||
|
||||
double interval = hi - lo;
|
||||
|
||||
return t - interval * iFloor((t - lo) / interval);
|
||||
|
||||
}
|
||||
|
||||
inline double wrap(double t, double hi) {
|
||||
return wrap(t, 0, hi);
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning (pop)
|
||||
#endif
|
||||
|
||||
#include "g3dmath.inl"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,289 @@
|
||||
/**
|
||||
@file g3dmath.inl
|
||||
|
||||
@maintainer Morgan McGuire, [email protected]
|
||||
|
||||
@created 2001-06-02
|
||||
@edited 2006-01-14
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Disable conditional expression is constant, which occurs incorrectly on inlined functions
|
||||
# pragma warning (push)
|
||||
# pragma warning( disable : 4127 )
|
||||
#endif
|
||||
|
||||
namespace G3D {
|
||||
|
||||
inline bool isNaN(double x) {
|
||||
bool b1 = (x < 0.0);
|
||||
bool b2 = (x >= 0.0);
|
||||
bool b3 = !(b1 || b2);
|
||||
return b3;
|
||||
}
|
||||
|
||||
inline bool isFinite(double x) {
|
||||
return ! isNaN(x) && (x < G3D::inf()) && (x > -G3D::inf());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline int iAbs (int iValue) {
|
||||
return ( iValue >= 0 ? iValue : -iValue );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline int iCeil (double fValue) {
|
||||
return int(::ceil(fValue));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline int iClamp(int val, int low, int hi) {
|
||||
debugAssert(low <= hi);
|
||||
if (val <= low) {
|
||||
return low;
|
||||
} else if (val >= hi) {
|
||||
return hi;
|
||||
} else {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline double clamp(double val, double low, double hi) {
|
||||
debugAssert(low <= hi);
|
||||
if (val <= low) {
|
||||
return low;
|
||||
} else if (val >= hi) {
|
||||
return hi;
|
||||
} else {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
inline float clamp(float val, float low, float hi) {
|
||||
debugAssert(low <= hi);
|
||||
if (val <= low) {
|
||||
return low;
|
||||
} else if (val >= hi) {
|
||||
return hi;
|
||||
} else {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline int iWrap(int val, int hi) {
|
||||
if (val < 0) {
|
||||
return ((val % hi) + hi) % hi;
|
||||
} else {
|
||||
return val % hi;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline int iFloor (double fValue) {
|
||||
return int(::floor(fValue));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline int iSign (int iValue) {
|
||||
return ( iValue > 0 ? + 1 : ( iValue < 0 ? -1 : 0 ) );
|
||||
}
|
||||
|
||||
inline int iSign (double fValue) {
|
||||
return ( fValue > 0.0 ? + 1 : ( fValue < 0.0 ? -1 : 0 ) );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline double abs (double fValue) {
|
||||
return double(::fabs(fValue));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline double aCos (double fValue) {
|
||||
if ( -1.0 < fValue ) {
|
||||
if ( fValue < 1.0 )
|
||||
return double(::acos(fValue));
|
||||
else
|
||||
return 0.0;
|
||||
} else {
|
||||
return G3D_PI;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline double aSin (double fValue) {
|
||||
if ( -1.0 < fValue ) {
|
||||
if ( fValue < 1.0 ) {
|
||||
return double(::asin(fValue));
|
||||
} else {
|
||||
return -G3D_HALF_PI;
|
||||
}
|
||||
} else {
|
||||
return G3D_HALF_PI;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline double aTan (double fValue) {
|
||||
return double(::atan(fValue));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline double aTan2 (double fY, double fX) {
|
||||
return double(::atan2(fY, fX));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline double sign (double fValue) {
|
||||
if (fValue > 0.0) {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
if (fValue < 0.0) {
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
inline double G3D_DEPRECATED unitRandom () {
|
||||
return double(::rand()) / double(RAND_MAX);
|
||||
}
|
||||
|
||||
inline float uniformRandom(float low, float hi) {
|
||||
return (hi - low) * float(::rand()) / float(RAND_MAX) + low;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline double G3D_DEPRECATED symmetricRandom () {
|
||||
return 2.0 * double(::rand()) / double(RAND_MAX) - 1.0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline double square(double x) {
|
||||
return x * x;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline double sumSquares(double x, double y) {
|
||||
return x*x + y*y;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline double sumSquares(double x, double y, double z) {
|
||||
return x*x + y*y + z*z;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline double distance(double x, double y) {
|
||||
return sqrt(sumSquares(x, y));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline double distance(double x, double y, double z) {
|
||||
return sqrt(sumSquares(x, y, z));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
/** @deprecated use G3D::min */
|
||||
inline int iMin(int x, int y) {
|
||||
return (x >= y) ? y : x;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/** @deprecated use G3D::min */
|
||||
inline int iMax(int x, int y) {
|
||||
return (x >= y) ? x : y;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline int ceilPow2(unsigned int in) {
|
||||
in -= 1;
|
||||
|
||||
in |= in >> 16;
|
||||
in |= in >> 8;
|
||||
in |= in >> 4;
|
||||
in |= in >> 2;
|
||||
in |= in >> 1;
|
||||
|
||||
return in + 1;
|
||||
}
|
||||
|
||||
inline bool isPow2(int num) {
|
||||
return ((num & -num) == num);
|
||||
}
|
||||
|
||||
inline bool isOdd(int num) {
|
||||
return (num & 1) == 1;
|
||||
}
|
||||
|
||||
inline bool isEven(int num) {
|
||||
return (num & 1) == 0;
|
||||
}
|
||||
|
||||
inline double toRadians(double deg) {
|
||||
return deg * G3D_PI / 180.0;
|
||||
}
|
||||
|
||||
inline double toDegrees(double rad) {
|
||||
return rad * 180.0 / G3D_PI;
|
||||
}
|
||||
|
||||
/**
|
||||
Computes an appropriate epsilon for comparing a and b.
|
||||
*/
|
||||
inline double eps(double a, double b) {
|
||||
// For a and b to be nearly equal, they must have nearly
|
||||
// the same magnitude. This means that we can ignore b
|
||||
// since it either has the same magnitude or the comparison
|
||||
// will fail anyway.
|
||||
(void)b;
|
||||
const double aa = abs(a) + 1;
|
||||
if (aa == inf()) {
|
||||
return fuzzyEpsilon;
|
||||
} else {
|
||||
return fuzzyEpsilon * aa;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool fuzzyEq(double a, double b) {
|
||||
return (a == b) || (abs(a - b) <= eps(a, b));
|
||||
}
|
||||
|
||||
inline bool fuzzyNe(double a, double b) {
|
||||
return ! fuzzyEq(a, b);
|
||||
}
|
||||
|
||||
inline bool fuzzyGt(double a, double b) {
|
||||
return a > b + eps(a, b);
|
||||
}
|
||||
|
||||
inline bool fuzzyGe(double a, double b) {
|
||||
return a > b - eps(a, b);
|
||||
}
|
||||
|
||||
inline bool fuzzyLt(double a, double b) {
|
||||
return a < b - eps(a, b);
|
||||
}
|
||||
|
||||
inline bool fuzzyLe(double a, double b) {
|
||||
return a < b + eps(a, b);
|
||||
}
|
||||
|
||||
inline int iMod3(int x) {
|
||||
return x % 3;
|
||||
}
|
||||
|
||||
} // namespace G3D
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Disable conditional expression is constant, which occurs incorrectly on inlined functions
|
||||
# pragma warning (pop)
|
||||
#endif
|
||||
@@ -0,0 +1,269 @@
|
||||
/**
|
||||
@file platform.h
|
||||
|
||||
#defines for platform specific issues.
|
||||
|
||||
@maintainer Morgan McGuire, [email protected]
|
||||
|
||||
@created 2003-06-09
|
||||
@edited 2006-01-16
|
||||
*/
|
||||
|
||||
#ifndef G3D_PLATFORM_H
|
||||
#define G3D_PLATFORM_H
|
||||
|
||||
/**
|
||||
The version number of G3D in the form: MmmBB ->
|
||||
version M.mm [beta BB]
|
||||
*/
|
||||
#define G3D_VER 61000
|
||||
|
||||
#if defined(G3D_RELEASEDEBUG)
|
||||
# define G3D_DEBUGRELEASE
|
||||
#endif
|
||||
|
||||
#if defined(G3D_DEBUGRELEASE) && defined(_DEBUG)
|
||||
# undef _DEBUG
|
||||
#endif
|
||||
|
||||
#if !defined(G3D_DEBUG) && (defined(_DEBUG) || defined(G3D_DEBUGRELEASE))
|
||||
# define G3D_DEBUG
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define G3D_WIN32
|
||||
#elif defined(__MINGW32__)
|
||||
#define G3D_WIN32
|
||||
#define G3D_MINGW32
|
||||
#elif defined(__linux__)
|
||||
#define G3D_LINUX
|
||||
#elif defined(__OpenBSD__)
|
||||
#define G3D_LINUX
|
||||
#elif defined(__FreeBSD__)
|
||||
#define G3D_LINUX
|
||||
#elif defined(__NetBSD__)
|
||||
#define G3D_LINUX
|
||||
#elif defined(__APPLE__)
|
||||
#define G3D_OSX
|
||||
#else
|
||||
#error Unknown platform
|
||||
#endif
|
||||
|
||||
|
||||
// Default to compiling with SSE, but if you want to compile
|
||||
// without installing SP5.0 and the Processor Pack on Windows, compile with NO_SSE
|
||||
// defined (can be passed to the compiler command line with /D "NO_SSE")
|
||||
#if !defined(NO_SSE)
|
||||
#define SSE
|
||||
#endif
|
||||
|
||||
#ifdef G3D_WIN32
|
||||
// Turn off warnings about deprecated C routines (TODO: revisit)
|
||||
# pragma warning (disable : 4996)
|
||||
#endif
|
||||
|
||||
// On g++, recognize cases where the -msse2 flag was not specified
|
||||
#if defined(SSE) && defined(__GNUC__) && ! defined (__SSE__)
|
||||
# undef SSE
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# if __STDC_VERSION__ < 199901
|
||||
# define restrict __restrict__
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
// Verify that the supported compilers are being used and that this is a known
|
||||
// processor.
|
||||
|
||||
#ifdef G3D_LINUX
|
||||
# ifndef __GNUC__
|
||||
# error G3D only supports the gcc compiler on Linux.
|
||||
# endif
|
||||
|
||||
//# ifndef __i386__
|
||||
//# error G3D only supports x86 machines on Linux.
|
||||
//# endif
|
||||
|
||||
# define G3D_DEPRECATED __attribute__((__deprecated__))
|
||||
|
||||
# ifndef __cdecl
|
||||
# define __cdecl __attribute__((cdecl))
|
||||
# endif
|
||||
|
||||
# ifndef __stdcall
|
||||
# define __stdcall __attribute__((stdcall))
|
||||
# endif
|
||||
|
||||
# define G3D_CHECK_PRINTF_METHOD_ARGS __attribute__((__format__(__printf__, 2, 3)))
|
||||
# define G3D_CHECK_VPRINTF_METHOD_ARGS __attribute__((__format__(__printf__, 2, 0)))
|
||||
# define G3D_CHECK_PRINTF_ARGS __attribute__((__format__(__printf__, 1, 2)))
|
||||
# define G3D_CHECK_VPRINTF_ARGS __attribute__((__format__(__printf__, 1, 0)))
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef G3D_OSX
|
||||
#ifndef __GNUC__
|
||||
#error G3D only supports the gcc compiler on OS X.
|
||||
#endif
|
||||
|
||||
#if defined(__i386__)
|
||||
#define G3D_OSX_INTEL
|
||||
#elif defined(__PPC__)
|
||||
#define G3D_OSX_PPC
|
||||
#else
|
||||
#define G3D_OSX_UNKNOWN
|
||||
#endif
|
||||
|
||||
# ifndef __cdecl
|
||||
# define __cdecl __attribute__((cdecl))
|
||||
# endif
|
||||
|
||||
# ifndef __stdcall
|
||||
# define __stdcall __attribute__((stdcall))
|
||||
# endif
|
||||
|
||||
# define G3D_DEPRECATED __attribute__((__deprecated__))
|
||||
|
||||
# define G3D_CHECK_PRINTF_METHOD_ARGS __attribute__((__format__(__printf__, 2, 3)))
|
||||
# define G3D_CHECK_VPRINTF_METHOD_ARGS __attribute__((__format__(__printf__, 2, 0)))
|
||||
# define G3D_CHECK_PRINTF_ARGS __attribute__((__format__(__printf__, 1, 2)))
|
||||
# define G3D_CHECK_VPRINTF_ARGS __attribute__((__format__(__printf__, 1, 0)))
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef G3D_WIN32
|
||||
// Microsoft Visual C++ 7.1 _MSC_VER = 1310
|
||||
// Microsoft Visual C++ 7.0 _MSC_VER = 1300
|
||||
// Microsoft Visual C++ 6.0 _MSC_VER = 1200
|
||||
// Microsoft Visual C++ 5.0 _MSC_VER = 1100
|
||||
|
||||
// Old versions of MSVC (6.0 and previous) don't
|
||||
// support C99 for loop scoping rules. This fixes them.
|
||||
# if (_MSC_VER <= 1200)
|
||||
// This trick will generate a warning; disable the warning
|
||||
# pragma warning (disable : 4127)
|
||||
# define for if (false) {} else for
|
||||
# endif
|
||||
|
||||
# if (_MSC_VER <= 1200)
|
||||
// Nothing we can do on VC6 for deprecated functions
|
||||
# define G3D_DEPRECATED
|
||||
# else
|
||||
# define G3D_DEPRECATED __declspec(deprecated)
|
||||
# endif
|
||||
|
||||
// Prevent Winsock conflicts by hiding the winsock API
|
||||
#ifndef _WINSOCKAPI_
|
||||
# define _G3D_INTERNAL_HIDE_WINSOCK_
|
||||
# define _WINSOCKAPI_
|
||||
# endif
|
||||
|
||||
// Disable 'name too long for browse information' warning
|
||||
# pragma warning (disable : 4786)
|
||||
// TODO: remove
|
||||
# pragma warning (disable : 4244)
|
||||
|
||||
# if defined(_MSC_VER) && (_MSC_VER <= 1200)
|
||||
// VC6 std:: has signed problems in it
|
||||
# pragma warning (disable : 4018)
|
||||
# endif
|
||||
|
||||
# define ZLIB_WINAPI
|
||||
|
||||
// Mingw32 defines restrict
|
||||
# ifndef G3D_MINGW32
|
||||
# define restrict
|
||||
# endif
|
||||
|
||||
# define G3D_CHECK_PRINTF_ARGS
|
||||
# define G3D_CHECK_VPRINTF_ARGS
|
||||
# define G3D_CHECK_PRINTF_METHOD_ARGS
|
||||
# define G3D_CHECK_VPRINTF_METHOD_ARGS
|
||||
|
||||
// On MSVC, we need to link against the multithreaded DLL version of
|
||||
// the C++ runtime because that is what SDL and ZLIB are compiled
|
||||
// against. This is not the default for MSVC, so we set the following
|
||||
// defines to force correct linking.
|
||||
//
|
||||
// For documentation on compiler options, see:
|
||||
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/_core_.2f.md.2c_2f.ml.2c_2f.mt.2c_2f.ld.asp
|
||||
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/HTML/_core_Compiler_Reference.asp
|
||||
//
|
||||
|
||||
#if 0 //ignore that for mangos
|
||||
// DLL runtime
|
||||
#ifndef _DLL
|
||||
#define _DLL
|
||||
#endif
|
||||
|
||||
// Multithreaded runtime
|
||||
#ifndef _MT
|
||||
#define _MT 1
|
||||
#endif
|
||||
// Ensure that we aren't forced into the static lib
|
||||
#ifdef _STATIC_CPPLIB
|
||||
#undef _STATIC_CPPLIB
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _DEBUG
|
||||
#pragma comment (linker, "/NODEFAULTLIB:libc.lib")
|
||||
#pragma comment (linker, "/NODEFAULTLIB:libcmt.lib")
|
||||
#pragma comment (linker, "/NODEFAULTLIB:msvcrt.lib")
|
||||
#pragma comment (linker, "/NODEFAULTLIB:libcd.lib")
|
||||
#pragma comment (linker, "/NODEFAULTLIB:msvcrtd.lib")
|
||||
#else
|
||||
#pragma comment(linker, "/NODEFAULTLIB:LIBC.LIB")
|
||||
#pragma comment(linker, "/NODEFAULTLIB:msvcrt.lib")
|
||||
#pragma comment(linker, "/NODEFAULTLIB:libcd.lib")
|
||||
#pragma comment(linker, "/NODEFAULTLIB:libcmtd.lib")
|
||||
#pragma comment(linker, "/NODEFAULTLIB:msvcrtd.lib")
|
||||
#endif
|
||||
|
||||
// Now set up external linking
|
||||
|
||||
#ifdef _DEBUG
|
||||
// zlib and SDL were linked against the release MSVCRT; force
|
||||
// the debug version.
|
||||
#pragma comment(linker, "/NODEFAULTLIB:MSVCRT.LIB")
|
||||
# endif
|
||||
|
||||
# ifndef WIN32_LEAN_AND_MEAN
|
||||
# define WIN32_LEAN_AND_MEAN 1
|
||||
# endif
|
||||
|
||||
|
||||
# define NOMINMAX 1
|
||||
# include <windows.h>
|
||||
# undef WIN32_LEAN_AND_MEAN
|
||||
# undef NOMINMAX
|
||||
|
||||
#ifdef _G3D_INTERNAL_HIDE_WINSOCK_
|
||||
# undef _G3D_INTERNAL_HIDE_WINSOCK_
|
||||
# undef _WINSOCKAPI_
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
# if defined(_MSC_VER) && (_MSC_VER <= 1200)
|
||||
// VC6 std:: has signed/unsigned problems
|
||||
# pragma warning (disable : 4018)
|
||||
# endif
|
||||
|
||||
/**
|
||||
@def STR(expression)
|
||||
|
||||
Creates a string from the expression. Frequently used with G3D::Shader
|
||||
to express shading programs inline.
|
||||
|
||||
<CODE>STR(this becomes a string)<PRE> evaluates the same as <CODE>"this becomes a string"</CODE>
|
||||
*/
|
||||
#define STR(x) #x
|
||||
|
||||
#undef G3D_DEPRECATED
|
||||
#define G3D_DEPRECATED
|
||||
|
||||
// Header guard
|
||||
#endif
|
||||
@@ -0,0 +1,130 @@
|
||||
/**
|
||||
@file stringutils.h
|
||||
|
||||
@maintainer Morgan McGuire, [email protected]
|
||||
|
||||
@author 2000-09-09
|
||||
@edited 2002-11-30
|
||||
*/
|
||||
|
||||
#ifndef G3D_STRINGUTILS_H
|
||||
#define G3D_STRINGUTILS_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Array.h"
|
||||
#include <string>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
extern const char* NEWLINE;
|
||||
|
||||
/**
|
||||
Returns true if the test string begins with the pattern string.
|
||||
*/
|
||||
bool beginsWith(
|
||||
const std::string& test,
|
||||
const std::string& pattern);
|
||||
|
||||
/**
|
||||
Returns true if the test string ends with the pattern string.
|
||||
*/
|
||||
bool endsWith(
|
||||
const std::string& test,
|
||||
const std::string& pattern);
|
||||
|
||||
/**
|
||||
Produces a new string that is the input string
|
||||
wrapped at a certain number of columns (where
|
||||
the line is broken at the latest space before the
|
||||
column limit.) Platform specific NEWLINEs
|
||||
are inserted to wrap.
|
||||
*/
|
||||
std::string wordWrap(
|
||||
const std::string& input,
|
||||
int numCols);
|
||||
|
||||
/**
|
||||
A comparison function for passing to Array::sort.
|
||||
*/
|
||||
int stringCompare(
|
||||
const std::string& s1,
|
||||
const std::string& s2);
|
||||
|
||||
int stringPtrCompare(
|
||||
const std::string* s1,
|
||||
const std::string* s2);
|
||||
|
||||
/**
|
||||
Returns a new string that is an uppercase version of x.
|
||||
*/
|
||||
std::string toUpper(
|
||||
const std::string& x);
|
||||
|
||||
std::string toLower(
|
||||
const std::string& x);
|
||||
|
||||
/**
|
||||
Splits x at each occurance of splitChar.
|
||||
*/
|
||||
G3D::Array<std::string> stringSplit(
|
||||
const std::string& x,
|
||||
char splitChar);
|
||||
|
||||
/**
|
||||
joinChar is not inserted at the beginning or end, just in between
|
||||
elements.
|
||||
*/
|
||||
std::string stringJoin(
|
||||
const G3D::Array<std::string>& a,
|
||||
char joinChar);
|
||||
|
||||
std::string stringJoin(
|
||||
const G3D::Array<std::string>& a,
|
||||
const std::string& joinStr);
|
||||
|
||||
/**
|
||||
Strips whitespace from both ends of the string.
|
||||
*/
|
||||
std::string trimWhitespace(
|
||||
const std::string& s);
|
||||
|
||||
/** These standard C functions are renamed for clarity/naming
|
||||
conventions and to return bool, not int.
|
||||
*/
|
||||
inline bool isWhiteSpace(const char c) {
|
||||
return isspace(c) != 0;
|
||||
}
|
||||
|
||||
/** These standard C functions are renamed for clarity/naming
|
||||
conventions and to return bool, not int.
|
||||
*/
|
||||
inline bool isNewline(const char c) {
|
||||
return (c == '\n') || (c == '\r');
|
||||
}
|
||||
|
||||
/** These standard C functions are renamed for clarity/naming
|
||||
conventions and to return bool, not int.
|
||||
*/
|
||||
inline bool isDigit(const char c) {
|
||||
return isdigit(c) != 0;
|
||||
}
|
||||
|
||||
/** These standard C functions are renamed for clarity/naming
|
||||
conventions and to return bool, not int.
|
||||
*/
|
||||
inline bool isLetter(const char c) {
|
||||
return isalpha(c) != 0;
|
||||
}
|
||||
|
||||
inline bool isSlash(const char c) {
|
||||
return (c == '\\') || (c == '/');
|
||||
}
|
||||
|
||||
inline bool isQuote(const char c) {
|
||||
return (c == '\'') || (c == '\"');
|
||||
}
|
||||
|
||||
}; // namespace
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user