[svn] * Proper SVN structure

--HG--
branch : trunk
This commit is contained in:
Neo2003
2008-10-02 16:23:55 -05:00
commit 9b1c0e006f
2564 changed files with 621124 additions and 0 deletions
+255
View File
@@ -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
+228
View File
@@ -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
+318
View File
@@ -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
+46
View File
@@ -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
+251
View File
@@ -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
+85
View File
@@ -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
+311
View File
@@ -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
+156
View File
@@ -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
+702
View File
@@ -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
+38
View File
@@ -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);
}
}
+327
View File
@@ -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
+86
View File
@@ -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
+128
View File
@@ -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
+122
View File
@@ -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
+695
View File
@@ -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
+116
View File
@@ -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
+438
View File
@@ -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
+20
View File
@@ -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.
*/
}
+75
View File
@@ -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
+504
View File
@@ -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
+250
View File
@@ -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
+55
View File
@@ -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
+524
View File
@@ -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
+193
View File
@@ -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;
}
}
+11
View File
@@ -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
+57
View File
@@ -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
+525
View File
@@ -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
+289
View File
@@ -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
+269
View File
@@ -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
+130
View File
@@ -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